// Copyright 2014 The PDFium Authors
// 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 "fpdfsdk/pwl/cpwl_edit_impl.h"

#include <algorithm>
#include <memory>
#include <utility>

#include "constants/ascii.h"
#include "core/fpdfapi/font/cpdf_font.h"
#include "core/fpdfapi/render/cpdf_renderoptions.h"
#include "core/fpdfapi/render/cpdf_textrenderer.h"
#include "core/fpdfdoc/cpvt_line.h"
#include "core/fpdfdoc/cpvt_word.h"
#include "core/fpdfdoc/ipvt_fontmap.h"
#include "core/fxcrt/autorestorer.h"
#include "core/fxcrt/check.h"
#include "core/fxcrt/check_op.h"
#include "core/fxcrt/fx_codepage.h"
#include "core/fxge/cfx_fillrenderoptions.h"
#include "core/fxge/cfx_graphstatedata.h"
#include "core/fxge/cfx_path.h"
#include "core/fxge/cfx_renderdevice.h"
#include "fpdfsdk/pwl/cpwl_edit.h"
#include "fpdfsdk/pwl/cpwl_scroll_bar.h"
#include "fpdfsdk/pwl/ipwl_fillernotify.h"

namespace {

CFX_FloatRect GetWordRect(const CPVT_Word& word, const CPVT_Line& line) {
  return CFX_FloatRect(word.location().x, line.ptLine.y + line.fLineDescent,
                       word.location().x + word.width(),
                       line.ptLine.y + line.fLineAscent);
}

void DrawTextString(CFX_RenderDevice* pDevice,
                    const CFX_PointF& pt,
                    CPDF_Font* font,
                    float fFontSize,
                    const CFX_Matrix& mtUser2Device,
                    const ByteString& str,
                    FX_ARGB crTextFill) {
  if (!font) {
    return;
  }

  CFX_PointF pos = mtUser2Device.Transform(pt);
  CPDF_RenderOptions ro;
  CHECK(ro.GetOptions().bClearType);
  ro.SetColorMode(CPDF_RenderOptions::kNormal);
  CPDF_TextRenderer::DrawTextString(pDevice, pos.x, pos.y, font, fFontSize,
                                    mtUser2Device, str, crTextFill, ro);
}

}  // namespace

CPWL_EditImpl::Iterator::Iterator(CPWL_EditImpl* pEdit,
                                  CPVT_VariableText::Iterator* pVTIterator)
    : edit_(pEdit), vt_iterator_(pVTIterator) {}

CPWL_EditImpl::Iterator::~Iterator() = default;

bool CPWL_EditImpl::Iterator::NextWord() {
  return vt_iterator_->NextWord();
}

bool CPWL_EditImpl::Iterator::GetWord(CPVT_Word& word) const {
  CHECK(edit_);

  if (vt_iterator_->GetWord(word)) {
    word.set_location(edit_->VTToEdit(word.location()));
    return true;
  }
  return false;
}

bool CPWL_EditImpl::Iterator::GetLine(CPVT_Line& line) const {
  CHECK(edit_);

  if (vt_iterator_->GetLine(line)) {
    line.ptLine = edit_->VTToEdit(line.ptLine);
    return true;
  }
  return false;
}

void CPWL_EditImpl::Iterator::SetAt(int32_t nWordIndex) {
  vt_iterator_->SetAt(nWordIndex);
}

void CPWL_EditImpl::Iterator::SetAt(const CPVT_WordPlace& place) {
  vt_iterator_->SetAt(place);
}

const CPVT_WordPlace& CPWL_EditImpl::Iterator::GetAt() const {
  return vt_iterator_->GetWordPlace();
}

float CPWL_EditImpl::Iterator::GetLineCaretX(const CPVT_Line& line) {
  return vt_iterator_->GetLineCaretX(line);
}

class CPWL_EditImpl::Provider final : public CPVT_VariableText::Provider {
 public:
  explicit Provider(IPVT_FontMap* font_map);
  ~Provider() override;

  // CPVT_VariableText::Provider:
  int GetCharWidth(int32_t nFontIndex, uint16_t word) override;
  int32_t GetWordFontIndex(uint16_t word,
                           FX_Charset charset,
                           int32_t nFontIndex) override;
};

CPWL_EditImpl::Provider::Provider(IPVT_FontMap* font_map)
    : CPVT_VariableText::Provider(font_map) {}

CPWL_EditImpl::Provider::~Provider() = default;

int CPWL_EditImpl::Provider::GetCharWidth(int32_t nFontIndex, uint16_t word) {
  RetainPtr<CPDF_Font> pPDFFont = GetFontMap()->GetPDFFont(nFontIndex);
  if (!pPDFFont) {
    return 0;
  }

  uint32_t charcode = pPDFFont->IsUnicodeCompatible()
                          ? pPDFFont->CharCodeFromUnicode(word)
                          : GetFontMap()->CharCodeFromUnicode(nFontIndex, word);
  if (charcode == CPDF_Font::kInvalidCharCode) {
    return 0;
  }

  return pPDFFont->GetCharWidth(charcode);
}

int32_t CPWL_EditImpl::Provider::GetWordFontIndex(uint16_t word,
                                                  FX_Charset charset,
                                                  int32_t nFontIndex) {
  return GetFontMap()->GetWordFontIndex(word, charset, nFontIndex);
}

CPWL_EditImpl::RefreshState::RefreshState() = default;

CPWL_EditImpl::RefreshState::~RefreshState() = default;

void CPWL_EditImpl::RefreshState::BeginRefresh() {
  old_line_rects_ = std::move(new_line_rects_);
  new_line_rects_.clear();
  refresh_rects_.clear();
}

void CPWL_EditImpl::RefreshState::Push(const CPVT_WordRange& linerange,
                                       const CFX_FloatRect& rect) {
  new_line_rects_.emplace_back(linerange, rect);
}

void CPWL_EditImpl::RefreshState::NoAnalyse() {
  for (const auto& lineRect : old_line_rects_) {
    Add(lineRect.line_rect_);
  }

  for (const auto& lineRect : new_line_rects_) {
    Add(lineRect.line_rect_);
  }
}

std::vector<CFX_FloatRect>* CPWL_EditImpl::RefreshState::GetRefreshRects() {
  return &refresh_rects_;
}

void CPWL_EditImpl::RefreshState::EndRefresh() {
  refresh_rects_.clear();
}

void CPWL_EditImpl::RefreshState::Add(const CFX_FloatRect& new_rect) {
  // Check for overlapped area.
  for (const auto& rect : refresh_rects_) {
    if (rect.Contains(new_rect)) {
      return;
    }
  }
  refresh_rects_.push_back(new_rect);
}

bool CPWL_EditImpl::UndoItemIface::IsSentinel() {
  return false;
}

CPWL_EditImpl::UndoStack::UndoStack() = default;

CPWL_EditImpl::UndoStack::~UndoStack() = default;

bool CPWL_EditImpl::UndoStack::CanUndo() const {
  return cur_undo_pos_ > 0;
}

void CPWL_EditImpl::UndoStack::Undo() {
  CHECK(!working_);
  working_ = true;
  bool first_undo = true;
  while (CanUndo()) {
    --cur_undo_pos_;
    std::unique_ptr<UndoItemIface>& item = undo_item_stack_[cur_undo_pos_];
    item->Undo();

    if (first_undo) {
      first_undo = false;
      if (!item->IsSentinel()) {
        break;
      }
    } else {
      if (item->IsSentinel()) {
        break;
      }
    }
  }
  CHECK(working_);
  working_ = false;
}

bool CPWL_EditImpl::UndoStack::CanRedo() const {
  return cur_undo_pos_ < undo_item_stack_.size();
}

void CPWL_EditImpl::UndoStack::Redo() {
  CHECK(!working_);
  working_ = true;

  bool first_undo = true;
  while (CanRedo()) {
    std::unique_ptr<UndoItemIface>& item = undo_item_stack_[cur_undo_pos_];
    ++cur_undo_pos_;
    item->Redo();
    if (first_undo) {
      first_undo = false;
      if (!item->IsSentinel()) {
        break;
      }
    } else {
      if (item->IsSentinel()) {
        break;
      }
    }
  }
  CHECK(working_);
  working_ = false;
}

void CPWL_EditImpl::UndoStack::SetMaxUndoItemsForTest(size_t items) {
  CHECK_GE(items, kMinEditUndoMaxItems);
  max_undo_items_ = items;
}

void CPWL_EditImpl::UndoStack::AddItem(std::unique_ptr<UndoItemIface> pItem) {
  CHECK(!working_);
  CHECK(pItem);
  if (CanRedo()) {
    RemoveTails();
  }

  if (undo_item_stack_.size() >= max_undo_items_) {
    RemoveHeads();
  }

  undo_item_stack_.push_back(std::move(pItem));
  cur_undo_pos_ = undo_item_stack_.size();
}

