// 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 "core/fpdfapi/font/cpdf_font.h"
#include "core/fpdfapi/render/cpdf_renderoptions.h"
#include "core/fpdfapi/render/cpdf_textrenderer.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 {

const int kEditUndoMaxItems = 10000;

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

  CFX_PointF pos = mtUser2Device.Transform(pt);
  CPDF_RenderOptions ro;
  DCHECK(ro.GetOptions().bClearType);
  ro.SetColorMode(CPDF_RenderOptions::kNormal);
  CPDF_TextRenderer::DrawTextString(pDevice, pos.x, pos.y, pFont, 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 {
  DCHECK(edit_);

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

bool CPWL_EditImpl::Iterator::GetLine(CPVT_Line& line) const {
  DCHECK(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();
}

class CPWL_EditImpl::Provider final : public CPVT_VariableText::Provider {
 public:
  explicit Provider(IPVT_FontMap* pFontMap);
  ~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* pFontMap)
    : CPVT_VariableText::Provider(pFontMap) {}

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->GetCharWidthF(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);
}

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() {
  DCHECK(!working_);
  working_ = true;
  int undo_remaining = 1;
  while (CanUndo() && undo_remaining > 0) {
    undo_remaining += undo_item_stack_[cur_undo_pos_ - 1]->Undo();
    cur_undo_pos_--;
    undo_remaining--;
  }
  DCHECK_EQ(undo_remaining, 0);
  DCHECK(working_);
  working_ = false;
}

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

CPWL_EditImpl::UndoItemIface* CPWL_EditImpl::UndoStack::GetLastAddItem() {
  CHECK(!undo_item_stack_.empty());
  return undo_item_stack_.back().get();
}

void CPWL_EditImpl::UndoStack::Redo() {
  DCHECK(!working_);
  working_ = true;
  int nRedoRemain = 1;
  while (CanRedo() && nRedoRemain > 0) {
    nRedoRemain += undo_item_stack_[cur_undo_pos_]->Redo();
    cur_undo_pos_++;
    nRedoRemain--;
  }
  DCHECK_EQ(nRedoRemain, 0);
  DCHECK(working_);
  working_ = false;
}

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

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

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

void CPWL_EditImpl::UndoStack::RemoveHeads() {
  DCHECK(undo_item_stack_.size() > 1);
  undo_item_stack_.pop_front();
}

void CPWL_EditImpl::UndoStack::RemoveTails() {
  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:
  int Redo() override;
  int 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) {
  DCHECK(edit_);
}

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

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

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

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:
  int Redo() override;
  int 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) {
  DCHECK(edit_);
}

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

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

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

class CPWL_EditImpl::UndoReplaceSelection final
    : public CPWL_EditImpl::UndoItemIface {
 public:
  UndoReplaceSelection(CPWL_EditImpl* pEdit, bool bIsEnd);
  ~UndoReplaceSelection() override;

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

 private:
  bool IsEnd() const { return end_; }

  UnownedPtr<CPWL_EditImpl> edit_;
  const bool end_;  // indicate whether this is the end of replace action
};

CPWL_EditImpl::UndoReplaceSelection::UndoReplaceSelection(CPWL_EditImpl* pEdit,
                                                          bool bIsEnd)
    : edit_(pEdit), end_(bIsEnd) {
  DCHECK(edit_);
  // Redo ClearSelection, InsertText and ReplaceSelection's end marker
  // Undo InsertText, ClearSelection and ReplaceSelection's beginning
  // marker
  set_undo_remaining(3);
}

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

int CPWL_EditImpl::UndoReplaceSelection::Redo() {
  edit_->SelectNone();
  if (IsEnd()) {
    return 0;
  }
  // Redo ClearSelection, InsertText and ReplaceSelection's end
  // marker. (ClearSelection may not exist)
  return undo_remaining();
}

int CPWL_EditImpl::UndoReplaceSelection::Undo() {
  edit_->SelectNone();
  if (!IsEnd()) {
    return 0;
  }
  // Undo InsertText, ClearSelection and ReplaceSelection's beginning
  // marker. (ClearSelection may not exist)
  return undo_remaining();
}

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:
  int Redo() override;
  int 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) {
  DCHECK(edit_);
}

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

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

int 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);
  }
  return 0;
}

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:
  int Redo() override;
  int 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) {
  DCHECK(edit_);
}

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

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

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

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

  // UndoItemIface:
  int Redo() override;
  int 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) {
  DCHECK(edit_);
}

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

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

