Home | History | Annotate | Download | only in fee
      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/fee/include/ifde_txtedtengine.h"
     11 #include "xfa/src/fee/include/ifde_txtedtbuf.h"
     12 #include "xfa/src/fee/include/ifde_txtedtpage.h"
     13 #include "fde_txtedtengine.h"
     14 #include "fde_txtedtparag.h"
     15 #include "fde_txtedtbuf.h"
     16 #ifdef FDE_USEFORMATBLOCK
     17 #include "fde_txtedtblock.h"
     18 #endif
     19 #define FDE_PAGEWIDTH_MAX 0xFFFF
     20 #define FDE_TXTPLATESIZE (1024 * 12)
     21 #define FDE_UNICODE_PARAGRAPH_SPERATOR (0x2029)
     22 #define FDE_TXTEDT_DORECORD_INS 0
     23 #define FDE_TXTEDT_DORECORD_DEL 1
     24 #ifdef FDE_USEFORMATBLOCK
     25 #define FDE_TXTEDT_DORECORD_FORMATINS 3
     26 #define FDE_TXTEDT_DORECORD_FORMATDEL 4
     27 #define FDE_TXTEDT_DORECORD_FORMATREP 5
     28 #define FDE_TXTEDT_FORMATBLOCK_BGN 0xFFF9
     29 #define FDE_TXTEDT_FORMATBLOCK_END 0xFFFB
     30 #endif
     31 IFDE_TxtEdtEngine* IFDE_TxtEdtEngine::Create() {
     32   return new CFDE_TxtEdtEngine();
     33 }
     34 CFDE_TxtEdtEngine::CFDE_TxtEdtEngine()
     35     : m_pTextBreak(nullptr),
     36       m_nPageLineCount(20),
     37       m_nLineCount(0),
     38       m_nAnchorPos(-1),
     39       m_nLayoutPos(0),
     40       m_fCaretPosReserve(0.0),
     41       m_nCaret(0),
     42       m_bBefore(TRUE),
     43       m_nCaretPage(0),
     44       m_dwFindFlags(0),
     45       m_bLock(FALSE),
     46       m_nLimit(0),
     47       m_wcAliasChar(L'*'),
     48 #ifdef FDE_USEFORMATBLOCK
     49       m_nFixLength(-1),  // FIXME: no such member => USEFORMATBLOCK can't work.
     50 #endif
     51       m_nFirstLineEnd(FDE_TXTEDIT_LINEEND_Auto),
     52       m_bAutoLineEnd(TRUE),
     53       m_wLineEnd(FDE_UNICODE_PARAGRAPH_SPERATOR) {
     54   FXSYS_memset(&m_rtCaret, 0, sizeof(CFX_RectF));
     55   m_pTxtBuf = new CFDE_TxtEdtBuf();
     56   m_bAutoLineEnd = (m_Param.nLineEnd == FDE_TXTEDIT_LINEEND_Auto);
     57 }
     58 CFDE_TxtEdtEngine::~CFDE_TxtEdtEngine() {
     59   if (m_pTxtBuf) {
     60     m_pTxtBuf->Release();
     61     m_pTxtBuf = NULL;
     62   }
     63   if (m_pTextBreak) {
     64     m_pTextBreak->Release();
     65     m_pTextBreak = NULL;
     66   }
     67 #ifdef FDE_USEFORMATBLOCK
     68   int32_t nBlockCount = m_BlockArray.GetSize();
     69   if (nBlockCount > 0) {
     70     int32_t i = 0;
     71     for (; i < nBlockCount; i++) {
     72       CFDE_TxtEdtBlock* pBlock = m_BlockArray[i];
     73       delete pBlock;
     74     }
     75     m_BlockArray.RemoveAll();
     76   }
     77 #endif
     78   RemoveAllParags();
     79   RemoveAllPages();
     80   m_Param.pEventSink = NULL;
     81   ClearSelection();
     82 }
     83 void CFDE_TxtEdtEngine::Release() {
     84   delete this;
     85 }
     86 void CFDE_TxtEdtEngine::SetEditParams(const FDE_TXTEDTPARAMS& params) {
     87   if (m_pTextBreak == NULL) {
     88     m_pTextBreak = IFX_TxtBreak::Create(FX_TXTBREAKPOLICY_None);
     89   }
     90   FXSYS_memcpy(&m_Param, &params, sizeof(FDE_TXTEDTPARAMS));
     91   m_wLineEnd = params.wLineBreakChar;
     92   m_bAutoLineEnd = (m_Param.nLineEnd == FDE_TXTEDIT_LINEEND_Auto);
     93   UpdateTxtBreak();
     94 }
     95 const FDE_TXTEDTPARAMS* CFDE_TxtEdtEngine::GetEditParams() const {
     96   return &m_Param;
     97 }
     98 int32_t CFDE_TxtEdtEngine::CountPages() const {
     99   if (m_nLineCount == 0) {
    100     return 0;
    101   }
    102   return ((m_nLineCount - 1) / m_nPageLineCount) + 1;
    103 }
    104 IFDE_TxtEdtPage* CFDE_TxtEdtEngine::GetPage(int32_t nIndex) {
    105   if (m_PagePtrArray.GetSize() <= nIndex) {
    106     return NULL;
    107   }
    108   return (IFDE_TxtEdtPage*)m_PagePtrArray[nIndex];
    109 }
    110 FX_BOOL CFDE_TxtEdtEngine::SetBufChunkSize(int32_t nChunkSize) {
    111   return m_pTxtBuf->SetChunkSize(nChunkSize);
    112 }
    113 void CFDE_TxtEdtEngine::SetTextByStream(IFX_Stream* pStream) {
    114   ResetEngine();
    115   int32_t nIndex = 0;
    116   if (pStream != NULL && pStream->GetLength()) {
    117     int32_t nStreamLength = pStream->GetLength();
    118     FX_BOOL bValid = TRUE;
    119     if (m_nLimit > 0 && nStreamLength > m_nLimit) {
    120       bValid = FALSE;
    121     }
    122     FX_BOOL bPreIsCR = FALSE;
    123     if (bValid) {
    124       uint8_t bom[4];
    125       int32_t nPos = pStream->GetBOM(bom);
    126       pStream->Seek(FX_STREAMSEEK_Begin, nPos);
    127       int32_t nPlateSize = std::min(nStreamLength, m_pTxtBuf->GetChunkSize());
    128       FX_WCHAR* lpwstr = FX_Alloc(FX_WCHAR, nPlateSize);
    129       FX_BOOL bEos = false;
    130       while (!bEos) {
    131         int32_t nRead = pStream->ReadString(lpwstr, nPlateSize, bEos);
    132         bPreIsCR = ReplaceParagEnd(lpwstr, nRead, bPreIsCR);
    133         m_pTxtBuf->Insert(nIndex, lpwstr, nRead);
    134         nIndex += nRead;
    135       }
    136       FX_Free(lpwstr);
    137     }
    138   }
    139   m_pTxtBuf->Insert(nIndex, &m_wLineEnd, 1);
    140   RebuildParagraphs();
    141 }
    142 void CFDE_TxtEdtEngine::SetText(const CFX_WideString& wsText) {
    143   ResetEngine();
    144   int32_t nLength = wsText.GetLength();
    145   if (nLength > 0) {
    146     CFX_WideString wsTemp;
    147     FX_WCHAR* lpBuffer = wsTemp.GetBuffer(nLength);
    148     FXSYS_memcpy(lpBuffer, wsText.c_str(), nLength * sizeof(FX_WCHAR));
    149     ReplaceParagEnd(lpBuffer, nLength, FALSE);
    150     wsTemp.ReleaseBuffer(nLength);
    151     if (m_nLimit > 0 && nLength > m_nLimit) {
    152       wsTemp.Delete(m_nLimit, nLength - m_nLimit);
    153       nLength = m_nLimit;
    154     }
    155     m_pTxtBuf->SetText(wsTemp);
    156   }
    157   m_pTxtBuf->Insert(nLength, &m_wLineEnd, 1);
    158   RebuildParagraphs();
    159 }
    160 int32_t CFDE_TxtEdtEngine::GetTextLength() const {
    161   return GetTextBufLength();
    162 }
    163 void CFDE_TxtEdtEngine::GetText(CFX_WideString& wsText,
    164                                 int32_t nStart,
    165                                 int32_t nCount) {
    166   int32_t nTextBufLength = GetTextBufLength();
    167   if (nCount == -1) {
    168     nCount = nTextBufLength - nStart;
    169   }
    170 #ifdef FDE_USEFORMATBLOCK
    171   int32_t nBlockCount = m_BlockArray.GetSize();
    172   if (nBlockCount == 0 || m_wsFixText.IsEmpty()) {
    173     m_pTxtBuf->GetRange(wsText, nStart, nCount);
    174     return;
    175   }
    176   CFX_WideString wsTemp;
    177   const FX_WCHAR* lpFixBuffer = const FX_WCHAR * (m_wsFixText);
    178   FX_WCHAR* lpBuffer = wsTemp.GetBuffer(nTextBufLength);
    179   int32_t nRealLength = 0;
    180   int32_t nPrePos = 0;
    181   for (int32_t i = 0; i < nBlockCount; i++) {
    182     CFDE_TxtEdtBlock* pBlock = m_BlockArray[i];
    183     int32_t nPos = pBlock->GetPos();
    184     int32_t nCopyLength = nPos - nPrePos;
    185     FXSYS_memcpy(lpBuffer + nRealLength, lpFixBuffer + nPrePos,
    186                  nCopyLength * sizeof(FX_WCHAR));
    187     nRealLength += nCopyLength;
    188     nPrePos = nPos;
    189     CFX_WideString wsBlock;
    190     pBlock->GetRealText(wsBlock);
    191     nCopyLength = wsBlock.GetLength();
    192     FXSYS_memcpy(lpBuffer + nRealLength, const FX_WCHAR*(wsBlock),
    193                  nCopyLength * sizeof(FX_WCHAR));
    194     nRealLength += nCopyLength;
    195   }
    196   int32_t nLeftLength = m_wsFixText.GetLength() - nPrePos;
    197   if (nLeftLength > 0) {
    198     FXSYS_memcpy(lpBuffer + nRealLength, lpFixBuffer + nPrePos,
    199                  nLeftLength * sizeof(FX_WCHAR));
    200     nRealLength += nLeftLength;
    201   }
    202   wsTemp.ReleaseBuffer(nRealLength);
    203   int32_t nRealBgn = GetRealIndex(nStart);
    204   int32_t nRealEnd = GetRealIndex(nStart + nCount - 1);
    205   int32_t nRealCount = nRealEnd - nRealBgn;
    206   FX_WCHAR* lpDestBuf = wsText.GetBuffer(nRealCount);
    207   FXSYS_memcpy(lpDestBuf, const FX_WCHAR*(wsTemp) + nRealBgn,
    208                nRealCount * sizeof(FX_WCHAR));
    209   wsText.ReleaseBuffer();
    210 #else
    211   m_pTxtBuf->GetRange(wsText, nStart, nCount);
    212   RecoverParagEnd(wsText);
    213   return;
    214 #endif
    215 }
    216 void CFDE_TxtEdtEngine::ClearText() {
    217   DeleteRange(0, -1);
    218 }
    219 int32_t CFDE_TxtEdtEngine::GetCaretRect(CFX_RectF& rtCaret) const {
    220   rtCaret = m_rtCaret;
    221   return m_nCaret;
    222 }
    223 int32_t CFDE_TxtEdtEngine::GetCaretPos() const {
    224   if (IsLocked()) {
    225     return 0;
    226   }
    227   return m_nCaret + (m_bBefore ? 0 : 1);
    228 }
    229 int32_t CFDE_TxtEdtEngine::SetCaretPos(int32_t nIndex, FX_BOOL bBefore) {
    230   if (IsLocked()) {
    231     return 0;
    232   }
    233   FXSYS_assert(nIndex >= 0 && nIndex <= GetTextBufLength());
    234   if (m_PagePtrArray.GetSize() <= m_nCaretPage) {
    235     return 0;
    236   }
    237 #ifdef FDE_USEFORMATBLOCK
    238   if (m_BlockArray.GetSize() > 0) {
    239     nIndex = NormalizeCaretPos(nIndex, FDE_FORMAT_CARET_MIDDLE, bBefore);
    240   }
    241 #endif
    242   m_bBefore = bBefore;
    243   m_nCaret = nIndex;
    244   MovePage2Char(m_nCaret);
    245   GetCaretRect(m_rtCaret, m_nCaretPage, m_nCaret, m_bBefore);
    246   if (!m_bBefore) {
    247     m_nCaret++;
    248     m_bBefore = TRUE;
    249   }
    250   m_fCaretPosReserve = (m_Param.dwLayoutStyles & FDE_TEXTEDITLAYOUT_DocVertical)
    251                            ? m_rtCaret.top
    252                            : m_rtCaret.left;
    253   m_Param.pEventSink->On_CaretChanged(this, m_nCaretPage, 0);
    254   m_nAnchorPos = -1;
    255   return m_nCaret;
    256 }
    257 int32_t CFDE_TxtEdtEngine::MoveCaretPos(FDE_TXTEDTMOVECARET eMoveCaret,
    258                                         FX_BOOL bShift,
    259                                         FX_BOOL bCtrl) {
    260   if (IsLocked()) {
    261     return 0;
    262   }
    263   if (m_PagePtrArray.GetSize() <= m_nCaretPage) {
    264     return 0;
    265   }
    266   FX_BOOL bSelChange = FALSE;
    267   if (IsSelect()) {
    268     ClearSelection();
    269     bSelChange = TRUE;
    270   }
    271   if (bShift) {
    272     if (m_nAnchorPos == -1) {
    273       m_nAnchorPos = m_nCaret;
    274     }
    275   } else {
    276     m_nAnchorPos = -1;
    277   }
    278   FX_BOOL bVertical = m_Param.dwLayoutStyles & FDE_TEXTEDITLAYOUT_DocVertical;
    279   switch (eMoveCaret) {
    280     case MC_Left: {
    281       if (bVertical) {
    282         CFX_PointF ptCaret;
    283         if (MoveUp(ptCaret)) {
    284           UpdateCaretIndex(ptCaret);
    285         }
    286       } else {
    287         FX_BOOL bBefore = TRUE;
    288         int32_t nIndex = MoveBackward(bBefore);
    289 #ifdef FDE_USEFORMATBLOCK
    290         if (m_BlockArray.GetSize()) {
    291           nIndex =
    292               NormalizeCaretPos(nIndex, FDE_FORMAT_CARET_BACKWARD, bBefore);
    293           if (nIndex < 0) {
    294             return m_nCaret;
    295           }
    296         }
    297 #endif
    298         if (nIndex >= 0) {
    299           UpdateCaretRect(nIndex, bBefore);
    300         }
    301       }
    302     } break;
    303     case MC_Right: {
    304       if (bVertical) {
    305         CFX_PointF ptCaret;
    306         if (MoveDown(ptCaret)) {
    307           UpdateCaretIndex(ptCaret);
    308         }
    309       } else {
    310         FX_BOOL bBefore = TRUE;
    311         int32_t nIndex = MoveForward(bBefore);
    312 #ifdef FDE_USEFORMATBLOCK
    313         if (m_BlockArray.GetSize()) {
    314           if (nIndex == -1) {
    315             nIndex = GetTextBufLength();
    316           }
    317           nIndex = NormalizeCaretPos(nIndex, FDE_FORMAT_CARET_FORWARD, bBefore);
    318         }
    319 #endif
    320         if (nIndex >= 0) {
    321           UpdateCaretRect(nIndex, bBefore);
    322         }
    323       }
    324     } break;
    325     case MC_Up: {
    326       if (bVertical) {
    327         FX_BOOL bBefore = TRUE;
    328         int32_t nIndex = MoveBackward(bBefore);
    329 #ifdef FDE_USEFORMATBLOCK
    330         if (m_BlockArray.GetSize()) {
    331           nIndex =
    332               NormalizeCaretPos(nIndex, FDE_FORMAT_CARET_BACKWARD, bBefore);
    333         }
    334 #endif
    335         if (nIndex >= 0) {
    336           UpdateCaretRect(nIndex, bBefore);
    337         }
    338       } else {
    339         CFX_PointF ptCaret;
    340         if (MoveUp(ptCaret)) {
    341           UpdateCaretIndex(ptCaret);
    342         }
    343       }
    344     } break;
    345     case MC_Down: {
    346       if (bVertical) {
    347         FX_BOOL bBefore = TRUE;
    348         int32_t nIndex = MoveForward(bBefore);
    349 #ifdef FDE_USEFORMATBLOCK
    350         if (m_BlockArray.GetSize()) {
    351           nIndex = NormalizeCaretPos(nIndex, FDE_FORMAT_CARET_FORWARD, bBefore);
    352         }
    353 #endif
    354         if (nIndex >= 0) {
    355           UpdateCaretRect(nIndex, bBefore);
    356         }
    357       } else {
    358         CFX_PointF ptCaret;
    359         if (MoveDown(ptCaret)) {
    360           UpdateCaretIndex(ptCaret);
    361         }
    362       }
    363     } break;
    364     case MC_WordBackward:
    365       break;
    366     case MC_WordForward:
    367       break;
    368     case MC_LineStart:
    369       MoveLineStart();
    370       break;
    371     case MC_LineEnd:
    372       MoveLineEnd();
    373       break;
    374     case MC_ParagStart:
    375       MoveParagStart();
    376       break;
    377     case MC_ParagEnd:
    378       MoveParagEnd();
    379       break;
    380     case MC_PageDown:
    381       break;
    382     case MC_PageUp:
    383       break;
    384     case MC_Home:
    385       MoveHome();
    386       break;
    387     case MC_End:
    388       MoveEnd();
    389       break;
    390     default:
    391       break;
    392   }
    393   if (bShift && m_nAnchorPos != -1 && (m_nAnchorPos != m_nCaret)) {
    394     AddSelRange(std::min(m_nAnchorPos, m_nCaret),
    395                 FXSYS_abs(m_nAnchorPos - m_nCaret));
    396     m_Param.pEventSink->On_SelChanged(this);
    397   }
    398   if (bSelChange) {
    399     m_Param.pEventSink->On_SelChanged(this);
    400   }
    401   return m_nCaret;
    402 }
    403 void CFDE_TxtEdtEngine::Lock() {
    404   m_bLock = TRUE;
    405 }
    406 void CFDE_TxtEdtEngine::Unlock() {
    407   m_bLock = FALSE;
    408 }
    409 FX_BOOL CFDE_TxtEdtEngine::IsLocked() const {
    410   return m_bLock;
    411 }
    412 int32_t CFDE_TxtEdtEngine::Insert(int32_t nStart,
    413                                   const FX_WCHAR* lpText,
    414                                   int32_t nLength) {
    415   if (IsLocked()) {
    416     return FDE_TXTEDT_MODIFY_RET_F_Locked;
    417   }
    418 #ifdef FDE_USEFORMATBLOCK
    419   int32_t nBlockCount = m_BlockArray.GetSize();
    420   if (nBlockCount) {
    421     if (m_Param.dwMode & FDE_TEXTEDITMODE_FIELD_TAB && nLength == 1 &&
    422         lpText[0] == L'\t') {
    423       return Move2NextEditableField(nStart) ? FDE_TXTEDT_MODIFY_RET_T_Tab
    424                                             : FDE_TXTEDT_MODIFY_RET_F_Tab;
    425     }
    426     int32_t nSelRangeCount = CountSelRanges();
    427     if (nSelRangeCount > 0) {
    428       if (nSelRangeCount > 1) {
    429         return FDE_TXTEDT_MODIFY_RET_F_Boundary;
    430       }
    431       int32_t nSelStart;
    432       int32_t nSelCount;
    433       nSelCount = GetSelRange(0, nSelStart);
    434       int32_t nSelEnd = nSelStart + nSelCount;
    435       int32_t nBgn = 0;
    436       int32_t nEnd = 0;
    437       CFDE_TxtEdtField* pField = NULL;
    438       FX_BOOL bInField = GetFieldBoundary(nSelStart, nBgn, nEnd, pField);
    439       if (nSelEnd > nEnd) {
    440         return FDE_TXTEDT_MODIFY_RET_F_Boundary;
    441       }
    442       if (bInField) {
    443         pField->Backup();
    444         FX_BOOL bBefore = FALSE;
    445         CFX_WideString wsDel;
    446         int32_t nCaret;
    447         int32_t nIndexInField = nSelStart - nBgn;
    448         int32_t nRet = pField->Replace(nSelStart - nBgn, nSelCount,
    449                                        CFX_WideStringC(lpText, nLength), wsDel,
    450                                        nCaret, bBefore);
    451         switch (nRet) {
    452           case FDE_FORMAT_FIELD_INSERT_RET_F_FULL:
    453             pField->Restore();
    454             return FDE_TXTEDT_MODIFY_RET_F_Full;
    455           case FDE_FORMAT_FIELD_INSERT_RET_F_INVALIDATE:
    456             pField->Restore();
    457             return FDE_TXTEDT_MODIFY_RET_F_Invalidate;
    458           default:
    459             break;
    460         }
    461         CFX_WideString wsField;
    462         pField->GetFieldText(wsField);
    463         if (!m_Param.pEventSink->On_ValidateField(this, pField->GetBlockIndex(),
    464                                                   pField->GetIndex(), wsField,
    465                                                   0)) {
    466           pField->Restore();
    467           return FDE_TXTEDT_MODIFY_RET_F_Invalidate;
    468         }
    469         CFX_WideString wsDisplay;
    470         pField->GetDisplayText(wsDisplay);
    471         if ((m_Param.dwMode & FDE_TEXTEDITMODE_LimitArea_Vert) ||
    472             (m_Param.dwMode & FDE_TEXTEDITMODE_LimitArea_Horz)) {
    473           CFX_WideString wsText;
    474           GetPreReplaceText(wsText, nBgn, nEnd - nBgn + 1,
    475                             const FX_WCHAR*(wsDisplay), wsDisplay.GetLength());
    476           if (!IsFitArea(wsText)) {
    477             pField->Restore();
    478             return FDE_TXTEDT_MODIFY_RET_F_Full;
    479           }
    480         }
    481         Replace(nBgn, nEnd - nBgn + 1, wsDisplay);
    482         int32_t nNewCaret = nBgn + nCaret;
    483         if (!(m_Param.dwMode & FDE_TEXTEDITMODE_NoRedoUndo)) {
    484           IFDE_TxtEdtDoRecord* pRecord = new CFDE_TxtEdtDoRecord_FieldReplace(
    485               this, m_nCaret, nNewCaret, pField, nIndexInField, nBgn,
    486               wsDisplay.GetLength(), wsDel, CFX_WideStringC(lpText, nLength),
    487               TRUE);
    488           CFX_ByteString bsDoRecord;
    489           pRecord->Serialize(bsDoRecord);
    490           m_Param.pEventSink->On_AddDoRecord(this, bsDoRecord);
    491           pRecord->Release();
    492         }
    493         SetCaretPos(nBgn + nCaret, bBefore);
    494         return FDE_TXTEDT_MODIFY_RET_S_Normal;
    495       }
    496     }
    497     int32_t nBgn = 0;
    498     int32_t nEnd = 0;
    499     CFDE_TxtEdtField* pField = NULL;
    500     FX_BOOL bInField = GetFieldBoundary(m_nCaret, nBgn, nEnd, pField);
    501     int32_t nCaretInField = m_nCaret - nBgn;
    502     FX_BOOL bBefore = FALSE;
    503     if (bInField) {
    504       pField->Backup();
    505       CFX_WideStringC wsIns(lpText, nLength);
    506       int32_t nRet =
    507           pField->Insert(nCaretInField, wsIns, nCaretInField, bBefore);
    508       FX_BOOL bFull = FALSE;
    509       switch (nRet) {
    510         case FDE_FORMAT_FIELD_INSERT_RET_S_NORMAL:
    511           break;
    512         case FDE_FORMAT_FIELD_INSERT_RET_S_FULL:
    513           bFull = TRUE;
    514           break;
    515         case FDE_FORMAT_FIELD_INSERT_RET_F_FULL:
    516           return FDE_TXTEDT_MODIFY_RET_F_Full;
    517         case FDE_FORMAT_FIELD_INSERT_RET_F_INVALIDATE:
    518           return FDE_TXTEDT_MODIFY_RET_F_Invalidate;
    519         default:
    520           return FDE_TXTEDT_MODIFY_RET_F_Normal;
    521       }
    522       CFX_WideString wsField;
    523       pField->GetFieldText(wsField);
    524       if (!m_Param.pEventSink->On_ValidateField(
    525               this, pField->GetBlockIndex(), pField->GetIndex(), wsField, 0)) {
    526         pField->Restore();
    527         return FDE_TXTEDT_MODIFY_RET_F_Invalidate;
    528       }
    529       CFX_WideString wsDisplay;
    530       pField->GetDisplayText(wsDisplay);
    531       if ((m_Param.dwMode & FDE_TEXTEDITMODE_LimitArea_Vert) ||
    532           (m_Param.dwMode & FDE_TEXTEDITMODE_LimitArea_Horz)) {
    533         CFX_WideString wsText;
    534         GetPreReplaceText(wsText, nBgn, nEnd - nBgn + 1,
    535                           const FX_WCHAR*(wsDisplay), wsDisplay.GetLength());
    536         if (!IsFitArea(wsText)) {
    537           pField->Restore();
    538           return FDE_TXTEDT_MODIFY_RET_F_Full;
    539         }
    540       }
    541       Replace(nBgn, nEnd - nBgn + 1, wsDisplay);
    542       if (!(m_Param.dwMode & FDE_TEXTEDITMODE_NoRedoUndo)) {
    543         IFDE_TxtEdtDoRecord* pRecord = new CFDE_TxtEdtDoRecord_FieldInsert(
    544             this, m_nCaret, pField, m_nCaret - nBgn, nBgn, nEnd - nBgn + 1,
    545             wsDisplay.GetLength(), CFX_WideStringC(lpText, nLength), FALSE);
    546         CFX_ByteString bsDoRecord;
    547         pRecord->Serialize(bsDoRecord);
    548         m_Param.pEventSink->On_AddDoRecord(this, bsDoRecord);
    549         pRecord->Release();
    550       }
    551       int32_t nCaretPos = nBgn + nCaretInField;
    552       if (m_Param.dwMode & FDE_TEXTEDITMODE_FIELD_AUTO && bFull &&
    553           nCaretPos == nEnd) {
    554         if (Move2NextEditableField(nEnd, TRUE, FALSE)) {
    555           return TRUE;
    556         }
    557       }
    558       SetCaretPos(nCaretPos, bBefore);
    559       return bFull ? FDE_TXTEDT_MODIFY_RET_S_Full
    560                    : FDE_TXTEDT_MODIFY_RET_S_Normal;
    561     }
    562     FXSYS_assert(0);
    563     return FDE_TXTEDT_MODIFY_RET_F_Normal;
    564   }
    565 #endif
    566   CFX_WideString wsTemp;
    567   FX_WCHAR* lpBuffer = wsTemp.GetBuffer(nLength);
    568   FXSYS_memcpy(lpBuffer, lpText, nLength * sizeof(FX_WCHAR));
    569   ReplaceParagEnd(lpBuffer, nLength, FALSE);
    570   wsTemp.ReleaseBuffer(nLength);
    571   FX_BOOL bPart = FALSE;
    572   if (m_nLimit > 0) {
    573     int32_t nTotalLength = GetTextBufLength();
    574     int32_t nCount = m_SelRangePtrArr.GetSize();
    575     for (int32_t i = 0; i < nCount; i++) {
    576       FDE_LPTXTEDTSELRANGE lpSelRange = m_SelRangePtrArr.GetAt(i);
    577       nTotalLength -= lpSelRange->nCount;
    578     }
    579     int32_t nExpectLength = nTotalLength + nLength;
    580     if (nTotalLength == m_nLimit) {
    581       return FDE_TXTEDT_MODIFY_RET_F_Full;
    582     }
    583     if (nExpectLength > m_nLimit) {
    584       nLength -= (nExpectLength - m_nLimit);
    585       bPart = TRUE;
    586     }
    587   }
    588   if ((m_Param.dwMode & FDE_TEXTEDITMODE_LimitArea_Vert) ||
    589       (m_Param.dwMode & FDE_TEXTEDITMODE_LimitArea_Horz)) {
    590     int32_t nTemp = nLength;
    591     if (m_Param.dwMode & FDE_TEXTEDITMODE_Password) {
    592       CFX_WideString wsText;
    593       while (nLength > 0) {
    594         GetPreInsertText(wsText, m_nCaret, lpBuffer, nLength);
    595         int32_t nTotal = wsText.GetLength();
    596         FX_WCHAR* lpBuf = wsText.GetBuffer(nTotal);
    597         for (int32_t i = 0; i < nTotal; i++) {
    598           lpBuf[i] = m_wcAliasChar;
    599         }
    600         wsText.ReleaseBuffer(nTotal);
    601         if (IsFitArea(wsText)) {
    602           break;
    603         }
    604         nLength--;
    605       }
    606     } else {
    607       CFX_WideString wsText;
    608       while (nLength > 0) {
    609         GetPreInsertText(wsText, m_nCaret, lpBuffer, nLength);
    610         if (IsFitArea(wsText)) {
    611           break;
    612         }
    613         nLength--;
    614       }
    615     }
    616     if (nLength == 0) {
    617       return FDE_TXTEDT_MODIFY_RET_F_Full;
    618     }
    619     if (nLength < nTemp) {
    620       bPart = TRUE;
    621     }
    622   }
    623   if (m_Param.dwMode & FDE_TEXTEDITMODE_Validate) {
    624     CFX_WideString wsText;
    625     GetPreInsertText(wsText, m_nCaret, lpBuffer, nLength);
    626     if (!m_Param.pEventSink->On_Validate(this, wsText)) {
    627       return FDE_TXTEDT_MODIFY_RET_F_Invalidate;
    628     }
    629   }
    630   if (IsSelect()) {
    631     DeleteSelect();
    632   }
    633   if (!(m_Param.dwMode & FDE_TEXTEDITMODE_NoRedoUndo)) {
    634     IFDE_TxtEdtDoRecord* pRecord =
    635         new CFDE_TxtEdtDoRecord_Insert(this, m_nCaret, lpBuffer, nLength);
    636     CFX_ByteString bsDoRecord;
    637     pRecord->Serialize(bsDoRecord);
    638     m_Param.pEventSink->On_AddDoRecord(this, bsDoRecord);
    639     pRecord->Release();
    640   }
    641   GetText(m_ChangeInfo.wsPrevText, 0);
    642   Inner_Insert(m_nCaret, lpBuffer, nLength);
    643   m_ChangeInfo.nChangeType = FDE_TXTEDT_TEXTCHANGE_TYPE_Insert;
    644   m_ChangeInfo.wsInsert = CFX_WideString(lpBuffer, nLength);
    645   nStart = m_nCaret;
    646   nStart += nLength;
    647   FX_WCHAR wChar = m_pTxtBuf->GetCharByIndex(nStart - 1);
    648   FX_BOOL bBefore = TRUE;
    649   if (wChar != L'\n' && wChar != L'\r') {
    650     nStart--;
    651     bBefore = FALSE;
    652   }
    653   SetCaretPos(nStart, bBefore);
    654   m_Param.pEventSink->On_TextChanged(this, m_ChangeInfo);
    655   return bPart ? FDE_TXTEDT_MODIFY_RET_S_Part : FDE_TXTEDT_MODIFY_RET_S_Normal;
    656 }
    657 int32_t CFDE_TxtEdtEngine::Delete(int32_t nStart, FX_BOOL bBackspace) {
    658   if (IsLocked()) {
    659     return FDE_TXTEDT_MODIFY_RET_F_Locked;
    660   }
    661   if (IsSelect()) {
    662     DeleteSelect();
    663     return FDE_TXTEDT_MODIFY_RET_S_Normal;
    664   }
    665 #ifdef FDE_USEFORMATBLOCK
    666   int32_t nBlockCount = m_BlockArray.GetSize();
    667   if (nBlockCount > 0) {
    668     if (bBackspace) {
    669       nStart--;
    670     }
    671     int32_t nCount = 1;
    672     int32_t nBgn = 0;
    673     int32_t nEnd = 0;
    674     CFDE_TxtEdtField* pField = NULL;
    675     FX_BOOL bInField = GetFieldBoundary(nStart, nBgn, nEnd, pField);
    676     int32_t nCaretInField = nStart - nBgn;
    677     FX_BOOL bBefore = FALSE;
    678     if (bInField && !pField->IsFix()) {
    679       pField->Backup();
    680       CFX_WideString wsDel;
    681       int32_t nCaret = 0;
    682       int32_t nRet =
    683           pField->Delete(nCaretInField, nCount, wsDel, nCaret, bBefore);
    684       nCaret += nBgn;
    685       switch (nRet) {
    686         case FDE_FORMAT_FIELD_DELETE_RET_S:
    687           break;
    688         case FDE_FORMAT_FIELD_DELETE_RET_F_INVALIDATE:
    689           return FDE_TXTEDT_MODIFY_RET_F_Invalidate;
    690         case FDE_FORMAT_FIELD_DELETE_RET_F_BOUNDARY:
    691           return FDE_TXTEDT_MODIFY_RET_F_Boundary;
    692         default:
    693           FXSYS_assert(0);
    694           break;
    695       }
    696       CFX_WideString wsField;
    697       pField->GetFieldText(wsField);
    698       if (!m_Param.pEventSink->On_ValidateField(
    699               this, pField->GetBlockIndex(), pField->GetIndex(), wsField, 0)) {
    700         pField->Restore();
    701         return FDE_TXTEDT_MODIFY_RET_F_Invalidate;
    702       }
    703       CFX_WideString wsDisplay;
    704       pField->GetDisplayText(wsDisplay);
    705       Replace(nBgn, nEnd - nBgn + 1, wsDisplay);
    706       if (!(m_Param.dwMode & FDE_TEXTEDITMODE_NoRedoUndo)) {
    707         IFDE_TxtEdtDoRecord* pRecord = new CFDE_TxtEdtDoRecord_FieldDelete(
    708             this, nStart, pField, nCaretInField, nBgn, nEnd - nBgn + 1,
    709             wsDisplay.GetLength(), wsDel, FALSE);
    710         CFX_ByteString bsDoRecord;
    711         pRecord->Serialize(bsDoRecord);
    712         m_Param.pEventSink->On_AddDoRecord(this, bsDoRecord);
    713         pRecord->Release();
    714       }
    715       SetCaretPos(nStart, bBefore);
    716       return FDE_TXTEDT_MODIFY_RET_S_Normal;
    717     }
    718     return FDE_TXTEDT_MODIFY_RET_F_Boundary;
    719   }
    720 #endif
    721   int32_t nCount = 1;
    722   if (bBackspace) {
    723     if (nStart == 0) {
    724       return FDE_TXTEDT_MODIFY_RET_F_Boundary;
    725     }
    726     if (nStart > 2 && m_pTxtBuf->GetCharByIndex(nStart - 1) == L'\n' &&
    727         m_pTxtBuf->GetCharByIndex(nStart - 2) == L'\r') {
    728       nStart--;
    729       nCount++;
    730     }
    731     nStart--;
    732   } else {
    733     if (nStart == GetTextBufLength()) {
    734       return FDE_TXTEDT_MODIFY_RET_F_Full;
    735     }
    736     if ((nStart + 1 < GetTextBufLength()) &&
    737         (m_pTxtBuf->GetCharByIndex(nStart) == L'\r') &&
    738         (m_pTxtBuf->GetCharByIndex(nStart + 1) == L'\n')) {
    739       nCount++;
    740     }
    741   }
    742   if (m_Param.dwMode & FDE_TEXTEDITMODE_Validate) {
    743     CFX_WideString wsText;
    744     GetPreDeleteText(wsText, nStart, nCount);
    745     if (!m_Param.pEventSink->On_Validate(this, wsText)) {
    746       return FDE_TXTEDT_MODIFY_RET_F_Invalidate;
    747     }
    748   }
    749   if (!(m_Param.dwMode & FDE_TEXTEDITMODE_NoRedoUndo)) {
    750     CFX_WideString wsRange;
    751     m_pTxtBuf->GetRange(wsRange, nStart, nCount);
    752     IFDE_TxtEdtDoRecord* pRecord =
    753         new CFDE_TxtEdtDoRecord_DeleteRange(this, nStart, m_nCaret, wsRange);
    754     CFX_ByteString bsDoRecord;
    755     pRecord->Serialize(bsDoRecord);
    756     m_Param.pEventSink->On_AddDoRecord(this, bsDoRecord);
    757     pRecord->Release();
    758   }
    759   m_ChangeInfo.nChangeType = FDE_TXTEDT_TEXTCHANGE_TYPE_Delete;
    760   GetText(m_ChangeInfo.wsDelete, nStart, nCount);
    761   Inner_DeleteRange(nStart, nCount);
    762   SetCaretPos(nStart + ((!bBackspace && nStart > 0) ? -1 : 0),
    763               (bBackspace || nStart == 0));
    764   m_Param.pEventSink->On_TextChanged(this, m_ChangeInfo);
    765   return FDE_TXTEDT_MODIFY_RET_S_Normal;
    766 }
    767 int32_t CFDE_TxtEdtEngine::DeleteRange(int32_t nStart, int32_t nCount) {
    768   if (IsLocked()) {
    769     return FDE_TXTEDT_MODIFY_RET_F_Locked;
    770   }
    771   if (nCount == -1) {
    772     nCount = GetTextBufLength();
    773   }
    774   if (nCount == 0) {
    775     return FDE_TXTEDT_MODIFY_RET_S_Normal;
    776   }
    777   if (m_Param.dwMode & FDE_TEXTEDITMODE_Validate) {
    778     CFX_WideString wsText;
    779     GetPreDeleteText(wsText, nStart, nCount);
    780     if (!m_Param.pEventSink->On_Validate(this, wsText)) {
    781       return FDE_TXTEDT_MODIFY_RET_F_Invalidate;
    782     }
    783   }
    784   DeleteRange_DoRecord(nStart, nCount);
    785   m_Param.pEventSink->On_TextChanged(this, m_ChangeInfo);
    786   SetCaretPos(nStart, TRUE);
    787   return FDE_TXTEDT_MODIFY_RET_S_Normal;
    788 }
    789 int32_t CFDE_TxtEdtEngine::Replace(int32_t nStart,
    790                                    int32_t nLength,
    791                                    const CFX_WideString& wsReplace) {
    792   if (IsLocked()) {
    793     return FDE_TXTEDT_MODIFY_RET_F_Locked;
    794   }
    795   if (nStart < 0 || (nStart + nLength > GetTextBufLength())) {
    796     return FDE_TXTEDT_MODIFY_RET_F_Boundary;
    797   }
    798   if (m_Param.dwMode & FDE_TEXTEDITMODE_Validate) {
    799     CFX_WideString wsText;
    800     GetPreReplaceText(wsText, nStart, nLength, wsReplace.c_str(),
    801                       wsReplace.GetLength());
    802     if (!m_Param.pEventSink->On_Validate(this, wsText)) {
    803       return FDE_TXTEDT_MODIFY_RET_F_Invalidate;
    804     }
    805   }
    806   if (IsSelect()) {
    807     ClearSelection();
    808   }
    809   m_ChangeInfo.nChangeType = FDE_TXTEDT_TEXTCHANGE_TYPE_Replace;
    810   GetText(m_ChangeInfo.wsDelete, nStart, nLength);
    811   if (nLength > 0) {
    812     Inner_DeleteRange(nStart, nLength);
    813   }
    814   int32_t nTextLength = wsReplace.GetLength();
    815   if (nTextLength > 0) {
    816     Inner_Insert(nStart, wsReplace.c_str(), nTextLength);
    817   }
    818   m_ChangeInfo.wsInsert = CFX_WideString(wsReplace.c_str(), nTextLength);
    819   nStart += nTextLength;
    820   FX_WCHAR wChar = m_pTxtBuf->GetCharByIndex(nStart - 1);
    821   FX_BOOL bBefore = TRUE;
    822   if (wChar != L'\n' && wChar != L'\r') {
    823     nStart--;
    824     bBefore = FALSE;
    825   }
    826   SetCaretPos(nStart, bBefore);
    827   m_Param.pEventSink->On_PageUnload(this, m_nCaretPage, 0);
    828   m_Param.pEventSink->On_PageLoad(this, m_nCaretPage, 0);
    829   m_Param.pEventSink->On_TextChanged(this, m_ChangeInfo);
    830   return FDE_TXTEDT_MODIFY_RET_S_Normal;
    831 }
    832 void CFDE_TxtEdtEngine::SetLimit(int32_t nLimit) {
    833   m_nLimit = nLimit;
    834 }
    835 void CFDE_TxtEdtEngine::SetAliasChar(FX_WCHAR wcAlias) {
    836   m_wcAliasChar = wcAlias;
    837 }
    838 void CFDE_TxtEdtEngine::SetFormatBlock(int32_t nIndex,
    839                                        const CFX_WideString& wsBlockFormat) {
    840 #ifdef FDE_USEFORMATBLOCK
    841   if (m_nFixLength == -1) {
    842     m_nFixLength = GetTextLength();
    843     FXSYS_assert(m_wsFixText.IsEmpty());
    844     GetText(m_wsFixText, 0, -1);
    845   }
    846   FX_BOOL bInBlock = FALSE;
    847   int32_t nCharIndex = 0;
    848   int32_t nBlockIndex = 0;
    849   int32_t nBlockPos = -1;
    850   FX_WCHAR wc;
    851   CFDE_TxtEdtBufIter* pIter =
    852       new CFDE_TxtEdtBufIter((CFDE_TxtEdtBuf*)m_pTxtBuf, FALSE);
    853   pIter->SetAt(0);
    854   do {
    855     wc = pIter->GetChar();
    856     if (bInBlock) {
    857       if (wc == FDE_TXTEDT_FORMATBLOCK_END) {
    858         nBlockIndex++;
    859         bInBlock = FALSE;
    860       }
    861     } else {
    862       if (wc == FDE_TXTEDT_FORMATBLOCK_BGN) {
    863         bInBlock = TRUE;
    864       } else {
    865         if (nCharIndex++ == nIndex) {
    866           nBlockPos = pIter->GetAt();
    867           break;
    868         }
    869       }
    870     }
    871   } while (pIter->Next());
    872   pIter->Release();
    873   if (nBlockPos == -1) {
    874     nBlockPos = GetTextBufLength();
    875   }
    876   CFDE_TxtEdtBlock* pEditBlock =
    877       new CFDE_TxtEdtBlock(this, wsBlockFormat, nIndex);
    878   m_BlockArray.InsertAt(m_BlockArray.GetSize(), pEditBlock);
    879   CFX_WideString wsDisplay;
    880   pEditBlock->GetDisplayText(wsDisplay);
    881   m_nCaret = nBlockPos;
    882   if (wsDisplay.GetLength() > 0) {
    883     RawInsert(nBlockPos, const FX_WCHAR*(wsDisplay), wsDisplay.GetLength());
    884   }
    885 #endif
    886 }
    887 int32_t CFDE_TxtEdtEngine::CountEditBlocks() const {
    888 #ifdef FDE_USEFORMATBLOCK
    889   return m_BlockArray.GetSize();
    890 #else
    891   return 0;
    892 #endif
    893 }
    894 void CFDE_TxtEdtEngine::GetEditBlockText(int32_t nIndex,
    895                                          CFX_WideString& wsBlockText) const {
    896 #ifdef FDE_USEFORMATBLOCK
    897   CFDE_TxtEdtBlock* pBlock = m_BlockArray[nIndex];
    898   pBlock->GetBlockText(wsBlockText);
    899 #endif
    900 }
    901 int32_t CFDE_TxtEdtEngine::CountEditFields(int32_t nBlockIndex) const {
    902 #ifdef FDE_USEFORMATBLOCK
    903   CFDE_TxtEdtBlock* pBlock = m_BlockArray[nBlockIndex];
    904   return pBlock->CountField();
    905 #else
    906   return 0;
    907 #endif
    908 }
    909 void CFDE_TxtEdtEngine::GetEditFieldText(int32_t nBlockIndex,
    910                                          int32_t nFieldIndex,
    911                                          CFX_WideString& wsFieldText) const {
    912 #ifdef FDE_USEFORMATBLOCK
    913   CFDE_TxtEdtBlock* pBlock = m_BlockArray[nBlockIndex];
    914   pBlock->GetFieldText(nFieldIndex, wsFieldText);
    915 #endif
    916 }
    917 void CFDE_TxtEdtEngine::StartEdit() {
    918 #ifdef FDE_USEFORMATBLOCK
    919 #endif
    920 }
    921 void CFDE_TxtEdtEngine::EndEdit() {
    922 #ifdef FDE_USEFORMATBLOCK
    923 #endif
    924 }
    925 void CFDE_TxtEdtEngine::RemoveSelRange(int32_t nStart, int32_t nCount) {
    926   FDE_LPTXTEDTSELRANGE lpTemp = NULL;
    927   int32_t nRangeCount = m_SelRangePtrArr.GetSize();
    928   int32_t i = 0;
    929   for (i = 0; i < nRangeCount; i++) {
    930     lpTemp = m_SelRangePtrArr[i];
    931     if (lpTemp->nStart == nStart && lpTemp->nCount == nCount) {
    932       delete lpTemp;
    933       m_SelRangePtrArr.RemoveAt(i);
    934       return;
    935     }
    936   }
    937   return;
    938 }
    939 void CFDE_TxtEdtEngine::AddSelRange(int32_t nStart, int32_t nCount) {
    940   if (nCount == -1) {
    941     nCount = GetTextLength() - nStart;
    942   }
    943   int32_t nSize = m_SelRangePtrArr.GetSize();
    944   if (nSize <= 0) {
    945     FDE_LPTXTEDTSELRANGE lpSelRange = new FDE_TXTEDTSELRANGE;
    946     lpSelRange->nStart = nStart;
    947     lpSelRange->nCount = nCount;
    948     m_SelRangePtrArr.Add(lpSelRange);
    949     m_Param.pEventSink->On_SelChanged(this);
    950     return;
    951   }
    952   FDE_LPTXTEDTSELRANGE lpTemp = NULL;
    953   lpTemp = m_SelRangePtrArr[nSize - 1];
    954   if (nStart >= lpTemp->nStart + lpTemp->nCount) {
    955     FDE_LPTXTEDTSELRANGE lpSelRange = new FDE_TXTEDTSELRANGE;
    956     lpSelRange->nStart = nStart;
    957     lpSelRange->nCount = nCount;
    958     m_SelRangePtrArr.Add(lpSelRange);
    959     m_Param.pEventSink->On_SelChanged(this);
    960     return;
    961   }
    962   int32_t nEnd = nStart + nCount - 1;
    963   FX_BOOL bBegin = FALSE;
    964   int32_t nRangeBgn = 0;
    965   int32_t nRangeCnt = 0;
    966   for (int32_t i = 0; i < nSize; i++) {
    967     lpTemp = m_SelRangePtrArr[i];
    968     int32_t nTempBgn = lpTemp->nStart;
    969     int32_t nTempEnd = nTempBgn + lpTemp->nCount - 1;
    970     if (bBegin) {
    971       if (nEnd < nTempBgn) {
    972         break;
    973       } else if (nStart >= nTempBgn && nStart <= nTempEnd) {
    974         nRangeCnt++;
    975         break;
    976       }
    977       nRangeCnt++;
    978     } else {
    979       if (nStart <= nTempEnd) {
    980         nRangeBgn = i;
    981         if (nEnd < nTempBgn) {
    982           break;
    983         }
    984         nRangeCnt = 1;
    985         bBegin = TRUE;
    986       }
    987     }
    988   }
    989   if (nRangeCnt == 0) {
    990     FDE_LPTXTEDTSELRANGE lpSelRange = new FDE_TXTEDTSELRANGE;
    991     lpSelRange->nStart = nStart;
    992     lpSelRange->nCount = nCount;
    993     m_SelRangePtrArr.InsertAt(nRangeBgn, lpSelRange);
    994   } else {
    995     lpTemp = m_SelRangePtrArr[nRangeBgn];
    996     lpTemp->nStart = nStart;
    997     lpTemp->nCount = nCount;
    998     nRangeCnt--;
    999     nRangeBgn++;
   1000     while (nRangeCnt--) {
   1001       delete m_SelRangePtrArr[nRangeBgn];
   1002       m_SelRangePtrArr.RemoveAt(nRangeBgn);
   1003     }
   1004   }
   1005   m_Param.pEventSink->On_SelChanged(this);
   1006   return;
   1007 }
   1008 int32_t CFDE_TxtEdtEngine::CountSelRanges() {
   1009   return m_SelRangePtrArr.GetSize();
   1010 }
   1011 int32_t CFDE_TxtEdtEngine::GetSelRange(int32_t nIndex, int32_t& nStart) {
   1012   nStart = m_SelRangePtrArr[nIndex]->nStart;
   1013   return m_SelRangePtrArr[nIndex]->nCount;
   1014 }
   1015 void CFDE_TxtEdtEngine::ClearSelection() {
   1016   int32_t nCount = m_SelRangePtrArr.GetSize();
   1017   FDE_LPTXTEDTSELRANGE lpRange = NULL;
   1018   int32_t i = 0;
   1019   for (i = 0; i < nCount; i++) {
   1020     lpRange = m_SelRangePtrArr[i];
   1021     if (lpRange != NULL) {
   1022       delete lpRange;
   1023       lpRange = NULL;
   1024     }
   1025   }
   1026   m_SelRangePtrArr.RemoveAll();
   1027   if (nCount && m_Param.pEventSink) {
   1028     m_Param.pEventSink->On_SelChanged(this);
   1029   }
   1030 }
   1031 FX_BOOL CFDE_TxtEdtEngine::Redo(const CFX_ByteStringC& bsRedo) {
   1032   if (IsLocked()) {
   1033     return FALSE;
   1034   }
   1035   if (m_Param.dwMode & FDE_TEXTEDITMODE_NoRedoUndo) {
   1036     return FALSE;
   1037   }
   1038   IFDE_TxtEdtDoRecord* pDoRecord = IFDE_TxtEdtDoRecord::Create(bsRedo);
   1039   FXSYS_assert(pDoRecord);
   1040   if (pDoRecord == NULL) {
   1041     return FALSE;
   1042   }
   1043   FX_BOOL bOK = pDoRecord->Redo();
   1044   pDoRecord->Release();
   1045   return bOK;
   1046 }
   1047 FX_BOOL CFDE_TxtEdtEngine::Undo(const CFX_ByteStringC& bsUndo) {
   1048   if (IsLocked()) {
   1049     return FALSE;
   1050   }
   1051   if (m_Param.dwMode & FDE_TEXTEDITMODE_NoRedoUndo) {
   1052     return FALSE;
   1053   }
   1054   IFDE_TxtEdtDoRecord* pDoRecord = IFDE_TxtEdtDoRecord::Create(bsUndo);
   1055   FXSYS_assert(pDoRecord);
   1056   if (pDoRecord == NULL) {
   1057     return FALSE;
   1058   }
   1059   FX_BOOL bOK = pDoRecord->Undo();
   1060   pDoRecord->Release();
   1061   return bOK;
   1062 }
   1063 int32_t CFDE_TxtEdtEngine::StartLayout() {
   1064   Lock();
   1065   RemoveAllPages();
   1066   m_nLayoutPos = 0;
   1067   m_nLineCount = 0;
   1068   return 0;
   1069 }
   1070 int32_t CFDE_TxtEdtEngine::DoLayout(IFX_Pause* pPause) {
   1071   int32_t nCount = m_ParagPtrArray.GetSize();
   1072   CFDE_TxtEdtParag* pParag = NULL;
   1073   int32_t nLineCount = 0;
   1074   for (; m_nLayoutPos < nCount; m_nLayoutPos++) {
   1075     pParag = m_ParagPtrArray[m_nLayoutPos];
   1076     pParag->CalcLines();
   1077     nLineCount += pParag->m_nLineCount;
   1078     if ((pPause != NULL) && (nLineCount > m_nPageLineCount) &&
   1079         pPause->NeedToPauseNow()) {
   1080       m_nLineCount += nLineCount;
   1081       return (++m_nLayoutPos * 100) / nCount;
   1082     }
   1083   }
   1084   m_nLineCount += nLineCount;
   1085   return 100;
   1086 }
   1087 void CFDE_TxtEdtEngine::EndLayout() {
   1088   UpdatePages();
   1089   int32_t nLength = GetTextLength();
   1090   if (m_nCaret > nLength) {
   1091     m_nCaret = nLength;
   1092   }
   1093   int32_t nIndex = m_nCaret;
   1094   if (!m_bBefore) {
   1095     nIndex--;
   1096   }
   1097   m_rtCaret.Set(0, 0, 1, m_Param.fFontSize);
   1098   Unlock();
   1099 }
   1100 FX_BOOL CFDE_TxtEdtEngine::Optimize(IFX_Pause* pPause) {
   1101   return m_pTxtBuf->Optimize(pPause);
   1102 }
   1103 IFDE_TxtEdtBuf* CFDE_TxtEdtEngine::GetTextBuf() const {
   1104   return (IFDE_TxtEdtBuf*)m_pTxtBuf;
   1105 }
   1106 int32_t CFDE_TxtEdtEngine::GetTextBufLength() const {
   1107   return m_pTxtBuf->GetTextLength() - 1;
   1108 }
   1109 IFX_TxtBreak* CFDE_TxtEdtEngine::GetTextBreak() const {
   1110   return m_pTextBreak;
   1111 }
   1112 int32_t CFDE_TxtEdtEngine::GetLineCount() const {
   1113   return m_nLineCount;
   1114 }
   1115 int32_t CFDE_TxtEdtEngine::GetPageLineCount() const {
   1116   return m_nPageLineCount;
   1117 }
   1118 int32_t CFDE_TxtEdtEngine::CountParags() const {
   1119   return m_ParagPtrArray.GetSize();
   1120 }
   1121 IFDE_TxtEdtParag* CFDE_TxtEdtEngine::GetParag(int32_t nParagIndex) const {
   1122   return m_ParagPtrArray[nParagIndex];
   1123 }
   1124 IFX_CharIter* CFDE_TxtEdtEngine::CreateCharIter() {
   1125   if (!m_pTxtBuf) {
   1126     return NULL;
   1127   }
   1128   return new CFDE_TxtEdtBufIter((CFDE_TxtEdtBuf*)m_pTxtBuf);
   1129 }
   1130 int32_t CFDE_TxtEdtEngine::Line2Parag(int32_t nStartParag,
   1131                                       int32_t nStartLineofParag,
   1132                                       int32_t nLineIndex,
   1133                                       int32_t& nStartLine) const {
   1134   int32_t nLineTotal = nStartLineofParag;
   1135   int32_t nCount = m_ParagPtrArray.GetSize();
   1136   CFDE_TxtEdtParag* pParag = NULL;
   1137   int32_t i = nStartParag;
   1138   for (; i < nCount; i++) {
   1139     pParag = m_ParagPtrArray[i];
   1140     nLineTotal += pParag->m_nLineCount;
   1141     if (nLineTotal > nLineIndex) {
   1142       break;
   1143     }
   1144   }
   1145   nStartLine = nLineTotal - pParag->m_nLineCount;
   1146   return i;
   1147 }
   1148 void CFDE_TxtEdtEngine::GetPreDeleteText(CFX_WideString& wsText,
   1149                                          int32_t nIndex,
   1150                                          int32_t nLength) {
   1151   GetText(wsText, 0, GetTextBufLength());
   1152   wsText.Delete(nIndex, nLength);
   1153 }
   1154 void CFDE_TxtEdtEngine::GetPreInsertText(CFX_WideString& wsText,
   1155                                          int32_t nIndex,
   1156                                          const FX_WCHAR* lpText,
   1157                                          int32_t nLength) {
   1158   GetText(wsText, 0, GetTextBufLength());
   1159   int32_t nSelIndex = 0;
   1160   int32_t nSelLength = 0;
   1161   int32_t nSelCount = CountSelRanges();
   1162   while (nSelCount--) {
   1163     nSelLength = GetSelRange(nSelCount, nSelIndex);
   1164     wsText.Delete(nSelIndex, nSelLength);
   1165     nIndex = nSelIndex;
   1166   }
   1167   CFX_WideString wsTemp;
   1168   int32_t nOldLength = wsText.GetLength();
   1169   const FX_WCHAR* pOldBuffer = wsText.c_str();
   1170   FX_WCHAR* lpBuffer = wsTemp.GetBuffer(nOldLength + nLength);
   1171   FXSYS_memcpy(lpBuffer, pOldBuffer, (nIndex) * sizeof(FX_WCHAR));
   1172   FXSYS_memcpy(lpBuffer + nIndex, lpText, nLength * sizeof(FX_WCHAR));
   1173   FXSYS_memcpy(lpBuffer + nIndex + nLength, pOldBuffer + nIndex,
   1174                (nOldLength - nIndex) * sizeof(FX_WCHAR));
   1175   wsTemp.ReleaseBuffer(nOldLength + nLength);
   1176   wsText = wsTemp;
   1177 }
   1178 void CFDE_TxtEdtEngine::GetPreReplaceText(CFX_WideString& wsText,
   1179                                           int32_t nIndex,
   1180                                           int32_t nOriginLength,
   1181                                           const FX_WCHAR* lpText,
   1182                                           int32_t nLength) {
   1183   GetText(wsText, 0, GetTextBufLength());
   1184   int32_t nSelIndex = 0;
   1185   int32_t nSelLength = 0;
   1186   int32_t nSelCount = CountSelRanges();
   1187   while (nSelCount--) {
   1188     nSelLength = GetSelRange(nSelCount, nSelIndex);
   1189     wsText.Delete(nSelIndex, nSelLength);
   1190   }
   1191   wsText.Delete(nIndex, nOriginLength);
   1192   int32_t i = 0;
   1193   for (i = 0; i < nLength; i++) {
   1194     wsText.Insert(nIndex++, lpText[i]);
   1195   }
   1196 }
   1197 void CFDE_TxtEdtEngine::Inner_Insert(int32_t nStart,
   1198                                      const FX_WCHAR* lpText,
   1199                                      int32_t nLength) {
   1200   FXSYS_assert(nLength > 0);
   1201   FDE_TXTEDTPARAGPOS ParagPos;
   1202   TextPos2ParagPos(nStart, ParagPos);
   1203   m_Param.pEventSink->On_PageUnload(this, m_nCaretPage, 0);
   1204   int32_t nParagCount = m_ParagPtrArray.GetSize();
   1205   int32_t i = 0;
   1206   for (i = ParagPos.nParagIndex + 1; i < nParagCount; i++) {
   1207     m_ParagPtrArray[i]->m_nCharStart += nLength;
   1208   }
   1209   CFDE_TxtEdtParag* pParag = m_ParagPtrArray[ParagPos.nParagIndex];
   1210   int32_t nReserveLineCount = pParag->m_nLineCount;
   1211   int32_t nReserveCharStart = pParag->m_nCharStart;
   1212   int32_t nLeavePart = ParagPos.nCharIndex;
   1213   int32_t nCutPart = pParag->m_nCharCount - ParagPos.nCharIndex;
   1214   int32_t nTextStart = 0;
   1215   FX_WCHAR wCurChar = L' ';
   1216   const FX_WCHAR* lpPos = lpText;
   1217   FX_BOOL bFirst = TRUE;
   1218   int32_t nParagIndex = ParagPos.nParagIndex;
   1219   for (i = 0; i < nLength; i++, lpPos++) {
   1220     wCurChar = *lpPos;
   1221     if (wCurChar == m_wLineEnd) {
   1222       if (bFirst) {
   1223         pParag->m_nCharCount = nLeavePart + (i - nTextStart + 1);
   1224         pParag->m_nLineCount = -1;
   1225         nReserveCharStart += pParag->m_nCharCount;
   1226         bFirst = FALSE;
   1227       } else {
   1228         pParag = new CFDE_TxtEdtParag(this);
   1229         pParag->m_nLineCount = -1;
   1230         pParag->m_nCharCount = i - nTextStart + 1;
   1231         pParag->m_nCharStart = nReserveCharStart;
   1232         m_ParagPtrArray.InsertAt(++nParagIndex, pParag);
   1233         nReserveCharStart += pParag->m_nCharCount;
   1234       }
   1235       nTextStart = i + 1;
   1236     }
   1237   }
   1238   if (bFirst) {
   1239     pParag->m_nCharCount += nLength;
   1240     pParag->m_nLineCount = -1;
   1241     bFirst = FALSE;
   1242   } else {
   1243     pParag = new CFDE_TxtEdtParag(this);
   1244     pParag->m_nLineCount = -1;
   1245     pParag->m_nCharCount = nLength - nTextStart + nCutPart;
   1246     pParag->m_nCharStart = nReserveCharStart;
   1247     m_ParagPtrArray.InsertAt(++nParagIndex, pParag);
   1248   }
   1249   m_pTxtBuf->Insert(nStart, lpText, nLength);
   1250   int32_t nTotalLineCount = 0;
   1251   for (i = ParagPos.nParagIndex; i <= nParagIndex; i++) {
   1252     pParag = m_ParagPtrArray[i];
   1253     pParag->CalcLines();
   1254     nTotalLineCount += pParag->m_nLineCount;
   1255   }
   1256   m_nLineCount += nTotalLineCount - nReserveLineCount;
   1257   m_Param.pEventSink->On_PageLoad(this, m_nCaretPage, 0);
   1258   UpdatePages();
   1259 }
   1260 #ifdef FDE_USEFORMATBLOCK
   1261 void CFDE_TxtEdtEngine::RawInsert(int32_t nStart,
   1262                                   const FX_WCHAR* lpText,
   1263                                   int32_t nLength) {
   1264   FXSYS_assert(nLength > 0);
   1265   FDE_TXTEDTPARAGPOS ParagPos;
   1266   TextPos2ParagPos(nStart, ParagPos);
   1267   int32_t nParagCount = m_ParagPtrArray.GetSize();
   1268   int32_t i = 0;
   1269   for (i = ParagPos.nParagIndex + 1; i < nParagCount; i++) {
   1270     m_ParagPtrArray[i]->m_nCharStart += nLength;
   1271   }
   1272   CFDE_TxtEdtParag* pParag = m_ParagPtrArray[ParagPos.nParagIndex];
   1273   int32_t nReserveLineCount = pParag->m_nLineCount;
   1274   int32_t nReserveCharStart = pParag->m_nCharStart;
   1275   int32_t nLeavePart = ParagPos.nCharIndex;
   1276   int32_t nCutPart = pParag->m_nCharCount - ParagPos.nCharIndex;
   1277   int32_t nTextStart = 0;
   1278   FX_WCHAR wCurChar = L' ';
   1279   const FX_WCHAR* lpPos = lpText;
   1280   FX_BOOL bFirst = TRUE;
   1281   int32_t nParagIndex = ParagPos.nParagIndex;
   1282   for (i = 0; i < nLength; i++, lpPos++) {
   1283     wCurChar = *lpPos;
   1284     if (wCurChar == m_wLineEnd) {
   1285       if (bFirst) {
   1286         pParag->m_nCharCount = nLeavePart + (i - nTextStart + 1);
   1287         pParag->m_nLineCount = -1;
   1288         nReserveCharStart += pParag->m_nCharCount;
   1289         bFirst = FALSE;
   1290       } else {
   1291         pParag = new CFDE_TxtEdtParag(this);
   1292         pParag->m_nLineCount = -1;
   1293         pParag->m_nCharCount = i - nTextStart + 1;
   1294         pParag->m_nCharStart = nReserveCharStart;
   1295         m_ParagPtrArray.InsertAt(++nParagIndex, pParag);
   1296         nReserveCharStart += pParag->m_nCharCount;
   1297       }
   1298       nTextStart = i + 1;
   1299     }
   1300   }
   1301   if (bFirst) {
   1302     pParag->m_nCharCount += nLength;
   1303     pParag->m_nLineCount = -1;
   1304     bFirst = FALSE;
   1305   } else {
   1306     pParag = new CFDE_TxtEdtParag(this);
   1307     pParag->m_nLineCount = -1;
   1308     pParag->m_nCharCount = nLength - nTextStart + nCutPart;
   1309     pParag->m_nCharStart = nReserveCharStart;
   1310     m_ParagPtrArray.InsertAt(++nParagIndex, pParag);
   1311   }
   1312   m_pTxtBuf->Insert(nStart, lpText, nLength);
   1313 }
   1314 #endif
   1315 void CFDE_TxtEdtEngine::Inner_DeleteRange(int32_t nStart, int32_t nCount) {
   1316   if (nCount == -1) {
   1317     nCount = m_pTxtBuf->GetTextLength() - nStart;
   1318   }
   1319   int32_t nEnd = nStart + nCount - 1;
   1320   FXSYS_assert(nStart >= 0 && nEnd < m_pTxtBuf->GetTextLength());
   1321   m_Param.pEventSink->On_PageUnload(this, m_nCaretPage, 0);
   1322   FDE_TXTEDTPARAGPOS ParagPosBgn, ParagPosEnd;
   1323   TextPos2ParagPos(nStart, ParagPosBgn);
   1324   TextPos2ParagPos(nEnd, ParagPosEnd);
   1325   CFDE_TxtEdtParag* pParag = m_ParagPtrArray[ParagPosEnd.nParagIndex];
   1326   FX_BOOL bLastParag = FALSE;
   1327   if (ParagPosEnd.nCharIndex == pParag->m_nCharCount - 1) {
   1328     if (ParagPosEnd.nParagIndex < m_ParagPtrArray.GetSize() - 1) {
   1329       ParagPosEnd.nParagIndex++;
   1330     } else {
   1331       bLastParag = TRUE;
   1332     }
   1333   }
   1334   int32_t nTotalLineCount = 0;
   1335   int32_t nTotalCharCount = 0;
   1336   int32_t i = 0;
   1337   for (i = ParagPosBgn.nParagIndex; i <= ParagPosEnd.nParagIndex; i++) {
   1338     CFDE_TxtEdtParag* pParag = m_ParagPtrArray[i];
   1339     pParag->CalcLines();
   1340     nTotalLineCount += pParag->m_nLineCount;
   1341     nTotalCharCount += pParag->m_nCharCount;
   1342   }
   1343   m_pTxtBuf->Delete(nStart, nCount);
   1344   int32_t nNextParagIndex = (ParagPosBgn.nCharIndex == 0 && bLastParag)
   1345                                 ? ParagPosBgn.nParagIndex
   1346                                 : (ParagPosBgn.nParagIndex + 1);
   1347   for (i = nNextParagIndex; i <= ParagPosEnd.nParagIndex; i++) {
   1348     CFDE_TxtEdtParag* pParag = m_ParagPtrArray[nNextParagIndex];
   1349     delete pParag;
   1350     m_ParagPtrArray.RemoveAt(nNextParagIndex);
   1351   }
   1352   if (!(bLastParag && ParagPosBgn.nCharIndex == 0)) {
   1353     pParag = m_ParagPtrArray[ParagPosBgn.nParagIndex];
   1354     pParag->m_nCharCount = nTotalCharCount - nCount;
   1355     pParag->CalcLines();
   1356     nTotalLineCount -= pParag->m_nLineCount;
   1357   }
   1358   int32_t nParagCount = m_ParagPtrArray.GetSize();
   1359   for (i = nNextParagIndex; i < nParagCount; i++) {
   1360     m_ParagPtrArray[i]->m_nCharStart -= nCount;
   1361   }
   1362   m_nLineCount -= nTotalLineCount;
   1363   UpdatePages();
   1364   int32_t nPageCount = CountPages();
   1365   if (m_nCaretPage >= nPageCount) {
   1366     m_nCaretPage = nPageCount - 1;
   1367   }
   1368   m_Param.pEventSink->On_PageLoad(this, m_nCaretPage, 0);
   1369 }
   1370 void CFDE_TxtEdtEngine::DeleteRange_DoRecord(int32_t nStart,
   1371                                              int32_t nCount,
   1372                                              FX_BOOL bSel) {
   1373   FXSYS_assert(nStart >= 0);
   1374   if (nCount == -1) {
   1375     nCount = GetTextLength() - nStart;
   1376   }
   1377   FXSYS_assert((nStart + nCount) <= m_pTxtBuf->GetTextLength());
   1378 #ifdef FDE_USEFORMATBLOCK
   1379   int32_t nBlockCount = m_BlockArray.GetSize();
   1380   if (nBlockCount > 0) {
   1381   }
   1382 #endif
   1383   if (!(m_Param.dwMode & FDE_TEXTEDITMODE_NoRedoUndo)) {
   1384     CFX_WideString wsRange;
   1385     m_pTxtBuf->GetRange(wsRange, nStart, nCount);
   1386     IFDE_TxtEdtDoRecord* pRecord = new CFDE_TxtEdtDoRecord_DeleteRange(
   1387         this, nStart, m_nCaret, wsRange, bSel);
   1388     CFX_ByteString bsDoRecord;
   1389     pRecord->Serialize(bsDoRecord);
   1390     m_Param.pEventSink->On_AddDoRecord(this, bsDoRecord);
   1391     pRecord->Release();
   1392   }
   1393   m_ChangeInfo.nChangeType = FDE_TXTEDT_TEXTCHANGE_TYPE_Delete;
   1394   GetText(m_ChangeInfo.wsDelete, nStart, nCount);
   1395   Inner_DeleteRange(nStart, nCount);
   1396 }
   1397 void CFDE_TxtEdtEngine::ResetEngine() {
   1398   RemoveAllPages();
   1399   RemoveAllParags();
   1400   ClearSelection();
   1401   m_nCaret = 0;
   1402   m_pTxtBuf->Clear(FALSE);
   1403   m_nCaret = 0;
   1404 }
   1405 void CFDE_TxtEdtEngine::RebuildParagraphs() {
   1406   RemoveAllParags();
   1407   FX_WCHAR wChar = L' ';
   1408   int32_t nParagStart = 0;
   1409   int32_t nIndex = 0;
   1410   IFX_CharIter* pIter = new CFDE_TxtEdtBufIter((CFDE_TxtEdtBuf*)m_pTxtBuf);
   1411   pIter->SetAt(0);
   1412   do {
   1413     wChar = pIter->GetChar();
   1414     nIndex = pIter->GetAt();
   1415     if (wChar == m_wLineEnd) {
   1416       CFDE_TxtEdtParag* pParag = new CFDE_TxtEdtParag(this);
   1417       pParag->m_nCharStart = nParagStart;
   1418       pParag->m_nCharCount = nIndex - nParagStart + 1;
   1419       pParag->m_nLineCount = -1;
   1420       m_ParagPtrArray.Add(pParag);
   1421       nParagStart = nIndex + 1;
   1422     }
   1423   } while (pIter->Next());
   1424   pIter->Release();
   1425 }
   1426 void CFDE_TxtEdtEngine::RemoveAllParags() {
   1427   int32_t nCount = m_ParagPtrArray.GetSize();
   1428   int32_t i = 0;
   1429   for (i = 0; i < nCount; i++) {
   1430     CFDE_TxtEdtParag* pParag = m_ParagPtrArray[i];
   1431     if (pParag) {
   1432       delete pParag;
   1433     }
   1434   }
   1435   m_ParagPtrArray.RemoveAll();
   1436 }
   1437 void CFDE_TxtEdtEngine::RemoveAllPages() {
   1438   int32_t nCount = m_PagePtrArray.GetSize();
   1439   int32_t i = 0;
   1440   for (i = 0; i < nCount; i++) {
   1441     IFDE_TxtEdtPage* pPage = m_PagePtrArray[i];
   1442     if (pPage) {
   1443       pPage->Release();
   1444     }
   1445   }
   1446   m_PagePtrArray.RemoveAll();
   1447 }
   1448 void CFDE_TxtEdtEngine::UpdateParags() {
   1449   int32_t nCount = m_ParagPtrArray.GetSize();
   1450   if (nCount == 0) {
   1451     return;
   1452   }
   1453   CFDE_TxtEdtParag* pParag = NULL;
   1454   int32_t nLineCount = 0;
   1455   int32_t i = 0;
   1456   for (i = 0; i < nCount; i++) {
   1457     pParag = m_ParagPtrArray[i];
   1458     if (pParag->m_nLineCount == -1) {
   1459       pParag->CalcLines();
   1460     }
   1461     nLineCount += pParag->m_nLineCount;
   1462   }
   1463   m_nLineCount = nLineCount;
   1464 }
   1465 void CFDE_TxtEdtEngine::UpdatePages() {
   1466   if (m_nLineCount == 0) {
   1467     return;
   1468   }
   1469   int32_t nPageCount = (m_nLineCount - 1) / (m_nPageLineCount) + 1;
   1470   int32_t nSize = m_PagePtrArray.GetSize();
   1471   if (nSize == nPageCount) {
   1472     return;
   1473   }
   1474   if (nSize > nPageCount) {
   1475     IFDE_TxtEdtPage* pPage = NULL;
   1476     int32_t i = 0;
   1477     for (i = nSize - 1; i >= nPageCount; i--) {
   1478       pPage = m_PagePtrArray[i];
   1479       if (pPage) {
   1480         pPage->Release();
   1481       }
   1482       m_PagePtrArray.RemoveAt(i);
   1483     }
   1484     m_Param.pEventSink->On_PageCountChanged(this);
   1485     return;
   1486   }
   1487   if (nSize < nPageCount) {
   1488     IFDE_TxtEdtPage* pPage = NULL;
   1489     int32_t i = 0;
   1490     for (i = nSize; i < nPageCount; i++) {
   1491       pPage = IFDE_TxtEdtPage::Create(this, i);
   1492       m_PagePtrArray.Add(pPage);
   1493     }
   1494     m_Param.pEventSink->On_PageCountChanged(this);
   1495     return;
   1496   }
   1497 }
   1498 void CFDE_TxtEdtEngine::UpdateTxtBreak() {
   1499   FX_DWORD dwStyle = m_pTextBreak->GetLayoutStyles();
   1500   if (m_Param.dwMode & FDE_TEXTEDITMODE_MultiLines) {
   1501     dwStyle &= ~FX_TXTLAYOUTSTYLE_SingleLine;
   1502   } else {
   1503     dwStyle |= FX_TXTLAYOUTSTYLE_SingleLine;
   1504   }
   1505   if (m_Param.dwLayoutStyles & FDE_TEXTEDITLAYOUT_DocVertical) {
   1506     dwStyle |= FX_TXTLAYOUTSTYLE_VerticalLayout;
   1507   } else {
   1508     dwStyle &= ~FX_TXTLAYOUTSTYLE_VerticalLayout;
   1509   }
   1510   if (m_Param.dwLayoutStyles & FDE_TEXTEDITLAYOUT_LineReserve) {
   1511     dwStyle |= FX_TXTLAYOUTSTYLE_ReverseLine;
   1512   } else {
   1513     dwStyle &= ~FX_TXTLAYOUTSTYLE_ReverseLine;
   1514   }
   1515   if (m_Param.dwLayoutStyles & FDE_TEXTEDITLAYOUT_RTL) {
   1516     dwStyle |= FX_TXTLAYOUTSTYLE_RTLReadingOrder;
   1517   } else {
   1518     dwStyle &= ~FX_TXTLAYOUTSTYLE_RTLReadingOrder;
   1519   }
   1520   if (m_Param.dwLayoutStyles & FDE_TEXTEDITLAYOUT_CombText) {
   1521     dwStyle |= FX_TXTLAYOUTSTYLE_CombText;
   1522   } else {
   1523     dwStyle &= ~FX_TXTLAYOUTSTYLE_CombText;
   1524   }
   1525   if (m_Param.dwLayoutStyles & FDE_TEXTEDITLAYOUT_CharVertial) {
   1526     dwStyle |= FX_TXTLAYOUTSTYLE_VerticalChars;
   1527   } else {
   1528     dwStyle &= ~FX_TXTLAYOUTSTYLE_VerticalChars;
   1529   }
   1530   if (m_Param.dwLayoutStyles & FDE_TEXTEDITLAYOUT_ExpandTab) {
   1531     dwStyle |= FX_TXTLAYOUTSTYLE_ExpandTab;
   1532   } else {
   1533     dwStyle &= ~FX_TXTLAYOUTSTYLE_ExpandTab;
   1534   }
   1535   if (m_Param.dwLayoutStyles & FDE_TEXTEDITLAYOUT_ArabicContext) {
   1536     dwStyle |= FX_TXTLAYOUTSTYLE_ArabicContext;
   1537   } else {
   1538     dwStyle &= ~FX_TXTLAYOUTSTYLE_ArabicContext;
   1539   }
   1540   if (m_Param.dwLayoutStyles & FDE_TEXTEDITLAYOUT_ArabicShapes) {
   1541     dwStyle |= FX_TXTLAYOUTSTYLE_ArabicShapes;
   1542   } else {
   1543     dwStyle &= ~FX_TXTLAYOUTSTYLE_ArabicShapes;
   1544   }
   1545   m_pTextBreak->SetLayoutStyles(dwStyle);
   1546   FX_DWORD dwAligment = 0;
   1547   if (m_Param.dwAlignment & FDE_TEXTEDITALIGN_Justified) {
   1548     dwAligment |= FX_TXTLINEALIGNMENT_Justified;
   1549   } else if (m_Param.dwAlignment & FDE_TEXTEDITALIGN_Distributed) {
   1550     dwAligment |= FX_TXTLINEALIGNMENT_Distributed;
   1551   }
   1552   if (m_Param.dwAlignment & FDE_TEXTEDITALIGN_Center) {
   1553     dwAligment |= FX_TXTLINEALIGNMENT_Center;
   1554   } else if (m_Param.dwAlignment & FDE_TEXTEDITALIGN_Right) {
   1555     dwAligment |= FX_TXTLINEALIGNMENT_Right;
   1556   }
   1557   m_pTextBreak->SetAlignment(dwAligment);
   1558   if (m_Param.dwLayoutStyles & FDE_TEXTEDITLAYOUT_DocVertical) {
   1559     if (m_Param.dwMode & FDE_TEXTEDITMODE_AutoLineWrap) {
   1560       m_pTextBreak->SetLineWidth(m_Param.fPlateHeight);
   1561     } else {
   1562       m_pTextBreak->SetLineWidth(FDE_PAGEWIDTH_MAX);
   1563     }
   1564   } else {
   1565     if (m_Param.dwMode & FDE_TEXTEDITMODE_AutoLineWrap) {
   1566       m_pTextBreak->SetLineWidth(m_Param.fPlateWidth);
   1567     } else {
   1568       m_pTextBreak->SetLineWidth(FDE_PAGEWIDTH_MAX);
   1569     }
   1570   }
   1571   m_nPageLineCount = m_Param.nLineCount;
   1572   if (m_Param.dwLayoutStyles & FDE_TEXTEDITLAYOUT_CombText) {
   1573     FX_FLOAT fCombWidth =
   1574         m_Param.dwLayoutStyles & FDE_TEXTEDITLAYOUT_DocVertical
   1575             ? m_Param.fPlateHeight
   1576             : m_Param.fPlateWidth;
   1577     if (m_nLimit > 0) {
   1578       fCombWidth /= m_nLimit;
   1579     }
   1580     m_pTextBreak->SetCombWidth(fCombWidth);
   1581   }
   1582   m_pTextBreak->SetFont(m_Param.pFont);
   1583   m_pTextBreak->SetFontSize(m_Param.fFontSize);
   1584   m_pTextBreak->SetTabWidth(m_Param.fTabWidth, m_Param.bTabEquidistant);
   1585   m_pTextBreak->SetDefaultChar(m_Param.wDefChar);
   1586   m_pTextBreak->SetParagraphBreakChar(m_Param.wLineBreakChar);
   1587   m_pTextBreak->SetCharRotation(m_Param.nCharRotation);
   1588   m_pTextBreak->SetLineBreakTolerance(m_Param.fFontSize * 0.2f);
   1589   m_pTextBreak->SetHorizontalScale(m_Param.nHorzScale);
   1590   m_pTextBreak->SetCharSpace(m_Param.fCharSpace);
   1591 }
   1592 FX_BOOL CFDE_TxtEdtEngine::ReplaceParagEnd(FX_WCHAR*& lpText,
   1593                                            int32_t& nLength,
   1594                                            FX_BOOL bPreIsCR) {
   1595   for (int32_t i = 0; i < nLength; i++) {
   1596     FX_WCHAR wc = lpText[i];
   1597     switch (wc) {
   1598       case L'\r': {
   1599         lpText[i] = m_wLineEnd;
   1600         bPreIsCR = TRUE;
   1601       } break;
   1602       case L'\n': {
   1603         if (bPreIsCR == TRUE) {
   1604           int32_t nNext = i + 1;
   1605           if (nNext < nLength) {
   1606             FXSYS_memmove(lpText + i, lpText + nNext,
   1607                           (nLength - nNext) * sizeof(FX_WCHAR));
   1608           }
   1609           i--;
   1610           nLength--;
   1611           bPreIsCR = FALSE;
   1612           if (m_bAutoLineEnd) {
   1613             m_nFirstLineEnd = FDE_TXTEDIT_LINEEND_CRLF;
   1614             m_bAutoLineEnd = FALSE;
   1615           }
   1616         } else {
   1617           lpText[i] = m_wLineEnd;
   1618           if (m_bAutoLineEnd) {
   1619             m_nFirstLineEnd = FDE_TXTEDIT_LINEEND_LF;
   1620             m_bAutoLineEnd = FALSE;
   1621           }
   1622         }
   1623       } break;
   1624       default: {
   1625         if (bPreIsCR && m_bAutoLineEnd) {
   1626           m_nFirstLineEnd = FDE_TXTEDIT_LINEEND_CR;
   1627           m_bAutoLineEnd = FALSE;
   1628         }
   1629         bPreIsCR = FALSE;
   1630       } break;
   1631     }
   1632   }
   1633   return bPreIsCR;
   1634 }
   1635 void CFDE_TxtEdtEngine::RecoverParagEnd(CFX_WideString& wsText) {
   1636   FX_WCHAR wc = (m_nFirstLineEnd == FDE_TXTEDIT_LINEEND_CR) ? L'\n' : L'\r';
   1637   if (m_nFirstLineEnd == FDE_TXTEDIT_LINEEND_CRLF) {
   1638     CFX_ArrayTemplate<int32_t> PosArr;
   1639     int32_t nLength = wsText.GetLength();
   1640     int32_t i = 0;
   1641     FX_WCHAR* lpPos = (FX_WCHAR*)(const FX_WCHAR*)wsText;
   1642     for (i = 0; i < nLength; i++, lpPos++) {
   1643       if (*lpPos == m_wLineEnd) {
   1644         *lpPos = wc;
   1645         PosArr.Add(i);
   1646       }
   1647     }
   1648     const FX_WCHAR* lpSrcBuf = wsText.c_str();
   1649     CFX_WideString wsTemp;
   1650     int32_t nCount = PosArr.GetSize();
   1651     FX_WCHAR* lpDstBuf = wsTemp.GetBuffer(nLength + nCount);
   1652     int32_t nDstPos = 0;
   1653     int32_t nSrcPos = 0;
   1654     for (i = 0; i < nCount; i++) {
   1655       int32_t nPos = PosArr[i];
   1656       int32_t nCopyLen = nPos - nSrcPos + 1;
   1657       FXSYS_memcpy(lpDstBuf + nDstPos, lpSrcBuf + nSrcPos,
   1658                    nCopyLen * sizeof(FX_WCHAR));
   1659       nDstPos += nCopyLen;
   1660       nSrcPos += nCopyLen;
   1661       lpDstBuf[nDstPos] = L'\n';
   1662       nDstPos++;
   1663     }
   1664     if (nSrcPos < nLength) {
   1665       FXSYS_memcpy(lpDstBuf + nDstPos, lpSrcBuf + nSrcPos,
   1666                    (nLength - nSrcPos) * sizeof(FX_WCHAR));
   1667     }
   1668     wsTemp.ReleaseBuffer(nLength + nCount);
   1669     wsText = wsTemp;
   1670   } else {
   1671     int32_t nLength = wsText.GetLength();
   1672     FX_WCHAR* lpBuf = (FX_WCHAR*)(const FX_WCHAR*)wsText;
   1673     for (int32_t i = 0; i < nLength; i++, lpBuf++) {
   1674       if (*lpBuf == m_wLineEnd) {
   1675         *lpBuf = wc;
   1676       }
   1677     }
   1678   }
   1679 }
   1680 int32_t CFDE_TxtEdtEngine::MovePage2Char(int32_t nIndex) {
   1681   FXSYS_assert(nIndex >= 0);
   1682   FXSYS_assert(nIndex <= m_pTxtBuf->GetTextLength());
   1683   if (m_nCaretPage >= 0) {
   1684     IFDE_TxtEdtPage* pPage = m_PagePtrArray[m_nCaretPage];
   1685     m_Param.pEventSink->On_PageLoad(this, m_nCaretPage, 0);
   1686     int32_t nPageCharStart = pPage->GetCharStart();
   1687     int32_t nPageCharCount = pPage->GetCharCount();
   1688     if (nIndex >= nPageCharStart && nIndex < nPageCharStart + nPageCharCount) {
   1689       m_Param.pEventSink->On_PageUnload(this, m_nCaretPage, 0);
   1690       return m_nCaretPage;
   1691     }
   1692     m_Param.pEventSink->On_PageUnload(this, m_nCaretPage, 0);
   1693   }
   1694   CFDE_TxtEdtParag* pParag = NULL;
   1695   int32_t nLineCount = 0;
   1696   int32_t nParagCount = m_ParagPtrArray.GetSize();
   1697   int32_t i = 0;
   1698   for (i = 0; i < nParagCount; i++) {
   1699     pParag = m_ParagPtrArray[i];
   1700     if (pParag->m_nCharStart <= nIndex &&
   1701         nIndex < (pParag->m_nCharStart + pParag->m_nCharCount)) {
   1702       break;
   1703     }
   1704     nLineCount += pParag->m_nLineCount;
   1705   }
   1706   pParag->LoadParag();
   1707   int32_t nLineStart = -1;
   1708   int32_t nLineCharCount = -1;
   1709   for (i = 0; i < pParag->m_nLineCount; i++) {
   1710     pParag->GetLineRange(i, nLineStart, nLineCharCount);
   1711     if (nLineStart <= nIndex && nIndex < (nLineStart + nLineCharCount)) {
   1712       break;
   1713     }
   1714   }
   1715   FXSYS_assert(i < pParag->m_nLineCount);
   1716   nLineCount += (i + 1);
   1717   m_nCaretPage = (nLineCount - 1) / m_nPageLineCount + 1 - 1;
   1718   m_Param.pEventSink->On_PageChange(this, m_nCaretPage);
   1719   pParag->UnloadParag();
   1720   return m_nCaretPage;
   1721 }
   1722 void CFDE_TxtEdtEngine::TextPos2ParagPos(int32_t nIndex,
   1723                                          FDE_TXTEDTPARAGPOS& ParagPos) const {
   1724   FXSYS_assert(nIndex >= 0 && nIndex < m_pTxtBuf->GetTextLength());
   1725   int32_t nCount = m_ParagPtrArray.GetSize();
   1726   int32_t nBgn = 0;
   1727   int32_t nMid = 0;
   1728   int32_t nEnd = nCount - 1;
   1729   while (nEnd > nBgn) {
   1730     nMid = (nBgn + nEnd) / 2;
   1731     CFDE_TxtEdtParag* pParag = m_ParagPtrArray[nMid];
   1732     if (nIndex < pParag->m_nCharStart) {
   1733       nEnd = nMid - 1;
   1734     } else if (nIndex >= (pParag->m_nCharStart + pParag->m_nCharCount)) {
   1735       nBgn = nMid + 1;
   1736     } else {
   1737       break;
   1738     }
   1739   }
   1740   if (nBgn == nEnd) {
   1741     nMid = nBgn;
   1742   }
   1743   FXSYS_assert(nIndex >= m_ParagPtrArray[nMid]->m_nCharStart &&
   1744                (nIndex < m_ParagPtrArray[nMid]->m_nCharStart +
   1745                              m_ParagPtrArray[nMid]->m_nCharCount));
   1746   ParagPos.nParagIndex = nMid;
   1747   ParagPos.nCharIndex = nIndex - m_ParagPtrArray[nMid]->m_nCharStart;
   1748 }
   1749 int32_t CFDE_TxtEdtEngine::MoveForward(FX_BOOL& bBefore) {
   1750   if (m_nCaret == m_pTxtBuf->GetTextLength() - 1) {
   1751     return -1;
   1752   }
   1753   int32_t nCaret = m_nCaret;
   1754   if ((nCaret + 1 < m_pTxtBuf->GetTextLength()) &&
   1755       (m_pTxtBuf->GetCharByIndex(nCaret) == L'\r') &&
   1756       (m_pTxtBuf->GetCharByIndex(nCaret + 1) == L'\n')) {
   1757     nCaret++;
   1758   }
   1759   nCaret++;
   1760   bBefore = TRUE;
   1761   return nCaret;
   1762 }
   1763 int32_t CFDE_TxtEdtEngine::MoveBackward(FX_BOOL& bBefore) {
   1764   if (m_nCaret == 0) {
   1765     return FALSE;
   1766   }
   1767   int32_t nCaret = m_nCaret;
   1768   if (nCaret > 2 && m_pTxtBuf->GetCharByIndex(nCaret - 1) == L'\n' &&
   1769       m_pTxtBuf->GetCharByIndex(nCaret - 2) == L'\r') {
   1770     nCaret--;
   1771   }
   1772   nCaret--;
   1773   bBefore = TRUE;
   1774   return nCaret;
   1775 }
   1776 FX_BOOL CFDE_TxtEdtEngine::MoveUp(CFX_PointF& ptCaret) {
   1777   IFDE_TxtEdtPage* pPage = GetPage(m_nCaretPage);
   1778   const CFX_RectF& rtContent = pPage->GetContentsBox();
   1779   if (m_Param.dwLayoutStyles & FDE_TEXTEDITLAYOUT_DocVertical) {
   1780     ptCaret.x = m_rtCaret.left + m_rtCaret.width / 2 - m_Param.fLineSpace;
   1781     ptCaret.y = m_fCaretPosReserve;
   1782     FX_BOOL bLineReserve =
   1783         m_Param.dwLayoutStyles & FDE_TEXTEDITLAYOUT_LineReserve;
   1784     if (ptCaret.x < rtContent.left) {
   1785       if (bLineReserve) {
   1786         if (m_nCaretPage == CountPages() - 1) {
   1787           return FALSE;
   1788         }
   1789       } else {
   1790         if (m_nCaretPage == 0) {
   1791           return FALSE;
   1792         }
   1793       }
   1794       if (bLineReserve) {
   1795         m_nCaretPage++;
   1796       } else {
   1797         m_nCaretPage--;
   1798       }
   1799       m_Param.pEventSink->On_PageChange(this, m_nCaretPage);
   1800       ptCaret.x -= rtContent.left;
   1801       IFDE_TxtEdtPage* pCurPage = GetPage(m_nCaretPage);
   1802       ptCaret.x += pCurPage->GetContentsBox().right();
   1803     }
   1804   } else {
   1805     ptCaret.x = m_fCaretPosReserve;
   1806     ptCaret.y = m_rtCaret.top + m_rtCaret.height / 2 - m_Param.fLineSpace;
   1807     if (ptCaret.y < rtContent.top) {
   1808       if (m_nCaretPage == 0) {
   1809         return FALSE;
   1810       }
   1811       ptCaret.y -= rtContent.top;
   1812       m_nCaretPage--;
   1813       m_Param.pEventSink->On_PageChange(this, m_nCaretPage);
   1814       IFDE_TxtEdtPage* pCurPage = GetPage(m_nCaretPage);
   1815       ptCaret.y += pCurPage->GetContentsBox().bottom();
   1816     }
   1817   }
   1818   return TRUE;
   1819 }
   1820 FX_BOOL CFDE_TxtEdtEngine::MoveDown(CFX_PointF& ptCaret) {
   1821   IFDE_TxtEdtPage* pPage = GetPage(m_nCaretPage);
   1822   const CFX_RectF& rtContent = pPage->GetContentsBox();
   1823   if (m_Param.dwLayoutStyles & FDE_TEXTEDITLAYOUT_DocVertical) {
   1824     ptCaret.x = m_rtCaret.left + m_rtCaret.width / 2 + m_Param.fLineSpace;
   1825     ptCaret.y = m_fCaretPosReserve;
   1826     if (ptCaret.x >= rtContent.right()) {
   1827       FX_BOOL bLineReserve =
   1828           m_Param.dwLayoutStyles & FDE_TEXTEDITLAYOUT_LineReserve;
   1829       if (bLineReserve) {
   1830         if (m_nCaretPage == 0) {
   1831           return FALSE;
   1832         }
   1833       } else {
   1834         if (m_nCaretPage == CountPages() - 1) {
   1835           return FALSE;
   1836         }
   1837       }
   1838       if (bLineReserve) {
   1839         m_nCaretPage--;
   1840       } else {
   1841         m_nCaretPage++;
   1842       }
   1843       m_Param.pEventSink->On_PageChange(this, m_nCaretPage);
   1844       ptCaret.x -= rtContent.right();
   1845       IFDE_TxtEdtPage* pCurPage = GetPage(m_nCaretPage);
   1846       ptCaret.x += pCurPage->GetContentsBox().left;
   1847     }
   1848   } else {
   1849     ptCaret.x = m_fCaretPosReserve;
   1850     ptCaret.y = m_rtCaret.top + m_rtCaret.height / 2 + m_Param.fLineSpace;
   1851     if (ptCaret.y >= rtContent.bottom()) {
   1852       if (m_nCaretPage == CountPages() - 1) {
   1853         return FALSE;
   1854       }
   1855       ptCaret.y -= rtContent.bottom();
   1856       m_nCaretPage++;
   1857       m_Param.pEventSink->On_PageChange(this, m_nCaretPage);
   1858       IFDE_TxtEdtPage* pCurPage = GetPage(m_nCaretPage);
   1859       ptCaret.y += pCurPage->GetContentsBox().top;
   1860     }
   1861   }
   1862   return TRUE;
   1863 }
   1864 FX_BOOL CFDE_TxtEdtEngine::MoveLineStart() {
   1865   int32_t nIndex = m_bBefore ? m_nCaret : m_nCaret - 1;
   1866   FDE_TXTEDTPARAGPOS ParagPos;
   1867   TextPos2ParagPos(nIndex, ParagPos);
   1868   CFDE_TxtEdtParag* pParag = m_ParagPtrArray[ParagPos.nParagIndex];
   1869   pParag->LoadParag();
   1870   int32_t nLineCount = pParag->m_nLineCount;
   1871   int32_t i = 0;
   1872   int32_t nStart = 0;
   1873   int32_t nCount = 0;
   1874   for (; i < nLineCount; i++) {
   1875     pParag->GetLineRange(i, nStart, nCount);
   1876     if (nIndex >= nStart && nIndex < nStart + nCount) {
   1877       break;
   1878     }
   1879   }
   1880   UpdateCaretRect(nStart, TRUE);
   1881   pParag->UnloadParag();
   1882   return TRUE;
   1883 }
   1884 FX_BOOL CFDE_TxtEdtEngine::MoveLineEnd() {
   1885   int32_t nIndex = m_bBefore ? m_nCaret : m_nCaret - 1;
   1886   FDE_TXTEDTPARAGPOS ParagPos;
   1887   TextPos2ParagPos(nIndex, ParagPos);
   1888   CFDE_TxtEdtParag* pParag = m_ParagPtrArray[ParagPos.nParagIndex];
   1889   pParag->LoadParag();
   1890   int32_t nLineCount = pParag->m_nLineCount;
   1891   int32_t i = 0;
   1892   int32_t nStart = 0;
   1893   int32_t nCount = 0;
   1894   for (; i < nLineCount; i++) {
   1895     pParag->GetLineRange(i, nStart, nCount);
   1896     if (nIndex >= nStart && nIndex < nStart + nCount) {
   1897       break;
   1898     }
   1899   }
   1900   nIndex = nStart + nCount - 1;
   1901   FXSYS_assert(nIndex <= GetTextBufLength());
   1902   FX_WCHAR wChar = m_pTxtBuf->GetCharByIndex(nIndex);
   1903   FX_BOOL bBefore = FALSE;
   1904   if (nIndex <= GetTextBufLength()) {
   1905     if (wChar == L'\r') {
   1906       bBefore = TRUE;
   1907     } else if (wChar == L'\n' && nIndex > nStart) {
   1908       bBefore = TRUE;
   1909       nIndex--;
   1910       wChar = m_pTxtBuf->GetCharByIndex(nIndex);
   1911       if (wChar != L'\r') {
   1912         nIndex++;
   1913       }
   1914     }
   1915   }
   1916   UpdateCaretRect(nIndex, bBefore);
   1917   pParag->UnloadParag();
   1918   return TRUE;
   1919 }
   1920 FX_BOOL CFDE_TxtEdtEngine::MoveParagStart() {
   1921   int32_t nIndex = m_bBefore ? m_nCaret : m_nCaret - 1;
   1922   FDE_TXTEDTPARAGPOS ParagPos;
   1923   TextPos2ParagPos(nIndex, ParagPos);
   1924   CFDE_TxtEdtParag* pParag = m_ParagPtrArray[ParagPos.nParagIndex];
   1925   UpdateCaretRect(pParag->m_nCharStart, TRUE);
   1926   return TRUE;
   1927 }
   1928 FX_BOOL CFDE_TxtEdtEngine::MoveParagEnd() {
   1929   int32_t nIndex = m_bBefore ? m_nCaret : m_nCaret - 1;
   1930   FDE_TXTEDTPARAGPOS ParagPos;
   1931   TextPos2ParagPos(nIndex, ParagPos);
   1932   CFDE_TxtEdtParag* pParag = m_ParagPtrArray[ParagPos.nParagIndex];
   1933   nIndex = pParag->m_nCharStart + pParag->m_nCharCount - 1;
   1934   FX_WCHAR wChar = m_pTxtBuf->GetCharByIndex(nIndex);
   1935   if (wChar == L'\n' && nIndex > 0) {
   1936     nIndex--;
   1937     wChar = m_pTxtBuf->GetCharByIndex(nIndex);
   1938     if (wChar != L'\r') {
   1939       nIndex++;
   1940     }
   1941   }
   1942   UpdateCaretRect(nIndex, TRUE);
   1943   return TRUE;
   1944 }
   1945 FX_BOOL CFDE_TxtEdtEngine::MoveHome() {
   1946   UpdateCaretRect(0, TRUE);
   1947   return TRUE;
   1948 }
   1949 FX_BOOL CFDE_TxtEdtEngine::MoveEnd() {
   1950   UpdateCaretRect(GetTextBufLength(), TRUE);
   1951   return TRUE;
   1952 }
   1953 #ifdef FDE_USEFORMATBLOCK
   1954 int32_t CFDE_TxtEdtEngine::NormalizeCaretPos(int32_t nIndex,
   1955                                              int32_t nFlags,
   1956                                              FX_BOOL& bBefore) {
   1957   bBefore = TRUE;
   1958   int32_t nBgn = 0, nEnd = 0;
   1959   int32_t nRecord = -1;
   1960   CFDE_TxtEdtField* pField = NULL;
   1961   FX_BOOL bRet = GetFieldBoundary(nIndex, nBgn, nEnd, pField);
   1962   int32_t nDelta = 0;
   1963   if (bRet && !pField->IsFix()) {
   1964     if (nIndex - nBgn < FDE_FORMAT_EDIT_FIELD_HADERSIZE) {
   1965       if (nFlags == FDE_FORMAT_CARET_BACKWARD) {
   1966         CFDE_TxtEdtField* pEditableField = NULL;
   1967         if (FindEditableField(nIndex, nBgn, nEnd, pEditableField, FALSE)) {
   1968           return pEditableField->NormalizeCaretPos(nEnd - nBgn,
   1969                                                    FDE_FORMAT_CARET_BACKWARD) +
   1970                  nBgn;
   1971         }
   1972       }
   1973       nIndex = nBgn + FDE_FORMAT_EDIT_FIELD_HADERSIZE;
   1974     }
   1975     int32_t nRet = pField->NormalizeCaretPos(
   1976         nIndex - nBgn, (FDE_FORMAT_CARET_DIRECTION)nFlags);
   1977     if (nRet >= 0) {
   1978       return nRet + nBgn;
   1979     }
   1980     if (nRet == -2) {
   1981       int32_t nEditablePosBgn = 0, nEditablePosEnd = 0;
   1982       pField->GetEditableRange(nEditablePosBgn, nEditablePosEnd);
   1983       nRecord = nBgn + nEditablePosBgn;
   1984       nFlags = FDE_FORMAT_CARET_BACKWARD;
   1985     } else {
   1986       FXSYS_assert(nRet == -1);
   1987       int32_t nEditablePosBgn = 0, nEditablePosEnd = 0;
   1988       pField->GetEditableRange(nEditablePosBgn, nEditablePosEnd);
   1989       nRecord = nBgn + nEditablePosEnd;
   1990       nFlags = FDE_FORMAT_CARET_FORWARD;
   1991     }
   1992   } else if (!bRet) {
   1993     nDelta = FDE_FORMAT_EDIT_FIELD_HADERSIZE - FDE_FORMAT_EDIT_FIELD_TAILSIZE;
   1994   }
   1995   switch (nFlags) {
   1996     case FDE_FORMAT_CARET_FORWARD: {
   1997       if (FindEditableField(nIndex, nBgn, nEnd, pField)) {
   1998         return pField->NormalizeCaretPos(FDE_FORMAT_EDIT_FIELD_HADERSIZE,
   1999                                          FDE_FORMAT_CARET_FORWARD) +
   2000                nBgn;
   2001       } else {
   2002         if (nRecord != -1) {
   2003           return nRecord;
   2004         }
   2005         bRet = FindEditableField(nIndex, nBgn, nEnd, pField, FALSE);
   2006         FXSYS_assert(bRet);
   2007         return pField->NormalizeCaretPos(nEnd - nBgn,
   2008                                          FDE_FORMAT_CARET_BACKWARD) +
   2009                nBgn;
   2010       }
   2011     } break;
   2012     case FDE_FORMAT_CARET_MIDDLE: {
   2013       int32_t nBgn1 = 0, nEnd1 = 0, nBgn2 = 0, nEnd2 = 0;
   2014       CFDE_TxtEdtField* pEditableField1 = NULL;
   2015       CFDE_TxtEdtField* pEditableField2 = NULL;
   2016       FX_BOOL bRet1 =
   2017           FindEditableField(nIndex, nBgn1, nEnd1, pEditableField1, FALSE);
   2018       FX_BOOL bRet2 = FindEditableField(nIndex, nBgn2, nEnd2, pEditableField2);
   2019       if (bRet1 == FALSE) {
   2020         FXSYS_assert(bRet2);
   2021         return pEditableField2->NormalizeCaretPos(
   2022                    FDE_FORMAT_EDIT_FIELD_HADERSIZE, FDE_FORMAT_CARET_FORWARD) +
   2023                nBgn2;
   2024       } else if (bRet2 == FALSE) {
   2025         FXSYS_assert(bRet1);
   2026         return pEditableField1->NormalizeCaretPos(nEnd1 - nBgn1,
   2027                                                   FDE_FORMAT_CARET_BACKWARD) +
   2028                nBgn1;
   2029       } else {
   2030         int32_t nEditablePosBgn = 0, nEditablePosEnd = 0;
   2031         if (nIndex - nEnd1 < nBgn2 + nDelta - nIndex) {
   2032           pEditableField1->GetEditableRange(nEditablePosBgn, nEditablePosEnd);
   2033           return nEditablePosEnd + nBgn1;
   2034         } else {
   2035           pEditableField2->GetEditableRange(nEditablePosBgn, nEditablePosEnd);
   2036           return nEditablePosBgn + nBgn2;
   2037         }
   2038       }
   2039     } break;
   2040     case FDE_FORMAT_CARET_BACKWARD: {
   2041       if (FindEditableField(nIndex, nBgn, nEnd, pField, FALSE)) {
   2042         return pField->NormalizeCaretPos(nEnd - nBgn,
   2043                                          FDE_FORMAT_CARET_BACKWARD) +
   2044                nBgn;
   2045       } else {
   2046         if (nRecord != -1) {
   2047           return nRecord;
   2048         }
   2049         bRet = FindEditableField(nIndex, nBgn, nEnd, pField);
   2050         FXSYS_assert(bRet);
   2051         return pField->NormalizeCaretPos(FDE_FORMAT_EDIT_FIELD_HADERSIZE,
   2052                                          FDE_FORMAT_CARET_FORWARD) +
   2053                nBgn;
   2054       }
   2055     } break;
   2056     default:
   2057       FXSYS_assert(0);
   2058       return nIndex;
   2059   }
   2060 }
   2061 FX_BOOL CFDE_TxtEdtEngine::GetFieldBoundary(int32_t nIndex,
   2062                                             int32_t& nBgn,
   2063                                             int32_t& nEnd,
   2064                                             CFDE_TxtEdtField*& pField) {
   2065   CFDE_TxtEdtBufIter* pIter =
   2066       new CFDE_TxtEdtBufIter((CFDE_TxtEdtBuf*)m_pTxtBuf, FALSE);
   2067   pIter->SetAt(nIndex);
   2068   FX_BOOL bFind = FALSE;
   2069   do {
   2070     FX_WCHAR wc = pIter->GetChar();
   2071     if (wc == FDE_TXTEDT_FORMATBLOCK_END) {
   2072       nEnd = pIter->GetAt();
   2073       bFind = TRUE;
   2074       nIndex--;
   2075       break;
   2076     }
   2077     if (wc == FDE_TXTEDT_FORMATBLOCK_BGN) {
   2078       pIter->Release();
   2079       return FALSE;
   2080     }
   2081   } while (pIter->Next());
   2082   if (!bFind) {
   2083     pIter->Release();
   2084     return FALSE;
   2085   }
   2086   pIter->SetAt(nIndex);
   2087   do {
   2088     FX_WCHAR wc = pIter->GetChar();
   2089     if (wc == FDE_TXTEDT_FORMATBLOCK_BGN) {
   2090       nBgn = pIter->GetAt();
   2091       pIter->Next();
   2092       FX_DWORD dwPre = (FX_DWORD)pIter->GetChar();
   2093       pIter->Next();
   2094       FX_DWORD dwCur = (FX_DWORD)pIter->GetChar();
   2095       pField = (CFDE_TxtEdtField*)((dwCur << 16) | dwPre);
   2096       pIter->Release();
   2097       return TRUE;
   2098     }
   2099     if (wc == FDE_TXTEDT_FORMATBLOCK_END) {
   2100       pIter->Release();
   2101       return FALSE;
   2102     }
   2103   } while (pIter->Next(TRUE));
   2104   pIter->Release();
   2105   return FALSE;
   2106 }
   2107 FX_BOOL CFDE_TxtEdtEngine::FindEditableField(int32_t nIndex,
   2108                                              int32_t& nBgn,
   2109                                              int32_t& nEnd,
   2110                                              CFDE_TxtEdtField*& pField,
   2111                                              FX_BOOL bForward) {
   2112   FX_WCHAR wcFirst = FDE_TXTEDT_FORMATBLOCK_BGN;
   2113   FX_WCHAR wcSecond = FDE_TXTEDT_FORMATBLOCK_END;
   2114   if (!bForward) {
   2115     wcFirst = FDE_TXTEDT_FORMATBLOCK_END;
   2116     wcSecond = FDE_TXTEDT_FORMATBLOCK_BGN;
   2117   }
   2118   CFDE_TxtEdtBufIter* pIter =
   2119       new CFDE_TxtEdtBufIter((CFDE_TxtEdtBuf*)m_pTxtBuf, FALSE);
   2120   pIter->SetAt(nIndex);
   2121   int32_t bFind = FALSE;
   2122   do {
   2123     FX_WCHAR wc = pIter->GetChar();
   2124     if (wc == wcFirst) {
   2125       nBgn = pIter->GetAt();
   2126       bFind = TRUE;
   2127       break;
   2128     }
   2129   } while (pIter->Next(!bForward));
   2130   if (!bFind) {
   2131     pIter->Release();
   2132     return FALSE;
   2133   }
   2134   bFind = FALSE;
   2135   do {
   2136     FX_WCHAR wc = pIter->GetChar();
   2137     if (wc == wcSecond) {
   2138       nEnd = pIter->GetAt();
   2139       bFind = TRUE;
   2140       break;
   2141     }
   2142   } while (pIter->Next(!bForward));
   2143   FXSYS_assert(bFind);
   2144   if (!bForward) {
   2145     int32_t nTemp = nBgn;
   2146     nBgn = nEnd;
   2147     nEnd = nTemp;
   2148   }
   2149   pIter->SetAt(nBgn + 1);
   2150   FX_DWORD dwPre = (FX_DWORD)pIter->GetChar();
   2151   pIter->Next();
   2152   FX_DWORD dwCur = (FX_DWORD)pIter->GetChar();
   2153   pField = (CFDE_TxtEdtField*)((dwCur << 16) | dwPre);
   2154   pIter->Release();
   2155   if (!pField->IsFix()) {
   2156     return TRUE;
   2157   }
   2158   return FindEditableField((bForward ? nEnd : nBgn), nBgn, nEnd, pField,
   2159                            bForward);
   2160 }
   2161 FX_BOOL CFDE_TxtEdtEngine::Move2NextEditableField(int32_t nIndex,
   2162                                                   FX_BOOL bForward,
   2163                                                   FX_BOOL bSelect) {
   2164   if (m_SelRangePtrArr.GetSize() > 0) {
   2165     ClearSelection();
   2166     m_Param.pEventSink->On_SelChanged(this);
   2167   }
   2168   int32_t nBgn = 0, nEnd = 0;
   2169   CFDE_TxtEdtField* pField = NULL;
   2170   FX_BOOL bRet = FindEditableField(nIndex, nBgn, nEnd, pField, bForward);
   2171   if (!bRet) {
   2172     return FALSE;
   2173   }
   2174   int32_t nEditableBgn = 0, nEditableEnd = 0;
   2175   pField->GetEditableRange(nEditableBgn, nEditableEnd);
   2176   nEditableBgn += nBgn;
   2177   nEditableEnd += nBgn;
   2178   if (bSelect) {
   2179     int32_t nRangeCount = nEditableEnd - nEditableBgn;
   2180     if (nRangeCount > 0) {
   2181       AddSelRange(nEditableBgn, nEditableEnd - nEditableBgn);
   2182     }
   2183   }
   2184   SetCaretPos(nEditableEnd, TRUE);
   2185   return TRUE;
   2186 }
   2187 int32_t CFDE_TxtEdtEngine::GetRealIndex(int32_t nIndex) const {
   2188   CFDE_TxtEdtBufIter* pIter =
   2189       new CFDE_TxtEdtBufIter((CFDE_TxtEdtBuf*)m_pTxtBuf, FALSE);
   2190   pIter->SetAt(0);
   2191   FX_BOOL bInField = FALSE;
   2192   int32_t nFieldBgn = 0;
   2193   int32_t nRealIndex = 0;
   2194   for (int32_t i = 0; i <= nIndex; i++) {
   2195     FX_WCHAR wc = pIter->GetChar();
   2196     if (bInField) {
   2197       if (wc == FDE_TXTEDT_FORMATBLOCK_END) {
   2198         FX_DWORD dwPre = (FX_DWORD)m_pTxtBuf->GetCharByIndex(nFieldBgn + 1);
   2199         FX_DWORD dwCur = (FX_DWORD)m_pTxtBuf->GetCharByIndex(nFieldBgn + 2);
   2200         CFDE_TxtEdtField* pField = (CFDE_TxtEdtField*)((dwCur << 16) | dwPre);
   2201         nRealIndex += pField->GetFieldTextLength();
   2202         bInField = FALSE;
   2203       }
   2204     } else {
   2205       if (wc == FDE_TXTEDT_FORMATBLOCK_BGN) {
   2206         bInField = TRUE;
   2207         nFieldBgn = pIter->GetAt();
   2208       } else {
   2209         nRealIndex++;
   2210       }
   2211     }
   2212     pIter->Next();
   2213   }
   2214   if (!bInField) {
   2215     pIter->Release();
   2216     return nRealIndex;
   2217   }
   2218   pIter->SetAt(nFieldBgn + 1);
   2219   FX_DWORD dwPre = (FX_DWORD)pIter->GetChar();
   2220   pIter->Next();
   2221   FX_DWORD dwCur = (FX_DWORD)pIter->GetChar();
   2222   CFDE_TxtEdtField* pField = (CFDE_TxtEdtField*)((dwCur << 16) | dwPre);
   2223   pIter->Release();
   2224   if (pField->IsFix()) {
   2225     int32_t nDelta = nIndex - nFieldBgn - FDE_FORMAT_EDIT_FIELD_HADERSIZE + 1;
   2226     return nRealIndex + (nDelta > 0 ? nDelta : 0);
   2227   } else {
   2228     return nRealIndex + pField->GetRealIndex(nIndex - nFieldBgn);
   2229   }
   2230 }
   2231 #endif
   2232 FX_BOOL CFDE_TxtEdtEngine::IsFitArea(CFX_WideString& wsText) {
   2233   IFDE_TextOut* pTextOut = IFDE_TextOut::Create();
   2234   pTextOut->SetLineSpace(m_Param.fLineSpace);
   2235   pTextOut->SetFont(m_Param.pFont);
   2236   pTextOut->SetFontSize(m_Param.fFontSize);
   2237   CFX_RectF rcText;
   2238   FXSYS_memset(&rcText, 0, sizeof(rcText));
   2239   FX_DWORD dwStyle = 0;
   2240   if (!(m_Param.dwMode & FDE_TEXTEDITMODE_MultiLines)) {
   2241     dwStyle |= FDE_TTOSTYLE_SingleLine;
   2242   }
   2243   if (m_Param.dwMode & FDE_TEXTEDITMODE_AutoLineWrap) {
   2244     dwStyle |= FDE_TTOSTYLE_LineWrap;
   2245     rcText.width = m_Param.fPlateWidth;
   2246   } else {
   2247     rcText.width = 65535;
   2248   }
   2249   pTextOut->SetStyles(dwStyle);
   2250   wsText += L"\n";
   2251   pTextOut->CalcLogicSize(wsText, wsText.GetLength(), rcText);
   2252   pTextOut->Release();
   2253   wsText.Delete(wsText.GetLength() - 1);
   2254   if ((m_Param.dwMode & FDE_TEXTEDITMODE_LimitArea_Horz) &&
   2255       (rcText.width > m_Param.fPlateWidth)) {
   2256     return FALSE;
   2257   }
   2258   if ((m_Param.dwMode & FDE_TEXTEDITMODE_LimitArea_Vert) &&
   2259       (rcText.height > m_Param.fLineSpace * m_Param.nLineCount)) {
   2260     return FALSE;
   2261   }
   2262   return TRUE;
   2263 }
   2264 void CFDE_TxtEdtEngine::UpdateCaretRect(int32_t nIndex, FX_BOOL bBefore) {
   2265   MovePage2Char(nIndex);
   2266   GetCaretRect(m_rtCaret, m_nCaretPage, nIndex, bBefore);
   2267   m_nCaret = nIndex;
   2268   m_bBefore = bBefore;
   2269   if (!m_bBefore) {
   2270     m_nCaret++;
   2271     m_bBefore = TRUE;
   2272   }
   2273   m_fCaretPosReserve = (m_Param.dwLayoutStyles & FDE_TEXTEDITLAYOUT_DocVertical)
   2274                            ? m_rtCaret.top
   2275                            : m_rtCaret.left;
   2276   m_Param.pEventSink->On_CaretChanged(this, m_nCaretPage, 0);
   2277 }
   2278 void CFDE_TxtEdtEngine::GetCaretRect(CFX_RectF& rtCaret,
   2279                                      int32_t nPageIndex,
   2280                                      int32_t nCaret,
   2281                                      FX_BOOL bBefore) {
   2282   IFDE_TxtEdtPage* pPage = m_PagePtrArray[m_nCaretPage];
   2283   m_Param.pEventSink->On_PageLoad(this, m_nCaretPage, 0);
   2284   FX_BOOL bCombText = m_Param.dwLayoutStyles & FDE_TEXTEDITLAYOUT_CombText;
   2285   int32_t nIndexInpage = nCaret - pPage->GetCharStart();
   2286   if (bBefore && bCombText && nIndexInpage > 0) {
   2287     nIndexInpage--;
   2288     bBefore = FALSE;
   2289   }
   2290   int32_t nBIDILevel = pPage->GetCharRect(nIndexInpage, rtCaret, bCombText);
   2291   if (m_Param.dwLayoutStyles & FDE_TEXTEDITLAYOUT_DocVertical) {
   2292     if ((!FX_IsOdd(nBIDILevel) && !bBefore) ||
   2293         (FX_IsOdd(nBIDILevel) && bBefore)) {
   2294       rtCaret.Offset(0, rtCaret.height - 1.0f);
   2295     }
   2296     if (rtCaret.height == 0 && rtCaret.top > 1.0f) {
   2297       rtCaret.top -= 1.0f;
   2298     }
   2299     rtCaret.height = 1.0f;
   2300   } else {
   2301     if ((!FX_IsOdd(nBIDILevel) && !bBefore) ||
   2302         (FX_IsOdd(nBIDILevel) && bBefore)) {
   2303       rtCaret.Offset(rtCaret.width - 1.0f, 0);
   2304     }
   2305     if (rtCaret.width == 0 && rtCaret.left > 1.0f) {
   2306       rtCaret.left -= 1.0f;
   2307     }
   2308     rtCaret.width = 1.0f;
   2309   }
   2310   m_Param.pEventSink->On_PageUnload(this, m_nCaretPage, 0);
   2311 }
   2312 void CFDE_TxtEdtEngine::UpdateCaretIndex(const CFX_PointF& ptCaret) {
   2313   IFDE_TxtEdtPage* pPage = m_PagePtrArray[m_nCaretPage];
   2314   m_Param.pEventSink->On_PageLoad(this, m_nCaretPage, 0);
   2315   m_nCaret = pPage->GetCharIndex(ptCaret, m_bBefore);
   2316   GetCaretRect(m_rtCaret, m_nCaretPage, m_nCaret, m_bBefore);
   2317   if (!m_bBefore) {
   2318     m_nCaret++;
   2319     m_bBefore = TRUE;
   2320   }
   2321   m_Param.pEventSink->On_CaretChanged(this, m_nCaretPage);
   2322   m_Param.pEventSink->On_PageUnload(this, m_nCaretPage, 0);
   2323 }
   2324 FX_BOOL CFDE_TxtEdtEngine::IsSelect() {
   2325   return m_SelRangePtrArr.GetSize() > 0;
   2326 }
   2327 void CFDE_TxtEdtEngine::DeleteSelect() {
   2328   int32_t nCountRange = CountSelRanges();
   2329   if (nCountRange > 0) {
   2330 #ifdef FDE_USEFORMATBLOCK
   2331     int32_t nBlockCount = m_BlockArray.GetSize();
   2332     if (nBlockCount > 0) {
   2333       if (nCountRange > 1) {
   2334         return;
   2335       }
   2336       int32_t nSelStart;
   2337       int32_t nSelCount;
   2338       nSelCount = GetSelRange(0, nSelStart);
   2339       int32_t nSelEnd = nSelStart + nSelCount;
   2340       int32_t nBgn = 0;
   2341       int32_t nEnd = 0;
   2342       CFDE_TxtEdtField* pField = NULL;
   2343       FX_BOOL bInField = GetFieldBoundary(nSelStart, nBgn, nEnd, pField);
   2344       int32_t nCaretInField = nSelStart - nBgn;
   2345       FX_BOOL bBefore = FALSE;
   2346       if (!bInField || pField->IsFix() || nSelEnd > nEnd) {
   2347         return;
   2348       }
   2349       pField->Backup();
   2350       CFX_WideString wsDel;
   2351       int32_t nCaret = 0;
   2352       int32_t nRet =
   2353           pField->Delete(nCaretInField, nSelCount, wsDel, nCaret, bBefore);
   2354       nCaret += nBgn;
   2355       switch (nRet) {
   2356         case FDE_FORMAT_FIELD_DELETE_RET_S:
   2357           break;
   2358         case FDE_FORMAT_FIELD_DELETE_RET_F_INVALIDATE:
   2359         case FDE_FORMAT_FIELD_DELETE_RET_F_BOUNDARY:
   2360           return;
   2361         default:
   2362           FXSYS_assert(0);
   2363           break;
   2364       }
   2365       CFX_WideString wsField;
   2366       pField->GetFieldText(wsField);
   2367       if (!m_Param.pEventSink->On_ValidateField(
   2368               this, pField->GetBlockIndex(), pField->GetIndex(), wsField, 0)) {
   2369         pField->Restore();
   2370         return;
   2371       }
   2372       CFX_WideString wsDisplay;
   2373       pField->GetDisplayText(wsDisplay);
   2374       Replace(nBgn, nEnd - nBgn + 1, wsDisplay);
   2375       if (!(m_Param.dwMode & FDE_TEXTEDITMODE_NoRedoUndo)) {
   2376         IFDE_TxtEdtDoRecord* pRecord = new CFDE_TxtEdtDoRecord_FieldDelete(
   2377             this, nSelStart, pField, nCaretInField, nBgn, nEnd - nBgn + 1,
   2378             wsDisplay.GetLength(), wsDel, FALSE);
   2379         CFX_ByteString bsDoRecord;
   2380         pRecord->Serialize(bsDoRecord);
   2381         m_Param.pEventSink->On_AddDoRecord(this, bsDoRecord);
   2382         pRecord->Release();
   2383       }
   2384       SetCaretPos(nSelStart, bBefore);
   2385       return;
   2386     }
   2387 #endif
   2388     int32_t nSelStart;
   2389     int32_t nSelCount;
   2390     while (nCountRange > 0) {
   2391       nSelCount = GetSelRange(--nCountRange, nSelStart);
   2392       FDE_LPTXTEDTSELRANGE lpTemp = m_SelRangePtrArr[nCountRange];
   2393       delete lpTemp;
   2394       m_SelRangePtrArr.RemoveAt(nCountRange);
   2395       DeleteRange_DoRecord(nSelStart, nSelCount, TRUE);
   2396     }
   2397     ClearSelection();
   2398     m_Param.pEventSink->On_TextChanged(this, m_ChangeInfo);
   2399     m_Param.pEventSink->On_SelChanged(this);
   2400     SetCaretPos(nSelStart, TRUE);
   2401     return;
   2402   }
   2403 }
   2404 IFDE_TxtEdtDoRecord* IFDE_TxtEdtDoRecord::Create(
   2405     const CFX_ByteStringC& bsDoRecord) {
   2406   const FX_CHAR* lpBuf = bsDoRecord.GetCStr();
   2407   int32_t nType = *((int32_t*)lpBuf);
   2408   switch (nType) {
   2409     case FDE_TXTEDT_DORECORD_INS:
   2410       return new CFDE_TxtEdtDoRecord_Insert(bsDoRecord);
   2411     case FDE_TXTEDT_DORECORD_DEL:
   2412       return new CFDE_TxtEdtDoRecord_DeleteRange(bsDoRecord);
   2413 #ifdef FDE_USEFORMATBLOCK
   2414     case FDE_TXTEDT_DORECORD_FORMATINS:
   2415       return new CFDE_TxtEdtDoRecord_FieldInsert(bsDoRecord);
   2416     case FDE_TXTEDT_DORECORD_FORMATDEL:
   2417       return new CFDE_TxtEdtDoRecord_FieldDelete(bsDoRecord);
   2418     case FDE_TXTEDT_DORECORD_FORMATREP:
   2419       return new CFDE_TxtEdtDoRecord_FieldReplace(bsDoRecord);
   2420 #endif
   2421     default:
   2422       break;
   2423   }
   2424   return NULL;
   2425 }
   2426 CFDE_TxtEdtDoRecord_Insert::CFDE_TxtEdtDoRecord_Insert(
   2427     const CFX_ByteStringC& bsDoRecord) {
   2428   Deserialize(bsDoRecord);
   2429 }
   2430 CFDE_TxtEdtDoRecord_Insert::CFDE_TxtEdtDoRecord_Insert(
   2431     CFDE_TxtEdtEngine* pEngine,
   2432     int32_t nCaret,
   2433     const FX_WCHAR* lpText,
   2434     int32_t nLength)
   2435     : m_pEngine(pEngine), m_nCaret(nCaret) {
   2436   FXSYS_assert(pEngine);
   2437   FX_WCHAR* lpBuffer = m_wsInsert.GetBuffer(nLength);
   2438   FXSYS_memcpy(lpBuffer, lpText, nLength * sizeof(FX_WCHAR));
   2439   m_wsInsert.ReleaseBuffer();
   2440 }
   2441 CFDE_TxtEdtDoRecord_Insert::~CFDE_TxtEdtDoRecord_Insert() {}
   2442 void CFDE_TxtEdtDoRecord_Insert::Release() {
   2443   delete this;
   2444 }
   2445 FX_BOOL CFDE_TxtEdtDoRecord_Insert::Undo() {
   2446   if (m_pEngine->IsSelect()) {
   2447     m_pEngine->ClearSelection();
   2448   }
   2449   m_pEngine->Inner_DeleteRange(m_nCaret, m_wsInsert.GetLength());
   2450   FDE_TXTEDTPARAMS& Param = m_pEngine->m_Param;
   2451   m_pEngine->m_ChangeInfo.nChangeType = FDE_TXTEDT_TEXTCHANGE_TYPE_Delete;
   2452   m_pEngine->m_ChangeInfo.wsDelete = m_wsInsert;
   2453   Param.pEventSink->On_TextChanged(m_pEngine, m_pEngine->m_ChangeInfo);
   2454   m_pEngine->SetCaretPos(m_nCaret, TRUE);
   2455   return TRUE;
   2456 }
   2457 FX_BOOL CFDE_TxtEdtDoRecord_Insert::Redo() {
   2458   m_pEngine->Inner_Insert(m_nCaret, m_wsInsert.c_str(), m_wsInsert.GetLength());
   2459   FDE_TXTEDTPARAMS& Param = m_pEngine->m_Param;
   2460   m_pEngine->m_ChangeInfo.nChangeType = FDE_TXTEDT_TEXTCHANGE_TYPE_Insert;
   2461   m_pEngine->m_ChangeInfo.wsDelete = m_wsInsert;
   2462   Param.pEventSink->On_TextChanged(m_pEngine, m_pEngine->m_ChangeInfo);
   2463   m_pEngine->SetCaretPos(m_nCaret, FALSE);
   2464   return TRUE;
   2465 }
   2466 void CFDE_TxtEdtDoRecord_Insert::Serialize(CFX_ByteString& bsDoRecord) const {
   2467   CFX_ArchiveSaver ArchiveSaver;
   2468   ArchiveSaver << int32_t(FDE_TXTEDT_DORECORD_INS);
   2469   ArchiveSaver << (int32_t)(uintptr_t)m_pEngine;
   2470   ArchiveSaver << m_nCaret;
   2471   ArchiveSaver << m_wsInsert;
   2472   int32_t nLength = ArchiveSaver.GetLength();
   2473   const uint8_t* lpSrcBuf = ArchiveSaver.GetBuffer();
   2474   FX_CHAR* lpDstBuf = bsDoRecord.GetBuffer(nLength);
   2475   FXSYS_memcpy(lpDstBuf, lpSrcBuf, nLength);
   2476   bsDoRecord.ReleaseBuffer(nLength);
   2477 }
   2478 void CFDE_TxtEdtDoRecord_Insert::Deserialize(
   2479     const CFX_ByteStringC& bsDoRecord) {
   2480   CFX_ArchiveLoader ArchiveLoader((const uint8_t*)bsDoRecord.GetCStr(),
   2481                                   bsDoRecord.GetLength());
   2482   int32_t nType = 0;
   2483   ArchiveLoader >> nType;
   2484   FXSYS_assert(nType == FDE_TXTEDT_DORECORD_INS);
   2485   int32_t nEngine = 0;
   2486   ArchiveLoader >> nEngine;
   2487   m_pEngine = (CFDE_TxtEdtEngine*)(uintptr_t)nEngine;
   2488   ArchiveLoader >> m_nCaret;
   2489   ArchiveLoader >> m_wsInsert;
   2490 }
   2491 CFDE_TxtEdtDoRecord_DeleteRange::CFDE_TxtEdtDoRecord_DeleteRange(
   2492     const CFX_ByteStringC& bsDoRecord) {
   2493   Deserialize(bsDoRecord);
   2494 }
   2495 CFDE_TxtEdtDoRecord_DeleteRange::CFDE_TxtEdtDoRecord_DeleteRange(
   2496     CFDE_TxtEdtEngine* pEngine,
   2497     int32_t nIndex,
   2498     int32_t nCaret,
   2499     const CFX_WideString& wsRange,
   2500     FX_BOOL bSel)
   2501     : m_pEngine(pEngine),
   2502       m_bSel(bSel),
   2503       m_nIndex(nIndex),
   2504       m_nCaret(nCaret),
   2505       m_wsRange(wsRange) {
   2506   FXSYS_assert(pEngine);
   2507 }
   2508 CFDE_TxtEdtDoRecord_DeleteRange::~CFDE_TxtEdtDoRecord_DeleteRange() {}
   2509 void CFDE_TxtEdtDoRecord_DeleteRange::Release() {
   2510   delete this;
   2511 }
   2512 FX_BOOL CFDE_TxtEdtDoRecord_DeleteRange::Undo() {
   2513   if (m_pEngine->IsSelect()) {
   2514     m_pEngine->ClearSelection();
   2515   }
   2516   m_pEngine->Inner_Insert(m_nIndex, m_wsRange.c_str(), m_wsRange.GetLength());
   2517   if (m_bSel) {
   2518     m_pEngine->AddSelRange(m_nIndex, m_wsRange.GetLength());
   2519   }
   2520   FDE_TXTEDTPARAMS& Param = m_pEngine->m_Param;
   2521   m_pEngine->m_ChangeInfo.nChangeType = FDE_TXTEDT_TEXTCHANGE_TYPE_Insert;
   2522   m_pEngine->m_ChangeInfo.wsDelete = m_wsRange;
   2523   Param.pEventSink->On_TextChanged(m_pEngine, m_pEngine->m_ChangeInfo);
   2524   m_pEngine->SetCaretPos(m_nCaret, TRUE);
   2525   return TRUE;
   2526 }
   2527 FX_BOOL CFDE_TxtEdtDoRecord_DeleteRange::Redo() {
   2528   m_pEngine->Inner_DeleteRange(m_nIndex, m_wsRange.GetLength());
   2529   if (m_bSel) {
   2530     m_pEngine->RemoveSelRange(m_nIndex, m_wsRange.GetLength());
   2531   }
   2532   FDE_TXTEDTPARAMS& Param = m_pEngine->m_Param;
   2533   m_pEngine->m_ChangeInfo.nChangeType = FDE_TXTEDT_TEXTCHANGE_TYPE_Insert;
   2534   m_pEngine->m_ChangeInfo.wsDelete = m_wsRange;
   2535   Param.pEventSink->On_TextChanged(m_pEngine, m_pEngine->m_ChangeInfo);
   2536   m_pEngine->SetCaretPos(m_nIndex, TRUE);
   2537   return TRUE;
   2538 }
   2539 void CFDE_TxtEdtDoRecord_DeleteRange::Serialize(
   2540     CFX_ByteString& bsDoRecord) const {
   2541   CFX_ArchiveSaver ArchiveSaver;
   2542   ArchiveSaver << int32_t(FDE_TXTEDT_DORECORD_DEL);
   2543   ArchiveSaver << (int32_t)(uintptr_t)m_pEngine;
   2544   ArchiveSaver << (int32_t)m_bSel;
   2545   ArchiveSaver << m_nIndex;
   2546   ArchiveSaver << m_nCaret;
   2547   ArchiveSaver << m_wsRange;
   2548   int32_t nLength = ArchiveSaver.GetLength();
   2549   const uint8_t* lpSrcBuf = ArchiveSaver.GetBuffer();
   2550   FX_CHAR* lpDstBuf = bsDoRecord.GetBuffer(nLength);
   2551   FXSYS_memcpy(lpDstBuf, lpSrcBuf, nLength);
   2552   bsDoRecord.ReleaseBuffer(nLength);
   2553 }
   2554 void CFDE_TxtEdtDoRecord_DeleteRange::Deserialize(
   2555     const CFX_ByteStringC& bsDoRecord) {
   2556   CFX_ArchiveLoader ArchiveLoader((const uint8_t*)bsDoRecord.GetCStr(),
   2557                                   bsDoRecord.GetLength());
   2558   int32_t nType = 0;
   2559   ArchiveLoader >> nType;
   2560   FXSYS_assert(nType == FDE_TXTEDT_DORECORD_DEL);
   2561   int32_t nEngine = 0;
   2562   ArchiveLoader >> nEngine;
   2563   m_pEngine = (CFDE_TxtEdtEngine*)(uintptr_t)nEngine;
   2564   int32_t iSel = 0;
   2565   ArchiveLoader >> iSel;
   2566   m_bSel = !!iSel;
   2567   ArchiveLoader >> m_nIndex;
   2568   ArchiveLoader >> m_nCaret;
   2569   ArchiveLoader >> m_wsRange;
   2570 }
   2571 #ifdef FDE_USEFORMATBLOCK
   2572 CFDE_TxtEdtDoRecord_FieldInsert::CFDE_TxtEdtDoRecord_FieldInsert(
   2573     const CFX_ByteStringC& bsDoRecord) {
   2574   Deserialize(bsDoRecord);
   2575 }
   2576 CFDE_TxtEdtDoRecord_FieldInsert::CFDE_TxtEdtDoRecord_FieldInsert(
   2577     CFDE_TxtEdtEngine* pEngine,
   2578     int32_t nCaret,
   2579     CFDE_TxtEdtField* pField,
   2580     int32_t nIndexInField,
   2581     int32_t nFieldBgn,
   2582     int32_t nOldFieldLength,
   2583     int32_t nNewFieldLength,
   2584     const CFX_WideString& wsIns,
   2585     FX_BOOL bSel)
   2586     : m_pEngine(pEngine),
   2587       m_nCaret(nCaret),
   2588       m_pField(pField),
   2589       m_nIndexInField(nIndexInField),
   2590       m_nFieldBgn(nFieldBgn),
   2591       m_nOldFieldLength(nOldFieldLength),
   2592       m_nNewFieldLength(nNewFieldLength),
   2593       m_wsIns(wsIns),
   2594       m_bSel(bSel) {
   2595   FXSYS_assert(pEngine);
   2596   FXSYS_assert(pField);
   2597 }
   2598 CFDE_TxtEdtDoRecord_FieldInsert::~CFDE_TxtEdtDoRecord_FieldInsert() {}
   2599 void CFDE_TxtEdtDoRecord_FieldInsert::Release() {
   2600   delete this;
   2601 }
   2602 FX_BOOL CFDE_TxtEdtDoRecord_FieldInsert::Undo() {
   2603   CFX_WideString wsDel;
   2604   int32_t nCaret = 0;
   2605   FX_BOOL bBefore = FALSE;
   2606   int32_t nRet = m_pField->Delete(m_nIndexInField, m_wsIns.GetLength(), wsDel,
   2607                                   nCaret, bBefore);
   2608   FXSYS_assert(nRet != FDE_FORMAT_FIELD_DELETE_RET_F_INVALIDATE &&
   2609                nRet != FDE_FORMAT_FIELD_DELETE_RET_F_BOUNDARY);
   2610   CFX_WideString wsDisplay;
   2611   m_pField->GetDisplayText(wsDisplay);
   2612   m_pEngine->Replace(m_nFieldBgn, m_nNewFieldLength, wsDisplay);
   2613   m_pEngine->SetCaretPos(m_nCaret, TRUE);
   2614   return TRUE;
   2615 }
   2616 FX_BOOL CFDE_TxtEdtDoRecord_FieldInsert::Redo() {
   2617   int32_t nCaret = 0;
   2618   FX_BOOL bBefore = FALSE;
   2619   int32_t nRet = m_pField->Insert(m_nIndexInField, m_wsIns, nCaret, bBefore);
   2620   FXSYS_assert(nRet != FDE_FORMAT_FIELD_INSERT_RET_F_FULL &&
   2621                nRet != FDE_FORMAT_FIELD_INSERT_RET_F_INVALIDATE);
   2622   CFX_WideString wsDisplay;
   2623   m_pField->GetDisplayText(wsDisplay);
   2624   m_pEngine->Replace(m_nFieldBgn, m_nOldFieldLength, wsDisplay);
   2625   m_pEngine->SetCaretPos(m_nCaret + m_wsIns.GetLength(), TRUE);
   2626   return TRUE;
   2627 }
   2628 void CFDE_TxtEdtDoRecord_FieldInsert::Serialize(
   2629     CFX_ByteString& bsDoRecord) const {
   2630   CFX_ArchiveSaver ArchiveSaver;
   2631   ArchiveSaver << int32_t(FDE_TXTEDT_DORECORD_FORMATINS);
   2632   ArchiveSaver << int32_t(m_pEngine);
   2633   ArchiveSaver << m_nCaret;
   2634   ArchiveSaver << int32_t(m_pField);
   2635   ArchiveSaver << m_nIndexInField;
   2636   ArchiveSaver << m_nFieldBgn;
   2637   ArchiveSaver << m_nOldFieldLength;
   2638   ArchiveSaver << m_nNewFieldLength;
   2639   ArchiveSaver << m_wsIns;
   2640   ArchiveSaver << m_bSel;
   2641   int32_t nLength = ArchiveSaver.GetLength();
   2642   const uint8_t* lpSrcBuf = ArchiveSaver.GetBuffer();
   2643   FX_CHAR* lpDstBuf = bsDoRecord.GetBuffer(nLength);
   2644   FXSYS_memcpy(lpDstBuf, lpSrcBuf, nLength);
   2645   bsDoRecord.ReleaseBuffer(nLength);
   2646 }
   2647 void CFDE_TxtEdtDoRecord_FieldInsert::Deserialize(
   2648     const CFX_ByteStringC& bsDoRecord) {
   2649   CFX_ArchiveLoader ArchiveLoader((const uint8_t*)bsDoRecord.GetCStr(),
   2650                                   bsDoRecord.GetLength());
   2651   int32_t nType = 0;
   2652   ArchiveLoader >> nType;
   2653   FXSYS_assert(nType == FDE_TXTEDT_DORECORD_FORMATINS);
   2654   int32_t nEngine = 0;
   2655   ArchiveLoader >> nEngine;
   2656   m_pEngine = (CFDE_TxtEdtEngine*)(uintptr_t)nEngine;
   2657   ArchiveLoader >> m_nCaret;
   2658   int32_t nField = 0;
   2659   ArchiveLoader >> nField;
   2660   m_pField = (CFDE_TxtEdtField*)nField;
   2661   ArchiveLoader >> m_nIndexInField;
   2662   ArchiveLoader >> m_nFieldBgn;
   2663   ArchiveLoader >> m_nOldFieldLength;
   2664   ArchiveLoader >> m_nNewFieldLength;
   2665   ArchiveLoader >> m_wsIns;
   2666   ArchiveLoader >> m_bSel;
   2667 }
   2668 CFDE_TxtEdtDoRecord_FieldDelete::CFDE_TxtEdtDoRecord_FieldDelete(
   2669     const CFX_ByteStringC& bsDoRecord) {
   2670   Deserialize(bsDoRecord);
   2671 }
   2672 CFDE_TxtEdtDoRecord_FieldDelete::CFDE_TxtEdtDoRecord_FieldDelete(
   2673     CFDE_TxtEdtEngine* pEngine,
   2674     int32_t nCaret,
   2675     CFDE_TxtEdtField* pField,
   2676     int32_t nIndexInField,
   2677     int32_t nFieldBgn,
   2678     int32_t nOldLength,
   2679     int32_t nNewLength,
   2680     const CFX_WideString& wsDel,
   2681     FX_BOOL bSel)
   2682     : m_pEngine(pEngine),
   2683       m_nCaret(nCaret),
   2684       m_pField(pField),
   2685       m_nIndexInField(nIndexInField),
   2686       m_nFieldBgn(nFieldBgn),
   2687       m_nOldFieldLength(nOldLength),
   2688       m_nNewFieldLength(nNewLength),
   2689       m_wsDel(wsDel),
   2690       m_bSel(bSel) {
   2691   FXSYS_assert(m_pEngine);
   2692   FXSYS_assert(m_pField);
   2693 }
   2694 CFDE_TxtEdtDoRecord_FieldDelete::~CFDE_TxtEdtDoRecord_FieldDelete() {}
   2695 void CFDE_TxtEdtDoRecord_FieldDelete::Release() {
   2696   delete this;
   2697 }
   2698 FX_BOOL CFDE_TxtEdtDoRecord_FieldDelete::Undo() {
   2699   int32_t nCaret = 0;
   2700   FX_BOOL bBefore = FALSE;
   2701   int32_t nRet = m_pField->Insert(m_nIndexInField, m_wsDel, nCaret, bBefore);
   2702   FXSYS_assert(nRet != FDE_FORMAT_FIELD_INSERT_RET_F_FULL &&
   2703                nRet != FDE_FORMAT_FIELD_INSERT_RET_F_INVALIDATE);
   2704   CFX_WideString wsDisplay;
   2705   m_pField->GetDisplayText(wsDisplay);
   2706   m_pEngine->Replace(m_nFieldBgn, m_nNewFieldLength, wsDisplay);
   2707   m_pEngine->SetCaretPos(m_nCaret, TRUE);
   2708   return TRUE;
   2709 }
   2710 FX_BOOL CFDE_TxtEdtDoRecord_FieldDelete::Redo() {
   2711   int32_t nCaret = 0;
   2712   FX_BOOL bBefore = 0;
   2713   CFX_WideString wsDel;
   2714   int32_t nRet = m_pField->Delete(m_nIndexInField, m_wsDel.GetLength(), wsDel,
   2715                                   nCaret, bBefore);
   2716   FXSYS_assert(nRet != FDE_FORMAT_FIELD_DELETE_RET_F_INVALIDATE &&
   2717                nRet != FDE_FORMAT_FIELD_DELETE_RET_F_BOUNDARY);
   2718   CFX_WideString wsDisplay;
   2719   m_pField->GetDisplayText(wsDisplay);
   2720   m_pEngine->Replace(m_nFieldBgn, m_nOldFieldLength, wsDisplay);
   2721   m_pEngine->SetCaretPos(m_nCaret - m_wsDel.GetLength(), TRUE);
   2722   return TRUE;
   2723 }
   2724 void CFDE_TxtEdtDoRecord_FieldDelete::Serialize(
   2725     CFX_ByteString& bsDoRecord) const {
   2726   CFX_ArchiveSaver ArchiveSaver;
   2727   ArchiveSaver << int32_t(FDE_TXTEDT_DORECORD_FORMATDEL);
   2728   ArchiveSaver << int32_t(m_pEngine);
   2729   ArchiveSaver << m_nCaret;
   2730   ArchiveSaver << int32_t(m_pField);
   2731   ArchiveSaver << m_nIndexInField;
   2732   ArchiveSaver << m_nFieldBgn;
   2733   ArchiveSaver << m_nOldFieldLength;
   2734   ArchiveSaver << m_nNewFieldLength;
   2735   ArchiveSaver << m_wsDel;
   2736   ArchiveSaver << m_bSel;
   2737   int32_t nLength = ArchiveSaver.GetLength();
   2738   const uint8_t* lpSrcBuf = ArchiveSaver.GetBuffer();
   2739   FX_CHAR* lpDstBuf = bsDoRecord.GetBuffer(nLength);
   2740   FXSYS_memcpy(lpDstBuf, lpSrcBuf, nLength);
   2741   bsDoRecord.ReleaseBuffer(nLength);
   2742 }
   2743 void CFDE_TxtEdtDoRecord_FieldDelete::Deserialize(
   2744     const CFX_ByteStringC& bsDoRecord) {
   2745   CFX_ArchiveLoader ArchiveLoader((const uint8_t*)bsDoRecord.GetCStr(),
   2746                                   bsDoRecord.GetLength());
   2747   int32_t nType = 0;
   2748   ArchiveLoader >> nType;
   2749   FXSYS_assert(nType == FDE_TXTEDT_DORECORD_FORMATDEL);
   2750   int32_t nEngine = 0;
   2751   ArchiveLoader >> nEngine;
   2752   m_pEngine = (CFDE_TxtEdtEngine*)(uintptr_t)nEngine;
   2753   ArchiveLoader >> m_nCaret;
   2754   int32_t nField = 0;
   2755   ArchiveLoader >> nField;
   2756   m_pField = (CFDE_TxtEdtField*)nField;
   2757   ArchiveLoader >> m_nIndexInField;
   2758   ArchiveLoader >> m_nFieldBgn;
   2759   ArchiveLoader >> m_nOldFieldLength;
   2760   ArchiveLoader >> m_nNewFieldLength;
   2761   ArchiveLoader >> m_wsDel;
   2762   ArchiveLoader >> m_bSel;
   2763 }
   2764 CFDE_TxtEdtDoRecord_FieldReplace::CFDE_TxtEdtDoRecord_FieldReplace(
   2765     const CFX_ByteStringC& bsDoRecord) {
   2766   Deserialize(bsDoRecord);
   2767 }
   2768 CFDE_TxtEdtDoRecord_FieldReplace::CFDE_TxtEdtDoRecord_FieldReplace(
   2769     CFDE_TxtEdtEngine* pEngine,
   2770     int32_t nCaret,
   2771     int32_t nNewCaret,
   2772     CFDE_TxtEdtField* pField,
   2773     int32_t nIndexInField,
   2774     int32_t nFieldBgn,
   2775     int32_t nFieldNewLength,
   2776     const CFX_WideString& wsDel,
   2777     const CFX_WideString& wsIns,
   2778     FX_BOOL bSel)
   2779     : m_pEngine(pEngine),
   2780       m_nCaret(nCaret),
   2781       m_nNewCaret(nNewCaret),
   2782       m_pField(pField),
   2783       m_nIndexInField(nIndexInField),
   2784       m_nFieldBgn(nFieldBgn),
   2785       m_nFieldNewLength(nFieldNewLength),
   2786       m_wsDel(wsDel),
   2787       m_wsIns(wsIns),
   2788       m_bSel(bSel) {
   2789   FXSYS_assert(m_pEngine);
   2790   FXSYS_assert(m_pField);
   2791 }
   2792 CFDE_TxtEdtDoRecord_FieldReplace::~CFDE_TxtEdtDoRecord_FieldReplace() {}
   2793 void CFDE_TxtEdtDoRecord_FieldReplace::Release() {
   2794   delete this;
   2795 }
   2796 FX_BOOL CFDE_TxtEdtDoRecord_FieldReplace::Undo() {
   2797   CFX_WideString wsDel;
   2798   int32_t nCaret = 0;
   2799   FX_BOOL bBefore = FALSE;
   2800   int32_t nRet = m_pField->Replace(m_nIndexInField, m_wsIns.GetLength(),
   2801                                    m_wsDel, wsDel, nCaret, bBefore);
   2802   FXSYS_assert(nRet != FDE_FORMAT_FIELD_DELETE_RET_F_INVALIDATE &&
   2803                nRet != FDE_FORMAT_FIELD_DELETE_RET_F_BOUNDARY);
   2804   CFX_WideString wsDisplay;
   2805   m_pField->GetDisplayText(wsDisplay);
   2806   m_pEngine->Replace(m_nFieldBgn, m_nFieldNewLength, wsDisplay);
   2807   m_pEngine->SetCaretPos(m_nCaret, TRUE);
   2808   return TRUE;
   2809 }
   2810 FX_BOOL CFDE_TxtEdtDoRecord_FieldReplace::Redo() {
   2811   CFX_WideString wsDel;
   2812   int32_t nCaret = 0;
   2813   FX_BOOL bBefore = FALSE;
   2814   int32_t nRet = m_pField->Replace(m_nIndexInField, m_wsDel.GetLength(),
   2815                                    m_wsIns, wsDel, nCaret, bBefore);
   2816   FXSYS_assert(nRet != FDE_FORMAT_FIELD_DELETE_RET_F_INVALIDATE &&
   2817                nRet != FDE_FORMAT_FIELD_DELETE_RET_F_BOUNDARY);
   2818   CFX_WideString wsDisplay;
   2819   m_pField->GetDisplayText(wsDisplay);
   2820   m_pEngine->Replace(m_nFieldBgn, m_nFieldNewLength, wsDisplay);
   2821   m_pEngine->SetCaretPos(m_nNewCaret, TRUE);
   2822   return TRUE;
   2823 }
   2824 void CFDE_TxtEdtDoRecord_FieldReplace::Serialize(
   2825     CFX_ByteString& bsDoRecord) const {
   2826   CFX_ArchiveSaver ArchiveSaver;
   2827   ArchiveSaver << int32_t(FDE_TXTEDT_DORECORD_FORMATREP);
   2828   ArchiveSaver << int32_t(m_pEngine);
   2829   ArchiveSaver << m_nCaret;
   2830   ArchiveSaver << m_nNewCaret;
   2831   ArchiveSaver << int32_t(m_pField);
   2832   ArchiveSaver << m_nIndexInField;
   2833   ArchiveSaver << m_nFieldBgn;
   2834   ArchiveSaver << m_nFieldNewLength;
   2835   ArchiveSaver << m_wsDel;
   2836   ArchiveSaver << m_wsIns;
   2837   ArchiveSaver << m_bSel;
   2838   int32_t nLength = ArchiveSaver.GetLength();
   2839   const uint8_t* lpSrcBuf = ArchiveSaver.GetBuffer();
   2840   FX_CHAR* lpDstBuf = bsDoRecord.GetBuffer(nLength);
   2841   FXSYS_memcpy(lpDstBuf, lpSrcBuf, nLength);
   2842   bsDoRecord.ReleaseBuffer(nLength);
   2843 }
   2844 void CFDE_TxtEdtDoRecord_FieldReplace::Deserialize(
   2845     const CFX_ByteStringC& bsDoRecord) {
   2846   CFX_ArchiveLoader ArchiveLoader((const uint8_t*)bsDoRecord.GetCStr(),
   2847                                   bsDoRecord.GetLength());
   2848   int32_t nType = 0;
   2849   ArchiveLoader >> nType;
   2850   FXSYS_assert(nType == FDE_TXTEDT_DORECORD_FORMATREP);
   2851   int32_t nEngine = 0;
   2852   ArchiveLoader >> nEngine;
   2853   m_pEngine = (CFDE_TxtEdtEngine*)(uintptr_t)nEngine;
   2854   ArchiveLoader >> m_nCaret;
   2855   ArchiveLoader >> m_nNewCaret;
   2856   int32_t nField = 0;
   2857   ArchiveLoader >> nField;
   2858   m_pField = (CFDE_TxtEdtField*)nField;
   2859   ArchiveLoader >> m_nIndexInField;
   2860   ArchiveLoader >> m_nFieldBgn;
   2861   ArchiveLoader >> m_nFieldNewLength;
   2862   ArchiveLoader >> m_wsDel;
   2863   ArchiveLoader >> m_wsIns;
   2864   ArchiveLoader >> m_bSel;
   2865 }
   2866 #endif
   2867