void CPWL_EditImpl::UndoStack::RemoveHeads() {
  CHECK(!undo_item_stack_.empty());
  if (!undo_item_stack_.front()->IsSentinel()) {
    undo_item_stack_.pop_front();
    return;
  }
  // Pop everything from the initial sentinel, until the next sentinel item. Or
  // keep popping until the queue is empty.
  undo_item_stack_.pop_front();
  while (!undo_item_stack_.empty()) {
    bool is_sentinel = undo_item_stack_.front()->IsSentinel();
    undo_item_stack_.pop_front();
    if (is_sentinel) {
      break;
    }
  }
}

void CPWL_EditImpl::UndoStack::RemoveTails() {
  // Note: this covers the sentinel items in the queue automatically, since it
  // always pops all redo items.
  while (CanRedo()) {
    undo_item_stack_.pop_back();
  }
}

class CPWL_EditImpl::UndoInsertWord final
    : public CPWL_EditImpl::UndoItemIface {
 public:
  UndoInsertWord(CPWL_EditImpl* pEdit,
                 const CPVT_WordPlace& wpOldPlace,
                 const CPVT_WordPlace& wpNewPlace,
                 uint16_t word,
                 FX_Charset charset);
  ~UndoInsertWord() override;

  // UndoItemIface:
  void Redo() override;
  void Undo() override;

 private:
  UnownedPtr<CPWL_EditImpl> edit_;

  CPVT_WordPlace wp_old_;
  CPVT_WordPlace wp_new_;
  uint16_t word_;
  FX_Charset charset_;
};

CPWL_EditImpl::UndoInsertWord::UndoInsertWord(CPWL_EditImpl* pEdit,
                                              const CPVT_WordPlace& wpOldPlace,
                                              const CPVT_WordPlace& wpNewPlace,
                                              uint16_t word,
                                              FX_Charset charset)
    : edit_(pEdit),
      wp_old_(wpOldPlace),
      wp_new_(wpNewPlace),
      word_(word),
      charset_(charset) {
  CHECK(edit_);
}

CPWL_EditImpl::UndoInsertWord::~UndoInsertWord() = default;

void CPWL_EditImpl::UndoInsertWord::Redo() {
  edit_->SelectNone();
  edit_->SetCaret(wp_old_);
  edit_->InsertWord(word_, charset_, false);
}

void CPWL_EditImpl::UndoInsertWord::Undo() {
  edit_->SelectNone();
  edit_->SetCaret(wp_new_);
  edit_->Backspace(false);
}

class CPWL_EditImpl::UndoInsertReturn final
    : public CPWL_EditImpl::UndoItemIface {
 public:
  UndoInsertReturn(CPWL_EditImpl* pEdit,
                   const CPVT_WordPlace& wpOldPlace,
                   const CPVT_WordPlace& wpNewPlace);
  ~UndoInsertReturn() override;

  // UndoItemIface:
  void Redo() override;
  void Undo() override;

 private:
  UnownedPtr<CPWL_EditImpl> edit_;

  CPVT_WordPlace wp_old_;
  CPVT_WordPlace wp_new_;
};

CPWL_EditImpl::UndoInsertReturn::UndoInsertReturn(
    CPWL_EditImpl* pEdit,
    const CPVT_WordPlace& wpOldPlace,
    const CPVT_WordPlace& wpNewPlace)
    : edit_(pEdit), wp_old_(wpOldPlace), wp_new_(wpNewPlace) {
  CHECK(edit_);
}

CPWL_EditImpl::UndoInsertReturn::~UndoInsertReturn() = default;

void CPWL_EditImpl::UndoInsertReturn::Redo() {
  edit_->SelectNone();
  edit_->SetCaret(wp_old_);
  edit_->InsertReturn(false);
}

void CPWL_EditImpl::UndoInsertReturn::Undo() {
  edit_->SelectNone();
  edit_->SetCaret(wp_new_);
  edit_->Backspace(false);
}

class CPWL_EditImpl::UndoReplaceSelection final
    : public CPWL_EditImpl::UndoItemIface {
 public:
  UndoReplaceSelection() = default;
  ~UndoReplaceSelection() override = default;

  // UndoItemIface:
  void Redo() override {}
  void Undo() override {}
  bool IsSentinel() override { return true; }

 private:
  UnownedPtr<CPWL_EditImpl> edit_;
};

class CPWL_EditImpl::UndoBackspace final : public CPWL_EditImpl::UndoItemIface {
 public:
  UndoBackspace(CPWL_EditImpl* pEdit,
                const CPVT_WordPlace& wpOldPlace,
                const CPVT_WordPlace& wpNewPlace,
                uint16_t word,
                FX_Charset charset);
  ~UndoBackspace() override;

  // UndoItemIface:
  void Redo() override;
  void Undo() override;

 private:
  UnownedPtr<CPWL_EditImpl> edit_;

  CPVT_WordPlace wp_old_;
  CPVT_WordPlace wp_new_;
  uint16_t word_;
  FX_Charset charset_;
};

CPWL_EditImpl::UndoBackspace::UndoBackspace(CPWL_EditImpl* pEdit,
                                            const CPVT_WordPlace& wpOldPlace,
                                            const CPVT_WordPlace& wpNewPlace,
                                            uint16_t word,
                                            FX_Charset charset)
    : edit_(pEdit),
      wp_old_(wpOldPlace),
      wp_new_(wpNewPlace),
      word_(word),
      charset_(charset) {
  CHECK(edit_);
}

CPWL_EditImpl::UndoBackspace::~UndoBackspace() = default;

void CPWL_EditImpl::UndoBackspace::Redo() {
  edit_->SelectNone();
  edit_->SetCaret(wp_old_);
  edit_->Backspace(false);
}

void CPWL_EditImpl::UndoBackspace::Undo() {
  edit_->SelectNone();
  edit_->SetCaret(wp_new_);
  if (wp_new_.nSecIndex != wp_old_.nSecIndex) {
    edit_->InsertReturn(false);
  } else {
    edit_->InsertWord(word_, charset_, false);
  }
}

class CPWL_EditImpl::UndoDelete final : public CPWL_EditImpl::UndoItemIface {
 public:
  UndoDelete(CPWL_EditImpl* pEdit,
             const CPVT_WordPlace& wpOldPlace,
             const CPVT_WordPlace& wpNewPlace,
             uint16_t word,
             FX_Charset charset,
             bool bSecEnd);
  ~UndoDelete() override;

  // UndoItemIface:
  void Redo() override;
  void Undo() override;

 private:
  UnownedPtr<CPWL_EditImpl> edit_;

  CPVT_WordPlace wp_old_;
  CPVT_WordPlace wp_new_;
  uint16_t word_;
  FX_Charset charset_;
  bool sec_end_;
};

CPWL_EditImpl::UndoDelete::UndoDelete(CPWL_EditImpl* pEdit,
                                      const CPVT_WordPlace& wpOldPlace,
                                      const CPVT_WordPlace& wpNewPlace,
                                      uint16_t word,
                                      FX_Charset charset,
                                      bool bSecEnd)
    : edit_(pEdit),
      wp_old_(wpOldPlace),
      wp_new_(wpNewPlace),
      word_(word),
      charset_(charset),
      sec_end_(bSecEnd) {
  CHECK(edit_);
}

CPWL_EditImpl::UndoDelete::~UndoDelete() = default;

void CPWL_EditImpl::UndoDelete::Redo() {
  edit_->SelectNone();
  edit_->SetCaret(wp_old_);
  edit_->Delete(false);
}

void CPWL_EditImpl::UndoDelete::Undo() {
  edit_->SelectNone();
  edit_->SetCaret(wp_new_);
  if (sec_end_) {
    edit_->InsertReturn(false);
  } else {
    edit_->InsertWord(word_, charset_, false);
  }
}

class CPWL_EditImpl::UndoClear final : public CPWL_EditImpl::UndoItemIface {
 public:
  UndoClear(CPWL_EditImpl* pEdit,
            const CPVT_WordRange& wrSel,
            const WideString& swText);
  ~UndoClear() override;

  // UndoItemIface:
  void Redo() override;
  void Undo() override;

 private:
  UnownedPtr<CPWL_EditImpl> edit_;

  CPVT_WordRange wr_sel_;
  WideString sw_text_;
};

CPWL_EditImpl::UndoClear::UndoClear(CPWL_EditImpl* pEdit,
                                    const CPVT_WordRange& wrSel,
                                    const WideString& swText)
    : edit_(pEdit), wr_sel_(wrSel), sw_text_(swText) {
  CHECK(edit_);
}

CPWL_EditImpl::UndoClear::~UndoClear() = default;

void CPWL_EditImpl::UndoClear::Redo() {
  edit_->SelectNone();
  edit_->SetSelection(wr_sel_.BeginPos, wr_sel_.EndPos);
  edit_->Clear(false);
}