int 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);
  return 0;
}

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:
  int Redo() override;
  int 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) {
  DCHECK(edit_);
}

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

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

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

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* pFontMap = GetFontMap();
  if (!pFontMap)
    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);
        if (pFillerNotify->IsSelectionImplemented()) {
          CFX_FloatRect rc(word.ptWord.x, line.ptLine.y + line.fLineDescent,
                           word.ptWord.x + word.fWidth,
                           line.ptLine.y + line.fLineAscent);
          rc.Intersect(rcClip);
          pFillerNotify->OutputSelectedRect(pSystemData, rc);
        } else {
          CFX_Path pathSelBK;
          pathSelBK.AppendRect(word.ptWord.x, line.ptLine.y + line.fLineDescent,
                               word.ptWord.x + word.fWidth,
                               line.ptLine.y + line.fLineAscent);

          pDevice->DrawPath(pathSelBK, &mtUser2Device, nullptr, crSelBK, 0,
                            CFX_FillRenderOptions::WindingOptions());
        }
      }
      if (bContinuous) {
        if (place.LineCmp(oldplace) != 0 || word.nFontIndex != nFontIndex ||
            crOldFill != crCurFill) {
          if (!sTextBuf.IsEmpty()) {
            DrawTextString(pDevice,
                           CFX_PointF(ptBT.x + ptOffset.x, ptBT.y + ptOffset.y),
                           pFontMap->GetPDFFont(nFontIndex).Get(), fFontSize,
                           mtUser2Device, sTextBuf, crOldFill);
            sTextBuf.clear();
          }
          nFontIndex = word.nFontIndex;
          ptBT = word.ptWord;
          crOldFill = crCurFill;
        }
        sTextBuf += GetPDFWordString(word.nFontIndex, word.Word, SubWord);
      } else {
        DrawTextString(
            pDevice,
            CFX_PointF(word.ptWord.x + ptOffset.x, word.ptWord.y + ptOffset.y),
            pFontMap->GetPDFFont(word.nFontIndex).Get(), fFontSize,
            mtUser2Device,
            GetPDFWordString(word.nFontIndex, word.Word, SubWord), crCurFill);
      }
      oldplace = place;
    }
  }
  if (!sTextBuf.IsEmpty()) {
    DrawTextString(pDevice,
                   CFX_PointF(ptBT.x + ptOffset.x, ptBT.y + ptOffset.y),
                   pFontMap->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* pFontMap) {
  vt_provider_ = std::make_unique<Provider>(pFontMap);
  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(nFormat);
}

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

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.ptWord.x + word.fWidth;
    ptHead.y = word.ptWord.y + word.fAscent;
    ptFoot.x = word.ptWord.x + word.fWidth;
    ptFoot.y = word.ptWord.y + word.fDescent;
  } else if (pIterator->GetLine(line)) {
    ptHead.x = line.ptLine.x;
    ptHead.y = line.ptLine.y + line.fLineAscent;
    ptFoot.x = line.ptLine.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 rcWord(wordinfo.ptWord.x,
                           lineinfo.ptLine.y + lineinfo.fLineDescent,
                           wordinfo.ptWord.x + wordinfo.fWidth,
                           lineinfo.ptLine.y + lineinfo.fLineAscent);

      if (notify_) {
        if (!notify_flag_) {
          AutoRestorer<bool> restorer(&notify_flag_);
          notify_flag_ = true;
          CFX_FloatRect rcRefresh = VTToEdit(rcWord);
          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.ptWord.x + word.fWidth;
        ptHead.y = word.ptWord.y + word.fAscent;
        ptFoot.x = word.ptWord.x + word.fWidth;
        ptFoot.y = word.ptWord.y + word.fDescent;
      } else if (pIterator->GetLine(line)) {
        ptHead.x = line.ptLine.x;
        ptHead.y = line.ptLine.y + line.fLineAscent;
        ptFoot.x = line.ptLine.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.nCharset));
  }
  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.nCharset, bSecEnd));
    } else {
      AddEditUndoItem(std::make_unique<UndoDelete>(
          this, wp_old_caret_, wp_caret_, word.Word, word.nCharset, 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>(this, false));
  bool is_insert_undo_clear = ClearSelection();
  // It is necessary to determine whether the value of `undo_remaining_` is 2 or
  // 3 based on ClearSelection().
  if (!is_insert_undo_clear) {
    undo_.GetLastAddItem()->set_undo_remaining(2);
  }
  // Select the inserted text.
  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>(this, true));
  if (!is_insert_undo_clear) {
    undo_.GetLastAddItem()->set_undo_remaining(2);
  }
}

void CPWL_EditImpl::ReplaceSelection(const WideString& text) {
  AddEditUndoItem(std::make_unique<UndoReplaceSelection>(this, false));
  bool is_insert_undo_clear = ClearSelection();
  // It is necessary to determine whether the value of `undo_remaining_` is 2 or
  // 3 based on ClearSelection().
  if (!is_insert_undo_clear) {
    undo_.GetLastAddItem()->set_undo_remaining(2);
  }
  InsertText(text, FX_Charset::kDefault);
  AddEditUndoItem(std::make_unique<UndoReplaceSelection>(this, true));
  if (!is_insert_undo_clear) {
    undo_.GetLastAddItem()->set_undo_remaining(2);
  }
}

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.ptWord.x + word.fWidth;
    caret_point_.y = word.ptWord.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::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* pFontMap = GetFontMap())
    return pFontMap->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* pFontMap = GetFontMap();
  RetainPtr<CPDF_Font> pPDFFont = pFontMap->GetPDFFont(nFontIndex);
  if (!pPDFFont)
    return ByteString();

  ByteString sWord;
  if (SubWord > 0) {
    Word = SubWord;
  } else {
    uint32_t dwCharCode = pPDFFont->IsUnicodeCompatible()
                              ? pPDFFont->CharCodeFromUnicode(Word)
                              : pFontMap->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;
}
