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
31IFDE_TxtEdtEngine* IFDE_TxtEdtEngine::Create() {
32  return new CFDE_TxtEdtEngine();
33}
34CFDE_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}
58CFDE_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}
83void CFDE_TxtEdtEngine::Release() {
84  delete this;
85}
86void 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}
95const FDE_TXTEDTPARAMS* CFDE_TxtEdtEngine::GetEditParams() const {
96  return &m_Param;
97}
98int32_t CFDE_TxtEdtEngine::CountPages() const {
99  if (m_nLineCount == 0) {
100    return 0;
101  }
102  return ((m_nLineCount - 1) / m_nPageLineCount) + 1;
103}
104IFDE_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}
110FX_BOOL CFDE_TxtEdtEngine::SetBufChunkSize(int32_t nChunkSize) {
111  return m_pTxtBuf->SetChunkSize(nChunkSize);
112}
113void 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}
142void 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}
160int32_t CFDE_TxtEdtEngine::GetTextLength() const {
161  return GetTextBufLength();
162}
163void 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}
216void CFDE_TxtEdtEngine::ClearText() {
217  DeleteRange(0, -1);
218}
219int32_t CFDE_TxtEdtEngine::GetCaretRect(CFX_RectF& rtCaret) const {
220  rtCaret = m_rtCaret;
221  return m_nCaret;
222}
223int32_t CFDE_TxtEdtEngine::GetCaretPos() const {
224  if (IsLocked()) {
225    return 0;
226  }
227  return m_nCaret + (m_bBefore ? 0 : 1);
228}
229int32_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}
257int32_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}
403void CFDE_TxtEdtEngine::Lock() {
404  m_bLock = TRUE;
405}
406void CFDE_TxtEdtEngine::Unlock() {
407  m_bLock = FALSE;
408}
409FX_BOOL CFDE_TxtEdtEngine::IsLocked() const {
410  return m_bLock;
411}
412int32_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}
657int32_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}
767int32_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}
789int32_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}
832void CFDE_TxtEdtEngine::SetLimit(int32_t nLimit) {
833  m_nLimit = nLimit;
834}
835void CFDE_TxtEdtEngine::SetAliasChar(FX_WCHAR wcAlias) {
836  m_wcAliasChar = wcAlias;
837}
838void 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}
887int32_t CFDE_TxtEdtEngine::CountEditBlocks() const {
888#ifdef FDE_USEFORMATBLOCK
889  return m_BlockArray.GetSize();
890#else
891  return 0;
892#endif
893}
894void 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}
901int32_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}
909void 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}
917void CFDE_TxtEdtEngine::StartEdit() {
918#ifdef FDE_USEFORMATBLOCK
919#endif
920}
921void CFDE_TxtEdtEngine::EndEdit() {
922#ifdef FDE_USEFORMATBLOCK
923#endif
924}
925void 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}
939void 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}
1008int32_t CFDE_TxtEdtEngine::CountSelRanges() {
1009  return m_SelRangePtrArr.GetSize();
1010}
1011int32_t CFDE_TxtEdtEngine::GetSelRange(int32_t nIndex, int32_t& nStart) {
1012  nStart = m_SelRangePtrArr[nIndex]->nStart;
1013  return m_SelRangePtrArr[nIndex]->nCount;
1014}
1015void 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}
1031FX_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}
1047FX_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}
1063int32_t CFDE_TxtEdtEngine::StartLayout() {
1064  Lock();
1065  RemoveAllPages();
1066  m_nLayoutPos = 0;
1067  m_nLineCount = 0;
1068  return 0;
1069}
1070int32_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}
1087void 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}
1100FX_BOOL CFDE_TxtEdtEngine::Optimize(IFX_Pause* pPause) {
1101  return m_pTxtBuf->Optimize(pPause);
1102}
1103IFDE_TxtEdtBuf* CFDE_TxtEdtEngine::GetTextBuf() const {
1104  return (IFDE_TxtEdtBuf*)m_pTxtBuf;
1105}
1106int32_t CFDE_TxtEdtEngine::GetTextBufLength() const {
1107  return m_pTxtBuf->GetTextLength() - 1;
1108}
1109IFX_TxtBreak* CFDE_TxtEdtEngine::GetTextBreak() const {
1110  return m_pTextBreak;
1111}
1112int32_t CFDE_TxtEdtEngine::GetLineCount() const {
1113  return m_nLineCount;
1114}
1115int32_t CFDE_TxtEdtEngine::GetPageLineCount() const {
1116  return m_nPageLineCount;
1117}
1118int32_t CFDE_TxtEdtEngine::CountParags() const {
1119  return m_ParagPtrArray.GetSize();
1120}
1121IFDE_TxtEdtParag* CFDE_TxtEdtEngine::GetParag(int32_t nParagIndex) const {
1122  return m_ParagPtrArray[nParagIndex];
1123}
1124IFX_CharIter* CFDE_TxtEdtEngine::CreateCharIter() {
1125  if (!m_pTxtBuf) {
1126    return NULL;
1127  }
1128  return new CFDE_TxtEdtBufIter((CFDE_TxtEdtBuf*)m_pTxtBuf);
1129}
1130int32_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}
1148void 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}
1154void 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}
1178void 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}
1197void 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
1261void 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
1315void 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}
1370void 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}
1397void CFDE_TxtEdtEngine::ResetEngine() {
1398  RemoveAllPages();
1399  RemoveAllParags();
1400  ClearSelection();
1401  m_nCaret = 0;
1402  m_pTxtBuf->Clear(FALSE);
1403  m_nCaret = 0;
1404}
1405void 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}
1426void 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}
1437void 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}
1448void 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}
1465void 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}
1498void 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}
1592FX_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}
1635void 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}
1680int32_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}
1722void 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}
1749int32_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}
1763int32_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}
1776FX_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}
1820FX_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}
1864FX_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}
1884FX_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}
1920FX_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}
1928FX_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}
1945FX_BOOL CFDE_TxtEdtEngine::MoveHome() {
1946  UpdateCaretRect(0, TRUE);
1947  return TRUE;
1948}
1949FX_BOOL CFDE_TxtEdtEngine::MoveEnd() {
1950  UpdateCaretRect(GetTextBufLength(), TRUE);
1951  return TRUE;
1952}
1953#ifdef FDE_USEFORMATBLOCK
1954int32_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}
2061FX_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}
2107FX_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}
2161FX_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}
2187int32_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
2232FX_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}
2264void 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}
2278void 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}
2312void 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}
2324FX_BOOL CFDE_TxtEdtEngine::IsSelect() {
2325  return m_SelRangePtrArr.GetSize() > 0;
2326}
2327void 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}
2404IFDE_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}
2426CFDE_TxtEdtDoRecord_Insert::CFDE_TxtEdtDoRecord_Insert(
2427    const CFX_ByteStringC& bsDoRecord) {
2428  Deserialize(bsDoRecord);
2429}
2430CFDE_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}
2441CFDE_TxtEdtDoRecord_Insert::~CFDE_TxtEdtDoRecord_Insert() {}
2442void CFDE_TxtEdtDoRecord_Insert::Release() {
2443  delete this;
2444}
2445FX_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}
2457FX_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}
2466void 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}
2478void 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}
2491CFDE_TxtEdtDoRecord_DeleteRange::CFDE_TxtEdtDoRecord_DeleteRange(
2492    const CFX_ByteStringC& bsDoRecord) {
2493  Deserialize(bsDoRecord);
2494}
2495CFDE_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}
2508CFDE_TxtEdtDoRecord_DeleteRange::~CFDE_TxtEdtDoRecord_DeleteRange() {}
2509void CFDE_TxtEdtDoRecord_DeleteRange::Release() {
2510  delete this;
2511}
2512FX_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}
2527FX_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}
2539void 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}
2554void 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
2572CFDE_TxtEdtDoRecord_FieldInsert::CFDE_TxtEdtDoRecord_FieldInsert(
2573    const CFX_ByteStringC& bsDoRecord) {
2574  Deserialize(bsDoRecord);
2575}
2576CFDE_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}
2598CFDE_TxtEdtDoRecord_FieldInsert::~CFDE_TxtEdtDoRecord_FieldInsert() {}
2599void CFDE_TxtEdtDoRecord_FieldInsert::Release() {
2600  delete this;
2601}
2602FX_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}
2616FX_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}
2628void 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}
2647void 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}
2668CFDE_TxtEdtDoRecord_FieldDelete::CFDE_TxtEdtDoRecord_FieldDelete(
2669    const CFX_ByteStringC& bsDoRecord) {
2670  Deserialize(bsDoRecord);
2671}
2672CFDE_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}
2694CFDE_TxtEdtDoRecord_FieldDelete::~CFDE_TxtEdtDoRecord_FieldDelete() {}
2695void CFDE_TxtEdtDoRecord_FieldDelete::Release() {
2696  delete this;
2697}
2698FX_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}
2710FX_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}
2724void 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}
2743void 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}
2764CFDE_TxtEdtDoRecord_FieldReplace::CFDE_TxtEdtDoRecord_FieldReplace(
2765    const CFX_ByteStringC& bsDoRecord) {
2766  Deserialize(bsDoRecord);
2767}
2768CFDE_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}
2792CFDE_TxtEdtDoRecord_FieldReplace::~CFDE_TxtEdtDoRecord_FieldReplace() {}
2793void CFDE_TxtEdtDoRecord_FieldReplace::Release() {
2794  delete this;
2795}
2796FX_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}
2810FX_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}
2824void 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}
2844void 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