void CPWL_EditImpl::UndoClear::Undo() {
  edit_->SelectNone();
  edit_->SetCaret(wr_sel_.BeginPos);
  edit_->InsertText(sw_text_, FX_Charset::kDefault, false);
  edit_->SetSelection(wr_sel_.BeginPos, wr_sel_.EndPos);
}

class CPWL_EditImpl::UndoInsertText final
    : public CPWL_EditImpl::UndoItemIface {
 public:
  UndoInsertText(CPWL_EditImpl* pEdit,
                 const CPVT_WordPlace& wpOldPlace,
                 const CPVT_WordPlace& wpNewPlace,
                 const WideString& swText,
                 FX_Charset charset);
  ~UndoInsertText() override;

  // UndoItemIface:
  void Redo() override;
  void Undo() override;

 private:
  UnownedPtr<CPWL_EditImpl> edit_;

  CPVT_WordPlace wp_old_;
  CPVT_WordPlace wp_new_;
  WideString sw_text_;
  FX_Charset charset_;
};

CPWL_EditImpl::UndoInsertText::UndoInsertText(CPWL_EditImpl* pEdit,
                                              const CPVT_WordPlace& wpOldPlace,
                                              const CPVT_WordPlace& wpNewPlace,
                                              const WideString& swText,
                                              FX_Charset charset)
    : edit_(pEdit),
      wp_old_(wpOldPlace),
      wp_new_(wpNewPlace),
      sw_text_(swText),
      charset_(charset) {
  CHECK(edit_);
}

CPWL_EditImpl::UndoInsertText::~UndoInsertText() = default;

void CPWL_EditImpl::UndoInsertText::Redo() {
  edit_->SelectNone();
  edit_->SetCaret(wp_old_);
  edit_->InsertText(sw_text_, charset_, false);
}

void CPWL_EditImpl::UndoInsertText::Undo() {
  edit_->SelectNone();
  edit_->SetSelection(wp_old_, wp_new_);
  edit_->Clear(false);
}

void CPWL_EditImpl::DrawEdit(CFX_RenderDevice* pDevice,
                             const CFX_Matrix& mtUser2Device,
                             FX_COLORREF crTextFill,
                             const CFX_FloatRect& rcClip,
                             const CFX_PointF& ptOffset,
                             const CPVT_WordRange* pRange,
                             IPWL_FillerNotify* pFillerNotify,
                             IPWL_FillerNotify::PerWindowData* pSystemData) {
  const bool bContinuous = GetCharArray() == 0;
  uint16_t SubWord = GetPasswordChar();
  float fFontSize = GetFontSize();
  CPVT_WordRange wrSelect = GetSelectWordRange();
  FX_COLORREF crCurFill = crTextFill;
  FX_COLORREF crOldFill = crCurFill;
  bool bSelect = false;
  const FX_COLORREF crWhite = ArgbEncode(255, 255, 255, 255);
  const FX_COLORREF crSelBK = ArgbEncode(255, 0, 51, 113);

  int32_t nFontIndex = -1;
  CFX_PointF ptBT;
  CFX_RenderDevice::StateRestorer restorer(pDevice);
  if (!rcClip.IsEmpty()) {
    pDevice->SetClip_Rect(mtUser2Device.TransformRect(rcClip).ToFxRect());
  }

  Iterator* pIterator = GetIterator();
  IPVT_FontMap* font_map = GetFontMap();
  if (!font_map) {
    return;
  }

  if (pRange) {
    pIterator->SetAt(pRange->BeginPos);
  } else {
    pIterator->SetAt(0);
  }

  ByteString sTextBuf;
  CPVT_WordPlace oldplace;
  while (pIterator->NextWord()) {
    CPVT_WordPlace place = pIterator->GetAt();
    if (pRange && place > pRange->EndPos) {
      break;
    }

    if (!wrSelect.IsEmpty()) {
      bSelect = place > wrSelect.BeginPos && place <= wrSelect.EndPos;
      crCurFill = bSelect ? crWhite : crTextFill;
    }
    if (pFillerNotify->IsSelectionImplemented()) {
      crCurFill = crTextFill;
      crOldFill = crCurFill;
    }
    CPVT_Word word;
    if (pIterator->GetWord(word)) {
      if (bSelect) {
        CPVT_Line line;
        pIterator->GetLine(line);
        CFX_FloatRect word_rect = GetWordRect(word, line);
        if (pFillerNotify->IsSelectionImplemented()) {
          word_rect.Intersect(rcClip);
          pFillerNotify->OutputSelectedRect(pSystemData, word_rect);
        } else {
          CFX_Path pathSelBK;
          pathSelBK.AppendRect(word_rect.left, word_rect.bottom,
                               word_rect.right, word_rect.top);

          pDevice->DrawPath(pathSelBK, &mtUser2Device, nullptr, crSelBK, 0,
                            CFX_FillRenderOptions::WindingOptions());
        }
      }
      int32_t font_index = word.font_index();
      if (bContinuous && !word.is_rtl()) {
        if (place.LineCmp(oldplace) != 0 || font_index != nFontIndex ||
            crOldFill != crCurFill || sTextBuf.IsEmpty()) {
          if (!sTextBuf.IsEmpty()) {
            DrawTextString(pDevice, ptBT + ptOffset,
                           font_map->GetPDFFont(nFontIndex).Get(), fFontSize,
                           mtUser2Device, sTextBuf, crOldFill);
            sTextBuf.clear();
          }
          nFontIndex = font_index;
          ptBT = word.location();
          crOldFill = crCurFill;
        }
        sTextBuf += GetPDFWordString(font_index, word.word(), SubWord);
      } else {
        if (!sTextBuf.IsEmpty()) {
          DrawTextString(pDevice, ptBT + ptOffset,
                         font_map->GetPDFFont(nFontIndex).Get(), fFontSize,
                         mtUser2Device, sTextBuf, crOldFill);
          sTextBuf.clear();
        }
        DrawTextString(
            pDevice, word.location() + ptOffset,
            font_map->GetPDFFont(font_index).Get(), fFontSize, mtUser2Device,
            GetPDFWordString(font_index, word.word(), SubWord), crCurFill);
      }
      oldplace = place;
    }
  }
  if (!sTextBuf.IsEmpty()) {
    DrawTextString(pDevice, ptBT + ptOffset,
                   font_map->GetPDFFont(nFontIndex).Get(), fFontSize,
                   mtUser2Device, sTextBuf, crOldFill);
  }
}

CPWL_EditImpl::CPWL_EditImpl()
    : vt_(std::make_unique<CPVT_VariableText>(nullptr)) {}

CPWL_EditImpl::~CPWL_EditImpl() = default;

void CPWL_EditImpl::Initialize() {
  vt_->Initialize();
  SetCaret(vt_->GetBeginWordPlace());
  SetCaretOrigin();
}

void CPWL_EditImpl::SetFontMap(IPVT_FontMap* font_map) {
  vt_provider_ = std::make_unique<Provider>(font_map);
  vt_->SetProvider(vt_provider_.get());
}

void CPWL_EditImpl::SetNotify(CPWL_Edit* pNotify) {
  notify_ = pNotify;
}

CPWL_EditImpl::Iterator* CPWL_EditImpl::GetIterator() {
  if (!iterator_) {
    iterator_ = std::make_unique<Iterator>(this, vt_->GetIterator());
  }
  return iterator_.get();
}

IPVT_FontMap* CPWL_EditImpl::GetFontMap() {
  return vt_provider_ ? vt_provider_->GetFontMap() : nullptr;
}

void CPWL_EditImpl::SetPlateRect(const CFX_FloatRect& rect) {
  vt_->SetPlateRect(rect);
  scroll_pos_point_ = CFX_PointF(rect.left, rect.top);
}

void CPWL_EditImpl::SetAlignmentH(int32_t nFormat) {
  vt_->SetAlignment(CPVT_VariableText::ToAlignment(nFormat));
}

void CPWL_EditImpl::SetAlignmentV(int32_t nFormat) {
  alignment_ = nFormat;
}

void CPWL_EditImpl::SetTextDirection(
    CFX_BidiResolver::ParagraphDirection direction) {
  if (vt_->GetTextDirection() == direction) {
    return;
  }
  vt_->SetTextDirection(direction);
  Paint();
}

CFX_BidiResolver::ParagraphDirection CPWL_EditImpl::GetTextDirection() const {
  return vt_->GetTextDirection();
}

void CPWL_EditImpl::SetPasswordChar(uint16_t wSubWord) {
  vt_->SetPasswordChar(wSubWord);
}

void CPWL_EditImpl::SetLimitChar(int32_t nLimitChar) {
  vt_->SetLimitChar(nLimitChar);
}

void CPWL_EditImpl::SetCharArray(int32_t nCharArray) {
  vt_->SetCharArray(nCharArray);
}

