// Copyright 2014 PDFium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com

#include "fpdfsdk/include/fxedit/fxet_list.h"

#include "fpdfsdk/include/fxedit/fxet_edit.h"

CFX_ListItem::CFX_ListItem()
    : m_pEdit(NULL),
      m_bSelected(FALSE),
      m_bCaret(FALSE),
      m_rcListItem(0.0f, 0.0f, 0.0f, 0.0f) {
  m_pEdit = IFX_Edit::NewEdit();
  m_pEdit->SetAlignmentV(1);
  m_pEdit->Initialize();
}

CFX_ListItem::~CFX_ListItem() {
  IFX_Edit::DelEdit(m_pEdit);
}

void CFX_ListItem::SetFontMap(IFX_Edit_FontMap* pFontMap) {
  if (m_pEdit)
    m_pEdit->SetFontMap(pFontMap);
}

IFX_Edit* CFX_ListItem::GetEdit() const {
  return m_pEdit;
}

IFX_Edit_Iterator* CFX_ListItem::GetIterator() const {
  if (m_pEdit)
    return m_pEdit->GetIterator();

  return NULL;
}

void CFX_ListItem::SetRect(const CLST_Rect& rect) {
  m_rcListItem = rect;
}

CLST_Rect CFX_ListItem::GetRect() const {
  return m_rcListItem;
}

FX_BOOL CFX_ListItem::IsSelected() const {
  return m_bSelected;
}

void CFX_ListItem::SetSelect(FX_BOOL bSelected) {
  m_bSelected = bSelected;
}

FX_BOOL CFX_ListItem::IsCaret() const {
  return m_bCaret;
}

void CFX_ListItem::SetCaret(FX_BOOL bCaret) {
  m_bCaret = bCaret;
}

void CFX_ListItem::SetText(const FX_WCHAR* text) {
  if (m_pEdit)
    m_pEdit->SetText(text);
}

void CFX_ListItem::SetFontSize(FX_FLOAT fFontSize) {
  if (m_pEdit)
    m_pEdit->SetFontSize(fFontSize);
}

FX_FLOAT CFX_ListItem::GetItemHeight() const {
  if (m_pEdit)
    return m_pEdit->GetContentRect().Height();

  return 0.0f;
}

uint16_t CFX_ListItem::GetFirstChar() const {
  CPVT_Word word;

  if (IFX_Edit_Iterator* pIterator = GetIterator()) {
    pIterator->SetAt(1);
    pIterator->GetWord(word);
  }

  return word.Word;
}

CFX_WideString CFX_ListItem::GetText() const {
  if (m_pEdit)
    return m_pEdit->GetText();

  return L"";
}

CFX_List::CFX_List()
    : m_fFontSize(0.0f), m_pFontMap(NULL), m_bMultiple(FALSE) {}

CFX_List::~CFX_List() {
  Empty();
}

void CFX_List::Empty() {
  for (int32_t i = 0, sz = m_aListItems.GetSize(); i < sz; i++)
    delete m_aListItems.GetAt(i);

  m_aListItems.RemoveAll();
}

void CFX_List::SetFontMap(IFX_Edit_FontMap* pFontMap) {
  m_pFontMap = pFontMap;
}

void CFX_List::SetFontSize(FX_FLOAT fFontSize) {
  m_fFontSize = fFontSize;
}

void CFX_List::AddItem(const FX_WCHAR* str) {
  CFX_ListItem* pListItem = new CFX_ListItem();
  pListItem->SetFontMap(m_pFontMap);
  pListItem->SetFontSize(m_fFontSize);
  pListItem->SetText(str);
  m_aListItems.Add(pListItem);
}

