Home | History | Annotate | Download | only in basewidget
      1 // Copyright 2014 PDFium Authors. All rights reserved.
      2 // Use of this source code is governed by a BSD-style license that can be
      3 // found in the LICENSE file.
      4 
      5 // Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com
      6 
      7 #include <algorithm>
      8 
      9 #include "xfa/src/foxitlib.h"
     10 #include "xfa/src/fwl/src/core/include/fwl_threadimp.h"
     11 #include "xfa/src/fwl/src/core/include/fwl_appimp.h"
     12 #include "xfa/src/fwl/src/core/include/fwl_targetimp.h"
     13 #include "xfa/src/fwl/src/core/include/fwl_noteimp.h"
     14 #include "xfa/src/fwl/src/core/include/fwl_widgetimp.h"
     15 #include "xfa/src/fwl/src/core/include/fwl_widgetmgrimp.h"
     16 #include "xfa/src/fwl/src/basewidget/include/fwl_caretimp.h"
     17 #include "xfa/src/fwl/src/basewidget/include/fwl_comboboximp.h"
     18 #include "xfa/src/fwl/src/basewidget/include/fwl_editimp.h"
     19 #include "xfa/src/fwl/src/basewidget/include/fwl_scrollbarimp.h"
     20 
     21 // static
     22 IFWL_Edit* IFWL_Edit::Create(const CFWL_WidgetImpProperties& properties,
     23                              IFWL_Widget* pOuter) {
     24   IFWL_Edit* pEdit = new IFWL_Edit;
     25   CFWL_EditImp* pEditImpl = new CFWL_EditImp(properties, pOuter);
     26   pEdit->SetImpl(pEditImpl);
     27   pEditImpl->SetInterface(pEdit);
     28   return pEdit;
     29 }
     30 // static
     31 IFWL_Edit* IFWL_Edit::CreateComboEdit(
     32     const CFWL_WidgetImpProperties& properties,
     33     IFWL_Widget* pOuter) {
     34   IFWL_Edit* pEdit = new IFWL_Edit;
     35   CFWL_EditImp* pComboEditImpl = new CFWL_ComboEditImp(properties, pOuter);
     36   pEdit->SetImpl(pComboEditImpl);
     37   pComboEditImpl->SetInterface(pEdit);
     38   return pEdit;
     39 }
     40 IFWL_Edit::IFWL_Edit() {}
     41 FWL_ERR IFWL_Edit::SetText(const CFX_WideString& wsText) {
     42   return static_cast<CFWL_EditImp*>(GetImpl())->SetText(wsText);
     43 }
     44 int32_t IFWL_Edit::GetTextLength() const {
     45   return static_cast<CFWL_EditImp*>(GetImpl())->GetTextLength();
     46 }
     47 FWL_ERR IFWL_Edit::GetText(CFX_WideString& wsText,
     48                            int32_t nStart,
     49                            int32_t nCount) const {
     50   return static_cast<CFWL_EditImp*>(GetImpl())->GetText(wsText, nStart, nCount);
     51 }
     52 FWL_ERR IFWL_Edit::ClearText() {
     53   return static_cast<CFWL_EditImp*>(GetImpl())->ClearText();
     54 }
     55 int32_t IFWL_Edit::GetCaretPos() const {
     56   return static_cast<CFWL_EditImp*>(GetImpl())->GetCaretPos();
     57 }
     58 int32_t IFWL_Edit::SetCaretPos(int32_t nIndex, FX_BOOL bBefore) {
     59   return static_cast<CFWL_EditImp*>(GetImpl())->SetCaretPos(nIndex, bBefore);
     60 }
     61 FWL_ERR IFWL_Edit::AddSelRange(int32_t nStart, int32_t nCount) {
     62   return static_cast<CFWL_EditImp*>(GetImpl())->AddSelRange(nStart, nCount);
     63 }
     64 int32_t IFWL_Edit::CountSelRanges() {
     65   return static_cast<CFWL_EditImp*>(GetImpl())->CountSelRanges();
     66 }
     67 int32_t IFWL_Edit::GetSelRange(int32_t nIndex, int32_t& nStart) {
     68   return static_cast<CFWL_EditImp*>(GetImpl())->GetSelRange(nIndex, nStart);
     69 }
     70 FWL_ERR IFWL_Edit::ClearSelections() {
     71   return static_cast<CFWL_EditImp*>(GetImpl())->ClearSelections();
     72 }
     73 int32_t IFWL_Edit::GetLimit() {
     74   return static_cast<CFWL_EditImp*>(GetImpl())->GetLimit();
     75 }
     76 FWL_ERR IFWL_Edit::SetLimit(int32_t nLimit) {
     77   return static_cast<CFWL_EditImp*>(GetImpl())->SetLimit(nLimit);
     78 }
     79 FWL_ERR IFWL_Edit::SetAliasChar(FX_WCHAR wAlias) {
     80   return static_cast<CFWL_EditImp*>(GetImpl())->SetAliasChar(wAlias);
     81 }
     82 FWL_ERR IFWL_Edit::SetFormatString(const CFX_WideString& wsFormat) {
     83   return static_cast<CFWL_EditImp*>(GetImpl())->SetFormatString(wsFormat);
     84 }
     85 FWL_ERR IFWL_Edit::Insert(int32_t nStart,
     86                           const FX_WCHAR* lpText,
     87                           int32_t nLen) {
     88   return static_cast<CFWL_EditImp*>(GetImpl())->Insert(nStart, lpText, nLen);
     89 }
     90 FWL_ERR IFWL_Edit::DeleteSelections() {
     91   return static_cast<CFWL_EditImp*>(GetImpl())->DeleteSelections();
     92 }
     93 FWL_ERR IFWL_Edit::DeleteRange(int32_t nStart, int32_t nCount) {
     94   return static_cast<CFWL_EditImp*>(GetImpl())->DeleteRange(nStart, nCount);
     95 }
     96 FWL_ERR IFWL_Edit::ReplaceSelections(const CFX_WideStringC& wsReplace) {
     97   return static_cast<CFWL_EditImp*>(GetImpl())->ReplaceSelections(wsReplace);
     98 }
     99 FWL_ERR IFWL_Edit::Replace(int32_t nStart,
    100                            int32_t nLen,
    101                            const CFX_WideStringC& wsReplace) {
    102   return static_cast<CFWL_EditImp*>(GetImpl())
    103       ->Replace(nStart, nLen, wsReplace);
    104 }
    105 FWL_ERR IFWL_Edit::DoClipboard(int32_t iCmd) {
    106   return static_cast<CFWL_EditImp*>(GetImpl())->DoClipboard(iCmd);
    107 }
    108 FX_BOOL IFWL_Edit::Copy(CFX_WideString& wsCopy) {
    109   return static_cast<CFWL_EditImp*>(GetImpl())->Copy(wsCopy);
    110 }
    111 FX_BOOL IFWL_Edit::Cut(CFX_WideString& wsCut) {
    112   return static_cast<CFWL_EditImp*>(GetImpl())->Cut(wsCut);
    113 }
    114 FX_BOOL IFWL_Edit::Paste(const CFX_WideString& wsPaste) {
    115   return static_cast<CFWL_EditImp*>(GetImpl())->Paste(wsPaste);
    116 }
    117 FX_BOOL IFWL_Edit::Delete() {
    118   return static_cast<CFWL_EditImp*>(GetImpl())->Delete();
    119 }
    120 FX_BOOL IFWL_Edit::Redo(const CFX_ByteStringC& bsRecord) {
    121   return static_cast<CFWL_EditImp*>(GetImpl())->Redo(bsRecord);
    122 }
    123 FX_BOOL IFWL_Edit::Undo(const CFX_ByteStringC& bsRecord) {
    124   return static_cast<CFWL_EditImp*>(GetImpl())->Undo(bsRecord);
    125 }
    126 FX_BOOL IFWL_Edit::Undo() {
    127   return static_cast<CFWL_EditImp*>(GetImpl())->Undo();
    128 }
    129 FX_BOOL IFWL_Edit::Redo() {
    130   return static_cast<CFWL_EditImp*>(GetImpl())->Redo();
    131 }
    132 FX_BOOL IFWL_Edit::CanUndo() {
    133   return static_cast<CFWL_EditImp*>(GetImpl())->CanUndo();
    134 }
    135 FX_BOOL IFWL_Edit::CanRedo() {
    136   return static_cast<CFWL_EditImp*>(GetImpl())->CanRedo();
    137 }
    138 FWL_ERR IFWL_Edit::SetTabWidth(FX_FLOAT fTabWidth, FX_BOOL bEquidistant) {
    139   return static_cast<CFWL_EditImp*>(GetImpl())
    140       ->SetTabWidth(fTabWidth, bEquidistant);
    141 }
    142 FWL_ERR IFWL_Edit::SetOuter(IFWL_Widget* pOuter) {
    143   return static_cast<CFWL_EditImp*>(GetImpl())->SetOuter(pOuter);
    144 }
    145 FWL_ERR IFWL_Edit::SetNumberRange(int32_t iMin, int32_t iMax) {
    146   return static_cast<CFWL_EditImp*>(GetImpl())->SetNumberRange(iMin, iMax);
    147 }
    148 FWL_ERR IFWL_Edit::SetBackColor(FX_DWORD dwColor) {
    149   return static_cast<CFWL_EditImp*>(GetImpl())->SetBackgroundColor(dwColor);
    150 }
    151 FWL_ERR IFWL_Edit::SetFont(const CFX_WideString& wsFont, FX_FLOAT fSize) {
    152   return static_cast<CFWL_EditImp*>(GetImpl())->SetFont(wsFont, fSize);
    153 }
    154 void IFWL_Edit::SetScrollOffset(FX_FLOAT fScrollOffset) {
    155   return static_cast<CFWL_EditImp*>(GetImpl())->SetScrollOffset(fScrollOffset);
    156 }
    157 FX_BOOL IFWL_Edit::GetSuggestWords(CFX_PointF pointf,
    158                                    CFX_ByteStringArray& sSuggest) {
    159   return static_cast<CFWL_EditImp*>(GetImpl())
    160       ->GetSuggestWords(pointf, sSuggest);
    161 }
    162 FX_BOOL IFWL_Edit::ReplaceSpellCheckWord(CFX_PointF pointf,
    163                                          const CFX_ByteStringC& bsReplace) {
    164   return static_cast<CFWL_EditImp*>(GetImpl())
    165       ->ReplaceSpellCheckWord(pointf, bsReplace);
    166 }
    167 #define FWL_EDIT_Margin 3
    168 CFWL_EditImp::CFWL_EditImp(const CFWL_WidgetImpProperties& properties,
    169                            IFWL_Widget* pOuter)
    170     : CFWL_WidgetImp(properties, pOuter),
    171       m_fVAlignOffset(0.0f),
    172       m_fScrollOffsetX(0.0f),
    173       m_fScrollOffsetY(0.0f),
    174       m_pEdtEngine(NULL),
    175       m_bLButtonDown(FALSE),
    176       m_nSelStart(0),
    177       m_nLimit(-1),
    178       m_fSpaceAbove(0),
    179       m_fSpaceBelow(0),
    180       m_fFontSize(0),
    181       m_bSetRange(FALSE),
    182       m_iMin(-1),
    183       m_iMax(0xFFFFFFF),
    184       m_backColor(0),
    185       m_updateBackColor(FALSE),
    186       m_iCurRecord(-1),
    187       m_iMaxRecord(128) {
    188   m_rtClient.Reset();
    189   m_rtEngine.Reset();
    190   m_rtStatic.Reset();
    191 }
    192 CFWL_EditImp::~CFWL_EditImp() {
    193   if (m_pEdtEngine) {
    194     m_pEdtEngine->Release();
    195     m_pEdtEngine = NULL;
    196   }
    197   ClearRecord();
    198 }
    199 FWL_ERR CFWL_EditImp::GetClassName(CFX_WideString& wsClass) const {
    200   wsClass = FWL_CLASS_Edit;
    201   return FWL_ERR_Succeeded;
    202 }
    203 FX_DWORD CFWL_EditImp::GetClassID() const {
    204   return FWL_CLASSHASH_Edit;
    205 }
    206 FWL_ERR CFWL_EditImp::Initialize() {
    207   if (CFWL_WidgetImp::Initialize() != FWL_ERR_Succeeded)
    208     return FWL_ERR_Indefinite;
    209   if (!m_pDelegate) {
    210     m_pDelegate = new CFWL_EditImpDelegate(this);
    211   }
    212   InitCaret();
    213   if (!m_pEdtEngine) {
    214     InitEngine();
    215   }
    216   return FWL_ERR_Succeeded;
    217 }
    218 FWL_ERR CFWL_EditImp::Finalize() {
    219   if (m_pProperties->m_dwStates & FWL_WGTSTATE_Focused) {
    220     ShowCaret(FALSE);
    221   }
    222   if (m_pHorzScrollBar) {
    223     m_pHorzScrollBar->Finalize();
    224   }
    225   if (m_pVertScrollBar) {
    226     m_pVertScrollBar->Finalize();
    227   }
    228   delete m_pDelegate;
    229   m_pDelegate = nullptr;
    230   return CFWL_WidgetImp::Finalize();
    231 }
    232 FWL_ERR CFWL_EditImp::GetWidgetRect(CFX_RectF& rect, FX_BOOL bAutoSize) {
    233   if (bAutoSize) {
    234     rect.Set(0, 0, 0, 0);
    235     if (m_pEdtEngine) {
    236       int32_t iTextLen = m_pEdtEngine->GetTextLength();
    237       if (iTextLen > 0) {
    238         CFX_WideString wsText;
    239         m_pEdtEngine->GetText(wsText, 0);
    240         CFX_SizeF sz = CalcTextSize(
    241             wsText, m_pProperties->m_pThemeProvider,
    242             m_pProperties->m_dwStyleExes & FWL_STYLEEXT_EDT_MultiLine);
    243         rect.Set(0, 0, sz.x, sz.y);
    244       }
    245     }
    246     CFWL_WidgetImp::GetWidgetRect(rect, TRUE);
    247   } else {
    248     rect = m_pProperties->m_rtWidget;
    249     if (m_pProperties->m_dwStyleExes & FWL_STYLEEXT_EDT_OuterScrollbar) {
    250       if (IsShowScrollBar(TRUE)) {
    251         FX_FLOAT* pfWidth = static_cast<FX_FLOAT*>(
    252             GetThemeCapacity(FWL_WGTCAPACITY_ScrollBarWidth));
    253         rect.width += *pfWidth;
    254         rect.width += FWL_EDIT_Margin;
    255       }
    256       if (IsShowScrollBar(FALSE)) {
    257         FX_FLOAT* pfWidth = static_cast<FX_FLOAT*>(
    258             GetThemeCapacity(FWL_WGTCAPACITY_ScrollBarWidth));
    259         rect.height += *pfWidth;
    260         rect.height += FWL_EDIT_Margin;
    261       }
    262     }
    263   }
    264   return FWL_ERR_Succeeded;
    265 }
    266 FWL_ERR CFWL_EditImp::SetStates(FX_DWORD dwStates, FX_BOOL bSet) {
    267   if ((m_pProperties->m_dwStates & FWL_WGTSTATE_Invisible) ||
    268       (m_pProperties->m_dwStates & FWL_WGTSTATE_Disabled)) {
    269     ShowCaret(FALSE);
    270   }
    271   return CFWL_WidgetImp::SetStates(dwStates, bSet);
    272 }
    273 FWL_ERR CFWL_EditImp::SetWidgetRect(const CFX_RectF& rect) {
    274   return CFWL_WidgetImp::SetWidgetRect(rect);
    275 }
    276 FWL_ERR CFWL_EditImp::Update() {
    277   if (IsLocked()) {
    278     return FWL_ERR_Indefinite;
    279   }
    280   if (!m_pProperties->m_pThemeProvider) {
    281     m_pProperties->m_pThemeProvider = GetAvailableTheme();
    282   }
    283   Layout();
    284   if (m_rtClient.IsEmpty()) {
    285     return FWL_ERR_Indefinite;
    286   }
    287   UpdateEditEngine();
    288   UpdateVAlignment();
    289   UpdateScroll();
    290   InitCaret();
    291   return FWL_ERR_Succeeded;
    292 }
    293 FX_DWORD CFWL_EditImp::HitTest(FX_FLOAT fx, FX_FLOAT fy) {
    294   if (m_pProperties->m_dwStyleExes & FWL_STYLEEXT_EDT_OuterScrollbar) {
    295     if (IsShowScrollBar(TRUE)) {
    296       CFX_RectF rect;
    297       m_pVertScrollBar->GetWidgetRect(rect);
    298       if (rect.Contains(fx, fy)) {
    299         return FWL_WGTHITTEST_VScrollBar;
    300       }
    301     }
    302     if (IsShowScrollBar(FALSE)) {
    303       CFX_RectF rect;
    304       m_pHorzScrollBar->GetWidgetRect(rect);
    305       if (rect.Contains(fx, fy)) {
    306         return FWL_WGTHITTEST_HScrollBar;
    307       }
    308     }
    309   }
    310   if (m_rtClient.Contains(fx, fy)) {
    311     return FWL_WGTHITTEST_Edit;
    312   }
    313   return FWL_WGTHITTEST_Unknown;
    314 }
    315 #define FX_EDIT_ISLATINWORD(u)                                     \
    316   (u == 0x2D || (u <= 0x005A && u >= 0x0041) ||                    \
    317    (u <= 0x007A && u >= 0x0061) || (u <= 0x02AF && u >= 0x00C0) || \
    318    u == 0x0027)
    319 static void AddSquigglyPath(CFX_Path& PathData,
    320                             FX_FLOAT fStartX,
    321                             FX_FLOAT fEndX,
    322                             FX_FLOAT fY,
    323                             FX_FLOAT fStep) {
    324   PathData.MoveTo(fStartX, fY);
    325   FX_FLOAT fx;
    326   int32_t i;
    327   for (i = 1, fx = fStartX + fStep; fx < fEndX; fx += fStep, i++) {
    328     PathData.LineTo(fx, fY + (i & 1) * fStep);
    329   }
    330 }
    331 void CFWL_EditImp::AddSpellCheckObj(CFX_Path& PathData,
    332                                     int32_t nStart,
    333                                     int32_t nCount,
    334                                     FX_FLOAT fOffSetX,
    335                                     FX_FLOAT fOffSetY) {
    336   FX_FLOAT fStartX = 0.0f;
    337   FX_FLOAT fEndX = 0.0f;
    338   FX_FLOAT fY = 0.0f;
    339   FX_FLOAT fStep = 0.0f;
    340   IFDE_TxtEdtPage* pPage = m_pEdtEngine->GetPage(0);
    341   CFX_RectFArray rectArray;
    342   CFX_RectF rectText;
    343   const FDE_TXTEDTPARAMS* txtEdtParams = m_pEdtEngine->GetEditParams();
    344   FX_FLOAT fAsent = (FX_FLOAT)txtEdtParams->pFont->GetAscent() *
    345                     txtEdtParams->fFontSize / 1000;
    346   pPage->CalcRangeRectArray(nStart, nCount, rectArray);
    347   for (int i = 0; i < rectArray.GetSize(); i++) {
    348     rectText = rectArray.GetAt(i);
    349     fY = rectText.top + fAsent + fOffSetY;
    350     fStep = txtEdtParams->fFontSize / 16.0f;
    351     fStartX = rectText.left + fOffSetX;
    352     fEndX = fStartX + rectText.Width();
    353     AddSquigglyPath(PathData, fStartX, fEndX, fY, fStep);
    354   }
    355 }
    356 int32_t CFWL_EditImp::GetWordAtPoint(CFX_PointF pointf, int32_t& nCount) {
    357   return 0;
    358 }
    359 FX_BOOL CFWL_EditImp::GetSuggestWords(CFX_PointF pointf,
    360                                       CFX_ByteStringArray& sSuggest) {
    361   int32_t nWordCount = 0;
    362   int32_t nWordStart = GetWordAtPoint(pointf, nWordCount);
    363   if (nWordCount < 1) {
    364     return FALSE;
    365   }
    366   CFX_WideString wsSpell;
    367   GetText(wsSpell, nWordStart, nWordCount);
    368   CFX_ByteString sLatinWord;
    369   for (int i = 0; i < nWordCount; i++) {
    370     if (!FX_EDIT_ISLATINWORD(wsSpell[i])) {
    371       break;
    372     }
    373     sLatinWord += (FX_CHAR)wsSpell[i];
    374   }
    375   if (sLatinWord.IsEmpty()) {
    376     return FALSE;
    377   }
    378   CFWL_EvtEdtCheckWord checkWordEvent;
    379   checkWordEvent.m_pSrcTarget = m_pInterface;
    380   checkWordEvent.bsWord = sLatinWord;
    381   checkWordEvent.bCheckWord = TRUE;
    382   DispatchEvent(&checkWordEvent);
    383   if (checkWordEvent.bCheckWord) {
    384     return FALSE;
    385   }
    386   CFWL_EvtEdtGetSuggestWords suggestWordsEvent;
    387   suggestWordsEvent.m_pSrcTarget = m_pInterface;
    388   suggestWordsEvent.bsWord = sLatinWord;
    389   suggestWordsEvent.bsArraySuggestWords = sSuggest;
    390   suggestWordsEvent.bSuggestWords = FALSE;
    391   DispatchEvent(&checkWordEvent);
    392   return suggestWordsEvent.bSuggestWords;
    393 }
    394 FX_BOOL CFWL_EditImp::ReplaceSpellCheckWord(CFX_PointF pointf,
    395                                             const CFX_ByteStringC& bsReplace) {
    396   int32_t nWordCount = 0;
    397   int32_t nWordStart = GetWordAtPoint(pointf, nWordCount);
    398   if (nWordCount < 1) {
    399     return FALSE;
    400   }
    401   CFX_WideString wsSpell;
    402   GetText(wsSpell, nWordStart, nWordCount);
    403   for (int i = 0; i < nWordCount; i++) {
    404     if (!FX_EDIT_ISLATINWORD(wsSpell[i])) {
    405       nWordCount = i;
    406       break;
    407     }
    408   }
    409   int32_t nDestLen = bsReplace.GetLength();
    410   CFX_WideString wsDest;
    411   FX_WCHAR* pBuffer = wsDest.GetBuffer(nDestLen);
    412   for (int32_t i = 0; i < nDestLen; i++) {
    413     pBuffer[i] = bsReplace[i];
    414   }
    415   wsDest.ReleaseBuffer(nDestLen);
    416   Replace(nWordStart, nWordCount, wsDest);
    417   return TRUE;
    418 }
    419 void CFWL_EditImp::DrawSpellCheck(CFX_Graphics* pGraphics,
    420                                   const CFX_Matrix* pMatrix) {
    421   pGraphics->SaveGraphState();
    422   if (pMatrix) {
    423     pGraphics->ConcatMatrix(const_cast<CFX_Matrix*>(pMatrix));
    424   }
    425   FX_ARGB cr = 0xFFFF0000;
    426   CFX_Color crLine(cr);
    427   CFWL_EvtEdtCheckWord checkWordEvent;
    428   checkWordEvent.m_pSrcTarget = m_pInterface;
    429   CFX_ByteString sLatinWord;
    430   CFX_Path pathSpell;
    431   pathSpell.Create();
    432   int32_t nStart = 0;
    433   FX_FLOAT fOffSetX = m_rtEngine.left - m_fScrollOffsetX;
    434   FX_FLOAT fOffSetY = m_rtEngine.top - m_fScrollOffsetY + m_fVAlignOffset;
    435   CFX_WideString wsSpell;
    436   this->GetText(wsSpell);
    437   int32_t nContentLen = wsSpell.GetLength();
    438   for (int i = 0; i < nContentLen; i++) {
    439     if (FX_EDIT_ISLATINWORD(wsSpell[i])) {
    440       if (sLatinWord.IsEmpty()) {
    441         nStart = i;
    442       }
    443       sLatinWord += (FX_CHAR)wsSpell[i];
    444     } else {
    445       checkWordEvent.bsWord = sLatinWord;
    446       checkWordEvent.bCheckWord = TRUE;
    447       DispatchEvent(&checkWordEvent);
    448       if (!sLatinWord.IsEmpty() && !checkWordEvent.bCheckWord) {
    449         AddSpellCheckObj(pathSpell, nStart, sLatinWord.GetLength(), fOffSetX,
    450                          fOffSetY);
    451       }
    452       sLatinWord.Empty();
    453     }
    454   }
    455   checkWordEvent.bsWord = sLatinWord;
    456   checkWordEvent.bCheckWord = TRUE;
    457   DispatchEvent(&checkWordEvent);
    458   if (!sLatinWord.IsEmpty() && !checkWordEvent.bCheckWord) {
    459     AddSpellCheckObj(pathSpell, nStart, sLatinWord.GetLength(), fOffSetX,
    460                      fOffSetY);
    461   }
    462   if (!pathSpell.IsEmpty()) {
    463     CFX_RectF rtClip = m_rtEngine;
    464     CFX_Matrix mt;
    465     mt.Set(1, 0, 0, 1, fOffSetX, fOffSetY);
    466     if (pMatrix) {
    467       pMatrix->TransformRect(rtClip);
    468       mt.Concat(*pMatrix);
    469     }
    470     pGraphics->SetClipRect(rtClip);
    471     pGraphics->SetStrokeColor(&crLine);
    472     pGraphics->SetLineWidth(0);
    473     pGraphics->StrokePath(&pathSpell, NULL);
    474   }
    475   pGraphics->RestoreGraphState();
    476 }
    477 FWL_ERR CFWL_EditImp::DrawWidget(CFX_Graphics* pGraphics,
    478                                  const CFX_Matrix* pMatrix) {
    479   if (!pGraphics)
    480     return FWL_ERR_Indefinite;
    481   if (!m_pProperties->m_pThemeProvider)
    482     return FWL_ERR_Indefinite;
    483   if (m_rtClient.IsEmpty()) {
    484     return FWL_ERR_Indefinite;
    485   }
    486   IFWL_ThemeProvider* pTheme = m_pProperties->m_pThemeProvider;
    487   if (!m_pWidgetMgr->IsFormDisabled()) {
    488     DrawTextBk(pGraphics, pTheme, pMatrix);
    489   }
    490   if (m_pEdtEngine) {
    491     DrawContent(pGraphics, pTheme, pMatrix);
    492   }
    493   if ((m_pProperties->m_dwStates & FWL_WGTSTATE_Focused) &&
    494       !(m_pProperties->m_dwStyleExes & FWL_STYLEEXT_EDT_ReadOnly)) {
    495     DrawSpellCheck(pGraphics, pMatrix);
    496   }
    497   if (HasBorder()) {
    498     DrawBorder(pGraphics, FWL_PART_EDT_Border, pTheme, pMatrix);
    499   }
    500   if (HasEdge()) {
    501     DrawEdge(pGraphics, FWL_PART_EDT_Edge, pTheme, pMatrix);
    502   }
    503   return FWL_ERR_Succeeded;
    504 }
    505 FWL_ERR CFWL_EditImp::SetThemeProvider(IFWL_ThemeProvider* pThemeProvider) {
    506   if (!pThemeProvider)
    507     return FWL_ERR_Indefinite;
    508   if (m_pHorzScrollBar) {
    509     m_pHorzScrollBar->SetThemeProvider(pThemeProvider);
    510   }
    511   if (m_pVertScrollBar) {
    512     m_pVertScrollBar->SetThemeProvider(pThemeProvider);
    513   }
    514   if (m_pCaret) {
    515     m_pCaret->SetThemeProvider(pThemeProvider);
    516   }
    517   m_pProperties->m_pThemeProvider = pThemeProvider;
    518   return FWL_ERR_Succeeded;
    519 }
    520 FWL_ERR CFWL_EditImp::SetText(const CFX_WideString& wsText) {
    521   m_pEdtEngine->SetText(wsText);
    522   return FWL_ERR_Succeeded;
    523 }
    524 int32_t CFWL_EditImp::GetTextLength() const {
    525   if (!m_pEdtEngine)
    526     return -1;
    527   return m_pEdtEngine->GetTextLength();
    528 }
    529 FWL_ERR CFWL_EditImp::GetText(CFX_WideString& wsText,
    530                               int32_t nStart,
    531                               int32_t nCount) const {
    532   if (!m_pEdtEngine)
    533     return FWL_ERR_Succeeded;
    534   m_pEdtEngine->GetText(wsText, nStart, nCount);
    535   return FWL_ERR_Succeeded;
    536 }
    537 FWL_ERR CFWL_EditImp::ClearText() {
    538   if (!m_pEdtEngine)
    539     return FWL_ERR_Succeeded;
    540   m_pEdtEngine->ClearText();
    541   return FWL_ERR_Succeeded;
    542 }
    543 int32_t CFWL_EditImp::GetCaretPos() const {
    544   if (!m_pEdtEngine)
    545     return -1;
    546   return m_pEdtEngine->GetCaretPos();
    547 }
    548 int32_t CFWL_EditImp::SetCaretPos(int32_t nIndex, FX_BOOL bBefore) {
    549   if (!m_pEdtEngine)
    550     return -1;
    551   return m_pEdtEngine->SetCaretPos(nIndex, bBefore);
    552 }
    553 FWL_ERR CFWL_EditImp::AddSelRange(int32_t nStart, int32_t nCount) {
    554   if (!m_pEdtEngine)
    555     return FWL_ERR_Succeeded;
    556   m_pEdtEngine->AddSelRange(nStart, nCount);
    557   return FWL_ERR_Succeeded;
    558 }
    559 int32_t CFWL_EditImp::CountSelRanges() {
    560   if (!m_pEdtEngine)
    561     return 0;
    562   return m_pEdtEngine->CountSelRanges();
    563   return FWL_ERR_Succeeded;
    564 }
    565 int32_t CFWL_EditImp::GetSelRange(int32_t nIndex, int32_t& nStart) {
    566   if (!m_pEdtEngine)
    567     return -1;
    568   return m_pEdtEngine->GetSelRange(nIndex, nStart);
    569 }
    570 FWL_ERR CFWL_EditImp::ClearSelections() {
    571   if (!m_pEdtEngine)
    572     return FWL_ERR_Succeeded;
    573   m_pEdtEngine->ClearSelection();
    574   return FWL_ERR_Succeeded;
    575 }
    576 int32_t CFWL_EditImp::GetLimit() {
    577   return m_nLimit;
    578 }
    579 FWL_ERR CFWL_EditImp::SetLimit(int32_t nLimit) {
    580   m_nLimit = nLimit;
    581   if (!m_pEdtEngine)
    582     return FWL_ERR_Succeeded;
    583   m_pEdtEngine->SetLimit(nLimit);
    584   return FWL_ERR_Succeeded;
    585 }
    586 FWL_ERR CFWL_EditImp::SetAliasChar(FX_WCHAR wAlias) {
    587   if (!m_pEdtEngine)
    588     return FWL_ERR_Indefinite;
    589   m_pEdtEngine->SetAliasChar(wAlias);
    590   return FWL_ERR_Succeeded;
    591 }
    592 FWL_ERR CFWL_EditImp::SetFormatString(const CFX_WideString& wsFormat) {
    593   if (!m_pEdtEngine)
    594     return FWL_ERR_Succeeded;
    595   m_pEdtEngine->SetFormatBlock(0, wsFormat);
    596   return FWL_ERR_Succeeded;
    597 }
    598 FWL_ERR CFWL_EditImp::Insert(int32_t nStart,
    599                              const FX_WCHAR* lpText,
    600                              int32_t nLen) {
    601   if (!m_pEdtEngine)
    602     return FWL_ERR_Succeeded;
    603   if ((m_pProperties->m_dwStyleExes & FWL_STYLEEXT_EDT_ReadOnly) ||
    604       (m_pProperties->m_dwStates & FWL_WGTSTATE_Disabled)) {
    605     return FWL_ERR_Indefinite;
    606   }
    607   m_pEdtEngine->Insert(nStart, lpText, nLen);
    608   return FWL_ERR_Succeeded;
    609 }
    610 FWL_ERR CFWL_EditImp::DeleteSelections() {
    611   if (!m_pEdtEngine)
    612     return FWL_ERR_Succeeded;
    613   int32_t iCount = m_pEdtEngine->CountSelRanges();
    614   if (iCount > 0) {
    615     m_pEdtEngine->Delete(-1);
    616   }
    617   return FWL_ERR_Succeeded;
    618 }
    619 FWL_ERR CFWL_EditImp::DeleteRange(int32_t nStart, int32_t nCount) {
    620   if (!m_pEdtEngine)
    621     return FWL_ERR_Succeeded;
    622   m_pEdtEngine->DeleteRange(nStart, nCount);
    623   return FWL_ERR_Succeeded;
    624 }
    625 FWL_ERR CFWL_EditImp::ReplaceSelections(const CFX_WideStringC& wsReplace) {
    626   if (!m_pEdtEngine)
    627     return FWL_ERR_Succeeded;
    628   int32_t iCount = m_pEdtEngine->CountSelRanges();
    629   for (int i = 0; i < iCount; i++) {
    630     int32_t nStart;
    631     int32_t nCount = m_pEdtEngine->GetSelRange(i, nStart);
    632     m_pEdtEngine->Replace(nStart, nCount, wsReplace);
    633   }
    634   return FWL_ERR_Succeeded;
    635 }
    636 FWL_ERR CFWL_EditImp::Replace(int32_t nStart,
    637                               int32_t nLen,
    638                               const CFX_WideStringC& wsReplace) {
    639   if (!m_pEdtEngine)
    640     return FWL_ERR_Succeeded;
    641   m_pEdtEngine->Replace(nStart, nLen, wsReplace);
    642   return FWL_ERR_Succeeded;
    643 }
    644 FWL_ERR CFWL_EditImp::DoClipboard(int32_t iCmd) {
    645   if (!m_pEdtEngine)
    646     return FWL_ERR_Succeeded;
    647   if ((m_pProperties->m_dwStyleExes & FWL_STYLEEXT_EDT_ReadOnly) ||
    648       (m_pProperties->m_dwStates & FWL_WGTSTATE_Disabled)) {
    649     return FWL_ERR_Succeeded;
    650   }
    651   IFWL_AdapterNative* pNative = FWL_GetAdapterNative();
    652   if (!pNative)
    653     return FWL_ERR_Indefinite;
    654   IFWL_AdapterClipboardMgr* pClipBorder = pNative->GetClipboardMgr();
    655   if (!pClipBorder)
    656     return FWL_ERR_Indefinite;
    657   CFX_WideString wsText;
    658   switch (iCmd) {
    659     case 1: {
    660       int32_t nStart;
    661       int32_t nCount = m_pEdtEngine->GetSelRange(0, nStart);
    662       if (nCount < 1) {
    663         break;
    664       }
    665       m_pEdtEngine->GetText(wsText, nStart, nCount);
    666       pClipBorder->SetStringData(wsText);
    667       break;
    668     }
    669     case 2: {
    670       int32_t nStart;
    671       int32_t nCount = m_pEdtEngine->GetSelRange(0, nStart);
    672       if (nCount < 1) {
    673         break;
    674       }
    675       m_pEdtEngine->GetText(wsText, nStart, nCount);
    676       m_pEdtEngine->DeleteRange(nStart, nCount);
    677       m_pEdtEngine->ClearSelection();
    678       pClipBorder->SetStringData(wsText);
    679       break;
    680     }
    681     case 3: {
    682       pClipBorder->GetStringData(wsText);
    683       int32_t iLen = wsText.GetLength();
    684       if (iLen < 0) {
    685         break;
    686       }
    687       if (wsText[iLen] == L'\0') {
    688         if (iLen == 1) {
    689           break;
    690         }
    691         iLen--;
    692         wsText = wsText.Left(iLen);
    693       }
    694       int32_t nPos = m_pEdtEngine->GetCaretPos();
    695       m_pEdtEngine->Insert(nPos, wsText, iLen);
    696       break;
    697     }
    698     default: {}
    699   }
    700   return FWL_ERR_Succeeded;
    701 }
    702 FX_BOOL CFWL_EditImp::Copy(CFX_WideString& wsCopy) {
    703   if (!m_pEdtEngine)
    704     return FALSE;
    705   int32_t nCount = m_pEdtEngine->CountSelRanges();
    706   if (nCount == 0) {
    707     return FALSE;
    708   }
    709   wsCopy.Empty();
    710   CFX_WideString wsTemp;
    711   int32_t nStart, nLength;
    712   for (int32_t i = 0; i < nCount; i++) {
    713     nLength = m_pEdtEngine->GetSelRange(i, nStart);
    714     m_pEdtEngine->GetText(wsTemp, nStart, nLength);
    715     wsCopy += wsTemp;
    716     wsTemp.Empty();
    717   }
    718   return TRUE;
    719 }
    720 FX_BOOL CFWL_EditImp::Cut(CFX_WideString& wsCut) {
    721   if (!m_pEdtEngine)
    722     return FALSE;
    723   int32_t nCount = m_pEdtEngine->CountSelRanges();
    724   if (nCount == 0) {
    725     return FALSE;
    726   }
    727   wsCut.Empty();
    728   CFX_WideString wsTemp;
    729   int32_t nStart, nLength;
    730   for (int32_t i = 0; i < nCount; i++) {
    731     nLength = m_pEdtEngine->GetSelRange(i, nStart);
    732     m_pEdtEngine->GetText(wsTemp, nStart, nLength);
    733     wsCut += wsTemp;
    734     wsTemp.Empty();
    735   }
    736   m_pEdtEngine->Delete(0);
    737   return TRUE;
    738 }
    739 FX_BOOL CFWL_EditImp::Paste(const CFX_WideString& wsPaste) {
    740   if (!m_pEdtEngine)
    741     return FALSE;
    742   int32_t nCaret = m_pEdtEngine->GetCaretPos();
    743   int32_t iError =
    744       m_pEdtEngine->Insert(nCaret, wsPaste.c_str(), wsPaste.GetLength());
    745   if (iError < 0) {
    746     ProcessInsertError(iError);
    747     return FALSE;
    748   }
    749   return TRUE;
    750 }
    751 FX_BOOL CFWL_EditImp::Delete() {
    752   if (!m_pEdtEngine)
    753     return FALSE;
    754   int32_t nCount = m_pEdtEngine->CountSelRanges();
    755   if (nCount < 1) {
    756     return FALSE;
    757   }
    758   m_pEdtEngine->Delete(0);
    759   return TRUE;
    760 }
    761 FX_BOOL CFWL_EditImp::Redo(const CFX_ByteStringC& bsRecord) {
    762   if (!m_pEdtEngine)
    763     return FALSE;
    764   if (m_pProperties->m_dwStyleExes & FWL_STYLEEXT_EDT_NoRedoUndo) {
    765     return TRUE;
    766   }
    767   return m_pEdtEngine->Redo(bsRecord);
    768 }
    769 FX_BOOL CFWL_EditImp::Undo(const CFX_ByteStringC& bsRecord) {
    770   if (!m_pEdtEngine)
    771     return FALSE;
    772   if (m_pProperties->m_dwStyleExes & FWL_STYLEEXT_EDT_NoRedoUndo) {
    773     return TRUE;
    774   }
    775   return m_pEdtEngine->Undo(bsRecord);
    776 }
    777 FX_BOOL CFWL_EditImp::Undo() {
    778   if (!CanUndo()) {
    779     return FALSE;
    780   }
    781   CFX_ByteString bsRecord = m_RecordArr[m_iCurRecord--];
    782   return Undo(bsRecord);
    783 }
    784 FX_BOOL CFWL_EditImp::Redo() {
    785   if (!CanRedo()) {
    786     return FALSE;
    787   }
    788   CFX_ByteString bsRecord = m_RecordArr[++m_iCurRecord];
    789   return Redo(bsRecord);
    790 }
    791 FX_BOOL CFWL_EditImp::CanUndo() {
    792   return m_iCurRecord >= 0;
    793 }
    794 FX_BOOL CFWL_EditImp::CanRedo() {
    795   return m_iCurRecord < m_RecordArr.GetSize() - 1;
    796 }
    797 FWL_ERR CFWL_EditImp::SetTabWidth(FX_FLOAT fTabWidth, FX_BOOL bEquidistant) {
    798   if (!m_pEdtEngine)
    799     return FWL_ERR_Succeeded;
    800   FDE_LPTXTEDTPARAMS pParams =
    801       (FDE_LPTXTEDTPARAMS)m_pEdtEngine->GetEditParams();
    802   pParams->fTabWidth = fTabWidth;
    803   pParams->bTabEquidistant = bEquidistant;
    804   return FWL_ERR_Succeeded;
    805 }
    806 FWL_ERR CFWL_EditImp::SetOuter(IFWL_Widget* pOuter) {
    807   m_pOuter = pOuter;
    808   return FWL_ERR_Succeeded;
    809 }
    810 FWL_ERR CFWL_EditImp::SetNumberRange(int32_t iMin, int32_t iMax) {
    811   m_iMin = iMin;
    812   m_iMax = iMax;
    813   m_bSetRange = TRUE;
    814   return FWL_ERR_Succeeded;
    815 }
    816 void CFWL_EditImp::On_CaretChanged(IFDE_TxtEdtEngine* pEdit,
    817                                    int32_t nPage,
    818                                    FX_BOOL bVisible) {
    819   if (m_rtEngine.IsEmpty()) {
    820     return;
    821   }
    822   if ((m_pProperties->m_dwStates & FWL_WGTSTATE_Focused) == 0) {
    823     return;
    824   }
    825   FX_BOOL bRepaintContent = UpdateOffset();
    826   UpdateCaret();
    827   CFX_RectF rtInvalid;
    828   rtInvalid.Set(0, 0, 0, 0);
    829   FX_BOOL bRepaintScroll = FALSE;
    830   if (m_pProperties->m_dwStyleExes & FWL_STYLEEXT_EDT_MultiLine) {
    831     IFWL_ScrollBar* pScroll = UpdateScroll();
    832     if (pScroll) {
    833       pScroll->GetWidgetRect(rtInvalid);
    834       bRepaintScroll = TRUE;
    835     }
    836   }
    837   if (bRepaintContent || bRepaintScroll) {
    838     if (bRepaintContent) {
    839       rtInvalid.Union(m_rtEngine);
    840     }
    841     Repaint(&rtInvalid);
    842   }
    843 }
    844 void CFWL_EditImp::On_TextChanged(IFDE_TxtEdtEngine* pEdit,
    845                                   FDE_TXTEDT_TEXTCHANGE_INFO& ChangeInfo) {
    846   FX_DWORD dwStyleEx = m_pProperties->m_dwStyleExes;
    847   if (dwStyleEx & FWL_STYLEEXT_EDT_VAlignMask) {
    848     UpdateVAlignment();
    849   }
    850   IFDE_TxtEdtPage* page = m_pEdtEngine->GetPage(0);
    851   FX_FLOAT fContentWidth = page->GetContentsBox().width;
    852   FX_FLOAT fContentHeight = page->GetContentsBox().height;
    853   CFX_RectF rtTemp;
    854   GetClientRect(rtTemp);
    855   FX_BOOL bHSelfAdaption =
    856       m_pProperties->m_dwStyleExes & FWL_STYLEEXT_EDT_HSelfAdaption;
    857   FX_BOOL bVSelfAdaption =
    858       m_pProperties->m_dwStyleExes & FWL_STYLEEXT_EDT_VSelfAdaption;
    859   FX_BOOL bNeedUpdate = FALSE;
    860   if (bHSelfAdaption || bVSelfAdaption) {
    861     CFWL_EvtEdtPreSelfAdaption evt;
    862     evt.m_pSrcTarget = m_pInterface;
    863     evt.bHSelfAdaption = TRUE;
    864     evt.bVSelfAdaption = TRUE;
    865     FX_FLOAT fWidth;
    866     FX_FLOAT fHight;
    867     fWidth = bHSelfAdaption ? fContentWidth : m_pProperties->m_rtWidget.width;
    868     fHight = bVSelfAdaption ? fContentHeight : m_pProperties->m_rtWidget.height;
    869     evt.rtAfterChange.Set(0, 0, fWidth, fHight);
    870     DispatchEvent(&evt);
    871     if (!evt.bHSelfAdaption) {
    872       ModifyStylesEx(
    873           0, FWL_STYLEEXT_EDT_HSelfAdaption | FWL_STYLEEXT_EDT_AutoHScroll);
    874     }
    875     if (!evt.bVSelfAdaption) {
    876       ModifyStylesEx(
    877           0, FWL_STYLEEXT_EDT_VSelfAdaption | FWL_STYLEEXT_EDT_AutoVScroll);
    878     }
    879     bNeedUpdate = (bHSelfAdaption && !evt.bHSelfAdaption) ||
    880                   (bVSelfAdaption && !evt.bVSelfAdaption);
    881   }
    882   FX_FLOAT fContentWidth1 = fContentWidth;
    883   FX_FLOAT fContentHeight1 = fContentHeight;
    884   if (bNeedUpdate) {
    885     UpdateEditParams();
    886     UpdateEditLayout();
    887     IFDE_TxtEdtPage* page1 = m_pEdtEngine->GetPage(0);
    888     fContentWidth1 = page1->GetContentsBox().width;
    889     fContentHeight1 = page1->GetContentsBox().height;
    890   }
    891   if (m_pProperties->m_dwStyleExes & FWL_STYLEEXT_EDT_HSelfAdaption) {
    892     rtTemp.width = std::max(m_pProperties->m_rtWidget.width, fContentWidth1);
    893     m_pProperties->m_rtWidget.width = fContentWidth1;
    894   }
    895   if (m_pProperties->m_dwStyleExes & FWL_STYLEEXT_EDT_VSelfAdaption) {
    896     rtTemp.height = std::max(m_pProperties->m_rtWidget.height, fContentHeight1);
    897     m_pProperties->m_rtWidget.height = fContentHeight1;
    898   }
    899   CFWL_EvtEdtTextChanged event;
    900   event.m_pSrcTarget = m_pInterface;
    901   event.nChangeType = ChangeInfo.nChangeType;
    902   event.wsInsert = ChangeInfo.wsInsert;
    903   event.wsDelete = ChangeInfo.wsDelete;
    904   event.wsPrevText = ChangeInfo.wsPrevText;
    905   DispatchEvent(&event);
    906   LayoutScrollBar();
    907   Repaint(&rtTemp);
    908 }
    909 void CFWL_EditImp::On_SelChanged(IFDE_TxtEdtEngine* pEdit) {
    910   CFX_RectF rtTemp;
    911   GetClientRect(rtTemp);
    912   Repaint(&rtTemp);
    913 }
    914 FX_BOOL CFWL_EditImp::On_PageLoad(IFDE_TxtEdtEngine* pEdit,
    915                                   int32_t nPageIndex,
    916                                   int32_t nPurpose) {
    917   IFDE_TxtEdtEngine* pEdtEngine = m_pEdtEngine;
    918   IFDE_TxtEdtPage* pPage = pEdtEngine->GetPage(nPageIndex);
    919   if (!pPage)
    920     return FALSE;
    921   pPage->LoadPage();
    922   return TRUE;
    923 }
    924 FX_BOOL CFWL_EditImp::On_PageUnload(IFDE_TxtEdtEngine* pEdit,
    925                                     int32_t nPageIndex,
    926                                     int32_t nPurpose) {
    927   IFDE_TxtEdtEngine* pEdtEngine = m_pEdtEngine;
    928   IFDE_TxtEdtPage* pPage = pEdtEngine->GetPage(nPageIndex);
    929   if (!pPage)
    930     return FALSE;
    931   pPage->UnloadPage();
    932   return TRUE;
    933 }
    934 void CFWL_EditImp::On_AddDoRecord(IFDE_TxtEdtEngine* pEdit,
    935                                   const CFX_ByteStringC& bsDoRecord) {
    936   AddDoRecord(bsDoRecord);
    937   CFWL_WidgetImp* pSrcTarget = GetRootOuter();
    938   if (!pSrcTarget) {
    939     pSrcTarget = this;
    940   }
    941   CFWL_EvtEdtAddDoRecord evt;
    942   evt.m_pSrcTarget = m_pInterface;
    943   evt.m_wsDoRecord = bsDoRecord;
    944   m_pDelegate->OnProcessEvent(&evt);
    945 }
    946 FX_BOOL CFWL_EditImp::On_ValidateField(IFDE_TxtEdtEngine* pEdit,
    947                                        int32_t nBlockIndex,
    948                                        int32_t nFieldIndex,
    949                                        const CFX_WideString& wsFieldText,
    950                                        int32_t nCharIndex) {
    951   return TRUE;
    952 }
    953 FX_BOOL CFWL_EditImp::On_ValidateBlock(IFDE_TxtEdtEngine* pEdit,
    954                                        int32_t nBlockIndex) {
    955   return TRUE;
    956 }
    957 FX_BOOL CFWL_EditImp::On_GetBlockFormatText(IFDE_TxtEdtEngine* pEdit,
    958                                             int32_t nBlockIndex,
    959                                             CFX_WideString& wsBlockText) {
    960   return FALSE;
    961 }
    962 FX_BOOL CFWL_EditImp::On_Validate(IFDE_TxtEdtEngine* pEdit,
    963                                   CFX_WideString& wsText) {
    964   IFWL_Widget* pDst = GetOuter();
    965   if (!pDst) {
    966     pDst = m_pInterface;
    967   }
    968   CFWL_EvtEdtValidate event;
    969   event.pDstWidget = pDst;
    970   event.m_pSrcTarget = m_pInterface;
    971   event.wsInsert = wsText;
    972   event.bValidate = TRUE;
    973   DispatchEvent(&event);
    974   return event.bValidate;
    975 }
    976 FWL_ERR CFWL_EditImp::SetBackgroundColor(FX_DWORD color) {
    977   m_backColor = color;
    978   m_updateBackColor = TRUE;
    979   return FWL_ERR_Succeeded;
    980 }
    981 FWL_ERR CFWL_EditImp::SetFont(const CFX_WideString& wsFont, FX_FLOAT fSize) {
    982   m_wsFont = wsFont;
    983   m_fFontSize = fSize;
    984   return FWL_ERR_Succeeded;
    985 }
    986 void CFWL_EditImp::SetScrollOffset(FX_FLOAT fScrollOffset) {
    987   m_fScrollOffsetY = fScrollOffset;
    988 }
    989 void CFWL_EditImp::DrawTextBk(CFX_Graphics* pGraphics,
    990                               IFWL_ThemeProvider* pTheme,
    991                               const CFX_Matrix* pMatrix) {
    992   CFWL_ThemeBackground param;
    993   param.m_pWidget = m_pInterface;
    994   param.m_iPart = FWL_PART_EDT_Background;
    995   param.m_dwData = FWL_PARTDATA_EDT_Background;
    996   param.m_dwStates = m_pProperties->m_dwStyleExes & FWL_STYLEEXT_EDT_ReadOnly
    997                          ? FWL_PARTSTATE_EDT_ReadOnly
    998                          : FWL_PARTSTATE_EDT_Normal;
    999   FX_DWORD dwStates = (m_pProperties->m_dwStates & FWL_WGTSTATE_Disabled);
   1000   if (dwStates) {
   1001     param.m_dwStates = FWL_PARTSTATE_EDT_Disable;
   1002   }
   1003   param.m_pGraphics = pGraphics;
   1004   param.m_matrix = *pMatrix;
   1005   param.m_rtPart = m_rtClient;
   1006   pTheme->DrawBackground(&param);
   1007   if (!IsShowScrollBar(TRUE) || !IsShowScrollBar(FALSE)) {
   1008     return;
   1009   }
   1010   CFX_RectF rtScorll;
   1011   m_pHorzScrollBar->GetWidgetRect(rtScorll);
   1012   CFX_RectF rtStatic;
   1013   rtStatic.Set(m_rtClient.right() - rtScorll.height,
   1014                m_rtClient.bottom() - rtScorll.height, rtScorll.height,
   1015                rtScorll.height);
   1016   param.m_dwData = FWL_PARTDATA_EDT_StaticBackground;
   1017   param.m_rtPart = rtStatic;
   1018   pTheme->DrawBackground(&param);
   1019 }
   1020 void CFWL_EditImp::DrawContent(CFX_Graphics* pGraphics,
   1021                                IFWL_ThemeProvider* pTheme,
   1022                                const CFX_Matrix* pMatrix) {
   1023   if (!m_pEdtEngine)
   1024     return;
   1025   IFDE_TxtEdtPage* pPage = m_pEdtEngine->GetPage(0);
   1026   if (!pPage)
   1027     return;
   1028   pGraphics->SaveGraphState();
   1029   if (m_pProperties->m_dwStyleExes & FWL_STYLEEXT_EDT_CombText) {
   1030     pGraphics->SaveGraphState();
   1031   }
   1032   CFX_RectF rtClip = m_rtEngine;
   1033   FX_FLOAT fOffSetX = m_rtEngine.left - m_fScrollOffsetX;
   1034   FX_FLOAT fOffSetY = m_rtEngine.top - m_fScrollOffsetY + m_fVAlignOffset;
   1035   CFX_Matrix mt;
   1036   mt.Set(1, 0, 0, 1, fOffSetX, fOffSetY);
   1037   if (pMatrix) {
   1038     pMatrix->TransformRect(rtClip);
   1039     mt.Concat(*pMatrix);
   1040   }
   1041   FX_BOOL bShowSel =
   1042       (m_pProperties->m_dwStyleExes & FWL_STYLEEXT_EDT_NoHideSel) ||
   1043       (m_pProperties->m_dwStates & FWL_WGTSTATE_Focused);
   1044   if (bShowSel) {
   1045     IFWL_Widget* pForm =
   1046         m_pWidgetMgr->GetWidget(m_pInterface, FWL_WGTRELATION_SystemForm);
   1047     if (pForm) {
   1048       bShowSel = (pForm->GetStates() & FWL_WGTSTATE_Deactivated) !=
   1049                  FWL_WGTSTATE_Deactivated;
   1050     }
   1051   }
   1052   int32_t nSelCount = m_pEdtEngine->CountSelRanges();
   1053   if (bShowSel && nSelCount > 0) {
   1054     int32_t nPageCharStart = pPage->GetCharStart();
   1055     int32_t nPageCharCount = pPage->GetCharCount();
   1056     int32_t nPageCharEnd = nPageCharStart + nPageCharCount - 1;
   1057     int32_t nCharCount;
   1058     int32_t nCharStart;
   1059     CFX_RectFArray rectArr;
   1060     int32_t i = 0;
   1061     for (i = 0; i < nSelCount; i++) {
   1062       nCharCount = m_pEdtEngine->GetSelRange(i, nCharStart);
   1063       int32_t nCharEnd = nCharStart + nCharCount - 1;
   1064       if (nCharEnd < nPageCharStart || nCharStart > nPageCharEnd) {
   1065         continue;
   1066       }
   1067       int32_t nBgn = std::max(nCharStart, nPageCharStart);
   1068       int32_t nEnd = std::min(nCharEnd, nPageCharEnd);
   1069       pPage->CalcRangeRectArray(nBgn - nPageCharStart, nEnd - nBgn + 1,
   1070                                 rectArr);
   1071     }
   1072     int32_t nCount = rectArr.GetSize();
   1073     CFX_Path path;
   1074     path.Create();
   1075     for (i = 0; i < nCount; i++) {
   1076       rectArr[i].left += fOffSetX;
   1077       rectArr[i].top += fOffSetY;
   1078       path.AddRectangle(rectArr[i].left, rectArr[i].top, rectArr[i].width,
   1079                         rectArr[i].height);
   1080     }
   1081     pGraphics->SetClipRect(rtClip);
   1082     CFWL_ThemeBackground param;
   1083     param.m_pGraphics = pGraphics;
   1084     param.m_matrix = *pMatrix;
   1085     param.m_pWidget = m_pInterface;
   1086     param.m_iPart = FWL_PART_EDT_Background;
   1087     param.m_pPath = &path;
   1088     pTheme->DrawBackground(&param);
   1089   }
   1090   CFX_RenderDevice* pRenderDev = pGraphics->GetRenderDevice();
   1091   if (!pRenderDev)
   1092     return;
   1093   IFDE_RenderDevice* pRenderDevice = IFDE_RenderDevice::Create(pRenderDev);
   1094   if (!pRenderDevice)
   1095     return;
   1096   IFDE_RenderContext* pRenderContext = IFDE_RenderContext::Create();
   1097   if (!pRenderContext)
   1098     return;
   1099   pRenderDevice->SetClipRect(rtClip);
   1100   pRenderContext->StartRender(pRenderDevice, pPage, mt);
   1101   pRenderContext->DoRender(NULL);
   1102   pRenderContext->Release();
   1103   pRenderDevice->Release();
   1104   if (m_pProperties->m_dwStyleExes & FWL_STYLEEXT_EDT_CombText) {
   1105     pGraphics->RestoreGraphState();
   1106     CFX_Path path;
   1107     path.Create();
   1108     int32_t iLimit = m_nLimit > 0 ? m_nLimit : 1;
   1109     FX_FLOAT fStep = m_rtEngine.width / iLimit;
   1110     FX_FLOAT fLeft = m_rtEngine.left + 1;
   1111     for (int32_t i = 1; i < iLimit; i++) {
   1112       fLeft += fStep;
   1113       path.AddLine(fLeft, m_rtClient.top, fLeft, m_rtClient.bottom());
   1114     }
   1115     CFWL_ThemeBackground param;
   1116     param.m_pGraphics = pGraphics;
   1117     param.m_matrix = *pMatrix;
   1118     param.m_pWidget = m_pInterface;
   1119     param.m_iPart = FWL_PART_EDT_CombTextLine;
   1120     param.m_pPath = &path;
   1121     pTheme->DrawBackground(&param);
   1122   }
   1123   pGraphics->RestoreGraphState();
   1124 }
   1125 void CFWL_EditImp::UpdateEditEngine() {
   1126   UpdateEditParams();
   1127   UpdateEditLayout();
   1128   if (m_nLimit > -1) {
   1129     m_pEdtEngine->SetLimit(m_nLimit);
   1130   }
   1131 }
   1132 void CFWL_EditImp::UpdateEditParams() {
   1133   FDE_TXTEDTPARAMS params;
   1134   params.nHorzScale = 100;
   1135   params.fPlateWidth = m_rtEngine.width;
   1136   params.fPlateHeight = m_rtEngine.height;
   1137   if (m_pProperties->m_dwStyles & FWL_WGTSTYLE_RTLLayout) {
   1138     params.dwLayoutStyles |= FDE_TEXTEDITLAYOUT_RTL;
   1139   }
   1140   if (m_pProperties->m_dwStyleExes & FWL_STYLEEXT_EDT_VerticalLayout) {
   1141     params.dwLayoutStyles |= FDE_TEXTEDITLAYOUT_DocVertical;
   1142   }
   1143   if (m_pProperties->m_dwStyleExes & FWL_STYLEEXT_EDT_VerticalChars) {
   1144     params.dwLayoutStyles |= FDE_TEXTEDITLAYOUT_CharVertial;
   1145   }
   1146   if (m_pProperties->m_dwStyleExes & FWL_STYLEEXT_EDT_ReverseLine) {
   1147     params.dwLayoutStyles |= FDE_TEXTEDITLAYOUT_LineReserve;
   1148   }
   1149   if (m_pProperties->m_dwStyleExes & FWL_STYLEEXT_EDT_ArabicShapes) {
   1150     params.dwLayoutStyles |= FDE_TEXTEDITLAYOUT_ArabicShapes;
   1151   }
   1152   if (m_pProperties->m_dwStyleExes & FWL_STYLEEXT_EDT_ExpandTab) {
   1153     params.dwLayoutStyles |= FDE_TEXTEDITLAYOUT_ExpandTab;
   1154   }
   1155   if (m_pProperties->m_dwStyleExes & FWL_STYLEEXT_EDT_CombText) {
   1156     params.dwLayoutStyles |= FDE_TEXTEDITLAYOUT_CombText;
   1157   }
   1158   if (m_pProperties->m_dwStyleExes & FWL_STYLEEXT_EDT_LastLineHeight) {
   1159     params.dwLayoutStyles |= FDE_TEXTEDITLAYOUT_LastLineHeight;
   1160   }
   1161   if (m_pProperties->m_dwStyleExes & FWL_STYLEEXT_EDT_Validate) {
   1162     params.dwMode |= FDE_TEXTEDITMODE_Validate;
   1163   }
   1164   if (m_pProperties->m_dwStyleExes & FWL_STYLEEXT_EDT_Password) {
   1165     params.dwMode |= FDE_TEXTEDITMODE_Password;
   1166   }
   1167   switch (m_pProperties->m_dwStyleExes & FWL_STYLEEXT_EDT_HAlignMask) {
   1168     case FWL_STYLEEXT_EDT_HNear: {
   1169       params.dwAlignment |= FDE_TEXTEDITALIGN_Left;
   1170       break;
   1171     }
   1172     case FWL_STYLEEXT_EDT_HCenter: {
   1173       params.dwAlignment |= FDE_TEXTEDITALIGN_Center;
   1174       break;
   1175     }
   1176     case FWL_STYLEEXT_EDT_HFar: {
   1177       params.dwAlignment |= FDE_TEXTEDITALIGN_Right;
   1178       break;
   1179     }
   1180     default: {}
   1181   }
   1182   switch (m_pProperties->m_dwStyleExes & FWL_STYLEEXT_EDT_HAlignModeMask) {
   1183     case FWL_STYLEEXT_EDT_Justified: {
   1184       params.dwAlignment |= FDE_TEXTEDITALIGN_Justified;
   1185       break;
   1186     }
   1187     case FWL_STYLEEXT_EDT_Distributed: {
   1188       params.dwAlignment |= FDE_TEXTEDITALIGN_Distributed;
   1189       break;
   1190     }
   1191     default: { params.dwAlignment |= FDE_TEXTEDITALIGN_Normal; }
   1192   }
   1193   if (m_pProperties->m_dwStyleExes & FWL_STYLEEXT_EDT_MultiLine) {
   1194     params.dwMode |= FDE_TEXTEDITMODE_MultiLines;
   1195     if ((m_pProperties->m_dwStyles & FWL_WGTSTYLE_HScroll) == 0 &&
   1196         (m_pProperties->m_dwStyleExes & FWL_STYLEEXT_EDT_AutoHScroll) == 0) {
   1197       params.dwMode |=
   1198           FDE_TEXTEDITMODE_AutoLineWrap | FDE_TEXTEDITMODE_LimitArea_Horz;
   1199     }
   1200     if ((m_pProperties->m_dwStyles & FWL_WGTSTYLE_VScroll) == 0 &&
   1201         (m_pProperties->m_dwStyleExes & FWL_STYLEEXT_EDT_AutoVScroll) == 0) {
   1202       params.dwMode |= FDE_TEXTEDITMODE_LimitArea_Vert;
   1203     } else {
   1204       params.fPlateHeight = 0x00FFFFFF;
   1205     }
   1206   } else {
   1207     if ((m_pProperties->m_dwStyleExes & FWL_STYLEEXT_EDT_AutoHScroll) == 0) {
   1208       params.dwMode |= FDE_TEXTEDITMODE_LimitArea_Horz;
   1209     }
   1210   }
   1211   if ((m_pProperties->m_dwStyleExes & FWL_STYLEEXT_EDT_ReadOnly) ||
   1212       (m_pProperties->m_dwStates & FWL_WGTSTATE_Disabled)) {
   1213     params.dwMode |= FDE_TEXTEDITMODE_ReadOnly;
   1214   }
   1215   FX_FLOAT* pFontSize =
   1216       static_cast<FX_FLOAT*>(GetThemeCapacity(FWL_WGTCAPACITY_FontSize));
   1217   if (!pFontSize)
   1218     return;
   1219   m_fFontSize = *pFontSize;
   1220   FX_DWORD* pFontColor =
   1221       static_cast<FX_DWORD*>(GetThemeCapacity(FWL_WGTCAPACITY_TextColor));
   1222   if (!pFontColor)
   1223     return;
   1224   params.dwFontColor = *pFontColor;
   1225   FX_FLOAT* pLineHeight =
   1226       static_cast<FX_FLOAT*>(GetThemeCapacity(FWL_WGTCAPACITY_LineHeight));
   1227   if (!pLineHeight)
   1228     return;
   1229   params.fLineSpace = *pLineHeight;
   1230   IFX_Font* pFont =
   1231       static_cast<IFX_Font*>(GetThemeCapacity(FWL_WGTCAPACITY_Font));
   1232   if (!pFont)
   1233     return;
   1234   params.pFont = pFont;
   1235   params.fFontSize = m_fFontSize;
   1236   params.nLineCount = (int32_t)(params.fPlateHeight / params.fLineSpace);
   1237   if (params.nLineCount <= 0) {
   1238     params.nLineCount = 1;
   1239   }
   1240   params.fTabWidth = params.fFontSize * 1;
   1241   params.bTabEquidistant = TRUE;
   1242   params.wLineBreakChar = L'\n';
   1243   params.nCharRotation = 0;
   1244   params.pEventSink = this;
   1245   m_pEdtEngine->SetEditParams(params);
   1246 }
   1247 void CFWL_EditImp::UpdateEditLayout() {
   1248   if (m_pEdtEngine->GetTextLength() <= 0) {
   1249     m_pEdtEngine->SetTextByStream(NULL);
   1250   }
   1251   IFDE_TxtEdtPage* pPage = m_pEdtEngine->GetPage(0);
   1252   if (pPage) {
   1253     pPage->UnloadPage();
   1254     pPage = NULL;
   1255   }
   1256   m_pEdtEngine->StartLayout();
   1257   m_pEdtEngine->DoLayout(NULL);
   1258   m_pEdtEngine->EndLayout();
   1259   pPage = m_pEdtEngine->GetPage(0);
   1260   if (pPage) {
   1261     pPage->LoadPage();
   1262   }
   1263 }
   1264 FX_BOOL CFWL_EditImp::UpdateOffset() {
   1265   CFX_RectF rtCaret;
   1266   m_pEdtEngine->GetCaretRect(rtCaret);
   1267   FX_FLOAT fOffSetX = m_rtEngine.left - m_fScrollOffsetX;
   1268   FX_FLOAT fOffSetY = m_rtEngine.top - m_fScrollOffsetY + m_fVAlignOffset;
   1269   rtCaret.Offset(fOffSetX, fOffSetY);
   1270   const CFX_RectF& rtEidt = m_rtEngine;
   1271   if (rtEidt.Contains(rtCaret)) {
   1272     IFDE_TxtEdtPage* pPage = m_pEdtEngine->GetPage(0);
   1273     if (!pPage)
   1274       return FALSE;
   1275     CFX_RectF rtFDE = pPage->GetContentsBox();
   1276     rtFDE.Offset(fOffSetX, fOffSetY);
   1277     if (rtFDE.right() < rtEidt.right() && m_fScrollOffsetX > 0) {
   1278       m_fScrollOffsetX += rtFDE.right() - rtEidt.right();
   1279       if (m_fScrollOffsetX < 0) {
   1280         m_fScrollOffsetX = 0;
   1281       }
   1282     }
   1283     if (rtFDE.bottom() < rtEidt.bottom() && m_fScrollOffsetY > 0) {
   1284       m_fScrollOffsetY += rtFDE.bottom() - rtEidt.bottom();
   1285       if (m_fScrollOffsetY < 0) {
   1286         m_fScrollOffsetY = 0;
   1287       }
   1288     }
   1289     return FALSE;
   1290   } else {
   1291     FX_FLOAT offsetX = 0.0;
   1292     FX_FLOAT offsetY = 0.0;
   1293     if (rtCaret.left < rtEidt.left) {
   1294       offsetX = rtCaret.left - rtEidt.left;
   1295     }
   1296     if (rtCaret.right() > rtEidt.right()) {
   1297       offsetX = rtCaret.right() - rtEidt.right();
   1298     }
   1299     if (rtCaret.top < rtEidt.top) {
   1300       offsetY = rtCaret.top - rtEidt.top;
   1301     }
   1302     if (rtCaret.bottom() > rtEidt.bottom()) {
   1303       offsetY = rtCaret.bottom() - rtEidt.bottom();
   1304     }
   1305     if (!(m_pProperties->m_dwStyleExes & FWL_STYLEEXT_EDT_HSelfAdaption)) {
   1306       m_fScrollOffsetX += offsetX;
   1307     }
   1308     if (!(m_pProperties->m_dwStyleExes & FWL_STYLEEXT_EDT_VSelfAdaption)) {
   1309       m_fScrollOffsetY += offsetY;
   1310     }
   1311     if (m_fFontSize > m_rtEngine.height) {
   1312       m_fScrollOffsetY = 0;
   1313     }
   1314     return TRUE;
   1315   }
   1316 }
   1317 FX_BOOL CFWL_EditImp::UpdateOffset(IFWL_ScrollBar* pScrollBar,
   1318                                    FX_FLOAT fPosChanged) {
   1319   if (pScrollBar == m_pHorzScrollBar.get()) {
   1320     m_fScrollOffsetX += fPosChanged;
   1321   } else {
   1322     m_fScrollOffsetY += fPosChanged;
   1323   }
   1324   return TRUE;
   1325 }
   1326 void CFWL_EditImp::UpdateVAlignment() {
   1327   IFDE_TxtEdtPage* pPage = m_pEdtEngine->GetPage(0);
   1328   if (!pPage)
   1329     return;
   1330   const CFX_RectF& rtFDE = pPage->GetContentsBox();
   1331   FX_FLOAT fOffsetY = 0.0f;
   1332   FX_FLOAT fSpaceAbove = 0.0f;
   1333   FX_FLOAT fSpaceBelow = 0.0f;
   1334   CFX_SizeF* pSpace = static_cast<CFX_SizeF*>(
   1335       GetThemeCapacity(FWL_WGTCAPACITY_SpaceAboveBelow));
   1336   if (pSpace) {
   1337     fSpaceAbove = pSpace->x;
   1338     fSpaceBelow = pSpace->y;
   1339   }
   1340   if (fSpaceAbove < 0.1f) {
   1341     fSpaceAbove = 0;
   1342   }
   1343   if (fSpaceBelow < 0.1f) {
   1344     fSpaceBelow = 0;
   1345   }
   1346   if (m_pProperties->m_dwStyleExes & FWL_STYLEEXT_EDT_VCenter) {
   1347     fOffsetY = (m_rtEngine.height - rtFDE.height) / 2;
   1348     if (fOffsetY < (fSpaceAbove + fSpaceBelow) / 2 &&
   1349         fSpaceAbove < fSpaceBelow) {
   1350       return;
   1351     }
   1352     fOffsetY += (fSpaceAbove - fSpaceBelow) / 2;
   1353   } else if (m_pProperties->m_dwStyleExes & FWL_STYLEEXT_EDT_VFar) {
   1354     fOffsetY = (m_rtEngine.height - rtFDE.height);
   1355     fOffsetY -= fSpaceBelow;
   1356   } else {
   1357     fOffsetY += fSpaceAbove;
   1358   }
   1359   m_fVAlignOffset = fOffsetY;
   1360   if (m_fVAlignOffset < 0) {
   1361     m_fVAlignOffset = 0;
   1362   }
   1363 }
   1364 void CFWL_EditImp::UpdateCaret() {
   1365   CFX_RectF rtFDE;
   1366   m_pEdtEngine->GetCaretRect(rtFDE);
   1367   rtFDE.Offset(m_rtEngine.left - m_fScrollOffsetX,
   1368                m_rtEngine.top - m_fScrollOffsetY + m_fVAlignOffset);
   1369   CFX_RectF rtCaret;
   1370   rtCaret.Set(rtFDE.left, rtFDE.top, rtFDE.width, rtFDE.height);
   1371   CFX_RectF temp = rtCaret;
   1372   CFX_RectF rtClient;
   1373   GetClientRect(rtClient);
   1374   rtCaret.Intersect(rtClient);
   1375   if (rtCaret.left > rtClient.right()) {
   1376     FX_FLOAT right = rtCaret.right();
   1377     rtCaret.left = rtClient.right() - 1;
   1378     rtCaret.width = right - rtCaret.left;
   1379   }
   1380   FX_BOOL bIntersect = !rtCaret.IsEmpty();
   1381   FX_BOOL bShow = TRUE;
   1382   FX_BOOL bShowWhole = FALSE;
   1383   if (!(m_pProperties->m_dwStates & FWL_WGTSTATE_Focused) || !bIntersect) {
   1384     bShow = FALSE;
   1385   }
   1386   if (m_pProperties->m_dwStyleExes & FWL_STYLEEXT_EDT_HSelfAdaption &&
   1387       temp.right() > m_rtEngine.right()) {
   1388     bShowWhole = TRUE;
   1389   }
   1390   if (m_pProperties->m_dwStyleExes & FWL_STYLEEXT_EDT_VSelfAdaption &&
   1391       temp.bottom() > m_rtEngine.bottom()) {
   1392     bShowWhole = TRUE;
   1393   } else {
   1394     bShow = (m_pProperties->m_dwStates & FWL_WGTSTATE_Focused && bIntersect);
   1395   }
   1396   if (bShowWhole) {
   1397     rtCaret = temp;
   1398   }
   1399   ShowCaret(bShow, &rtCaret);
   1400 }
   1401 IFWL_ScrollBar* CFWL_EditImp::UpdateScroll() {
   1402   FX_BOOL bShowHorz =
   1403       m_pHorzScrollBar &&
   1404       ((m_pHorzScrollBar->GetStates() & FWL_WGTSTATE_Invisible) == 0);
   1405   FX_BOOL bShowVert =
   1406       m_pVertScrollBar &&
   1407       ((m_pVertScrollBar->GetStates() & FWL_WGTSTATE_Invisible) == 0);
   1408   if (!bShowHorz && !bShowVert) {
   1409     return NULL;
   1410   }
   1411   IFDE_TxtEdtPage* pPage = m_pEdtEngine->GetPage(0);
   1412   if (!pPage)
   1413     return NULL;
   1414   const CFX_RectF& rtFDE = pPage->GetContentsBox();
   1415   IFWL_ScrollBar* pRepaint = NULL;
   1416   if (bShowHorz) {
   1417     CFX_RectF rtScroll;
   1418     m_pHorzScrollBar->GetWidgetRect(rtScroll);
   1419     if (rtScroll.width < rtFDE.width) {
   1420       m_pHorzScrollBar->LockUpdate();
   1421       FX_FLOAT fRange = rtFDE.width - rtScroll.width;
   1422       m_pHorzScrollBar->SetRange(0.0f, fRange);
   1423       FX_FLOAT fPos = m_fScrollOffsetX;
   1424       if (fPos < 0.0f) {
   1425         fPos = 0.0f;
   1426       }
   1427       if (fPos > fRange) {
   1428         fPos = fRange;
   1429       }
   1430       m_pHorzScrollBar->SetPos(fPos);
   1431       m_pHorzScrollBar->SetTrackPos(fPos);
   1432       m_pHorzScrollBar->SetPageSize(rtScroll.width);
   1433       m_pHorzScrollBar->SetStepSize(rtScroll.width / 10);
   1434       m_pHorzScrollBar->SetStates(FWL_WGTSTATE_Disabled, FALSE);
   1435       m_pHorzScrollBar->UnlockUpdate();
   1436       m_pHorzScrollBar->Update();
   1437       pRepaint = m_pHorzScrollBar.get();
   1438     } else if ((m_pHorzScrollBar->GetStates() & FWL_WGTSTATE_Disabled) == 0) {
   1439       m_pHorzScrollBar->LockUpdate();
   1440       m_pHorzScrollBar->SetRange(0, -1);
   1441       m_pHorzScrollBar->SetStates(FWL_WGTSTATE_Disabled, TRUE);
   1442       m_pHorzScrollBar->UnlockUpdate();
   1443       m_pHorzScrollBar->Update();
   1444       pRepaint = m_pHorzScrollBar.get();
   1445     }
   1446   }
   1447   if (bShowVert) {
   1448     CFX_RectF rtScroll;
   1449     m_pVertScrollBar->GetWidgetRect(rtScroll);
   1450     if (rtScroll.height < rtFDE.height) {
   1451       m_pVertScrollBar->LockUpdate();
   1452       FX_FLOAT fStep = m_pEdtEngine->GetEditParams()->fLineSpace;
   1453       FX_FLOAT fRange = rtFDE.height - m_rtEngine.height;
   1454       if (fRange < fStep) {
   1455         fRange = fStep;
   1456       }
   1457       m_pVertScrollBar->SetRange(0.0f, fRange);
   1458       FX_FLOAT fPos = m_fScrollOffsetY;
   1459       if (fPos < 0.0f) {
   1460         fPos = 0.0f;
   1461       }
   1462       if (fPos > fRange) {
   1463         fPos = fRange;
   1464       }
   1465       m_pVertScrollBar->SetPos(fPos);
   1466       m_pVertScrollBar->SetTrackPos(fPos);
   1467       m_pVertScrollBar->SetPageSize(rtScroll.height);
   1468       m_pVertScrollBar->SetStepSize(fStep);
   1469       m_pVertScrollBar->SetStates(FWL_WGTSTATE_Disabled, FALSE);
   1470       m_pVertScrollBar->UnlockUpdate();
   1471       m_pVertScrollBar->Update();
   1472       pRepaint = m_pVertScrollBar.get();
   1473     } else if ((m_pVertScrollBar->GetStates() & FWL_WGTSTATE_Disabled) == 0) {
   1474       m_pVertScrollBar->LockUpdate();
   1475       m_pVertScrollBar->SetRange(0, -1);
   1476       m_pVertScrollBar->SetStates(FWL_WGTSTATE_Disabled, TRUE);
   1477       m_pVertScrollBar->UnlockUpdate();
   1478       m_pVertScrollBar->Update();
   1479       pRepaint = m_pVertScrollBar.get();
   1480     }
   1481   }
   1482   return pRepaint;
   1483 }
   1484 FX_BOOL CFWL_EditImp::IsShowScrollBar(FX_BOOL bVert) {
   1485   FX_BOOL bShow =
   1486       (m_pProperties->m_dwStyleExes & FWL_STYLEEXT_EDT_ShowScrollbarFocus)
   1487           ? (m_pProperties->m_dwStates & FWL_WGTSTATE_Focused) ==
   1488                 FWL_WGTSTATE_Focused
   1489           : TRUE;
   1490   if (bVert) {
   1491     return bShow && (m_pProperties->m_dwStyles & FWL_WGTSTYLE_VScroll) &&
   1492            (m_pProperties->m_dwStyleExes & FWL_STYLEEXT_EDT_MultiLine) &&
   1493            IsContentHeightOverflow();
   1494   }
   1495   return bShow && (m_pProperties->m_dwStyles & FWL_WGTSTYLE_HScroll) &&
   1496          (m_pProperties->m_dwStyleExes & FWL_STYLEEXT_EDT_MultiLine);
   1497 }
   1498 FX_BOOL CFWL_EditImp::IsContentHeightOverflow() {
   1499   if (!m_pEdtEngine)
   1500     return FALSE;
   1501   IFDE_TxtEdtPage* pPage = m_pEdtEngine->GetPage(0);
   1502   if (!pPage)
   1503     return FALSE;
   1504   return pPage->GetContentsBox().height > m_rtEngine.height + 1.0f;
   1505 }
   1506 int32_t CFWL_EditImp::AddDoRecord(const CFX_ByteStringC& bsDoRecord) {
   1507   int32_t nCount = m_RecordArr.GetSize();
   1508   if (m_iCurRecord == nCount - 1) {
   1509     if (nCount == m_iMaxRecord) {
   1510       m_RecordArr.RemoveAt(0);
   1511       m_iCurRecord--;
   1512     }
   1513   } else {
   1514     for (int32_t i = nCount - 1; i > m_iCurRecord; i--) {
   1515       m_RecordArr.RemoveAt(i);
   1516     }
   1517   }
   1518   m_RecordArr.Add(bsDoRecord);
   1519   return m_iCurRecord = m_RecordArr.GetSize() - 1;
   1520 }
   1521 void CFWL_EditImp::Layout() {
   1522   GetClientRect(m_rtClient);
   1523   m_rtEngine = m_rtClient;
   1524   FX_FLOAT* pfWidth =
   1525       static_cast<FX_FLOAT*>(GetThemeCapacity(FWL_WGTCAPACITY_ScrollBarWidth));
   1526   if (!pfWidth)
   1527     return;
   1528   FX_FLOAT fWidth = *pfWidth;
   1529   if (!m_pOuter) {
   1530     CFX_RectF* pUIMargin =
   1531         static_cast<CFX_RectF*>(GetThemeCapacity(FWL_WGTCAPACITY_UIMargin));
   1532     if (pUIMargin) {
   1533       m_rtEngine.Deflate(pUIMargin->left, pUIMargin->top, pUIMargin->width,
   1534                          pUIMargin->height);
   1535     }
   1536   } else if (m_pOuter->GetClassID() == FWL_CLASSHASH_DateTimePicker) {
   1537     CFWL_ThemePart part;
   1538     part.m_pWidget = m_pOuter;
   1539     CFX_RectF* pUIMargin =
   1540         static_cast<CFX_RectF*>(m_pOuter->GetThemeProvider()->GetCapacity(
   1541             &part, FWL_WGTCAPACITY_UIMargin));
   1542     if (pUIMargin) {
   1543       m_rtEngine.Deflate(pUIMargin->left, pUIMargin->top, pUIMargin->width,
   1544                          pUIMargin->height);
   1545     }
   1546   }
   1547   FX_BOOL bShowVertScrollbar = IsShowScrollBar(TRUE);
   1548   FX_BOOL bShowHorzScrollbar = IsShowScrollBar(FALSE);
   1549   if (bShowVertScrollbar) {
   1550     InitScrollBar();
   1551     CFX_RectF rtVertScr;
   1552     if (m_pProperties->m_dwStyleExes & FWL_STYLEEXT_EDT_OuterScrollbar) {
   1553       rtVertScr.Set(m_rtClient.right() + FWL_EDIT_Margin, m_rtClient.top,
   1554                     fWidth, m_rtClient.height);
   1555     } else {
   1556       rtVertScr.Set(m_rtClient.right() - fWidth, m_rtClient.top, fWidth,
   1557                     m_rtClient.height);
   1558       if (bShowHorzScrollbar) {
   1559         rtVertScr.height -= fWidth;
   1560       }
   1561       m_rtEngine.width -= fWidth;
   1562     }
   1563     m_pVertScrollBar->SetWidgetRect(rtVertScr);
   1564     m_pVertScrollBar->SetStates(FWL_WGTSTATE_Invisible, FALSE);
   1565     m_pVertScrollBar->Update();
   1566   } else if (m_pVertScrollBar) {
   1567     m_pVertScrollBar->SetStates(FWL_WGTSTATE_Invisible, TRUE);
   1568   }
   1569   if (bShowHorzScrollbar) {
   1570     InitScrollBar(FALSE);
   1571     CFX_RectF rtHoriScr;
   1572     if (m_pProperties->m_dwStyleExes & FWL_STYLEEXT_EDT_OuterScrollbar) {
   1573       rtHoriScr.Set(m_rtClient.left, m_rtClient.bottom() + FWL_EDIT_Margin,
   1574                     m_rtClient.width, fWidth);
   1575     } else {
   1576       rtHoriScr.Set(m_rtClient.left, m_rtClient.bottom() - fWidth,
   1577                     m_rtClient.width, fWidth);
   1578       if (bShowVertScrollbar) {
   1579         rtHoriScr.width -= fWidth;
   1580       }
   1581       m_rtEngine.height -= fWidth;
   1582     }
   1583     m_pHorzScrollBar->SetWidgetRect(rtHoriScr);
   1584     m_pHorzScrollBar->SetStates(FWL_WGTSTATE_Invisible, FALSE);
   1585     m_pHorzScrollBar->Update();
   1586   } else if (m_pHorzScrollBar) {
   1587     m_pHorzScrollBar->SetStates(FWL_WGTSTATE_Invisible, TRUE);
   1588   }
   1589 }
   1590 void CFWL_EditImp::LayoutScrollBar() {
   1591   if ((m_pProperties->m_dwStyleExes & FWL_STYLEEXT_EDT_ShowScrollbarFocus) ==
   1592       0) {
   1593     return;
   1594   }
   1595   FX_FLOAT* pfWidth = NULL;
   1596   FX_BOOL bShowVertScrollbar = IsShowScrollBar(TRUE);
   1597   FX_BOOL bShowHorzScrollbar = IsShowScrollBar(FALSE);
   1598   if (bShowVertScrollbar) {
   1599     if (!m_pVertScrollBar) {
   1600       pfWidth = static_cast<FX_FLOAT*>(
   1601           GetThemeCapacity(FWL_WGTCAPACITY_ScrollBarWidth));
   1602       FX_FLOAT fWidth = pfWidth ? *pfWidth : 0;
   1603       InitScrollBar();
   1604       CFX_RectF rtVertScr;
   1605       if (m_pProperties->m_dwStyleExes & FWL_STYLEEXT_EDT_OuterScrollbar) {
   1606         rtVertScr.Set(m_rtClient.right() + FWL_EDIT_Margin, m_rtClient.top,
   1607                       fWidth, m_rtClient.height);
   1608       } else {
   1609         rtVertScr.Set(m_rtClient.right() - fWidth, m_rtClient.top, fWidth,
   1610                       m_rtClient.height);
   1611         if (bShowHorzScrollbar) {
   1612           rtVertScr.height -= fWidth;
   1613         }
   1614       }
   1615       m_pVertScrollBar->SetWidgetRect(rtVertScr);
   1616       m_pVertScrollBar->Update();
   1617     }
   1618     m_pVertScrollBar->SetStates(FWL_WGTSTATE_Invisible, FALSE);
   1619   } else if (m_pVertScrollBar) {
   1620     m_pVertScrollBar->SetStates(FWL_WGTSTATE_Invisible, TRUE);
   1621   }
   1622   if (bShowHorzScrollbar) {
   1623     if (!m_pHorzScrollBar) {
   1624       if (!pfWidth) {
   1625         pfWidth = static_cast<FX_FLOAT*>(
   1626             GetThemeCapacity(FWL_WGTCAPACITY_ScrollBarWidth));
   1627       }
   1628       FX_FLOAT fWidth = pfWidth ? *pfWidth : 0;
   1629       InitScrollBar(FALSE);
   1630       CFX_RectF rtHoriScr;
   1631       if (m_pProperties->m_dwStyleExes & FWL_STYLEEXT_EDT_OuterScrollbar) {
   1632         rtHoriScr.Set(m_rtClient.left, m_rtClient.bottom() + FWL_EDIT_Margin,
   1633                       m_rtClient.width, fWidth);
   1634       } else {
   1635         rtHoriScr.Set(m_rtClient.left, m_rtClient.bottom() - fWidth,
   1636                       m_rtClient.width, fWidth);
   1637         if (bShowVertScrollbar) {
   1638           rtHoriScr.width -= (fWidth);
   1639         }
   1640       }
   1641       m_pHorzScrollBar->SetWidgetRect(rtHoriScr);
   1642       m_pHorzScrollBar->Update();
   1643     }
   1644     m_pHorzScrollBar->SetStates(FWL_WGTSTATE_Invisible, FALSE);
   1645   } else if (m_pHorzScrollBar) {
   1646     m_pHorzScrollBar->SetStates(FWL_WGTSTATE_Invisible, TRUE);
   1647   }
   1648   if (bShowVertScrollbar || bShowHorzScrollbar) {
   1649     UpdateScroll();
   1650   }
   1651 }
   1652 void CFWL_EditImp::DeviceToEngine(CFX_PointF& pt) {
   1653   pt.x += -m_rtEngine.left + m_fScrollOffsetX;
   1654   pt.y += -m_rtEngine.top - m_fVAlignOffset + m_fScrollOffsetY;
   1655 }
   1656 void CFWL_EditImp::InitScrollBar(FX_BOOL bVert) {
   1657   if ((bVert && m_pVertScrollBar) || (!bVert && m_pHorzScrollBar)) {
   1658     return;
   1659   }
   1660   CFWL_WidgetImpProperties prop;
   1661   prop.m_dwStyleExes = bVert ? FWL_STYLEEXT_SCB_Vert : FWL_STYLEEXT_SCB_Horz;
   1662   prop.m_dwStates = FWL_WGTSTATE_Disabled | FWL_WGTSTATE_Invisible;
   1663   prop.m_pParent = m_pInterface;
   1664   prop.m_pThemeProvider = m_pProperties->m_pThemeProvider;
   1665   IFWL_ScrollBar* pScrollBar = IFWL_ScrollBar::Create(prop, m_pInterface);
   1666   pScrollBar->Initialize();
   1667   (bVert ? &m_pVertScrollBar : &m_pHorzScrollBar)->reset(pScrollBar);
   1668 }
   1669 void CFWL_EditImp::InitEngine() {
   1670   if (m_pEdtEngine) {
   1671     return;
   1672   }
   1673   m_pEdtEngine = IFDE_TxtEdtEngine::Create();
   1674 }
   1675 extern FX_BOOL FWL_ShowCaret(IFWL_Widget* pWidget,
   1676                              FX_BOOL bVisible,
   1677                              const CFX_RectF* pRtAnchor);
   1678 void CFWL_EditImp::ShowCaret(FX_BOOL bVisible, CFX_RectF* pRect) {
   1679   if (m_pCaret) {
   1680     m_pCaret->ShowCaret(bVisible);
   1681     if (bVisible && !pRect->IsEmpty()) {
   1682       m_pCaret->SetWidgetRect(*pRect);
   1683     }
   1684     Repaint(&m_rtEngine);
   1685   } else {
   1686     IFWL_Widget* pOuter = m_pInterface;
   1687     if (bVisible) {
   1688       pRect->Offset(m_pProperties->m_rtWidget.left,
   1689                     m_pProperties->m_rtWidget.top);
   1690     }
   1691     while (pOuter->GetOuter()) {
   1692       pOuter = pOuter->GetOuter();
   1693       if (bVisible) {
   1694         CFX_RectF rtOuter;
   1695         pOuter->GetWidgetRect(rtOuter);
   1696         pRect->Offset(rtOuter.left, rtOuter.top);
   1697       }
   1698     }
   1699     FWL_ShowCaret(pOuter, bVisible, pRect);
   1700   }
   1701 }
   1702 FX_BOOL CFWL_EditImp::ValidateNumberChar(FX_WCHAR cNum) {
   1703   if (!m_pEdtEngine) {
   1704     return FALSE;
   1705   }
   1706   if (!m_bSetRange) {
   1707     return TRUE;
   1708   }
   1709   CFX_WideString wsOld, wsText;
   1710   m_pEdtEngine->GetText(wsText, 0);
   1711   if (wsText.IsEmpty()) {
   1712     if (cNum == L'0') {
   1713       return FALSE;
   1714     }
   1715     return TRUE;
   1716   }
   1717   int32_t caretPos = m_pEdtEngine->GetCaretPos();
   1718   int32_t iSel = CountSelRanges();
   1719   if (iSel == 0) {
   1720     if (cNum == L'0' && caretPos == 0) {
   1721       return FALSE;
   1722     }
   1723     int32_t nLen = wsText.GetLength();
   1724     CFX_WideString l = wsText.Mid(0, caretPos);
   1725     CFX_WideString r = wsText.Mid(caretPos, nLen - caretPos);
   1726     CFX_WideString wsNew = l + cNum + r;
   1727     if (wsNew.GetInteger() <= m_iMax) {
   1728       return TRUE;
   1729     }
   1730   } else {
   1731     if (wsText.GetInteger() <= m_iMax) {
   1732       return TRUE;
   1733     }
   1734   }
   1735   return FALSE;
   1736 }
   1737 void CFWL_EditImp::InitCaret() {
   1738   if (!m_pCaret) {
   1739     if ((m_pProperties->m_dwStyleExes & FWL_STYLEEXT_EDT_InnerCaret)) {
   1740       CFWL_WidgetImpProperties prop;
   1741       m_pCaret.reset(IFWL_Caret::Create(prop, m_pInterface));
   1742       m_pCaret->Initialize();
   1743       m_pCaret->SetParent(m_pInterface);
   1744       m_pCaret->SetStates(m_pProperties->m_dwStates);
   1745     }
   1746   } else if ((m_pProperties->m_dwStyleExes & FWL_STYLEEXT_EDT_InnerCaret) ==
   1747              0) {
   1748     m_pCaret.reset();
   1749   }
   1750 }
   1751 void CFWL_EditImp::ClearRecord() {
   1752   m_iCurRecord = -1;
   1753   m_RecordArr.RemoveAll();
   1754 }
   1755 void CFWL_EditImp::ProcessInsertError(int32_t iError) {
   1756   switch (iError) {
   1757     case -2: {
   1758       CFWL_EvtEdtTextFull textFullEvent;
   1759       textFullEvent.m_pSrcTarget = m_pInterface;
   1760       DispatchEvent(&textFullEvent);
   1761       break;
   1762     }
   1763     default: {}
   1764   }
   1765 }
   1766 CFWL_EditImpDelegate::CFWL_EditImpDelegate(CFWL_EditImp* pOwner)
   1767     : m_pOwner(pOwner) {}
   1768 int32_t CFWL_EditImpDelegate::OnProcessMessage(CFWL_Message* pMessage) {
   1769   if (!pMessage)
   1770     return 0;
   1771   FX_DWORD dwMsgCode = pMessage->GetClassID();
   1772   int32_t iRet = 1;
   1773   switch (dwMsgCode) {
   1774     case FWL_MSGHASH_Activate: {
   1775       DoActivate(static_cast<CFWL_MsgActivate*>(pMessage));
   1776       break;
   1777     }
   1778     case FWL_MSGHASH_Deactivate: {
   1779       DoDeactivate(static_cast<CFWL_MsgDeactivate*>(pMessage));
   1780       break;
   1781     }
   1782     case FWL_MSGHASH_SetFocus:
   1783     case FWL_MSGHASH_KillFocus: {
   1784       OnFocusChanged(pMessage, dwMsgCode == FWL_MSGHASH_SetFocus);
   1785       break;
   1786     }
   1787     case FWL_MSGHASH_Mouse: {
   1788       CFWL_MsgMouse* pMsg = static_cast<CFWL_MsgMouse*>(pMessage);
   1789       FX_DWORD dwCmd = pMsg->m_dwCmd;
   1790       switch (dwCmd) {
   1791         case FWL_MSGMOUSECMD_LButtonDown: {
   1792           OnLButtonDown(pMsg);
   1793           break;
   1794         }
   1795         case FWL_MSGMOUSECMD_LButtonUp: {
   1796           OnLButtonUp(pMsg);
   1797           break;
   1798         }
   1799         case FWL_MSGMOUSECMD_LButtonDblClk: {
   1800           OnButtonDblClk(pMsg);
   1801           break;
   1802         }
   1803         case FWL_MSGMOUSECMD_MouseMove: {
   1804           OnMouseMove(pMsg);
   1805           break;
   1806         }
   1807         case FWL_MSGMOUSECMD_RButtonDown: {
   1808           DoButtonDown(pMsg);
   1809           break;
   1810         }
   1811         default: {}
   1812       }
   1813       break;
   1814     }
   1815     case FWL_MSGHASH_Key: {
   1816       CFWL_MsgKey* pKey = static_cast<CFWL_MsgKey*>(pMessage);
   1817       FX_DWORD dwCmd = pKey->m_dwCmd;
   1818       if (dwCmd == FWL_MSGKEYCMD_KeyDown) {
   1819         OnKeyDown(pKey);
   1820       } else if (dwCmd == FWL_MSGKEYCMD_Char) {
   1821         OnChar(pKey);
   1822       }
   1823       break;
   1824     }
   1825     default: { iRet = 0; }
   1826   }
   1827   CFWL_WidgetImpDelegate::OnProcessMessage(pMessage);
   1828   return iRet;
   1829 }
   1830 FWL_ERR CFWL_EditImpDelegate::OnProcessEvent(CFWL_Event* pEvent) {
   1831   if (!pEvent)
   1832     return FWL_ERR_Indefinite;
   1833   FX_DWORD dwHashCode = pEvent->GetClassID();
   1834   if (dwHashCode != FWL_EVTHASH_Scroll) {
   1835     return FWL_ERR_Succeeded;
   1836   }
   1837   IFWL_Widget* pSrcTarget = pEvent->m_pSrcTarget;
   1838   if ((pSrcTarget == m_pOwner->m_pVertScrollBar.get() &&
   1839        m_pOwner->m_pVertScrollBar) ||
   1840       (pSrcTarget == m_pOwner->m_pHorzScrollBar.get() &&
   1841        m_pOwner->m_pHorzScrollBar)) {
   1842     CFWL_EvtScroll* pScrollEvent = static_cast<CFWL_EvtScroll*>(pEvent);
   1843     OnScroll(static_cast<IFWL_ScrollBar*>(pSrcTarget),
   1844              pScrollEvent->m_iScrollCode, pScrollEvent->m_fPos);
   1845   }
   1846   return FWL_ERR_Succeeded;
   1847 }
   1848 FWL_ERR CFWL_EditImpDelegate::OnDrawWidget(CFX_Graphics* pGraphics,
   1849                                            const CFX_Matrix* pMatrix) {
   1850   return m_pOwner->DrawWidget(pGraphics, pMatrix);
   1851 }
   1852 void CFWL_EditImpDelegate::DoActivate(CFWL_MsgActivate* pMsg) {
   1853   m_pOwner->m_pProperties->m_dwStates |= ~FWL_WGTSTATE_Deactivated;
   1854   m_pOwner->Repaint(&m_pOwner->m_rtClient);
   1855 }
   1856 void CFWL_EditImpDelegate::DoDeactivate(CFWL_MsgDeactivate* pMsg) {
   1857   m_pOwner->m_pProperties->m_dwStates &= FWL_WGTSTATE_Deactivated;
   1858   m_pOwner->Repaint(&m_pOwner->m_rtClient);
   1859 }
   1860 void CFWL_EditImpDelegate::DoButtonDown(CFWL_MsgMouse* pMsg) {
   1861   if ((m_pOwner->m_pProperties->m_dwStates & FWL_WGTSTATE_Focused) == 0) {
   1862     m_pOwner->SetFocus(TRUE);
   1863   }
   1864   if (!m_pOwner->m_pEdtEngine) {
   1865     m_pOwner->UpdateEditEngine();
   1866   }
   1867   IFDE_TxtEdtPage* pPage = m_pOwner->m_pEdtEngine->GetPage(0);
   1868   if (!pPage)
   1869     return;
   1870   CFX_PointF pt;
   1871   pt.Set(pMsg->m_fx, pMsg->m_fy);
   1872   m_pOwner->DeviceToEngine(pt);
   1873   FX_BOOL bBefore = TRUE;
   1874   int32_t nIndex = pPage->GetCharIndex(pt, bBefore);
   1875   if (nIndex < 0) {
   1876     nIndex = 0;
   1877   }
   1878   m_pOwner->m_pEdtEngine->SetCaretPos(nIndex, bBefore);
   1879 }
   1880 void CFWL_EditImpDelegate::OnFocusChanged(CFWL_Message* pMsg, FX_BOOL bSet) {
   1881   FX_DWORD dwStyleEx = m_pOwner->GetStylesEx();
   1882   FX_BOOL bRepaint = dwStyleEx & FWL_STYLEEXT_EDT_InnerCaret;
   1883   if (bSet) {
   1884     m_pOwner->m_pProperties->m_dwStates |= FWL_WGTSTATE_Focused;
   1885     if (!m_pOwner->m_pEdtEngine) {
   1886       m_pOwner->UpdateEditEngine();
   1887     }
   1888     m_pOwner->UpdateVAlignment();
   1889     m_pOwner->UpdateOffset();
   1890     m_pOwner->UpdateCaret();
   1891   } else if (m_pOwner->m_pProperties->m_dwStates & FWL_WGTSTATE_Focused) {
   1892     m_pOwner->m_pProperties->m_dwStates &= ~FWL_WGTSTATE_Focused;
   1893     m_pOwner->ShowCaret(FALSE);
   1894     if (m_pOwner->m_pEdtEngine &&
   1895         (dwStyleEx & FWL_STYLEEXT_EDT_NoHideSel) == 0) {
   1896       int32_t nSel = m_pOwner->CountSelRanges();
   1897       if (nSel > 0) {
   1898         m_pOwner->ClearSelections();
   1899         bRepaint = TRUE;
   1900       }
   1901       m_pOwner->SetCaretPos(0);
   1902       m_pOwner->UpdateOffset();
   1903     }
   1904     m_pOwner->ClearRecord();
   1905   }
   1906   m_pOwner->LayoutScrollBar();
   1907   if (bRepaint) {
   1908     CFX_RectF rtInvalidate;
   1909     rtInvalidate.Set(0, 0, m_pOwner->m_pProperties->m_rtWidget.width,
   1910                      m_pOwner->m_pProperties->m_rtWidget.height);
   1911     m_pOwner->Repaint(&rtInvalidate);
   1912   }
   1913 }
   1914 void CFWL_EditImpDelegate::OnLButtonDown(CFWL_MsgMouse* pMsg) {
   1915   DoCursor(pMsg);
   1916   if (m_pOwner->m_pProperties->m_dwStates & FWL_WGTSTATE_Disabled) {
   1917     return;
   1918   }
   1919   m_pOwner->m_bLButtonDown = TRUE;
   1920   m_pOwner->SetGrab(TRUE);
   1921   DoButtonDown(pMsg);
   1922   int32_t nIndex = m_pOwner->m_pEdtEngine->GetCaretPos();
   1923   FX_BOOL bRepaint = FALSE;
   1924   int32_t iCount = m_pOwner->m_pEdtEngine->CountSelRanges();
   1925   if (iCount > 0) {
   1926     m_pOwner->m_pEdtEngine->ClearSelection();
   1927     bRepaint = TRUE;
   1928   }
   1929   FX_BOOL bShift = pMsg->m_dwFlags & FWL_KEYFLAG_Shift;
   1930   if (bShift && m_pOwner->m_nSelStart != nIndex) {
   1931     int32_t iStart = std::min(m_pOwner->m_nSelStart, nIndex);
   1932     int32_t iEnd = std::max(m_pOwner->m_nSelStart, nIndex);
   1933     m_pOwner->m_pEdtEngine->AddSelRange(iStart, iEnd - iStart);
   1934     bRepaint = TRUE;
   1935   } else {
   1936     m_pOwner->m_nSelStart = nIndex;
   1937   }
   1938   if (bRepaint) {
   1939     m_pOwner->Repaint(&m_pOwner->m_rtEngine);
   1940   }
   1941 }
   1942 void CFWL_EditImpDelegate::OnLButtonUp(CFWL_MsgMouse* pMsg) {
   1943   DoCursor(pMsg);
   1944   m_pOwner->m_bLButtonDown = FALSE;
   1945   m_pOwner->SetGrab(FALSE);
   1946 }
   1947 void CFWL_EditImpDelegate::OnButtonDblClk(CFWL_MsgMouse* pMsg) {
   1948   if (!m_pOwner->m_pEdtEngine)
   1949     return;
   1950   DoCursor(pMsg);
   1951   IFDE_TxtEdtPage* pPage = m_pOwner->m_pEdtEngine->GetPage(0);
   1952   if (!pPage)
   1953     return;
   1954   CFX_PointF pt;
   1955   pt.Set(pMsg->m_fx, pMsg->m_fy);
   1956   m_pOwner->DeviceToEngine(pt);
   1957   int32_t nCount = 0;
   1958   int32_t nIndex = pPage->SelectWord(pt, nCount);
   1959   if (nIndex < 0) {
   1960     return;
   1961   }
   1962   m_pOwner->m_pEdtEngine->AddSelRange(nIndex, nCount);
   1963   m_pOwner->m_pEdtEngine->SetCaretPos(nIndex + nCount - 1, FALSE);
   1964   m_pOwner->Repaint(&m_pOwner->m_rtEngine);
   1965 }
   1966 void CFWL_EditImpDelegate::OnMouseMove(CFWL_MsgMouse* pMsg) {
   1967   if (!m_pOwner->m_pEdtEngine)
   1968     return;
   1969   DoCursor(pMsg);
   1970   if (m_pOwner->m_nSelStart == -1 || !m_pOwner->m_bLButtonDown) {
   1971     return;
   1972   }
   1973   IFDE_TxtEdtPage* pPage = m_pOwner->m_pEdtEngine->GetPage(0);
   1974   if (!pPage)
   1975     return;
   1976   CFX_PointF pt;
   1977   pt.Set(pMsg->m_fx, pMsg->m_fy);
   1978   m_pOwner->DeviceToEngine(pt);
   1979   FX_BOOL bBefore = TRUE;
   1980   int32_t nIndex = pPage->GetCharIndex(pt, bBefore);
   1981   m_pOwner->m_pEdtEngine->SetCaretPos(nIndex, bBefore);
   1982   nIndex = m_pOwner->m_pEdtEngine->GetCaretPos();
   1983   m_pOwner->m_pEdtEngine->ClearSelection();
   1984   if (nIndex != m_pOwner->m_nSelStart) {
   1985     int32_t nLen = m_pOwner->m_pEdtEngine->GetTextLength();
   1986     if (m_pOwner->m_nSelStart >= nLen) {
   1987       m_pOwner->m_nSelStart = nLen;
   1988     }
   1989     m_pOwner->m_pEdtEngine->AddSelRange(
   1990         std::min(m_pOwner->m_nSelStart, nIndex),
   1991         FXSYS_abs(nIndex - m_pOwner->m_nSelStart));
   1992   }
   1993 }
   1994 void CFWL_EditImpDelegate::OnKeyDown(CFWL_MsgKey* pMsg) {
   1995   if (!m_pOwner->m_pEdtEngine)
   1996     return;
   1997   FDE_TXTEDTMOVECARET MoveCaret = MC_MoveNone;
   1998   FX_BOOL bShift = pMsg->m_dwFlags & FWL_KEYFLAG_Shift;
   1999   FX_BOOL bCtrl = pMsg->m_dwFlags & FWL_KEYFLAG_Ctrl;
   2000   FX_DWORD dwKeyCode = pMsg->m_dwKeyCode;
   2001   switch (dwKeyCode) {
   2002     case FWL_VKEY_Left: {
   2003       MoveCaret = MC_Left;
   2004       break;
   2005     }
   2006     case FWL_VKEY_Right: {
   2007       MoveCaret = MC_Right;
   2008       break;
   2009     }
   2010     case FWL_VKEY_Up: {
   2011       MoveCaret = MC_Up;
   2012       break;
   2013     }
   2014     case FWL_VKEY_Down: {
   2015       MoveCaret = MC_Down;
   2016       break;
   2017     }
   2018     case FWL_VKEY_Home: {
   2019       if (bCtrl) {
   2020         MoveCaret = MC_Home;
   2021       } else {
   2022         MoveCaret = MC_LineStart;
   2023       }
   2024       break;
   2025     }
   2026     case FWL_VKEY_End: {
   2027       if (bCtrl) {
   2028         MoveCaret = MC_End;
   2029       } else {
   2030         MoveCaret = MC_LineEnd;
   2031       }
   2032       break;
   2033     }
   2034     case FWL_VKEY_Insert: {
   2035       break;
   2036     }
   2037     case FWL_VKEY_Delete: {
   2038       if ((m_pOwner->m_pProperties->m_dwStyleExes &
   2039            FWL_STYLEEXT_EDT_ReadOnly) ||
   2040           (m_pOwner->m_pProperties->m_dwStates & FWL_WGTSTATE_Disabled)) {
   2041         break;
   2042       }
   2043       int32_t nCaret = m_pOwner->m_pEdtEngine->GetCaretPos();
   2044 #if (_FX_OS_ == _FX_MACOSX_)
   2045       m_pOwner->m_pEdtEngine->Delete(nCaret, TRUE);
   2046 #else
   2047       m_pOwner->m_pEdtEngine->Delete(nCaret);
   2048 #endif
   2049       break;
   2050     }
   2051     case FWL_VKEY_F2: {
   2052       break;
   2053     }
   2054     case FWL_VKEY_Tab: {
   2055       m_pOwner->DispatchKeyEvent(pMsg);
   2056       break;
   2057     }
   2058     default: {
   2059 #if (_FX_OS_ == _FX_MACOSX_)
   2060       if (pMsg->m_dwFlags & FWL_KEYFLAG_Command)
   2061 #else
   2062       if (pMsg->m_dwFlags & FWL_KEYFLAG_Ctrl)
   2063 #endif
   2064       {
   2065         if (dwKeyCode == 0x43 || dwKeyCode == 0x63) {
   2066           m_pOwner->DoClipboard(1);
   2067           return;
   2068         }
   2069         if (dwKeyCode == 0x58 || dwKeyCode == 0x78) {
   2070           m_pOwner->DoClipboard(2);
   2071           return;
   2072         }
   2073         if (dwKeyCode == 0x56 || dwKeyCode == 0x76) {
   2074           m_pOwner->DoClipboard(3);
   2075           return;
   2076         }
   2077       }
   2078     }
   2079   }
   2080   if (MoveCaret != MC_MoveNone) {
   2081     m_pOwner->m_pEdtEngine->MoveCaretPos(MoveCaret, bShift, bCtrl);
   2082   }
   2083 }
   2084 void CFWL_EditImpDelegate::OnChar(CFWL_MsgKey* pMsg) {
   2085   if ((m_pOwner->m_pProperties->m_dwStyleExes & FWL_STYLEEXT_EDT_ReadOnly) ||
   2086       (m_pOwner->m_pProperties->m_dwStates & FWL_WGTSTATE_Disabled)) {
   2087     return;
   2088   }
   2089   if (!m_pOwner->m_pEdtEngine)
   2090     return;
   2091   int32_t iError = 0;
   2092   FX_WCHAR c = (FX_WCHAR)pMsg->m_dwKeyCode;
   2093   int32_t nCaret = m_pOwner->m_pEdtEngine->GetCaretPos();
   2094   switch (c) {
   2095     case FWL_VKEY_Back: {
   2096       m_pOwner->m_pEdtEngine->Delete(nCaret, TRUE);
   2097       break;
   2098     }
   2099     case 0x0A: {
   2100       break;
   2101     }
   2102     case FWL_VKEY_Escape: {
   2103       break;
   2104     }
   2105     case FWL_VKEY_Tab: {
   2106       iError = m_pOwner->m_pEdtEngine->Insert(nCaret, L"\t", 1);
   2107       break;
   2108     }
   2109     case FWL_VKEY_Return: {
   2110       if (m_pOwner->m_pProperties->m_dwStyleExes &
   2111           FWL_STYLEEXT_EDT_WantReturn) {
   2112         iError = m_pOwner->m_pEdtEngine->Insert(nCaret, L"\n", 1);
   2113       }
   2114       break;
   2115     }
   2116     default: {
   2117       if (!m_pOwner->m_pWidgetMgr->IsFormDisabled()) {
   2118         if (m_pOwner->m_pProperties->m_dwStyleExes & FWL_STYLEEXT_EDT_Number) {
   2119           if (((pMsg->m_dwKeyCode < FWL_VKEY_0) &&
   2120                (pMsg->m_dwKeyCode != 0x2E && pMsg->m_dwKeyCode != 0x2D)) ||
   2121               pMsg->m_dwKeyCode > FWL_VKEY_9) {
   2122             break;
   2123           }
   2124           if (!m_pOwner->ValidateNumberChar(c)) {
   2125             break;
   2126           }
   2127         }
   2128       }
   2129 #if (_FX_OS_ == _FX_MACOSX_)
   2130       if (pMsg->m_dwFlags & FWL_KEYFLAG_Command)
   2131 #else
   2132       if (pMsg->m_dwFlags & FWL_KEYFLAG_Ctrl)
   2133 #endif
   2134       {
   2135         break;
   2136       }
   2137       iError = m_pOwner->m_pEdtEngine->Insert(nCaret, &c, 1);
   2138       break;
   2139     }
   2140   }
   2141   if (iError < 0) {
   2142     m_pOwner->ProcessInsertError(iError);
   2143   }
   2144 }
   2145 FX_BOOL CFWL_EditImpDelegate::OnScroll(IFWL_ScrollBar* pScrollBar,
   2146                                        FX_DWORD dwCode,
   2147                                        FX_FLOAT fPos) {
   2148   CFX_SizeF fs;
   2149   pScrollBar->GetRange(fs.x, fs.y);
   2150   FX_FLOAT iCurPos = pScrollBar->GetPos();
   2151   FX_FLOAT fStep = pScrollBar->GetStepSize();
   2152   switch (dwCode) {
   2153     case FWL_SCBCODE_Min: {
   2154       fPos = fs.x;
   2155       break;
   2156     }
   2157     case FWL_SCBCODE_Max: {
   2158       fPos = fs.y;
   2159       break;
   2160     }
   2161     case FWL_SCBCODE_StepBackward: {
   2162       fPos -= fStep;
   2163       if (fPos < fs.x + fStep / 2) {
   2164         fPos = fs.x;
   2165       }
   2166       break;
   2167     }
   2168     case FWL_SCBCODE_StepForward: {
   2169       fPos += fStep;
   2170       if (fPos > fs.y - fStep / 2) {
   2171         fPos = fs.y;
   2172       }
   2173       break;
   2174     }
   2175     case FWL_SCBCODE_PageBackward: {
   2176       fPos -= pScrollBar->GetPageSize();
   2177       if (fPos < fs.x) {
   2178         fPos = fs.x;
   2179       }
   2180       break;
   2181     }
   2182     case FWL_SCBCODE_PageForward: {
   2183       fPos += pScrollBar->GetPageSize();
   2184       if (fPos > fs.y) {
   2185         fPos = fs.y;
   2186       }
   2187       break;
   2188     }
   2189     case FWL_SCBCODE_Pos:
   2190     case FWL_SCBCODE_TrackPos: {
   2191       break;
   2192     }
   2193     case FWL_SCBCODE_EndScroll: {
   2194       return FALSE;
   2195     }
   2196     default: {}
   2197   }
   2198   if (iCurPos != fPos) {
   2199     pScrollBar->SetPos(fPos);
   2200     pScrollBar->SetTrackPos(fPos);
   2201     m_pOwner->UpdateOffset(pScrollBar, fPos - iCurPos);
   2202     if (m_pOwner->m_pEdtEngine) {
   2203       m_pOwner->UpdateCaret();
   2204     }
   2205     CFX_RectF rect;
   2206     m_pOwner->GetWidgetRect(rect);
   2207     CFX_RectF rtInvalidate;
   2208     rtInvalidate.Set(0, 0, rect.width + 2, rect.height + 2);
   2209     m_pOwner->Repaint(&rtInvalidate);
   2210   }
   2211   return TRUE;
   2212 }
   2213 void CFWL_EditImpDelegate::DoCursor(CFWL_MsgMouse* pMsg) {
   2214   if (m_pOwner->m_rtClient.Contains(pMsg->m_fx, pMsg->m_fy)) {
   2215     IFWL_AdapterNative* pNative = FWL_GetAdapterNative();
   2216     IFWL_AdapterCursorMgr* pCursorMgr = pNative->GetCursorMgr();
   2217     if (NULL != pCursorMgr) {
   2218       FWL_HCURSOR hCursor =
   2219           pCursorMgr->GetSystemCursor(FWL_CURSORTYPE_InputBeam);
   2220       pCursorMgr->SetCursor(hCursor);
   2221       pCursorMgr->ShowCursor(TRUE);
   2222     }
   2223   }
   2224 }
   2225