void CPWL_EditImpl::SetMultiLine(bool bMultiLine) {
  vt_->SetMultiLine(bMultiLine);
}

void CPWL_EditImpl::SetAutoReturn(bool bAuto) {
  vt_->SetAutoReturn(bAuto);
}

void CPWL_EditImpl::SetAutoFontSize(bool bAuto) {
  vt_->SetAutoFontSize(bAuto);
}

void CPWL_EditImpl::SetFontSize(float fFontSize) {
  vt_->SetFontSize(fFontSize);
}

void CPWL_EditImpl::SetAutoScroll(bool bAuto) {
  enable_scroll_ = bAuto;
}

void CPWL_EditImpl::SetTextOverflow(bool bAllowed) {
  enable_overflow_ = bAllowed;
}

void CPWL_EditImpl::SetSelection(int32_t nStartChar, int32_t nEndChar) {
  if (vt_->IsValid()) {
    if (nStartChar == 0 && nEndChar < 0) {
      SelectAll();
    } else if (nStartChar < 0) {
      SelectNone();
    } else {
      if (nStartChar < nEndChar) {
        SetSelection(vt_->WordIndexToWordPlace(nStartChar),
                     vt_->WordIndexToWordPlace(nEndChar));
      } else {
        SetSelection(vt_->WordIndexToWordPlace(nEndChar),
                     vt_->WordIndexToWordPlace(nStartChar));
      }
    }
  }
}

void CPWL_EditImpl::SetSelection(const CPVT_WordPlace& begin,
                                 const CPVT_WordPlace& end) {
  if (!vt_->IsValid()) {
    return;
  }

  SelectNone();
  sel_state_.Set(begin, end);
  SetCaret(sel_state_.EndPos);
  ScrollToCaret();
  if (!sel_state_.IsEmpty()) {
    Refresh();
  }
  SetCaretInfo();
}

std::pair<int32_t, int32_t> CPWL_EditImpl::GetSelection() const {
  if (!vt_->IsValid()) {
    return std::make_pair(-1, -1);
  }

  if (sel_state_.IsEmpty()) {
    return std::make_pair(vt_->WordPlaceToWordIndex(wp_caret_),
                          vt_->WordPlaceToWordIndex(wp_caret_));
  }
  if (sel_state_.BeginPos < sel_state_.EndPos) {
    return std::make_pair(vt_->WordPlaceToWordIndex(sel_state_.BeginPos),
                          vt_->WordPlaceToWordIndex(sel_state_.EndPos));
  }
  return std::make_pair(vt_->WordPlaceToWordIndex(sel_state_.EndPos),
                        vt_->WordPlaceToWordIndex(sel_state_.BeginPos));
}

int32_t CPWL_EditImpl::GetCaret() const {
  if (vt_->IsValid()) {
    return vt_->WordPlaceToWordIndex(wp_caret_);
  }

  return -1;
}

CPVT_WordPlace CPWL_EditImpl::GetCaretWordPlace() const {
  return wp_caret_;
}

WideString CPWL_EditImpl::GetText() const {
  WideString swRet;
  if (!vt_->IsValid()) {
    return swRet;
  }

  CPVT_VariableText::Iterator* pIterator = vt_->GetIterator();
  pIterator->SetAt(0);

  CPVT_Word wordinfo;
  CPVT_WordPlace oldplace = pIterator->GetWordPlace();
  while (pIterator->NextWord()) {
    CPVT_WordPlace place = pIterator->GetWordPlace();
    if (pIterator->GetWord(wordinfo)) {
      swRet += wordinfo.word();
    }
    if (oldplace.nSecIndex != place.nSecIndex) {
      swRet += L"\r\n";
    }
    oldplace = place;
  }
  return swRet;
}

WideString CPWL_EditImpl::GetRangeText(const CPVT_WordRange& range) const {
  WideString swRet;
  if (!vt_->IsValid()) {
    return swRet;
  }

  CPVT_VariableText::Iterator* pIterator = vt_->GetIterator();
  CPVT_WordRange wrTemp = range;
  vt_->UpdateWordPlace(wrTemp.BeginPos);
  vt_->UpdateWordPlace(wrTemp.EndPos);
  pIterator->SetAt(wrTemp.BeginPos);

  CPVT_Word wordinfo;
  CPVT_WordPlace oldplace = wrTemp.BeginPos;
  while (pIterator->NextWord()) {
    CPVT_WordPlace place = pIterator->GetWordPlace();
    if (place > wrTemp.EndPos) {
      break;
    }
    if (pIterator->GetWord(wordinfo)) {
      swRet += wordinfo.word();
    }
    if (oldplace.nSecIndex != place.nSecIndex) {
      swRet += L"\r\n";
    }
    oldplace = place;
  }
  return swRet;
}

WideString CPWL_EditImpl::GetSelectedText() const {
  return GetRangeText(sel_state_.ConvertToWordRange());
}

int32_t CPWL_EditImpl::GetTotalLines() const {
  int32_t nLines = 1;

  CPVT_VariableText::Iterator* pIterator = vt_->GetIterator();
  pIterator->SetAt(0);
  while (pIterator->NextLine()) {
    ++nLines;
  }

  return nLines;
}

CPVT_WordRange CPWL_EditImpl::GetSelectWordRange() const {
  return sel_state_.ConvertToWordRange();
}

void CPWL_EditImpl::SetText(const WideString& sText) {
  Clear();
  DoInsertText(CPVT_WordPlace(0, 0, -1), sText, FX_Charset::kDefault);
}

bool CPWL_EditImpl::InsertWord(uint16_t word, FX_Charset charset) {
  return InsertWord(word, charset, true);
}

void CPWL_EditImpl::InsertReturn() {
  InsertReturn(true);
}

void CPWL_EditImpl::Backspace() {
  Backspace(true);
}

bool CPWL_EditImpl::Delete() {
  return Delete(true);
}

bool CPWL_EditImpl::ClearSelection() {
  return Clear(true);
}

void CPWL_EditImpl::InsertText(const WideString& sText, FX_Charset charset) {
  InsertText(sText, charset, true);
}

float CPWL_EditImpl::GetFontSize() const {
  return vt_->GetFontSize();
}

uint16_t CPWL_EditImpl::GetPasswordChar() const {
  return vt_->GetPasswordChar();
}

int32_t CPWL_EditImpl::GetCharArray() const {
  return vt_->GetCharArray();
}

CFX_FloatRect CPWL_EditImpl::GetContentRect() const {
  return VTToEdit(vt_->GetContentRect());
}

CPVT_WordRange CPWL_EditImpl::GetWholeWordRange() const {
  if (vt_->IsValid()) {
    return CPVT_WordRange(vt_->GetBeginWordPlace(), vt_->GetEndWordPlace());
  }

  return CPVT_WordRange();
}

CPVT_WordRange CPWL_EditImpl::GetVisibleWordRange() const {
  if (enable_overflow_) {
    return GetWholeWordRange();
  }

  if (vt_->IsValid()) {
    CFX_FloatRect rcPlate = vt_->GetPlateRect();

    CPVT_WordPlace place1 =
        vt_->SearchWordPlace(EditToVT(CFX_PointF(rcPlate.left, rcPlate.top)));
    CPVT_WordPlace place2 = vt_->SearchWordPlace(
        EditToVT(CFX_PointF(rcPlate.right, rcPlate.bottom)));

    return CPVT_WordRange(place1, place2);
  }

  return CPVT_WordRange();
}

CPVT_WordPlace CPWL_EditImpl::SearchWordPlace(const CFX_PointF& point) const {
  if (vt_->IsValid()) {
    return vt_->SearchWordPlace(EditToVT(point));
  }

  return CPVT_WordPlace();
}

void CPWL_EditImpl::Paint() {
  if (vt_->IsValid()) {
    RearrangeAll();
    ScrollToCaret();
    Refresh();
    SetCaretOrigin();
    SetCaretInfo();
  }
}

void CPWL_EditImpl::RearrangeAll() {
  if (vt_->IsValid()) {
    vt_->UpdateWordPlace(wp_caret_);
    vt_->RearrangeAll();
    vt_->UpdateWordPlace(wp_caret_);
    SetScrollInfo();
    SetContentChanged();
  }
}

void CPWL_EditImpl::RearrangePart(const CPVT_WordRange& range) {
  if (vt_->IsValid()) {
    vt_->UpdateWordPlace(wp_caret_);
    vt_->RearrangePart(range);
    vt_->UpdateWordPlace(wp_caret_);
    SetScrollInfo();
    SetContentChanged();
  }
}

void CPWL_EditImpl::SetContentChanged() {
  if (notify_) {
    CFX_FloatRect rcContent = vt_->GetContentRect();
    if (rcContent.Width() != old_content_rect_.Width() ||
        rcContent.Height() != old_content_rect_.Height()) {
      old_content_rect_ = rcContent;
    }
  }
}