void CFX_List::ReArrange(int32_t nItemIndex) {
  FX_FLOAT fPosY = 0.0f;

  if (CFX_ListItem* pPrevItem = m_aListItems.GetAt(nItemIndex - 1))
    fPosY = pPrevItem->GetRect().bottom;

  for (int32_t i = nItemIndex, sz = m_aListItems.GetSize(); i < sz; i++) {
    if (CFX_ListItem* pListItem = m_aListItems.GetAt(i)) {
      FX_FLOAT fListItemHeight = pListItem->GetItemHeight();
      pListItem->SetRect(CLST_Rect(0.0f, fPosY, 0.0f, fPosY + fListItemHeight));
      fPosY += fListItemHeight;
    }
  }

  SetContentRect(CLST_Rect(0.0f, 0.0f, 0.0f, fPosY));
}

IFX_Edit* CFX_List::GetItemEdit(int32_t nIndex) const {
  if (CFX_ListItem* pListItem = m_aListItems.GetAt(nIndex)) {
    return pListItem->GetEdit();
  }

  return NULL;
}

int32_t CFX_List::GetCount() const {
  return m_aListItems.GetSize();
}

CFX_FloatRect CFX_List::GetPlateRect() const {
  return CFX_ListContainer::GetPlateRect();
}

CFX_FloatRect CFX_List::GetContentRect() const {
  return InnerToOuter(CFX_ListContainer::GetContentRect());
}

FX_FLOAT CFX_List::GetFontSize() const {
  return m_fFontSize;
}

int32_t CFX_List::GetItemIndex(const CFX_FloatPoint& point) const {
  CFX_FloatPoint pt = OuterToInner(point);

  FX_BOOL bFirst = TRUE;
  FX_BOOL bLast = TRUE;

  for (int32_t i = 0, sz = m_aListItems.GetSize(); i < sz; i++) {
    if (CFX_ListItem* pListItem = m_aListItems.GetAt(i)) {
      CLST_Rect rcListItem = pListItem->GetRect();

      if (FX_EDIT_IsFloatBigger(pt.y, rcListItem.top)) {
        bFirst = FALSE;
      }

      if (FX_EDIT_IsFloatSmaller(pt.y, rcListItem.bottom)) {
        bLast = FALSE;
      }

      if (pt.y >= rcListItem.top && pt.y < rcListItem.bottom) {
        return i;
      }
    }
  }

  if (bFirst)
    return 0;
  if (bLast)
    return m_aListItems.GetSize() - 1;

  return -1;
}

FX_FLOAT CFX_List::GetFirstHeight() const {
  if (CFX_ListItem* pListItem = m_aListItems.GetAt(0)) {
    return pListItem->GetItemHeight();
  }

  return 1.0f;
}

int32_t CFX_List::GetFirstSelected() const {
  for (int32_t i = 0, sz = m_aListItems.GetSize(); i < sz; i++) {
    if (CFX_ListItem* pListItem = m_aListItems.GetAt(i)) {
      if (pListItem->IsSelected())
        return i;
    }
  }
  return -1;
}

int32_t CFX_List::GetLastSelected() const {
  for (int32_t i = m_aListItems.GetSize() - 1; i >= 0; i--) {
    if (CFX_ListItem* pListItem = m_aListItems.GetAt(i)) {
      if (pListItem->IsSelected())
        return i;
    }
  }
  return -1;
}

FX_WCHAR CFX_List::Toupper(FX_WCHAR c) const {
  if ((c >= 'a') && (c <= 'z'))
    c = c - ('a' - 'A');
  return c;
}

int32_t CFX_List::FindNext(int32_t nIndex, FX_WCHAR nChar) const {
  int32_t nCircleIndex = nIndex;

  for (int32_t i = 0, sz = m_aListItems.GetSize(); i < sz; i++) {
    nCircleIndex++;
    if (nCircleIndex >= sz)
      nCircleIndex = 0;

    if (CFX_ListItem* pListItem = m_aListItems.GetAt(nCircleIndex)) {
      if (Toupper(pListItem->GetFirstChar()) == Toupper(nChar))
        return nCircleIndex;
    }
  }

  return nCircleIndex;
}

CFX_FloatRect CFX_List::GetItemRect(int32_t nIndex) const {
  if (CFX_ListItem* pListItem = m_aListItems.GetAt(nIndex)) {
    CFX_FloatRect rcItem = pListItem->GetRect();
    rcItem.left = 0.0f;
    rcItem.right = GetPlateRect().Width();
    return InnerToOuter(rcItem);
  }

  return CFX_FloatRect();
}

