summaryrefslogtreecommitdiff
path: root/xfa/fde
diff options
context:
space:
mode:
Diffstat (limited to 'xfa/fde')
-rw-r--r--xfa/fde/cfde_texteditengine.cpp972
-rw-r--r--xfa/fde/cfde_texteditengine.h241
-rw-r--r--xfa/fde/cfde_texteditengine_unittest.cpp418
-rw-r--r--xfa/fde/cfde_txtedtbuf.cpp316
-rw-r--r--xfa/fde/cfde_txtedtbuf.h76
-rw-r--r--xfa/fde/cfde_txtedtbuf_unittest.cpp188
-rw-r--r--xfa/fde/cfde_txtedtengine.cpp1234
-rw-r--r--xfa/fde/cfde_txtedtengine.h223
-rw-r--r--xfa/fde/cfde_txtedtpage.cpp398
-rw-r--r--xfa/fde/cfde_txtedtpage.h94
-rw-r--r--xfa/fde/cfde_txtedtparag.cpp153
-rw-r--r--xfa/fde/cfde_txtedtparag.h45
-rw-r--r--xfa/fde/cfde_txtedttextset.cpp60
-rw-r--r--xfa/fde/cfde_txtedttextset.h33
-rw-r--r--xfa/fde/ifde_txtedtdorecord.h20
15 files changed, 1631 insertions, 2840 deletions
diff --git a/xfa/fde/cfde_texteditengine.cpp b/xfa/fde/cfde_texteditengine.cpp
new file mode 100644
index 0000000000..e92897ea7d
--- /dev/null
+++ b/xfa/fde/cfde_texteditengine.cpp
@@ -0,0 +1,972 @@
+// Copyright 2017 PDFium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com
+
+#include "xfa/fde/cfde_texteditengine.h"
+
+#include <algorithm>
+#include <limits>
+
+#include "xfa/fde/cfde_textout.h"
+
+namespace {
+
+constexpr size_t kMaxEditOperations = 128;
+constexpr size_t kGapSize = 128;
+constexpr size_t kPageWidthMax = 0xffff;
+
+class InsertOperation : public CFDE_TextEditEngine::Operation {
+ public:
+ InsertOperation(CFDE_TextEditEngine* engine,
+ size_t start_idx,
+ const CFX_WideString& added_text)
+ : engine_(engine), start_idx_(start_idx), added_text_(added_text) {}
+
+ ~InsertOperation() override {}
+
+ void Redo() const override {
+ engine_->Insert(start_idx_, added_text_,
+ CFDE_TextEditEngine::RecordOperation::kSkipRecord);
+ }
+
+ void Undo() const override {
+ engine_->Delete(start_idx_, added_text_.GetLength(),
+ CFDE_TextEditEngine::RecordOperation::kSkipRecord);
+ }
+
+ private:
+ CFX_UnownedPtr<CFDE_TextEditEngine> engine_;
+ size_t start_idx_;
+ CFX_WideString added_text_;
+};
+
+class DeleteOperation : public CFDE_TextEditEngine::Operation {
+ public:
+ DeleteOperation(CFDE_TextEditEngine* engine,
+ size_t start_idx,
+ const CFX_WideString& removed_text)
+ : engine_(engine), start_idx_(start_idx), removed_text_(removed_text) {}
+
+ ~DeleteOperation() override {}
+
+ void Redo() const override {
+ engine_->Delete(start_idx_, removed_text_.GetLength(),
+ CFDE_TextEditEngine::RecordOperation::kSkipRecord);
+ }
+
+ void Undo() const override {
+ engine_->Insert(start_idx_, removed_text_,
+ CFDE_TextEditEngine::RecordOperation::kSkipRecord);
+ }
+
+ private:
+ CFX_UnownedPtr<CFDE_TextEditEngine> engine_;
+ size_t start_idx_;
+ CFX_WideString removed_text_;
+};
+
+class ReplaceOperation : public CFDE_TextEditEngine::Operation {
+ public:
+ ReplaceOperation(CFDE_TextEditEngine* engine,
+ size_t start_idx,
+ const CFX_WideString& removed_text,
+ const CFX_WideString& added_text)
+ : insert_op_(engine, start_idx, added_text),
+ delete_op_(engine, start_idx, removed_text) {}
+
+ ~ReplaceOperation() override {}
+
+ void Redo() const override {
+ delete_op_.Redo();
+ insert_op_.Redo();
+ }
+
+ void Undo() const override {
+ insert_op_.Undo();
+ delete_op_.Undo();
+ }
+
+ private:
+ InsertOperation insert_op_;
+ DeleteOperation delete_op_;
+};
+
+} // namespace
+
+CFDE_TextEditEngine::CFDE_TextEditEngine()
+ : font_color_(0xff000000),
+ font_size_(10.0f),
+ line_spacing_(10.0f),
+ text_length_(0),
+ gap_position_(0),
+ gap_size_(kGapSize),
+ available_width_(kPageWidthMax),
+ character_limit_(std::numeric_limits<size_t>::max()),
+ visible_line_count_(1),
+ next_operation_index_to_undo_(kMaxEditOperations - 1),
+ next_operation_index_to_insert_(0),
+ max_edit_operations_(kMaxEditOperations),
+ character_alignment_(CFX_TxtLineAlignment_Left),
+ has_character_limit_(false),
+ is_comb_text_(false),
+ is_dirty_(false),
+ validation_enabled_(false),
+ is_multiline_(false),
+ is_linewrap_enabled_(false),
+ limit_horizontal_area_(false),
+ limit_vertical_area_(false),
+ password_mode_(false),
+ password_alias_(L'*'),
+ has_selection_(false),
+ selection_({0, 0}) {
+ content_.resize(gap_size_);
+ operation_buffer_.resize(max_edit_operations_);
+
+ text_break_.SetFontSize(font_size_);
+ text_break_.SetLineBreakTolerance(2.0f);
+ text_break_.SetTabWidth(36);
+}
+
+CFDE_TextEditEngine::~CFDE_TextEditEngine() {}
+
+void CFDE_TextEditEngine::Clear() {
+ text_length_ = 0;
+ gap_position_ = 0;
+ gap_size_ = kGapSize;
+
+ content_.clear();
+ content_.resize(gap_size_);
+
+ ClearSelection();
+ ClearOperationRecords();
+}
+
+void CFDE_TextEditEngine::SetMaxEditOperationsForTesting(size_t max) {
+ max_edit_operations_ = max;
+ operation_buffer_.resize(max);
+
+ ClearOperationRecords();
+}
+
+void CFDE_TextEditEngine::AdjustGap(size_t idx, size_t length) {
+ static const size_t char_size = sizeof(CFX_WideString::CharType);
+
+ // Move the gap, if necessary.
+ if (idx < gap_position_) {
+ memmove(content_.data() + idx + gap_size_, content_.data() + idx,
+ (gap_position_ - idx) * char_size);
+ gap_position_ = idx;
+ } else if (idx > gap_position_) {
+ memmove(content_.data() + gap_position_,
+ content_.data() + gap_position_ + gap_size_,
+ (idx - gap_position_) * char_size);
+ gap_position_ = idx;
+ }
+
+ // If the gap is too small, make it bigger.
+ if (length >= gap_size_) {
+ size_t new_gap_size = length + kGapSize;
+ content_.resize(text_length_ + new_gap_size);
+
+ memmove(content_.data() + gap_position_ + new_gap_size,
+ content_.data() + gap_position_ + gap_size_,
+ (text_length_ - gap_position_) * char_size);
+
+ gap_size_ = new_gap_size;
+ }
+}
+
+size_t CFDE_TextEditEngine::CountCharsExceedingSize(const CFX_WideString& text,
+ size_t num_to_check) {
+ if (!limit_horizontal_area_ && !limit_vertical_area_)
+ return 0;
+
+ auto text_out = pdfium::MakeUnique<CFDE_TextOut>();
+ text_out->SetLineSpace(line_spacing_);
+ text_out->SetFont(font_);
+ text_out->SetFontSize(font_size_);
+
+ FDE_TextStyle style;
+ style.single_line_ = !is_multiline_;
+
+ CFX_RectF text_rect;
+ if (is_linewrap_enabled_) {
+ style.line_wrap_ = true;
+ text_rect.width = available_width_;
+ } else {
+ text_rect.width = kPageWidthMax;
+ }
+ text_out->SetStyles(style);
+
+ size_t length = text.GetLength();
+ CFX_WideStringC temp(text.c_str(), length);
+
+ float vertical_height = line_spacing_ * visible_line_count_;
+ size_t chars_exceeding_size = 0;
+ // TODO(dsinclair): Can this get changed to a binary search?
+ for (size_t i = 0; i < num_to_check; i++) {
+ // This does a lot of string copying ....
+ // TODO(dsinclair): make CalcLogicSize take a WideStringC instead.
+ text_out->CalcLogicSize(CFX_WideString(temp), text_rect);
+
+ if (limit_horizontal_area_ && text_rect.width <= available_width_)
+ break;
+ if (limit_vertical_area_ && text_rect.height <= vertical_height)
+ break;
+
+ --length;
+ temp = temp.Mid(0, length);
+ ++chars_exceeding_size;
+ }
+
+ return chars_exceeding_size;
+}
+
+void CFDE_TextEditEngine::Insert(size_t idx,
+ const CFX_WideString& text,
+ RecordOperation add_operation) {
+ if (idx > text_length_)
+ idx = text_length_;
+
+ size_t length = text.GetLength();
+ if (length == 0)
+ return;
+
+ // If we're going to be too big we insert what we can and notify the
+ // delegate we've filled the text after the insert is done.
+ bool exceeded_limit = false;
+ if (has_character_limit_ && text_length_ + length > character_limit_) {
+ exceeded_limit = true;
+ length = character_limit_ - text_length_;
+ }
+
+ AdjustGap(idx, length);
+
+ if (validation_enabled_ || limit_horizontal_area_ || limit_vertical_area_) {
+ CFX_WideString str;
+ if (gap_position_ > 0)
+ str += CFX_WideStringC(content_.data(), gap_position_);
+
+ str += text;
+
+ if (text_length_ - gap_position_ > 0) {
+ str += CFX_WideStringC(content_.data() + gap_position_ + gap_size_,
+ text_length_ - gap_position_);
+ }
+
+ if (validation_enabled_ && delegate_ && !delegate_->OnValidate(str)) {
+ // TODO(dsinclair): Notify delegate of validation failure?
+ return;
+ }
+
+ // Check if we've limited the horizontal/vertical area, and if so determine
+ // how many of our characters would be outside the area.
+ size_t chars_exceeding = CountCharsExceedingSize(str, length);
+ if (chars_exceeding > 0) {
+ // If none of the characters will fit, notify and exit.
+ if (chars_exceeding == length) {
+ if (delegate_)
+ delegate_->NotifyTextFull();
+ return;
+ }
+
+ // Some, but not all, chars will fit, insert them and then notify
+ // we're full.
+ exceeded_limit = true;
+ length -= chars_exceeding;
+ }
+ }
+
+ if (add_operation == RecordOperation::kInsertRecord) {
+ AddOperationRecord(
+ pdfium::MakeUnique<InsertOperation>(this, gap_position_, text));
+ }
+
+ CFX_WideString previous_text;
+ if (delegate_)
+ previous_text = GetText();
+
+ // Copy the new text into the gap.
+ static const size_t char_size = sizeof(CFX_WideString::CharType);
+ memcpy(content_.data() + gap_position_, text.c_str(), length * char_size);
+ gap_position_ += length;
+ gap_size_ -= length;
+ text_length_ += length;
+
+ is_dirty_ = true;
+
+ // Inserting text resets the selection.
+ ClearSelection();
+
+ if (delegate_) {
+ if (exceeded_limit)
+ delegate_->NotifyTextFull();
+
+ delegate_->OnTextChanged(previous_text);
+ }
+}
+
+void CFDE_TextEditEngine::AddOperationRecord(std::unique_ptr<Operation> op) {
+ size_t last_insert_position = next_operation_index_to_insert_ == 0
+ ? max_edit_operations_ - 1
+ : next_operation_index_to_insert_ - 1;
+
+ // If our undo record is not the last thing we inserted then we need to
+ // remove all the undo records between our insert position and the undo marker
+ // and make that our new insert position.
+ if (next_operation_index_to_undo_ != last_insert_position) {
+ if (next_operation_index_to_undo_ > last_insert_position) {
+ // Our Undo position is ahead of us, which means we need to clear out the
+ // head of the queue.
+ while (last_insert_position != 0) {
+ operation_buffer_[last_insert_position].reset();
+ --last_insert_position;
+ }
+ operation_buffer_[0].reset();
+
+ // Moving this will let us then clear out the end, setting the undo
+ // position to before the insert position.
+ last_insert_position = max_edit_operations_ - 1;
+ }
+
+ // Clear out the vector from undo position to our set insert position.
+ while (next_operation_index_to_undo_ != last_insert_position) {
+ operation_buffer_[last_insert_position].reset();
+ --last_insert_position;
+ }
+ }
+
+ // We're now pointing at the next thing we want to Undo, so insert at the
+ // next position in the queue.
+ ++last_insert_position;
+ if (last_insert_position >= max_edit_operations_)
+ last_insert_position = 0;
+
+ operation_buffer_[last_insert_position] = std::move(op);
+ next_operation_index_to_insert_ =
+ (last_insert_position + 1) % max_edit_operations_;
+ next_operation_index_to_undo_ = last_insert_position;
+}
+
+void CFDE_TextEditEngine::ClearOperationRecords() {
+ for (auto& record : operation_buffer_)
+ record.reset();
+
+ next_operation_index_to_undo_ = max_edit_operations_ - 1;
+ next_operation_index_to_insert_ = 0;
+}
+
+void CFDE_TextEditEngine::LimitHorizontalScroll(bool val) {
+ ClearOperationRecords();
+ limit_horizontal_area_ = val;
+}
+void CFDE_TextEditEngine::LimitVerticalScroll(bool val) {
+ ClearOperationRecords();
+ limit_vertical_area_ = val;
+}
+
+bool CFDE_TextEditEngine::CanUndo() const {
+ return operation_buffer_[next_operation_index_to_undo_] != nullptr &&
+ next_operation_index_to_undo_ != next_operation_index_to_insert_;
+}
+
+bool CFDE_TextEditEngine::CanRedo() const {
+ size_t idx = (next_operation_index_to_undo_ + 1) % max_edit_operations_;
+ return idx != next_operation_index_to_insert_ &&
+ operation_buffer_[idx] != nullptr;
+}
+
+bool CFDE_TextEditEngine::Redo() {
+ if (!CanRedo())
+ return false;
+
+ next_operation_index_to_undo_ =
+ (next_operation_index_to_undo_ + 1) % max_edit_operations_;
+ operation_buffer_[next_operation_index_to_undo_]->Redo();
+ return true;
+}
+
+bool CFDE_TextEditEngine::Undo() {
+ if (!CanUndo())
+ return false;
+
+ operation_buffer_[next_operation_index_to_undo_]->Undo();
+ next_operation_index_to_undo_ = next_operation_index_to_undo_ == 0
+ ? max_edit_operations_ - 1
+ : next_operation_index_to_undo_ - 1;
+ return true;
+}
+
+void CFDE_TextEditEngine::Layout() {
+ if (!is_dirty_)
+ return;
+
+ is_dirty_ = false;
+ RebuildPieces();
+}
+
+CFX_RectF CFDE_TextEditEngine::GetContentsBoundingBox() {
+ // Layout if necessary.
+ Layout();
+ return contents_bounding_box_;
+}
+
+void CFDE_TextEditEngine::SetAvailableWidth(size_t width) {
+ if (width == available_width_)
+ return;
+
+ ClearOperationRecords();
+
+ available_width_ = width;
+ if (is_linewrap_enabled_)
+ text_break_.SetLineWidth(width);
+ if (is_comb_text_)
+ SetCombTextWidth();
+
+ is_dirty_ = true;
+}
+
+void CFDE_TextEditEngine::SetHasCharacterLimit(bool limit) {
+ if (has_character_limit_ == limit)
+ return;
+
+ has_character_limit_ = limit;
+ if (is_comb_text_)
+ SetCombTextWidth();
+
+ is_dirty_ = true;
+}
+
+void CFDE_TextEditEngine::SetCharacterLimit(size_t limit) {
+ if (character_limit_ == limit)
+ return;
+
+ ClearOperationRecords();
+
+ character_limit_ = limit;
+ if (is_comb_text_)
+ SetCombTextWidth();
+
+ is_dirty_ = true;
+}
+
+void CFDE_TextEditEngine::SetFont(CFX_RetainPtr<CFGAS_GEFont> font) {
+ if (font_ == font)
+ return;
+
+ font_ = font;
+ text_break_.SetFont(font_);
+ is_dirty_ = true;
+}
+
+void CFDE_TextEditEngine::SetFontSize(float size) {
+ if (font_size_ == size)
+ return;
+
+ font_size_ = size;
+ text_break_.SetFontSize(font_size_);
+ is_dirty_ = true;
+}
+
+void CFDE_TextEditEngine::SetTabWidth(float width) {
+ int32_t old_tab_width = text_break_.GetTabWidth();
+ text_break_.SetTabWidth(width);
+ if (old_tab_width == text_break_.GetTabWidth())
+ return;
+
+ is_dirty_ = true;
+}
+
+void CFDE_TextEditEngine::SetAlignment(uint32_t alignment) {
+ if (alignment == character_alignment_)
+ return;
+
+ character_alignment_ = alignment;
+ text_break_.SetAlignment(alignment);
+ is_dirty_ = true;
+}
+
+void CFDE_TextEditEngine::SetVisibleLineCount(size_t count) {
+ if (visible_line_count_ == count)
+ return;
+
+ visible_line_count_ = std::max(static_cast<size_t>(1), count);
+ is_dirty_ = true;
+}
+
+void CFDE_TextEditEngine::EnableMultiLine(bool val) {
+ if (is_multiline_ == val)
+ return;
+
+ is_multiline_ = true;
+
+ uint32_t style = text_break_.GetLayoutStyles();
+ if (is_multiline_)
+ style &= ~FX_LAYOUTSTYLE_SingleLine;
+ else
+ style |= FX_LAYOUTSTYLE_SingleLine;
+ text_break_.SetLayoutStyles(style);
+ is_dirty_ = true;
+}
+
+void CFDE_TextEditEngine::EnableLineWrap(bool val) {
+ if (is_linewrap_enabled_ == val)
+ return;
+
+ is_linewrap_enabled_ = val;
+ text_break_.SetLineWidth(is_linewrap_enabled_ ? available_width_
+ : kPageWidthMax);
+ is_dirty_ = true;
+}
+
+void CFDE_TextEditEngine::SetCombText(bool enable) {
+ if (is_comb_text_ == enable)
+ return;
+
+ is_comb_text_ = enable;
+
+ uint32_t style = text_break_.GetLayoutStyles();
+ if (enable) {
+ style |= FX_LAYOUTSTYLE_CombText;
+ SetCombTextWidth();
+ } else {
+ style &= ~FX_LAYOUTSTYLE_CombText;
+ }
+ text_break_.SetLayoutStyles(style);
+ is_dirty_ = true;
+}
+
+void CFDE_TextEditEngine::SetCombTextWidth() {
+ size_t width = available_width_;
+ if (has_character_limit_)
+ width /= character_limit_;
+
+ text_break_.SetCombWidth(width);
+}
+
+void CFDE_TextEditEngine::SelectAll() {
+ if (text_length_ == 0)
+ return;
+
+ has_selection_ = true;
+ selection_.start_idx = 0;
+ selection_.end_idx = text_length_ - 1;
+}
+
+void CFDE_TextEditEngine::ClearSelection() {
+ has_selection_ = false;
+ selection_.start_idx = 0;
+ selection_.end_idx = 0;
+}
+
+void CFDE_TextEditEngine::SetSelection(size_t start_idx, size_t end_idx) {
+ // If the points are the same, then we pretend the selection doesn't exist
+ // anymore.
+ if (start_idx == end_idx) {
+ ClearSelection();
+ return;
+ }
+
+ if (start_idx > text_length_)
+ return;
+ if (end_idx > text_length_)
+ end_idx = text_length_ - 1;
+
+ has_selection_ = true;
+ selection_.start_idx = start_idx;
+ selection_.end_idx = end_idx;
+}
+
+CFX_WideString CFDE_TextEditEngine::GetSelectedText() const {
+ if (!has_selection_)
+ return L"";
+
+ CFX_WideString text;
+ if (selection_.start_idx < gap_position_) {
+ if (selection_.end_idx < gap_position_) {
+ text += CFX_WideStringC(content_.data() + selection_.start_idx,
+ selection_.end_idx - selection_.start_idx + 1);
+ return text;
+ }
+
+ text += CFX_WideStringC(content_.data() + selection_.start_idx,
+ gap_position_ - selection_.start_idx);
+ text += CFX_WideStringC(
+ content_.data() + gap_position_ + gap_size_,
+ selection_.end_idx - (gap_position_ - selection_.start_idx) + 1);
+ return text;
+ }
+
+ text += CFX_WideStringC(content_.data() + gap_size_ + selection_.start_idx,
+ selection_.end_idx - selection_.start_idx + 1);
+ return text;
+}
+
+CFX_WideString CFDE_TextEditEngine::DeleteSelectedText(
+ RecordOperation add_operation) {
+ if (!has_selection_)
+ return L"";
+
+ return Delete(selection_.start_idx,
+ selection_.end_idx - selection_.start_idx + 1, add_operation);
+}
+
+CFX_WideString CFDE_TextEditEngine::Delete(size_t start_idx,
+ size_t length,
+ RecordOperation add_operation) {
+ if (start_idx >= text_length_)
+ return L"";
+
+ length = std::min(length, text_length_ - start_idx);
+ AdjustGap(start_idx + length, 0);
+
+ CFX_WideString ret;
+ ret += CFX_WideStringC(content_.data() + start_idx, length);
+
+ if (add_operation == RecordOperation::kInsertRecord) {
+ AddOperationRecord(
+ pdfium::MakeUnique<DeleteOperation>(this, start_idx, ret));
+ }
+
+ CFX_WideString previous_text = GetText();
+
+ gap_position_ = start_idx;
+ gap_size_ += length;
+
+ text_length_ -= length;
+ ClearSelection();
+
+ if (delegate_)
+ delegate_->OnTextChanged(previous_text);
+
+ return ret;
+}
+
+void CFDE_TextEditEngine::ReplaceSelectedText(const CFX_WideString& rep) {
+ size_t start_idx = selection_.start_idx;
+
+ CFX_WideString txt = DeleteSelectedText(RecordOperation::kSkipRecord);
+ Insert(gap_position_, rep, RecordOperation::kSkipRecord);
+
+ AddOperationRecord(
+ pdfium::MakeUnique<ReplaceOperation>(this, start_idx, txt, rep));
+}
+
+CFX_WideString CFDE_TextEditEngine::GetText() const {
+ CFX_WideString str;
+ if (gap_position_ > 0)
+ str += CFX_WideStringC(content_.data(), gap_position_);
+ if (text_length_ - gap_position_ > 0) {
+ str += CFX_WideStringC(content_.data() + gap_position_ + gap_size_,
+ text_length_ - gap_position_);
+ }
+ return str;
+}
+
+size_t CFDE_TextEditEngine::GetLength() const {
+ return text_length_;
+}
+
+wchar_t CFDE_TextEditEngine::GetChar(size_t idx) const {
+ if (idx >= text_length_)
+ return L'\0';
+ if (password_mode_)
+ return password_alias_;
+
+ return idx < gap_position_
+ ? content_[idx]
+ : content_[gap_position_ + gap_size_ + (idx - gap_position_)];
+}
+
+size_t CFDE_TextEditEngine::GetWidthOfChar(size_t idx) {
+ // Recalculate the widths if necessary.
+ Layout();
+ return idx < char_widths_.size() ? char_widths_[idx] : 0;
+}
+
+size_t CFDE_TextEditEngine::GetIndexForPoint(const CFX_PointF& point) {
+ // Recalculate the widths if necessary.
+ Layout();
+
+ auto start_it = text_piece_info_.begin();
+ for (; start_it < text_piece_info_.end(); ++start_it) {
+ if (start_it->rtPiece.top <= point.y &&
+ point.y < start_it->rtPiece.bottom())
+ break;
+ }
+ // We didn't find the point before getting to the end of the text, return
+ // end of text.
+ if (start_it == text_piece_info_.end())
+ return text_length_;
+
+ auto end_it = start_it;
+ for (; end_it < text_piece_info_.end(); ++end_it) {
+ // We've moved past where the point should be and didn't find anything.
+ // Return the start of the current piece as the location.
+ if (end_it->rtPiece.bottom() <= point.y || point.y < end_it->rtPiece.top)
+ break;
+ }
+ // Make sure the end iterator is pointing to our text pieces.
+ if (end_it == text_piece_info_.end())
+ --end_it;
+
+ size_t start_it_idx = start_it->nStart;
+ for (; start_it <= end_it; ++start_it) {
+ if (!start_it->rtPiece.Contains(point))
+ continue;
+
+ std::vector<CFX_RectF> rects = GetCharRects(*start_it);
+ for (size_t i = 0; i < rects.size(); ++i) {
+ if (!rects[i].Contains(point))
+ continue;
+ size_t pos = start_it->nStart + i;
+ if (pos >= text_length_)
+ return text_length_;
+
+ wchar_t wch = GetChar(pos);
+ if (wch == L'\n' || wch == L'\r') {
+ if (wch == L'\n' && pos > 0 && GetChar(pos - 1) == L'\r')
+ --pos;
+ return pos;
+ }
+
+ // TODO(dsinclair): Old code had a before flag set based on bidi?
+ return pos;
+ }
+ }
+
+ if (start_it == text_piece_info_.end())
+ return start_it_idx;
+ if (start_it == end_it)
+ return start_it->nStart;
+
+ // We didn't find the point before going over all of the pieces, we want to
+ // return the start of the piece after the point.
+ return end_it->nStart;
+}
+
+std::vector<CFX_RectF> CFDE_TextEditEngine::GetCharRects(
+ const FDE_TEXTEDITPIECE& piece) {
+ if (piece.nCount < 1)
+ return {};
+
+ FX_TXTRUN tr;
+ tr.pEdtEngine = this;
+ tr.pIdentity = &piece;
+ tr.iLength = piece.nCount;
+ tr.pFont = font_;
+ tr.fFontSize = font_size_;
+ tr.dwStyles = text_break_.GetLayoutStyles();
+ tr.dwCharStyles = piece.dwCharStyles;
+ tr.pRect = &piece.rtPiece;
+ return text_break_.GetCharRects(&tr, false);
+}
+
+std::vector<FXTEXT_CHARPOS> CFDE_TextEditEngine::GetDisplayPos(
+ const FDE_TEXTEDITPIECE& piece) {
+ if (piece.nCount < 1)
+ return std::vector<FXTEXT_CHARPOS>();
+
+ FX_TXTRUN tr;
+ tr.pEdtEngine = this;
+ tr.pIdentity = &piece;
+ tr.iLength = piece.nCount;
+ tr.pFont = font_;
+ tr.fFontSize = font_size_;
+ tr.dwStyles = text_break_.GetLayoutStyles();
+ tr.dwCharStyles = piece.dwCharStyles;
+ tr.pRect = &piece.rtPiece;
+
+ std::vector<FXTEXT_CHARPOS> data(text_break_.GetDisplayPos(&tr, nullptr));
+ text_break_.GetDisplayPos(&tr, data.data());
+ return data;
+}
+
+void CFDE_TextEditEngine::RebuildPieces() {
+ text_break_.EndBreak(CFX_BreakType::Paragraph);
+ text_break_.ClearBreakPieces();
+
+ char_widths_.clear();
+ text_piece_info_.clear();
+
+ // Must have a font set in order to break the text.
+ if (text_length_ == 0 || !font_)
+ return;
+
+ bool initialized_bounding_box = false;
+ contents_bounding_box_ = CFX_RectF();
+
+ auto iter = pdfium::MakeUnique<CFDE_TextEditEngine::Iterator>(this);
+ while (!iter->IsEOF(true)) {
+ iter->Next(false);
+
+ CFX_BreakType break_status = text_break_.AppendChar(
+ password_mode_ ? password_alias_ : iter->GetChar());
+ if (iter->IsEOF(true) && CFX_BreakTypeNoneOrPiece(break_status))
+ break_status = text_break_.EndBreak(CFX_BreakType::Paragraph);
+
+ if (CFX_BreakTypeNoneOrPiece(break_status))
+ continue;
+
+ size_t current_piece_start = 0;
+ float current_line_start = 0;
+ int32_t piece_count = text_break_.CountBreakPieces();
+ for (int32_t i = 0; i < piece_count; ++i) {
+ const CFX_BreakPiece* piece = text_break_.GetBreakPieceUnstable(i);
+
+ FDE_TEXTEDITPIECE txtEdtPiece;
+ memset(&txtEdtPiece, 0, sizeof(FDE_TEXTEDITPIECE));
+
+ txtEdtPiece.nBidiLevel = piece->m_iBidiLevel;
+ txtEdtPiece.nCount = piece->GetLength();
+ txtEdtPiece.nStart = current_piece_start;
+ txtEdtPiece.dwCharStyles = piece->m_dwCharStyles;
+ if (FX_IsOdd(piece->m_iBidiLevel))
+ txtEdtPiece.dwCharStyles |= FX_TXTCHARSTYLE_OddBidiLevel;
+
+ txtEdtPiece.rtPiece.left = piece->m_iStartPos / 20000.0f;
+ txtEdtPiece.rtPiece.top = current_line_start;
+ txtEdtPiece.rtPiece.width = piece->m_iWidth / 20000.0f;
+ txtEdtPiece.rtPiece.height = line_spacing_;
+ text_piece_info_.push_back(txtEdtPiece);
+
+ if (initialized_bounding_box) {
+ contents_bounding_box_.Union(txtEdtPiece.rtPiece);
+ } else {
+ contents_bounding_box_ = txtEdtPiece.rtPiece;
+ initialized_bounding_box = true;
+ }
+
+ current_piece_start += txtEdtPiece.nCount;
+ for (int32_t k = 0; k < txtEdtPiece.nCount; ++k)
+ char_widths_.push_back(piece->GetChar(k)->m_iCharWidth);
+ }
+
+ current_line_start += line_spacing_;
+ text_break_.ClearBreakPieces();
+ }
+
+ float delta = 0.0;
+ bool bounds_smaller = contents_bounding_box_.width < available_width_;
+ if (IsAlignedRight() && bounds_smaller) {
+ delta = available_width_ - contents_bounding_box_.width;
+ } else if (IsAlignedCenter() && bounds_smaller) {
+ // TODO(dsinclair): Old code used CombText here and set the space to
+ // something unrelated to the available width .... Figure out if this is
+ // needed and what it should do.
+ // if (is_comb_text_) {
+ // } else {
+ delta = (available_width_ - contents_bounding_box_.width) / 2.0f;
+ // }
+ }
+
+ if (delta != 0.0) {
+ float offset = delta - contents_bounding_box_.left;
+ for (auto& info : text_piece_info_)
+ info.rtPiece.Offset(offset, 0.0f);
+ contents_bounding_box_.Offset(offset, 0.0f);
+ }
+
+ // Shrink the last piece down to the font_size.
+ contents_bounding_box_.height -= line_spacing_ - font_size_;
+ text_piece_info_.back().rtPiece.height = font_size_;
+}
+
+std::pair<int32_t, CFX_RectF> CFDE_TextEditEngine::GetCharacterInfo(
+ int32_t start_idx) {
+ ASSERT(start_idx >= 0);
+ ASSERT(static_cast<size_t>(start_idx) <= text_length_);
+
+ // Make sure the current available data is fresh.
+ Layout();
+
+ auto it = text_piece_info_.begin();
+ for (; it != text_piece_info_.end(); ++it) {
+ if (it->nStart <= start_idx && start_idx < it->nStart + it->nCount)
+ break;
+ }
+ if (it == text_piece_info_.end()) {
+ NOTREACHED();
+ return {0, CFX_RectF()};
+ }
+
+ return {it->nBidiLevel, GetCharRects(*it)[start_idx - it->nStart]};
+}
+
+std::vector<CFX_RectF> CFDE_TextEditEngine::GetCharacterRectsInRange(
+ int32_t start_idx,
+ int32_t count) {
+ // Make sure the current available data is fresh.
+ Layout();
+
+ auto it = text_piece_info_.begin();
+ for (; it != text_piece_info_.end(); ++it) {
+ if (it->nStart <= start_idx && start_idx < it->nStart + it->nCount)
+ break;
+ }
+ if (it == text_piece_info_.end())
+ return {};
+
+ int32_t end_idx = start_idx + count - 1;
+ std::vector<CFX_RectF> rects;
+ while (it != text_piece_info_.end()) {
+ // If we end inside the current piece, extract what we need and we're done.
+ if (it->nStart <= end_idx && end_idx < it->nStart + it->nCount) {
+ std::vector<CFX_RectF> arr = GetCharRects(*it);
+ CFX_RectF piece = arr[0];
+ piece.Union(arr[end_idx - it->nStart]);
+ rects.push_back(piece);
+ break;
+ }
+ rects.push_back(it->rtPiece);
+ ++it;
+ }
+
+ return rects;
+}
+
+CFDE_TextEditEngine::Iterator::Iterator(CFDE_TextEditEngine* engine)
+ : engine_(engine), current_position_(-1) {}
+
+CFDE_TextEditEngine::Iterator::~Iterator() {}
+
+bool CFDE_TextEditEngine::Iterator::Next(bool bPrev) {
+ if (bPrev && current_position_ == -1)
+ return false;
+ if (!bPrev && current_position_ > -1 &&
+ static_cast<size_t>(current_position_) == engine_->GetLength())
+ return false;
+
+ if (bPrev)
+ --current_position_;
+ else
+ ++current_position_;
+
+ return true;
+}
+
+wchar_t CFDE_TextEditEngine::Iterator::GetChar() const {
+ return engine_->GetChar(current_position_);
+}
+
+void CFDE_TextEditEngine::Iterator::SetAt(int32_t nIndex) {
+ NOTREACHED();
+}
+
+int32_t CFDE_TextEditEngine::Iterator::GetAt() const {
+ return current_position_;
+}
+
+bool CFDE_TextEditEngine::Iterator::IsEOF(bool bTail) const {
+ return bTail ? current_position_ > -1 &&
+ static_cast<size_t>(current_position_) ==
+ engine_->GetLength()
+ : current_position_ == -1;
+}
+
+std::unique_ptr<IFX_CharIter> CFDE_TextEditEngine::Iterator::Clone() const {
+ NOTREACHED();
+ return pdfium::MakeUnique<CFDE_TextEditEngine::Iterator>(engine_.Get());
+}
diff --git a/xfa/fde/cfde_texteditengine.h b/xfa/fde/cfde_texteditengine.h
new file mode 100644
index 0000000000..35d9664f99
--- /dev/null
+++ b/xfa/fde/cfde_texteditengine.h
@@ -0,0 +1,241 @@
+// Copyright 2017 PDFium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com
+
+#ifndef XFA_FDE_CFDE_TEXTEDITENGINE_H_
+#define XFA_FDE_CFDE_TEXTEDITENGINE_H_
+
+#include <memory>
+#include <utility>
+#include <vector>
+
+#include "core/fxcrt/cfx_retain_ptr.h"
+#include "core/fxcrt/fx_string.h"
+#include "core/fxcrt/ifx_chariter.h"
+#include "core/fxge/cfx_renderdevice.h"
+#include "core/fxge/fx_dib.h"
+#include "xfa/fgas/font/cfgas_gefont.h"
+#include "xfa/fgas/layout/cfx_txtbreak.h"
+
+struct FDE_TEXTEDITPIECE {
+ FDE_TEXTEDITPIECE();
+ FDE_TEXTEDITPIECE(const FDE_TEXTEDITPIECE& that);
+ ~FDE_TEXTEDITPIECE();
+
+ int32_t nStart;
+ int32_t nCount;
+ int32_t nBidiLevel;
+ CFX_RectF rtPiece;
+ uint32_t dwCharStyles;
+};
+
+inline FDE_TEXTEDITPIECE::FDE_TEXTEDITPIECE() = default;
+inline FDE_TEXTEDITPIECE::FDE_TEXTEDITPIECE(const FDE_TEXTEDITPIECE& that) =
+ default;
+inline FDE_TEXTEDITPIECE::~FDE_TEXTEDITPIECE() = default;
+
+class CFDE_TextEditEngine {
+ public:
+ class Iterator : public IFX_CharIter {
+ public:
+ explicit Iterator(CFDE_TextEditEngine* engine);
+ ~Iterator() override;
+
+ bool Next(bool bPrev = false) override;
+ wchar_t GetChar() const override;
+ void SetAt(int32_t nIndex) override;
+ int32_t GetAt() const override;
+ bool IsEOF(bool bTail = true) const override;
+ std::unique_ptr<IFX_CharIter> Clone() const override;
+
+ private:
+ CFX_UnownedPtr<CFDE_TextEditEngine> engine_;
+ int32_t current_position_;
+ };
+
+ class Operation {
+ public:
+ virtual ~Operation() = default;
+ virtual void Redo() const = 0;
+ virtual void Undo() const = 0;
+ };
+
+ class Delegate {
+ public:
+ virtual void NotifyTextFull() = 0;
+
+ virtual void OnCaretChanged() = 0;
+ virtual void OnTextChanged(const CFX_WideString& prevText) = 0;
+ virtual void OnSelChanged() = 0;
+ virtual bool OnValidate(const CFX_WideString& wsText) = 0;
+ virtual void SetScrollOffset(float fScrollOffset) = 0;
+ };
+
+ enum class RecordOperation {
+ kInsertRecord,
+ kSkipRecord,
+ };
+
+ CFDE_TextEditEngine();
+ ~CFDE_TextEditEngine();
+
+ void SetDelegate(Delegate* delegate) { delegate_ = delegate; }
+ void Clear();
+
+ void Insert(size_t idx,
+ const CFX_WideString& text,
+ RecordOperation add_operation = RecordOperation::kInsertRecord);
+ CFX_WideString Delete(
+ size_t start_idx,
+ size_t length,
+ RecordOperation add_operation = RecordOperation::kInsertRecord);
+ CFX_WideString GetText() const;
+ size_t GetLength() const;
+
+ // Non-const so we can force a layout.
+ CFX_RectF GetContentsBoundingBox();
+ void SetAvailableWidth(size_t width);
+
+ void SetFont(CFX_RetainPtr<CFGAS_GEFont> font);
+ CFX_RetainPtr<CFGAS_GEFont> GetFont() const { return font_; }
+ void SetFontSize(float size);
+ float GetFontSize() const { return font_size_; }
+ void SetFontColor(FX_ARGB color) { font_color_ = color; }
+ FX_ARGB GetFontColor() const { return font_color_; }
+ float GetFontAscent() const {
+ return (static_cast<float>(font_->GetAscent()) * font_size_) / 1000;
+ }
+
+ void SetAlignment(uint32_t alignment);
+ float GetLineSpace() const { return line_spacing_; }
+ void SetLineSpace(float space) { line_spacing_ = space; }
+ void SetAliasChar(wchar_t alias) { password_alias_ = alias; }
+ void SetHasCharacterLimit(bool limit);
+ void SetCharacterLimit(size_t limit);
+ void SetCombText(bool enable);
+ void SetTabWidth(float width);
+ void SetVisibleLineCount(size_t lines);
+
+ void EnableValidation(bool val) { validation_enabled_ = val; }
+ void EnablePasswordMode(bool val) { password_mode_ = val; }
+ void EnableMultiLine(bool val);
+ void EnableLineWrap(bool val);
+ void LimitHorizontalScroll(bool val);
+ void LimitVerticalScroll(bool val);
+
+ bool CanUndo() const;
+ bool CanRedo() const;
+ bool Redo();
+ bool Undo();
+ void ClearOperationRecords();
+
+ // TODO(dsinclair): Implement ....
+ size_t GetIndexBefore(size_t pos) { return 0; }
+ size_t GetIndexLeft(size_t pos) { return 0; }
+ size_t GetIndexRight(size_t pos) { return 0; }
+ size_t GetIndexUp(size_t pos) { return 0; }
+ size_t GetIndexDown(size_t pos) { return 0; }
+ size_t GetIndexAtStartOfLine(size_t pos) { return 0; }
+ size_t GetIndexAtEndOfLine(size_t pos) { return 0; }
+
+ void SelectAll();
+ void SetSelection(size_t start_idx, size_t end_idx);
+ void ClearSelection();
+ bool HasSelection() const { return has_selection_; }
+ // Returns <start, end> indices of the selection.
+ std::pair<size_t, size_t> GetSelection() const {
+ return {selection_.start_idx, selection_.end_idx};
+ }
+ CFX_WideString GetSelectedText() const;
+ CFX_WideString DeleteSelectedText(
+ RecordOperation add_operation = RecordOperation::kInsertRecord);
+ void ReplaceSelectedText(const CFX_WideString& str);
+
+ void Layout();
+
+ wchar_t GetChar(size_t idx) const;
+ // Non-const so we can force a Layout() if needed.
+ size_t GetWidthOfChar(size_t idx);
+ // Non-const so we can force a Layout() if needed.
+ size_t GetIndexForPoint(const CFX_PointF& point);
+
+ // Returns <bidi level, character rect>
+ std::pair<int32_t, CFX_RectF> GetCharacterInfo(int32_t start_idx);
+ std::vector<CFX_RectF> GetCharacterRectsInRange(int32_t start_idx,
+ int32_t count);
+
+ CFX_TxtBreak* GetTextBreak() { return &text_break_; }
+
+ const std::vector<FDE_TEXTEDITPIECE>& GetTextPieces() {
+ // Force a layout if needed.
+ Layout();
+ return text_piece_info_;
+ }
+
+ std::vector<FXTEXT_CHARPOS> GetDisplayPos(const FDE_TEXTEDITPIECE& info);
+
+ void SetMaxEditOperationsForTesting(size_t max);
+
+ private:
+ void SetCombTextWidth();
+ void AdjustGap(size_t idx, size_t length);
+ void RebuildPieces();
+ size_t CountCharsExceedingSize(const CFX_WideString& str,
+ size_t num_to_check);
+ void AddOperationRecord(std::unique_ptr<Operation> op);
+
+ bool IsAlignedRight() const {
+ return !!(character_alignment_ & CFX_TxtLineAlignment_Left);
+ }
+
+ bool IsAlignedCenter() const {
+ return !!(character_alignment_ & CFX_TxtLineAlignment_Center);
+ }
+ std::vector<CFX_RectF> GetCharRects(const FDE_TEXTEDITPIECE& piece);
+
+ struct Selection {
+ size_t start_idx;
+ size_t end_idx;
+ };
+
+ CFX_RectF contents_bounding_box_;
+ CFX_UnownedPtr<Delegate> delegate_;
+ std::vector<FDE_TEXTEDITPIECE> text_piece_info_;
+ std::vector<size_t> char_widths_;
+ CFX_TxtBreak text_break_;
+ CFX_RetainPtr<CFGAS_GEFont> font_;
+ FX_ARGB font_color_;
+ float font_size_;
+ float line_spacing_;
+ std::vector<CFX_WideString::CharType> content_;
+ size_t text_length_;
+ size_t gap_position_;
+ size_t gap_size_;
+ size_t available_width_;
+ size_t character_limit_;
+ size_t visible_line_count_;
+ // Ring buffer of edit operations
+ std::vector<std::unique_ptr<Operation>> operation_buffer_;
+ // Next edit operation to undo.
+ size_t next_operation_index_to_undo_;
+ // Next index to insert an edit operation into.
+ size_t next_operation_index_to_insert_;
+ size_t max_edit_operations_;
+ uint32_t character_alignment_;
+ bool has_character_limit_;
+ bool is_comb_text_;
+ bool is_dirty_;
+ bool validation_enabled_;
+ bool is_multiline_;
+ bool is_linewrap_enabled_;
+ bool limit_horizontal_area_;
+ bool limit_vertical_area_;
+ bool password_mode_;
+ wchar_t password_alias_;
+ bool has_selection_;
+ Selection selection_;
+};
+
+#endif // XFA_FDE_CFDE_TEXTEDITENGINE_H_
diff --git a/xfa/fde/cfde_texteditengine_unittest.cpp b/xfa/fde/cfde_texteditengine_unittest.cpp
new file mode 100644
index 0000000000..da11e46daa
--- /dev/null
+++ b/xfa/fde/cfde_texteditengine_unittest.cpp
@@ -0,0 +1,418 @@
+// Copyright 2017 PDFium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "xfa/fde/cfde_texteditengine.h"
+
+#include "testing/gtest/include/gtest/gtest.h"
+#include "testing/test_support.h"
+#include "third_party/base/ptr_util.h"
+
+class CFDE_TextEditEngineTest : public testing::Test {
+ public:
+ class Delegate : public CFDE_TextEditEngine::Delegate {
+ public:
+ void Reset() {
+ text_is_full = false;
+ fail_validation = false;
+ }
+
+ void NotifyTextFull() override { text_is_full = true; }
+
+ void OnCaretChanged() override {}
+ void OnTextChanged(const CFX_WideString& prevText) override {}
+ void OnSelChanged() override {}
+ bool OnValidate(const CFX_WideString& wsText) override {
+ return !fail_validation;
+ }
+ void SetScrollOffset(float fScrollOffset) override {}
+
+ bool fail_validation = false;
+ bool text_is_full = false;
+ };
+
+ CFDE_TextEditEngineTest() {}
+ ~CFDE_TextEditEngineTest() override {}
+
+ void SetUp() override {
+ font_ =
+ CFGAS_GEFont::LoadFont(L"Arial Black", 0, 0, GetGlobalFontManager());
+ ASSERT(font_.Get() != nullptr);
+
+ engine_ = pdfium::MakeUnique<CFDE_TextEditEngine>();
+ engine_->SetFont(font_);
+ engine_->SetFontSize(12.0f);
+ }
+
+ void TearDown() override { engine_.reset(); }
+
+ CFDE_TextEditEngine* engine() const { return engine_.get(); }
+
+ private:
+ CFX_RetainPtr<CFGAS_GEFont> font_;
+ std::unique_ptr<CFDE_TextEditEngine> engine_;
+};
+
+TEST_F(CFDE_TextEditEngineTest, Insert) {
+ EXPECT_STREQ(L"", engine()->GetText().c_str());
+
+ engine()->Insert(0, L"");
+ EXPECT_STREQ(L"", engine()->GetText().c_str());
+ EXPECT_EQ(0U, engine()->GetLength());
+
+ engine()->Insert(0, L"Hello");
+ EXPECT_STREQ(L"Hello", engine()->GetText().c_str());
+ EXPECT_EQ(5U, engine()->GetLength());
+
+ engine()->Insert(5, L" World");
+ EXPECT_STREQ(L"Hello World", engine()->GetText().c_str());
+ EXPECT_EQ(11U, engine()->GetLength());
+
+ engine()->Insert(5, L" New");
+ EXPECT_STREQ(L"Hello New World", engine()->GetText().c_str());
+
+ engine()->Insert(100, L" Cat");
+ EXPECT_STREQ(L"Hello New World Cat", engine()->GetText().c_str());
+
+ engine()->Clear();
+
+ engine()->SetHasCharacterLimit(true);
+ engine()->SetCharacterLimit(5);
+ engine()->Insert(0, L"Hello");
+
+ // No delegate
+ engine()->Insert(5, L" World");
+ EXPECT_STREQ(L"Hello", engine()->GetText().c_str());
+
+ engine()->SetCharacterLimit(8);
+ engine()->Insert(5, L" World");
+ EXPECT_STREQ(L"Hello Wo", engine()->GetText().c_str());
+
+ engine()->Clear();
+
+ // With Delegate
+ auto delegate = pdfium::MakeUnique<CFDE_TextEditEngineTest::Delegate>();
+ engine()->SetDelegate(delegate.get());
+
+ engine()->SetCharacterLimit(5);
+ engine()->Insert(0, L"Hello");
+
+ // Insert when full.
+ engine()->Insert(5, L" World");
+ EXPECT_TRUE(delegate->text_is_full);
+ EXPECT_STREQ(L"Hello", engine()->GetText().c_str());
+ delegate->Reset();
+
+ engine()->SetCharacterLimit(8);
+ engine()->Insert(5, L" World");
+ EXPECT_TRUE(delegate->text_is_full);
+ EXPECT_STREQ(L"Hello Wo", engine()->GetText().c_str());
+ delegate->Reset();
+ engine()->SetHasCharacterLimit(false);
+
+ engine()->Clear();
+ engine()->Insert(0, L"Hello");
+
+ // Insert Invalid text
+ delegate->fail_validation = true;
+ engine()->EnableValidation(true);
+ engine()->Insert(5, L" World");
+ EXPECT_STREQ(L"Hello", engine()->GetText().c_str());
+
+ delegate->fail_validation = false;
+ engine()->Insert(5, L" World");
+ EXPECT_STREQ(L"Hello World", engine()->GetText().c_str());
+ engine()->EnableValidation(false);
+
+ engine()->Clear();
+
+ engine()->Insert(0, L"Hello\nWorld");
+ EXPECT_FALSE(delegate->text_is_full);
+ EXPECT_STREQ(L"Hello\nWorld", engine()->GetText().c_str());
+ delegate->Reset();
+ engine()->Clear();
+
+ // Insert with limited area and over-fill
+ engine()->LimitHorizontalScroll(true);
+ engine()->SetAvailableWidth(60.0f); // Fits 'Hello Wo'.
+ engine()->Insert(0, L"Hello");
+ EXPECT_FALSE(delegate->text_is_full);
+ engine()->Insert(5, L" World");
+ EXPECT_TRUE(delegate->text_is_full);
+ EXPECT_STREQ(L"Hello Wo", engine()->GetText().c_str());
+ engine()->LimitHorizontalScroll(false);
+
+ delegate->Reset();
+ engine()->Clear();
+
+ engine()->SetLineSpace(12.0f);
+ engine()->LimitVerticalScroll(true);
+ // Default is one line of text.
+ engine()->Insert(0, L"Hello");
+ EXPECT_FALSE(delegate->text_is_full);
+ engine()->Insert(5, L" Wo\nrld");
+ EXPECT_TRUE(delegate->text_is_full);
+ EXPECT_STREQ(L"Hello Wo\n", engine()->GetText().c_str());
+ engine()->LimitVerticalScroll(false);
+
+ engine()->SetDelegate(nullptr);
+}
+
+TEST_F(CFDE_TextEditEngineTest, Delete) {
+ EXPECT_STREQ(L"", engine()->Delete(0, 50).c_str());
+ EXPECT_STREQ(L"", engine()->GetText().c_str());
+
+ engine()->Insert(0, L"Hello World");
+ EXPECT_STREQ(L" World", engine()->Delete(5, 6).c_str());
+ EXPECT_STREQ(L"Hello", engine()->GetText().c_str());
+
+ engine()->Clear();
+ engine()->Insert(0, L"Hello World");
+ EXPECT_STREQ(L" ", engine()->Delete(5, 1).c_str());
+ EXPECT_STREQ(L"HelloWorld", engine()->GetText().c_str());
+
+ EXPECT_STREQ(L"elloWorld", engine()->Delete(1, 50).c_str());
+ EXPECT_STREQ(L"H", engine()->GetText().c_str());
+}
+
+TEST_F(CFDE_TextEditEngineTest, Clear) {
+ EXPECT_STREQ(L"", engine()->GetText().c_str());
+
+ engine()->Clear();
+ EXPECT_STREQ(L"", engine()->GetText().c_str());
+
+ engine()->Insert(0, L"Hello World");
+ EXPECT_STREQ(L"Hello World", engine()->GetText().c_str());
+
+ engine()->Clear();
+ EXPECT_STREQ(L"", engine()->GetText().c_str());
+ EXPECT_EQ(0U, engine()->GetLength());
+}
+
+TEST_F(CFDE_TextEditEngineTest, GetChar) {
+ // Out of bounds.
+ EXPECT_EQ(L'\0', engine()->GetChar(0));
+
+ engine()->Insert(0, L"Hello World");
+ EXPECT_EQ(L'H', engine()->GetChar(0));
+ EXPECT_EQ(L'd', engine()->GetChar(engine()->GetLength() - 1));
+ EXPECT_EQ(L' ', engine()->GetChar(5));
+
+ engine()->Insert(5, L" A");
+ EXPECT_STREQ(L"Hello A World", engine()->GetText().c_str());
+ EXPECT_EQ(L'W', engine()->GetChar(8));
+
+ engine()->EnablePasswordMode(true);
+ EXPECT_EQ(L'*', engine()->GetChar(8));
+
+ engine()->SetAliasChar(L'+');
+ EXPECT_EQ(L'+', engine()->GetChar(8));
+}
+
+TEST_F(CFDE_TextEditEngineTest, GetWidthOfChar) {
+ // Out of Bounds.
+ EXPECT_EQ(0U, engine()->GetWidthOfChar(0));
+
+ engine()->Insert(0, L"Hello World");
+ EXPECT_EQ(199920U, engine()->GetWidthOfChar(0));
+ EXPECT_EQ(159840U, engine()->GetWidthOfChar(1));
+
+ engine()->Insert(0, L"\t");
+ EXPECT_EQ(0U, engine()->GetWidthOfChar(0));
+}
+
+TEST_F(CFDE_TextEditEngineTest, GetDisplayPos) {
+ EXPECT_EQ(0U, engine()->GetDisplayPos(FDE_TEXTEDITPIECE()).size());
+}
+
+TEST_F(CFDE_TextEditEngineTest, Selection) {
+ EXPECT_FALSE(engine()->HasSelection());
+ engine()->SelectAll();
+ EXPECT_FALSE(engine()->HasSelection());
+
+ engine()->Insert(0, L"Hello World");
+ EXPECT_STREQ(L"", engine()->DeleteSelectedText().c_str());
+
+ EXPECT_FALSE(engine()->HasSelection());
+ engine()->SelectAll();
+ EXPECT_TRUE(engine()->HasSelection());
+ EXPECT_STREQ(L"Hello World", engine()->GetSelectedText().c_str());
+
+ engine()->ClearSelection();
+ EXPECT_FALSE(engine()->HasSelection());
+ EXPECT_STREQ(L"", engine()->GetSelectedText().c_str());
+
+ engine()->SelectAll();
+ size_t start_idx;
+ size_t end_idx;
+ std::tie(start_idx, end_idx) = engine()->GetSelection();
+ EXPECT_EQ(0U, start_idx);
+ EXPECT_EQ(10U, end_idx);
+
+ // Selection before gap.
+ EXPECT_STREQ(L"Hello World", engine()->GetSelectedText().c_str());
+ EXPECT_TRUE(engine()->HasSelection());
+ EXPECT_STREQ(L"Hello World", engine()->GetText().c_str());
+
+ engine()->Insert(5, L" A");
+ EXPECT_FALSE(engine()->HasSelection());
+ EXPECT_STREQ(L"", engine()->GetSelectedText().c_str());
+
+ // Selection over the gap.
+ engine()->SelectAll();
+ EXPECT_TRUE(engine()->HasSelection());
+ EXPECT_STREQ(L"Hello A World", engine()->GetSelectedText().c_str());
+ engine()->Clear();
+
+ engine()->Insert(0, L"Hello World");
+ engine()->SelectAll();
+
+ EXPECT_STREQ(L"Hello World", engine()->DeleteSelectedText().c_str());
+ EXPECT_FALSE(engine()->HasSelection());
+ EXPECT_STREQ(L"", engine()->GetText().c_str());
+
+ engine()->Insert(0, L"Hello World");
+ engine()->SetSelection(5, 9);
+ EXPECT_STREQ(L" Worl", engine()->DeleteSelectedText().c_str());
+ EXPECT_FALSE(engine()->HasSelection());
+ EXPECT_STREQ(L"Hellod", engine()->GetText().c_str());
+
+ engine()->Clear();
+ engine()->Insert(0, L"Hello World");
+ engine()->SelectAll();
+ engine()->ReplaceSelectedText(L"Goodbye Everybody");
+ EXPECT_FALSE(engine()->HasSelection());
+ EXPECT_STREQ(L"Goodbye Everybody", engine()->GetText().c_str());
+
+ engine()->Clear();
+ engine()->Insert(0, L"Hello World");
+ engine()->SetSelection(1, 4);
+ engine()->ReplaceSelectedText(L"i,");
+ EXPECT_FALSE(engine()->HasSelection());
+ EXPECT_STREQ(L"Hi, World", engine()->GetText().c_str());
+
+ // Selection fully after gap.
+ engine()->Clear();
+ engine()->Insert(0, L"Hello");
+ engine()->Insert(0, L"A ");
+ engine()->SetSelection(3, 6);
+ EXPECT_STREQ(L"ello", engine()->GetSelectedText().c_str());
+
+ engine()->Clear();
+ engine()->Insert(0, L"Hello World");
+ engine()->ClearSelection();
+ engine()->DeleteSelectedText();
+ EXPECT_STREQ(L"Hello World", engine()->GetText().c_str());
+}
+
+TEST_F(CFDE_TextEditEngineTest, UndoRedo) {
+ EXPECT_FALSE(engine()->CanUndo());
+ EXPECT_FALSE(engine()->CanRedo());
+ EXPECT_FALSE(engine()->Undo());
+ EXPECT_FALSE(engine()->Redo());
+
+ engine()->Insert(0, L"Hello");
+ EXPECT_TRUE(engine()->CanUndo());
+ EXPECT_FALSE(engine()->CanRedo());
+ EXPECT_TRUE(engine()->Undo());
+ EXPECT_STREQ(L"", engine()->GetText().c_str());
+ EXPECT_FALSE(engine()->CanUndo());
+ EXPECT_TRUE(engine()->CanRedo());
+ EXPECT_TRUE(engine()->Redo());
+ EXPECT_STREQ(L"Hello", engine()->GetText().c_str());
+ EXPECT_TRUE(engine()->CanUndo());
+ EXPECT_FALSE(engine()->CanRedo());
+
+ engine()->Clear();
+ EXPECT_FALSE(engine()->CanUndo());
+ EXPECT_FALSE(engine()->CanRedo());
+
+ engine()->Insert(0, L"Hello World");
+ engine()->SelectAll();
+ engine()->DeleteSelectedText();
+ EXPECT_STREQ(L"", engine()->GetText().c_str());
+ EXPECT_TRUE(engine()->CanUndo());
+ EXPECT_TRUE(engine()->Undo());
+ EXPECT_STREQ(L"Hello World", engine()->GetText().c_str());
+ EXPECT_TRUE(engine()->CanRedo());
+ EXPECT_TRUE(engine()->Redo());
+ EXPECT_STREQ(L"", engine()->GetText().c_str());
+ EXPECT_TRUE(engine()->CanUndo());
+ EXPECT_FALSE(engine()->CanRedo());
+
+ engine()->Insert(0, L"Hello World");
+ engine()->SelectAll();
+ engine()->ReplaceSelectedText(L"Goodbye Friend");
+ EXPECT_STREQ(L"Goodbye Friend", engine()->GetText().c_str());
+ EXPECT_TRUE(engine()->CanUndo());
+ EXPECT_TRUE(engine()->Undo());
+ EXPECT_STREQ(L"Hello World", engine()->GetText().c_str());
+ EXPECT_TRUE(engine()->CanRedo());
+ EXPECT_TRUE(engine()->Redo());
+ EXPECT_STREQ(L"Goodbye Friend", engine()->GetText().c_str());
+
+ engine()->Clear();
+ engine()->SetMaxEditOperationsForTesting(3);
+ engine()->Insert(0, L"First ");
+ engine()->Insert(engine()->GetLength(), L"Second ");
+ engine()->Insert(engine()->GetLength(), L"Third");
+
+ EXPECT_TRUE(engine()->CanUndo());
+ EXPECT_TRUE(engine()->Undo());
+ EXPECT_STREQ(L"First Second ", engine()->GetText().c_str());
+ EXPECT_TRUE(engine()->CanUndo());
+ EXPECT_TRUE(engine()->Undo());
+ EXPECT_FALSE(
+ engine()->CanUndo()); // Can't undo First; undo buffer too small.
+ EXPECT_STREQ(L"First ", engine()->GetText().c_str());
+
+ EXPECT_TRUE(engine()->CanRedo());
+ EXPECT_TRUE(engine()->Redo());
+ EXPECT_TRUE(engine()->CanRedo());
+ EXPECT_TRUE(engine()->Redo());
+ EXPECT_FALSE(engine()->CanRedo());
+ EXPECT_STREQ(L"First Second Third", engine()->GetText().c_str());
+
+ engine()->Clear();
+
+ engine()->SetMaxEditOperationsForTesting(4);
+
+ // Go beyond the max operations limit.
+ engine()->Insert(0, L"H");
+ engine()->Insert(1, L"e");
+ engine()->Insert(2, L"l");
+ engine()->Insert(3, L"l");
+ engine()->Insert(4, L"o");
+ engine()->Insert(5, L" World");
+ EXPECT_STREQ(L"Hello World", engine()->GetText().c_str());
+
+ // Do A, undo. Do B, undo. Redo should cause B.
+ engine()->Delete(4, 3);
+ EXPECT_STREQ(L"Hellorld", engine()->GetText().c_str());
+ EXPECT_TRUE(engine()->Undo());
+ EXPECT_STREQ(L"Hello World", engine()->GetText().c_str());
+ engine()->Delete(5, 6);
+ EXPECT_STREQ(L"Hello", engine()->GetText().c_str());
+ EXPECT_TRUE(engine()->Undo());
+ EXPECT_STREQ(L"Hello World", engine()->GetText().c_str());
+ EXPECT_TRUE(engine()->Redo());
+ EXPECT_STREQ(L"Hello", engine()->GetText().c_str());
+
+ // Undo down to the limit.
+ EXPECT_TRUE(engine()->Undo());
+ EXPECT_STREQ(L"Hello World", engine()->GetText().c_str());
+ EXPECT_TRUE(engine()->Undo());
+ EXPECT_STREQ(L"Hello", engine()->GetText().c_str());
+ EXPECT_TRUE(engine()->Undo());
+ EXPECT_STREQ(L"Hell", engine()->GetText().c_str());
+ EXPECT_FALSE(engine()->Undo());
+ EXPECT_STREQ(L"Hell", engine()->GetText().c_str());
+}
+
+TEST_F(CFDE_TextEditEngineTest, GetIndexForPoint) {
+ engine()->SetFontSize(10.0f);
+ engine()->Insert(0, L"Hello World");
+ EXPECT_EQ(0U, engine()->GetIndexForPoint({0.0f, 0.0f}));
+ EXPECT_EQ(11U, engine()->GetIndexForPoint({999999.0f, 9999999.0f}));
+ EXPECT_EQ(1U, engine()->GetIndexForPoint({10.0f, 5.0f}));
+}
diff --git a/xfa/fde/cfde_txtedtbuf.cpp b/xfa/fde/cfde_txtedtbuf.cpp
deleted file mode 100644
index caa223c697..0000000000
--- a/xfa/fde/cfde_txtedtbuf.cpp
+++ /dev/null
@@ -1,316 +0,0 @@
-// Copyright 2014 PDFium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com
-
-#include "xfa/fde/cfde_txtedtbuf.h"
-
-#include <algorithm>
-#include <utility>
-
-#include "third_party/base/ptr_util.h"
-#include "third_party/base/stl_util.h"
-
-namespace {
-
-const int32_t kDefaultChunkSize = 1024;
-
-} // namespace
-
-CFDE_TxtEdtBuf::CFDE_TxtEdtBuf() : m_chunkSize(kDefaultChunkSize), m_nTotal(0) {
- m_chunks.push_back(pdfium::MakeUnique<ChunkHeader>(m_chunkSize));
-}
-
-CFDE_TxtEdtBuf::~CFDE_TxtEdtBuf() {}
-
-void CFDE_TxtEdtBuf::SetText(const CFX_WideString& wsText) {
- ASSERT(!wsText.IsEmpty());
-
- Clear();
-
- int32_t nTextLength = wsText.GetLength();
- int32_t nNeedCount = ((nTextLength - 1) / m_chunkSize + 1) -
- pdfium::CollectionSize<int32_t>(m_chunks);
- for (int32_t i = 0; i < nNeedCount; ++i)
- m_chunks.push_back(pdfium::MakeUnique<ChunkHeader>(m_chunkSize));
-
- const wchar_t* lpSrcBuf = wsText.c_str();
- int32_t nLeave = nTextLength;
- int32_t nCopyedLength = m_chunkSize;
- for (size_t i = 0; i < m_chunks.size() && nLeave > 0; ++i) {
- if (nLeave < nCopyedLength)
- nCopyedLength = nLeave;
-
- ChunkHeader* chunk = m_chunks[i].get();
- memcpy(chunk->wChars.data(), lpSrcBuf, nCopyedLength * sizeof(wchar_t));
- nLeave -= nCopyedLength;
- lpSrcBuf += nCopyedLength;
- chunk->nUsed = nCopyedLength;
- }
- m_nTotal = nTextLength;
-}
-
-wchar_t CFDE_TxtEdtBuf::GetCharByIndex(int32_t nIndex) const {
- ASSERT(nIndex >= 0 && nIndex < GetTextLength());
-
- ChunkHeader* pChunkHeader = nullptr;
- int32_t nTotal = 0;
- for (const auto& chunk : m_chunks) {
- pChunkHeader = chunk.get();
- nTotal += pChunkHeader->nUsed;
- if (nTotal > nIndex)
- break;
- }
- ASSERT(pChunkHeader);
-
- return pChunkHeader->wChars[pChunkHeader->nUsed - (nTotal - nIndex)];
-}
-
-CFX_WideString CFDE_TxtEdtBuf::GetRange(int32_t nBegin, int32_t nLength) const {
- if (nLength == 0 || GetTextLength() == 0)
- return CFX_WideString();
-
- ASSERT(nBegin >= 0 && nLength > 0 && nBegin < GetTextLength() &&
- nBegin + nLength <= GetTextLength());
-
- int32_t chunkIndex = 0;
- int32_t charIndex = 0;
- std::tie(chunkIndex, charIndex) = Index2CP(nBegin);
-
- int32_t nLeave = nLength;
- CFX_WideString wsText;
-
- int32_t nCopyLength = m_chunks[chunkIndex]->nUsed - charIndex;
- wchar_t* lpSrcBuf = m_chunks[chunkIndex]->wChars.data() + charIndex;
- while (nLeave > 0) {
- if (nLeave <= nCopyLength)
- nCopyLength = nLeave;
-
- wsText += CFX_WideStringC(lpSrcBuf, nCopyLength);
-
- ++chunkIndex;
- if (chunkIndex >= pdfium::CollectionSize<int32_t>(m_chunks))
- break;
-
- lpSrcBuf = m_chunks[chunkIndex]->wChars.data();
- nLeave -= nCopyLength;
- nCopyLength = m_chunks[chunkIndex]->nUsed;
- }
- return wsText;
-}
-
-void CFDE_TxtEdtBuf::Insert(int32_t nPos, const CFX_WideString& wsText) {
- ASSERT(nPos >= 0 && nPos <= m_nTotal);
-
- int32_t nLength = wsText.GetLength();
- ASSERT(nLength > 0);
-
- int32_t chunkIndex = 0;
- int32_t charIndex = 0;
- std::tie(chunkIndex, charIndex) = Index2CP(nPos);
-
- if (charIndex != 0) {
- auto newChunk = pdfium::MakeUnique<ChunkHeader>(m_chunkSize);
-
- ChunkHeader* chunk = m_chunks[chunkIndex].get();
- int32_t nCopy = chunk->nUsed - charIndex;
-
- memcpy(newChunk->wChars.data(), chunk->wChars.data() + charIndex,
- nCopy * sizeof(wchar_t));
- chunk->nUsed -= nCopy;
- ++chunkIndex;
-
- newChunk->nUsed = nCopy;
- m_chunks.insert(m_chunks.begin() + chunkIndex, std::move(newChunk));
- charIndex = 0;
- }
-
- const wchar_t* lpText = wsText.c_str();
- if (chunkIndex != 0) {
- ChunkHeader* chunk = m_chunks[chunkIndex - 1].get();
- if (chunk->nUsed != m_chunkSize) {
- chunkIndex--;
- int32_t nCopy = std::min(nLength, m_chunkSize - chunk->nUsed);
- memcpy(chunk->wChars.data() + chunk->nUsed, lpText,
- nCopy * sizeof(wchar_t));
- lpText += nCopy;
- nLength -= nCopy;
- chunk->nUsed += nCopy;
- ++chunkIndex;
- }
- }
-
- while (nLength > 0) {
- auto chunk = pdfium::MakeUnique<ChunkHeader>(m_chunkSize);
-
- int32_t nCopy = std::min(nLength, m_chunkSize);
- memcpy(chunk->wChars.data(), lpText, nCopy * sizeof(wchar_t));
- lpText += nCopy;
- nLength -= nCopy;
- chunk->nUsed = nCopy;
- m_chunks.insert(m_chunks.begin() + chunkIndex, std::move(chunk));
- ++chunkIndex;
- }
-
- m_nTotal += wsText.GetLength();
-}
-
-void CFDE_TxtEdtBuf::Delete(int32_t nIndex, int32_t nLength) {
- ASSERT(nLength > 0 && nIndex >= 0 && nIndex + nLength <= m_nTotal);
-
- int32_t endChunkIndex = 0;
- int32_t endCharIndex = 0;
- std::tie(endChunkIndex, endCharIndex) = Index2CP(nIndex + nLength - 1);
- m_nTotal -= nLength;
-
- int32_t nFirstPart = endCharIndex + 1;
- int32_t nMovePart = m_chunks[endChunkIndex]->nUsed - nFirstPart;
- if (nMovePart != 0) {
- int32_t nDelete = std::min(nFirstPart, nLength);
- memmove(m_chunks[endChunkIndex]->wChars.data() + nFirstPart - nDelete,
- m_chunks[endChunkIndex]->wChars.data() + nFirstPart,
- nMovePart * sizeof(wchar_t));
- m_chunks[endChunkIndex]->nUsed -= nDelete;
- nLength -= nDelete;
- --endChunkIndex;
- }
-
- while (nLength > 0) {
- int32_t nDeleted = std::min(m_chunks[endChunkIndex]->nUsed, nLength);
- m_chunks[endChunkIndex]->nUsed -= nDeleted;
- if (m_chunks[endChunkIndex]->nUsed == 0)
- m_chunks.erase(m_chunks.begin() + endChunkIndex);
-
- nLength -= nDeleted;
- --endChunkIndex;
- }
-}
-
-void CFDE_TxtEdtBuf::Clear() {
- for (auto& chunk : m_chunks)
- chunk->nUsed = 0;
- m_nTotal = 0;
-}
-
-void CFDE_TxtEdtBuf::SetChunkSizeForTesting(size_t size) {
- ASSERT(size > 0);
-
- m_chunkSize = size;
- m_chunks.clear();
- m_chunks.push_back(pdfium::MakeUnique<ChunkHeader>(m_chunkSize));
-}
-
-std::pair<int32_t, int32_t> CFDE_TxtEdtBuf::Index2CP(int32_t nIndex) const {
- ASSERT(nIndex <= GetTextLength());
-
- if (nIndex == m_nTotal)
- return {m_chunks.size() - 1, m_chunks.back()->nUsed};
-
- int32_t chunkIndex = 0;
- int32_t nTotal = 0;
- for (auto& chunk : m_chunks) {
- nTotal += chunk->nUsed;
- if (nTotal > nIndex)
- break;
-
- ++chunkIndex;
- }
-
- return {chunkIndex, m_chunks[chunkIndex]->nUsed - (nTotal - nIndex)};
-}
-
-CFDE_TxtEdtBuf::ChunkHeader::ChunkHeader(int32_t chunkSize) : nUsed(0) {
- wChars.resize(chunkSize);
-}
-
-CFDE_TxtEdtBuf::ChunkHeader::~ChunkHeader() {}
-
-CFDE_TxtEdtBuf::Iterator::Iterator(CFDE_TxtEdtBuf* pBuf, wchar_t wcAlias)
- : m_pBuf(pBuf),
- m_nCurChunk(0),
- m_nCurIndex(0),
- m_nIndex(0),
- m_Alias(wcAlias) {
- ASSERT(m_pBuf);
-}
-
-CFDE_TxtEdtBuf::Iterator::~Iterator() {}
-
-bool CFDE_TxtEdtBuf::Iterator::Next(bool bPrev) {
- if (bPrev) {
- if (m_nIndex == 0)
- return false;
-
- ASSERT(m_nCurChunk < pdfium::CollectionSize<int32_t>(m_pBuf->m_chunks));
-
- if (m_nCurIndex > 0) {
- --m_nCurIndex;
- } else {
- while (m_nCurChunk > 0) {
- --m_nCurChunk;
- ChunkHeader* chunk = m_pBuf->m_chunks[m_nCurChunk].get();
- if (chunk->nUsed > 0) {
- m_nCurIndex = chunk->nUsed - 1;
- break;
- }
- }
- }
- ASSERT(m_nCurChunk >= 0);
-
- --m_nIndex;
- return true;
- }
-
- if (m_nIndex >= (m_pBuf->m_nTotal - 1))
- return false;
-
- ASSERT(m_nCurChunk < pdfium::CollectionSize<int32_t>(m_pBuf->m_chunks));
-
- if (m_pBuf->m_chunks[m_nCurChunk]->nUsed != (m_nCurIndex + 1)) {
- ++m_nCurIndex;
- } else {
- while (m_nCurChunk <
- pdfium::CollectionSize<int32_t>(m_pBuf->m_chunks) - 1) {
- ++m_nCurChunk;
- if (m_pBuf->m_chunks[m_nCurChunk]->nUsed > 0) {
- m_nCurIndex = 0;
- break;
- }
- }
- }
- ++m_nIndex;
- return true;
-}
-
-void CFDE_TxtEdtBuf::Iterator::SetAt(int32_t nIndex) {
- ASSERT(nIndex >= 0 && nIndex < m_pBuf->m_nTotal);
-
- std::tie(m_nCurChunk, m_nCurIndex) = m_pBuf->Index2CP(nIndex);
- m_nIndex = nIndex;
-}
-
-int32_t CFDE_TxtEdtBuf::Iterator::GetAt() const {
- return m_nIndex;
-}
-
-wchar_t CFDE_TxtEdtBuf::Iterator::GetChar() const {
- ASSERT(m_nIndex >= 0 && m_nIndex < m_pBuf->m_nTotal);
-
- if (m_Alias != 0 && m_nIndex != (m_pBuf->m_nTotal - 1))
- return m_Alias;
- return m_pBuf->m_chunks[m_nCurChunk]->wChars[m_nCurIndex];
-}
-
-bool CFDE_TxtEdtBuf::Iterator::IsEOF(bool bTail) const {
- return bTail ? m_nIndex == (m_pBuf->GetTextLength() - 2) : m_nIndex == 0;
-}
-
-std::unique_ptr<IFX_CharIter> CFDE_TxtEdtBuf::Iterator::Clone() const {
- auto pIter = pdfium::MakeUnique<CFDE_TxtEdtBuf::Iterator>(m_pBuf, 0);
- pIter->m_nCurChunk = m_nCurChunk;
- pIter->m_nCurIndex = m_nCurIndex;
- pIter->m_nIndex = m_nIndex;
- pIter->m_Alias = m_Alias;
- return pIter;
-}
diff --git a/xfa/fde/cfde_txtedtbuf.h b/xfa/fde/cfde_txtedtbuf.h
deleted file mode 100644
index e8293d0240..0000000000
--- a/xfa/fde/cfde_txtedtbuf.h
+++ /dev/null
@@ -1,76 +0,0 @@
-// Copyright 2014 PDFium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com
-
-#ifndef XFA_FDE_CFDE_TXTEDTBUF_H_
-#define XFA_FDE_CFDE_TXTEDTBUF_H_
-
-#include <memory>
-#include <utility>
-#include <vector>
-
-#include "core/fxcrt/fx_basic.h"
-#include "core/fxcrt/fx_system.h"
-#include "core/fxcrt/ifx_chariter.h"
-
-class CFDE_TxtEdtBuf {
- public:
- class Iterator : public IFX_CharIter {
- public:
- Iterator(CFDE_TxtEdtBuf* pBuf, wchar_t wcAlias);
- ~Iterator() override;
-
- bool Next(bool bPrev = false) override;
- wchar_t GetChar() const override;
-
- void SetAt(int32_t nIndex) override;
- int32_t GetAt() const override;
-
- bool IsEOF(bool bTail = true) const override;
- std::unique_ptr<IFX_CharIter> Clone() const override;
-
- private:
- CFDE_TxtEdtBuf* m_pBuf;
- int32_t m_nCurChunk;
- int32_t m_nCurIndex;
- int32_t m_nIndex;
- wchar_t m_Alias;
- };
-
- CFDE_TxtEdtBuf();
- ~CFDE_TxtEdtBuf();
-
- int32_t GetTextLength() const { return m_nTotal; }
- void SetText(const CFX_WideString& wsText);
- CFX_WideString GetText() const { return GetRange(0, m_nTotal); }
-
- wchar_t GetCharByIndex(int32_t nIndex) const;
- CFX_WideString GetRange(int32_t nBegin, int32_t nCount) const;
-
- void Insert(int32_t nPos, const CFX_WideString& wsText);
- void Delete(int32_t nIndex, int32_t nLength);
- void Clear();
-
- void SetChunkSizeForTesting(size_t size);
- size_t GetChunkCountForTesting() const { return m_chunks.size(); }
-
- private:
- class ChunkHeader {
- public:
- explicit ChunkHeader(int32_t chunkSize);
- ~ChunkHeader();
-
- int32_t nUsed;
- std::vector<wchar_t> wChars;
- };
-
- std::pair<int32_t, int32_t> Index2CP(int32_t nIndex) const;
-
- int32_t m_chunkSize;
- int32_t m_nTotal;
- std::vector<std::unique_ptr<ChunkHeader>> m_chunks;
-};
-
-#endif // XFA_FDE_CFDE_TXTEDTBUF_H_
diff --git a/xfa/fde/cfde_txtedtbuf_unittest.cpp b/xfa/fde/cfde_txtedtbuf_unittest.cpp
deleted file mode 100644
index 8c112f19e2..0000000000
--- a/xfa/fde/cfde_txtedtbuf_unittest.cpp
+++ /dev/null
@@ -1,188 +0,0 @@
-// Copyright 2017 PDFium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "xfa/fde/cfde_txtedtbuf.h"
-
-#include "testing/gtest/include/gtest/gtest.h"
-#include "testing/test_support.h"
-#include "third_party/base/ptr_util.h"
-
-class CFDE_TxtEdtBufTest : public testing::Test {
- public:
- void SetUp() override {
- buf_ = pdfium::MakeUnique<CFDE_TxtEdtBuf>();
- buf_->SetChunkSizeForTesting(5);
- }
-
- size_t ChunkCount() const { return buf_->GetChunkCountForTesting(); }
-
- std::unique_ptr<CFDE_TxtEdtBuf> buf_;
-};
-
-TEST_F(CFDE_TxtEdtBufTest, SetTextLessThenChunkSize) {
- buf_->SetText(L"Hi");
- EXPECT_EQ(1UL, ChunkCount());
- EXPECT_EQ(2, buf_->GetTextLength());
-
- CFX_WideString res = buf_->GetText();
- EXPECT_EQ(2, res.GetLength());
- EXPECT_EQ(L"Hi", res);
-}
-
-TEST_F(CFDE_TxtEdtBufTest, InsertAppendChunk) {
- buf_->SetText(L"Hi");
-
- CFX_WideString end = L" World";
- buf_->Insert(2, end);
- EXPECT_EQ(3UL, ChunkCount());
- EXPECT_EQ(8, buf_->GetTextLength());
-
- CFX_WideString res = buf_->GetText();
- EXPECT_EQ(8, res.GetLength());
- EXPECT_EQ(L"Hi World", res);
-}
-
-TEST_F(CFDE_TxtEdtBufTest, InsertPrependChunk) {
- buf_->SetText(L"Hi");
-
- CFX_WideString end = L"World ";
- buf_->Insert(0, end);
- EXPECT_EQ(3UL, ChunkCount());
- EXPECT_EQ(8, buf_->GetTextLength());
-
- CFX_WideString res = buf_->GetText();
- EXPECT_EQ(L"World Hi", res);
- EXPECT_EQ(8, res.GetLength());
-}
-
-TEST_F(CFDE_TxtEdtBufTest, InsertBetweenChunks) {
- buf_->SetText(L"Hello World");
- EXPECT_EQ(3UL, ChunkCount());
-
- CFX_WideString inst = L"there ";
- buf_->Insert(6, inst);
- EXPECT_EQ(5UL, ChunkCount());
- EXPECT_EQ(17, buf_->GetTextLength());
-
- CFX_WideString res = buf_->GetText();
- EXPECT_EQ(L"Hello there World", res);
- EXPECT_EQ(17, res.GetLength());
-}
-
-TEST_F(CFDE_TxtEdtBufTest, SetText) {
- buf_->SetText(L"Hello World");
- EXPECT_EQ(11, buf_->GetTextLength());
-
- buf_->SetText(L"Hi");
- // Don't remove chunks on setting shorter text.
- EXPECT_EQ(3UL, ChunkCount());
- EXPECT_EQ(2, buf_->GetTextLength());
-
- CFX_WideString res = buf_->GetText();
- EXPECT_EQ(L"Hi", res);
- EXPECT_EQ(2, res.GetLength());
-}
-
-TEST_F(CFDE_TxtEdtBufTest, DeleteMiddleText) {
- buf_->SetText(L"Hello there World");
- buf_->Delete(6, 6);
- EXPECT_EQ(4UL, ChunkCount());
- EXPECT_EQ(11, buf_->GetTextLength());
-
- CFX_WideString res = buf_->GetText();
- EXPECT_EQ(L"Hello World", res);
- EXPECT_EQ(11, res.GetLength());
-}
-
-TEST_F(CFDE_TxtEdtBufTest, DeleteEndText) {
- buf_->SetText(L"Hello World");
- buf_->Delete(5, 6);
- EXPECT_EQ(1UL, ChunkCount());
- EXPECT_EQ(5, buf_->GetTextLength());
-
- CFX_WideString res = buf_->GetText();
- EXPECT_EQ(L"Hello", res);
- EXPECT_EQ(5, res.GetLength());
-}
-
-TEST_F(CFDE_TxtEdtBufTest, DeleteStartText) {
- buf_->SetText(L"Hello World");
- buf_->Delete(0, 6);
- EXPECT_EQ(2UL, ChunkCount());
- EXPECT_EQ(5, buf_->GetTextLength());
-
- CFX_WideString res = buf_->GetText();
- EXPECT_EQ(L"World", res);
- EXPECT_EQ(5, res.GetLength());
-}
-
-TEST_F(CFDE_TxtEdtBufTest, DeleteAllText) {
- buf_->SetText(L"Hello World");
- buf_->Delete(0, 11);
- EXPECT_EQ(0UL, ChunkCount());
- EXPECT_EQ(0, buf_->GetTextLength());
-
- CFX_WideString res = buf_->GetText();
- EXPECT_EQ(L"", res);
- EXPECT_EQ(0, res.GetLength());
-}
-
-TEST_F(CFDE_TxtEdtBufTest, Clear) {
- buf_->SetText(L"Hello World");
- buf_->Clear();
- EXPECT_EQ(3UL, ChunkCount());
- EXPECT_EQ(0, buf_->GetTextLength());
-
- CFX_WideString res = buf_->GetText();
- EXPECT_EQ(L"", res);
- EXPECT_EQ(0, res.GetLength());
-}
-
-TEST_F(CFDE_TxtEdtBufTest, GetCharByIndex) {
- buf_->SetText(L"Hello world");
- EXPECT_EQ(L"e", CFX_WideString(buf_->GetCharByIndex(1)));
- EXPECT_EQ(L"o", CFX_WideString(buf_->GetCharByIndex(7)));
-}
-
-TEST_F(CFDE_TxtEdtBufTest, GetRange) {
- buf_->SetText(L"Hello World");
- EXPECT_EQ(L"", buf_->GetRange(1, 0));
- EXPECT_EQ(L"ello", buf_->GetRange(1, 4));
- EXPECT_EQ(L"lo Wo", buf_->GetRange(3, 5));
-}
-
-#ifndef NDEBUG
-using CFDE_TxtEdtBufTestDeathTest = CFDE_TxtEdtBufTest;
-
-TEST_F(CFDE_TxtEdtBufTestDeathTest, InsertBadIndexes) {
- CFX_WideString inst = L"there ";
-
- buf_->SetText(L"Hi");
- EXPECT_DEATH(buf_->Insert(-4, inst), "Assertion");
- EXPECT_DEATH(buf_->Insert(9999, inst), "Assertion");
-}
-
-TEST_F(CFDE_TxtEdtBufTestDeathTest, DeleteWithBadIdx) {
- buf_->SetText(L"Hi");
- EXPECT_DEATH(buf_->Delete(-10, 4), "Assertion");
- EXPECT_DEATH(buf_->Delete(1, -5), "Assertion");
- EXPECT_DEATH(buf_->Delete(5, 1), "Assertion");
- EXPECT_DEATH(buf_->Delete(0, 10000), "Assertion");
-}
-
-TEST_F(CFDE_TxtEdtBufTestDeathTest, GetCharByIndex) {
- buf_->SetText(L"Hi");
- EXPECT_DEATH(buf_->GetCharByIndex(-1), "Assertion");
- EXPECT_DEATH(buf_->GetCharByIndex(100), "Assertion");
-}
-
-TEST_F(CFDE_TxtEdtBufTestDeathTest, GetRange) {
- buf_->SetText(L"Hi");
- EXPECT_DEATH(buf_->GetRange(1, -1), "Assertion");
- EXPECT_DEATH(buf_->GetRange(-1, 1), "Assertion");
- EXPECT_DEATH(buf_->GetRange(10, 1), "Assertion");
- EXPECT_DEATH(buf_->GetRange(1, 100), "Assertion");
-}
-
-#endif // NDEBUG
diff --git a/xfa/fde/cfde_txtedtengine.cpp b/xfa/fde/cfde_txtedtengine.cpp
deleted file mode 100644
index e3815e7de4..0000000000
--- a/xfa/fde/cfde_txtedtengine.cpp
+++ /dev/null
@@ -1,1234 +0,0 @@
-// Copyright 2014 PDFium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com
-
-#include "xfa/fde/cfde_txtedtengine.h"
-
-#include <algorithm>
-#include <utility>
-
-#include "core/fxcrt/ifx_chariter.h"
-#include "third_party/base/ptr_util.h"
-#include "xfa/fde/cfde_textout.h"
-#include "xfa/fde/cfde_txtedtbuf.h"
-#include "xfa/fde/cfde_txtedtpage.h"
-#include "xfa/fde/cfde_txtedtparag.h"
-#include "xfa/fwl/cfwl_edit.h"
-
-namespace {
-
-const uint32_t kPageWidthMax = 0xffff;
-
-class InsertOperation : public IFDE_TxtEdtDoRecord {
- public:
- InsertOperation(CFDE_TxtEdtEngine* pEngine,
- int32_t nCaret,
- const CFX_WideString& str)
- : m_pEngine(pEngine), m_nCaret(nCaret), m_wsInsert(str) {
- ASSERT(m_pEngine);
- }
-
- ~InsertOperation() override {}
-
- void Undo() const override {
- CFX_WideString prev = m_pEngine->GetText(0, -1);
-
- if (m_pEngine->IsSelect())
- m_pEngine->ClearSelection();
-
- m_pEngine->Inner_DeleteRange(m_nCaret, m_wsInsert.GetLength());
- m_pEngine->GetParams()->pEventSink->OnTextChanged(prev);
- m_pEngine->SetCaretPos(m_nCaret, true);
- }
-
- void Redo() const override {
- CFX_WideString prev = m_pEngine->GetText(0, -1);
- m_pEngine->Inner_Insert(m_nCaret, m_wsInsert);
- m_pEngine->GetParams()->pEventSink->OnTextChanged(prev);
- m_pEngine->SetCaretPos(m_nCaret, false);
- }
-
- private:
- CFDE_TxtEdtEngine* m_pEngine;
- int32_t m_nCaret;
- CFX_WideString m_wsInsert;
-};
-
-class DeleteOperation : public IFDE_TxtEdtDoRecord {
- public:
- DeleteOperation(CFDE_TxtEdtEngine* pEngine,
- int32_t nIndex,
- int32_t nCaret,
- const CFX_WideString& wsRange,
- bool bSel)
- : m_pEngine(pEngine),
- m_bSel(bSel),
- m_nIndex(nIndex),
- m_nCaret(nCaret),
- m_wsRange(wsRange) {
- ASSERT(m_pEngine);
- }
-
- ~DeleteOperation() override {}
-
- void Undo() const override {
- CFX_WideString prev = m_pEngine->GetText(0, -1);
- if (m_pEngine->IsSelect())
- m_pEngine->ClearSelection();
-
- m_pEngine->Inner_Insert(m_nIndex, m_wsRange);
- if (m_bSel)
- m_pEngine->AddSelRange(m_nIndex, m_wsRange.GetLength());
-
- m_pEngine->GetParams()->pEventSink->OnTextChanged(prev);
- m_pEngine->SetCaretPos(m_nCaret, true);
- }
-
- void Redo() const override {
- CFX_WideString prev = m_pEngine->GetText(0, -1);
- m_pEngine->Inner_DeleteRange(m_nIndex, m_wsRange.GetLength());
- if (m_bSel)
- m_pEngine->RemoveSelRange(m_nIndex, m_wsRange.GetLength());
-
- m_pEngine->GetParams()->pEventSink->OnTextChanged(prev);
- m_pEngine->SetCaretPos(m_nIndex, true);
- }
-
- private:
- CFDE_TxtEdtEngine* m_pEngine;
- bool m_bSel;
- int32_t m_nIndex;
- int32_t m_nCaret;
- CFX_WideString m_wsRange;
-};
-
-} // namespace
-
-FDE_TXTEDTPARAMS::FDE_TXTEDTPARAMS()
- : fPlateWidth(0),
- fPlateHeight(0),
- nLineCount(0),
- dwLayoutStyles(0),
- dwAlignment(0),
- dwMode(0),
- fFontSize(10.0f),
- dwFontColor(0xff000000),
- fLineSpace(10.0f),
- fTabWidth(36),
- pEventSink(nullptr) {}
-
-FDE_TXTEDTPARAMS::~FDE_TXTEDTPARAMS() {}
-
-CFDE_TxtEdtEngine::CFDE_TxtEdtEngine()
- : m_pTxtBuf(pdfium::MakeUnique<CFDE_TxtEdtBuf>()),
- m_nPageLineCount(20),
- m_nLineCount(0),
- m_nAnchorPos(-1),
- m_fCaretPosReserve(0.0),
- m_nCaret(0),
- m_nCaretPage(0),
- m_nLimit(0),
- m_wcAliasChar(L'*'),
- m_FirstLineEnding(LineEnding::kAuto),
- m_bBefore(true),
- m_bLock(false),
- m_bAutoLineEnd(true) {}
-
-CFDE_TxtEdtEngine::~CFDE_TxtEdtEngine() {
- RemoveAllParags();
- RemoveAllPages();
- m_Param.pEventSink = nullptr;
- ClearSelection();
-}
-
-void CFDE_TxtEdtEngine::SetEditParams(const FDE_TXTEDTPARAMS& params) {
- m_Param = params;
- m_bAutoLineEnd = true;
- UpdateTxtBreak();
-}
-
-CFDE_TxtEdtPage* CFDE_TxtEdtEngine::GetPage(int32_t nIndex) {
- if (!pdfium::IndexInBounds(m_PagePtrArray, nIndex))
- return nullptr;
- return m_PagePtrArray[nIndex].get();
-}
-
-void CFDE_TxtEdtEngine::SetText(const CFX_WideString& wsText) {
- ResetEngine();
- int32_t nLength = wsText.GetLength();
- if (nLength > 0) {
- CFX_WideString wsTemp;
- wchar_t* lpBuffer = wsTemp.GetBuffer(nLength);
- memcpy(lpBuffer, wsText.c_str(), nLength * sizeof(wchar_t));
- ReplaceParagEnd(lpBuffer, nLength, false);
- wsTemp.ReleaseBuffer(nLength);
- if (m_nLimit > 0 && nLength > m_nLimit) {
- wsTemp.Delete(m_nLimit, nLength - m_nLimit);
- nLength = m_nLimit;
- }
- m_pTxtBuf->SetText(wsTemp);
- }
- m_pTxtBuf->Insert(nLength, L"\n");
- RebuildParagraphs();
-}
-
-CFX_WideString CFDE_TxtEdtEngine::GetText(int32_t nStart,
- int32_t nCount) const {
- int32_t nTextBufLength = GetTextLength();
- if (nCount == -1)
- nCount = nTextBufLength - nStart;
-
- CFX_WideString wsText = m_pTxtBuf->GetRange(nStart, nCount);
- RecoverParagEnd(wsText);
- return wsText;
-}
-
-void CFDE_TxtEdtEngine::ClearText() {
- if (IsLocked())
- return;
-
- int32_t len = GetTextLength();
- if (len == 0)
- return;
- if (m_Param.dwMode & FDE_TEXTEDITMODE_Validate) {
- // This doesn't really make sense, if the cleared text isn't valid we
- // don't clear it? But what if you want to clear and start again? Should
- // this validation check be removed?
- CFX_WideString wsText = GetText(0, GetTextLength());
- wsText.Delete(0, len);
- if (!m_Param.pEventSink->OnValidate(wsText))
- return;
- }
-
- CFX_WideString prev = GetText(0, -1);
-
- DeleteRange_DoRecord(0, len, false);
- m_Param.pEventSink->OnTextChanged(prev);
- SetCaretPos(0, true);
-}
-
-int32_t CFDE_TxtEdtEngine::SetCaretPos(int32_t nIndex, bool bBefore) {
- if (IsLocked())
- return 0;
-
- ASSERT(nIndex >= 0 && nIndex <= GetTextLength());
- if (!pdfium::IndexInBounds(m_PagePtrArray, m_nCaretPage))
- return 0;
-
- m_bBefore = bBefore;
- m_nCaret = nIndex;
- MovePage2Char(m_nCaret);
- GetCaretRect(m_rtCaret, m_nCaretPage, m_nCaret, m_bBefore);
- if (!m_bBefore) {
- m_nCaret++;
- m_bBefore = true;
- }
- m_fCaretPosReserve = m_rtCaret.left;
- m_Param.pEventSink->OnCaretChanged();
- m_nAnchorPos = -1;
- return m_nCaret;
-}
-
-int32_t CFDE_TxtEdtEngine::MoveCaretPos(FDE_CaretMove eMoveCaret, bool bShift) {
- if (IsLocked() || !pdfium::IndexInBounds(m_PagePtrArray, m_nCaretPage))
- return 0;
-
- bool bSelChange = false;
- if (IsSelect()) {
- ClearSelection();
- bSelChange = true;
- }
- if (bShift) {
- if (m_nAnchorPos == -1)
- m_nAnchorPos = m_nCaret;
- } else {
- m_nAnchorPos = -1;
- }
-
- switch (eMoveCaret) {
- case FDE_CaretMove::Left: {
- bool bBefore = true;
- int32_t nIndex = MoveBackward(bBefore);
- if (nIndex >= 0)
- UpdateCaretRect(nIndex, bBefore);
- break;
- }
- case FDE_CaretMove::Right: {
- bool bBefore = true;
- int32_t nIndex = MoveForward(bBefore);
- if (nIndex >= 0)
- UpdateCaretRect(nIndex, bBefore);
- break;
- }
- case FDE_CaretMove::Up: {
- CFX_PointF ptCaret;
- if (MoveUp(ptCaret))
- UpdateCaretIndex(ptCaret);
- break;
- }
- case FDE_CaretMove::Down: {
- CFX_PointF ptCaret;
- if (MoveDown(ptCaret))
- UpdateCaretIndex(ptCaret);
- break;
- }
- case FDE_CaretMove::LineStart:
- MoveLineStart();
- break;
- case FDE_CaretMove::LineEnd:
- MoveLineEnd();
- break;
- case FDE_CaretMove::Home:
- MoveHome();
- break;
- case FDE_CaretMove::End:
- MoveEnd();
- break;
- }
- if (bShift && m_nAnchorPos != -1 && (m_nAnchorPos != m_nCaret)) {
- AddSelRange(std::min(m_nAnchorPos, m_nCaret), abs(m_nAnchorPos - m_nCaret));
- m_Param.pEventSink->OnSelChanged();
- }
- if (bSelChange)
- m_Param.pEventSink->OnSelChanged();
-
- return m_nCaret;
-}
-
-FDE_EditResult CFDE_TxtEdtEngine::Insert(const CFX_WideString& str) {
- if (IsLocked())
- return FDE_EditResult::kLocked;
-
- int32_t nLength = str.GetLength();
- CFX_WideString wsTemp;
- wchar_t* lpBuffer = wsTemp.GetBuffer(nLength);
- memcpy(lpBuffer, str.c_str(), nLength * sizeof(wchar_t));
- ReplaceParagEnd(lpBuffer, nLength, false);
- wsTemp.ReleaseBuffer(nLength);
-
- if (m_nLimit > 0) {
- int32_t nTotalLength = GetTextLength();
- for (const auto& lpSelRange : m_SelRangePtrArr)
- nTotalLength -= lpSelRange->nCount;
-
- int32_t nExpectLength = nTotalLength + nLength;
- if (nTotalLength == m_nLimit)
- return FDE_EditResult::kFull;
-
- if (nExpectLength > m_nLimit)
- nLength -= (nExpectLength - m_nLimit);
- }
- if ((m_Param.dwMode & FDE_TEXTEDITMODE_LimitArea_Vert) ||
- (m_Param.dwMode & FDE_TEXTEDITMODE_LimitArea_Horz)) {
- if (m_Param.dwMode & FDE_TEXTEDITMODE_Password) {
- while (nLength > 0) {
- CFX_WideString wsText = InsertIntoTextCopy(m_nCaret, lpBuffer, nLength);
- int32_t nTotal = wsText.GetLength();
- wchar_t* lpBuf = wsText.GetBuffer(nTotal);
- for (int32_t i = 0; i < nTotal; i++) {
- lpBuf[i] = m_wcAliasChar;
- }
- wsText.ReleaseBuffer(nTotal);
- if (IsFitArea(wsText)) {
- break;
- }
- nLength--;
- }
- } else {
- while (nLength > 0) {
- CFX_WideString wsText = InsertIntoTextCopy(m_nCaret, lpBuffer, nLength);
- if (IsFitArea(wsText))
- break;
-
- nLength--;
- }
- }
- if (nLength == 0)
- return FDE_EditResult::kFull;
- }
- if (m_Param.dwMode & FDE_TEXTEDITMODE_Validate) {
- CFX_WideString wsText = InsertIntoTextCopy(m_nCaret, lpBuffer, nLength);
- if (!m_Param.pEventSink->OnValidate(wsText))
- return FDE_EditResult::kInvalidate;
- }
- if (IsSelect()) {
- DeleteSelect();
- }
- m_Param.pEventSink->OnAddDoRecord(pdfium::MakeUnique<InsertOperation>(
- this, m_nCaret, CFX_WideString(lpBuffer, nLength)));
-
- CFX_WideString prev = GetText(0, -1);
- Inner_Insert(m_nCaret, CFX_WideString(lpBuffer, nLength));
-
- int32_t nStart = m_nCaret;
- nStart += nLength;
- wchar_t wChar = m_pTxtBuf->GetCharByIndex(nStart - 1);
- bool bBefore = true;
- if (wChar != L'\n' && wChar != L'\r') {
- nStart--;
- bBefore = false;
- }
- SetCaretPos(nStart, bBefore);
- m_Param.pEventSink->OnTextChanged(prev);
- return FDE_EditResult::kSuccess;
-}
-
-void CFDE_TxtEdtEngine::Delete(bool bBackspace) {
- if (IsLocked())
- return;
- if (IsSelect()) {
- DeleteSelect();
- return;
- }
-
- int32_t nCount = 1;
- int32_t nStart = m_nCaret;
- if (bBackspace) {
- if (nStart == 0)
- return;
-
- if (nStart > 2 && m_pTxtBuf->GetCharByIndex(nStart - 1) == L'\n' &&
- m_pTxtBuf->GetCharByIndex(nStart - 2) == L'\r') {
- nStart--;
- nCount++;
- }
- nStart--;
- } else {
- if (nStart == GetTextLength())
- return;
-
- if ((nStart + 1 < GetTextLength()) &&
- (m_pTxtBuf->GetCharByIndex(nStart) == L'\r') &&
- (m_pTxtBuf->GetCharByIndex(nStart + 1) == L'\n')) {
- nCount++;
- }
- }
- if (m_Param.dwMode & FDE_TEXTEDITMODE_Validate) {
- // This doesn't really make sense, if the text with the character removed
- // isn't valid we disallow the removal? Is that even possible as the string
- // must have been valid in order to type the character in before hand?
- // Should this check be removed?
- CFX_WideString wsText = GetText(0, GetTextLength());
- wsText.Delete(nStart, nCount);
- if (!m_Param.pEventSink->OnValidate(wsText))
- return;
- }
-
- CFX_WideString wsRange = m_pTxtBuf->GetRange(nStart, nCount);
- m_Param.pEventSink->OnAddDoRecord(pdfium::MakeUnique<DeleteOperation>(
- this, nStart, m_nCaret, wsRange, false));
-
- CFX_WideString prev = GetText(0, -1);
- Inner_DeleteRange(nStart, nCount);
- SetCaretPos(nStart + ((!bBackspace && nStart > 0) ? -1 : 0),
- (bBackspace || nStart == 0));
- m_Param.pEventSink->OnTextChanged(prev);
-}
-
-void CFDE_TxtEdtEngine::RemoveSelRange(int32_t nStart, int32_t nCount) {
- int32_t nRangeCount = pdfium::CollectionSize<int32_t>(m_SelRangePtrArr);
- for (int32_t i = 0; i < nRangeCount; i++) {
- FDE_TXTEDTSELRANGE* lpTemp = m_SelRangePtrArr[i].get();
- if (lpTemp->nStart == nStart && lpTemp->nCount == nCount) {
- m_SelRangePtrArr.erase(m_SelRangePtrArr.begin() + i);
- return;
- }
- }
-}
-
-void CFDE_TxtEdtEngine::AddSelRange(int32_t nStart, int32_t nCount) {
- if (nCount == -1)
- nCount = GetTextLength() - nStart;
-
- if (m_SelRangePtrArr.empty()) {
- auto lpSelRange = pdfium::MakeUnique<FDE_TXTEDTSELRANGE>();
- lpSelRange->nStart = nStart;
- lpSelRange->nCount = nCount;
- m_SelRangePtrArr.push_back(std::move(lpSelRange));
- m_Param.pEventSink->OnSelChanged();
- return;
- }
- auto* lpTemp = m_SelRangePtrArr.back().get();
- if (nStart >= lpTemp->nStart + lpTemp->nCount) {
- auto lpSelRange = pdfium::MakeUnique<FDE_TXTEDTSELRANGE>();
- lpSelRange->nStart = nStart;
- lpSelRange->nCount = nCount;
- m_SelRangePtrArr.push_back(std::move(lpSelRange));
- m_Param.pEventSink->OnSelChanged();
- return;
- }
- int32_t nEnd = nStart + nCount - 1;
- bool bBegin = false;
- int32_t nRangeBgn = 0;
- int32_t nRangeCnt = 0;
- for (int32_t i = 0, nSize = pdfium::CollectionSize<int32_t>(m_SelRangePtrArr);
- i < nSize; i++) {
- lpTemp = m_SelRangePtrArr[i].get();
- int32_t nTempBgn = lpTemp->nStart;
- int32_t nTempEnd = nTempBgn + lpTemp->nCount - 1;
- if (bBegin) {
- if (nEnd < nTempBgn) {
- break;
- } else if (nStart >= nTempBgn && nStart <= nTempEnd) {
- nRangeCnt++;
- break;
- }
- nRangeCnt++;
- } else {
- if (nStart <= nTempEnd) {
- nRangeBgn = i;
- if (nEnd < nTempBgn) {
- break;
- }
- nRangeCnt = 1;
- bBegin = true;
- }
- }
- }
- if (nRangeCnt == 0) {
- auto lpSelRange = pdfium::MakeUnique<FDE_TXTEDTSELRANGE>();
- lpSelRange->nStart = nStart;
- lpSelRange->nCount = nCount;
- m_SelRangePtrArr.insert(m_SelRangePtrArr.begin() + nRangeBgn,
- std::move(lpSelRange));
- } else {
- lpTemp = m_SelRangePtrArr[nRangeBgn].get();
- lpTemp->nStart = nStart;
- lpTemp->nCount = nCount;
- nRangeCnt--;
- nRangeBgn++;
- m_SelRangePtrArr.erase(m_SelRangePtrArr.begin() + nRangeBgn,
- m_SelRangePtrArr.begin() + nRangeBgn + nRangeCnt);
- }
- m_Param.pEventSink->OnSelChanged();
-}
-
-int32_t CFDE_TxtEdtEngine::GetSelRange(int32_t nIndex, int32_t* nStart) const {
- if (nStart)
- *nStart = m_SelRangePtrArr[nIndex]->nStart;
- return m_SelRangePtrArr[nIndex]->nCount;
-}
-
-void CFDE_TxtEdtEngine::ClearSelection() {
- if (m_SelRangePtrArr.empty())
- return;
- m_SelRangePtrArr.clear();
- if (m_Param.pEventSink)
- m_Param.pEventSink->OnSelChanged();
-}
-
-bool CFDE_TxtEdtEngine::Redo(const IFDE_TxtEdtDoRecord* pDoRecord) {
- if (IsLocked())
- return false;
- pDoRecord->Redo();
- return true;
-}
-
-bool CFDE_TxtEdtEngine::Undo(const IFDE_TxtEdtDoRecord* pDoRecord) {
- if (IsLocked())
- return false;
- pDoRecord->Undo();
- return true;
-}
-
-void CFDE_TxtEdtEngine::Layout() {
- CFX_AutoRestorer<bool> lock(&m_bLock);
- m_bLock = true;
-
- RemoveAllPages();
- UpdateLineCounts();
- UpdatePages();
-
- m_nCaret = std::min(m_nCaret, GetTextLength());
- m_rtCaret = CFX_RectF(0, 0, 1, m_Param.fFontSize);
-}
-
-int32_t CFDE_TxtEdtEngine::Line2Parag(int32_t nStartParag,
- int32_t nStartLineofParag,
- int32_t nLineIndex,
- int32_t& nStartLine) const {
- int32_t nLineTotal = nStartLineofParag;
- int32_t nCount = pdfium::CollectionSize<int32_t>(m_ParagPtrArray);
- CFDE_TxtEdtParag* pParag = nullptr;
- int32_t i = nStartParag;
- for (; i < nCount; i++) {
- pParag = m_ParagPtrArray[i].get();
- nLineTotal += pParag->GetLineCount();
- if (nLineTotal > nLineIndex) {
- break;
- }
- }
- nStartLine = nLineTotal - pParag->GetLineCount();
- return i;
-}
-
-CFX_WideString CFDE_TxtEdtEngine::InsertIntoTextCopy(int32_t nIndex,
- const wchar_t* lpText,
- int32_t nLength) {
- CFX_WideString wsText = GetText(0, GetTextLength());
- int32_t nSelIndex = 0;
- int32_t nSelLength = 0;
- int32_t nSelCount = CountSelRanges();
- while (nSelCount--) {
- nSelLength = GetSelRange(nSelCount, &nSelIndex);
- wsText.Delete(nSelIndex, nSelLength);
- nIndex = nSelIndex;
- }
- CFX_WideString wsTemp;
- int32_t nOldLength = wsText.GetLength();
- const wchar_t* pOldBuffer = wsText.c_str();
- wchar_t* lpBuffer = wsTemp.GetBuffer(nOldLength + nLength);
- memcpy(lpBuffer, pOldBuffer, (nIndex) * sizeof(wchar_t));
- memcpy(lpBuffer + nIndex, lpText, nLength * sizeof(wchar_t));
- memcpy(lpBuffer + nIndex + nLength, pOldBuffer + nIndex,
- (nOldLength - nIndex) * sizeof(wchar_t));
- wsTemp.ReleaseBuffer(nOldLength + nLength);
- wsText = wsTemp;
- return wsText;
-}
-
-void CFDE_TxtEdtEngine::Inner_Insert(int32_t nStart,
- const CFX_WideString& wsText) {
- const int32_t nLength = wsText.GetLength();
- ASSERT(nLength > 0);
- FDE_TXTEDTPARAGPOS ParagPos;
- TextPos2ParagPos(nStart, ParagPos);
-
- GetPage(m_nCaretPage)->UnloadPage();
-
- int32_t nParagCount = pdfium::CollectionSize<int32_t>(m_ParagPtrArray);
- for (int32_t i = ParagPos.nParagIndex + 1; i < nParagCount; i++)
- m_ParagPtrArray[i]->IncrementStartIndex(nLength);
-
- CFDE_TxtEdtParag* pParag = m_ParagPtrArray[ParagPos.nParagIndex].get();
- int32_t nReserveLineCount = pParag->GetLineCount();
- int32_t nReserveCharStart = pParag->GetStartIndex();
- int32_t nLeavePart = ParagPos.nCharIndex;
- int32_t nCutPart = pParag->GetTextLength() - ParagPos.nCharIndex;
- int32_t nTextStart = 0;
- int32_t nCur = 0;
- bool bFirst = true;
- int32_t nParagIndex = ParagPos.nParagIndex;
- for (const auto& wCurChar : wsText) {
- ++nCur;
- if (wCurChar == L'\n') {
- if (bFirst) {
- pParag->SetTextLength(nLeavePart + (nCur - nTextStart + 1));
- pParag->SetLineCount(-1);
- nReserveCharStart += pParag->GetTextLength();
- bFirst = false;
- } else {
- auto pParag2 = pdfium::MakeUnique<CFDE_TxtEdtParag>(this);
- pParag2->SetLineCount(-1);
- pParag2->SetTextLength(nCur - nTextStart + 1);
- pParag2->SetStartIndex(nReserveCharStart);
- nReserveCharStart += pParag2->GetTextLength();
- m_ParagPtrArray.insert(m_ParagPtrArray.begin() + ++nParagIndex,
- std::move(pParag2));
- }
- nTextStart = nCur + 1;
- }
- }
- if (bFirst) {
- pParag->IncrementTextLength(nLength);
- pParag->SetLineCount(-1);
- bFirst = false;
- } else {
- auto pParag2 = pdfium::MakeUnique<CFDE_TxtEdtParag>(this);
- pParag2->SetLineCount(-1);
- pParag2->SetTextLength(nLength - nTextStart + nCutPart);
- pParag2->SetStartIndex(nReserveCharStart);
- m_ParagPtrArray.insert(m_ParagPtrArray.begin() + ++nParagIndex,
- std::move(pParag2));
- }
- m_pTxtBuf->Insert(nStart, wsText);
- int32_t nTotalLineCount = 0;
- for (int32_t i = ParagPos.nParagIndex; i <= nParagIndex; i++) {
- pParag = m_ParagPtrArray[i].get();
- pParag->CalcLines();
- nTotalLineCount += pParag->GetLineCount();
- }
- m_nLineCount += nTotalLineCount - nReserveLineCount;
-
- GetPage(m_nCaretPage)->LoadPage();
- UpdatePages();
-}
-
-void CFDE_TxtEdtEngine::Inner_DeleteRange(int32_t nStart, int32_t nCount) {
- if (nCount == -1) {
- nCount = m_pTxtBuf->GetTextLength() - nStart;
- }
- int32_t nEnd = nStart + nCount - 1;
- ASSERT(nStart >= 0 && nEnd < m_pTxtBuf->GetTextLength());
-
- GetPage(m_nCaretPage)->UnloadPage();
-
- FDE_TXTEDTPARAGPOS ParagPosBgn, ParagPosEnd;
- TextPos2ParagPos(nStart, ParagPosBgn);
- TextPos2ParagPos(nEnd, ParagPosEnd);
- CFDE_TxtEdtParag* pParag = m_ParagPtrArray[ParagPosEnd.nParagIndex].get();
- bool bLastParag = false;
- if (ParagPosEnd.nCharIndex == pParag->GetTextLength() - 1) {
- if (ParagPosEnd.nParagIndex <
- pdfium::CollectionSize<int32_t>(m_ParagPtrArray) - 1) {
- ParagPosEnd.nParagIndex++;
- } else {
- bLastParag = true;
- }
- }
- int32_t nTotalLineCount = 0;
- int32_t nTotalCharCount = 0;
- int32_t i = 0;
- for (i = ParagPosBgn.nParagIndex; i <= ParagPosEnd.nParagIndex; i++) {
- CFDE_TxtEdtParag* pTextParag = m_ParagPtrArray[i].get();
- pTextParag->CalcLines();
- nTotalLineCount += pTextParag->GetLineCount();
- nTotalCharCount += pTextParag->GetTextLength();
- }
- m_pTxtBuf->Delete(nStart, nCount);
- int32_t nNextParagIndex = (ParagPosBgn.nCharIndex == 0 && bLastParag)
- ? ParagPosBgn.nParagIndex
- : (ParagPosBgn.nParagIndex + 1);
- m_ParagPtrArray.erase(m_ParagPtrArray.begin() + nNextParagIndex,
- m_ParagPtrArray.begin() + ParagPosEnd.nParagIndex + 1);
-
- if (!(bLastParag && ParagPosBgn.nCharIndex == 0)) {
- pParag = m_ParagPtrArray[ParagPosBgn.nParagIndex].get();
- pParag->SetTextLength(nTotalCharCount - nCount);
- pParag->CalcLines();
- nTotalLineCount -= pParag->GetLineCount();
- }
- int32_t nParagCount = pdfium::CollectionSize<int32_t>(m_ParagPtrArray);
- for (i = nNextParagIndex; i < nParagCount; i++)
- m_ParagPtrArray[i]->DecrementStartIndex(nCount);
-
- m_nLineCount -= nTotalLineCount;
- UpdatePages();
- int32_t nPageCount = CountPages();
- if (m_nCaretPage >= nPageCount) {
- m_nCaretPage = nPageCount - 1;
- }
-
- GetPage(m_nCaret)->LoadPage();
-}
-
-void CFDE_TxtEdtEngine::DeleteRange_DoRecord(int32_t nStart,
- int32_t nCount,
- bool bSel) {
- ASSERT(nStart >= 0);
- if (nCount == -1) {
- nCount = GetTextLength() - nStart;
- }
- ASSERT((nStart + nCount) <= m_pTxtBuf->GetTextLength());
-
- CFX_WideString wsRange = m_pTxtBuf->GetRange(nStart, nCount);
- m_Param.pEventSink->OnAddDoRecord(pdfium::MakeUnique<DeleteOperation>(
- this, nStart, m_nCaret, wsRange, bSel));
-
- Inner_DeleteRange(nStart, nCount);
-}
-
-void CFDE_TxtEdtEngine::ResetEngine() {
- RemoveAllPages();
- RemoveAllParags();
- ClearSelection();
- m_nCaret = 0;
- m_pTxtBuf->Clear();
- m_nCaret = 0;
-}
-
-void CFDE_TxtEdtEngine::RebuildParagraphs() {
- RemoveAllParags();
- wchar_t wChar = L' ';
- int32_t nParagStart = 0;
- int32_t nIndex = 0;
- auto pIter = pdfium::MakeUnique<CFDE_TxtEdtBuf::Iterator>(m_pTxtBuf.get(), 0);
- pIter->SetAt(0);
- do {
- wChar = pIter->GetChar();
- nIndex = pIter->GetAt();
- if (wChar == L'\n') {
- auto pParag = pdfium::MakeUnique<CFDE_TxtEdtParag>(this);
- pParag->SetStartIndex(nParagStart);
- pParag->SetTextLength(nIndex - nParagStart + 1);
- pParag->SetLineCount(-1);
- m_ParagPtrArray.push_back(std::move(pParag));
- nParagStart = nIndex + 1;
- }
- } while (pIter->Next());
-}
-
-void CFDE_TxtEdtEngine::UpdateLineCounts() {
- if (m_ParagPtrArray.empty())
- return;
-
- int32_t nLineCount = 0;
- for (auto& pParag : m_ParagPtrArray) {
- pParag->CalcLines();
- nLineCount += pParag->GetLineCount();
- }
- m_nLineCount = nLineCount;
-}
-
-void CFDE_TxtEdtEngine::UpdatePages() {
- if (m_nLineCount == 0)
- return;
-
- int32_t nPageCount = (m_nLineCount - 1) / (m_nPageLineCount) + 1;
- int32_t nSize = pdfium::CollectionSize<int32_t>(m_PagePtrArray);
- if (nSize == nPageCount)
- return;
-
- if (nSize > nPageCount) {
- m_PagePtrArray.erase(m_PagePtrArray.begin() + nPageCount,
- m_PagePtrArray.end());
- return;
- }
- for (int32_t i = nSize; i < nPageCount; i++)
- m_PagePtrArray.push_back(pdfium::MakeUnique<CFDE_TxtEdtPage>(this, i));
-}
-
-void CFDE_TxtEdtEngine::UpdateTxtBreak() {
- uint32_t dwStyle = m_TextBreak.GetLayoutStyles();
- if (m_Param.dwMode & FDE_TEXTEDITMODE_MultiLines)
- dwStyle &= ~FX_LAYOUTSTYLE_SingleLine;
- else
- dwStyle |= FX_LAYOUTSTYLE_SingleLine;
-
- if (m_Param.dwLayoutStyles & FDE_TEXTEDITLAYOUT_CombText)
- dwStyle |= FX_LAYOUTSTYLE_CombText;
- else
- dwStyle &= ~FX_LAYOUTSTYLE_CombText;
-
- m_TextBreak.SetLayoutStyles(dwStyle);
- uint32_t dwAligment = 0;
- if (m_Param.dwAlignment & FDE_TEXTEDITALIGN_Justified)
- dwAligment |= CFX_TxtLineAlignment_Justified;
-
- if (m_Param.dwAlignment & FDE_TEXTEDITALIGN_Center)
- dwAligment |= CFX_TxtLineAlignment_Center;
- else if (m_Param.dwAlignment & FDE_TEXTEDITALIGN_Right)
- dwAligment |= CFX_TxtLineAlignment_Right;
-
- m_TextBreak.SetAlignment(dwAligment);
-
- if (m_Param.dwMode & FDE_TEXTEDITMODE_AutoLineWrap)
- m_TextBreak.SetLineWidth(m_Param.fPlateWidth);
- else
- m_TextBreak.SetLineWidth(kPageWidthMax);
-
- m_nPageLineCount = m_Param.nLineCount;
- if (m_Param.dwLayoutStyles & FDE_TEXTEDITLAYOUT_CombText) {
- float fCombWidth = m_Param.fPlateWidth;
- if (m_nLimit > 0)
- fCombWidth /= m_nLimit;
-
- m_TextBreak.SetCombWidth(fCombWidth);
- }
- m_TextBreak.SetFont(m_Param.pFont);
- m_TextBreak.SetFontSize(m_Param.fFontSize);
- m_TextBreak.SetTabWidth(m_Param.fTabWidth);
- m_TextBreak.SetDefaultChar(0xFEFF);
- m_TextBreak.SetParagraphBreakChar(L'\n');
- m_TextBreak.SetLineBreakTolerance(m_Param.fFontSize * 0.2f);
- m_TextBreak.SetHorizontalScale(100);
- m_TextBreak.SetCharSpace(0);
-}
-
-bool CFDE_TxtEdtEngine::ReplaceParagEnd(wchar_t*& lpText,
- int32_t& nLength,
- bool bPreIsCR) {
- for (int32_t i = 0; i < nLength; i++) {
- wchar_t wc = lpText[i];
- switch (wc) {
- case L'\r': {
- lpText[i] = L'\n';
- bPreIsCR = true;
- } break;
- case L'\n': {
- if (bPreIsCR == true) {
- int32_t nNext = i + 1;
- if (nNext < nLength) {
- memmove(lpText + i, lpText + nNext,
- (nLength - nNext) * sizeof(wchar_t));
- }
- i--;
- nLength--;
- bPreIsCR = false;
- if (m_bAutoLineEnd) {
- m_FirstLineEnding = LineEnding::kCRLF;
- m_bAutoLineEnd = false;
- }
- } else {
- lpText[i] = L'\n';
- if (m_bAutoLineEnd) {
- m_FirstLineEnding = LineEnding::kLF;
- m_bAutoLineEnd = false;
- }
- }
- } break;
- default: {
- if (bPreIsCR && m_bAutoLineEnd) {
- m_FirstLineEnding = LineEnding::kCR;
- m_bAutoLineEnd = false;
- }
- bPreIsCR = false;
- } break;
- }
- }
- return bPreIsCR;
-}
-
-void CFDE_TxtEdtEngine::RecoverParagEnd(CFX_WideString& wsText) const {
- if (m_FirstLineEnding == LineEnding::kCR)
- return;
-
- if (m_FirstLineEnding == LineEnding::kCRLF) {
- std::vector<int32_t> PosArr;
- int32_t nLength = wsText.GetLength();
- wchar_t* lpPos = const_cast<wchar_t*>(wsText.c_str());
- for (int32_t i = 0; i < nLength; i++, lpPos++) {
- if (*lpPos == L'\n') {
- *lpPos = L'\r';
- PosArr.push_back(i);
- }
- }
- const wchar_t* lpSrcBuf = wsText.c_str();
- CFX_WideString wsTemp;
- int32_t nCount = pdfium::CollectionSize<int32_t>(PosArr);
- wchar_t* lpDstBuf = wsTemp.GetBuffer(nLength + nCount);
- int32_t nDstPos = 0;
- int32_t nSrcPos = 0;
- for (int32_t i = 0; i < nCount; i++) {
- int32_t nPos = PosArr[i];
- int32_t nCopyLen = nPos - nSrcPos + 1;
- memcpy(lpDstBuf + nDstPos, lpSrcBuf + nSrcPos,
- nCopyLen * sizeof(wchar_t));
- nDstPos += nCopyLen;
- nSrcPos += nCopyLen;
- lpDstBuf[nDstPos] = L'\n';
- nDstPos++;
- }
- if (nSrcPos < nLength) {
- memcpy(lpDstBuf + nDstPos, lpSrcBuf + nSrcPos,
- (nLength - nSrcPos) * sizeof(wchar_t));
- }
- wsTemp.ReleaseBuffer(nLength + nCount);
- wsText = wsTemp;
- return;
- }
-
- int32_t nLength = wsText.GetLength();
- wchar_t* lpBuf = const_cast<wchar_t*>(wsText.c_str());
- for (int32_t i = 0; i < nLength; i++, lpBuf++) {
- if (*lpBuf == L'\n')
- *lpBuf = L'\r';
- }
-}
-
-int32_t CFDE_TxtEdtEngine::MovePage2Char(int32_t nIndex) {
- ASSERT(nIndex >= 0);
- ASSERT(nIndex <= m_pTxtBuf->GetTextLength());
- if (m_nCaretPage >= 0) {
- CFDE_TxtEdtPage* pPage = m_PagePtrArray[m_nCaretPage].get();
- pPage->LoadPage();
-
- int32_t nPageCharStart = pPage->GetCharStart();
- int32_t nPageCharCount = pPage->GetCharCount();
-
- pPage->UnloadPage();
- if (nIndex >= nPageCharStart && nIndex < nPageCharStart + nPageCharCount)
- return m_nCaretPage;
- }
-
- CFDE_TxtEdtParag* pParag = nullptr;
- int32_t nLineCount = 0;
- int32_t nParagCount = pdfium::CollectionSize<int32_t>(m_ParagPtrArray);
- int32_t i = 0;
- for (i = 0; i < nParagCount; i++) {
- pParag = m_ParagPtrArray[i].get();
- if (pParag->GetStartIndex() <= nIndex &&
- nIndex < (pParag->GetStartIndex() + pParag->GetTextLength())) {
- break;
- }
- nLineCount += pParag->GetLineCount();
- }
- pParag->LoadParag();
- int32_t nLineStart = -1;
- int32_t nLineCharCount = -1;
- for (i = 0; i < pParag->GetLineCount(); i++) {
- pParag->GetLineRange(i, nLineStart, nLineCharCount);
- if (nLineStart <= nIndex && nIndex < (nLineStart + nLineCharCount))
- break;
- }
- ASSERT(i < pParag->GetLineCount());
- nLineCount += (i + 1);
- m_nCaretPage = (nLineCount - 1) / m_nPageLineCount + 1 - 1;
- pParag->UnloadParag();
- return m_nCaretPage;
-}
-
-void CFDE_TxtEdtEngine::TextPos2ParagPos(int32_t nIndex,
- FDE_TXTEDTPARAGPOS& ParagPos) const {
- ASSERT(nIndex >= 0 && nIndex < m_pTxtBuf->GetTextLength());
- int32_t nCount = pdfium::CollectionSize<int32_t>(m_ParagPtrArray);
- int32_t nBgn = 0;
- int32_t nMid = 0;
- int32_t nEnd = nCount - 1;
- while (nEnd > nBgn) {
- nMid = (nBgn + nEnd) / 2;
- CFDE_TxtEdtParag* pParag = m_ParagPtrArray[nMid].get();
- if (nIndex < pParag->GetStartIndex())
- nEnd = nMid - 1;
- else if (nIndex >= (pParag->GetStartIndex() + pParag->GetTextLength()))
- nBgn = nMid + 1;
- else
- break;
- }
- if (nBgn == nEnd)
- nMid = nBgn;
-
- ASSERT(nIndex >= m_ParagPtrArray[nMid]->GetStartIndex() &&
- (nIndex < m_ParagPtrArray[nMid]->GetStartIndex() +
- m_ParagPtrArray[nMid]->GetTextLength()));
- ParagPos.nParagIndex = nMid;
- ParagPos.nCharIndex = nIndex - m_ParagPtrArray[nMid]->GetStartIndex();
-}
-
-int32_t CFDE_TxtEdtEngine::MoveForward(bool& bBefore) {
- if (m_nCaret == m_pTxtBuf->GetTextLength() - 1)
- return -1;
-
- int32_t nCaret = m_nCaret;
- if ((nCaret + 1 < m_pTxtBuf->GetTextLength()) &&
- (m_pTxtBuf->GetCharByIndex(nCaret) == L'\r') &&
- (m_pTxtBuf->GetCharByIndex(nCaret + 1) == L'\n')) {
- nCaret++;
- }
- nCaret++;
- bBefore = true;
- return nCaret;
-}
-
-int32_t CFDE_TxtEdtEngine::MoveBackward(bool& bBefore) {
- if (m_nCaret == 0)
- return false;
-
- int32_t nCaret = m_nCaret;
- if (nCaret > 2 && m_pTxtBuf->GetCharByIndex(nCaret - 1) == L'\n' &&
- m_pTxtBuf->GetCharByIndex(nCaret - 2) == L'\r') {
- nCaret--;
- }
- nCaret--;
- bBefore = true;
- return nCaret;
-}
-
-bool CFDE_TxtEdtEngine::MoveUp(CFX_PointF& ptCaret) {
- CFDE_TxtEdtPage* pPage = GetPage(m_nCaretPage);
- const CFX_RectF& rtContent = pPage->GetContentsBox();
- ptCaret.x = m_fCaretPosReserve;
- ptCaret.y = m_rtCaret.top + m_rtCaret.height / 2 - m_Param.fLineSpace;
- if (ptCaret.y < rtContent.top) {
- if (m_nCaretPage == 0) {
- return false;
- }
- ptCaret.y -= rtContent.top;
- m_nCaretPage--;
- CFDE_TxtEdtPage* pCurPage = GetPage(m_nCaretPage);
- ptCaret.y += pCurPage->GetContentsBox().bottom();
- }
-
- return true;
-}
-
-bool CFDE_TxtEdtEngine::MoveDown(CFX_PointF& ptCaret) {
- CFDE_TxtEdtPage* pPage = GetPage(m_nCaretPage);
- const CFX_RectF& rtContent = pPage->GetContentsBox();
- ptCaret.x = m_fCaretPosReserve;
- ptCaret.y = m_rtCaret.top + m_rtCaret.height / 2 + m_Param.fLineSpace;
- if (ptCaret.y >= rtContent.bottom()) {
- if (m_nCaretPage == CountPages() - 1) {
- return false;
- }
- ptCaret.y -= rtContent.bottom();
- m_nCaretPage++;
- CFDE_TxtEdtPage* pCurPage = GetPage(m_nCaretPage);
- ptCaret.y += pCurPage->GetContentsBox().top;
- }
- return true;
-}
-
-bool CFDE_TxtEdtEngine::MoveLineStart() {
- int32_t nIndex = m_bBefore ? m_nCaret : m_nCaret - 1;
- FDE_TXTEDTPARAGPOS ParagPos;
- TextPos2ParagPos(nIndex, ParagPos);
- CFDE_TxtEdtParag* pParag = m_ParagPtrArray[ParagPos.nParagIndex].get();
- pParag->LoadParag();
- int32_t nLineCount = pParag->GetLineCount();
- int32_t i = 0;
- int32_t nStart = 0;
- int32_t nCount = 0;
- for (; i < nLineCount; i++) {
- pParag->GetLineRange(i, nStart, nCount);
- if (nIndex >= nStart && nIndex < nStart + nCount) {
- break;
- }
- }
- UpdateCaretRect(nStart, true);
- pParag->UnloadParag();
- return true;
-}
-
-bool CFDE_TxtEdtEngine::MoveLineEnd() {
- int32_t nIndex = m_bBefore ? m_nCaret : m_nCaret - 1;
- FDE_TXTEDTPARAGPOS ParagPos;
- TextPos2ParagPos(nIndex, ParagPos);
- CFDE_TxtEdtParag* pParag = m_ParagPtrArray[ParagPos.nParagIndex].get();
- pParag->LoadParag();
- int32_t nLineCount = pParag->GetLineCount();
- int32_t i = 0;
- int32_t nStart = 0;
- int32_t nCount = 0;
- for (; i < nLineCount; i++) {
- pParag->GetLineRange(i, nStart, nCount);
- if (nIndex >= nStart && nIndex < nStart + nCount) {
- break;
- }
- }
- nIndex = nStart + nCount - 1;
- ASSERT(nIndex <= GetTextLength());
- wchar_t wChar = m_pTxtBuf->GetCharByIndex(nIndex);
- bool bBefore = false;
- if (nIndex <= GetTextLength()) {
- if (wChar == L'\r') {
- bBefore = true;
- } else if (wChar == L'\n' && nIndex > nStart) {
- bBefore = true;
- nIndex--;
- wChar = m_pTxtBuf->GetCharByIndex(nIndex);
- if (wChar != L'\r') {
- nIndex++;
- }
- }
- }
- UpdateCaretRect(nIndex, bBefore);
- pParag->UnloadParag();
- return true;
-}
-
-bool CFDE_TxtEdtEngine::MoveHome() {
- UpdateCaretRect(0, true);
- return true;
-}
-
-bool CFDE_TxtEdtEngine::MoveEnd() {
- UpdateCaretRect(GetTextLength(), true);
- return true;
-}
-
-bool CFDE_TxtEdtEngine::IsFitArea(CFX_WideString& wsText) {
- auto pTextOut = pdfium::MakeUnique<CFDE_TextOut>();
- pTextOut->SetLineSpace(m_Param.fLineSpace);
- pTextOut->SetFont(m_Param.pFont);
- pTextOut->SetFontSize(m_Param.fFontSize);
-
- FDE_TextStyle dwStyle;
- if (!(m_Param.dwMode & FDE_TEXTEDITMODE_MultiLines))
- dwStyle.single_line_ = true;
-
- CFX_RectF rcText;
- if (m_Param.dwMode & FDE_TEXTEDITMODE_AutoLineWrap) {
- dwStyle.line_wrap_ = true;
- rcText.width = m_Param.fPlateWidth;
- } else {
- rcText.width = 65535;
- }
- pTextOut->SetStyles(dwStyle);
- wsText += L"\n";
- pTextOut->CalcLogicSize(wsText, rcText);
- wsText.Delete(wsText.GetLength() - 1);
- if ((m_Param.dwMode & FDE_TEXTEDITMODE_LimitArea_Horz) &&
- (rcText.width > m_Param.fPlateWidth)) {
- return false;
- }
- if ((m_Param.dwMode & FDE_TEXTEDITMODE_LimitArea_Vert) &&
- (rcText.height > m_Param.fLineSpace * m_Param.nLineCount)) {
- return false;
- }
- return true;
-}
-
-void CFDE_TxtEdtEngine::UpdateCaretRect(int32_t nIndex, bool bBefore) {
- MovePage2Char(nIndex);
- GetCaretRect(m_rtCaret, m_nCaretPage, nIndex, bBefore);
- m_nCaret = nIndex;
- m_bBefore = bBefore;
- if (!m_bBefore) {
- m_nCaret++;
- m_bBefore = true;
- }
- m_fCaretPosReserve = m_rtCaret.left;
- m_Param.pEventSink->OnCaretChanged();
-}
-
-void CFDE_TxtEdtEngine::GetCaretRect(CFX_RectF& rtCaret,
- int32_t nPageIndex,
- int32_t nCaret,
- bool bBefore) {
- CFDE_TxtEdtPage* pPage = m_PagePtrArray[m_nCaretPage].get();
- pPage->LoadPage();
-
- bool bCombText = !!(m_Param.dwLayoutStyles & FDE_TEXTEDITLAYOUT_CombText);
- int32_t nIndexInpage = nCaret - pPage->GetCharStart();
- if (bBefore && bCombText && nIndexInpage > 0) {
- nIndexInpage--;
- bBefore = false;
- }
- int32_t nBIDILevel = pPage->GetCharRect(nIndexInpage, rtCaret, bCombText);
- if ((!FX_IsOdd(nBIDILevel) && !bBefore) ||
- (FX_IsOdd(nBIDILevel) && bBefore)) {
- rtCaret.Offset(rtCaret.width - 1.0f, 0);
- }
- if (rtCaret.width == 0 && rtCaret.left > 1.0f)
- rtCaret.left -= 1.0f;
-
- rtCaret.width = 1.0f;
-
- GetPage(m_nCaretPage)->UnloadPage();
-}
-
-void CFDE_TxtEdtEngine::UpdateCaretIndex(const CFX_PointF& ptCaret) {
- CFDE_TxtEdtPage* pPage = m_PagePtrArray[m_nCaretPage].get();
- pPage->LoadPage();
-
- m_nCaret = pPage->GetCharIndex(ptCaret, m_bBefore);
- GetCaretRect(m_rtCaret, m_nCaretPage, m_nCaret, m_bBefore);
- if (!m_bBefore) {
- m_nCaret++;
- m_bBefore = true;
- }
- m_Param.pEventSink->OnCaretChanged();
- GetPage(m_nCaretPage)->UnloadPage();
-}
-
-void CFDE_TxtEdtEngine::DeleteSelect() {
- int32_t nCountRange = CountSelRanges();
- if (nCountRange <= 0)
- return;
-
- CFX_WideString prev = GetText(0, -1);
-
- int32_t nSelStart = 0;
- while (nCountRange > 0) {
- int32_t nSelCount = GetSelRange(--nCountRange, &nSelStart);
- m_SelRangePtrArr.erase(m_SelRangePtrArr.begin() + nCountRange);
- DeleteRange_DoRecord(nSelStart, nSelCount, true);
- }
- ClearSelection();
- m_Param.pEventSink->OnTextChanged(prev);
- m_Param.pEventSink->OnSelChanged();
- SetCaretPos(nSelStart, true);
-}
diff --git a/xfa/fde/cfde_txtedtengine.h b/xfa/fde/cfde_txtedtengine.h
deleted file mode 100644
index f2bc62cd42..0000000000
--- a/xfa/fde/cfde_txtedtengine.h
+++ /dev/null
@@ -1,223 +0,0 @@
-// Copyright 2014 PDFium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com
-
-#ifndef XFA_FDE_CFDE_TXTEDTENGINE_H_
-#define XFA_FDE_CFDE_TXTEDTENGINE_H_
-
-#include <memory>
-#include <vector>
-
-#include "core/fxcrt/cfx_retain_ptr.h"
-#include "core/fxcrt/fx_coordinates.h"
-#include "core/fxge/fx_dib.h"
-#include "xfa/fde/cfde_txtedtbuf.h"
-#include "xfa/fde/cfde_txtedtpage.h"
-#include "xfa/fde/cfde_txtedtparag.h"
-#include "xfa/fgas/layout/cfx_txtbreak.h"
-
-class CFGAS_GEFont;
-class CFWL_Edit;
-class IFDE_TxtEdtDoRecord;
-class IFX_CharIter;
-
-#define FDE_TEXTEDITMODE_MultiLines (1L << 0)
-#define FDE_TEXTEDITMODE_AutoLineWrap (1L << 1)
-#define FDE_TEXTEDITMODE_LimitArea_Vert (1L << 3)
-#define FDE_TEXTEDITMODE_LimitArea_Horz (1L << 4)
-#define FDE_TEXTEDITMODE_Validate (1L << 8)
-#define FDE_TEXTEDITMODE_Password (1L << 9)
-
-#define FDE_TEXTEDITALIGN_Left 0
-#define FDE_TEXTEDITALIGN_Center (1L << 0)
-#define FDE_TEXTEDITALIGN_Right (1L << 1)
-#define FDE_TEXTEDITALIGN_Justified (1L << 4)
-
-#define FDE_TEXTEDITLAYOUT_CombText (1L << 4)
-#define FDE_TEXTEDITLAYOUT_LastLineHeight (1L << 8)
-
-enum class FDE_CaretMove {
- Left,
- Right,
- Up,
- Down,
- LineStart,
- LineEnd,
- Home,
- End,
-};
-
-enum class FDE_EditResult {
- kLocked = -5,
- kInvalidate = -4,
- kFull = -2,
- kSuccess = 0,
-};
-
-struct FDE_TXTEDTPARAMS {
- FDE_TXTEDTPARAMS();
- ~FDE_TXTEDTPARAMS();
-
- float fPlateWidth;
- float fPlateHeight;
-
- int32_t nLineCount;
- uint32_t dwLayoutStyles;
- uint32_t dwAlignment;
- uint32_t dwMode;
-
- CFX_RetainPtr<CFGAS_GEFont> pFont;
- float fFontSize;
- FX_ARGB dwFontColor;
-
- float fLineSpace;
- float fTabWidth;
-
- CFWL_Edit* pEventSink;
-};
-
-class CFDE_TxtEdtEngine {
- public:
- CFDE_TxtEdtEngine();
- ~CFDE_TxtEdtEngine();
-
- void SetEditParams(const FDE_TXTEDTPARAMS& params);
- FDE_TXTEDTPARAMS* GetEditParams() { return &m_Param; }
-
- CFDE_TxtEdtPage* GetPage(int32_t nIndex);
-
- void SetText(const CFX_WideString& wsText);
- int32_t GetTextLength() const { return m_pTxtBuf->GetTextLength() - 1; }
- CFX_WideString GetText(int32_t nStart, int32_t nCount) const;
- void ClearText();
-
- CFX_RectF GetCaretRect() const { return m_rtCaret; }
- int32_t GetCaretPos() const {
- return IsLocked() ? 0 : m_nCaret + (m_bBefore ? 0 : 1);
- }
- int32_t SetCaretPos(int32_t nIndex, bool bBefore);
- int32_t MoveCaretPos(FDE_CaretMove eMoveCaret, bool bShift);
-
- FDE_EditResult Insert(const CFX_WideString& str);
- void Delete(bool bBackspace);
-
- void SetLimit(int32_t nLimit) { m_nLimit = nLimit; }
- int32_t GetLimit() const { return m_nLimit; }
- void SetAliasChar(wchar_t wcAlias) { m_wcAliasChar = wcAlias; }
-
- void RemoveSelRange(int32_t nStart, int32_t nCount);
- void AddSelRange(int32_t nStart, int32_t nCount);
- int32_t CountSelRanges() const {
- return pdfium::CollectionSize<int32_t>(m_SelRangePtrArr);
- }
- int32_t GetSelRange(int32_t nIndex, int32_t* nStart) const;
- void ClearSelection();
-
- bool Redo(const IFDE_TxtEdtDoRecord* pRecord);
- bool Undo(const IFDE_TxtEdtDoRecord* pRecord);
-
- void Layout();
-
- CFDE_TxtEdtParag* GetParag(int32_t nParagIndex) const {
- return m_ParagPtrArray[nParagIndex].get();
- }
- CFDE_TxtEdtBuf* GetTextBuf() const { return m_pTxtBuf.get(); }
-
- CFX_TxtBreak* GetTextBreak() { return &m_TextBreak; }
- int32_t GetLineCount() const { return m_nLineCount; }
- int32_t GetPageLineCount() const { return m_nPageLineCount; }
-
- int32_t Line2Parag(int32_t nStartParag,
- int32_t nStartLineofParag,
- int32_t nLineIndex,
- int32_t& nStartLine) const;
- wchar_t GetAliasChar() const { return m_wcAliasChar; }
-
- bool IsSelect() const { return !m_SelRangePtrArr.empty(); }
- void Inner_DeleteRange(int32_t nStart, int32_t nCount);
- void Inner_Insert(int32_t nStart, const CFX_WideString& wsText);
- const FDE_TXTEDTPARAMS* GetParams() const { return &m_Param; }
-
- private:
- struct FDE_TXTEDTSELRANGE {
- int32_t nStart;
- int32_t nCount;
- };
-
- struct FDE_TXTEDTPARAGPOS {
- int32_t nParagIndex;
- int32_t nCharIndex;
- };
-
- enum class LineEnding : uint8_t {
- kAuto,
- kCRLF,
- kCR,
- kLF,
- };
-
- int32_t CountPages() const {
- return m_nLineCount == 0 ? 0 : ((m_nLineCount - 1) / m_nPageLineCount) + 1;
- }
-
- bool IsLocked() const { return m_bLock; }
-
- CFX_WideString InsertIntoTextCopy(int32_t nIndex,
- const wchar_t* lpText,
- int32_t nLength);
-
- void DeleteRange_DoRecord(int32_t nStart, int32_t nCount, bool bSel);
- void ResetEngine();
- void RebuildParagraphs();
- void RemoveAllParags() { m_ParagPtrArray.clear(); }
- void RemoveAllPages() { m_PagePtrArray.clear(); }
- void UpdateLineCounts();
- void UpdatePages();
- void UpdateTxtBreak();
-
- bool ReplaceParagEnd(wchar_t*& lpText, int32_t& nLength, bool bPreIsCR);
- void RecoverParagEnd(CFX_WideString& wsText) const;
- int32_t MovePage2Char(int32_t nIndex);
- void TextPos2ParagPos(int32_t nIndex, FDE_TXTEDTPARAGPOS& ParagPos) const;
- int32_t MoveForward(bool& bBefore);
- int32_t MoveBackward(bool& bBefore);
- bool MoveUp(CFX_PointF& ptCaret);
- bool MoveDown(CFX_PointF& ptCaret);
- bool MoveLineStart();
- bool MoveLineEnd();
- bool MoveHome();
- bool MoveEnd();
- bool IsFitArea(CFX_WideString& wsText);
- void UpdateCaretRect(int32_t nIndex, bool bBefore);
- void GetCaretRect(CFX_RectF& rtCaret,
- int32_t nPageIndex,
- int32_t nCaret,
- bool bBefore);
- void UpdateCaretIndex(const CFX_PointF& ptCaret);
-
- void DeleteSelect();
-
- std::unique_ptr<CFDE_TxtEdtBuf> m_pTxtBuf;
- CFX_TxtBreak m_TextBreak;
- FDE_TXTEDTPARAMS m_Param;
- std::vector<std::unique_ptr<CFDE_TxtEdtPage>> m_PagePtrArray;
- std::vector<std::unique_ptr<CFDE_TxtEdtParag>> m_ParagPtrArray;
- std::vector<std::unique_ptr<FDE_TXTEDTSELRANGE>> m_SelRangePtrArr;
- int32_t m_nPageLineCount;
- int32_t m_nLineCount;
- int32_t m_nAnchorPos;
- float m_fCaretPosReserve;
- int32_t m_nCaret;
- int32_t m_nCaretPage;
- CFX_RectF m_rtCaret;
- int32_t m_nLimit;
- wchar_t m_wcAliasChar;
- LineEnding m_FirstLineEnding;
- bool m_bBefore;
- bool m_bLock;
- bool m_bAutoLineEnd;
-};
-
-#endif // XFA_FDE_CFDE_TXTEDTENGINE_H_
diff --git a/xfa/fde/cfde_txtedtpage.cpp b/xfa/fde/cfde_txtedtpage.cpp
deleted file mode 100644
index 3020882c7e..0000000000
--- a/xfa/fde/cfde_txtedtpage.cpp
+++ /dev/null
@@ -1,398 +0,0 @@
-// Copyright 2014 PDFium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com
-
-#include "xfa/fde/cfde_txtedtpage.h"
-
-#include <algorithm>
-
-#include "core/fxcrt/cfx_wordbreak.h"
-#include "third_party/base/ptr_util.h"
-#include "third_party/base/stl_util.h"
-#include "xfa/fde/cfde_txtedtbuf.h"
-#include "xfa/fde/cfde_txtedtengine.h"
-#include "xfa/fde/cfde_txtedtparag.h"
-#include "xfa/fde/cfde_txtedttextset.h"
-#include "xfa/fgas/layout/cfx_txtbreak.h"
-
-namespace {
-
-const double kTolerance = 0.1f;
-
-} // namespace
-
-CFDE_TxtEdtPage::CFDE_TxtEdtPage(CFDE_TxtEdtEngine* pEngine, int32_t nPageIndex)
- : m_pEditEngine(pEngine),
- m_pBgnParag(nullptr),
- m_pEndParag(nullptr),
- m_nRefCount(0),
- m_nPageStart(-1),
- m_nCharCount(0),
- m_nPageIndex(nPageIndex),
- m_bLoaded(false) {
-}
-
-CFDE_TxtEdtPage::~CFDE_TxtEdtPage() {}
-
-int32_t CFDE_TxtEdtPage::GetCharRect(int32_t nIndex,
- CFX_RectF& rect,
- bool bBBox) const {
- ASSERT(m_nRefCount > 0);
- ASSERT(nIndex >= 0 && nIndex < m_nCharCount);
- if (m_nRefCount < 1)
- return 0;
-
- for (const auto& piece : m_Pieces) {
- if (nIndex >= piece.nStart && nIndex < piece.nStart + piece.nCount) {
- std::vector<CFX_RectF> rectArr = m_pTextSet->GetCharRects(&piece, bBBox);
- rect = rectArr[nIndex - piece.nStart];
- return piece.nBidiLevel;
- }
- }
- ASSERT(0);
- return 0;
-}
-
-int32_t CFDE_TxtEdtPage::GetCharIndex(const CFX_PointF& fPoint, bool& bBefore) {
- CFX_PointF ptF = fPoint;
- NormalizePt2Rect(ptF, m_rtPageContents, kTolerance);
- int32_t nCount = pdfium::CollectionSize<int32_t>(m_Pieces);
- CFX_RectF rtLine;
- int32_t nBgn = 0;
- int32_t nEnd = 0;
- bool bInLine = false;
- int32_t i = 0;
- for (i = 0; i < nCount; i++) {
- const FDE_TEXTEDITPIECE* pPiece = &m_Pieces[i];
- if (!bInLine &&
- (pPiece->rtPiece.top <= ptF.y && pPiece->rtPiece.bottom() > ptF.y)) {
- nBgn = nEnd = i;
- rtLine = pPiece->rtPiece;
- bInLine = true;
- } else if (bInLine) {
- if (pPiece->rtPiece.bottom() <= ptF.y || pPiece->rtPiece.top > ptF.y) {
- nEnd = i - 1;
- break;
- } else {
- rtLine.Union(pPiece->rtPiece);
- }
- }
- }
- NormalizePt2Rect(ptF, rtLine, kTolerance);
- int32_t nCaret = 0;
- FDE_TEXTEDITPIECE* pPiece = nullptr;
- for (i = nBgn; i <= nEnd; i++) {
- pPiece = &m_Pieces[i];
- nCaret = m_nPageStart + pPiece->nStart;
- if (pPiece->rtPiece.Contains(ptF)) {
- std::vector<CFX_RectF> rectArr = m_pTextSet->GetCharRects(pPiece, false);
- int32_t nRtCount = pdfium::CollectionSize<int32_t>(rectArr);
- for (int32_t j = 0; j < nRtCount; j++) {
- if (rectArr[j].Contains(ptF)) {
- nCaret = m_nPageStart + pPiece->nStart + j;
- if (nCaret >= m_pEditEngine->GetTextLength()) {
- bBefore = true;
- return m_pEditEngine->GetTextLength();
- }
- wchar_t wChar = m_pEditEngine->GetTextBuf()->GetCharByIndex(nCaret);
- if (wChar == L'\n' || wChar == L'\r') {
- if (wChar == L'\n') {
- if (m_pEditEngine->GetTextBuf()->GetCharByIndex(nCaret - 1) ==
- L'\r') {
- nCaret--;
- }
- }
- bBefore = true;
- return nCaret;
- }
- if (ptF.x > ((rectArr[j].left + rectArr[j].right()) / 2)) {
- bBefore = FX_IsOdd(pPiece->nBidiLevel);
- } else {
- bBefore = !FX_IsOdd(pPiece->nBidiLevel);
- }
- return nCaret;
- }
- }
- }
- }
- bBefore = true;
- return nCaret;
-}
-
-void CFDE_TxtEdtPage::CalcRangeRectArray(
- int32_t nStart,
- int32_t nCount,
- std::vector<CFX_RectF>* pRectFArr) const {
- int32_t nEnd = nStart + nCount - 1;
- bool bInRange = false;
- for (const auto& piece : m_Pieces) {
- if (!bInRange) {
- if (nStart >= piece.nStart && nStart < piece.nStart + piece.nCount) {
- int32_t nRangeEnd = piece.nCount - 1;
- bool bEnd = false;
- if (nEnd >= piece.nStart && nEnd < piece.nStart + piece.nCount) {
- nRangeEnd = nEnd - piece.nStart;
- bEnd = true;
- }
- std::vector<CFX_RectF> rcArr = m_pTextSet->GetCharRects(&piece, false);
- CFX_RectF rectPiece = rcArr[nStart - piece.nStart];
- rectPiece.Union(rcArr[nRangeEnd]);
- pRectFArr->push_back(rectPiece);
- if (bEnd)
- return;
-
- bInRange = true;
- }
- } else {
- if (nEnd >= piece.nStart && nEnd < piece.nStart + piece.nCount) {
- std::vector<CFX_RectF> rcArr = m_pTextSet->GetCharRects(&piece, false);
- CFX_RectF rectPiece = rcArr[0];
- rectPiece.Union(rcArr[nEnd - piece.nStart]);
- pRectFArr->push_back(rectPiece);
- return;
- }
- pRectFArr->push_back(piece.rtPiece);
- }
- }
-}
-
-int32_t CFDE_TxtEdtPage::SelectWord(const CFX_PointF& fPoint, int32_t& nCount) {
- if (m_nRefCount < 0) {
- return -1;
- }
- CFDE_TxtEdtBuf* pBuf = m_pEditEngine->GetTextBuf();
- bool bBefore;
- int32_t nIndex = GetCharIndex(fPoint, bBefore);
- if (nIndex == m_pEditEngine->GetTextLength()) {
- nIndex = m_pEditEngine->GetTextLength() - 1;
- }
- if (nIndex < 0) {
- return -1;
- }
- auto pIter = pdfium::MakeUnique<CFX_WordBreak>();
- pIter->Attach(new CFDE_TxtEdtBuf::Iterator(pBuf, 0));
- pIter->SetAt(nIndex);
- nCount = pIter->GetWordLength();
- return pIter->GetWordPos();
-}
-
-int32_t CFDE_TxtEdtPage::LoadPage() {
- if (m_nRefCount > 0) {
- m_nRefCount++;
- return m_nRefCount;
- }
-
- CFDE_TxtEdtBuf* pBuf = m_pEditEngine->GetTextBuf();
- const FDE_TXTEDTPARAMS* pParams = m_pEditEngine->GetEditParams();
- wchar_t wcAlias = 0;
- if (pParams->dwMode & FDE_TEXTEDITMODE_Password)
- wcAlias = m_pEditEngine->GetAliasChar();
-
- m_pIter = pdfium::MakeUnique<CFDE_TxtEdtBuf::Iterator>(
- static_cast<CFDE_TxtEdtBuf*>(pBuf), wcAlias);
- CFX_TxtBreak* pBreak = m_pEditEngine->GetTextBreak();
- pBreak->EndBreak(CFX_BreakType::Paragraph);
- pBreak->ClearBreakPieces();
- int32_t nPageLineCount = m_pEditEngine->GetPageLineCount();
- int32_t nStartLine = nPageLineCount * m_nPageIndex;
- int32_t nEndLine = std::min((nStartLine + nPageLineCount - 1),
- (m_pEditEngine->GetLineCount() - 1));
- int32_t nPageStart, nPageEnd, nTemp, nBgnParag, nStartLineInParag, nEndParag,
- nEndLineInParag;
- nBgnParag = m_pEditEngine->Line2Parag(0, 0, nStartLine, nStartLineInParag);
- m_pBgnParag =
- static_cast<CFDE_TxtEdtParag*>(m_pEditEngine->GetParag(nBgnParag));
- m_pBgnParag->LoadParag();
- m_pBgnParag->GetLineRange(nStartLine - nStartLineInParag, nPageStart, nTemp);
- nEndParag = m_pEditEngine->Line2Parag(nBgnParag, nStartLineInParag, nEndLine,
- nEndLineInParag);
- m_pEndParag =
- static_cast<CFDE_TxtEdtParag*>(m_pEditEngine->GetParag(nEndParag));
- m_pEndParag->LoadParag();
- m_pEndParag->GetLineRange(nEndLine - nEndLineInParag, nPageEnd, nTemp);
- nPageEnd += (nTemp - 1);
-
- float fLineStart = 0.0f;
- float fLineStep = pParams->fLineSpace;
- float fLinePos = fLineStart;
- if (!m_pTextSet)
- m_pTextSet = pdfium::MakeUnique<CFDE_TxtEdtTextSet>(this);
-
- m_Pieces.clear();
- CFX_BreakType dwBreakStatus = CFX_BreakType::None;
- int32_t nPieceStart = 0;
-
- m_CharWidths.resize(nPageEnd - nPageStart + 1, 0);
- pBreak->EndBreak(CFX_BreakType::Paragraph);
- pBreak->ClearBreakPieces();
- m_nPageStart = nPageStart;
- m_nCharCount = nPageEnd - nPageStart + 1;
- bool bReload = false;
- float fDefCharWidth = 0;
- std::unique_ptr<IFX_CharIter> pIter = m_pIter->Clone();
- pIter->SetAt(nPageStart);
- m_pIter->SetAt(nPageStart);
- bool bFirstPiece = true;
- do {
- if (bReload) {
- dwBreakStatus = pBreak->EndBreak(CFX_BreakType::Paragraph);
- } else {
- wchar_t wAppend = pIter->GetChar();
- dwBreakStatus = pBreak->AppendChar(wAppend);
- }
- if (pIter->GetAt() == nPageEnd && CFX_BreakTypeNoneOrPiece(dwBreakStatus))
- dwBreakStatus = pBreak->EndBreak(CFX_BreakType::Paragraph);
-
- if (!CFX_BreakTypeNoneOrPiece(dwBreakStatus)) {
- int32_t nPieceCount = pBreak->CountBreakPieces();
- for (int32_t j = 0; j < nPieceCount; j++) {
- const CFX_BreakPiece* pPiece = pBreak->GetBreakPieceUnstable(j);
- FDE_TEXTEDITPIECE TxtEdtPiece;
- memset(&TxtEdtPiece, 0, sizeof(FDE_TEXTEDITPIECE));
- TxtEdtPiece.nBidiLevel = pPiece->m_iBidiLevel;
- TxtEdtPiece.nCount = pPiece->GetLength();
- TxtEdtPiece.nStart = nPieceStart;
- TxtEdtPiece.dwCharStyles = pPiece->m_dwCharStyles;
- if (FX_IsOdd(pPiece->m_iBidiLevel))
- TxtEdtPiece.dwCharStyles |= FX_TXTCHARSTYLE_OddBidiLevel;
-
- float fParaBreakWidth = 0.0f;
- if (!CFX_BreakTypeNoneOrPiece(pPiece->m_dwStatus)) {
- if (TxtEdtPiece.nCount >= 2) {
- wchar_t wChar = pBuf->GetCharByIndex(
- m_nPageStart + TxtEdtPiece.nStart + TxtEdtPiece.nCount - 1);
- wchar_t wCharPre = pBuf->GetCharByIndex(
- m_nPageStart + TxtEdtPiece.nStart + TxtEdtPiece.nCount - 2);
- if (wChar == L'\n') {
- fParaBreakWidth += fDefCharWidth;
- }
- if (wCharPre == L'\n') {
- fParaBreakWidth += fDefCharWidth;
- }
- } else if (TxtEdtPiece.nCount >= 1) {
- wchar_t wChar = pBuf->GetCharByIndex(
- m_nPageStart + TxtEdtPiece.nStart + TxtEdtPiece.nCount - 1);
- if (wChar == L'\n') {
- fParaBreakWidth += fDefCharWidth;
- }
- }
- }
-
- TxtEdtPiece.rtPiece.left = (float)pPiece->m_iStartPos / 20000.0f;
- TxtEdtPiece.rtPiece.top = fLinePos;
- TxtEdtPiece.rtPiece.width =
- (float)pPiece->m_iWidth / 20000.0f + fParaBreakWidth;
- TxtEdtPiece.rtPiece.height = pParams->fLineSpace;
-
- if (bFirstPiece) {
- m_rtPageContents = TxtEdtPiece.rtPiece;
- bFirstPiece = false;
- } else {
- m_rtPageContents.Union(TxtEdtPiece.rtPiece);
- }
- nPieceStart += TxtEdtPiece.nCount;
- m_Pieces.push_back(TxtEdtPiece);
- for (int32_t k = 0; k < TxtEdtPiece.nCount; k++) {
- m_CharWidths[TxtEdtPiece.nStart + k] =
- pPiece->GetChar(k)->m_iCharWidth;
- }
- }
- fLinePos += fLineStep;
- pBreak->ClearBreakPieces();
- }
- if (pIter->GetAt() == nPageEnd && dwBreakStatus == CFX_BreakType::Line) {
- bReload = true;
- pIter->Next(true);
- }
- } while (pIter->Next(false) && (pIter->GetAt() <= nPageEnd));
- if (m_rtPageContents.left != 0) {
- float fDelta = 0.0f;
- if (m_rtPageContents.width < pParams->fPlateWidth) {
- if (pParams->dwAlignment & FDE_TEXTEDITALIGN_Right) {
- fDelta = pParams->fPlateWidth - m_rtPageContents.width;
- } else if (pParams->dwAlignment & FDE_TEXTEDITALIGN_Center) {
- if ((pParams->dwLayoutStyles & FDE_TEXTEDITLAYOUT_CombText) &&
- m_nCharCount > 1) {
- int32_t nCount = m_nCharCount - 1;
- int32_t n = (m_pEditEngine->GetLimit() - nCount) / 2;
- fDelta = (m_rtPageContents.width / nCount) * n;
- } else {
- fDelta = (pParams->fPlateWidth - m_rtPageContents.width) / 2;
- }
- }
- }
- float fOffset = m_rtPageContents.left - fDelta;
- for (auto& piece : m_Pieces)
- piece.rtPiece.Offset(-fOffset, 0.0f);
-
- m_rtPageContents.Offset(-fOffset, 0.0f);
- }
- if (m_pEditEngine->GetEditParams()->dwLayoutStyles &
- FDE_TEXTEDITLAYOUT_LastLineHeight) {
- m_rtPageContents.height -= pParams->fLineSpace - pParams->fFontSize;
- m_Pieces.back().rtPiece.height = pParams->fFontSize;
- }
- m_nRefCount = 1;
- m_bLoaded = true;
- return 0;
-}
-
-void CFDE_TxtEdtPage::UnloadPage() {
- ASSERT(m_nRefCount > 0);
- m_nRefCount--;
- if (m_nRefCount != 0)
- return;
-
- m_Pieces.clear();
- m_pTextSet.reset();
- m_CharWidths.clear();
- if (m_pBgnParag) {
- m_pBgnParag->UnloadParag();
- m_pBgnParag = nullptr;
- }
- if (m_pEndParag) {
- m_pEndParag->UnloadParag();
- m_pEndParag = nullptr;
- }
- m_pIter.reset();
-}
-
-const FDE_TEXTEDITPIECE& CFDE_TxtEdtPage::GetTextPiece(size_t pos) const {
- ASSERT(pos < m_Pieces.size());
- return m_Pieces[pos];
-}
-
-wchar_t CFDE_TxtEdtPage::GetChar(const FDE_TEXTEDITPIECE* pIdentity,
- int32_t index) const {
- int32_t nIndex = m_nPageStart + pIdentity->nStart + index;
- if (nIndex != m_pIter->GetAt())
- m_pIter->SetAt(nIndex);
-
- wchar_t wChar = m_pIter->GetChar();
- m_pIter->Next();
- return wChar;
-}
-
-int32_t CFDE_TxtEdtPage::GetWidth(const FDE_TEXTEDITPIECE* pIdentity,
- int32_t index) const {
- int32_t nWidth = m_CharWidths[pIdentity->nStart + index];
- return nWidth;
-}
-
-void CFDE_TxtEdtPage::NormalizePt2Rect(CFX_PointF& ptF,
- const CFX_RectF& rtF,
- float fTolerance) const {
- if (rtF.Contains(ptF))
- return;
- if (ptF.x < rtF.left)
- ptF.x = rtF.left;
- else if (ptF.x >= rtF.right())
- ptF.x = rtF.right() - fTolerance;
-
- if (ptF.y < rtF.top)
- ptF.y = rtF.top;
- else if (ptF.y >= rtF.bottom())
- ptF.y = rtF.bottom() - fTolerance;
-}
diff --git a/xfa/fde/cfde_txtedtpage.h b/xfa/fde/cfde_txtedtpage.h
deleted file mode 100644
index cdf6c55080..0000000000
--- a/xfa/fde/cfde_txtedtpage.h
+++ /dev/null
@@ -1,94 +0,0 @@
-// Copyright 2014 PDFium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com
-
-#ifndef XFA_FDE_CFDE_TXTEDTPAGE_H_
-#define XFA_FDE_CFDE_TXTEDTPAGE_H_
-
-#include <deque>
-#include <memory>
-#include <vector>
-
-#include "core/fxcrt/fx_coordinates.h"
-#include "core/fxcrt/ifx_chariter.h"
-#include "core/fxge/cfx_renderdevice.h"
-
-class CFDE_TxtEdtEngine;
-class CFDE_TxtEdtParag;
-class CFDE_TxtEdtTextSet;
-
-struct FDE_TEXTEDITPIECE {
- FDE_TEXTEDITPIECE();
- FDE_TEXTEDITPIECE(const FDE_TEXTEDITPIECE& that);
- ~FDE_TEXTEDITPIECE();
-
- int32_t nStart;
- int32_t nCount;
- int32_t nBidiLevel;
- CFX_RectF rtPiece;
- uint32_t dwCharStyles;
-};
-
-inline FDE_TEXTEDITPIECE::FDE_TEXTEDITPIECE() = default;
-inline FDE_TEXTEDITPIECE::FDE_TEXTEDITPIECE(const FDE_TEXTEDITPIECE& that) =
- default;
-inline FDE_TEXTEDITPIECE::~FDE_TEXTEDITPIECE() = default;
-
-class CFDE_TxtEdtPage {
- public:
- CFDE_TxtEdtPage(CFDE_TxtEdtEngine* pEngine, int32_t nLineIndex);
- ~CFDE_TxtEdtPage();
-
- CFDE_TxtEdtEngine* GetEngine() const { return m_pEditEngine.Get(); }
-
- int32_t GetCharRect(int32_t nIndex, CFX_RectF& rect, bool bBBox) const;
- int32_t GetCharIndex(const CFX_PointF& fPoint, bool& bBefore);
-
- void CalcRangeRectArray(int32_t nStart,
- int32_t nCount,
- std::vector<CFX_RectF>* RectFArr) const;
-
- int32_t SelectWord(const CFX_PointF& fPoint, int32_t& nCount);
-
- int32_t GetCharStart() const { return m_nPageStart; }
- int32_t GetCharCount() const { return m_nCharCount; }
-
- int32_t LoadPage();
- void UnloadPage();
-
- const CFX_RectF& GetContentsBox() { return m_rtPageContents; }
-
- size_t GetTextPieceCount() const { return m_pTextSet ? m_Pieces.size() : 0; }
- const FDE_TEXTEDITPIECE& GetTextPiece(size_t pos) const;
-
- wchar_t GetChar(const FDE_TEXTEDITPIECE* pIdentity, int32_t index) const;
- int32_t GetWidth(const FDE_TEXTEDITPIECE* pIdentity, int32_t index) const;
-
- CFDE_TxtEdtTextSet* GetTextSet() const { return m_pTextSet.get(); }
-
- private:
- void NormalizePt2Rect(CFX_PointF& ptF,
- const CFX_RectF& rtF,
- float fTolerance) const;
-
- std::unique_ptr<IFX_CharIter> m_pIter;
- std::unique_ptr<CFDE_TxtEdtTextSet> m_pTextSet;
- CFX_UnownedPtr<CFDE_TxtEdtEngine> const m_pEditEngine;
- std::deque<FDE_TEXTEDITPIECE> m_Pieces;
- CFDE_TxtEdtParag* m_pBgnParag;
- CFDE_TxtEdtParag* m_pEndParag;
- int32_t m_nRefCount;
- int32_t m_nPageStart;
- int32_t m_nCharCount;
- int32_t m_nPageIndex;
- bool m_bLoaded;
- CFX_RectF m_rtPage;
- CFX_RectF m_rtPageMargin;
- CFX_RectF m_rtPageContents;
- CFX_RectF m_rtPageCanvas;
- std::vector<int32_t> m_CharWidths;
-};
-
-#endif // XFA_FDE_CFDE_TXTEDTPAGE_H_
diff --git a/xfa/fde/cfde_txtedtparag.cpp b/xfa/fde/cfde_txtedtparag.cpp
deleted file mode 100644
index 3c1c2adbda..0000000000
--- a/xfa/fde/cfde_txtedtparag.cpp
+++ /dev/null
@@ -1,153 +0,0 @@
-// Copyright 2014 PDFium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com
-
-#include "xfa/fde/cfde_txtedtparag.h"
-
-#include <memory>
-#include <vector>
-
-#include "core/fxcrt/ifx_chariter.h"
-#include "third_party/base/ptr_util.h"
-#include "third_party/base/stl_util.h"
-#include "xfa/fde/cfde_txtedtbuf.h"
-#include "xfa/fde/cfde_txtedtengine.h"
-#include "xfa/fgas/layout/cfx_txtbreak.h"
-
-CFDE_TxtEdtParag::CFDE_TxtEdtParag(CFDE_TxtEdtEngine* pEngine)
- : m_nCharStart(0),
- m_nCharCount(0),
- m_nLineCount(0),
- m_lpData(nullptr),
- m_pEngine(pEngine) {
- ASSERT(m_pEngine);
-}
-
-CFDE_TxtEdtParag::~CFDE_TxtEdtParag() {
- if (m_lpData)
- FX_Free(m_lpData);
-}
-
-void CFDE_TxtEdtParag::LoadParag() {
- if (m_lpData) {
- m_lpData[0]++;
- return;
- }
- CFX_TxtBreak* pTxtBreak = m_pEngine->GetTextBreak();
- CFDE_TxtEdtBuf* pTxtBuf = m_pEngine->GetTextBuf();
- const FDE_TXTEDTPARAMS* pParam = m_pEngine->GetEditParams();
- wchar_t wcAlias = 0;
- if (pParam->dwMode & FDE_TEXTEDITMODE_Password)
- wcAlias = m_pEngine->GetAliasChar();
-
- auto pIter = pdfium::MakeUnique<CFDE_TxtEdtBuf::Iterator>(
- static_cast<CFDE_TxtEdtBuf*>(pTxtBuf), wcAlias);
- pIter->SetAt(m_nCharStart);
- int32_t nEndIndex = m_nCharStart + m_nCharCount;
- std::vector<int32_t> LineBaseArr;
- bool bReload = false;
- CFX_BreakType dwBreakStatus = CFX_BreakType::None;
- do {
- if (bReload) {
- dwBreakStatus = pTxtBreak->EndBreak(CFX_BreakType::Paragraph);
- } else {
- wchar_t wAppend = pIter->GetChar();
- dwBreakStatus = pTxtBreak->AppendChar(wAppend);
- }
- if (pIter->GetAt() + 1 == nEndIndex &&
- CFX_BreakTypeNoneOrPiece(dwBreakStatus)) {
- dwBreakStatus = pTxtBreak->EndBreak(CFX_BreakType::Paragraph);
- }
- if (!CFX_BreakTypeNoneOrPiece(dwBreakStatus)) {
- int32_t nCount = pTxtBreak->CountBreakPieces();
- int32_t nTotal = 0;
- for (int32_t j = 0; j < nCount; j++) {
- const CFX_BreakPiece* Piece = pTxtBreak->GetBreakPieceUnstable(j);
- nTotal += Piece->GetLength();
- }
- LineBaseArr.push_back(nTotal);
- pTxtBreak->ClearBreakPieces();
- }
- if (pIter->GetAt() + 1 == nEndIndex &&
- dwBreakStatus == CFX_BreakType::Line) {
- bReload = true;
- pIter->Next(true);
- }
- } while (pIter->Next(false) && (pIter->GetAt() < nEndIndex));
- pTxtBreak->EndBreak(CFX_BreakType::Paragraph);
- pTxtBreak->ClearBreakPieces();
- int32_t nLineCount = pdfium::CollectionSize<int32_t>(LineBaseArr);
- m_nLineCount = nLineCount;
- if (m_lpData)
- m_lpData = FX_Realloc(int32_t, m_lpData, nLineCount + 1);
- else
- m_lpData = FX_Alloc(int32_t, nLineCount + 1);
-
- int32_t* pIntArr = m_lpData;
- pIntArr[0] = 1;
- m_nLineCount = nLineCount;
- pIntArr++;
- for (int32_t j = 0; j < nLineCount; j++, pIntArr++)
- *pIntArr = LineBaseArr[j];
-}
-
-void CFDE_TxtEdtParag::UnloadParag() {
- m_lpData[0]--;
- ASSERT(m_lpData[0] >= 0);
- if (m_lpData[0] == 0) {
- FX_Free(m_lpData);
- m_lpData = nullptr;
- }
-}
-
-void CFDE_TxtEdtParag::CalcLines() {
- CFX_TxtBreak* pTxtBreak = m_pEngine->GetTextBreak();
- CFDE_TxtEdtBuf* pTxtBuf = m_pEngine->GetTextBuf();
- int32_t nCount = 0;
- CFX_BreakType dwBreakStatus = CFX_BreakType::None;
- int32_t nEndIndex = m_nCharStart + m_nCharCount;
- auto pIter = pdfium::MakeUnique<CFDE_TxtEdtBuf::Iterator>(
- static_cast<CFDE_TxtEdtBuf*>(pTxtBuf), 0);
- pIter->SetAt(m_nCharStart);
- bool bReload = false;
- do {
- if (bReload) {
- dwBreakStatus = pTxtBreak->EndBreak(CFX_BreakType::Paragraph);
- } else {
- wchar_t wAppend = pIter->GetChar();
- dwBreakStatus = pTxtBreak->AppendChar(wAppend);
- }
- if (pIter->GetAt() + 1 == nEndIndex &&
- CFX_BreakTypeNoneOrPiece(dwBreakStatus)) {
- dwBreakStatus = pTxtBreak->EndBreak(CFX_BreakType::Paragraph);
- }
- if (!CFX_BreakTypeNoneOrPiece(dwBreakStatus)) {
- nCount++;
- pTxtBreak->ClearBreakPieces();
- }
- if (pIter->GetAt() + 1 == nEndIndex &&
- dwBreakStatus == CFX_BreakType::Line) {
- bReload = true;
- pIter->Next(true);
- }
- } while (pIter->Next(false) && (pIter->GetAt() < nEndIndex));
- pTxtBreak->EndBreak(CFX_BreakType::Paragraph);
- pTxtBreak->ClearBreakPieces();
- m_nLineCount = nCount;
-}
-
-void CFDE_TxtEdtParag::GetLineRange(int32_t nLineIndex,
- int32_t& nStart,
- int32_t& nCount) const {
- int32_t* pLineBaseArr = m_lpData;
- ASSERT(nLineIndex < m_nLineCount);
- nStart = m_nCharStart;
- pLineBaseArr++;
- for (int32_t i = 0; i < nLineIndex; i++) {
- nStart += *pLineBaseArr;
- pLineBaseArr++;
- }
- nCount = *pLineBaseArr;
-}
diff --git a/xfa/fde/cfde_txtedtparag.h b/xfa/fde/cfde_txtedtparag.h
deleted file mode 100644
index becfb61070..0000000000
--- a/xfa/fde/cfde_txtedtparag.h
+++ /dev/null
@@ -1,45 +0,0 @@
-// Copyright 2014 PDFium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com
-
-#ifndef XFA_FDE_CFDE_TXTEDTPARAG_H_
-#define XFA_FDE_CFDE_TXTEDTPARAG_H_
-
-#include <stdint.h>
-
-#include "core/fxcrt/cfx_unowned_ptr.h"
-
-class CFDE_TxtEdtEngine;
-
-class CFDE_TxtEdtParag {
- public:
- explicit CFDE_TxtEdtParag(CFDE_TxtEdtEngine* pEngine);
- ~CFDE_TxtEdtParag();
-
- int32_t GetTextLength() const { return m_nCharCount; }
- int32_t GetStartIndex() const { return m_nCharStart; }
- int32_t GetLineCount() const { return m_nLineCount; }
-
- void SetTextLength(int32_t len) { m_nCharCount = len; }
- void IncrementTextLength(int32_t len) { m_nCharCount += len; }
- void SetStartIndex(int32_t idx) { m_nCharStart = idx; }
- void IncrementStartIndex(int32_t val) { m_nCharStart += val; }
- void DecrementStartIndex(int32_t val) { m_nCharStart -= val; }
- void SetLineCount(int32_t count) { m_nLineCount = count; }
-
- void GetLineRange(int32_t nLineIndex, int32_t& nStart, int32_t& nCount) const;
- void LoadParag();
- void UnloadParag();
- void CalcLines();
-
- private:
- int32_t m_nCharStart;
- int32_t m_nCharCount;
- int32_t m_nLineCount;
- int32_t* m_lpData;
- CFX_UnownedPtr<CFDE_TxtEdtEngine> m_pEngine;
-};
-
-#endif // XFA_FDE_CFDE_TXTEDTPARAG_H_
diff --git a/xfa/fde/cfde_txtedttextset.cpp b/xfa/fde/cfde_txtedttextset.cpp
deleted file mode 100644
index 0b6cf8214e..0000000000
--- a/xfa/fde/cfde_txtedttextset.cpp
+++ /dev/null
@@ -1,60 +0,0 @@
-// Copyright 2016 PDFium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com
-
-#include "xfa/fde/cfde_txtedttextset.h"
-
-#include "xfa/fde/cfde_txtedtengine.h"
-#include "xfa/fgas/font/cfgas_gefont.h"
-#include "xfa/fgas/layout/cfx_txtbreak.h"
-
-CFDE_TxtEdtTextSet::CFDE_TxtEdtTextSet(CFDE_TxtEdtPage* pPage)
- : m_pPage(pPage) {}
-
-CFDE_TxtEdtTextSet::~CFDE_TxtEdtTextSet() {}
-
-int32_t CFDE_TxtEdtTextSet::GetDisplayPos(const FDE_TEXTEDITPIECE& piece,
- FXTEXT_CHARPOS* pCharPos) const {
- int32_t nLength = piece.nCount;
- if (nLength < 1)
- return 0;
-
- CFDE_TxtEdtEngine* pEngine =
- static_cast<CFDE_TxtEdtEngine*>(m_pPage->GetEngine());
- const FDE_TXTEDTPARAMS* pTextParams = pEngine->GetEditParams();
- CFX_TxtBreak* pBreak = pEngine->GetTextBreak();
- uint32_t dwLayoutStyle = pBreak->GetLayoutStyles();
- FX_TXTRUN tr;
- tr.pAccess = m_pPage.Get();
- tr.pIdentity = &piece;
- tr.iLength = nLength;
- tr.pFont = pTextParams->pFont;
- tr.fFontSize = pTextParams->fFontSize;
- tr.dwStyles = dwLayoutStyle;
- tr.dwCharStyles = piece.dwCharStyles;
- tr.pRect = &piece.rtPiece;
- return pBreak->GetDisplayPos(&tr, pCharPos);
-}
-
-std::vector<CFX_RectF> CFDE_TxtEdtTextSet::GetCharRects(
- const FDE_TEXTEDITPIECE* pPiece,
- bool bBBox) const {
- if (!pPiece || pPiece->nCount < 1)
- return std::vector<CFX_RectF>();
-
- auto* pEngine = static_cast<CFDE_TxtEdtEngine*>(m_pPage->GetEngine());
- const FDE_TXTEDTPARAMS* pTextParams = pEngine->GetEditParams();
- uint32_t dwLayoutStyle = pEngine->GetTextBreak()->GetLayoutStyles();
- FX_TXTRUN tr;
- tr.pAccess = m_pPage.Get();
- tr.pIdentity = pPiece;
- tr.iLength = pPiece->nCount;
- tr.pFont = pTextParams->pFont;
- tr.fFontSize = pTextParams->fFontSize;
- tr.dwStyles = dwLayoutStyle;
- tr.dwCharStyles = pPiece->dwCharStyles;
- tr.pRect = &pPiece->rtPiece;
- return pEngine->GetTextBreak()->GetCharRects(&tr, bBBox);
-}
diff --git a/xfa/fde/cfde_txtedttextset.h b/xfa/fde/cfde_txtedttextset.h
deleted file mode 100644
index 4fbf2ac649..0000000000
--- a/xfa/fde/cfde_txtedttextset.h
+++ /dev/null
@@ -1,33 +0,0 @@
-// Copyright 2016 PDFium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com
-
-#ifndef XFA_FDE_CFDE_TXTEDTTEXTSET_H_
-#define XFA_FDE_CFDE_TXTEDTTEXTSET_H_
-
-#include <vector>
-
-#include "core/fxcrt/fx_coordinates.h"
-#include "xfa/fde/cfde_txtedtpage.h"
-#include "xfa/fgas/font/cfgas_gefont.h"
-
-class CFDE_TxtEdtTextSet {
- public:
- explicit CFDE_TxtEdtTextSet(CFDE_TxtEdtPage* pPage);
- ~CFDE_TxtEdtTextSet();
-
- CFX_RectF GetRect(const FDE_TEXTEDITPIECE& pPiece) const {
- return pPiece.rtPiece;
- }
- int32_t GetDisplayPos(const FDE_TEXTEDITPIECE& pPiece,
- FXTEXT_CHARPOS* pCharPos) const;
- std::vector<CFX_RectF> GetCharRects(const FDE_TEXTEDITPIECE* pPiece,
- bool bBBox) const;
-
- private:
- CFX_UnownedPtr<CFDE_TxtEdtPage> const m_pPage;
-};
-
-#endif // XFA_FDE_CFDE_TXTEDTTEXTSET_H_
diff --git a/xfa/fde/ifde_txtedtdorecord.h b/xfa/fde/ifde_txtedtdorecord.h
deleted file mode 100644
index e464e7937c..0000000000
--- a/xfa/fde/ifde_txtedtdorecord.h
+++ /dev/null
@@ -1,20 +0,0 @@
-// Copyright 2016 PDFium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com
-
-#ifndef XFA_FDE_IFDE_TXTEDTDORECORD_H_
-#define XFA_FDE_IFDE_TXTEDTDORECORD_H_
-
-#include "core/fxcrt/fx_system.h"
-
-class IFDE_TxtEdtDoRecord {
- public:
- virtual ~IFDE_TxtEdtDoRecord() {}
-
- virtual void Redo() const = 0;
- virtual void Undo() const = 0;
-};
-
-#endif // XFA_FDE_IFDE_TXTEDTDORECORD_H_