void CPWL_EditImpl::SelectAll() {
  if (!vt_->IsValid()) {
    return;
  }
  sel_state_ = SelectState(GetWholeWordRange());
  SetCaret(sel_state_.EndPos);
  ScrollToCaret();
  Refresh();
  SetCaretInfo();
}

void CPWL_EditImpl::SelectNone() {
  if (!vt_->IsValid() || sel_state_.IsEmpty()) {
    return;
  }

  sel_state_.Reset();
  Refresh();
}

bool CPWL_EditImpl::IsSelected() const {
  return !sel_state_.IsEmpty();
}

CFX_PointF CPWL_EditImpl::VTToEdit(const CFX_PointF& point) const {
  CFX_FloatRect rcContent = vt_->GetContentRect();
  CFX_FloatRect rcPlate = vt_->GetPlateRect();

  float fPadding = 0.0f;

  switch (alignment_) {
    case 0:
      fPadding = 0.0f;
      break;
    case 1:
      fPadding = (rcPlate.Height() - rcContent.Height()) * 0.5f;
      break;
    case 2:
      fPadding = rcPlate.Height() - rcContent.Height();
      break;
  }

  return CFX_PointF(point.x - (scroll_pos_point_.x - rcPlate.left),
                    point.y - (scroll_pos_point_.y + fPadding - rcPlate.top));
}

CFX_PointF CPWL_EditImpl::EditToVT(const CFX_PointF& point) const {
  CFX_FloatRect rcContent = vt_->GetContentRect();
  CFX_FloatRect rcPlate = vt_->GetPlateRect();

  float fPadding = 0.0f;

  switch (alignment_) {
    case 0:
      fPadding = 0.0f;
      break;
    case 1:
      fPadding = (rcPlate.Height() - rcContent.Height()) * 0.5f;
      break;
    case 2:
      fPadding = rcPlate.Height() - rcContent.Height();
      break;
  }

  return CFX_PointF(point.x + (scroll_pos_point_.x - rcPlate.left),
                    point.y + (scroll_pos_point_.y + fPadding - rcPlate.top));
}

CFX_FloatRect CPWL_EditImpl::VTToEdit(const CFX_FloatRect& rect) const {
  CFX_PointF ptLeftBottom = VTToEdit(CFX_PointF(rect.left, rect.bottom));
  CFX_PointF ptRightTop = VTToEdit(CFX_PointF(rect.right, rect.top));

  return CFX_FloatRect(ptLeftBottom.x, ptLeftBottom.y, ptRightTop.x,
                       ptRightTop.y);
}

void CPWL_EditImpl::SetScrollInfo() {
  if (!notify_) {
    return;
  }

  CFX_FloatRect rcPlate = vt_->GetPlateRect();
  CFX_FloatRect rcContent = vt_->GetContentRect();
  if (notify_flag_) {
    return;
  }

  AutoRestorer<bool> restorer(&notify_flag_);
  notify_flag_ = true;

  PWL_SCROLL_INFO Info;
  Info.fPlateWidth = rcPlate.top - rcPlate.bottom;
  Info.fContentMin = rcContent.bottom;
  Info.fContentMax = rcContent.top;
  Info.fSmallStep = rcPlate.Height() / 3;
  Info.fBigStep = rcPlate.Height();
  notify_->SetScrollInfo(Info);
}

void CPWL_EditImpl::SetScrollPosX(float fx) {
  if (!enable_scroll_) {
    return;
  }

  if (vt_->IsValid()) {
    if (!FXSYS_IsFloatEqual(scroll_pos_point_.x, fx)) {
      scroll_pos_point_.x = fx;
      Refresh();
    }
  }
}

void CPWL_EditImpl::SetScrollPosY(float fy) {
  if (!enable_scroll_) {
    return;
  }

  if (vt_->IsValid()) {
    if (!FXSYS_IsFloatEqual(scroll_pos_point_.y, fy)) {
      scroll_pos_point_.y = fy;
      Refresh();

      if (notify_) {
        if (!notify_flag_) {
          AutoRestorer<bool> restorer(&notify_flag_);
          notify_flag_ = true;
          notify_->SetScrollPosition(fy);
        }
      }
    }
  }
}

void CPWL_EditImpl::SetScrollPos(const CFX_PointF& point) {
  SetScrollPosX(point.x);
  SetScrollPosY(point.y);
  SetScrollLimit();
  SetCaretInfo();
}

CFX_PointF CPWL_EditImpl::GetScrollPos() const {
  return scroll_pos_point_;
}

void CPWL_EditImpl::SetScrollLimit() {
  if (vt_->IsValid()) {
    CFX_FloatRect rcContent = vt_->GetContentRect();
    CFX_FloatRect rcPlate = vt_->GetPlateRect();

    if (rcPlate.Width() > rcContent.Width()) {
      SetScrollPosX(rcPlate.left);
    } else {
      if (FXSYS_IsFloatSmaller(scroll_pos_point_.x, rcContent.left)) {
        SetScrollPosX(rcContent.left);
      } else if (FXSYS_IsFloatBigger(scroll_pos_point_.x,
                                     rcContent.right - rcPlate.Width())) {
        SetScrollPosX(rcContent.right - rcPlate.Width());
      }
    }

    if (rcPlate.Height() > rcContent.Height()) {
      SetScrollPosY(rcPlate.top);
    } else {
      if (FXSYS_IsFloatSmaller(scroll_pos_point_.y,
                               rcContent.bottom + rcPlate.Height())) {
        SetScrollPosY(rcContent.bottom + rcPlate.Height());
      } else if (FXSYS_IsFloatBigger(scroll_pos_point_.y, rcContent.top)) {
        SetScrollPosY(rcContent.top);
      }
    }
  }
}

void CPWL_EditImpl::ScrollToCaret() {
  SetScrollLimit();

  if (!vt_->IsValid()) {
    return;
  }

  CPVT_VariableText::Iterator* pIterator = vt_->GetIterator();
  pIterator->SetAt(wp_caret_);

  CFX_PointF ptHead;
  CFX_PointF ptFoot;
  CPVT_Word word;
  CPVT_Line line;
  if (pIterator->GetWord(word)) {
    ptHead.x = word.CaretX();
    ptHead.y = word.AscentY();
    ptFoot.x = ptHead.x;
    ptFoot.y = word.DescentY();
  } else if (pIterator->GetLine(line)) {
    ptHead.x = pIterator->GetLineCaretX(line);
    ptHead.y = line.ptLine.y + line.fLineAscent;
    ptFoot.x = ptHead.x;
    ptFoot.y = line.ptLine.y + line.fLineDescent;
  }

  CFX_PointF ptHeadEdit = VTToEdit(ptHead);
  CFX_PointF ptFootEdit = VTToEdit(ptFoot);
  CFX_FloatRect rcPlate = vt_->GetPlateRect();
  if (!FXSYS_IsFloatEqual(rcPlate.left, rcPlate.right)) {
    if (FXSYS_IsFloatSmaller(ptHeadEdit.x, rcPlate.left) ||
        FXSYS_IsFloatEqual(ptHeadEdit.x, rcPlate.left)) {
      SetScrollPosX(ptHead.x);
    } else if (FXSYS_IsFloatBigger(ptHeadEdit.x, rcPlate.right)) {
      SetScrollPosX(ptHead.x - rcPlate.Width());
    }
  }

  if (!FXSYS_IsFloatEqual(rcPlate.top, rcPlate.bottom)) {
    if (FXSYS_IsFloatSmaller(ptFootEdit.y, rcPlate.bottom) ||
        FXSYS_IsFloatEqual(ptFootEdit.y, rcPlate.bottom)) {
      if (FXSYS_IsFloatSmaller(ptHeadEdit.y, rcPlate.top)) {
        SetScrollPosY(ptFoot.y + rcPlate.Height());
      }
    } else if (FXSYS_IsFloatBigger(ptHeadEdit.y, rcPlate.top)) {
      if (FXSYS_IsFloatBigger(ptFootEdit.y, rcPlate.bottom)) {
        SetScrollPosY(ptHead.y);
      }
    }
  }
}

void CPWL_EditImpl::Refresh() {
  if (enable_refresh_ && vt_->IsValid()) {
    refresh_.BeginRefresh();
    RefreshPushLineRects(GetVisibleWordRange());

    refresh_.NoAnalyse();
    pt_refresh_scroll_pos_ = scroll_pos_point_;

    if (notify_) {
      if (!notify_flag_) {
        AutoRestorer<bool> restorer(&notify_flag_);
        notify_flag_ = true;
        std::vector<CFX_FloatRect>* pRects = refresh_.GetRefreshRects();
        for (auto& rect : *pRects) {
          if (!notify_->InvalidateRect(&rect)) {
            notify_ = nullptr;  // Gone, dangling even.
            break;
          }
        }
      }
    }

    refresh_.EndRefresh();
  }
}