FX_BOOL CFX_List::IsItemSelected(int32_t nIndex) const {
  if (CFX_ListItem* pListItem = m_aListItems.GetAt(nIndex)) {
    return pListItem->IsSelected();
  }

  return FALSE;
}

void CFX_List::SetItemSelect(int32_t nItemIndex, FX_BOOL bSelected) {
  if (CFX_ListItem* pListItem = m_aListItems.GetAt(nItemIndex)) {
    pListItem->SetSelect(bSelected);
  }
}

void CFX_List::SetItemCaret(int32_t nItemIndex, FX_BOOL bCaret) {
  if (CFX_ListItem* pListItem = m_aListItems.GetAt(nItemIndex)) {
    pListItem->SetCaret(bCaret);
  }
}

void CFX_List::SetMultipleSel(FX_BOOL bMultiple) {
  m_bMultiple = bMultiple;
}

FX_BOOL CFX_List::IsMultipleSel() const {
  return m_bMultiple;
}

FX_BOOL CFX_List::IsValid(int32_t nItemIndex) const {
  return nItemIndex >= 0 && nItemIndex < m_aListItems.GetSize();
}

CFX_WideString CFX_List::GetItemText(int32_t nIndex) const {
  if (CFX_ListItem* pListItem = m_aListItems.GetAt(nIndex)) {
    return pListItem->GetText();
  }

  return L"";
}

CPLST_Select::CPLST_Select() {}

CPLST_Select::~CPLST_Select() {
  for (int32_t i = 0, sz = m_aItems.GetSize(); i < sz; i++)
    delete m_aItems.GetAt(i);

  m_aItems.RemoveAll();
}

void CPLST_Select::Add(int32_t nItemIndex) {
  int32_t nIndex = Find(nItemIndex);

  if (nIndex < 0) {
    m_aItems.Add(new CPLST_Select_Item(nItemIndex, 1));
  } else {
    if (CPLST_Select_Item* pItem = m_aItems.GetAt(nIndex)) {
      pItem->nState = 1;
    }
  }
}

void CPLST_Select::Add(int32_t nBeginIndex, int32_t nEndIndex) {
  if (nBeginIndex > nEndIndex) {
    int32_t nTemp = nEndIndex;
    nEndIndex = nBeginIndex;
    nBeginIndex = nTemp;
  }

  for (int32_t i = nBeginIndex; i <= nEndIndex; i++)
    Add(i);
}

void CPLST_Select::Sub(int32_t nItemIndex) {
  for (int32_t i = m_aItems.GetSize() - 1; i >= 0; i--) {
    if (CPLST_Select_Item* pItem = m_aItems.GetAt(i))
      if (pItem->nItemIndex == nItemIndex)
        pItem->nState = -1;
  }
}

void CPLST_Select::Sub(int32_t nBeginIndex, int32_t nEndIndex) {
  if (nBeginIndex > nEndIndex) {
    int32_t nTemp = nEndIndex;
    nEndIndex = nBeginIndex;
    nBeginIndex = nTemp;
  }

  for (int32_t i = nBeginIndex; i <= nEndIndex; i++)
    Sub(i);
}

int32_t CPLST_Select::Find(int32_t nItemIndex) const {
  for (int32_t i = 0, sz = m_aItems.GetSize(); i < sz; i++) {
    if (CPLST_Select_Item* pItem = m_aItems.GetAt(i)) {
      if (pItem->nItemIndex == nItemIndex)
        return i;
    }
  }

  return -1;
}

FX_BOOL CPLST_Select::IsExist(int32_t nItemIndex) const {
  return Find(nItemIndex) >= 0;
}

int32_t CPLST_Select::GetCount() const {
  return m_aItems.GetSize();
}

