Get rid of g_timeMap global object.
[pdfium.git] / fpdfsdk / src / fxedit / fxet_list.cpp
index dd70e0c..64ed694 100644 (file)
-// Copyright 2014 PDFium Authors. All rights reserved.\r
-// Use of this source code is governed by a BSD-style license that can be\r
-// found in the LICENSE file.\r
\r
-// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com\r
-\r
-#include "../../include/fxedit/fxet_stub.h"\r
-#include "../../include/fxedit/fxet_edit.h"\r
-#include "../../include/fxedit/fxet_list.h"\r
-\r
-/* ------------------------------- CFX_ListItem ---------------------------------- */\r
-\r
-CFX_ListItem::CFX_ListItem() : m_pEdit(NULL),\r
-       m_bSelected(FALSE),\r
-       m_bCaret(FALSE),\r
-       m_rcListItem(0.0f,0.0f,0.0f,0.0f)\r
-{\r
-       m_pEdit = IFX_Edit::NewEdit();\r
-       ASSERT(m_pEdit != NULL);\r
-\r
-       m_pEdit->SetAlignmentV(1);\r
-       m_pEdit->Initialize();\r
-}\r
-\r
-CFX_ListItem::~CFX_ListItem()\r
-{\r
-       IFX_Edit::DelEdit(m_pEdit);\r
-}\r
-\r
-void CFX_ListItem::SetFontMap(IFX_Edit_FontMap * pFontMap)\r
-{\r
-       if (m_pEdit)\r
-               m_pEdit->SetFontMap(pFontMap);\r
-}\r
-\r
-IFX_Edit* CFX_ListItem::GetEdit() const\r
-{\r
-       return m_pEdit;\r
-}\r
-\r
-IFX_Edit_Iterator*     CFX_ListItem::GetIterator() const\r
-{\r
-       if (m_pEdit)\r
-               return m_pEdit->GetIterator();\r
-\r
-       return NULL;\r
-}\r
-\r
-void CFX_ListItem::SetRect(const CLST_Rect & rect)\r
-{\r
-       m_rcListItem = rect;\r
-}\r
-\r
-CLST_Rect CFX_ListItem::GetRect() const\r
-{\r
-       return m_rcListItem;\r
-}\r
-\r
-FX_BOOL CFX_ListItem::IsSelected() const\r
-{\r
-       return m_bSelected;\r
-}\r
-\r
-void CFX_ListItem::SetSelect(FX_BOOL bSelected)\r
-{\r
-       m_bSelected = bSelected;\r
-}\r
-\r
-FX_BOOL CFX_ListItem::IsCaret() const\r
-{\r
-       return m_bCaret;\r
-}\r
-\r
-void CFX_ListItem::SetCaret(FX_BOOL bCaret)\r
-{\r
-       m_bCaret = bCaret;\r
-}\r
-\r
-void CFX_ListItem::SetText(FX_LPCWSTR text)\r
-{\r
-       if (m_pEdit)\r
-               m_pEdit->SetText(text);\r
-}\r
-\r
-void CFX_ListItem::SetFontSize(FX_FLOAT fFontSize)\r
-{\r
-       if (m_pEdit)\r
-               m_pEdit->SetFontSize(fFontSize);\r
-}\r
-\r
-FX_FLOAT CFX_ListItem::GetItemHeight() const\r
-{\r
-       if (m_pEdit)\r
-               return m_pEdit->GetContentRect().Height();\r
-\r
-       return 0.0f;\r
-}\r
-\r
-FX_WORD CFX_ListItem::GetFirstChar() const\r
-{\r
-       CPVT_Word word;\r
-\r
-       if (IFX_Edit_Iterator*  pIterator = GetIterator())\r
-       {\r
-               pIterator->SetAt(1);            \r
-               pIterator->GetWord(word);\r
-       }\r
-\r
-       return word.Word;\r
-}\r
-\r
-CFX_WideString CFX_ListItem::GetText() const\r
-{\r
-       if (m_pEdit)\r
-               return m_pEdit->GetText();\r
-\r
-       return L"";\r
-}\r
-\r
-/* ------------------------------------ CFX_List --------------------------------- */\r
-\r
-CFX_List::CFX_List() : m_pFontMap(NULL), m_fFontSize(0.0f), m_bMultiple(FALSE) \r
-{\r
-}\r
-\r
-CFX_List::~CFX_List()\r
-{\r
-       Empty();\r
-}\r
-\r
-void CFX_List::Empty()\r
-{\r
-       for (FX_INT32 i=0,sz=m_aListItems.GetSize(); i<sz; i++)\r
-               delete m_aListItems.GetAt(i);\r
-\r
-       m_aListItems.RemoveAll();\r
-}\r
-\r
-void CFX_List::SetFontMap(IFX_Edit_FontMap * pFontMap)\r
-{\r
-       m_pFontMap = pFontMap;\r
-}\r
-\r
-void CFX_List::SetFontSize(FX_FLOAT fFontSize)\r
-{\r
-       m_fFontSize = fFontSize;\r
-}\r
-\r
-void CFX_List::AddItem(FX_LPCWSTR str)\r
-{      \r
-       if (CFX_ListItem * pListItem = new CFX_ListItem())\r
-       {\r
-               pListItem->SetFontMap(m_pFontMap);\r
-               pListItem->SetFontSize(m_fFontSize);\r
-               pListItem->SetText(str);\r
-               m_aListItems.Add(pListItem);\r
-       }\r
-}\r
-\r
-void CFX_List::ReArrange(FX_INT32 nItemIndex)\r
-{\r
-       FX_FLOAT fPosY = 0.0f;\r
-\r
-       if (CFX_ListItem * pPrevItem = m_aListItems.GetAt(nItemIndex - 1))\r
-               fPosY = pPrevItem->GetRect().bottom;\r
-       \r
-       for (FX_INT32 i=nItemIndex,sz=m_aListItems.GetSize(); i<sz; i++)\r
-       {\r
-               if (CFX_ListItem * pListItem = m_aListItems.GetAt(i))\r
-               {\r
-                       FX_FLOAT fListItemHeight = pListItem->GetItemHeight();\r
-                       pListItem->SetRect(CLST_Rect(0.0f,fPosY,0.0f,fPosY + fListItemHeight));\r
-                       fPosY += fListItemHeight;                       \r
-               }\r
-       }\r
-\r
-       SetContentRect(CLST_Rect(0.0f,0.0f,0.0f,fPosY));        \r
-}\r
-\r
-IFX_Edit * CFX_List::GetItemEdit(FX_INT32 nIndex) const\r
-{\r
-       if (CFX_ListItem * pListItem = m_aListItems.GetAt(nIndex))\r
-       {\r
-               return pListItem->GetEdit();\r
-       }\r
-\r
-       return NULL;\r
-}\r
-\r
-FX_INT32 CFX_List::GetCount() const\r
-{\r
-       return m_aListItems.GetSize();\r
-}\r
-\r
-CPDF_Rect CFX_List::GetPlateRect() const\r
-{\r
-       return CFX_ListContainer::GetPlateRect();\r
-}\r
-\r
-CPDF_Rect CFX_List::GetContentRect() const\r
-{\r
-       return InnerToOuter(CFX_ListContainer::GetContentRect());\r
-}\r
-\r
-FX_FLOAT CFX_List::GetFontSize() const\r
-{\r
-       return m_fFontSize;\r
-}\r
-\r
-FX_INT32 CFX_List::GetItemIndex(const CPDF_Point & point) const\r
-{\r
-       CPDF_Point pt = OuterToInner(point);\r
-\r
-       FX_BOOL bFirst = TRUE;\r
-       FX_BOOL bLast = TRUE;\r
-\r
-       for (FX_INT32 i=0,sz=m_aListItems.GetSize(); i<sz; i++)\r
-       {\r
-               if (CFX_ListItem * pListItem = m_aListItems.GetAt(i))\r
-               {\r
-                       CLST_Rect rcListItem = pListItem->GetRect();\r
-\r
-                       if (FX_EDIT_IsFloatBigger(pt.y, rcListItem.top))\r
-                       {                       \r
-                               bFirst = FALSE;\r
-                       }\r
-\r
-                       if (FX_EDIT_IsFloatSmaller(pt.y, rcListItem.bottom))\r
-                       {\r
-                               bLast = FALSE;\r
-                       }\r
-\r
-                       if (pt.y >= rcListItem.top && pt.y < rcListItem.bottom)\r
-                       {\r
-                               return i;\r
-                       }\r
-               }\r
-       }\r
-\r
-       if (bFirst) return 0;\r
-       if (bLast) return m_aListItems.GetSize()-1;\r
-\r
-       return -1;\r
-}\r
-\r
-FX_FLOAT CFX_List::GetFirstHeight() const\r
-{\r
-       if (CFX_ListItem * pListItem = m_aListItems.GetAt(0))\r
-       {\r
-               return pListItem->GetItemHeight();\r
-       }\r
-\r
-       return 1.0f;\r
-}\r
-\r
-FX_INT32 CFX_List::GetFirstSelected() const\r
-{\r
-       for (FX_INT32 i=0,sz=m_aListItems.GetSize(); i<sz; i++)\r
-       {\r
-               if (CFX_ListItem * pListItem = m_aListItems.GetAt(i))\r
-               {\r
-                       if (pListItem->IsSelected())\r
-                               return i;\r
-               }\r
-       }\r
-       return -1;\r
-}\r
-\r
-FX_INT32 CFX_List::GetLastSelected() const\r
-{\r
-       for (FX_INT32 i=m_aListItems.GetSize()-1; i>=0; i--)\r
-       {\r
-               if (CFX_ListItem * pListItem = m_aListItems.GetAt(i))\r
-               {\r
-                       if (pListItem->IsSelected())\r
-                               return i;\r
-               }\r
-       }\r
-       return -1;\r
-}\r
-\r
-FX_WCHAR CFX_List::Toupper(FX_WCHAR c) const\r
-{\r
-       if ( (c >= 'a') && (c <= 'z') )\r
-               c = c - ('a' - 'A');\r
-       return c;\r
-}\r
-\r
-FX_INT32 CFX_List::FindNext(FX_INT32 nIndex,FX_WCHAR nChar) const\r
-{\r
-       FX_INT32 nCircleIndex = nIndex;\r
-\r
-       for (FX_INT32 i=0,sz=m_aListItems.GetSize(); i<sz; i++)\r
-       {\r
-               nCircleIndex ++;\r
-               if (nCircleIndex >= sz) nCircleIndex = 0;\r
-\r
-               if (CFX_ListItem * pListItem = m_aListItems.GetAt(nCircleIndex))\r
-               {\r
-                       if (Toupper(pListItem->GetFirstChar()) == Toupper(nChar))\r
-                               return nCircleIndex;\r
-               }\r
-       }\r
-\r
-       return nCircleIndex;\r
-}\r
-\r
-CPDF_Rect CFX_List::GetItemRect(FX_INT32 nIndex) const\r
-{\r
-       if (CFX_ListItem * pListItem = m_aListItems.GetAt(nIndex))\r
-       {\r
-               CPDF_Rect rcItem = pListItem->GetRect();\r
-               rcItem.left = 0.0f;\r
-               rcItem.right = GetPlateRect().Width();\r
-               return InnerToOuter(rcItem);\r
-       }\r
-\r
-       return CPDF_Rect();\r
-}\r
-\r
-FX_BOOL CFX_List::IsItemSelected(FX_INT32 nIndex) const\r
-{\r
-       if (CFX_ListItem * pListItem = m_aListItems.GetAt(nIndex))\r
-       {\r
-               return pListItem->IsSelected();\r
-       }\r
-\r
-       return FALSE;\r
-}\r
-\r
-void CFX_List::SetItemSelect(FX_INT32 nItemIndex, FX_BOOL bSelected)\r
-{\r
-       if (CFX_ListItem * pListItem = m_aListItems.GetAt(nItemIndex))\r
-       {\r
-               pListItem->SetSelect(bSelected);\r
-       }\r
-}\r
-\r
-void CFX_List::SetItemCaret(FX_INT32 nItemIndex, FX_BOOL bCaret)\r
-{\r
-       if (CFX_ListItem * pListItem = m_aListItems.GetAt(nItemIndex))\r
-       {\r
-               pListItem->SetCaret(bCaret);            \r
-       }\r
-}\r
-\r
-void CFX_List::SetMultipleSel(FX_BOOL bMultiple)\r
-{\r
-       m_bMultiple = bMultiple;\r
-}\r
-\r
-FX_BOOL CFX_List::IsMultipleSel() const\r
-{\r
-       return m_bMultiple;\r
-}\r
-\r
-FX_BOOL CFX_List::IsValid(FX_INT32 nItemIndex) const\r
-{\r
-       return nItemIndex >= 0 && nItemIndex < m_aListItems.GetSize();\r
-}\r
-\r
-CFX_WideString CFX_List::GetItemText(FX_INT32 nIndex) const\r
-{\r
-       if (CFX_ListItem * pListItem = m_aListItems.GetAt(nIndex))\r
-       {\r
-               return pListItem->GetText();\r
-       }\r
-\r
-       return L"";\r
-}\r
-\r
-/* ------------------------------------ CPLST_Select ---------------------------------- */\r
-\r
-CPLST_Select::CPLST_Select()\r
-{\r
-}\r
-\r
-CPLST_Select::~CPLST_Select()\r
-{\r
-       for (FX_INT32 i=0,sz=m_aItems.GetSize(); i<sz; i++)\r
-               delete m_aItems.GetAt(i);\r
-\r
-       m_aItems.RemoveAll();\r
-}\r
-\r
-void CPLST_Select::Add(FX_INT32 nItemIndex)\r
-{\r
-       FX_INT32 nIndex = Find(nItemIndex);\r
-\r
-       if (nIndex < 0) \r
-               m_aItems.Add(new CPLST_Select_Item(nItemIndex,1));\r
-       else\r
-       {\r
-               if (CPLST_Select_Item * pItem = m_aItems.GetAt(nIndex))\r
-               {\r
-                       pItem->nState = 1;\r
-               }\r
-       }\r
-}\r
-\r
-void CPLST_Select::Add(FX_INT32 nBeginIndex, FX_INT32 nEndIndex)\r
-{\r
-       if (nBeginIndex > nEndIndex)\r
-       {\r
-               FX_INT32 nTemp = nEndIndex;\r
-               nEndIndex = nBeginIndex;\r
-               nBeginIndex = nTemp;\r
-       }\r
-\r
-       for (FX_INT32 i=nBeginIndex; i<=nEndIndex; i++) Add(i);\r
-}\r
-\r
-void CPLST_Select::Sub(FX_INT32 nItemIndex)\r
-{\r
-       for (FX_INT32 i=m_aItems.GetSize()-1; i>=0; i--)\r
-       {\r
-               if (CPLST_Select_Item * pItem = m_aItems.GetAt(i))\r
-                       if (pItem->nItemIndex == nItemIndex)\r
-                               pItem->nState = -1;\r
-       }\r
-}\r
-\r
-void CPLST_Select::Sub(FX_INT32 nBeginIndex, FX_INT32 nEndIndex)\r
-{\r
-       if (nBeginIndex > nEndIndex)\r
-       {\r
-               FX_INT32 nTemp = nEndIndex;\r
-               nEndIndex = nBeginIndex;\r
-               nBeginIndex = nTemp;\r
-       }\r
-\r
-       for (FX_INT32 i=nBeginIndex; i<=nEndIndex; i++) Sub(i);\r
-}\r
-\r
-FX_INT32 CPLST_Select::Find(FX_INT32 nItemIndex) const\r
-{\r
-       for (FX_INT32 i=0,sz=m_aItems.GetSize(); i<sz; i++)\r
-       {\r
-               if (CPLST_Select_Item * pItem = m_aItems.GetAt(i))\r
-               {\r
-                       if (pItem->nItemIndex == nItemIndex)\r
-                               return i;\r
-               }\r
-       }\r
-\r
-       return -1;\r
-}\r
-\r
-FX_BOOL CPLST_Select::IsExist(FX_INT32 nItemIndex) const\r
-{\r
-       return Find(nItemIndex) >= 0;\r
-}\r
-\r
-FX_INT32 CPLST_Select::GetCount() const\r
-{\r
-       return m_aItems.GetSize();\r
-}\r
-\r
-FX_INT32 CPLST_Select::GetItemIndex(FX_INT32 nIndex) const\r
-{\r
-       if (nIndex >= 0 && nIndex < m_aItems.GetSize())\r
-               if (CPLST_Select_Item * pItem = m_aItems.GetAt(nIndex))\r
-                       return pItem->nItemIndex;\r
-\r
-       return -1;\r
-}\r
-\r
-FX_INT32 CPLST_Select::GetState(FX_INT32 nIndex) const\r
-{\r
-       if (nIndex >= 0 && nIndex < m_aItems.GetSize())\r
-               if (CPLST_Select_Item * pItem = m_aItems.GetAt(nIndex))\r
-                       return pItem->nState;\r
-\r
-       return 0;\r
-}\r
-\r
-void CPLST_Select::DeselectAll()\r
-{\r
-       for (FX_INT32 i=0,sz=m_aItems.GetSize(); i<sz; i++)\r
-       {\r
-               if (CPLST_Select_Item * pItem = m_aItems.GetAt(i))\r
-               {\r
-                       pItem->nState = -1;\r
-               }\r
-       }\r
-}\r
-\r
-void CPLST_Select::Done()\r
-{\r
-       for (FX_INT32 i=m_aItems.GetSize()-1; i>=0; i--)\r
-       {       \r
-               if (CPLST_Select_Item * pItem = m_aItems.GetAt(i))\r
-               {\r
-                       if (pItem->nState == -1)\r
-                       {\r
-                               delete pItem;\r
-                               m_aItems.RemoveAt(i);\r
-                       }\r
-                       else\r
-                       {\r
-                               pItem->nState = 0;\r
-                       }\r
-               }\r
-       }\r
-}\r
-\r
-/* ------------------------------------ CFX_ListCtrl --------------------------------- */\r
-\r
-CFX_ListCtrl::CFX_ListCtrl() : m_pNotify(NULL),\r
-       m_ptScrollPos(0.0f,0.0f),\r
-       m_nSelItem(-1),\r
-       m_nFootIndex(-1),\r
-       m_bCtrlSel(FALSE),      \r
-       m_nCaretIndex(-1),\r
-       m_bNotifyFlag(FALSE)\r
-{\r
-}\r
-\r
-CFX_ListCtrl::~CFX_ListCtrl()\r
-{\r
-}\r
-\r
-void CFX_ListCtrl::SetNotify(IFX_List_Notify * pNotify)\r
-{\r
-       m_pNotify = pNotify;\r
-}\r
-\r
-CPDF_Point CFX_ListCtrl::InToOut(const CPDF_Point & point) const\r
-{\r
-       CPDF_Rect rcPlate = GetPlateRect();\r
-\r
-       return CPDF_Point(point.x - (m_ptScrollPos.x - rcPlate.left),\r
-               point.y - (m_ptScrollPos.y - rcPlate.top));\r
-}\r
-\r
-CPDF_Point CFX_ListCtrl::OutToIn(const CPDF_Point & point) const\r
-{\r
-       CPDF_Rect rcPlate = GetPlateRect();\r
-\r
-       return CPDF_Point(point.x + (m_ptScrollPos.x - rcPlate.left),\r
-               point.y + (m_ptScrollPos.y - rcPlate.top));\r
-}\r
-\r
-CPDF_Rect CFX_ListCtrl::InToOut(const CPDF_Rect & rect) const\r
-{\r
-       CPDF_Point ptLeftBottom = InToOut(CPDF_Point(rect.left,rect.bottom));\r
-       CPDF_Point ptRightTop = InToOut(CPDF_Point(rect.right,rect.top));\r
-\r
-       return CPDF_Rect(ptLeftBottom.x,ptLeftBottom.y,ptRightTop.x,ptRightTop.y);\r
-}\r
-\r
-CPDF_Rect CFX_ListCtrl::OutToIn(const CPDF_Rect & rect) const\r
-{\r
-       CPDF_Point ptLeftBottom = OutToIn(CPDF_Point(rect.left,rect.bottom));\r
-       CPDF_Point ptRightTop = OutToIn(CPDF_Point(rect.right,rect.top));\r
-\r
-       return CPDF_Rect(ptLeftBottom.x,ptLeftBottom.y,ptRightTop.x,ptRightTop.y);\r
-}\r
-\r
-void CFX_ListCtrl::OnMouseDown(const CPDF_Point & point,FX_BOOL bShift,FX_BOOL bCtrl)\r
-{\r
-       FX_INT32 nHitIndex = this->GetItemIndex(point);\r
-\r
-       if (IsMultipleSel())\r
-       {\r
-               if (bCtrl)\r
-               {\r
-                       if (IsItemSelected(nHitIndex))\r
-                       {\r
-                               m_aSelItems.Sub(nHitIndex);\r
-                               SelectItems();\r
-                               m_bCtrlSel = FALSE;\r
-                       }\r
-                       else\r
-                       {\r
-                               m_aSelItems.Add(nHitIndex);\r
-                               SelectItems();\r
-                               m_bCtrlSel = TRUE;\r
-                       }               \r
-                       \r
-                       m_nFootIndex = nHitIndex;\r
-               }\r
-               else if (bShift)\r
-               {\r
-                       m_aSelItems.DeselectAll();\r
-                       m_aSelItems.Add(m_nFootIndex,nHitIndex);\r
-                       SelectItems();\r
-               }\r
-               else\r
-               {\r
-                       m_aSelItems.DeselectAll();\r
-                       m_aSelItems.Add(nHitIndex);\r
-                       SelectItems();\r
-\r
-                       m_nFootIndex = nHitIndex;\r
-               }\r
-\r
-               SetCaret(nHitIndex);\r
-       }\r
-       else\r
-       {\r
-               SetSingleSelect(nHitIndex);\r
-       }\r
-\r
-       if (!this->IsItemVisible(nHitIndex))\r
-               this->ScrollToListItem(nHitIndex);\r
-}\r
-\r
-void CFX_ListCtrl::OnMouseMove(const CPDF_Point & point,FX_BOOL bShift,FX_BOOL bCtrl)\r
-{\r
-       FX_INT32 nHitIndex = this->GetItemIndex(point);\r
-\r
-       if (IsMultipleSel())\r
-       {                       \r
-               if (bCtrl)\r
-               {\r
-                       if (m_bCtrlSel)\r
-                               m_aSelItems.Add(m_nFootIndex,nHitIndex);\r
-                       else\r
-                               m_aSelItems.Sub(m_nFootIndex,nHitIndex);                        \r
-                       \r
-                       SelectItems();\r
-               }\r
-               else\r
-               {\r
-                       m_aSelItems.DeselectAll();\r
-                       m_aSelItems.Add(m_nFootIndex,nHitIndex);\r
-                       SelectItems();\r
-               }\r
-\r
-               SetCaret(nHitIndex);\r
-       }\r
-       else\r
-       {\r
-               SetSingleSelect(nHitIndex);\r
-       }\r
-\r
-       if (!this->IsItemVisible(nHitIndex))\r
-               this->ScrollToListItem(nHitIndex);\r
-}\r
-\r
-void CFX_ListCtrl::OnVK(FX_INT32 nItemIndex,FX_BOOL bShift,FX_BOOL bCtrl)\r
-{\r
-       if (IsMultipleSel())\r
-       {\r
-               if (nItemIndex >= 0 && nItemIndex < GetCount())\r
-               {\r
-                       if (bCtrl)\r
-                       {\r
-                       }\r
-                       else if (bShift)\r
-                       {\r
-                               m_aSelItems.DeselectAll();\r
-                               m_aSelItems.Add(m_nFootIndex,nItemIndex);\r
-                               SelectItems();\r
-                       }\r
-                       else\r
-                       {\r
-                               m_aSelItems.DeselectAll();\r
-                               m_aSelItems.Add(nItemIndex);\r
-                               SelectItems();\r
-                               m_nFootIndex = nItemIndex;\r
-                       }\r
-\r
-                       SetCaret(nItemIndex);   \r
-               }\r
-       }\r
-       else\r
-       {\r
-               SetSingleSelect(nItemIndex);\r
-       }\r
-\r
-       if (!this->IsItemVisible(nItemIndex))\r
-               this->ScrollToListItem(nItemIndex);\r
-}\r
-\r
-void CFX_ListCtrl::OnVK_UP(FX_BOOL bShift,FX_BOOL bCtrl)\r
-{\r
-       OnVK(IsMultipleSel() ? GetCaret()-1 : GetSelect()-1, bShift, bCtrl);\r
-}\r
-\r
-void CFX_ListCtrl::OnVK_DOWN(FX_BOOL bShift,FX_BOOL bCtrl)\r
-{\r
-       OnVK(IsMultipleSel() ? GetCaret()+1 : GetSelect()+1, bShift, bCtrl);\r
-}\r
-\r
-void CFX_ListCtrl::OnVK_LEFT(FX_BOOL bShift,FX_BOOL bCtrl)\r
-{\r
-       OnVK(0, bShift, bCtrl);\r
-}\r
-\r
-void CFX_ListCtrl::OnVK_RIGHT(FX_BOOL bShift,FX_BOOL bCtrl)\r
-{\r
-       OnVK(GetCount()-1, bShift, bCtrl);\r
-}\r
-\r
-void CFX_ListCtrl::OnVK_HOME(FX_BOOL bShift,FX_BOOL bCtrl)\r
-{\r
-       OnVK(0, bShift, bCtrl);\r
-}\r
-\r
-void CFX_ListCtrl::OnVK_END(FX_BOOL bShift,FX_BOOL bCtrl)\r
-{\r
-       OnVK(GetCount()-1, bShift, bCtrl);\r
-}\r
-\r
-FX_BOOL        CFX_ListCtrl::OnChar(FX_WORD nChar,FX_BOOL bShift,FX_BOOL bCtrl)\r
-{\r
-       FX_INT32 nIndex = GetLastSelected();    \r
-       FX_INT32 nFindIndex = FindNext(nIndex,nChar);\r
-\r
-       if (nFindIndex != nIndex)\r
-       {\r
-               OnVK(nFindIndex, bShift, bCtrl);\r
-               return TRUE;\r
-       }\r
-       return FALSE;\r
-}\r
-\r
-/* -------- inner methods ------- */\r
-\r
-void CFX_ListCtrl::SetPlateRect(const CPDF_Rect & rect)\r
-{\r
-       CFX_ListContainer::SetPlateRect(rect);\r
-       m_ptScrollPos.x = rect.left;\r
-       SetScrollPos(CPDF_Point(rect.left,rect.top));   \r
-       ReArrange(0);\r
-       InvalidateItem(-1);\r
-}\r
-\r
-CPDF_Rect CFX_ListCtrl::GetItemRect(FX_INT32 nIndex) const\r
-{\r
-       return InToOut(CFX_List::GetItemRect(nIndex));\r
-}\r
-\r
-void CFX_ListCtrl::AddString(FX_LPCWSTR string)\r
-{\r
-       AddItem(string);\r
-       ReArrange(GetCount() - 1);\r
-}\r
-\r
-void CFX_ListCtrl::SetMultipleSelect(FX_INT32 nItemIndex, FX_BOOL bSelected)\r
-{\r
-       if (!IsValid(nItemIndex)) return;\r
-\r
-       if (bSelected != this->IsItemSelected(nItemIndex))\r
-       {\r
-               if (bSelected)\r
-               {\r
-                       SetItemSelect(nItemIndex,TRUE);\r
-                       InvalidateItem(nItemIndex);\r
-               }\r
-               else\r
-               {\r
-                       SetItemSelect(nItemIndex,FALSE);\r
-                       InvalidateItem(nItemIndex);\r
-               }\r
-       }\r
-}\r
-\r
-void CFX_ListCtrl::SetSingleSelect(FX_INT32 nItemIndex)\r
-{\r
-       if (!IsValid(nItemIndex)) return;\r
-\r
-       if (m_nSelItem != nItemIndex)\r
-       {\r
-               if (m_nSelItem >= 0)\r
-               {\r
-                       SetItemSelect(m_nSelItem,FALSE);\r
-                       InvalidateItem(m_nSelItem);\r
-               }\r
-               \r
-               SetItemSelect(nItemIndex,TRUE);\r
-               InvalidateItem(nItemIndex);\r
-               m_nSelItem = nItemIndex;                \r
-       }\r
-}\r
-\r
-void CFX_ListCtrl::SetCaret(FX_INT32 nItemIndex)\r
-{\r
-       if (!IsValid(nItemIndex)) return;\r
-\r
-       if (this->IsMultipleSel())\r
-       {               \r
-               FX_INT32 nOldIndex = m_nCaretIndex;\r
-\r
-               if (nOldIndex != nItemIndex)\r
-               {\r
-                       m_nCaretIndex = nItemIndex;\r
-\r
-                       SetItemCaret(nOldIndex, FALSE);\r
-                       SetItemCaret(nItemIndex,TRUE);\r
-\r
-                       InvalidateItem(nOldIndex);\r
-                       InvalidateItem(nItemIndex);                     \r
-               }\r
-       }\r
-}\r
-\r
-void CFX_ListCtrl::InvalidateItem(FX_INT32 nItemIndex)\r
-{\r
-       if (m_pNotify)\r
-       {\r
-               if (nItemIndex == -1)\r
-               {\r
-                       if (!m_bNotifyFlag)\r
-                       {\r
-                               m_bNotifyFlag = TRUE;\r
-                               CPDF_Rect rcRefresh = GetPlateRect();\r
-                               m_pNotify->IOnInvalidateRect(&rcRefresh);\r
-                               m_bNotifyFlag = FALSE;\r
-                       }\r
-               }\r
-               else\r
-               {\r
-                       if (!m_bNotifyFlag)\r
-                       {\r
-                               m_bNotifyFlag = TRUE;\r
-                               CPDF_Rect rcRefresh = GetItemRect(nItemIndex);\r
-                               rcRefresh.left -= 1.0f;\r
-                               rcRefresh.right += 1.0f;\r
-                               rcRefresh.bottom -= 1.0f;\r
-                               rcRefresh.top += 1.0f;\r
-\r
-                               m_pNotify->IOnInvalidateRect(&rcRefresh);\r
-                               m_bNotifyFlag = FALSE;\r
-                       }\r
-               }\r
-       }\r
-}\r
-\r
-void CFX_ListCtrl::SelectItems()\r
-{\r
-       for (FX_INT32 i=0,sz=m_aSelItems.GetCount(); i<sz; i++)\r
-       {\r
-               FX_INT32 nItemIndex = m_aSelItems.GetItemIndex(i);\r
-               FX_INT32 nState = m_aSelItems.GetState(i);\r
-\r
-               switch(nState)\r
-               {\r
-               case 1:\r
-                       SetMultipleSelect(nItemIndex, TRUE);                    \r
-                       break;\r
-               case -1:\r
-                       SetMultipleSelect(nItemIndex, FALSE);\r
-                       break;\r
-               }\r
-       }\r
-\r
-       m_aSelItems.Done();\r
-}\r
-\r
-void CFX_ListCtrl::Select(FX_INT32 nItemIndex)\r
-{\r
-       if (!IsValid(nItemIndex)) return;\r
-\r
-       if (this->IsMultipleSel())\r
-       {\r
-               m_aSelItems.Add(nItemIndex);\r
-               SelectItems();\r
-       }\r
-       else\r
-               SetSingleSelect(nItemIndex);\r
-}\r
-\r
-FX_BOOL        CFX_ListCtrl::IsItemVisible(FX_INT32 nItemIndex) const\r
-{\r
-       CPDF_Rect rcPlate = this->GetPlateRect();\r
-       CPDF_Rect rcItem = this->GetItemRect(nItemIndex);\r
-\r
-       return rcItem.bottom >= rcPlate.bottom && rcItem.top <= rcPlate.top;\r
-}\r
-\r
-void CFX_ListCtrl::ScrollToListItem(FX_INT32 nItemIndex)\r
-{\r
-       if (!IsValid(nItemIndex)) return;\r
-\r
-       CPDF_Rect rcPlate = this->GetPlateRect();\r
-       CPDF_Rect rcItem = CFX_List::GetItemRect(nItemIndex);\r
-       CPDF_Rect rcItemCtrl = GetItemRect(nItemIndex);\r
-\r
-       if (FX_EDIT_IsFloatSmaller(rcItemCtrl.bottom, rcPlate.bottom))\r
-       {\r
-               if (FX_EDIT_IsFloatSmaller(rcItemCtrl.top, rcPlate.top))\r
-               {\r
-                       SetScrollPosY(rcItem.bottom + rcPlate.Height());\r
-               }\r
-       }\r
-       else if (FX_EDIT_IsFloatBigger(rcItemCtrl.top, rcPlate.top))\r
-       {\r
-               if (FX_EDIT_IsFloatBigger(rcItemCtrl.bottom, rcPlate.bottom))\r
-               {\r
-                       SetScrollPosY(rcItem.top);\r
-               }\r
-       }\r
-}\r
-\r
-void CFX_ListCtrl::SetScrollInfo()\r
-{\r
-       if (m_pNotify)\r
-       {\r
-               CPDF_Rect rcPlate = GetPlateRect();\r
-               CPDF_Rect rcContent = CFX_List::GetContentRect();\r
-\r
-               if (!m_bNotifyFlag)\r
-               {\r
-                       m_bNotifyFlag = TRUE;\r
-                       m_pNotify->IOnSetScrollInfoY(rcPlate.bottom, rcPlate.top, \r
-                                       rcContent.bottom, rcContent.top, GetFirstHeight(), rcPlate.Height());\r
-                       m_bNotifyFlag = FALSE;\r
-               }\r
-       }\r
-}\r
-\r
-void CFX_ListCtrl::SetScrollPos(const CPDF_Point & point)\r
-{\r
-       SetScrollPosY(point.y);\r
-}\r
-\r
-void CFX_ListCtrl::SetScrollPosY(FX_FLOAT fy)\r
-{\r
-       if (!FX_EDIT_IsFloatEqual(m_ptScrollPos.y,fy))\r
-       {\r
-               CPDF_Rect rcPlate = this->GetPlateRect();\r
-               CPDF_Rect rcContent = CFX_List::GetContentRect();\r
-\r
-               if (rcPlate.Height() > rcContent.Height())\r
-               {\r
-                       fy = rcPlate.top;\r
-               }\r
-               else\r
-               {\r
-                       if (FX_EDIT_IsFloatSmaller(fy - rcPlate.Height(), rcContent.bottom))\r
-                       {\r
-                               fy = rcContent.bottom + rcPlate.Height();\r
-                       }\r
-                       else if (FX_EDIT_IsFloatBigger(fy, rcContent.top))\r
-                       {\r
-                               fy = rcContent.top;\r
-                       }\r
-               }\r
-\r
-               m_ptScrollPos.y = fy;\r
-               InvalidateItem(-1);\r
-\r
-               if (m_pNotify) \r
-               {\r
-                       if (!m_bNotifyFlag)\r
-                       {\r
-                               m_bNotifyFlag = TRUE;\r
-                               m_pNotify->IOnSetScrollPosY(fy);\r
-                               m_bNotifyFlag = FALSE;\r
-                       }\r
-               }\r
-       }\r
-}\r
-\r
-CPDF_Rect CFX_ListCtrl::GetContentRect() const\r
-{\r
-       return InToOut(CFX_List::GetContentRect());\r
-}\r
-\r
-void CFX_ListCtrl::ReArrange(FX_INT32 nItemIndex)\r
-{\r
-       CFX_List::ReArrange(nItemIndex);\r
-       SetScrollInfo();\r
-}\r
-\r
-void CFX_ListCtrl::SetTopItem(FX_INT32 nIndex)\r
-{\r
-       if (IsValid(nIndex))\r
-       {\r
-               this->GetPlateRect();\r
-               CPDF_Rect rcItem = CFX_List::GetItemRect(nIndex);\r
-               SetScrollPosY(rcItem.top);\r
-       }\r
-}\r
-\r
-FX_INT32 CFX_ListCtrl::GetTopItem() const\r
-{\r
-       FX_INT32 nItemIndex = this->GetItemIndex(this->GetBTPoint());\r
-\r
-       if (!IsItemVisible(nItemIndex) && IsItemVisible(nItemIndex + 1))\r
-                       nItemIndex += 1;\r
-\r
-       return nItemIndex;\r
-}\r
-\r
-void CFX_ListCtrl::Empty()\r
-{\r
-       CFX_List::Empty();\r
-       InvalidateItem(-1);\r
-}\r
-\r
-void CFX_ListCtrl::Cancel()\r
-{\r
-       m_aSelItems.DeselectAll();\r
-}\r
-\r
-FX_INT32 CFX_ListCtrl::GetItemIndex(const CPDF_Point & point) const\r
-{\r
-       return CFX_List::GetItemIndex(OutToIn(point));\r
-}\r
-\r
-CFX_WideString CFX_ListCtrl::GetText() const\r
-{\r
-       if (this->IsMultipleSel())\r
-               return this->GetItemText(this->m_nCaretIndex);  \r
-       else\r
-               return this->GetItemText(this->m_nSelItem);\r
-}\r
-\r
+// 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 "../../include/fxedit/fxet_stub.h"
+#include "../../include/fxedit/fxet_edit.h"
+#include "../../include/fxedit/fxet_list.h"
+
+/* ------------------------------- CFX_ListItem ---------------------------------- */
+
+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();
+       ASSERT(m_pEdit != NULL);
+
+       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(FX_LPCWSTR 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;
+}
+
+FX_WORD 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::CFX_List() : m_fFontSize(0.0f), m_pFontMap(NULL), m_bMultiple(FALSE)
+{
+}
+
+CFX_List::~CFX_List()
+{
+       Empty();
+}
+
+void CFX_List::Empty()
+{
+       for (FX_INT32 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(FX_LPCWSTR str)
+{      
+       if (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(FX_INT32 nItemIndex)
+{
+       FX_FLOAT fPosY = 0.0f;
+
+       if (CFX_ListItem * pPrevItem = m_aListItems.GetAt(nItemIndex - 1))
+               fPosY = pPrevItem->GetRect().bottom;
+       
+       for (FX_INT32 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(FX_INT32 nIndex) const
+{
+       if (CFX_ListItem * pListItem = m_aListItems.GetAt(nIndex))
+       {
+               return pListItem->GetEdit();
+       }
+
+       return NULL;
+}
+
+FX_INT32 CFX_List::GetCount() const
+{
+       return m_aListItems.GetSize();
+}
+
+CPDF_Rect CFX_List::GetPlateRect() const
+{
+       return CFX_ListContainer::GetPlateRect();
+}
+
+CPDF_Rect CFX_List::GetContentRect() const
+{
+       return InnerToOuter(CFX_ListContainer::GetContentRect());
+}
+
+FX_FLOAT CFX_List::GetFontSize() const
+{
+       return m_fFontSize;
+}
+
+FX_INT32 CFX_List::GetItemIndex(const CPDF_Point & point) const
+{
+       CPDF_Point pt = OuterToInner(point);
+
+       FX_BOOL bFirst = TRUE;
+       FX_BOOL bLast = TRUE;
+
+       for (FX_INT32 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;
+}
+
+FX_INT32 CFX_List::GetFirstSelected() const
+{
+       for (FX_INT32 i=0,sz=m_aListItems.GetSize(); i<sz; i++)
+       {
+               if (CFX_ListItem * pListItem = m_aListItems.GetAt(i))
+               {
+                       if (pListItem->IsSelected())
+                               return i;
+               }
+       }
+       return -1;
+}
+
+FX_INT32 CFX_List::GetLastSelected() const
+{
+       for (FX_INT32 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;
+}
+
+FX_INT32 CFX_List::FindNext(FX_INT32 nIndex,FX_WCHAR nChar) const
+{
+       FX_INT32 nCircleIndex = nIndex;
+
+       for (FX_INT32 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;
+}
+
+CPDF_Rect CFX_List::GetItemRect(FX_INT32 nIndex) const
+{
+       if (CFX_ListItem * pListItem = m_aListItems.GetAt(nIndex))
+       {
+               CPDF_Rect rcItem = pListItem->GetRect();
+               rcItem.left = 0.0f;
+               rcItem.right = GetPlateRect().Width();
+               return InnerToOuter(rcItem);
+       }
+
+       return CPDF_Rect();
+}
+
+FX_BOOL CFX_List::IsItemSelected(FX_INT32 nIndex) const
+{
+       if (CFX_ListItem * pListItem = m_aListItems.GetAt(nIndex))
+       {
+               return pListItem->IsSelected();
+       }
+
+       return FALSE;
+}
+
+void CFX_List::SetItemSelect(FX_INT32 nItemIndex, FX_BOOL bSelected)
+{
+       if (CFX_ListItem * pListItem = m_aListItems.GetAt(nItemIndex))
+       {
+               pListItem->SetSelect(bSelected);
+       }
+}
+
+void CFX_List::SetItemCaret(FX_INT32 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(FX_INT32 nItemIndex) const
+{
+       return nItemIndex >= 0 && nItemIndex < m_aListItems.GetSize();
+}
+
+CFX_WideString CFX_List::GetItemText(FX_INT32 nIndex) const
+{
+       if (CFX_ListItem * pListItem = m_aListItems.GetAt(nIndex))
+       {
+               return pListItem->GetText();
+       }
+
+       return L"";
+}
+
+/* ------------------------------------ CPLST_Select ---------------------------------- */
+
+CPLST_Select::CPLST_Select()
+{
+}
+
+CPLST_Select::~CPLST_Select()
+{
+       for (FX_INT32 i=0,sz=m_aItems.GetSize(); i<sz; i++)
+               delete m_aItems.GetAt(i);
+
+       m_aItems.RemoveAll();
+}
+
+void CPLST_Select::Add(FX_INT32 nItemIndex)
+{
+       FX_INT32 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(FX_INT32 nBeginIndex, FX_INT32 nEndIndex)
+{
+       if (nBeginIndex > nEndIndex)
+       {
+               FX_INT32 nTemp = nEndIndex;
+               nEndIndex = nBeginIndex;
+               nBeginIndex = nTemp;
+       }
+
+       for (FX_INT32 i=nBeginIndex; i<=nEndIndex; i++) Add(i);
+}
+
+void CPLST_Select::Sub(FX_INT32 nItemIndex)
+{
+       for (FX_INT32 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(FX_INT32 nBeginIndex, FX_INT32 nEndIndex)
+{
+       if (nBeginIndex > nEndIndex)
+       {
+               FX_INT32 nTemp = nEndIndex;
+               nEndIndex = nBeginIndex;
+               nBeginIndex = nTemp;
+       }
+
+       for (FX_INT32 i=nBeginIndex; i<=nEndIndex; i++) Sub(i);
+}
+
+FX_INT32 CPLST_Select::Find(FX_INT32 nItemIndex) const
+{
+       for (FX_INT32 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(FX_INT32 nItemIndex) const
+{
+       return Find(nItemIndex) >= 0;
+}
+
+FX_INT32 CPLST_Select::GetCount() const
+{
+       return m_aItems.GetSize();
+}
+
+FX_INT32 CPLST_Select::GetItemIndex(FX_INT32 nIndex) const
+{
+       if (nIndex >= 0 && nIndex < m_aItems.GetSize())
+               if (CPLST_Select_Item * pItem = m_aItems.GetAt(nIndex))
+                       return pItem->nItemIndex;
+
+       return -1;
+}
+
+FX_INT32 CPLST_Select::GetState(FX_INT32 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 (FX_INT32 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 (FX_INT32 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::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;
+}
+
+CPDF_Point CFX_ListCtrl::InToOut(const CPDF_Point & point) const
+{
+       CPDF_Rect rcPlate = GetPlateRect();
+
+       return CPDF_Point(point.x - (m_ptScrollPos.x - rcPlate.left),
+               point.y - (m_ptScrollPos.y - rcPlate.top));
+}
+
+CPDF_Point CFX_ListCtrl::OutToIn(const CPDF_Point & point) const
+{
+       CPDF_Rect rcPlate = GetPlateRect();
+
+       return CPDF_Point(point.x + (m_ptScrollPos.x - rcPlate.left),
+               point.y + (m_ptScrollPos.y - rcPlate.top));
+}
+
+CPDF_Rect CFX_ListCtrl::InToOut(const CPDF_Rect & rect) const
+{
+       CPDF_Point ptLeftBottom = InToOut(CPDF_Point(rect.left,rect.bottom));
+       CPDF_Point ptRightTop = InToOut(CPDF_Point(rect.right,rect.top));
+
+       return CPDF_Rect(ptLeftBottom.x,ptLeftBottom.y,ptRightTop.x,ptRightTop.y);
+}
+
+CPDF_Rect CFX_ListCtrl::OutToIn(const CPDF_Rect & rect) const
+{
+       CPDF_Point ptLeftBottom = OutToIn(CPDF_Point(rect.left,rect.bottom));
+       CPDF_Point ptRightTop = OutToIn(CPDF_Point(rect.right,rect.top));
+
+       return CPDF_Rect(ptLeftBottom.x,ptLeftBottom.y,ptRightTop.x,ptRightTop.y);
+}
+
+void CFX_ListCtrl::OnMouseDown(const CPDF_Point & point,FX_BOOL bShift,FX_BOOL bCtrl)
+{
+       FX_INT32 nHitIndex = this->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 (!this->IsItemVisible(nHitIndex))
+               this->ScrollToListItem(nHitIndex);
+}
+
+void CFX_ListCtrl::OnMouseMove(const CPDF_Point & point,FX_BOOL bShift,FX_BOOL bCtrl)
+{
+       FX_INT32 nHitIndex = this->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 (!this->IsItemVisible(nHitIndex))
+               this->ScrollToListItem(nHitIndex);
+}
+
+void CFX_ListCtrl::OnVK(FX_INT32 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 (!this->IsItemVisible(nItemIndex))
+               this->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(FX_WORD nChar,FX_BOOL bShift,FX_BOOL bCtrl)
+{
+       FX_INT32 nIndex = GetLastSelected();    
+       FX_INT32 nFindIndex = FindNext(nIndex,nChar);
+
+       if (nFindIndex != nIndex)
+       {
+               OnVK(nFindIndex, bShift, bCtrl);
+               return TRUE;
+       }
+       return FALSE;
+}
+
+/* -------- inner methods ------- */
+
+void CFX_ListCtrl::SetPlateRect(const CPDF_Rect & rect)
+{
+       CFX_ListContainer::SetPlateRect(rect);
+       m_ptScrollPos.x = rect.left;
+       SetScrollPos(CPDF_Point(rect.left,rect.top));   
+       ReArrange(0);
+       InvalidateItem(-1);
+}
+
+CPDF_Rect CFX_ListCtrl::GetItemRect(FX_INT32 nIndex) const
+{
+       return InToOut(CFX_List::GetItemRect(nIndex));
+}
+
+void CFX_ListCtrl::AddString(FX_LPCWSTR string)
+{
+       AddItem(string);
+       ReArrange(GetCount() - 1);
+}
+
+void CFX_ListCtrl::SetMultipleSelect(FX_INT32 nItemIndex, FX_BOOL bSelected)
+{
+       if (!IsValid(nItemIndex)) return;
+
+       if (bSelected != this->IsItemSelected(nItemIndex))
+       {
+               if (bSelected)
+               {
+                       SetItemSelect(nItemIndex,TRUE);
+                       InvalidateItem(nItemIndex);
+               }
+               else
+               {
+                       SetItemSelect(nItemIndex,FALSE);
+                       InvalidateItem(nItemIndex);
+               }
+       }
+}
+
+void CFX_ListCtrl::SetSingleSelect(FX_INT32 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(FX_INT32 nItemIndex)
+{
+       if (!IsValid(nItemIndex)) return;
+
+       if (this->IsMultipleSel())
+       {               
+               FX_INT32 nOldIndex = m_nCaretIndex;
+
+               if (nOldIndex != nItemIndex)
+               {
+                       m_nCaretIndex = nItemIndex;
+
+                       SetItemCaret(nOldIndex, FALSE);
+                       SetItemCaret(nItemIndex,TRUE);
+
+                       InvalidateItem(nOldIndex);
+                       InvalidateItem(nItemIndex);                     
+               }
+       }
+}
+
+void CFX_ListCtrl::InvalidateItem(FX_INT32 nItemIndex)
+{
+       if (m_pNotify)
+       {
+               if (nItemIndex == -1)
+               {
+                       if (!m_bNotifyFlag)
+                       {
+                               m_bNotifyFlag = TRUE;
+                               CPDF_Rect rcRefresh = GetPlateRect();
+                               m_pNotify->IOnInvalidateRect(&rcRefresh);
+                               m_bNotifyFlag = FALSE;
+                       }
+               }
+               else
+               {
+                       if (!m_bNotifyFlag)
+                       {
+                               m_bNotifyFlag = TRUE;
+                               CPDF_Rect 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 (FX_INT32 i=0,sz=m_aSelItems.GetCount(); i<sz; i++)
+       {
+               FX_INT32 nItemIndex = m_aSelItems.GetItemIndex(i);
+               FX_INT32 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(FX_INT32 nItemIndex)
+{
+       if (!IsValid(nItemIndex)) return;
+
+       if (this->IsMultipleSel())
+       {
+               m_aSelItems.Add(nItemIndex);
+               SelectItems();
+       }
+       else
+               SetSingleSelect(nItemIndex);
+}
+
+FX_BOOL        CFX_ListCtrl::IsItemVisible(FX_INT32 nItemIndex) const
+{
+       CPDF_Rect rcPlate = this->GetPlateRect();
+       CPDF_Rect rcItem = this->GetItemRect(nItemIndex);
+
+       return rcItem.bottom >= rcPlate.bottom && rcItem.top <= rcPlate.top;
+}
+
+void CFX_ListCtrl::ScrollToListItem(FX_INT32 nItemIndex)
+{
+       if (!IsValid(nItemIndex)) return;
+
+       CPDF_Rect rcPlate = this->GetPlateRect();
+       CPDF_Rect rcItem = CFX_List::GetItemRect(nItemIndex);
+       CPDF_Rect 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)
+       {
+               CPDF_Rect rcPlate = GetPlateRect();
+               CPDF_Rect 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 CPDF_Point & point)
+{
+       SetScrollPosY(point.y);
+}
+
+void CFX_ListCtrl::SetScrollPosY(FX_FLOAT fy)
+{
+       if (!FX_EDIT_IsFloatEqual(m_ptScrollPos.y,fy))
+       {
+               CPDF_Rect rcPlate = this->GetPlateRect();
+               CPDF_Rect 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;
+                       }
+               }
+       }
+}
+
+CPDF_Rect CFX_ListCtrl::GetContentRect() const
+{
+       return InToOut(CFX_List::GetContentRect());
+}
+
+void CFX_ListCtrl::ReArrange(FX_INT32 nItemIndex)
+{
+       CFX_List::ReArrange(nItemIndex);
+       SetScrollInfo();
+}
+
+void CFX_ListCtrl::SetTopItem(FX_INT32 nIndex)
+{
+       if (IsValid(nIndex))
+       {
+               this->GetPlateRect();
+               CPDF_Rect rcItem = CFX_List::GetItemRect(nIndex);
+               SetScrollPosY(rcItem.top);
+       }
+}
+
+FX_INT32 CFX_ListCtrl::GetTopItem() const
+{
+       FX_INT32 nItemIndex = this->GetItemIndex(this->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();
+}
+
+FX_INT32 CFX_ListCtrl::GetItemIndex(const CPDF_Point & point) const
+{
+       return CFX_List::GetItemIndex(OutToIn(point));
+}
+
+CFX_WideString CFX_ListCtrl::GetText() const
+{
+       if (this->IsMultipleSel())
+               return this->GetItemText(this->m_nCaretIndex);  
+       else
+               return this->GetItemText(this->m_nSelItem);
+}
+