void CPWL_EditImpl::RefreshPushLineRects(const CPVT_WordRange& wr) {
  if (!vt_->IsValid()) {
    return;
  }

  CPVT_VariableText::Iterator* pIterator = vt_->GetIterator();
  CPVT_WordPlace wpBegin = wr.BeginPos;
  vt_->UpdateWordPlace(wpBegin);
  CPVT_WordPlace wpEnd = wr.EndPos;
  vt_->UpdateWordPlace(wpEnd);
  pIterator->SetAt(wpBegin);

  CPVT_Line lineinfo;
  do {
    if (!pIterator->GetLine(lineinfo)) {
      break;
    }
    if (lineinfo.lineplace.LineCmp(wpEnd) > 0) {
      break;
    }

    CFX_FloatRect rcLine(lineinfo.ptLine.x,
                         lineinfo.ptLine.y + lineinfo.fLineDescent,
                         lineinfo.ptLine.x + lineinfo.fLineWidth,
                         lineinfo.ptLine.y + lineinfo.fLineAscent);

    refresh_.Push(CPVT_WordRange(lineinfo.lineplace, lineinfo.lineEnd),
                  VTToEdit(rcLine));
  } while (pIterator->NextLine());
}

void CPWL_EditImpl::RefreshWordRange(const CPVT_WordRange& wr) {
  CPVT_VariableText::Iterator* pIterator = vt_->GetIterator();
  CPVT_WordRange wrTemp = wr;

  vt_->UpdateWordPlace(wrTemp.BeginPos);
  vt_->UpdateWordPlace(wrTemp.EndPos);
  pIterator->SetAt(wrTemp.BeginPos);

  CPVT_Word wordinfo;
  CPVT_Line lineinfo;
  CPVT_WordPlace place;

  while (pIterator->NextWord()) {
    place = pIterator->GetWordPlace();
    if (place > wrTemp.EndPos) {
      break;
    }

    pIterator->GetWord(wordinfo);
    pIterator->GetLine(lineinfo);
    if (place.LineCmp(wrTemp.BeginPos) == 0 ||
        place.LineCmp(wrTemp.EndPos) == 0) {
      CFX_FloatRect word_rect = GetWordRect(wordinfo, lineinfo);

      if (notify_) {
        if (!notify_flag_) {
          AutoRestorer<bool> restorer(&notify_flag_);
          notify_flag_ = true;
          CFX_FloatRect rcRefresh = VTToEdit(word_rect);
          if (!notify_->InvalidateRect(&rcRefresh)) {
            notify_ = nullptr;  // Gone, dangling even.
          }
        }
      }
    } else {
      CFX_FloatRect rcLine(lineinfo.ptLine.x,
                           lineinfo.ptLine.y + lineinfo.fLineDescent,
                           lineinfo.ptLine.x + lineinfo.fLineWidth,
                           lineinfo.ptLine.y + lineinfo.fLineAscent);

      if (notify_) {
        if (!notify_flag_) {
          AutoRestorer<bool> restorer(&notify_flag_);
          notify_flag_ = true;
          CFX_FloatRect rcRefresh = VTToEdit(rcLine);
          if (!notify_->InvalidateRect(&rcRefresh)) {
            notify_ = nullptr;  // Gone, dangling even.
          }
        }
      }

      pIterator->NextLine();
    }
  }
}

void CPWL_EditImpl::SetCaret(const CPVT_WordPlace& place) {
  wp_old_caret_ = wp_caret_;
  wp_caret_ = place;
}

void CPWL_EditImpl::SetCaretInfo() {
  if (notify_) {
    if (!notify_flag_) {
      CPVT_VariableText::Iterator* pIterator = vt_->GetIterator();
      pIterator->SetAt(wp_caret_);

      CFX_PointF ptHead;
      CFX_PointF ptFoot;
      CPVT_Word word;
      CPVT_Line line;
      if (pIterator->GetWord(word)) {
        ptHead.x = word.CaretX();
        ptHead.y = word.AscentY();
        ptFoot.x = ptHead.x;
        ptFoot.y = word.DescentY();
      } else if (pIterator->GetLine(line)) {
        ptHead.x = pIterator->GetLineCaretX(line);
        ptHead.y = line.ptLine.y + line.fLineAscent;
        ptFoot.x = ptHead.x;
        ptFoot.y = line.ptLine.y + line.fLineDescent;
      }

      AutoRestorer<bool> restorer(&notify_flag_);
      notify_flag_ = true;
      notify_->SetCaret(sel_state_.IsEmpty(), VTToEdit(ptHead),
                        VTToEdit(ptFoot));
    }
  }
}

void CPWL_EditImpl::OnMouseDown(const CFX_PointF& point,
                                bool bShift,
                                bool bCtrl) {
  if (!vt_->IsValid()) {
    return;
  }

  SelectNone();
  SetCaret(vt_->SearchWordPlace(EditToVT(point)));
  sel_state_.Set(wp_caret_, wp_caret_);
  ScrollToCaret();
  SetCaretOrigin();
  SetCaretInfo();
}

void CPWL_EditImpl::OnMouseMove(const CFX_PointF& point,
                                bool bShift,
                                bool bCtrl) {
  if (!vt_->IsValid()) {
    return;
  }

  SetCaret(vt_->SearchWordPlace(EditToVT(point)));
  if (wp_caret_ == wp_old_caret_) {
    return;
  }

  sel_state_.SetEndPos(wp_caret_);
  ScrollToCaret();
  Refresh();
  SetCaretOrigin();
  SetCaretInfo();
}

void CPWL_EditImpl::OnVK_UP(bool bShift) {
  if (!vt_->IsValid()) {
    return;
  }

  SetCaret(vt_->GetUpWordPlace(wp_caret_, caret_point_));
  if (bShift) {
    if (sel_state_.IsEmpty()) {
      sel_state_.Set(wp_old_caret_, wp_caret_);
    } else {
      sel_state_.SetEndPos(wp_caret_);
    }

    if (wp_old_caret_ != wp_caret_) {
      ScrollToCaret();
      Refresh();
      SetCaretInfo();
    }
  } else {
    SelectNone();
    ScrollToCaret();
    SetCaretInfo();
  }
}

void CPWL_EditImpl::OnVK_DOWN(bool bShift) {
  if (!vt_->IsValid()) {
    return;
  }

  SetCaret(vt_->GetDownWordPlace(wp_caret_, caret_point_));
  if (bShift) {
    if (sel_state_.IsEmpty()) {
      sel_state_.Set(wp_old_caret_, wp_caret_);
    } else {
      sel_state_.SetEndPos(wp_caret_);
    }

    if (wp_old_caret_ != wp_caret_) {
      ScrollToCaret();
      Refresh();
      SetCaretInfo();
    }
  } else {
    SelectNone();
    ScrollToCaret();
    SetCaretInfo();
  }
}

void CPWL_EditImpl::OnVK_LEFT(bool bShift) {
  if (!vt_->IsValid()) {
    return;
  }

  if (bShift) {
    if (wp_caret_ == vt_->GetLineBeginPlace(wp_caret_) &&
        wp_caret_ != vt_->GetSectionBeginPlace(wp_caret_)) {
      SetCaret(vt_->GetPrevWordPlace(wp_caret_));
    }
    SetCaret(vt_->GetPrevWordPlace(wp_caret_));
    if (sel_state_.IsEmpty()) {
      sel_state_.Set(wp_old_caret_, wp_caret_);
    } else {
      sel_state_.SetEndPos(wp_caret_);
    }

    if (wp_old_caret_ != wp_caret_) {
      ScrollToCaret();
      Refresh();
      SetCaretInfo();
    }
  } else {
    if (!sel_state_.IsEmpty()) {
      if (sel_state_.BeginPos < sel_state_.EndPos) {
        SetCaret(sel_state_.BeginPos);
      } else {
        SetCaret(sel_state_.EndPos);
      }

      SelectNone();
      ScrollToCaret();
      SetCaretInfo();
    } else {
      if (wp_caret_ == vt_->GetLineBeginPlace(wp_caret_) &&
          wp_caret_ != vt_->GetSectionBeginPlace(wp_caret_)) {
        SetCaret(vt_->GetPrevWordPlace(wp_caret_));
      }
      SetCaret(vt_->GetPrevWordPlace(wp_caret_));
      ScrollToCaret();
      SetCaretOrigin();
      SetCaretInfo();
    }
  }
}