int32_t CPLST_Select::GetItemIndex(int32_t nIndex) const {
  if (nIndex >= 0 && nIndex < m_aItems.GetSize())
    if (CPLST_Select_Item* pItem = m_aItems.GetAt(nIndex))
      return pItem->nItemIndex;

  return -1;
}

int32_t CPLST_Select::GetState(int32_t nIndex) const {
  if (nIndex >= 0 && nIndex < m_aItems.GetSize())
    if (CPLST_Select_Item* pItem = m_aItems.GetAt(nIndex))
      return pItem->nState;

  return 0;
}

void CPLST_Select::DeselectAll() {
  for (int32_t i = 0, sz = m_aItems.GetSize(); i < sz; i++) {
    if (CPLST_Select_Item* pItem = m_aItems.GetAt(i)) {
      pItem->nState = -1;
    }
  }
}

void CPLST_Select::Done() {
  for (int32_t i = m_aItems.GetSize() - 1; i >= 0; i--) {
    if (CPLST_Select_Item* pItem = m_aItems.GetAt(i)) {
      if (pItem->nState == -1) {
        delete pItem;
        m_aItems.RemoveAt(i);
      } else {
        pItem->nState = 0;
      }
    }
  }
}

CFX_ListCtrl::CFX_ListCtrl()
    : m_pNotify(NULL),
      m_bNotifyFlag(FALSE),
      m_ptScrollPos(0.0f, 0.0f),
      m_nSelItem(-1),
      m_nFootIndex(-1),
      m_bCtrlSel(FALSE),
      m_nCaretIndex(-1) {}

CFX_ListCtrl::~CFX_ListCtrl() {}

void CFX_ListCtrl::SetNotify(IFX_List_Notify* pNotify) {
  m_pNotify = pNotify;
}

CFX_FloatPoint CFX_ListCtrl::InToOut(const CFX_FloatPoint& point) const {
  CFX_FloatRect rcPlate = GetPlateRect();

  return CFX_FloatPoint(point.x - (m_ptScrollPos.x - rcPlate.left),
                        point.y - (m_ptScrollPos.y - rcPlate.top));
}

CFX_FloatPoint CFX_ListCtrl::OutToIn(const CFX_FloatPoint& point) const {
  CFX_FloatRect rcPlate = GetPlateRect();

  return CFX_FloatPoint(point.x + (m_ptScrollPos.x - rcPlate.left),
                        point.y + (m_ptScrollPos.y - rcPlate.top));
}

