CPDFDoc_Environment::GetAnnotHandlerMgr() never returns nullptr.
[pdfium.git] / fpdfsdk / src / pdfwindow / PWL_Edit.cpp
index 87ddd87..8e45060 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/pdfwindow/PDFWindow.h"\r
-#include "../../include/pdfwindow/PWL_Wnd.h"\r
-#include "../../include/pdfwindow/PWL_EditCtrl.h"\r
-#include "../../include/pdfwindow/PWL_Edit.h"\r
-#include "../../include/pdfwindow/PWL_ScrollBar.h"\r
-#include "../../include/pdfwindow/PWL_Utils.h"\r
-#include "../../include/pdfwindow/PWL_Caret.h"\r
-#include "../../include/pdfwindow/PWL_FontMap.h"\r
-\r
-/* ---------------------------- CPWL_Edit ------------------------------ */\r
-\r
-CPWL_Edit::CPWL_Edit() : m_pFillerNotify(NULL), \r
-       m_pSpellCheck(NULL),\r
-       m_bFocus(FALSE)\r
-{\r
-       m_pFormFiller = NULL;\r
-}\r
-\r
-CPWL_Edit::~CPWL_Edit()\r
-{\r
-       ASSERT(m_bFocus == FALSE);\r
-}\r
-\r
-CFX_ByteString CPWL_Edit::GetClassName() const\r
-{\r
-       return PWL_CLASSNAME_EDIT;\r
-}\r
-\r
-void CPWL_Edit::OnDestroy()\r
-{\r
-}\r
-\r
-void CPWL_Edit::SetText(FX_LPCWSTR csText)\r
-{\r
-       CFX_WideString swText = csText;\r
-\r
-       if (HasFlag(PES_RICH))\r
-       {               \r
-               CFX_ByteString sValue = CFX_ByteString::FromUnicode(swText);\r
-               \r
-               if (CXML_Element * pXML = CXML_Element::Parse((FX_LPCSTR)sValue,sValue.GetLength()))\r
-               {\r
-                       FX_INT32 nCount = pXML->CountChildren();\r
-                       FX_BOOL bFirst = TRUE;\r
-\r
-                       swText.Empty();\r
-\r
-                       for (FX_INT32 i=0; i<nCount; i++)\r
-                       {\r
-                               if (CXML_Element * pSubElement = pXML->GetElement(i))\r
-                               {\r
-                                       CFX_ByteString tag=pSubElement->GetTagName();\r
-                                       if (tag.EqualNoCase("p"))\r
-                                       {\r
-                                               int nChild = pSubElement->CountChildren();\r
-                                               CFX_WideString swSection;\r
-                                               for(FX_INT32 j=0; j<nChild; j++)\r
-                                               {\r
-                                                       swSection += pSubElement->GetContent(j);\r
-                                               }\r
-                                               \r
-                                               if (bFirst)bFirst = FALSE;\r
-                                               else\r
-                                                       swText += FWL_VKEY_Return;\r
-                                               swText += swSection;\r
-                                       }\r
-                               }\r
-                       }\r
-\r
-                       delete pXML;\r
-               }\r
-       }       \r
-\r
-       m_pEdit->SetText(swText);\r
-}\r
-\r
-void CPWL_Edit::RePosChildWnd()\r
-{\r
-       if (CPWL_ScrollBar * pVSB = this->GetVScrollBar())\r
-       {\r
-               //if (pVSB->IsVisible())\r
-               {\r
-                       CPDF_Rect rcWindow = m_rcOldWindow;             \r
-                       CPDF_Rect rcVScroll = CPDF_Rect(rcWindow.right,\r
-                                                               rcWindow.bottom,\r
-                                                               rcWindow.right + PWL_SCROLLBAR_WIDTH,\r
-                                                               rcWindow.top);\r
-                       pVSB->Move(rcVScroll, TRUE, FALSE);\r
-               }\r
-       }\r
-\r
-       if (m_pEditCaret && !HasFlag(PES_TEXTOVERFLOW))\r
-               m_pEditCaret->SetClipRect(CPWL_Utils::InflateRect(GetClientRect(),1.0f)); //+1 for caret beside border\r
-\r
-       CPWL_EditCtrl::RePosChildWnd();\r
-}\r
-\r
-CPDF_Rect CPWL_Edit::GetClientRect() const\r
-{\r
-       CPDF_Rect rcClient = CPWL_Utils::DeflateRect(GetWindowRect(),(FX_FLOAT)(GetBorderWidth()+GetInnerBorderWidth()));\r
-       \r
-       if (CPWL_ScrollBar * pVSB = this->GetVScrollBar())\r
-       {\r
-               if (pVSB->IsVisible())\r
-               {\r
-                       rcClient.right -= PWL_SCROLLBAR_WIDTH;\r
-               }\r
-       }\r
-\r
-       return rcClient;\r
-}\r
-\r
-void CPWL_Edit::SetAlignFormatH(PWL_EDIT_ALIGNFORMAT_H nFormat, FX_BOOL bPaint/* = TRUE*/)\r
-{\r
-       m_pEdit->SetAlignmentH((FX_INT32)nFormat, bPaint);\r
-}\r
-\r
-void CPWL_Edit::SetAlignFormatV(PWL_EDIT_ALIGNFORMAT_V nFormat, FX_BOOL bPaint/* = TRUE*/)\r
-{\r
-       m_pEdit->SetAlignmentV((FX_INT32)nFormat, bPaint);\r
-}\r
-\r
-FX_BOOL        CPWL_Edit::CanSelectAll() const\r
-{\r
-       return  GetSelectWordRange() != m_pEdit->GetWholeWordRange();\r
-}\r
-\r
-FX_BOOL        CPWL_Edit::CanClear() const\r
-{\r
-       return !IsReadOnly() && m_pEdit->IsSelected();\r
-}\r
-\r
-FX_BOOL        CPWL_Edit::CanCopy() const\r
-{\r
-       return  !HasFlag(PES_PASSWORD) && !HasFlag(PES_NOREAD) && m_pEdit->IsSelected();\r
-}\r
-\r
-FX_BOOL        CPWL_Edit::CanCut() const\r
-{\r
-       return  CanCopy() && !IsReadOnly();\r
-}\r
-\r
-FX_BOOL        CPWL_Edit::CanPaste() const\r
-{\r
-       if (IsReadOnly()) return FALSE;\r
-\r
-       CFX_WideString swClipboard;\r
-       if (IFX_SystemHandler* pSH = GetSystemHandler())\r
-               swClipboard = pSH->GetClipboardText(GetAttachedHWnd());\r
-\r
-       return !swClipboard.IsEmpty();\r
-}\r
-\r
-void CPWL_Edit::CopyText()\r
-{\r
-       if (!CanCopy()) return;\r
-\r
-       CFX_WideString str = m_pEdit->GetSelText();\r
-\r
-       if (IFX_SystemHandler* pSH = GetSystemHandler())\r
-               pSH->SetClipboardText(GetAttachedHWnd(), str);\r
-}\r
-\r
-void CPWL_Edit::PasteText()\r
-{\r
-       if (!CanPaste()) return;\r
-\r
-       CFX_WideString swClipboard;\r
-       if (IFX_SystemHandler* pSH = GetSystemHandler())\r
-               swClipboard = pSH->GetClipboardText(GetAttachedHWnd());\r
-\r
-       if (m_pFillerNotify)\r
-       {\r
-               FX_BOOL bRC = TRUE;\r
-               FX_BOOL bExit = FALSE;\r
-               CFX_WideString strChangeEx;\r
-               int nSelStart = 0;\r
-               int nSelEnd = 0;\r
-               GetSel(nSelStart, nSelEnd);\r
-               m_pFillerNotify->OnBeforeKeyStroke(TRUE, GetAttachedData(), 0 , swClipboard, strChangeEx, nSelStart, nSelEnd, TRUE, bRC, bExit, 0);\r
-               if (!bRC) return;\r
-               if (bExit) return;\r
-       }\r
-\r
-       if (swClipboard.GetLength() > 0)\r
-       {\r
-               Clear();\r
-               InsertText(swClipboard);\r
-       }\r
-\r
-       if (m_pFillerNotify)\r
-       {\r
-               FX_BOOL bExit = FALSE;\r
-               m_pFillerNotify->OnAfterKeyStroke(TRUE, GetAttachedData(), bExit,0);\r
-               if (bExit) return;\r
-       }\r
-}\r
-\r
-void CPWL_Edit::CutText()\r
-{\r
-       if (!CanCut()) return;\r
-\r
-       CFX_WideString str = m_pEdit->GetSelText();\r
-\r
-       if (IFX_SystemHandler* pSH = GetSystemHandler())\r
-               pSH->SetClipboardText(GetAttachedHWnd(), str);\r
-\r
-       m_pEdit->Clear();\r
-}\r
-\r
-void CPWL_Edit::OnCreated()\r
-{\r
-       CPWL_EditCtrl::OnCreated();\r
-\r
-       if (CPWL_ScrollBar * pScroll = GetVScrollBar())\r
-       {\r
-               pScroll->RemoveFlag(PWS_AUTOTRANSPARENT);\r
-               pScroll->SetTransparency(255);\r
-       }\r
-\r
-       SetParamByFlag();\r
-\r
-       m_rcOldWindow = GetWindowRect();\r
-\r
-       m_pEdit->SetOprNotify(this);\r
-       m_pEdit->EnableOprNotify(TRUE);\r
-}\r
-\r
-void CPWL_Edit::SetParamByFlag()\r
-{      \r
-       if (HasFlag(PES_RIGHT))\r
-       {\r
-               m_pEdit->SetAlignmentH(2, FALSE);\r
-       }\r
-       else if (HasFlag(PES_MIDDLE))\r
-       {\r
-               m_pEdit->SetAlignmentH(1, FALSE);\r
-       }\r
-       else\r
-       {\r
-               m_pEdit->SetAlignmentH(0, FALSE);\r
-       }\r
-\r
-       if (HasFlag(PES_BOTTOM))\r
-       {\r
-               m_pEdit->SetAlignmentV(2, FALSE);\r
-       }\r
-       else if (HasFlag(PES_CENTER))\r
-       {\r
-               m_pEdit->SetAlignmentV(1, FALSE);\r
-       }\r
-       else\r
-       {\r
-               m_pEdit->SetAlignmentV(0, FALSE);\r
-       }\r
-\r
-       if (HasFlag(PES_PASSWORD))\r
-       {\r
-               m_pEdit->SetPasswordChar('*', FALSE);\r
-       }\r
-\r
-       m_pEdit->SetMultiLine(HasFlag(PES_MULTILINE), FALSE);\r
-       m_pEdit->SetAutoReturn(HasFlag(PES_AUTORETURN), FALSE);\r
-       m_pEdit->SetAutoFontSize(HasFlag(PWS_AUTOFONTSIZE), FALSE);\r
-       m_pEdit->SetAutoScroll(HasFlag(PES_AUTOSCROLL), FALSE);\r
-       m_pEdit->EnableUndo(HasFlag(PES_UNDO));\r
-\r
-       if (HasFlag(PES_TEXTOVERFLOW))\r
-       {\r
-               SetClipRect(CPDF_Rect(0.0f,0.0f,0.0f,0.0f));\r
-               m_pEdit->SetTextOverflow(TRUE, FALSE);\r
-       }\r
-       else\r
-       {\r
-               if (m_pEditCaret)\r
-               {\r
-                       m_pEditCaret->SetClipRect(CPWL_Utils::InflateRect(GetClientRect(),1.0f)); //+1 for caret beside border\r
-               }\r
-       }\r
-\r
-       if (HasFlag(PES_SPELLCHECK))\r
-       {\r
-               m_pSpellCheck = GetCreationParam().pSpellCheck;\r
-       }\r
-}\r
-\r
-void CPWL_Edit::GetThisAppearanceStream(CFX_ByteTextBuf & sAppStream)\r
-{\r
-       CPWL_Wnd::GetThisAppearanceStream(sAppStream);\r
-\r
-       CPDF_Rect rcClient = GetClientRect();\r
-       CFX_ByteTextBuf sLine;\r
-\r
-       FX_INT32 nCharArray = m_pEdit->GetCharArray();\r
-\r
-       if (nCharArray > 0)\r
-       {\r
-               switch (GetBorderStyle())\r
-               {\r
-               case PBS_SOLID:\r
-                       {\r
-                               sLine << "q\n" << GetBorderWidth() << " w\n" \r
-                                       << CPWL_Utils::GetColorAppStream(GetBorderColor(),FALSE) << " 2 J 0 j\n";                                       \r
-\r
-                               for (FX_INT32 i=1;i<nCharArray;i++)\r
-                               {\r
-                                       sLine << rcClient.left + ((rcClient.right - rcClient.left)/nCharArray)*i << " "\r
-                                               << rcClient.bottom << " m\n"\r
-                                               << rcClient.left + ((rcClient.right - rcClient.left)/nCharArray)*i << " "\r
-                                               << rcClient.top << " l S\n";                                            \r
-                               }\r
-\r
-                               sLine << "Q\n";                                 \r
-                       }\r
-                       break; \r
-               case PBS_DASH:\r
-                       {\r
-                               sLine << "q\n" << GetBorderWidth() << " w\n" \r
-                                       << CPWL_Utils::GetColorAppStream(GetBorderColor(),FALSE) << " 2 J 0 j\n"\r
-                                       << "[" << GetBorderDash().nDash << " " \r
-                                       << GetBorderDash().nGap << "] " \r
-                                       << GetBorderDash().nPhase << " d\n";\r
-\r
-                               for (FX_INT32 i=1;i<nCharArray;i++)                                     \r
-                               {\r
-                                       sLine << rcClient.left + ((rcClient.right - rcClient.left)/nCharArray)*i << " "\r
-                                               << rcClient.bottom << " m\n"\r
-                                               << rcClient.left + ((rcClient.right - rcClient.left)/nCharArray)*i << " "\r
-                                               << rcClient.top << " l S\n";    \r
-                               }\r
-\r
-                               sLine << "Q\n";\r
-                       }\r
-                       break;\r
-               }               \r
-       }\r
-\r
-       sAppStream << sLine;\r
-\r
-       CFX_ByteTextBuf sText;\r
-\r
-       CPDF_Point ptOffset = CPDF_Point(0.0f,0.0f);\r
-\r
-       CPVT_WordRange wrWhole = m_pEdit->GetWholeWordRange();\r
-       CPVT_WordRange wrSelect = GetSelectWordRange();\r
-       CPVT_WordRange wrVisible = (HasFlag(PES_TEXTOVERFLOW) ? wrWhole : m_pEdit->GetVisibleWordRange());\r
-       CPVT_WordRange wrSelBefore(wrWhole.BeginPos,wrSelect.BeginPos);\r
-       CPVT_WordRange wrSelAfter(wrSelect.EndPos,wrWhole.EndPos);\r
-\r
-       CPVT_WordRange wrTemp = CPWL_Utils::OverlapWordRange(GetSelectWordRange(),wrVisible);\r
-       CFX_ByteString sEditSel = CPWL_Utils::GetEditSelAppStream(m_pEdit, ptOffset,\r
-                       &wrTemp);\r
-\r
-       if (sEditSel.GetLength() > 0)\r
-               sText << CPWL_Utils::GetColorAppStream(PWL_DEFAULT_SELBACKCOLOR) << sEditSel ;\r
-\r
-       wrTemp = CPWL_Utils::OverlapWordRange(wrVisible,wrSelBefore);\r
-       CFX_ByteString sEditBefore = CPWL_Utils::GetEditAppStream(m_pEdit, ptOffset,  \r
-                       &wrTemp, !HasFlag(PES_CHARARRAY), m_pEdit->GetPasswordChar());                  \r
-\r
-       if (sEditBefore.GetLength() > 0)\r
-               sText << "BT\n" << CPWL_Utils::GetColorAppStream(GetTextColor()) << sEditBefore << "ET\n";\r
-\r
-       wrTemp = CPWL_Utils::OverlapWordRange(wrVisible,wrSelect);\r
-       CFX_ByteString sEditMid = CPWL_Utils::GetEditAppStream(m_pEdit, ptOffset, \r
-                       &wrTemp, !HasFlag(PES_CHARARRAY), m_pEdit->GetPasswordChar());                  \r
-\r
-       if (sEditMid.GetLength() > 0)\r
-               sText << "BT\n" << CPWL_Utils::GetColorAppStream(CPWL_Color(COLORTYPE_GRAY,1)) << sEditMid << "ET\n";\r
-\r
-       wrTemp = CPWL_Utils::OverlapWordRange(wrVisible,wrSelAfter);\r
-       CFX_ByteString sEditAfter = CPWL_Utils::GetEditAppStream(m_pEdit, ptOffset, \r
-                       &wrTemp, !HasFlag(PES_CHARARRAY), m_pEdit->GetPasswordChar());                  \r
-\r
-       if (sEditAfter.GetLength() > 0)\r
-               sText << "BT\n" << CPWL_Utils::GetColorAppStream(GetTextColor()) << sEditAfter<< "ET\n";\r
-\r
-       if (HasFlag(PES_SPELLCHECK))\r
-       {\r
-               CFX_ByteString sSpellCheck = CPWL_Utils::GetSpellCheckAppStream(m_pEdit, m_pSpellCheck, ptOffset, &wrVisible);\r
-               if (sSpellCheck.GetLength() > 0)\r
-                       sText << CPWL_Utils::GetColorAppStream(CPWL_Color(COLORTYPE_RGB,1,0,0),FALSE) << sSpellCheck;\r
-       }\r
-\r
-       if (sText.GetLength() > 0)\r
-       {\r
-               CPDF_Rect rcClient = this->GetClientRect();\r
-               sAppStream << "q\n/Tx BMC\n";\r
-               \r
-               if (!HasFlag(PES_TEXTOVERFLOW))\r
-                       sAppStream << rcClient.left << " " << rcClient.bottom << " "\r
-                               << rcClient.right - rcClient.left << " " << rcClient.top - rcClient.bottom << " re W n\n";\r
-\r
-               sAppStream << sText;\r
-\r
-               sAppStream << "EMC\nQ\n";\r
-       }\r
-}\r
-\r
-void CPWL_Edit::DrawThisAppearance(CFX_RenderDevice* pDevice, CPDF_Matrix* pUser2Device)\r
-{\r
-       CPWL_Wnd::DrawThisAppearance(pDevice,pUser2Device);\r
-\r
-       CPDF_Rect rcClient = GetClientRect();\r
-       CFX_ByteTextBuf sLine;\r
-\r
-       FX_INT32 nCharArray = m_pEdit->GetCharArray();\r
-\r
-       if (nCharArray > 0)\r
-       {\r
-               switch (GetBorderStyle())\r
-               {\r
-               case PBS_SOLID:\r
-                       {\r
-                               CFX_GraphStateData gsd;\r
-                               gsd.m_LineWidth = (FX_FLOAT)GetBorderWidth();\r
-\r
-                               CFX_PathData path;\r
-                               path.SetPointCount((nCharArray-1)*2);\r
-                               \r
-                               for (FX_INT32 i=0; i<nCharArray-1; i++)\r
-                               {                                       \r
-                                       path.SetPoint(i*2, rcClient.left + ((rcClient.right - rcClient.left)/nCharArray)*(i+1), \r
-                                               rcClient.bottom, FXPT_MOVETO);\r
-                                       path.SetPoint(i*2+1, rcClient.left + ((rcClient.right - rcClient.left)/nCharArray)*(i+1),\r
-                                               rcClient.top, FXPT_LINETO);                                                                                     \r
-                               }                       \r
-                               if (path.GetPointCount() > 0)\r
-                                       pDevice->DrawPath(&path, pUser2Device, &gsd,0,  \r
-                                               CPWL_Utils::PWLColorToFXColor(GetBorderColor(),255), FXFILL_ALTERNATE);\r
-                       }\r
-                       break; \r
-               case PBS_DASH:\r
-                       {\r
-                               CFX_GraphStateData gsd;\r
-                               gsd.m_LineWidth = (FX_FLOAT)GetBorderWidth();\r
-\r
-                               gsd.SetDashCount(2);\r
-                               gsd.m_DashArray[0] = (FX_FLOAT)GetBorderDash().nDash;\r
-                               gsd.m_DashArray[1] = (FX_FLOAT)GetBorderDash().nGap;\r
-                               gsd.m_DashPhase = (FX_FLOAT)GetBorderDash().nPhase;\r
-\r
-                               CFX_PathData path;\r
-                               path.SetPointCount((nCharArray-1)*2);\r
-                               \r
-                               for (FX_INT32 i=0; i<nCharArray-1; i++)\r
-                               {                                       \r
-                                       path.SetPoint(i*2, rcClient.left + ((rcClient.right - rcClient.left)/nCharArray)*(i+1), \r
-                                               rcClient.bottom, FXPT_MOVETO);\r
-                                       path.SetPoint(i*2+1, rcClient.left + ((rcClient.right - rcClient.left)/nCharArray)*(i+1),\r
-                                               rcClient.top, FXPT_LINETO);                                                                                     \r
-                               }               \r
-                               if (path.GetPointCount() > 0)\r
-                                       pDevice->DrawPath(&path, pUser2Device, &gsd,0,  \r
-                                               CPWL_Utils::PWLColorToFXColor(GetBorderColor(),255), FXFILL_ALTERNATE);\r
-                       }\r
-                       break;\r
-               }               \r
-       }\r
-\r
-       CPDF_Rect rcClip;\r
-       CPVT_WordRange wrRange = m_pEdit->GetVisibleWordRange();\r
-       CPVT_WordRange* pRange = NULL;\r
-\r
-       if (!HasFlag(PES_TEXTOVERFLOW))\r
-       {\r
-               rcClip = GetClientRect();\r
-               pRange = &wrRange;\r
-       }\r
-IFX_SystemHandler* pSysHandler = GetSystemHandler();\r
-       IFX_Edit::DrawEdit(pDevice,pUser2Device,m_pEdit,\r
-               CPWL_Utils::PWLColorToFXColor(GetTextColor(),this->GetTransparency()),\r
-               CPWL_Utils::PWLColorToFXColor(GetTextStrokeColor(),this->GetTransparency()),\r
-               rcClip,CPDF_Point(0.0f,0.0f),pRange, pSysHandler, m_pFormFiller);\r
-\r
-       if (HasFlag(PES_SPELLCHECK))\r
-       {\r
-               CPWL_Utils::DrawEditSpellCheck(pDevice,pUser2Device,m_pEdit,rcClip,\r
-                       CPDF_Point(0.0f,0.0f),pRange, this->GetCreationParam().pSpellCheck);\r
-       }\r
-}\r
-\r
-FX_BOOL CPWL_Edit::OnLButtonDown(const CPDF_Point & point, FX_DWORD nFlag)\r
-{\r
-       CPWL_Wnd::OnLButtonDown(point,nFlag);\r
-\r
-       if (HasFlag(PES_TEXTOVERFLOW) || ClientHitTest(point))\r
-       {\r
-               if (m_bMouseDown)\r
-                       this->InvalidateRect();\r
-\r
-               m_bMouseDown = TRUE;            \r
-               SetCapture();\r
-\r
-               m_pEdit->OnMouseDown(point,IsSHIFTpressed(nFlag),IsCTRLpressed(nFlag));\r
-       }\r
-\r
-       return TRUE;\r
-}\r
-\r
-FX_BOOL        CPWL_Edit::OnLButtonDblClk(const CPDF_Point & point, FX_DWORD nFlag)\r
-{\r
-       CPWL_Wnd::OnLButtonDblClk(point, nFlag);\r
-\r
-       if (HasFlag(PES_TEXTOVERFLOW) || ClientHitTest(point))\r
-       {\r
-               m_pEdit->SelectAll();\r
-       }\r
-\r
-       return TRUE;\r
-}\r
-\r
-#define WM_PWLEDIT_UNDO                                        0x01\r
-#define WM_PWLEDIT_REDO                                        0x02\r
-#define WM_PWLEDIT_CUT                                 0x03\r
-#define WM_PWLEDIT_COPY                                        0x04\r
-#define WM_PWLEDIT_PASTE                               0x05\r
-#define WM_PWLEDIT_DELETE                              0x06\r
-#define WM_PWLEDIT_SELECTALL                   0x07\r
-#define WM_PWLEDIT_SUGGEST                             0x08\r
-\r
-FX_BOOL CPWL_Edit::OnRButtonUp(const CPDF_Point & point, FX_DWORD nFlag)\r
-{\r
-       if (m_bMouseDown) return FALSE;\r
-\r
-       CPWL_Wnd::OnRButtonUp(point, nFlag);\r
-       \r
-       if (!HasFlag(PES_TEXTOVERFLOW) && !ClientHitTest(point)) return TRUE;\r
-\r
-       IFX_SystemHandler* pSH = GetSystemHandler();\r
-       if (!pSH) return FALSE;\r
-\r
-       this->SetFocus();\r
-\r
-       CPVT_WordRange wrLatin = GetLatinWordsRange(point);\r
-       CFX_WideString swLatin = m_pEdit->GetRangeText(wrLatin);\r
-\r
-       FX_HMENU hPopup = pSH->CreatePopupMenu();\r
-       if (!hPopup) return FALSE;\r
-\r
-       CFX_ByteStringArray sSuggestWords;\r
-       CPDF_Point ptPopup = point;\r
-\r
-       if (!IsReadOnly())\r
-       {\r
-               if (HasFlag(PES_SPELLCHECK) && !swLatin.IsEmpty())\r
-               {\r
-                       if (m_pSpellCheck)\r
-                       {\r
-                               CFX_ByteString sLatin = CFX_ByteString::FromUnicode(swLatin);\r
-\r
-                               if (!m_pSpellCheck->CheckWord(sLatin))\r
-                               {                                               \r
-                                       m_pSpellCheck->SuggestWords(sLatin,sSuggestWords);\r
-\r
-                                       FX_INT32 nSuggest = sSuggestWords.GetSize();\r
-\r
-                                       for (FX_INT32 nWord=0; nWord<nSuggest; nWord++)\r
-                                       {       \r
-                                               pSH->AppendMenuItem(hPopup, WM_PWLEDIT_SUGGEST+nWord, sSuggestWords[nWord].UTF8Decode());\r
-                                       }\r
-\r
-                                       if (nSuggest > 0)\r
-                                               pSH->AppendMenuItem(hPopup, 0, L"");\r
-\r
-                                       ptPopup = GetWordRightBottomPoint(wrLatin.EndPos);\r
-                               }\r
-                       }\r
-               }\r
-       }\r
-\r
-       IPWL_Provider* pProvider = this->GetProvider();\r
-\r
-       if (HasFlag(PES_UNDO))\r
-       {\r
-               pSH->AppendMenuItem(hPopup, WM_PWLEDIT_UNDO, \r
-                       pProvider ? pProvider->LoadPopupMenuString(0) : L"&Undo");\r
-               pSH->AppendMenuItem(hPopup, WM_PWLEDIT_REDO,\r
-                       pProvider ? pProvider->LoadPopupMenuString(1) : L"&Redo");\r
-               pSH->AppendMenuItem(hPopup, 0, L"");\r
-\r
-               if (!m_pEdit->CanUndo())\r
-                       pSH->EnableMenuItem(hPopup, WM_PWLEDIT_UNDO, FALSE);\r
-               if (!m_pEdit->CanRedo())\r
-                       pSH->EnableMenuItem(hPopup, WM_PWLEDIT_REDO, FALSE);\r
-       }\r
-\r
-       pSH->AppendMenuItem(hPopup, WM_PWLEDIT_CUT, \r
-               pProvider ? pProvider->LoadPopupMenuString(2) : L"Cu&t");\r
-       pSH->AppendMenuItem(hPopup, WM_PWLEDIT_COPY, \r
-               pProvider ? pProvider->LoadPopupMenuString(3) : L"&Copy");\r
-       pSH->AppendMenuItem(hPopup, WM_PWLEDIT_PASTE, \r
-               pProvider ? pProvider->LoadPopupMenuString(4) : L"&Paste");\r
-       pSH->AppendMenuItem(hPopup, WM_PWLEDIT_DELETE, \r
-               pProvider ? pProvider->LoadPopupMenuString(5) : L"&Delete");\r
-\r
-       CFX_WideString swText = pSH->GetClipboardText(this->GetAttachedHWnd());\r
-       if (swText.IsEmpty())\r
-               pSH->EnableMenuItem(hPopup, WM_PWLEDIT_PASTE, FALSE);\r
-\r
-       if (!m_pEdit->IsSelected())\r
-       {\r
-               pSH->EnableMenuItem(hPopup, WM_PWLEDIT_CUT, FALSE);\r
-               pSH->EnableMenuItem(hPopup, WM_PWLEDIT_COPY, FALSE);\r
-               pSH->EnableMenuItem(hPopup, WM_PWLEDIT_DELETE, FALSE);\r
-       }\r
-\r
-       if (IsReadOnly())\r
-       {\r
-               pSH->EnableMenuItem(hPopup, WM_PWLEDIT_CUT, FALSE);\r
-               pSH->EnableMenuItem(hPopup, WM_PWLEDIT_DELETE, FALSE);\r
-               pSH->EnableMenuItem(hPopup, WM_PWLEDIT_PASTE, FALSE);                   \r
-       }\r
-\r
-       if (HasFlag(PES_PASSWORD))\r
-       {\r
-               pSH->EnableMenuItem(hPopup, WM_PWLEDIT_CUT, FALSE);\r
-               pSH->EnableMenuItem(hPopup, WM_PWLEDIT_COPY, FALSE);\r
-       }\r
-\r
-       if (HasFlag(PES_NOREAD))\r
-       {\r
-               pSH->EnableMenuItem(hPopup, WM_PWLEDIT_CUT, FALSE);\r
-               pSH->EnableMenuItem(hPopup, WM_PWLEDIT_COPY, FALSE);\r
-       }\r
-\r
-       pSH->AppendMenuItem(hPopup, 0, L"");\r
-       pSH->AppendMenuItem(hPopup, WM_PWLEDIT_SELECTALL,\r
-               pProvider ? pProvider->LoadPopupMenuString(6) : L"&Select All");\r
-\r
-       if (m_pEdit->GetTotalWords() == 0)\r
-       {\r
-               pSH->EnableMenuItem(hPopup, WM_PWLEDIT_SELECTALL, FALSE);\r
-       }\r
-\r
-       FX_INT32 x, y;\r
-       PWLtoWnd(ptPopup, x, y);\r
-       pSH->ClientToScreen(GetAttachedHWnd(), x, y);\r
-       pSH->SetCursor(FXCT_ARROW);\r
-       FX_INT32 nCmd = pSH->TrackPopupMenu(hPopup,\r
-                                        x,\r
-                                        y,\r
-                                        GetAttachedHWnd());\r
-\r
-\r
-       switch (nCmd)\r
-       {\r
-       case WM_PWLEDIT_UNDO:\r
-               Undo();\r
-               break;\r
-       case WM_PWLEDIT_REDO:\r
-               Redo();\r
-               break;\r
-       case WM_PWLEDIT_CUT:\r
-               this->CutText();\r
-               break;\r
-       case WM_PWLEDIT_COPY:\r
-               this->CopyText();\r
-               break;\r
-       case WM_PWLEDIT_PASTE:\r
-               this->PasteText();\r
-               break;\r
-       case WM_PWLEDIT_DELETE:\r
-               this->Clear();\r
-               break;\r
-       case WM_PWLEDIT_SELECTALL:\r
-               this->SelectAll();\r
-               break;\r
-       case WM_PWLEDIT_SUGGEST + 0:\r
-               SetSel(m_pEdit->WordPlaceToWordIndex(wrLatin.BeginPos),m_pEdit->WordPlaceToWordIndex(wrLatin.EndPos));\r
-               ReplaceSel(sSuggestWords[0].UTF8Decode());\r
-               break;\r
-       case WM_PWLEDIT_SUGGEST + 1:\r
-               SetSel(m_pEdit->WordPlaceToWordIndex(wrLatin.BeginPos),m_pEdit->WordPlaceToWordIndex(wrLatin.EndPos));\r
-               ReplaceSel(sSuggestWords[1].UTF8Decode());\r
-               break;\r
-       case WM_PWLEDIT_SUGGEST + 2:\r
-               SetSel(m_pEdit->WordPlaceToWordIndex(wrLatin.BeginPos),m_pEdit->WordPlaceToWordIndex(wrLatin.EndPos));\r
-               ReplaceSel(sSuggestWords[2].UTF8Decode());\r
-               break;\r
-       case WM_PWLEDIT_SUGGEST + 3:\r
-               SetSel(m_pEdit->WordPlaceToWordIndex(wrLatin.BeginPos),m_pEdit->WordPlaceToWordIndex(wrLatin.EndPos));\r
-               ReplaceSel(sSuggestWords[3].UTF8Decode());\r
-               break;\r
-       case WM_PWLEDIT_SUGGEST + 4:            \r
-               SetSel(m_pEdit->WordPlaceToWordIndex(wrLatin.BeginPos),m_pEdit->WordPlaceToWordIndex(wrLatin.EndPos));\r
-               ReplaceSel(sSuggestWords[4].UTF8Decode());\r
-               break;\r
-       default:\r
-               break;\r
-       }\r
-\r
-       pSH->DestroyMenu(hPopup);\r
-\r
-       return TRUE;\r
-}\r
-\r
-void CPWL_Edit::OnSetFocus()\r
-{\r
-       SetEditCaret(TRUE);\r
-\r
-       if (!IsReadOnly())\r
-       {\r
-               if (IPWL_FocusHandler* pFocusHandler = GetFocusHandler())\r
-                       pFocusHandler->OnSetFocus(this);\r
-       }\r
-\r
-       m_bFocus = TRUE;\r
-}\r
-\r
-void CPWL_Edit::OnKillFocus()\r
-{\r
-       ShowVScrollBar(FALSE);\r
-       \r
-       m_pEdit->SelectNone();\r
-       SetCaret(FALSE, CPDF_Point(0.0f,0.0f), CPDF_Point(0.0f,0.0f));\r
-       \r
-       SetCharSet(0);\r
-\r
-       if (!IsReadOnly())\r
-       {\r
-               if (IPWL_FocusHandler* pFocusHandler = GetFocusHandler())\r
-                       pFocusHandler->OnKillFocus(this);\r
-       }\r
-\r
-       m_bFocus = FALSE;\r
-}\r
-\r
-void CPWL_Edit::SetHorzScale(FX_INT32 nHorzScale, FX_BOOL bPaint/* = TRUE*/)\r
-{\r
-       m_pEdit->SetHorzScale(nHorzScale, bPaint);\r
-}\r
-\r
-void CPWL_Edit::SetCharSpace(FX_FLOAT fCharSpace, FX_BOOL bPaint/* = TRUE*/)\r
-{\r
-       m_pEdit->SetCharSpace(fCharSpace, bPaint);\r
-}\r
-\r
-void CPWL_Edit::SetLineLeading(FX_FLOAT fLineLeading, FX_BOOL bPaint/* = TRUE*/)\r
-{\r
-       m_pEdit->SetLineLeading(fLineLeading, bPaint);\r
-}\r
-\r
-CFX_ByteString CPWL_Edit::GetSelectAppearanceStream(const CPDF_Point & ptOffset) const\r
-{\r
-       CPVT_WordRange wr = GetSelectWordRange();\r
-       return CPWL_Utils::GetEditSelAppStream(m_pEdit,ptOffset,&wr);\r
-}\r
-\r
-CPVT_WordRange CPWL_Edit::GetSelectWordRange() const\r
-{\r
-       if (m_pEdit->IsSelected())\r
-       {\r
-               FX_INT32 nStart = -1;\r
-               FX_INT32 nEnd = -1;\r
-\r
-               m_pEdit->GetSel(nStart, nEnd);\r
-\r
-               CPVT_WordPlace wpStart = m_pEdit->WordIndexToWordPlace(nStart);\r
-               CPVT_WordPlace wpEnd = m_pEdit->WordIndexToWordPlace(nEnd);\r
-\r
-               return CPVT_WordRange(wpStart,wpEnd);\r
-       }\r
-\r
-       return CPVT_WordRange();\r
-}\r
-\r
-CFX_ByteString CPWL_Edit::GetTextAppearanceStream(const CPDF_Point & ptOffset) const\r
-{\r
-       CFX_ByteTextBuf sRet;\r
-       CFX_ByteString sEdit = CPWL_Utils::GetEditAppStream(m_pEdit,ptOffset);\r
-       \r
-       if (sEdit.GetLength() > 0)\r
-       {\r
-               sRet << "BT\n" << CPWL_Utils::GetColorAppStream(GetTextColor()) << sEdit << "ET\n";\r
-       }\r
-\r
-       return sRet.GetByteString();\r
-}\r
-\r
-CFX_ByteString CPWL_Edit::GetCaretAppearanceStream(const CPDF_Point & ptOffset) const\r
-{\r
-       if (m_pEditCaret)\r
-               return m_pEditCaret->GetCaretAppearanceStream(ptOffset);\r
-\r
-       return CFX_ByteString();\r
-}\r
-\r
-CPDF_Point CPWL_Edit::GetWordRightBottomPoint(const CPVT_WordPlace& wpWord)\r
-{\r
-       CPDF_Point pt(0.0f, 0.0f);\r
-\r
-       if (IFX_Edit_Iterator * pIterator = m_pEdit->GetIterator())\r
-       {\r
-               CPVT_WordPlace wpOld = pIterator->GetAt();\r
-               pIterator->SetAt(wpWord);\r
-               CPVT_Word word;\r
-               if (pIterator->GetWord(word))\r
-               {\r
-                       pt = CPDF_Point(word.ptWord.x + word.fWidth, word.ptWord.y + word.fDescent);\r
-               }\r
-\r
-               pIterator->SetAt(wpOld);\r
-       }\r
-\r
-       return pt;\r
-}\r
-\r
-FX_BOOL        CPWL_Edit::IsTextFull() const\r
-{\r
-       return m_pEdit->IsTextFull();\r
-}\r
-\r
-FX_FLOAT CPWL_Edit::GetCharArrayAutoFontSize(CPDF_Font* pFont, const CPDF_Rect& rcPlate, FX_INT32 nCharArray)\r
-{\r
-       if (pFont && !pFont->IsStandardFont())\r
-       {\r
-               FX_RECT rcBBox;\r
-               pFont->GetFontBBox(rcBBox);\r
-\r
-               CPDF_Rect rcCell = rcPlate;\r
-               FX_FLOAT xdiv = rcCell.Width() / nCharArray * 1000.0f / rcBBox.Width();\r
-               FX_FLOAT ydiv = - rcCell.Height() * 1000.0f / rcBBox.Height();\r
-\r
-               return xdiv < ydiv ? xdiv : ydiv;\r
-       }\r
-\r
-       return 0.0f;\r
-}\r
-\r
-void CPWL_Edit::SetCharArray(FX_INT32 nCharArray)\r
-{\r
-       if (HasFlag(PES_CHARARRAY) && nCharArray > 0)\r
-       {\r
-               m_pEdit->SetCharArray(nCharArray);      \r
-               m_pEdit->SetTextOverflow(TRUE);\r
-\r
-               if (HasFlag(PWS_AUTOFONTSIZE))\r
-               {\r
-                       if (IFX_Edit_FontMap* pFontMap = this->GetFontMap())\r
-                       {\r
-                               FX_FLOAT fFontSize = GetCharArrayAutoFontSize(pFontMap->GetPDFFont(0), GetClientRect(), nCharArray);\r
-                               if (fFontSize > 0.0f)\r
-                               {\r
-                                       m_pEdit->SetAutoFontSize(FALSE);\r
-                                       m_pEdit->SetFontSize(fFontSize);\r
-                               }\r
-                       }\r
-               }\r
-       }\r
-}\r
-\r
-void CPWL_Edit::SetLimitChar(FX_INT32 nLimitChar)\r
-{\r
-       m_pEdit->SetLimitChar(nLimitChar);\r
-}\r
-\r
-void CPWL_Edit::ReplaceSel(FX_LPCWSTR csText)\r
-{\r
-       m_pEdit->Clear();\r
-       m_pEdit->InsertText(csText);\r
-}\r
-\r
-CPDF_Rect CPWL_Edit::GetFocusRect() const\r
-{\r
-       return CPDF_Rect();\r
-}\r
-\r
-void CPWL_Edit::ShowVScrollBar(FX_BOOL bShow)\r
-{\r
-       if (CPWL_ScrollBar * pScroll = GetVScrollBar())\r
-       {\r
-               if (bShow)\r
-               {\r
-                       if (!pScroll->IsVisible())\r
-                       {\r
-                               pScroll->SetVisible(TRUE);\r
-                               CPDF_Rect rcWindow = GetWindowRect();\r
-                               m_rcOldWindow = rcWindow;\r
-                               rcWindow.right += PWL_SCROLLBAR_WIDTH;                  \r
-                               Move(rcWindow, TRUE, TRUE);\r
-                       }\r
-               }\r
-               else\r
-               {\r
-                       if (pScroll->IsVisible())\r
-                       {\r
-                               pScroll->SetVisible(FALSE);\r
-                               Move(m_rcOldWindow, TRUE, TRUE);\r
-                       }       \r
-               }\r
-       }\r
-}\r
-\r
-FX_BOOL        CPWL_Edit::IsVScrollBarVisible() const\r
-{\r
-       if (CPWL_ScrollBar * pScroll = GetVScrollBar())\r
-       {\r
-               return pScroll->IsVisible();\r
-       }\r
-\r
-       return FALSE;\r
-}\r
-\r
-void CPWL_Edit::EnableSpellCheck(FX_BOOL bEnabled)\r
-{\r
-       if (bEnabled)\r
-               AddFlag(PES_SPELLCHECK);\r
-       else\r
-               RemoveFlag(PES_SPELLCHECK);\r
-}\r
-\r
-FX_BOOL CPWL_Edit::OnKeyDown(FX_WORD nChar, FX_DWORD nFlag)\r
-{\r
-       if (m_bMouseDown) return TRUE;\r
-\r
-       if (nChar == FWL_VKEY_Delete)\r
-       {\r
-               if (m_pFillerNotify)\r
-               {\r
-                       FX_BOOL bRC = TRUE;\r
-                       FX_BOOL bExit = FALSE;\r
-                       CFX_WideString strChange;\r
-                       CFX_WideString strChangeEx;\r
-\r
-                       int nSelStart = 0;\r
-                       int nSelEnd = 0;\r
-                       GetSel(nSelStart, nSelEnd);\r
-\r
-                       if (nSelStart == nSelEnd)\r
-                               nSelEnd = nSelStart + 1;\r
-                       m_pFillerNotify->OnBeforeKeyStroke(TRUE, GetAttachedData(), FWL_VKEY_Delete, strChange, strChangeEx, nSelStart, nSelEnd, TRUE, bRC, bExit, nFlag);\r
-                       if (!bRC) return FALSE;                         \r
-                       if (bExit) return FALSE;\r
-               }\r
-       }\r
-\r
-       FX_BOOL bRet = CPWL_EditCtrl::OnKeyDown(nChar,  nFlag);\r
-\r
-       if (nChar == FWL_VKEY_Delete)\r
-       {\r
-               if (m_pFillerNotify)\r
-               {\r
-                       FX_BOOL bExit = FALSE;\r
-                       m_pFillerNotify->OnAfterKeyStroke(TRUE, GetAttachedData(), bExit,nFlag);\r
-                       if (bExit) return FALSE;\r
-               }\r
-       }\r
-\r
-       //In case of implementation swallow the OnKeyDown event.\r
-       if(IsProceedtoOnChar(nChar, nFlag))\r
-                       return TRUE;\r
-\r
-       return bRet;\r
-}\r
-\r
-/**\r
-*In case of implementation swallow the OnKeyDown event. \r
-*If the event is swallowed, implementation may do other unexpected things, which is not the control means to do.\r
-*/\r
-FX_BOOL CPWL_Edit::IsProceedtoOnChar(FX_WORD nKeyCode, FX_DWORD nFlag)\r
-{\r
-\r
-       FX_BOOL bCtrl = IsCTRLpressed(nFlag);\r
-       FX_BOOL bAlt = IsALTpressed(nFlag);\r
-       if(bCtrl && !bAlt)\r
-       {\r
-       //hot keys for edit control.    \r
-               switch(nKeyCode)\r
-               {\r
-               case 'C':\r
-               case 'V':\r
-               case 'X':\r
-               case 'A':\r
-               case 'Z':\r
-                       return TRUE;\r
-               default:\r
-                       break;\r
-               }\r
-       }\r
-       //control characters.\r
-       switch(nKeyCode)\r
-       {\r
-       case FWL_VKEY_Escape:\r
-       case FWL_VKEY_Back:\r
-       case FWL_VKEY_Return:\r
-       case FWL_VKEY_Space:\r
-               return TRUE;\r
-       default:\r
-               break;\r
-       }\r
-       return FALSE;\r
-\r
-}\r
-\r
-FX_BOOL CPWL_Edit::OnChar(FX_WORD nChar, FX_DWORD nFlag)\r
-{\r
-       if (m_bMouseDown) return TRUE;\r
-\r
-       FX_BOOL bRC = TRUE;\r
-       FX_BOOL bExit = FALSE;\r
-\r
-       FX_BOOL bCtrl = IsCTRLpressed(nFlag);\r
-       if (!bCtrl)\r
-       {\r
-               if (m_pFillerNotify)\r
-               {\r
-                       CFX_WideString swChange;\r
-                       FX_INT32 nKeyCode;\r
-\r
-                       int nSelStart = 0;\r
-                       int nSelEnd = 0;\r
-                       GetSel(nSelStart, nSelEnd);\r
-\r
-                       switch (nChar)\r
-                       {\r
-                       case FWL_VKEY_Back:\r
-                               nKeyCode = nChar;\r
-                               if (nSelStart == nSelEnd)\r
-                                       nSelStart = nSelEnd - 1;\r
-                               break;\r
-                       case FWL_VKEY_Return:\r
-                               nKeyCode = nChar;\r
-                               break;\r
-                       default:\r
-                               nKeyCode = 0;\r
-                               swChange += nChar;\r
-                               break;\r
-                       }\r
-               \r
-                       CFX_WideString strChangeEx;\r
-                       m_pFillerNotify->OnBeforeKeyStroke(TRUE, GetAttachedData(), nKeyCode, swChange, strChangeEx, nSelStart, nSelEnd, TRUE, bRC, bExit, nFlag);\r
-               }\r
-       }\r
-\r
-       if (!bRC) return TRUE;\r
-       if (bExit) return FALSE;\r
-\r
-       if (IFX_Edit_FontMap * pFontMap = GetFontMap())\r
-       {\r
-               FX_INT32 nOldCharSet = GetCharSet();\r
-               FX_INT32 nNewCharSet = pFontMap->CharSetFromUnicode(nChar, DEFAULT_CHARSET);\r
-               if(nOldCharSet != nNewCharSet)\r
-               {\r
-                       SetCharSet(nNewCharSet);\r
-               }\r
-       }\r
-       FX_BOOL bRet = CPWL_EditCtrl::OnChar(nChar,nFlag);\r
-\r
-       if (!bCtrl)\r
-       {\r
-               if (m_pFillerNotify)\r
-               {\r
-                       m_pFillerNotify->OnAfterKeyStroke(TRUE, GetAttachedData(), bExit,nFlag);\r
-                       if (bExit) return FALSE;\r
-               }\r
-       }\r
-\r
-       return bRet;\r
-}\r
-\r
-FX_BOOL        CPWL_Edit::OnMouseWheel(short zDelta, const CPDF_Point & point, FX_DWORD nFlag)\r
-{\r
-       if (HasFlag(PES_MULTILINE))\r
-       {\r
-               CPDF_Point ptScroll = GetScrollPos();\r
-\r
-               if (zDelta > 0)\r
-               {\r
-                       ptScroll.y += this->GetFontSize();\r
-               }\r
-               else\r
-               {\r
-                       ptScroll.y -= this->GetFontSize();\r
-               }\r
-               this->SetScrollPos(ptScroll);\r
-\r
-               return TRUE;\r
-       }\r
-\r
-       return FALSE;\r
-}\r
-\r
-void CPWL_Edit::OnInsertReturn(const CPVT_WordPlace& place, const CPVT_WordPlace& oldplace)\r
-{\r
-       if (HasFlag(PES_SPELLCHECK))\r
-       {\r
-               m_pEdit->RefreshWordRange(CombineWordRange(GetLatinWordsRange(oldplace),GetLatinWordsRange(place)));\r
-       }\r
-\r
-       if (m_pEditNotify)\r
-       {\r
-               m_pEditNotify->OnInsertReturn(place, oldplace);\r
-       }\r
-}\r
-\r
-void CPWL_Edit::OnBackSpace(const CPVT_WordPlace& place, const CPVT_WordPlace& oldplace)\r
-{\r
-       if (HasFlag(PES_SPELLCHECK))\r
-       {\r
-               m_pEdit->RefreshWordRange(CombineWordRange(GetLatinWordsRange(oldplace),GetLatinWordsRange(place)));\r
-       }\r
-\r
-       if (m_pEditNotify)\r
-       {\r
-               m_pEditNotify->OnBackSpace(place, oldplace);\r
-       }\r
-}\r
-\r
-void CPWL_Edit::OnDelete(const CPVT_WordPlace& place, const CPVT_WordPlace& oldplace)\r
-{\r
-       if (HasFlag(PES_SPELLCHECK))\r
-       {\r
-               m_pEdit->RefreshWordRange(CombineWordRange(GetLatinWordsRange(oldplace),GetLatinWordsRange(place)));\r
-       }\r
-\r
-       if (m_pEditNotify)\r
-       {\r
-               m_pEditNotify->OnDelete(place, oldplace);\r
-       }\r
-}\r
-\r
-void CPWL_Edit::OnClear(const CPVT_WordPlace& place, const CPVT_WordPlace& oldplace)\r
-{\r
-       if (HasFlag(PES_SPELLCHECK))\r
-       {\r
-               m_pEdit->RefreshWordRange(CombineWordRange(GetLatinWordsRange(oldplace),GetLatinWordsRange(place)));\r
-       }\r
-\r
-       if (m_pEditNotify)\r
-       {\r
-               m_pEditNotify->OnClear(place, oldplace);\r
-       }\r
-}\r
-\r
-void CPWL_Edit::OnInsertWord(const CPVT_WordPlace& place, const CPVT_WordPlace& oldplace)\r
-{\r
-       if (HasFlag(PES_SPELLCHECK))\r
-       {\r
-               m_pEdit->RefreshWordRange(CombineWordRange(GetLatinWordsRange(oldplace),GetLatinWordsRange(place)));\r
-       }\r
-\r
-       if (m_pEditNotify)\r
-       {\r
-               m_pEditNotify->OnInsertWord(place, oldplace);\r
-       }\r
-}\r
-\r
-void CPWL_Edit::OnSetText(const CPVT_WordPlace& place, const CPVT_WordPlace& oldplace)\r
-{\r
-}\r
-\r
-void CPWL_Edit::OnInsertText(const CPVT_WordPlace& place, const CPVT_WordPlace& oldplace)\r
-{\r
-       if (HasFlag(PES_SPELLCHECK))\r
-       {\r
-               m_pEdit->RefreshWordRange(CombineWordRange(GetLatinWordsRange(oldplace),GetLatinWordsRange(place)));\r
-       }\r
-\r
-       if (m_pEditNotify)\r
-       {\r
-               m_pEditNotify->OnInsertText(place, oldplace);\r
-       }\r
-}\r
-\r
-void CPWL_Edit::OnAddUndo(IFX_Edit_UndoItem* pUndoItem)\r
-{\r
-       if (m_pEditNotify)\r
-       {\r
-               m_pEditNotify->OnAddUndo(this);\r
-       }\r
-}\r
-\r
-CPVT_WordRange CPWL_Edit::CombineWordRange(const CPVT_WordRange& wr1, const CPVT_WordRange& wr2)\r
-{\r
-       CPVT_WordRange wrRet;\r
-\r
-       if (wr1.BeginPos.WordCmp(wr2.BeginPos) < 0)\r
-       {\r
-               wrRet.BeginPos = wr1.BeginPos;\r
-       }\r
-       else\r
-       {\r
-               wrRet.BeginPos = wr2.BeginPos;\r
-       }\r
-\r
-       if (wr1.EndPos.WordCmp(wr2.EndPos) < 0)\r
-       {\r
-               wrRet.EndPos = wr2.EndPos;\r
-       }\r
-       else\r
-       {\r
-               wrRet.EndPos = wr1.EndPos;\r
-       }\r
-\r
-       return wrRet;\r
-}\r
-\r
-CPVT_WordRange CPWL_Edit::GetLatinWordsRange(const CPDF_Point& point) const\r
-{\r
-       return GetSameWordsRange(m_pEdit->SearchWordPlace(point), TRUE, FALSE);\r
-}\r
-\r
-CPVT_WordRange CPWL_Edit::GetLatinWordsRange(const CPVT_WordPlace & place) const\r
-{\r
-       return GetSameWordsRange(place, TRUE, FALSE);\r
-}\r
-\r
-CPVT_WordRange CPWL_Edit::GetArabicWordsRange(const CPVT_WordPlace & place) const\r
-{\r
-       return GetSameWordsRange(place, FALSE, TRUE);\r
-}\r
-\r
-#define PWL_ISARABICWORD(word) ((word >= 0x0600 && word <= 0x06FF) || (word >= 0xFB50 && word <= 0xFEFC))\r
-\r
-CPVT_WordRange CPWL_Edit::GetSameWordsRange(const CPVT_WordPlace & place, FX_BOOL bLatin, FX_BOOL bArabic) const\r
-{\r
-       CPVT_WordRange range;\r
-\r
-       if (IFX_Edit_Iterator* pIterator = m_pEdit->GetIterator())\r
-       {\r
-               CPVT_Word wordinfo;     \r
-               CPVT_WordPlace wpStart(place),wpEnd(place);                     \r
-               pIterator->SetAt(place);                        \r
-               \r
-               if (bLatin)\r
-               {\r
-                       while (pIterator->NextWord())\r
-                       {\r
-                               if (pIterator->GetWord(wordinfo) && FX_EDIT_ISLATINWORD(wordinfo.Word))\r
-                               {\r
-                                       wpEnd = pIterator->GetAt();\r
-                                       continue;\r
-                               }\r
-                               else \r
-                                       break;\r
-                       };\r
-               }\r
-               else if (bArabic)\r
-               {\r
-                       while (pIterator->NextWord())\r
-                       {\r
-                               if (pIterator->GetWord(wordinfo) && PWL_ISARABICWORD(wordinfo.Word))\r
-                               {\r
-                                       wpEnd = pIterator->GetAt();\r
-                                       continue;\r
-                               }\r
-                               else \r
-                                       break;\r
-                       };\r
-               }\r
-\r
-               pIterator->SetAt(place);\r
-\r
-               if (bLatin)\r
-               {\r
-                       do\r
-                       {\r
-                               if (pIterator->GetWord(wordinfo) && FX_EDIT_ISLATINWORD(wordinfo.Word))\r
-                               {                                       \r
-                                       continue;\r
-                               }\r
-                               else\r
-                               {\r
-                                       wpStart = pIterator->GetAt();\r
-                                       break;\r
-                               }\r
-                       }\r
-                       while (pIterator->PrevWord());\r
-               }\r
-               else if (bArabic)\r
-               {\r
-                       do\r
-                       {\r
-                               if (pIterator->GetWord(wordinfo) && PWL_ISARABICWORD(wordinfo.Word))\r
-                               {                                       \r
-                                       continue;\r
-                               }\r
-                               else\r
-                               {\r
-                                       wpStart = pIterator->GetAt();\r
-                                       break;\r
-                               }\r
-                       }\r
-                       while (pIterator->PrevWord());\r
-               }\r
-\r
-               range.Set(wpStart,wpEnd);\r
-       }       \r
-\r
-       return range;\r
-}\r
-\r
-void CPWL_Edit::AjustArabicWords(const CPVT_WordRange& wr)\r
-{\r
-}\r
-\r
-void CPWL_Edit::GeneratePageObjects(CPDF_PageObjects* pPageObjects, \r
-                                                                               const CPDF_Point& ptOffset, CFX_ArrayTemplate<CPDF_TextObject*>& ObjArray)\r
-{\r
-       IFX_Edit::GeneratePageObjects(pPageObjects, m_pEdit, ptOffset, NULL, CPWL_Utils::PWLColorToFXColor(GetTextColor(),GetTransparency()), ObjArray);\r
-}\r
-\r
-void CPWL_Edit::GeneratePageObjects(CPDF_PageObjects* pPageObjects, \r
-                                                                       const CPDF_Point& ptOffset)\r
-{\r
-       CFX_ArrayTemplate<CPDF_TextObject*> ObjArray;\r
-       IFX_Edit::GeneratePageObjects(pPageObjects, m_pEdit, ptOffset, NULL, CPWL_Utils::PWLColorToFXColor(GetTextColor(),GetTransparency()), ObjArray);\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 "../../../core/include/fxcrt/fx_safe_types.h"
+#include "../../../core/include/fxcrt/fx_xml.h"
+#include "../../include/pdfwindow/PDFWindow.h"
+#include "../../include/pdfwindow/PWL_Caret.h"
+#include "../../include/pdfwindow/PWL_Edit.h"
+#include "../../include/pdfwindow/PWL_EditCtrl.h"
+#include "../../include/pdfwindow/PWL_FontMap.h"
+#include "../../include/pdfwindow/PWL_ScrollBar.h"
+#include "../../include/pdfwindow/PWL_Utils.h"
+#include "../../include/pdfwindow/PWL_Wnd.h"
+
+/* ---------------------------- CPWL_Edit ------------------------------ */
+
+CPWL_Edit::CPWL_Edit()
+    : m_pFillerNotify(NULL), m_pSpellCheck(NULL), m_bFocus(FALSE) {
+  m_pFormFiller = NULL;
+}
+
+CPWL_Edit::~CPWL_Edit() {
+  ASSERT(m_bFocus == FALSE);
+}
+
+CFX_ByteString CPWL_Edit::GetClassName() const {
+  return PWL_CLASSNAME_EDIT;
+}
+
+void CPWL_Edit::OnDestroy() {}
+
+void CPWL_Edit::SetText(const FX_WCHAR* csText) {
+  CFX_WideString swText = csText;
+
+  if (HasFlag(PES_RICH)) {
+    CFX_ByteString sValue = CFX_ByteString::FromUnicode(swText);
+
+    if (CXML_Element* pXML =
+            CXML_Element::Parse(sValue.c_str(), sValue.GetLength())) {
+      int32_t nCount = pXML->CountChildren();
+      FX_BOOL bFirst = TRUE;
+
+      swText.Empty();
+
+      for (int32_t i = 0; i < nCount; i++) {
+        if (CXML_Element* pSubElement = pXML->GetElement(i)) {
+          CFX_ByteString tag = pSubElement->GetTagName();
+          if (tag.EqualNoCase("p")) {
+            int nChild = pSubElement->CountChildren();
+            CFX_WideString swSection;
+            for (int32_t j = 0; j < nChild; j++) {
+              swSection += pSubElement->GetContent(j);
+            }
+
+            if (bFirst)
+              bFirst = FALSE;
+            else
+              swText += FWL_VKEY_Return;
+            swText += swSection;
+          }
+        }
+      }
+
+      delete pXML;
+    }
+  }
+
+  m_pEdit->SetText(swText.c_str());
+}
+
+void CPWL_Edit::RePosChildWnd() {
+  if (CPWL_ScrollBar* pVSB = GetVScrollBar()) {
+    CPDF_Rect rcWindow = m_rcOldWindow;
+    CPDF_Rect rcVScroll =
+        CPDF_Rect(rcWindow.right, rcWindow.bottom,
+                  rcWindow.right + PWL_SCROLLBAR_WIDTH, rcWindow.top);
+    pVSB->Move(rcVScroll, TRUE, FALSE);
+  }
+
+  if (m_pEditCaret && !HasFlag(PES_TEXTOVERFLOW))
+    m_pEditCaret->SetClipRect(CPWL_Utils::InflateRect(
+        GetClientRect(), 1.0f));  //+1 for caret beside border
+
+  CPWL_EditCtrl::RePosChildWnd();
+}
+
+CPDF_Rect CPWL_Edit::GetClientRect() const {
+  CPDF_Rect rcClient = CPWL_Utils::DeflateRect(
+      GetWindowRect(), (FX_FLOAT)(GetBorderWidth() + GetInnerBorderWidth()));
+
+  if (CPWL_ScrollBar* pVSB = GetVScrollBar()) {
+    if (pVSB->IsVisible()) {
+      rcClient.right -= PWL_SCROLLBAR_WIDTH;
+    }
+  }
+
+  return rcClient;
+}
+
+void CPWL_Edit::SetAlignFormatH(PWL_EDIT_ALIGNFORMAT_H nFormat,
+                                FX_BOOL bPaint /* = TRUE*/) {
+  m_pEdit->SetAlignmentH((int32_t)nFormat, bPaint);
+}
+
+void CPWL_Edit::SetAlignFormatV(PWL_EDIT_ALIGNFORMAT_V nFormat,
+                                FX_BOOL bPaint /* = TRUE*/) {
+  m_pEdit->SetAlignmentV((int32_t)nFormat, bPaint);
+}
+
+FX_BOOL CPWL_Edit::CanSelectAll() const {
+  return GetSelectWordRange() != m_pEdit->GetWholeWordRange();
+}
+
+FX_BOOL CPWL_Edit::CanClear() const {
+  return !IsReadOnly() && m_pEdit->IsSelected();
+}
+
+FX_BOOL CPWL_Edit::CanCopy() const {
+  return !HasFlag(PES_PASSWORD) && !HasFlag(PES_NOREAD) &&
+         m_pEdit->IsSelected();
+}
+
+FX_BOOL CPWL_Edit::CanCut() const {
+  return CanCopy() && !IsReadOnly();
+}
+
+FX_BOOL CPWL_Edit::CanPaste() const {
+  if (IsReadOnly())
+    return FALSE;
+
+  CFX_WideString swClipboard;
+  if (IFX_SystemHandler* pSH = GetSystemHandler())
+    swClipboard = pSH->GetClipboardText(GetAttachedHWnd());
+
+  return !swClipboard.IsEmpty();
+}
+
+void CPWL_Edit::CopyText() {
+  if (!CanCopy())
+    return;
+
+  CFX_WideString str = m_pEdit->GetSelText();
+
+  if (IFX_SystemHandler* pSH = GetSystemHandler())
+    pSH->SetClipboardText(GetAttachedHWnd(), str);
+}
+
+void CPWL_Edit::PasteText() {
+  if (!CanPaste())
+    return;
+
+  CFX_WideString swClipboard;
+  if (IFX_SystemHandler* pSH = GetSystemHandler())
+    swClipboard = pSH->GetClipboardText(GetAttachedHWnd());
+
+  if (m_pFillerNotify) {
+    FX_BOOL bRC = TRUE;
+    FX_BOOL bExit = FALSE;
+    CFX_WideString strChangeEx;
+    int nSelStart = 0;
+    int nSelEnd = 0;
+    GetSel(nSelStart, nSelEnd);
+    m_pFillerNotify->OnBeforeKeyStroke(GetAttachedData(), swClipboard,
+                                       strChangeEx, nSelStart, nSelEnd, TRUE,
+                                       bRC, bExit, 0);
+    if (!bRC)
+      return;
+    if (bExit)
+      return;
+  }
+
+  if (swClipboard.GetLength() > 0) {
+    Clear();
+    InsertText(swClipboard.c_str());
+  }
+}
+
+void CPWL_Edit::CutText() {
+  if (!CanCut())
+    return;
+
+  CFX_WideString str = m_pEdit->GetSelText();
+
+  if (IFX_SystemHandler* pSH = GetSystemHandler())
+    pSH->SetClipboardText(GetAttachedHWnd(), str);
+
+  m_pEdit->Clear();
+}
+
+void CPWL_Edit::OnCreated() {
+  CPWL_EditCtrl::OnCreated();
+
+  if (CPWL_ScrollBar* pScroll = GetVScrollBar()) {
+    pScroll->RemoveFlag(PWS_AUTOTRANSPARENT);
+    pScroll->SetTransparency(255);
+  }
+
+  SetParamByFlag();
+
+  m_rcOldWindow = GetWindowRect();
+
+  m_pEdit->SetOprNotify(this);
+  m_pEdit->EnableOprNotify(TRUE);
+}
+
+void CPWL_Edit::SetParamByFlag() {
+  if (HasFlag(PES_RIGHT)) {
+    m_pEdit->SetAlignmentH(2, FALSE);
+  } else if (HasFlag(PES_MIDDLE)) {
+    m_pEdit->SetAlignmentH(1, FALSE);
+  } else {
+    m_pEdit->SetAlignmentH(0, FALSE);
+  }
+
+  if (HasFlag(PES_BOTTOM)) {
+    m_pEdit->SetAlignmentV(2, FALSE);
+  } else if (HasFlag(PES_CENTER)) {
+    m_pEdit->SetAlignmentV(1, FALSE);
+  } else {
+    m_pEdit->SetAlignmentV(0, FALSE);
+  }
+
+  if (HasFlag(PES_PASSWORD)) {
+    m_pEdit->SetPasswordChar('*', FALSE);
+  }
+
+  m_pEdit->SetMultiLine(HasFlag(PES_MULTILINE), FALSE);
+  m_pEdit->SetAutoReturn(HasFlag(PES_AUTORETURN), FALSE);
+  m_pEdit->SetAutoFontSize(HasFlag(PWS_AUTOFONTSIZE), FALSE);
+  m_pEdit->SetAutoScroll(HasFlag(PES_AUTOSCROLL), FALSE);
+  m_pEdit->EnableUndo(HasFlag(PES_UNDO));
+
+  if (HasFlag(PES_TEXTOVERFLOW)) {
+    SetClipRect(CPDF_Rect(0.0f, 0.0f, 0.0f, 0.0f));
+    m_pEdit->SetTextOverflow(TRUE, FALSE);
+  } else {
+    if (m_pEditCaret) {
+      m_pEditCaret->SetClipRect(CPWL_Utils::InflateRect(
+          GetClientRect(), 1.0f));  //+1 for caret beside border
+    }
+  }
+
+  if (HasFlag(PES_SPELLCHECK)) {
+    m_pSpellCheck = GetCreationParam().pSpellCheck;
+  }
+}
+
+void CPWL_Edit::GetThisAppearanceStream(CFX_ByteTextBuf& sAppStream) {
+  CPWL_Wnd::GetThisAppearanceStream(sAppStream);
+
+  CPDF_Rect rcClient = GetClientRect();
+  CFX_ByteTextBuf sLine;
+
+  int32_t nCharArray = m_pEdit->GetCharArray();
+
+  if (nCharArray > 0) {
+    switch (GetBorderStyle()) {
+      case PBS_SOLID: {
+        sLine << "q\n" << GetBorderWidth() << " w\n"
+              << CPWL_Utils::GetColorAppStream(GetBorderColor(), FALSE)
+              << " 2 J 0 j\n";
+
+        for (int32_t i = 1; i < nCharArray; i++) {
+          sLine << rcClient.left +
+                       ((rcClient.right - rcClient.left) / nCharArray) * i
+                << " " << rcClient.bottom << " m\n"
+                << rcClient.left +
+                       ((rcClient.right - rcClient.left) / nCharArray) * i
+                << " " << rcClient.top << " l S\n";
+        }
+
+        sLine << "Q\n";
+      } break;
+      case PBS_DASH: {
+        sLine << "q\n" << GetBorderWidth() << " w\n"
+              << CPWL_Utils::GetColorAppStream(GetBorderColor(), FALSE)
+              << " 2 J 0 j\n"
+              << "[" << GetBorderDash().nDash << " " << GetBorderDash().nGap
+              << "] " << GetBorderDash().nPhase << " d\n";
+
+        for (int32_t i = 1; i < nCharArray; i++) {
+          sLine << rcClient.left +
+                       ((rcClient.right - rcClient.left) / nCharArray) * i
+                << " " << rcClient.bottom << " m\n"
+                << rcClient.left +
+                       ((rcClient.right - rcClient.left) / nCharArray) * i
+                << " " << rcClient.top << " l S\n";
+        }
+
+        sLine << "Q\n";
+      } break;
+    }
+  }
+
+  sAppStream << sLine;
+
+  CFX_ByteTextBuf sText;
+
+  CPDF_Point ptOffset = CPDF_Point(0.0f, 0.0f);
+
+  CPVT_WordRange wrWhole = m_pEdit->GetWholeWordRange();
+  CPVT_WordRange wrSelect = GetSelectWordRange();
+  CPVT_WordRange wrVisible =
+      (HasFlag(PES_TEXTOVERFLOW) ? wrWhole : m_pEdit->GetVisibleWordRange());
+  CPVT_WordRange wrSelBefore(wrWhole.BeginPos, wrSelect.BeginPos);
+  CPVT_WordRange wrSelAfter(wrSelect.EndPos, wrWhole.EndPos);
+
+  CPVT_WordRange wrTemp =
+      CPWL_Utils::OverlapWordRange(GetSelectWordRange(), wrVisible);
+  CFX_ByteString sEditSel =
+      CPWL_Utils::GetEditSelAppStream(m_pEdit, ptOffset, &wrTemp);
+
+  if (sEditSel.GetLength() > 0)
+    sText << CPWL_Utils::GetColorAppStream(PWL_DEFAULT_SELBACKCOLOR)
+          << sEditSel;
+
+  wrTemp = CPWL_Utils::OverlapWordRange(wrVisible, wrSelBefore);
+  CFX_ByteString sEditBefore = CPWL_Utils::GetEditAppStream(
+      m_pEdit, ptOffset, &wrTemp, !HasFlag(PES_CHARARRAY),
+      m_pEdit->GetPasswordChar());
+
+  if (sEditBefore.GetLength() > 0)
+    sText << "BT\n" << CPWL_Utils::GetColorAppStream(GetTextColor())
+          << sEditBefore << "ET\n";
+
+  wrTemp = CPWL_Utils::OverlapWordRange(wrVisible, wrSelect);
+  CFX_ByteString sEditMid = CPWL_Utils::GetEditAppStream(
+      m_pEdit, ptOffset, &wrTemp, !HasFlag(PES_CHARARRAY),
+      m_pEdit->GetPasswordChar());
+
+  if (sEditMid.GetLength() > 0)
+    sText << "BT\n"
+          << CPWL_Utils::GetColorAppStream(CPWL_Color(COLORTYPE_GRAY, 1))
+          << sEditMid << "ET\n";
+
+  wrTemp = CPWL_Utils::OverlapWordRange(wrVisible, wrSelAfter);
+  CFX_ByteString sEditAfter = CPWL_Utils::GetEditAppStream(
+      m_pEdit, ptOffset, &wrTemp, !HasFlag(PES_CHARARRAY),
+      m_pEdit->GetPasswordChar());
+
+  if (sEditAfter.GetLength() > 0)
+    sText << "BT\n" << CPWL_Utils::GetColorAppStream(GetTextColor())
+          << sEditAfter << "ET\n";
+
+  if (HasFlag(PES_SPELLCHECK)) {
+    CFX_ByteString sSpellCheck = CPWL_Utils::GetSpellCheckAppStream(
+        m_pEdit, m_pSpellCheck, ptOffset, &wrVisible);
+    if (sSpellCheck.GetLength() > 0)
+      sText << CPWL_Utils::GetColorAppStream(CPWL_Color(COLORTYPE_RGB, 1, 0, 0),
+                                             FALSE)
+            << sSpellCheck;
+  }
+
+  if (sText.GetLength() > 0) {
+    CPDF_Rect rcClient = GetClientRect();
+    sAppStream << "q\n/Tx BMC\n";
+
+    if (!HasFlag(PES_TEXTOVERFLOW))
+      sAppStream << rcClient.left << " " << rcClient.bottom << " "
+                 << rcClient.right - rcClient.left << " "
+                 << rcClient.top - rcClient.bottom << " re W n\n";
+
+    sAppStream << sText;
+
+    sAppStream << "EMC\nQ\n";
+  }
+}
+
+void CPWL_Edit::DrawThisAppearance(CFX_RenderDevice* pDevice,
+                                   CPDF_Matrix* pUser2Device) {
+  CPWL_Wnd::DrawThisAppearance(pDevice, pUser2Device);
+
+  CPDF_Rect rcClient = GetClientRect();
+  CFX_ByteTextBuf sLine;
+
+  int32_t nCharArray = m_pEdit->GetCharArray();
+  FX_SAFE_INT32 nCharArraySafe = nCharArray;
+  nCharArraySafe -= 1;
+  nCharArraySafe *= 2;
+
+  if (nCharArray > 0 && nCharArraySafe.IsValid()) {
+    switch (GetBorderStyle()) {
+      case PBS_SOLID: {
+        CFX_GraphStateData gsd;
+        gsd.m_LineWidth = (FX_FLOAT)GetBorderWidth();
+
+        CFX_PathData path;
+        path.SetPointCount(nCharArraySafe.ValueOrDie());
+
+        for (int32_t i = 0; i < nCharArray - 1; i++) {
+          path.SetPoint(
+              i * 2,
+              rcClient.left +
+                  ((rcClient.right - rcClient.left) / nCharArray) * (i + 1),
+              rcClient.bottom, FXPT_MOVETO);
+          path.SetPoint(
+              i * 2 + 1,
+              rcClient.left +
+                  ((rcClient.right - rcClient.left) / nCharArray) * (i + 1),
+              rcClient.top, FXPT_LINETO);
+        }
+        if (path.GetPointCount() > 0)
+          pDevice->DrawPath(
+              &path, pUser2Device, &gsd, 0,
+              CPWL_Utils::PWLColorToFXColor(GetBorderColor(), 255),
+              FXFILL_ALTERNATE);
+      } break;
+      case PBS_DASH: {
+        CFX_GraphStateData gsd;
+        gsd.m_LineWidth = (FX_FLOAT)GetBorderWidth();
+
+        gsd.SetDashCount(2);
+        gsd.m_DashArray[0] = (FX_FLOAT)GetBorderDash().nDash;
+        gsd.m_DashArray[1] = (FX_FLOAT)GetBorderDash().nGap;
+        gsd.m_DashPhase = (FX_FLOAT)GetBorderDash().nPhase;
+
+        CFX_PathData path;
+        path.SetPointCount(nCharArraySafe.ValueOrDie());
+
+        for (int32_t i = 0; i < nCharArray - 1; i++) {
+          path.SetPoint(
+              i * 2,
+              rcClient.left +
+                  ((rcClient.right - rcClient.left) / nCharArray) * (i + 1),
+              rcClient.bottom, FXPT_MOVETO);
+          path.SetPoint(
+              i * 2 + 1,
+              rcClient.left +
+                  ((rcClient.right - rcClient.left) / nCharArray) * (i + 1),
+              rcClient.top, FXPT_LINETO);
+        }
+        if (path.GetPointCount() > 0)
+          pDevice->DrawPath(
+              &path, pUser2Device, &gsd, 0,
+              CPWL_Utils::PWLColorToFXColor(GetBorderColor(), 255),
+              FXFILL_ALTERNATE);
+      } break;
+    }
+  }
+
+  CPDF_Rect rcClip;
+  CPVT_WordRange wrRange = m_pEdit->GetVisibleWordRange();
+  CPVT_WordRange* pRange = NULL;
+
+  if (!HasFlag(PES_TEXTOVERFLOW)) {
+    rcClip = GetClientRect();
+    pRange = &wrRange;
+  }
+  IFX_SystemHandler* pSysHandler = GetSystemHandler();
+  IFX_Edit::DrawEdit(
+      pDevice, pUser2Device, m_pEdit,
+      CPWL_Utils::PWLColorToFXColor(GetTextColor(), GetTransparency()),
+      CPWL_Utils::PWLColorToFXColor(GetTextStrokeColor(), GetTransparency()),
+      rcClip, CPDF_Point(0.0f, 0.0f), pRange, pSysHandler, m_pFormFiller);
+
+  if (HasFlag(PES_SPELLCHECK)) {
+    CPWL_Utils::DrawEditSpellCheck(pDevice, pUser2Device, m_pEdit, rcClip,
+                                   CPDF_Point(0.0f, 0.0f), pRange,
+                                   GetCreationParam().pSpellCheck);
+  }
+}
+
+FX_BOOL CPWL_Edit::OnLButtonDown(const CPDF_Point& point, FX_DWORD nFlag) {
+  CPWL_Wnd::OnLButtonDown(point, nFlag);
+
+  if (HasFlag(PES_TEXTOVERFLOW) || ClientHitTest(point)) {
+    if (m_bMouseDown)
+      InvalidateRect();
+
+    m_bMouseDown = TRUE;
+    SetCapture();
+
+    m_pEdit->OnMouseDown(point, IsSHIFTpressed(nFlag), IsCTRLpressed(nFlag));
+  }
+
+  return TRUE;
+}
+
+FX_BOOL CPWL_Edit::OnLButtonDblClk(const CPDF_Point& point, FX_DWORD nFlag) {
+  CPWL_Wnd::OnLButtonDblClk(point, nFlag);
+
+  if (HasFlag(PES_TEXTOVERFLOW) || ClientHitTest(point)) {
+    m_pEdit->SelectAll();
+  }
+
+  return TRUE;
+}
+
+#define WM_PWLEDIT_UNDO 0x01
+#define WM_PWLEDIT_REDO 0x02
+#define WM_PWLEDIT_CUT 0x03
+#define WM_PWLEDIT_COPY 0x04
+#define WM_PWLEDIT_PASTE 0x05
+#define WM_PWLEDIT_DELETE 0x06
+#define WM_PWLEDIT_SELECTALL 0x07
+#define WM_PWLEDIT_SUGGEST 0x08
+
+FX_BOOL CPWL_Edit::OnRButtonUp(const CPDF_Point& point, FX_DWORD nFlag) {
+  if (m_bMouseDown)
+    return FALSE;
+
+  CPWL_Wnd::OnRButtonUp(point, nFlag);
+
+  if (!HasFlag(PES_TEXTOVERFLOW) && !ClientHitTest(point))
+    return TRUE;
+
+  IFX_SystemHandler* pSH = GetSystemHandler();
+  if (!pSH)
+    return FALSE;
+
+  SetFocus();
+
+  CPVT_WordRange wrLatin = GetLatinWordsRange(point);
+  CFX_WideString swLatin = m_pEdit->GetRangeText(wrLatin);
+
+  FX_HMENU hPopup = pSH->CreatePopupMenu();
+  if (!hPopup)
+    return FALSE;
+
+  CFX_ByteStringArray sSuggestWords;
+  CPDF_Point ptPopup = point;
+
+  if (!IsReadOnly()) {
+    if (HasFlag(PES_SPELLCHECK) && !swLatin.IsEmpty()) {
+      if (m_pSpellCheck) {
+        CFX_ByteString sLatin = CFX_ByteString::FromUnicode(swLatin);
+
+        if (!m_pSpellCheck->CheckWord(sLatin)) {
+          m_pSpellCheck->SuggestWords(sLatin, sSuggestWords);
+
+          int32_t nSuggest = sSuggestWords.GetSize();
+
+          for (int32_t nWord = 0; nWord < nSuggest; nWord++) {
+            pSH->AppendMenuItem(hPopup, WM_PWLEDIT_SUGGEST + nWord,
+                                sSuggestWords[nWord].UTF8Decode());
+          }
+
+          if (nSuggest > 0)
+            pSH->AppendMenuItem(hPopup, 0, L"");
+
+          ptPopup = GetWordRightBottomPoint(wrLatin.EndPos);
+        }
+      }
+    }
+  }
+
+  IPWL_Provider* pProvider = GetProvider();
+
+  if (HasFlag(PES_UNDO)) {
+    pSH->AppendMenuItem(
+        hPopup, WM_PWLEDIT_UNDO,
+        pProvider ? pProvider->LoadPopupMenuString(0) : L"&Undo");
+    pSH->AppendMenuItem(
+        hPopup, WM_PWLEDIT_REDO,
+        pProvider ? pProvider->LoadPopupMenuString(1) : L"&Redo");
+    pSH->AppendMenuItem(hPopup, 0, L"");
+
+    if (!m_pEdit->CanUndo())
+      pSH->EnableMenuItem(hPopup, WM_PWLEDIT_UNDO, FALSE);
+    if (!m_pEdit->CanRedo())
+      pSH->EnableMenuItem(hPopup, WM_PWLEDIT_REDO, FALSE);
+  }
+
+  pSH->AppendMenuItem(hPopup, WM_PWLEDIT_CUT,
+                      pProvider ? pProvider->LoadPopupMenuString(2) : L"Cu&t");
+  pSH->AppendMenuItem(hPopup, WM_PWLEDIT_COPY,
+                      pProvider ? pProvider->LoadPopupMenuString(3) : L"&Copy");
+  pSH->AppendMenuItem(
+      hPopup, WM_PWLEDIT_PASTE,
+      pProvider ? pProvider->LoadPopupMenuString(4) : L"&Paste");
+  pSH->AppendMenuItem(
+      hPopup, WM_PWLEDIT_DELETE,
+      pProvider ? pProvider->LoadPopupMenuString(5) : L"&Delete");
+
+  CFX_WideString swText = pSH->GetClipboardText(GetAttachedHWnd());
+  if (swText.IsEmpty())
+    pSH->EnableMenuItem(hPopup, WM_PWLEDIT_PASTE, FALSE);
+
+  if (!m_pEdit->IsSelected()) {
+    pSH->EnableMenuItem(hPopup, WM_PWLEDIT_CUT, FALSE);
+    pSH->EnableMenuItem(hPopup, WM_PWLEDIT_COPY, FALSE);
+    pSH->EnableMenuItem(hPopup, WM_PWLEDIT_DELETE, FALSE);
+  }
+
+  if (IsReadOnly()) {
+    pSH->EnableMenuItem(hPopup, WM_PWLEDIT_CUT, FALSE);
+    pSH->EnableMenuItem(hPopup, WM_PWLEDIT_DELETE, FALSE);
+    pSH->EnableMenuItem(hPopup, WM_PWLEDIT_PASTE, FALSE);
+  }
+
+  if (HasFlag(PES_PASSWORD)) {
+    pSH->EnableMenuItem(hPopup, WM_PWLEDIT_CUT, FALSE);
+    pSH->EnableMenuItem(hPopup, WM_PWLEDIT_COPY, FALSE);
+  }
+
+  if (HasFlag(PES_NOREAD)) {
+    pSH->EnableMenuItem(hPopup, WM_PWLEDIT_CUT, FALSE);
+    pSH->EnableMenuItem(hPopup, WM_PWLEDIT_COPY, FALSE);
+  }
+
+  pSH->AppendMenuItem(hPopup, 0, L"");
+  pSH->AppendMenuItem(
+      hPopup, WM_PWLEDIT_SELECTALL,
+      pProvider ? pProvider->LoadPopupMenuString(6) : L"&Select All");
+
+  if (m_pEdit->GetTotalWords() == 0) {
+    pSH->EnableMenuItem(hPopup, WM_PWLEDIT_SELECTALL, FALSE);
+  }
+
+  int32_t x, y;
+  PWLtoWnd(ptPopup, x, y);
+  pSH->ClientToScreen(GetAttachedHWnd(), x, y);
+  pSH->SetCursor(FXCT_ARROW);
+  int32_t nCmd = pSH->TrackPopupMenu(hPopup, x, y, GetAttachedHWnd());
+
+  switch (nCmd) {
+    case WM_PWLEDIT_UNDO:
+      Undo();
+      break;
+    case WM_PWLEDIT_REDO:
+      Redo();
+      break;
+    case WM_PWLEDIT_CUT:
+      CutText();
+      break;
+    case WM_PWLEDIT_COPY:
+      CopyText();
+      break;
+    case WM_PWLEDIT_PASTE:
+      PasteText();
+      break;
+    case WM_PWLEDIT_DELETE:
+      Clear();
+      break;
+    case WM_PWLEDIT_SELECTALL:
+      SelectAll();
+      break;
+    case WM_PWLEDIT_SUGGEST + 0:
+      SetSel(m_pEdit->WordPlaceToWordIndex(wrLatin.BeginPos),
+             m_pEdit->WordPlaceToWordIndex(wrLatin.EndPos));
+      ReplaceSel(sSuggestWords[0].UTF8Decode().c_str());
+      break;
+    case WM_PWLEDIT_SUGGEST + 1:
+      SetSel(m_pEdit->WordPlaceToWordIndex(wrLatin.BeginPos),
+             m_pEdit->WordPlaceToWordIndex(wrLatin.EndPos));
+      ReplaceSel(sSuggestWords[1].UTF8Decode().c_str());
+      break;
+    case WM_PWLEDIT_SUGGEST + 2:
+      SetSel(m_pEdit->WordPlaceToWordIndex(wrLatin.BeginPos),
+             m_pEdit->WordPlaceToWordIndex(wrLatin.EndPos));
+      ReplaceSel(sSuggestWords[2].UTF8Decode().c_str());
+      break;
+    case WM_PWLEDIT_SUGGEST + 3:
+      SetSel(m_pEdit->WordPlaceToWordIndex(wrLatin.BeginPos),
+             m_pEdit->WordPlaceToWordIndex(wrLatin.EndPos));
+      ReplaceSel(sSuggestWords[3].UTF8Decode().c_str());
+      break;
+    case WM_PWLEDIT_SUGGEST + 4:
+      SetSel(m_pEdit->WordPlaceToWordIndex(wrLatin.BeginPos),
+             m_pEdit->WordPlaceToWordIndex(wrLatin.EndPos));
+      ReplaceSel(sSuggestWords[4].UTF8Decode().c_str());
+      break;
+    default:
+      break;
+  }
+
+  pSH->DestroyMenu(hPopup);
+
+  return TRUE;
+}
+
+void CPWL_Edit::OnSetFocus() {
+  SetEditCaret(TRUE);
+
+  if (!IsReadOnly()) {
+    if (IPWL_FocusHandler* pFocusHandler = GetFocusHandler())
+      pFocusHandler->OnSetFocus(this);
+  }
+
+  m_bFocus = TRUE;
+}
+
+void CPWL_Edit::OnKillFocus() {
+  ShowVScrollBar(FALSE);
+
+  m_pEdit->SelectNone();
+  SetCaret(FALSE, CPDF_Point(0.0f, 0.0f), CPDF_Point(0.0f, 0.0f));
+
+  SetCharSet(0);
+
+  if (!IsReadOnly()) {
+    if (IPWL_FocusHandler* pFocusHandler = GetFocusHandler())
+      pFocusHandler->OnKillFocus(this);
+  }
+
+  m_bFocus = FALSE;
+}
+
+void CPWL_Edit::SetHorzScale(int32_t nHorzScale, FX_BOOL bPaint /* = TRUE*/) {
+  m_pEdit->SetHorzScale(nHorzScale, bPaint);
+}
+
+void CPWL_Edit::SetCharSpace(FX_FLOAT fCharSpace, FX_BOOL bPaint /* = TRUE*/) {
+  m_pEdit->SetCharSpace(fCharSpace, bPaint);
+}
+
+void CPWL_Edit::SetLineLeading(FX_FLOAT fLineLeading,
+                               FX_BOOL bPaint /* = TRUE*/) {
+  m_pEdit->SetLineLeading(fLineLeading, bPaint);
+}
+
+CFX_ByteString CPWL_Edit::GetSelectAppearanceStream(
+    const CPDF_Point& ptOffset) const {
+  CPVT_WordRange wr = GetSelectWordRange();
+  return CPWL_Utils::GetEditSelAppStream(m_pEdit, ptOffset, &wr);
+}
+
+CPVT_WordRange CPWL_Edit::GetSelectWordRange() const {
+  if (m_pEdit->IsSelected()) {
+    int32_t nStart = -1;
+    int32_t nEnd = -1;
+
+    m_pEdit->GetSel(nStart, nEnd);
+
+    CPVT_WordPlace wpStart = m_pEdit->WordIndexToWordPlace(nStart);
+    CPVT_WordPlace wpEnd = m_pEdit->WordIndexToWordPlace(nEnd);
+
+    return CPVT_WordRange(wpStart, wpEnd);
+  }
+
+  return CPVT_WordRange();
+}
+
+CFX_ByteString CPWL_Edit::GetTextAppearanceStream(
+    const CPDF_Point& ptOffset) const {
+  CFX_ByteTextBuf sRet;
+  CFX_ByteString sEdit = CPWL_Utils::GetEditAppStream(m_pEdit, ptOffset);
+
+  if (sEdit.GetLength() > 0) {
+    sRet << "BT\n" << CPWL_Utils::GetColorAppStream(GetTextColor()) << sEdit
+         << "ET\n";
+  }
+
+  return sRet.GetByteString();
+}
+
+CFX_ByteString CPWL_Edit::GetCaretAppearanceStream(
+    const CPDF_Point& ptOffset) const {
+  if (m_pEditCaret)
+    return m_pEditCaret->GetCaretAppearanceStream(ptOffset);
+
+  return CFX_ByteString();
+}
+
+CPDF_Point CPWL_Edit::GetWordRightBottomPoint(const CPVT_WordPlace& wpWord) {
+  CPDF_Point pt(0.0f, 0.0f);
+
+  if (IFX_Edit_Iterator* pIterator = m_pEdit->GetIterator()) {
+    CPVT_WordPlace wpOld = pIterator->GetAt();
+    pIterator->SetAt(wpWord);
+    CPVT_Word word;
+    if (pIterator->GetWord(word)) {
+      pt = CPDF_Point(word.ptWord.x + word.fWidth,
+                      word.ptWord.y + word.fDescent);
+    }
+
+    pIterator->SetAt(wpOld);
+  }
+
+  return pt;
+}
+
+FX_BOOL CPWL_Edit::IsTextFull() const {
+  return m_pEdit->IsTextFull();
+}
+
+FX_FLOAT CPWL_Edit::GetCharArrayAutoFontSize(CPDF_Font* pFont,
+                                             const CPDF_Rect& rcPlate,
+                                             int32_t nCharArray) {
+  if (pFont && !pFont->IsStandardFont()) {
+    FX_RECT rcBBox;
+    pFont->GetFontBBox(rcBBox);
+
+    CPDF_Rect rcCell = rcPlate;
+    FX_FLOAT xdiv = rcCell.Width() / nCharArray * 1000.0f / rcBBox.Width();
+    FX_FLOAT ydiv = -rcCell.Height() * 1000.0f / rcBBox.Height();
+
+    return xdiv < ydiv ? xdiv : ydiv;
+  }
+
+  return 0.0f;
+}
+
+void CPWL_Edit::SetCharArray(int32_t nCharArray) {
+  if (HasFlag(PES_CHARARRAY) && nCharArray > 0) {
+    m_pEdit->SetCharArray(nCharArray);
+    m_pEdit->SetTextOverflow(TRUE);
+
+    if (HasFlag(PWS_AUTOFONTSIZE)) {
+      if (IFX_Edit_FontMap* pFontMap = GetFontMap()) {
+        FX_FLOAT fFontSize = GetCharArrayAutoFontSize(
+            pFontMap->GetPDFFont(0), GetClientRect(), nCharArray);
+        if (fFontSize > 0.0f) {
+          m_pEdit->SetAutoFontSize(FALSE);
+          m_pEdit->SetFontSize(fFontSize);
+        }
+      }
+    }
+  }
+}
+
+void CPWL_Edit::SetLimitChar(int32_t nLimitChar) {
+  m_pEdit->SetLimitChar(nLimitChar);
+}
+
+void CPWL_Edit::ReplaceSel(const FX_WCHAR* csText) {
+  m_pEdit->Clear();
+  m_pEdit->InsertText(csText);
+}
+
+CPDF_Rect CPWL_Edit::GetFocusRect() const {
+  return CPDF_Rect();
+}
+
+void CPWL_Edit::ShowVScrollBar(FX_BOOL bShow) {
+  if (CPWL_ScrollBar* pScroll = GetVScrollBar()) {
+    if (bShow) {
+      if (!pScroll->IsVisible()) {
+        pScroll->SetVisible(TRUE);
+        CPDF_Rect rcWindow = GetWindowRect();
+        m_rcOldWindow = rcWindow;
+        rcWindow.right += PWL_SCROLLBAR_WIDTH;
+        Move(rcWindow, TRUE, TRUE);
+      }
+    } else {
+      if (pScroll->IsVisible()) {
+        pScroll->SetVisible(FALSE);
+        Move(m_rcOldWindow, TRUE, TRUE);
+      }
+    }
+  }
+}
+
+FX_BOOL CPWL_Edit::IsVScrollBarVisible() const {
+  if (CPWL_ScrollBar* pScroll = GetVScrollBar()) {
+    return pScroll->IsVisible();
+  }
+
+  return FALSE;
+}
+
+void CPWL_Edit::EnableSpellCheck(FX_BOOL bEnabled) {
+  if (bEnabled)
+    AddFlag(PES_SPELLCHECK);
+  else
+    RemoveFlag(PES_SPELLCHECK);
+}
+
+FX_BOOL CPWL_Edit::OnKeyDown(FX_WORD nChar, FX_DWORD nFlag) {
+  if (m_bMouseDown)
+    return TRUE;
+
+  if (nChar == FWL_VKEY_Delete) {
+    if (m_pFillerNotify) {
+      FX_BOOL bRC = TRUE;
+      FX_BOOL bExit = FALSE;
+      CFX_WideString strChange;
+      CFX_WideString strChangeEx;
+
+      int nSelStart = 0;
+      int nSelEnd = 0;
+      GetSel(nSelStart, nSelEnd);
+
+      if (nSelStart == nSelEnd)
+        nSelEnd = nSelStart + 1;
+      m_pFillerNotify->OnBeforeKeyStroke(GetAttachedData(), strChange,
+                                         strChangeEx, nSelStart, nSelEnd, TRUE,
+                                         bRC, bExit, nFlag);
+      if (!bRC)
+        return FALSE;
+      if (bExit)
+        return FALSE;
+    }
+  }
+
+  FX_BOOL bRet = CPWL_EditCtrl::OnKeyDown(nChar, nFlag);
+
+  // In case of implementation swallow the OnKeyDown event.
+  if (IsProceedtoOnChar(nChar, nFlag))
+    return TRUE;
+
+  return bRet;
+}
+
+/**
+*In case of implementation swallow the OnKeyDown event.
+*If the event is swallowed, implementation may do other unexpected things, which
+*is not the control means to do.
+*/
+FX_BOOL CPWL_Edit::IsProceedtoOnChar(FX_WORD nKeyCode, FX_DWORD nFlag) {
+  FX_BOOL bCtrl = IsCTRLpressed(nFlag);
+  FX_BOOL bAlt = IsALTpressed(nFlag);
+  if (bCtrl && !bAlt) {
+    // hot keys for edit control.
+    switch (nKeyCode) {
+      case 'C':
+      case 'V':
+      case 'X':
+      case 'A':
+      case 'Z':
+        return TRUE;
+      default:
+        break;
+    }
+  }
+  // control characters.
+  switch (nKeyCode) {
+    case FWL_VKEY_Escape:
+    case FWL_VKEY_Back:
+    case FWL_VKEY_Return:
+    case FWL_VKEY_Space:
+      return TRUE;
+    default:
+      return FALSE;
+  }
+}
+
+FX_BOOL CPWL_Edit::OnChar(FX_WORD nChar, FX_DWORD nFlag) {
+  if (m_bMouseDown)
+    return TRUE;
+
+  FX_BOOL bRC = TRUE;
+  FX_BOOL bExit = FALSE;
+
+  if (!IsCTRLpressed(nFlag)) {
+    if (m_pFillerNotify) {
+      CFX_WideString swChange;
+
+      int nSelStart = 0;
+      int nSelEnd = 0;
+      GetSel(nSelStart, nSelEnd);
+
+      switch (nChar) {
+        case FWL_VKEY_Back:
+          if (nSelStart == nSelEnd)
+            nSelStart = nSelEnd - 1;
+          break;
+        case FWL_VKEY_Return:
+          break;
+        default:
+          swChange += nChar;
+          break;
+      }
+
+      CFX_WideString strChangeEx;
+      m_pFillerNotify->OnBeforeKeyStroke(GetAttachedData(), swChange,
+                                         strChangeEx, nSelStart, nSelEnd, TRUE,
+                                         bRC, bExit, nFlag);
+    }
+  }
+
+  if (!bRC)
+    return TRUE;
+  if (bExit)
+    return FALSE;
+
+  if (IFX_Edit_FontMap* pFontMap = GetFontMap()) {
+    int32_t nOldCharSet = GetCharSet();
+    int32_t nNewCharSet = pFontMap->CharSetFromUnicode(nChar, DEFAULT_CHARSET);
+    if (nOldCharSet != nNewCharSet) {
+      SetCharSet(nNewCharSet);
+    }
+  }
+
+  return CPWL_EditCtrl::OnChar(nChar, nFlag);
+}
+
+FX_BOOL CPWL_Edit::OnMouseWheel(short zDelta,
+                                const CPDF_Point& point,
+                                FX_DWORD nFlag) {
+  if (HasFlag(PES_MULTILINE)) {
+    CPDF_Point ptScroll = GetScrollPos();
+
+    if (zDelta > 0) {
+      ptScroll.y += GetFontSize();
+    } else {
+      ptScroll.y -= GetFontSize();
+    }
+    SetScrollPos(ptScroll);
+
+    return TRUE;
+  }
+
+  return FALSE;
+}
+
+void CPWL_Edit::OnInsertReturn(const CPVT_WordPlace& place,
+                               const CPVT_WordPlace& oldplace) {
+  if (HasFlag(PES_SPELLCHECK)) {
+    m_pEdit->RefreshWordRange(CombineWordRange(GetLatinWordsRange(oldplace),
+                                               GetLatinWordsRange(place)));
+  }
+
+  if (m_pEditNotify) {
+    m_pEditNotify->OnInsertReturn(place, oldplace);
+  }
+}
+
+void CPWL_Edit::OnBackSpace(const CPVT_WordPlace& place,
+                            const CPVT_WordPlace& oldplace) {
+  if (HasFlag(PES_SPELLCHECK)) {
+    m_pEdit->RefreshWordRange(CombineWordRange(GetLatinWordsRange(oldplace),
+                                               GetLatinWordsRange(place)));
+  }
+
+  if (m_pEditNotify) {
+    m_pEditNotify->OnBackSpace(place, oldplace);
+  }
+}
+
+void CPWL_Edit::OnDelete(const CPVT_WordPlace& place,
+                         const CPVT_WordPlace& oldplace) {
+  if (HasFlag(PES_SPELLCHECK)) {
+    m_pEdit->RefreshWordRange(CombineWordRange(GetLatinWordsRange(oldplace),
+                                               GetLatinWordsRange(place)));
+  }
+
+  if (m_pEditNotify) {
+    m_pEditNotify->OnDelete(place, oldplace);
+  }
+}
+
+void CPWL_Edit::OnClear(const CPVT_WordPlace& place,
+                        const CPVT_WordPlace& oldplace) {
+  if (HasFlag(PES_SPELLCHECK)) {
+    m_pEdit->RefreshWordRange(CombineWordRange(GetLatinWordsRange(oldplace),
+                                               GetLatinWordsRange(place)));
+  }
+
+  if (m_pEditNotify) {
+    m_pEditNotify->OnClear(place, oldplace);
+  }
+}
+
+void CPWL_Edit::OnInsertWord(const CPVT_WordPlace& place,
+                             const CPVT_WordPlace& oldplace) {
+  if (HasFlag(PES_SPELLCHECK)) {
+    m_pEdit->RefreshWordRange(CombineWordRange(GetLatinWordsRange(oldplace),
+                                               GetLatinWordsRange(place)));
+  }
+
+  if (m_pEditNotify) {
+    m_pEditNotify->OnInsertWord(place, oldplace);
+  }
+}
+
+void CPWL_Edit::OnSetText(const CPVT_WordPlace& place,
+                          const CPVT_WordPlace& oldplace) {}
+
+void CPWL_Edit::OnInsertText(const CPVT_WordPlace& place,
+                             const CPVT_WordPlace& oldplace) {
+  if (HasFlag(PES_SPELLCHECK)) {
+    m_pEdit->RefreshWordRange(CombineWordRange(GetLatinWordsRange(oldplace),
+                                               GetLatinWordsRange(place)));
+  }
+
+  if (m_pEditNotify) {
+    m_pEditNotify->OnInsertText(place, oldplace);
+  }
+}
+
+void CPWL_Edit::OnAddUndo(IFX_Edit_UndoItem* pUndoItem) {
+  if (m_pEditNotify) {
+    m_pEditNotify->OnAddUndo(this);
+  }
+}
+
+CPVT_WordRange CPWL_Edit::CombineWordRange(const CPVT_WordRange& wr1,
+                                           const CPVT_WordRange& wr2) {
+  CPVT_WordRange wrRet;
+
+  if (wr1.BeginPos.WordCmp(wr2.BeginPos) < 0) {
+    wrRet.BeginPos = wr1.BeginPos;
+  } else {
+    wrRet.BeginPos = wr2.BeginPos;
+  }
+
+  if (wr1.EndPos.WordCmp(wr2.EndPos) < 0) {
+    wrRet.EndPos = wr2.EndPos;
+  } else {
+    wrRet.EndPos = wr1.EndPos;
+  }
+
+  return wrRet;
+}
+
+CPVT_WordRange CPWL_Edit::GetLatinWordsRange(const CPDF_Point& point) const {
+  return GetSameWordsRange(m_pEdit->SearchWordPlace(point), TRUE, FALSE);
+}
+
+CPVT_WordRange CPWL_Edit::GetLatinWordsRange(
+    const CPVT_WordPlace& place) const {
+  return GetSameWordsRange(place, TRUE, FALSE);
+}
+
+CPVT_WordRange CPWL_Edit::GetArabicWordsRange(
+    const CPVT_WordPlace& place) const {
+  return GetSameWordsRange(place, FALSE, TRUE);
+}
+
+#define PWL_ISARABICWORD(word) \
+  ((word >= 0x0600 && word <= 0x06FF) || (word >= 0xFB50 && word <= 0xFEFC))
+
+CPVT_WordRange CPWL_Edit::GetSameWordsRange(const CPVT_WordPlace& place,
+                                            FX_BOOL bLatin,
+                                            FX_BOOL bArabic) const {
+  CPVT_WordRange range;
+
+  if (IFX_Edit_Iterator* pIterator = m_pEdit->GetIterator()) {
+    CPVT_Word wordinfo;
+    CPVT_WordPlace wpStart(place), wpEnd(place);
+    pIterator->SetAt(place);
+
+    if (bLatin) {
+      while (pIterator->NextWord()) {
+        if (pIterator->GetWord(wordinfo) &&
+            FX_EDIT_ISLATINWORD(wordinfo.Word)) {
+          wpEnd = pIterator->GetAt();
+          continue;
+        } else
+          break;
+      };
+    } else if (bArabic) {
+      while (pIterator->NextWord()) {
+        if (pIterator->GetWord(wordinfo) && PWL_ISARABICWORD(wordinfo.Word)) {
+          wpEnd = pIterator->GetAt();
+          continue;
+        } else
+          break;
+      };
+    }
+
+    pIterator->SetAt(place);
+
+    if (bLatin) {
+      do {
+        if (pIterator->GetWord(wordinfo) &&
+            FX_EDIT_ISLATINWORD(wordinfo.Word)) {
+          continue;
+        } else {
+          wpStart = pIterator->GetAt();
+          break;
+        }
+      } while (pIterator->PrevWord());
+    } else if (bArabic) {
+      do {
+        if (pIterator->GetWord(wordinfo) && PWL_ISARABICWORD(wordinfo.Word)) {
+          continue;
+        } else {
+          wpStart = pIterator->GetAt();
+          break;
+        }
+      } while (pIterator->PrevWord());
+    }
+
+    range.Set(wpStart, wpEnd);
+  }
+
+  return range;
+}
+
+void CPWL_Edit::GeneratePageObjects(
+    CPDF_PageObjects* pPageObjects,
+    const CPDF_Point& ptOffset,
+    CFX_ArrayTemplate<CPDF_TextObject*>& ObjArray) {
+  IFX_Edit::GeneratePageObjects(
+      pPageObjects, m_pEdit, ptOffset, NULL,
+      CPWL_Utils::PWLColorToFXColor(GetTextColor(), GetTransparency()),
+      ObjArray);
+}
+
+void CPWL_Edit::GeneratePageObjects(CPDF_PageObjects* pPageObjects,
+                                    const CPDF_Point& ptOffset) {
+  CFX_ArrayTemplate<CPDF_TextObject*> ObjArray;
+  IFX_Edit::GeneratePageObjects(
+      pPageObjects, m_pEdit, ptOffset, NULL,
+      CPWL_Utils::PWLColorToFXColor(GetTextColor(), GetTransparency()),
+      ObjArray);
+}