void CPWL_EditImpl::OnVK_RIGHT(bool bShift) {
  if (!vt_->IsValid()) {
    return;
  }

  if (bShift) {
    SetCaret(vt_->GetNextWordPlace(wp_caret_));
    if (wp_caret_ == vt_->GetLineEndPlace(wp_caret_) &&
        wp_caret_ != vt_->GetSectionEndPlace(wp_caret_)) {
      SetCaret(vt_->GetNextWordPlace(wp_caret_));
    }

    if (sel_state_.IsEmpty()) {
      sel_state_.Set(wp_old_caret_, wp_caret_);
    } else {
      sel_state_.SetEndPos(wp_caret_);
    }

    if (wp_old_caret_ != wp_caret_) {
      ScrollToCaret();
      Refresh();
      SetCaretInfo();
    }
  } else {
    if (!sel_state_.IsEmpty()) {
      if (sel_state_.BeginPos > sel_state_.EndPos) {
        SetCaret(sel_state_.BeginPos);
      } else {
        SetCaret(sel_state_.EndPos);
      }

      SelectNone();
      ScrollToCaret();
      SetCaretInfo();
    } else {
      SetCaret(vt_->GetNextWordPlace(wp_caret_));
      if (wp_caret_ == vt_->GetLineEndPlace(wp_caret_) &&
          wp_caret_ != vt_->GetSectionEndPlace(wp_caret_)) {
        SetCaret(vt_->GetNextWordPlace(wp_caret_));
      }
      ScrollToCaret();
      SetCaretOrigin();
      SetCaretInfo();
    }
  }
}

void CPWL_EditImpl::OnVK_HOME(bool bShift, bool bCtrl) {
  if (!vt_->IsValid()) {
    return;
  }

  if (bShift) {
    if (bCtrl) {
      SetCaret(vt_->GetBeginWordPlace());
    } else {
      SetCaret(vt_->GetLineBeginPlace(wp_caret_));
    }

    if (sel_state_.IsEmpty()) {
      sel_state_.Set(wp_old_caret_, wp_caret_);
    } else {
      sel_state_.SetEndPos(wp_caret_);
    }

    ScrollToCaret();
    Refresh();
    SetCaretInfo();
  } else {
    if (!sel_state_.IsEmpty()) {
      SetCaret(std::min(sel_state_.BeginPos, sel_state_.EndPos));
      SelectNone();
      ScrollToCaret();
      SetCaretInfo();
    } else {
      if (bCtrl) {
        SetCaret(vt_->GetBeginWordPlace());
      } else {
        SetCaret(vt_->GetLineBeginPlace(wp_caret_));
      }

      ScrollToCaret();
      SetCaretOrigin();
      SetCaretInfo();
    }
  }
}

void CPWL_EditImpl::OnVK_END(bool bShift, bool bCtrl) {
  if (!vt_->IsValid()) {
    return;
  }

  if (bShift) {
    if (bCtrl) {
      SetCaret(vt_->GetEndWordPlace());
    } else {
      SetCaret(vt_->GetLineEndPlace(wp_caret_));
    }

    if (sel_state_.IsEmpty()) {
      sel_state_.Set(wp_old_caret_, wp_caret_);
    } else {
      sel_state_.SetEndPos(wp_caret_);
    }

    ScrollToCaret();
    Refresh();
    SetCaretInfo();
  } else {
    if (!sel_state_.IsEmpty()) {
      SetCaret(std::max(sel_state_.BeginPos, sel_state_.EndPos));
      SelectNone();
      ScrollToCaret();
      SetCaretInfo();
    } else {
      if (bCtrl) {
        SetCaret(vt_->GetEndWordPlace());
      } else {
        SetCaret(vt_->GetLineEndPlace(wp_caret_));
      }

      ScrollToCaret();
      SetCaretOrigin();
      SetCaretInfo();
    }
  }
}

bool CPWL_EditImpl::InsertWord(uint16_t word,
                               FX_Charset charset,
                               bool bAddUndo) {
  if (IsTextOverflow() || !vt_->IsValid()) {
    return false;
  }

  vt_->UpdateWordPlace(wp_caret_);
  SetCaret(
      vt_->InsertWord(wp_caret_, word, GetCharSetFromUnicode(word, charset)));
  sel_state_.Set(wp_caret_, wp_caret_);
  if (wp_caret_ == wp_old_caret_) {
    return false;
  }

  if (bAddUndo && enable_undo_) {
    AddEditUndoItem(std::make_unique<UndoInsertWord>(this, wp_old_caret_,
                                                     wp_caret_, word, charset));
  }
  PaintInsertText(wp_old_caret_, wp_caret_);
  return true;
}

void CPWL_EditImpl::InsertReturn(bool bAddUndo) {
  if (IsTextOverflow() || !vt_->IsValid()) {
    return;
  }

  vt_->UpdateWordPlace(wp_caret_);
  SetCaret(vt_->InsertSection(wp_caret_));
  sel_state_.Set(wp_caret_, wp_caret_);
  if (wp_caret_ == wp_old_caret_) {
    return;
  }

  if (bAddUndo && enable_undo_) {
    AddEditUndoItem(
        std::make_unique<UndoInsertReturn>(this, wp_old_caret_, wp_caret_));
  }
  RearrangePart(CPVT_WordRange(wp_old_caret_, wp_caret_));
  ScrollToCaret();
  Refresh();
  SetCaretOrigin();
  SetCaretInfo();
}

void CPWL_EditImpl::Backspace(bool bAddUndo) {
  if (!vt_->IsValid() || wp_caret_ == vt_->GetBeginWordPlace()) {
    return;
  }

  CPVT_Word word;
  if (bAddUndo) {
    CPVT_VariableText::Iterator* pIterator = vt_->GetIterator();
    pIterator->SetAt(wp_caret_);
    pIterator->GetWord(word);
  }
  vt_->UpdateWordPlace(wp_caret_);
  SetCaret(vt_->BackSpaceWord(wp_caret_));
  sel_state_.Set(wp_caret_, wp_caret_);
  if (wp_caret_ == wp_old_caret_) {
    return;
  }

  if (bAddUndo && enable_undo_) {
    AddEditUndoItem(std::make_unique<UndoBackspace>(
        this, wp_old_caret_, wp_caret_, word.word(), word.charset()));
  }
  RearrangePart(CPVT_WordRange(wp_caret_, wp_old_caret_));
  ScrollToCaret();
  Refresh();
  SetCaretOrigin();
  SetCaretInfo();
}

bool CPWL_EditImpl::Delete(bool bAddUndo) {
  if (!vt_->IsValid() || wp_caret_ == vt_->GetEndWordPlace()) {
    return false;
  }

  CPVT_Word word;
  if (bAddUndo) {
    CPVT_VariableText::Iterator* pIterator = vt_->GetIterator();
    pIterator->SetAt(vt_->GetNextWordPlace(wp_caret_));
    pIterator->GetWord(word);
  }
  vt_->UpdateWordPlace(wp_caret_);
  bool bSecEnd = (wp_caret_ == vt_->GetSectionEndPlace(wp_caret_));
  SetCaret(vt_->DeleteWord(wp_caret_));
  sel_state_.Set(wp_caret_, wp_caret_);
  if (bAddUndo && enable_undo_) {
    if (bSecEnd) {
      AddEditUndoItem(std::make_unique<UndoDelete>(this, wp_old_caret_,
                                                   wp_caret_, word.word(),
                                                   word.charset(), bSecEnd));
    } else {
      AddEditUndoItem(std::make_unique<UndoDelete>(this, wp_old_caret_,
                                                   wp_caret_, word.word(),
                                                   word.charset(), bSecEnd));
    }
  }
  RearrangePart(CPVT_WordRange(wp_old_caret_, wp_caret_));
  ScrollToCaret();
  Refresh();
  SetCaretOrigin();
  SetCaretInfo();
  return true;
}

bool CPWL_EditImpl::Clear() {
  if (vt_->IsValid()) {
    vt_->DeleteWords(GetWholeWordRange());
    SetCaret(vt_->GetBeginWordPlace());

    return true;
  }

  return false;
}

bool CPWL_EditImpl::Clear(bool bAddUndo) {
  if (!vt_->IsValid() || sel_state_.IsEmpty()) {
    return false;
  }

  CPVT_WordRange range = sel_state_.ConvertToWordRange();
  if (bAddUndo && enable_undo_) {
    AddEditUndoItem(
        std::make_unique<UndoClear>(this, range, GetSelectedText()));
  }
  SelectNone();
  SetCaret(vt_->DeleteWords(range));
  sel_state_.Set(wp_caret_, wp_caret_);
  RearrangePart(range);
  ScrollToCaret();
  Refresh();
  SetCaretOrigin();
  SetCaretInfo();
  return true;
}

void CPWL_EditImpl::InsertText(const WideString& sText,
                               FX_Charset charset,
                               bool bAddUndo) {
  if (IsTextOverflow()) {
    return;
  }

  vt_->UpdateWordPlace(wp_caret_);
  SetCaret(DoInsertText(wp_caret_, sText, charset));
  sel_state_.Set(wp_caret_, wp_caret_);
  if (wp_caret_ == wp_old_caret_) {
    return;
  }

  if (bAddUndo && enable_undo_) {
    AddEditUndoItem(std::make_unique<UndoInsertText>(
        this, wp_old_caret_, wp_caret_, sText, charset));
  }
  PaintInsertText(wp_old_caret_, wp_caret_);
}