CFX_FloatRect CFX_ListCtrl::InToOut(const CFX_FloatRect& rect) const {
  CFX_FloatPoint ptLeftBottom = InToOut(CFX_FloatPoint(rect.left, rect.bottom));
  CFX_FloatPoint ptRightTop = InToOut(CFX_FloatPoint(rect.right, rect.top));

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

CFX_FloatRect CFX_ListCtrl::OutToIn(const CFX_FloatRect& rect) const {
  CFX_FloatPoint ptLeftBottom = OutToIn(CFX_FloatPoint(rect.left, rect.bottom));
  CFX_FloatPoint ptRightTop = OutToIn(CFX_FloatPoint(rect.right, rect.top));

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

void CFX_ListCtrl::OnMouseDown(const CFX_FloatPoint& point,
                               FX_BOOL bShift,
                               FX_BOOL bCtrl) {
  int32_t nHitIndex = GetItemIndex(point);

  if (IsMultipleSel()) {
    if (bCtrl) {
      if (IsItemSelected(nHitIndex)) {
        m_aSelItems.Sub(nHitIndex);
        SelectItems();
        m_bCtrlSel = FALSE;
      } else {
        m_aSelItems.Add(nHitIndex);
        SelectItems();
        m_bCtrlSel = TRUE;
      }

      m_nFootIndex = nHitIndex;
    } else if (bShift) {
      m_aSelItems.DeselectAll();
      m_aSelItems.Add(m_nFootIndex, nHitIndex);
      SelectItems();
    } else {
      m_aSelItems.DeselectAll();
      m_aSelItems.Add(nHitIndex);
      SelectItems();

      m_nFootIndex = nHitIndex;
    }

    SetCaret(nHitIndex);
  } else {
    SetSingleSelect(nHitIndex);
  }

  if (!IsItemVisible(nHitIndex))
    ScrollToListItem(nHitIndex);
}

void CFX_ListCtrl::OnMouseMove(const CFX_FloatPoint& point,
                               FX_BOOL bShift,
                               FX_BOOL bCtrl) {
  int32_t nHitIndex = GetItemIndex(point);

  if (IsMultipleSel()) {
    if (bCtrl) {
      if (m_bCtrlSel)
        m_aSelItems.Add(m_nFootIndex, nHitIndex);
      else
        m_aSelItems.Sub(m_nFootIndex, nHitIndex);

      SelectItems();
    } else {
      m_aSelItems.DeselectAll();
      m_aSelItems.Add(m_nFootIndex, nHitIndex);
      SelectItems();
    }

    SetCaret(nHitIndex);
  } else {
    SetSingleSelect(nHitIndex);
  }

  if (!IsItemVisible(nHitIndex))
    ScrollToListItem(nHitIndex);
}

void CFX_ListCtrl::OnVK(int32_t nItemIndex, FX_BOOL bShift, FX_BOOL bCtrl) {
  if (IsMultipleSel()) {
    if (nItemIndex >= 0 && nItemIndex < GetCount()) {
      if (bCtrl) {
      } else if (bShift) {
        m_aSelItems.DeselectAll();
        m_aSelItems.Add(m_nFootIndex, nItemIndex);
        SelectItems();
      } else {
        m_aSelItems.DeselectAll();
        m_aSelItems.Add(nItemIndex);
        SelectItems();
        m_nFootIndex = nItemIndex;
      }

      SetCaret(nItemIndex);
    }
  } else {
    SetSingleSelect(nItemIndex);
  }

  if (!IsItemVisible(nItemIndex))
    ScrollToListItem(nItemIndex);
}

void CFX_ListCtrl::OnVK_UP(FX_BOOL bShift, FX_BOOL bCtrl) {
  OnVK(IsMultipleSel() ? GetCaret() - 1 : GetSelect() - 1, bShift, bCtrl);
}

void CFX_ListCtrl::OnVK_DOWN(FX_BOOL bShift, FX_BOOL bCtrl) {
  OnVK(IsMultipleSel() ? GetCaret() + 1 : GetSelect() + 1, bShift, bCtrl);
}

void CFX_ListCtrl::OnVK_LEFT(FX_BOOL bShift, FX_BOOL bCtrl) {
  OnVK(0, bShift, bCtrl);
}

void CFX_ListCtrl::OnVK_RIGHT(FX_BOOL bShift, FX_BOOL bCtrl) {
  OnVK(GetCount() - 1, bShift, bCtrl);
}

void CFX_ListCtrl::OnVK_HOME(FX_BOOL bShift, FX_BOOL bCtrl) {
  OnVK(0, bShift, bCtrl);
}

void CFX_ListCtrl::OnVK_END(FX_BOOL bShift, FX_BOOL bCtrl) {
  OnVK(GetCount() - 1, bShift, bCtrl);
}

FX_BOOL CFX_ListCtrl::OnChar(uint16_t nChar, FX_BOOL bShift, FX_BOOL bCtrl) {
  int32_t nIndex = GetLastSelected();
  int32_t nFindIndex = FindNext(nIndex, nChar);

  if (nFindIndex != nIndex) {
    OnVK(nFindIndex, bShift, bCtrl);
    return TRUE;
  }
  return FALSE;
}

void CFX_ListCtrl::SetPlateRect(const CFX_FloatRect& rect) {
  CFX_ListContainer::SetPlateRect(rect);
  m_ptScrollPos.x = rect.left;
  SetScrollPos(CFX_FloatPoint(rect.left, rect.top));
  ReArrange(0);
  InvalidateItem(-1);
}

CFX_FloatRect CFX_ListCtrl::GetItemRect(int32_t nIndex) const {
  return InToOut(CFX_List::GetItemRect(nIndex));
}

void CFX_ListCtrl::AddString(const FX_WCHAR* str) {
  AddItem(str);
  ReArrange(GetCount() - 1);
}

void CFX_ListCtrl::SetMultipleSelect(int32_t nItemIndex, FX_BOOL bSelected) {
  if (!IsValid(nItemIndex))
    return;

  if (bSelected != IsItemSelected(nItemIndex)) {
    if (bSelected) {
      SetItemSelect(nItemIndex, TRUE);
      InvalidateItem(nItemIndex);
    } else {
      SetItemSelect(nItemIndex, FALSE);
      InvalidateItem(nItemIndex);
    }
  }
}

void CFX_ListCtrl::SetSingleSelect(int32_t nItemIndex) {
  if (!IsValid(nItemIndex))
    return;

  if (m_nSelItem != nItemIndex) {
    if (m_nSelItem >= 0) {
      SetItemSelect(m_nSelItem, FALSE);
      InvalidateItem(m_nSelItem);
    }

    SetItemSelect(nItemIndex, TRUE);
    InvalidateItem(nItemIndex);
    m_nSelItem = nItemIndex;
  }
}

void CFX_ListCtrl::SetCaret(int32_t nItemIndex) {
  if (!IsValid(nItemIndex))
    return;

  if (IsMultipleSel()) {
    int32_t nOldIndex = m_nCaretIndex;

    if (nOldIndex != nItemIndex) {
      m_nCaretIndex = nItemIndex;

      SetItemCaret(nOldIndex, FALSE);
      SetItemCaret(nItemIndex, TRUE);

      InvalidateItem(nOldIndex);
      InvalidateItem(nItemIndex);
    }
  }
}

void CFX_ListCtrl::InvalidateItem(int32_t nItemIndex) {
  if (m_pNotify) {
    if (nItemIndex == -1) {
      if (!m_bNotifyFlag) {
        m_bNotifyFlag = TRUE;
        CFX_FloatRect rcRefresh = GetPlateRect();
        m_pNotify->IOnInvalidateRect(&rcRefresh);
        m_bNotifyFlag = FALSE;
      }
    } else {
      if (!m_bNotifyFlag) {
        m_bNotifyFlag = TRUE;
        CFX_FloatRect rcRefresh = GetItemRect(nItemIndex);
        rcRefresh.left -= 1.0f;
        rcRefresh.right += 1.0f;
        rcRefresh.bottom -= 1.0f;
        rcRefresh.top += 1.0f;

        m_pNotify->IOnInvalidateRect(&rcRefresh);
        m_bNotifyFlag = FALSE;
      }
    }
  }
}

void CFX_ListCtrl::SelectItems() {
  for (int32_t i = 0, sz = m_aSelItems.GetCount(); i < sz; i++) {
    int32_t nItemIndex = m_aSelItems.GetItemIndex(i);
    int32_t nState = m_aSelItems.GetState(i);

    switch (nState) {
      case 1:
        SetMultipleSelect(nItemIndex, TRUE);
        break;
      case -1:
        SetMultipleSelect(nItemIndex, FALSE);
        break;
    }
  }

  m_aSelItems.Done();
}

void CFX_ListCtrl::Select(int32_t nItemIndex) {
  if (!IsValid(nItemIndex))
    return;

  if (IsMultipleSel()) {
    m_aSelItems.Add(nItemIndex);
    SelectItems();
  } else {
    SetSingleSelect(nItemIndex);
  }
}

FX_BOOL CFX_ListCtrl::IsItemVisible(int32_t nItemIndex) const {
  CFX_FloatRect rcPlate = GetPlateRect();
  CFX_FloatRect rcItem = GetItemRect(nItemIndex);

  return rcItem.bottom >= rcPlate.bottom && rcItem.top <= rcPlate.top;
}

void CFX_ListCtrl::ScrollToListItem(int32_t nItemIndex) {
  if (!IsValid(nItemIndex))
    return;

  CFX_FloatRect rcPlate = GetPlateRect();
  CFX_FloatRect rcItem = CFX_List::GetItemRect(nItemIndex);
  CFX_FloatRect rcItemCtrl = GetItemRect(nItemIndex);

  if (FX_EDIT_IsFloatSmaller(rcItemCtrl.bottom, rcPlate.bottom)) {
    if (FX_EDIT_IsFloatSmaller(rcItemCtrl.top, rcPlate.top)) {
      SetScrollPosY(rcItem.bottom + rcPlate.Height());
    }
  } else if (FX_EDIT_IsFloatBigger(rcItemCtrl.top, rcPlate.top)) {
    if (FX_EDIT_IsFloatBigger(rcItemCtrl.bottom, rcPlate.bottom)) {
      SetScrollPosY(rcItem.top);
    }
  }
}

void CFX_ListCtrl::SetScrollInfo() {
  if (m_pNotify) {
    CFX_FloatRect rcPlate = GetPlateRect();
    CFX_FloatRect rcContent = CFX_List::GetContentRect();

    if (!m_bNotifyFlag) {
      m_bNotifyFlag = TRUE;
      m_pNotify->IOnSetScrollInfoY(rcPlate.bottom, rcPlate.top,
                                   rcContent.bottom, rcContent.top,
                                   GetFirstHeight(), rcPlate.Height());
      m_bNotifyFlag = FALSE;
    }
  }
}

void CFX_ListCtrl::SetScrollPos(const CFX_FloatPoint& point) {
  SetScrollPosY(point.y);
}

void CFX_ListCtrl::SetScrollPosY(FX_FLOAT fy) {
  if (!FX_EDIT_IsFloatEqual(m_ptScrollPos.y, fy)) {
    CFX_FloatRect rcPlate = GetPlateRect();
    CFX_FloatRect rcContent = CFX_List::GetContentRect();

    if (rcPlate.Height() > rcContent.Height()) {
      fy = rcPlate.top;
    } else {
      if (FX_EDIT_IsFloatSmaller(fy - rcPlate.Height(), rcContent.bottom)) {
        fy = rcContent.bottom + rcPlate.Height();
      } else if (FX_EDIT_IsFloatBigger(fy, rcContent.top)) {
        fy = rcContent.top;
      }
    }

    m_ptScrollPos.y = fy;
    InvalidateItem(-1);

    if (m_pNotify) {
      if (!m_bNotifyFlag) {
        m_bNotifyFlag = TRUE;
        m_pNotify->IOnSetScrollPosY(fy);
        m_bNotifyFlag = FALSE;
      }
    }
  }
}

CFX_FloatRect CFX_ListCtrl::GetContentRect() const {
  return InToOut(CFX_List::GetContentRect());
}

void CFX_ListCtrl::ReArrange(int32_t nItemIndex) {
  CFX_List::ReArrange(nItemIndex);
  SetScrollInfo();
}

void CFX_ListCtrl::SetTopItem(int32_t nIndex) {
  if (IsValid(nIndex)) {
    GetPlateRect();
    CFX_FloatRect rcItem = CFX_List::GetItemRect(nIndex);
    SetScrollPosY(rcItem.top);
  }
}

int32_t CFX_ListCtrl::GetTopItem() const {
  int32_t nItemIndex = GetItemIndex(GetBTPoint());

  if (!IsItemVisible(nItemIndex) && IsItemVisible(nItemIndex + 1))
    nItemIndex += 1;

  return nItemIndex;
}

void CFX_ListCtrl::Empty() {
  CFX_List::Empty();
  InvalidateItem(-1);
}

void CFX_ListCtrl::Cancel() {
  m_aSelItems.DeselectAll();
}

int32_t CFX_ListCtrl::GetItemIndex(const CFX_FloatPoint& point) const {
  return CFX_List::GetItemIndex(OutToIn(point));
}

CFX_WideString CFX_ListCtrl::GetText() const {
  if (IsMultipleSel())
    return GetItemText(m_nCaretIndex);
  return GetItemText(m_nSelItem);
}