void CPWL_EditImpl::PaintInsertText(const CPVT_WordPlace& wpOld,
                                    const CPVT_WordPlace& wpNew) {
  if (vt_->IsValid()) {
    RearrangePart(CPVT_WordRange(wpOld, wpNew));
    ScrollToCaret();
    Refresh();
    SetCaretOrigin();
    SetCaretInfo();
  }
}

void CPWL_EditImpl::ReplaceAndKeepSelection(const WideString& text) {
  AddEditUndoItem(std::make_unique<UndoReplaceSelection>());
  ClearSelection();

  // Insert the text and then select it
  CPVT_WordPlace caret_before_insert = wp_caret_;
  InsertText(text, FX_Charset::kDefault);
  CPVT_WordPlace caret_after_insert = wp_caret_;
  sel_state_.Set(caret_before_insert, caret_after_insert);

  AddEditUndoItem(std::make_unique<UndoReplaceSelection>());
}

void CPWL_EditImpl::ReplaceSelection(const WideString& text) {
  // UndoReplaceSelection acts as a sentinel object in the undo queue. Since
  // ClearSelection and InsertText only optionally add undo items there are a
  // variable number of items in the queue for this action. These sentinel
  // objects mark the start and the end of the series of related undo items.
  AddEditUndoItem(std::make_unique<UndoReplaceSelection>());
  ClearSelection();
  InsertText(text, FX_Charset::kDefault);
  AddEditUndoItem(std::make_unique<UndoReplaceSelection>());
}

void CPWL_EditImpl::TypeChar(uint16_t word, FX_Charset charset) {
  bool was_selected = IsSelected();

  // Backspace is special because it always needs only one undo item.
  // ClearSelection() deletes the selected text so Backspace() isn't needed in
  // that case.
  if (word == pdfium::ascii::kBackspace) {
    if (was_selected) {
      ClearSelection();
    } else {
      Backspace();
    }
    return;
  }

  // Don't add the UndoReplaceSelection sentinel items if there's no selection
  // so that in the normal "typing one character" case only one undo item goes
  // into the queue.
  if (was_selected) {
    AddEditUndoItem(std::make_unique<UndoReplaceSelection>());
    ClearSelection();
  }

  if (word == pdfium::ascii::kReturn) {
    InsertReturn();
  } else {
    // Not a special character, just typing letters
    InsertWord(word, charset);
  }

  if (was_selected) {
    AddEditUndoItem(std::make_unique<UndoReplaceSelection>());
  }
}

bool CPWL_EditImpl::Redo() {
  if (enable_undo_) {
    if (undo_.CanRedo()) {
      undo_.Redo();
      return true;
    }
  }

  return false;
}

bool CPWL_EditImpl::Undo() {
  if (enable_undo_) {
    if (undo_.CanUndo()) {
      undo_.Undo();
      return true;
    }
  }

  return false;
}

void CPWL_EditImpl::SetCaretOrigin() {
  if (!vt_->IsValid()) {
    return;
  }

  CPVT_VariableText::Iterator* pIterator = vt_->GetIterator();
  pIterator->SetAt(wp_caret_);
  CPVT_Word word;
  CPVT_Line line;
  if (pIterator->GetWord(word)) {
    caret_point_.x = word.CaretX();
    caret_point_.y = word.location().y;
  } else if (pIterator->GetLine(line)) {
    caret_point_.x = line.ptLine.x;
    caret_point_.y = line.ptLine.y;
  }
}

CPVT_WordPlace CPWL_EditImpl::WordIndexToWordPlace(int32_t index) const {
  if (vt_->IsValid()) {
    return vt_->WordIndexToWordPlace(index);
  }

  return CPVT_WordPlace();
}

bool CPWL_EditImpl::IsTextFull() const {
  int32_t nTotalWords = vt_->GetTotalWords();
  int32_t nLimitChar = vt_->GetLimitChar();
  int32_t nCharArray = vt_->GetCharArray();

  return IsTextOverflow() || (nLimitChar > 0 && nTotalWords >= nLimitChar) ||
         (nCharArray > 0 && nTotalWords >= nCharArray);
}

bool CPWL_EditImpl::IsTextOverflow() const {
  if (!enable_scroll_ && !enable_overflow_) {
    CFX_FloatRect rcPlate = vt_->GetPlateRect();
    CFX_FloatRect rcContent = vt_->GetContentRect();

    if (vt_->IsMultiLine() && GetTotalLines() > 1 &&
        FXSYS_IsFloatBigger(rcContent.Height(), rcPlate.Height())) {
      return true;
    }

    if (FXSYS_IsFloatBigger(rcContent.Width(), rcPlate.Width())) {
      return true;
    }
  }

  return false;
}

bool CPWL_EditImpl::CanUndo() const {
  if (enable_undo_) {
    return undo_.CanUndo();
  }

  return false;
}

bool CPWL_EditImpl::CanRedo() const {
  if (enable_undo_) {
    return undo_.CanRedo();
  }

  return false;
}

void CPWL_EditImpl::SetMaxUndoItemsForTest(size_t items) {
  undo_.SetMaxUndoItemsForTest(items);
}

void CPWL_EditImpl::EnableRefresh(bool bRefresh) {
  enable_refresh_ = bRefresh;
}

void CPWL_EditImpl::EnableUndo(bool bUndo) {
  enable_undo_ = bUndo;
}

CPVT_WordPlace CPWL_EditImpl::DoInsertText(const CPVT_WordPlace& place,
                                           const WideString& sText,
                                           FX_Charset charset) {
  if (!vt_->IsValid()) {
    return place;
  }

  CPVT_WordPlace wp = place;
  for (size_t i = 0; i < sText.GetLength(); ++i) {
    uint16_t word = sText[i];
    switch (word) {
      case '\r':
        wp = vt_->InsertSection(wp);
        if (i + 1 < sText.GetLength() && sText[i + 1] == '\n') {
          i++;
        }
        break;
      case '\n':
        wp = vt_->InsertSection(wp);
        break;
      case '\t':
        word = ' ';
        [[fallthrough]];
      default:
        wp = vt_->InsertWord(wp, word, GetCharSetFromUnicode(word, charset));
        break;
    }
  }
  return wp;
}

FX_Charset CPWL_EditImpl::GetCharSetFromUnicode(uint16_t word,
                                                FX_Charset nOldCharset) {
  if (IPVT_FontMap* font_map = GetFontMap()) {
    return font_map->CharSetFromUnicode(word, nOldCharset);
  }
  return nOldCharset;
}

void CPWL_EditImpl::AddEditUndoItem(
    std::unique_ptr<UndoItemIface> pEditUndoItem) {
  undo_.AddItem(std::move(pEditUndoItem));
}

ByteString CPWL_EditImpl::GetPDFWordString(int32_t nFontIndex,
                                           uint16_t Word,
                                           uint16_t SubWord) {
  IPVT_FontMap* font_map = GetFontMap();
  RetainPtr<CPDF_Font> pPDFFont = font_map->GetPDFFont(nFontIndex);
  if (!pPDFFont) {
    return ByteString();
  }

  ByteString sWord;
  if (SubWord > 0) {
    Word = SubWord;
  } else {
    uint32_t dwCharCode = pPDFFont->IsUnicodeCompatible()
                              ? pPDFFont->CharCodeFromUnicode(Word)
                              : font_map->CharCodeFromUnicode(nFontIndex, Word);
    if (dwCharCode > 0) {
      pPDFFont->AppendChar(&sWord, dwCharCode);
      return sWord;
    }
  }
  pPDFFont->AppendChar(&sWord, Word);
  return sWord;
}

CPWL_EditImpl::SelectState::SelectState() = default;

CPWL_EditImpl::SelectState::SelectState(const CPVT_WordRange& range) {
  Set(range.BeginPos, range.EndPos);
}

CPVT_WordRange CPWL_EditImpl::SelectState::ConvertToWordRange() const {
  return CPVT_WordRange(BeginPos, EndPos);
}

void CPWL_EditImpl::SelectState::Reset() {
  BeginPos.Reset();
  EndPos.Reset();
}

void CPWL_EditImpl::SelectState::Set(const CPVT_WordPlace& begin,
                                     const CPVT_WordPlace& end) {
  BeginPos = begin;
  EndPos = end;
}

void CPWL_EditImpl::SelectState::SetEndPos(const CPVT_WordPlace& end) {
  EndPos = end;
}

bool CPWL_EditImpl::SelectState::IsEmpty() const {
  return BeginPos == EndPos;
}
