// Copyright 2014 PDFium Authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. // Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com #include #include "xfa/src/foxitlib.h" #include "xfa/src/fee/include/ifde_txtedtengine.h" #include "xfa/src/fee/include/ifde_txtedtbuf.h" #include "xfa/src/fee/include/ifde_txtedtpage.h" #include "fde_txtedtengine.h" #include "fde_txtedtparag.h" #include "fde_txtedtbuf.h" #ifdef FDE_USEFORMATBLOCK #include "fde_txtedtblock.h" #endif #define FDE_PAGEWIDTH_MAX 0xFFFF #define FDE_TXTPLATESIZE (1024 * 12) #define FDE_UNICODE_PARAGRAPH_SPERATOR (0x2029) #define FDE_TXTEDT_DORECORD_INS 0 #define FDE_TXTEDT_DORECORD_DEL 1 #ifdef FDE_USEFORMATBLOCK #define FDE_TXTEDT_DORECORD_FORMATINS 3 #define FDE_TXTEDT_DORECORD_FORMATDEL 4 #define FDE_TXTEDT_DORECORD_FORMATREP 5 #define FDE_TXTEDT_FORMATBLOCK_BGN 0xFFF9 #define FDE_TXTEDT_FORMATBLOCK_END 0xFFFB #endif IFDE_TxtEdtEngine* IFDE_TxtEdtEngine::Create() { return new CFDE_TxtEdtEngine(); } CFDE_TxtEdtEngine::CFDE_TxtEdtEngine() : m_pTextBreak(nullptr), m_nPageLineCount(20), m_nLineCount(0), m_nAnchorPos(-1), m_nLayoutPos(0), m_fCaretPosReserve(0.0), m_nCaret(0), m_bBefore(TRUE), m_nCaretPage(0), m_dwFindFlags(0), m_bLock(FALSE), m_nLimit(0), m_wcAliasChar(L'*'), #ifdef FDE_USEFORMATBLOCK m_nFixLength(-1), // FIXME: no such member => USEFORMATBLOCK can't work. #endif m_nFirstLineEnd(FDE_TXTEDIT_LINEEND_Auto), m_bAutoLineEnd(TRUE), m_wLineEnd(FDE_UNICODE_PARAGRAPH_SPERATOR) { FXSYS_memset(&m_rtCaret, 0, sizeof(CFX_RectF)); m_pTxtBuf = new CFDE_TxtEdtBuf(); m_bAutoLineEnd = (m_Param.nLineEnd == FDE_TXTEDIT_LINEEND_Auto); } CFDE_TxtEdtEngine::~CFDE_TxtEdtEngine() { if (m_pTxtBuf) { m_pTxtBuf->Release(); m_pTxtBuf = NULL; } if (m_pTextBreak) { m_pTextBreak->Release(); m_pTextBreak = NULL; } #ifdef FDE_USEFORMATBLOCK int32_t nBlockCount = m_BlockArray.GetSize(); if (nBlockCount > 0) { int32_t i = 0; for (; i < nBlockCount; i++) { CFDE_TxtEdtBlock* pBlock = m_BlockArray[i]; delete pBlock; } m_BlockArray.RemoveAll(); } #endif RemoveAllParags(); RemoveAllPages(); m_Param.pEventSink = NULL; ClearSelection(); } void CFDE_TxtEdtEngine::Release() { delete this; } void CFDE_TxtEdtEngine::SetEditParams(const FDE_TXTEDTPARAMS& params) { if (m_pTextBreak == NULL) { m_pTextBreak = IFX_TxtBreak::Create(FX_TXTBREAKPOLICY_None); } FXSYS_memcpy(&m_Param, ¶ms, sizeof(FDE_TXTEDTPARAMS)); m_wLineEnd = params.wLineBreakChar; m_bAutoLineEnd = (m_Param.nLineEnd == FDE_TXTEDIT_LINEEND_Auto); UpdateTxtBreak(); } const FDE_TXTEDTPARAMS* CFDE_TxtEdtEngine::GetEditParams() const { return &m_Param; } int32_t CFDE_TxtEdtEngine::CountPages() const { if (m_nLineCount == 0) { return 0; } return ((m_nLineCount - 1) / m_nPageLineCount) + 1; } IFDE_TxtEdtPage* CFDE_TxtEdtEngine::GetPage(int32_t nIndex) { if (m_PagePtrArray.GetSize() <= nIndex) { return NULL; } return (IFDE_TxtEdtPage*)m_PagePtrArray[nIndex]; } FX_BOOL CFDE_TxtEdtEngine::SetBufChunkSize(int32_t nChunkSize) { return m_pTxtBuf->SetChunkSize(nChunkSize); } void CFDE_TxtEdtEngine::SetTextByStream(IFX_Stream* pStream) { ResetEngine(); int32_t nIndex = 0; if (pStream != NULL && pStream->GetLength()) { int32_t nStreamLength = pStream->GetLength(); FX_BOOL bValid = TRUE; if (m_nLimit > 0 && nStreamLength > m_nLimit) { bValid = FALSE; } FX_BOOL bPreIsCR = FALSE; if (bValid) { uint8_t bom[4]; int32_t nPos = pStream->GetBOM(bom); pStream->Seek(FX_STREAMSEEK_Begin, nPos); int32_t nPlateSize = std::min(nStreamLength, m_pTxtBuf->GetChunkSize()); FX_WCHAR* lpwstr = FX_Alloc(FX_WCHAR, nPlateSize); FX_BOOL bEos = false; while (!bEos) { int32_t nRead = pStream->ReadString(lpwstr, nPlateSize, bEos); bPreIsCR = ReplaceParagEnd(lpwstr, nRead, bPreIsCR); m_pTxtBuf->Insert(nIndex, lpwstr, nRead); nIndex += nRead; } FX_Free(lpwstr); } } m_pTxtBuf->Insert(nIndex, &m_wLineEnd, 1); RebuildParagraphs(); } void CFDE_TxtEdtEngine::SetText(const CFX_WideString& wsText) { ResetEngine(); int32_t nLength = wsText.GetLength(); if (nLength > 0) { CFX_WideString wsTemp; FX_WCHAR* lpBuffer = wsTemp.GetBuffer(nLength); FXSYS_memcpy(lpBuffer, wsText.c_str(), nLength * sizeof(FX_WCHAR)); ReplaceParagEnd(lpBuffer, nLength, FALSE); wsTemp.ReleaseBuffer(nLength); if (m_nLimit > 0 && nLength > m_nLimit) { wsTemp.Delete(m_nLimit, nLength - m_nLimit); nLength = m_nLimit; } m_pTxtBuf->SetText(wsTemp); } m_pTxtBuf->Insert(nLength, &m_wLineEnd, 1); RebuildParagraphs(); } int32_t CFDE_TxtEdtEngine::GetTextLength() const { return GetTextBufLength(); } void CFDE_TxtEdtEngine::GetText(CFX_WideString& wsText, int32_t nStart, int32_t nCount) { int32_t nTextBufLength = GetTextBufLength(); if (nCount == -1) { nCount = nTextBufLength - nStart; } #ifdef FDE_USEFORMATBLOCK int32_t nBlockCount = m_BlockArray.GetSize(); if (nBlockCount == 0 || m_wsFixText.IsEmpty()) { m_pTxtBuf->GetRange(wsText, nStart, nCount); return; } CFX_WideString wsTemp; const FX_WCHAR* lpFixBuffer = const FX_WCHAR * (m_wsFixText); FX_WCHAR* lpBuffer = wsTemp.GetBuffer(nTextBufLength); int32_t nRealLength = 0; int32_t nPrePos = 0; for (int32_t i = 0; i < nBlockCount; i++) { CFDE_TxtEdtBlock* pBlock = m_BlockArray[i]; int32_t nPos = pBlock->GetPos(); int32_t nCopyLength = nPos - nPrePos; FXSYS_memcpy(lpBuffer + nRealLength, lpFixBuffer + nPrePos, nCopyLength * sizeof(FX_WCHAR)); nRealLength += nCopyLength; nPrePos = nPos; CFX_WideString wsBlock; pBlock->GetRealText(wsBlock); nCopyLength = wsBlock.GetLength(); FXSYS_memcpy(lpBuffer + nRealLength, const FX_WCHAR*(wsBlock), nCopyLength * sizeof(FX_WCHAR)); nRealLength += nCopyLength; } int32_t nLeftLength = m_wsFixText.GetLength() - nPrePos; if (nLeftLength > 0) { FXSYS_memcpy(lpBuffer + nRealLength, lpFixBuffer + nPrePos, nLeftLength * sizeof(FX_WCHAR)); nRealLength += nLeftLength; } wsTemp.ReleaseBuffer(nRealLength); int32_t nRealBgn = GetRealIndex(nStart); int32_t nRealEnd = GetRealIndex(nStart + nCount - 1); int32_t nRealCount = nRealEnd - nRealBgn; FX_WCHAR* lpDestBuf = wsText.GetBuffer(nRealCount); FXSYS_memcpy(lpDestBuf, const FX_WCHAR*(wsTemp) + nRealBgn, nRealCount * sizeof(FX_WCHAR)); wsText.ReleaseBuffer(); #else m_pTxtBuf->GetRange(wsText, nStart, nCount); RecoverParagEnd(wsText); #endif } void CFDE_TxtEdtEngine::ClearText() { DeleteRange(0, -1); } int32_t CFDE_TxtEdtEngine::GetCaretRect(CFX_RectF& rtCaret) const { rtCaret = m_rtCaret; return m_nCaret; } int32_t CFDE_TxtEdtEngine::GetCaretPos() const { if (IsLocked()) { return 0; } return m_nCaret + (m_bBefore ? 0 : 1); } int32_t CFDE_TxtEdtEngine::SetCaretPos(int32_t nIndex, FX_BOOL bBefore) { if (IsLocked()) { return 0; } FXSYS_assert(nIndex >= 0 && nIndex <= GetTextBufLength()); if (m_PagePtrArray.GetSize() <= m_nCaretPage) { return 0; } #ifdef FDE_USEFORMATBLOCK if (m_BlockArray.GetSize() > 0) { nIndex = NormalizeCaretPos(nIndex, FDE_FORMAT_CARET_MIDDLE, bBefore); } #endif m_bBefore = bBefore; m_nCaret = nIndex; MovePage2Char(m_nCaret); GetCaretRect(m_rtCaret, m_nCaretPage, m_nCaret, m_bBefore); if (!m_bBefore) { m_nCaret++; m_bBefore = TRUE; } m_fCaretPosReserve = (m_Param.dwLayoutStyles & FDE_TEXTEDITLAYOUT_DocVertical) ? m_rtCaret.top : m_rtCaret.left; m_Param.pEventSink->On_CaretChanged(this, m_nCaretPage, 0); m_nAnchorPos = -1; return m_nCaret; } int32_t CFDE_TxtEdtEngine::MoveCaretPos(FDE_TXTEDTMOVECARET eMoveCaret, FX_BOOL bShift, FX_BOOL bCtrl) { if (IsLocked()) { return 0; } if (m_PagePtrArray.GetSize() <= m_nCaretPage) { return 0; } FX_BOOL bSelChange = FALSE; if (IsSelect()) { ClearSelection(); bSelChange = TRUE; } if (bShift) { if (m_nAnchorPos == -1) { m_nAnchorPos = m_nCaret; } } else { m_nAnchorPos = -1; } FX_BOOL bVertical = m_Param.dwLayoutStyles & FDE_TEXTEDITLAYOUT_DocVertical; switch (eMoveCaret) { case MC_Left: { if (bVertical) { CFX_PointF ptCaret; if (MoveUp(ptCaret)) { UpdateCaretIndex(ptCaret); } } else { FX_BOOL bBefore = TRUE; int32_t nIndex = MoveBackward(bBefore); #ifdef FDE_USEFORMATBLOCK if (m_BlockArray.GetSize()) { nIndex = NormalizeCaretPos(nIndex, FDE_FORMAT_CARET_BACKWARD, bBefore); if (nIndex < 0) { return m_nCaret; } } #endif if (nIndex >= 0) { UpdateCaretRect(nIndex, bBefore); } } } break; case MC_Right: { if (bVertical) { CFX_PointF ptCaret; if (MoveDown(ptCaret)) { UpdateCaretIndex(ptCaret); } } else { FX_BOOL bBefore = TRUE; int32_t nIndex = MoveForward(bBefore); #ifdef FDE_USEFORMATBLOCK if (m_BlockArray.GetSize()) { if (nIndex == -1) { nIndex = GetTextBufLength(); } nIndex = NormalizeCaretPos(nIndex, FDE_FORMAT_CARET_FORWARD, bBefore); } #endif if (nIndex >= 0) { UpdateCaretRect(nIndex, bBefore); } } } break; case MC_Up: { if (bVertical) { FX_BOOL bBefore = TRUE; int32_t nIndex = MoveBackward(bBefore); #ifdef FDE_USEFORMATBLOCK if (m_BlockArray.GetSize()) { nIndex = NormalizeCaretPos(nIndex, FDE_FORMAT_CARET_BACKWARD, bBefore); } #endif if (nIndex >= 0) { UpdateCaretRect(nIndex, bBefore); } } else { CFX_PointF ptCaret; if (MoveUp(ptCaret)) { UpdateCaretIndex(ptCaret); } } } break; case MC_Down: { if (bVertical) { FX_BOOL bBefore = TRUE; int32_t nIndex = MoveForward(bBefore); #ifdef FDE_USEFORMATBLOCK if (m_BlockArray.GetSize()) { nIndex = NormalizeCaretPos(nIndex, FDE_FORMAT_CARET_FORWARD, bBefore); } #endif if (nIndex >= 0) { UpdateCaretRect(nIndex, bBefore); } } else { CFX_PointF ptCaret; if (MoveDown(ptCaret)) { UpdateCaretIndex(ptCaret); } } } break; case MC_WordBackward: break; case MC_WordForward: break; case MC_LineStart: MoveLineStart(); break; case MC_LineEnd: MoveLineEnd(); break; case MC_ParagStart: MoveParagStart(); break; case MC_ParagEnd: MoveParagEnd(); break; case MC_PageDown: break; case MC_PageUp: break; case MC_Home: MoveHome(); break; case MC_End: MoveEnd(); break; default: break; } if (bShift && m_nAnchorPos != -1 && (m_nAnchorPos != m_nCaret)) { AddSelRange(std::min(m_nAnchorPos, m_nCaret), FXSYS_abs(m_nAnchorPos - m_nCaret)); m_Param.pEventSink->On_SelChanged(this); } if (bSelChange) { m_Param.pEventSink->On_SelChanged(this); } return m_nCaret; } void CFDE_TxtEdtEngine::Lock() { m_bLock = TRUE; } void CFDE_TxtEdtEngine::Unlock() { m_bLock = FALSE; } FX_BOOL CFDE_TxtEdtEngine::IsLocked() const { return m_bLock; } int32_t CFDE_TxtEdtEngine::Insert(int32_t nStart, const FX_WCHAR* lpText, int32_t nLength) { if (IsLocked()) { return FDE_TXTEDT_MODIFY_RET_F_Locked; } #ifdef FDE_USEFORMATBLOCK int32_t nBlockCount = m_BlockArray.GetSize(); if (nBlockCount) { if (m_Param.dwMode & FDE_TEXTEDITMODE_FIELD_TAB && nLength == 1 && lpText[0] == L'\t') { return Move2NextEditableField(nStart) ? FDE_TXTEDT_MODIFY_RET_T_Tab : FDE_TXTEDT_MODIFY_RET_F_Tab; } int32_t nSelRangeCount = CountSelRanges(); if (nSelRangeCount > 0) { if (nSelRangeCount > 1) { return FDE_TXTEDT_MODIFY_RET_F_Boundary; } int32_t nSelStart; int32_t nSelCount; nSelCount = GetSelRange(0, nSelStart); int32_t nSelEnd = nSelStart + nSelCount; int32_t nBgn = 0; int32_t nEnd = 0; CFDE_TxtEdtField* pField = NULL; FX_BOOL bInField = GetFieldBoundary(nSelStart, nBgn, nEnd, pField); if (nSelEnd > nEnd) { return FDE_TXTEDT_MODIFY_RET_F_Boundary; } if (bInField) { pField->Backup(); FX_BOOL bBefore = FALSE; CFX_WideString wsDel; int32_t nCaret; int32_t nIndexInField = nSelStart - nBgn; int32_t nRet = pField->Replace(nSelStart - nBgn, nSelCount, CFX_WideStringC(lpText, nLength), wsDel, nCaret, bBefore); switch (nRet) { case FDE_FORMAT_FIELD_INSERT_RET_F_FULL: pField->Restore(); return FDE_TXTEDT_MODIFY_RET_F_Full; case FDE_FORMAT_FIELD_INSERT_RET_F_INVALIDATE: pField->Restore(); return FDE_TXTEDT_MODIFY_RET_F_Invalidate; default: break; } CFX_WideString wsField; pField->GetFieldText(wsField); if (!m_Param.pEventSink->On_ValidateField(this, pField->GetBlockIndex(), pField->GetIndex(), wsField, 0)) { pField->Restore(); return FDE_TXTEDT_MODIFY_RET_F_Invalidate; } CFX_WideString wsDisplay; pField->GetDisplayText(wsDisplay); if ((m_Param.dwMode & FDE_TEXTEDITMODE_LimitArea_Vert) || (m_Param.dwMode & FDE_TEXTEDITMODE_LimitArea_Horz)) { CFX_WideString wsText; GetPreReplaceText(wsText, nBgn, nEnd - nBgn + 1, const FX_WCHAR*(wsDisplay), wsDisplay.GetLength()); if (!IsFitArea(wsText)) { pField->Restore(); return FDE_TXTEDT_MODIFY_RET_F_Full; } } Replace(nBgn, nEnd - nBgn + 1, wsDisplay); int32_t nNewCaret = nBgn + nCaret; if (!(m_Param.dwMode & FDE_TEXTEDITMODE_NoRedoUndo)) { IFDE_TxtEdtDoRecord* pRecord = new CFDE_TxtEdtDoRecord_FieldReplace( this, m_nCaret, nNewCaret, pField, nIndexInField, nBgn, wsDisplay.GetLength(), wsDel, CFX_WideStringC(lpText, nLength), TRUE); CFX_ByteString bsDoRecord; pRecord->Serialize(bsDoRecord); m_Param.pEventSink->On_AddDoRecord(this, bsDoRecord); pRecord->Release(); } SetCaretPos(nBgn + nCaret, bBefore); return FDE_TXTEDT_MODIFY_RET_S_Normal; } } int32_t nBgn = 0; int32_t nEnd = 0; CFDE_TxtEdtField* pField = NULL; FX_BOOL bInField = GetFieldBoundary(m_nCaret, nBgn, nEnd, pField); int32_t nCaretInField = m_nCaret - nBgn; FX_BOOL bBefore = FALSE; if (bInField) { pField->Backup(); CFX_WideStringC wsIns(lpText, nLength); int32_t nRet = pField->Insert(nCaretInField, wsIns, nCaretInField, bBefore); FX_BOOL bFull = FALSE; switch (nRet) { case FDE_FORMAT_FIELD_INSERT_RET_S_NORMAL: break; case FDE_FORMAT_FIELD_INSERT_RET_S_FULL: bFull = TRUE; break; case FDE_FORMAT_FIELD_INSERT_RET_F_FULL: return FDE_TXTEDT_MODIFY_RET_F_Full; case FDE_FORMAT_FIELD_INSERT_RET_F_INVALIDATE: return FDE_TXTEDT_MODIFY_RET_F_Invalidate; default: return FDE_TXTEDT_MODIFY_RET_F_Normal; } CFX_WideString wsField; pField->GetFieldText(wsField); if (!m_Param.pEventSink->On_ValidateField( this, pField->GetBlockIndex(), pField->GetIndex(), wsField, 0)) { pField->Restore(); return FDE_TXTEDT_MODIFY_RET_F_Invalidate; } CFX_WideString wsDisplay; pField->GetDisplayText(wsDisplay); if ((m_Param.dwMode & FDE_TEXTEDITMODE_LimitArea_Vert) || (m_Param.dwMode & FDE_TEXTEDITMODE_LimitArea_Horz)) { CFX_WideString wsText; GetPreReplaceText(wsText, nBgn, nEnd - nBgn + 1, const FX_WCHAR*(wsDisplay), wsDisplay.GetLength()); if (!IsFitArea(wsText)) { pField->Restore(); return FDE_TXTEDT_MODIFY_RET_F_Full; } } Replace(nBgn, nEnd - nBgn + 1, wsDisplay); if (!(m_Param.dwMode & FDE_TEXTEDITMODE_NoRedoUndo)) { IFDE_TxtEdtDoRecord* pRecord = new CFDE_TxtEdtDoRecord_FieldInsert( this, m_nCaret, pField, m_nCaret - nBgn, nBgn, nEnd - nBgn + 1, wsDisplay.GetLength(), CFX_WideStringC(lpText, nLength), FALSE); CFX_ByteString bsDoRecord; pRecord->Serialize(bsDoRecord); m_Param.pEventSink->On_AddDoRecord(this, bsDoRecord); pRecord->Release(); } int32_t nCaretPos = nBgn + nCaretInField; if (m_Param.dwMode & FDE_TEXTEDITMODE_FIELD_AUTO && bFull && nCaretPos == nEnd) { if (Move2NextEditableField(nEnd, TRUE, FALSE)) { return TRUE; } } SetCaretPos(nCaretPos, bBefore); return bFull ? FDE_TXTEDT_MODIFY_RET_S_Full : FDE_TXTEDT_MODIFY_RET_S_Normal; } FXSYS_assert(0); return FDE_TXTEDT_MODIFY_RET_F_Normal; } #endif CFX_WideString wsTemp; FX_WCHAR* lpBuffer = wsTemp.GetBuffer(nLength); FXSYS_memcpy(lpBuffer, lpText, nLength * sizeof(FX_WCHAR)); ReplaceParagEnd(lpBuffer, nLength, FALSE); wsTemp.ReleaseBuffer(nLength); FX_BOOL bPart = FALSE; if (m_nLimit > 0) { int32_t nTotalLength = GetTextBufLength(); int32_t nCount = m_SelRangePtrArr.GetSize(); for (int32_t i = 0; i < nCount; i++) { FDE_LPTXTEDTSELRANGE lpSelRange = m_SelRangePtrArr.GetAt(i); nTotalLength -= lpSelRange->nCount; } int32_t nExpectLength = nTotalLength + nLength; if (nTotalLength == m_nLimit) { return FDE_TXTEDT_MODIFY_RET_F_Full; } if (nExpectLength > m_nLimit) { nLength -= (nExpectLength - m_nLimit); bPart = TRUE; } } if ((m_Param.dwMode & FDE_TEXTEDITMODE_LimitArea_Vert) || (m_Param.dwMode & FDE_TEXTEDITMODE_LimitArea_Horz)) { int32_t nTemp = nLength; if (m_Param.dwMode & FDE_TEXTEDITMODE_Password) { CFX_WideString wsText; while (nLength > 0) { GetPreInsertText(wsText, m_nCaret, lpBuffer, nLength); int32_t nTotal = wsText.GetLength(); FX_WCHAR* lpBuf = wsText.GetBuffer(nTotal); for (int32_t i = 0; i < nTotal; i++) { lpBuf[i] = m_wcAliasChar; } wsText.ReleaseBuffer(nTotal); if (IsFitArea(wsText)) { break; } nLength--; } } else { CFX_WideString wsText; while (nLength > 0) { GetPreInsertText(wsText, m_nCaret, lpBuffer, nLength); if (IsFitArea(wsText)) { break; } nLength--; } } if (nLength == 0) { return FDE_TXTEDT_MODIFY_RET_F_Full; } if (nLength < nTemp) { bPart = TRUE; } } if (m_Param.dwMode & FDE_TEXTEDITMODE_Validate) { CFX_WideString wsText; GetPreInsertText(wsText, m_nCaret, lpBuffer, nLength); if (!m_Param.pEventSink->On_Validate(this, wsText)) { return FDE_TXTEDT_MODIFY_RET_F_Invalidate; } } if (IsSelect()) { DeleteSelect(); } if (!(m_Param.dwMode & FDE_TEXTEDITMODE_NoRedoUndo)) { IFDE_TxtEdtDoRecord* pRecord = new CFDE_TxtEdtDoRecord_Insert(this, m_nCaret, lpBuffer, nLength); CFX_ByteString bsDoRecord; pRecord->Serialize(bsDoRecord); m_Param.pEventSink->On_AddDoRecord(this, bsDoRecord); pRecord->Release(); } GetText(m_ChangeInfo.wsPrevText, 0); Inner_Insert(m_nCaret, lpBuffer, nLength); m_ChangeInfo.nChangeType = FDE_TXTEDT_TEXTCHANGE_TYPE_Insert; m_ChangeInfo.wsInsert = CFX_WideString(lpBuffer, nLength); nStart = m_nCaret; nStart += nLength; FX_WCHAR wChar = m_pTxtBuf->GetCharByIndex(nStart - 1); FX_BOOL bBefore = TRUE; if (wChar != L'\n' && wChar != L'\r') { nStart--; bBefore = FALSE; } SetCaretPos(nStart, bBefore); m_Param.pEventSink->On_TextChanged(this, m_ChangeInfo); return bPart ? FDE_TXTEDT_MODIFY_RET_S_Part : FDE_TXTEDT_MODIFY_RET_S_Normal; } int32_t CFDE_TxtEdtEngine::Delete(int32_t nStart, FX_BOOL bBackspace) { if (IsLocked()) { return FDE_TXTEDT_MODIFY_RET_F_Locked; } if (IsSelect()) { DeleteSelect(); return FDE_TXTEDT_MODIFY_RET_S_Normal; } #ifdef FDE_USEFORMATBLOCK int32_t nBlockCount = m_BlockArray.GetSize(); if (nBlockCount > 0) { if (bBackspace) { nStart--; } int32_t nCount = 1; int32_t nBgn = 0; int32_t nEnd = 0; CFDE_TxtEdtField* pField = NULL; FX_BOOL bInField = GetFieldBoundary(nStart, nBgn, nEnd, pField); int32_t nCaretInField = nStart - nBgn; FX_BOOL bBefore = FALSE; if (bInField && !pField->IsFix()) { pField->Backup(); CFX_WideString wsDel; int32_t nCaret = 0; int32_t nRet = pField->Delete(nCaretInField, nCount, wsDel, nCaret, bBefore); nCaret += nBgn; switch (nRet) { case FDE_FORMAT_FIELD_DELETE_RET_S: break; case FDE_FORMAT_FIELD_DELETE_RET_F_INVALIDATE: return FDE_TXTEDT_MODIFY_RET_F_Invalidate; case FDE_FORMAT_FIELD_DELETE_RET_F_BOUNDARY: return FDE_TXTEDT_MODIFY_RET_F_Boundary; default: FXSYS_assert(0); break; } CFX_WideString wsField; pField->GetFieldText(wsField); if (!m_Param.pEventSink->On_ValidateField( this, pField->GetBlockIndex(), pField->GetIndex(), wsField, 0)) { pField->Restore(); return FDE_TXTEDT_MODIFY_RET_F_Invalidate; } CFX_WideString wsDisplay; pField->GetDisplayText(wsDisplay); Replace(nBgn, nEnd - nBgn + 1, wsDisplay); if (!(m_Param.dwMode & FDE_TEXTEDITMODE_NoRedoUndo)) { IFDE_TxtEdtDoRecord* pRecord = new CFDE_TxtEdtDoRecord_FieldDelete( this, nStart, pField, nCaretInField, nBgn, nEnd - nBgn + 1, wsDisplay.GetLength(), wsDel, FALSE); CFX_ByteString bsDoRecord; pRecord->Serialize(bsDoRecord); m_Param.pEventSink->On_AddDoRecord(this, bsDoRecord); pRecord->Release(); } SetCaretPos(nStart, bBefore); return FDE_TXTEDT_MODIFY_RET_S_Normal; } return FDE_TXTEDT_MODIFY_RET_F_Boundary; } #endif int32_t nCount = 1; if (bBackspace) { if (nStart == 0) { return FDE_TXTEDT_MODIFY_RET_F_Boundary; } if (nStart > 2 && m_pTxtBuf->GetCharByIndex(nStart - 1) == L'\n' && m_pTxtBuf->GetCharByIndex(nStart - 2) == L'\r') { nStart--; nCount++; } nStart--; } else { if (nStart == GetTextBufLength()) { return FDE_TXTEDT_MODIFY_RET_F_Full; } if ((nStart + 1 < GetTextBufLength()) && (m_pTxtBuf->GetCharByIndex(nStart) == L'\r') && (m_pTxtBuf->GetCharByIndex(nStart + 1) == L'\n')) { nCount++; } } if (m_Param.dwMode & FDE_TEXTEDITMODE_Validate) { CFX_WideString wsText; GetPreDeleteText(wsText, nStart, nCount); if (!m_Param.pEventSink->On_Validate(this, wsText)) { return FDE_TXTEDT_MODIFY_RET_F_Invalidate; } } if (!(m_Param.dwMode & FDE_TEXTEDITMODE_NoRedoUndo)) { CFX_WideString wsRange; m_pTxtBuf->GetRange(wsRange, nStart, nCount); IFDE_TxtEdtDoRecord* pRecord = new CFDE_TxtEdtDoRecord_DeleteRange(this, nStart, m_nCaret, wsRange); CFX_ByteString bsDoRecord; pRecord->Serialize(bsDoRecord); m_Param.pEventSink->On_AddDoRecord(this, bsDoRecord); pRecord->Release(); } m_ChangeInfo.nChangeType = FDE_TXTEDT_TEXTCHANGE_TYPE_Delete; GetText(m_ChangeInfo.wsDelete, nStart, nCount); Inner_DeleteRange(nStart, nCount); SetCaretPos(nStart + ((!bBackspace && nStart > 0) ? -1 : 0), (bBackspace || nStart == 0)); m_Param.pEventSink->On_TextChanged(this, m_ChangeInfo); return FDE_TXTEDT_MODIFY_RET_S_Normal; } int32_t CFDE_TxtEdtEngine::DeleteRange(int32_t nStart, int32_t nCount) { if (IsLocked()) { return FDE_TXTEDT_MODIFY_RET_F_Locked; } if (nCount == -1) { nCount = GetTextBufLength(); } if (nCount == 0) { return FDE_TXTEDT_MODIFY_RET_S_Normal; } if (m_Param.dwMode & FDE_TEXTEDITMODE_Validate) { CFX_WideString wsText; GetPreDeleteText(wsText, nStart, nCount); if (!m_Param.pEventSink->On_Validate(this, wsText)) { return FDE_TXTEDT_MODIFY_RET_F_Invalidate; } } DeleteRange_DoRecord(nStart, nCount); m_Param.pEventSink->On_TextChanged(this, m_ChangeInfo); SetCaretPos(nStart, TRUE); return FDE_TXTEDT_MODIFY_RET_S_Normal; } int32_t CFDE_TxtEdtEngine::Replace(int32_t nStart, int32_t nLength, const CFX_WideString& wsReplace) { if (IsLocked()) { return FDE_TXTEDT_MODIFY_RET_F_Locked; } if (nStart < 0 || (nStart + nLength > GetTextBufLength())) { return FDE_TXTEDT_MODIFY_RET_F_Boundary; } if (m_Param.dwMode & FDE_TEXTEDITMODE_Validate) { CFX_WideString wsText; GetPreReplaceText(wsText, nStart, nLength, wsReplace.c_str(), wsReplace.GetLength()); if (!m_Param.pEventSink->On_Validate(this, wsText)) { return FDE_TXTEDT_MODIFY_RET_F_Invalidate; } } if (IsSelect()) { ClearSelection(); } m_ChangeInfo.nChangeType = FDE_TXTEDT_TEXTCHANGE_TYPE_Replace; GetText(m_ChangeInfo.wsDelete, nStart, nLength); if (nLength > 0) { Inner_DeleteRange(nStart, nLength); } int32_t nTextLength = wsReplace.GetLength(); if (nTextLength > 0) { Inner_Insert(nStart, wsReplace.c_str(), nTextLength); } m_ChangeInfo.wsInsert = CFX_WideString(wsReplace.c_str(), nTextLength); nStart += nTextLength; FX_WCHAR wChar = m_pTxtBuf->GetCharByIndex(nStart - 1); FX_BOOL bBefore = TRUE; if (wChar != L'\n' && wChar != L'\r') { nStart--; bBefore = FALSE; } SetCaretPos(nStart, bBefore); m_Param.pEventSink->On_PageUnload(this, m_nCaretPage, 0); m_Param.pEventSink->On_PageLoad(this, m_nCaretPage, 0); m_Param.pEventSink->On_TextChanged(this, m_ChangeInfo); return FDE_TXTEDT_MODIFY_RET_S_Normal; } void CFDE_TxtEdtEngine::SetLimit(int32_t nLimit) { m_nLimit = nLimit; } void CFDE_TxtEdtEngine::SetAliasChar(FX_WCHAR wcAlias) { m_wcAliasChar = wcAlias; } void CFDE_TxtEdtEngine::SetFormatBlock(int32_t nIndex, const CFX_WideString& wsBlockFormat) { #ifdef FDE_USEFORMATBLOCK if (m_nFixLength == -1) { m_nFixLength = GetTextLength(); FXSYS_assert(m_wsFixText.IsEmpty()); GetText(m_wsFixText, 0, -1); } FX_BOOL bInBlock = FALSE; int32_t nCharIndex = 0; int32_t nBlockIndex = 0; int32_t nBlockPos = -1; FX_WCHAR wc; CFDE_TxtEdtBufIter* pIter = new CFDE_TxtEdtBufIter((CFDE_TxtEdtBuf*)m_pTxtBuf, FALSE); pIter->SetAt(0); do { wc = pIter->GetChar(); if (bInBlock) { if (wc == FDE_TXTEDT_FORMATBLOCK_END) { nBlockIndex++; bInBlock = FALSE; } } else { if (wc == FDE_TXTEDT_FORMATBLOCK_BGN) { bInBlock = TRUE; } else { if (nCharIndex++ == nIndex) { nBlockPos = pIter->GetAt(); break; } } } } while (pIter->Next()); pIter->Release(); if (nBlockPos == -1) { nBlockPos = GetTextBufLength(); } CFDE_TxtEdtBlock* pEditBlock = new CFDE_TxtEdtBlock(this, wsBlockFormat, nIndex); m_BlockArray.InsertAt(m_BlockArray.GetSize(), pEditBlock); CFX_WideString wsDisplay; pEditBlock->GetDisplayText(wsDisplay); m_nCaret = nBlockPos; if (wsDisplay.GetLength() > 0) { RawInsert(nBlockPos, const FX_WCHAR*(wsDisplay), wsDisplay.GetLength()); } #endif } int32_t CFDE_TxtEdtEngine::CountEditBlocks() const { #ifdef FDE_USEFORMATBLOCK return m_BlockArray.GetSize(); #else return 0; #endif } void CFDE_TxtEdtEngine::GetEditBlockText(int32_t nIndex, CFX_WideString& wsBlockText) const { #ifdef FDE_USEFORMATBLOCK CFDE_TxtEdtBlock* pBlock = m_BlockArray[nIndex]; pBlock->GetBlockText(wsBlockText); #endif } int32_t CFDE_TxtEdtEngine::CountEditFields(int32_t nBlockIndex) const { #ifdef FDE_USEFORMATBLOCK CFDE_TxtEdtBlock* pBlock = m_BlockArray[nBlockIndex]; return pBlock->CountField(); #else return 0; #endif } void CFDE_TxtEdtEngine::GetEditFieldText(int32_t nBlockIndex, int32_t nFieldIndex, CFX_WideString& wsFieldText) const { #ifdef FDE_USEFORMATBLOCK CFDE_TxtEdtBlock* pBlock = m_BlockArray[nBlockIndex]; pBlock->GetFieldText(nFieldIndex, wsFieldText); #endif } void CFDE_TxtEdtEngine::StartEdit() { #ifdef FDE_USEFORMATBLOCK #endif } void CFDE_TxtEdtEngine::EndEdit() { #ifdef FDE_USEFORMATBLOCK #endif } void CFDE_TxtEdtEngine::RemoveSelRange(int32_t nStart, int32_t nCount) { FDE_LPTXTEDTSELRANGE lpTemp = NULL; int32_t nRangeCount = m_SelRangePtrArr.GetSize(); int32_t i = 0; for (i = 0; i < nRangeCount; i++) { lpTemp = m_SelRangePtrArr[i]; if (lpTemp->nStart == nStart && lpTemp->nCount == nCount) { delete lpTemp; m_SelRangePtrArr.RemoveAt(i); return; } } } void CFDE_TxtEdtEngine::AddSelRange(int32_t nStart, int32_t nCount) { if (nCount == -1) { nCount = GetTextLength() - nStart; } int32_t nSize = m_SelRangePtrArr.GetSize(); if (nSize <= 0) { FDE_LPTXTEDTSELRANGE lpSelRange = new FDE_TXTEDTSELRANGE; lpSelRange->nStart = nStart; lpSelRange->nCount = nCount; m_SelRangePtrArr.Add(lpSelRange); m_Param.pEventSink->On_SelChanged(this); return; } FDE_LPTXTEDTSELRANGE lpTemp = NULL; lpTemp = m_SelRangePtrArr[nSize - 1]; if (nStart >= lpTemp->nStart + lpTemp->nCount) { FDE_LPTXTEDTSELRANGE lpSelRange = new FDE_TXTEDTSELRANGE; lpSelRange->nStart = nStart; lpSelRange->nCount = nCount; m_SelRangePtrArr.Add(lpSelRange); m_Param.pEventSink->On_SelChanged(this); return; } int32_t nEnd = nStart + nCount - 1; FX_BOOL bBegin = FALSE; int32_t nRangeBgn = 0; int32_t nRangeCnt = 0; for (int32_t i = 0; i < nSize; i++) { lpTemp = m_SelRangePtrArr[i]; int32_t nTempBgn = lpTemp->nStart; int32_t nTempEnd = nTempBgn + lpTemp->nCount - 1; if (bBegin) { if (nEnd < nTempBgn) { break; } else if (nStart >= nTempBgn && nStart <= nTempEnd) { nRangeCnt++; break; } nRangeCnt++; } else { if (nStart <= nTempEnd) { nRangeBgn = i; if (nEnd < nTempBgn) { break; } nRangeCnt = 1; bBegin = TRUE; } } } if (nRangeCnt == 0) { FDE_LPTXTEDTSELRANGE lpSelRange = new FDE_TXTEDTSELRANGE; lpSelRange->nStart = nStart; lpSelRange->nCount = nCount; m_SelRangePtrArr.InsertAt(nRangeBgn, lpSelRange); } else { lpTemp = m_SelRangePtrArr[nRangeBgn]; lpTemp->nStart = nStart; lpTemp->nCount = nCount; nRangeCnt--; nRangeBgn++; while (nRangeCnt--) { delete m_SelRangePtrArr[nRangeBgn]; m_SelRangePtrArr.RemoveAt(nRangeBgn); } } m_Param.pEventSink->On_SelChanged(this); } int32_t CFDE_TxtEdtEngine::CountSelRanges() { return m_SelRangePtrArr.GetSize(); } int32_t CFDE_TxtEdtEngine::GetSelRange(int32_t nIndex, int32_t& nStart) { nStart = m_SelRangePtrArr[nIndex]->nStart; return m_SelRangePtrArr[nIndex]->nCount; } void CFDE_TxtEdtEngine::ClearSelection() { int32_t nCount = m_SelRangePtrArr.GetSize(); FDE_LPTXTEDTSELRANGE lpRange = NULL; int32_t i = 0; for (i = 0; i < nCount; i++) { lpRange = m_SelRangePtrArr[i]; if (lpRange != NULL) { delete lpRange; lpRange = NULL; } } m_SelRangePtrArr.RemoveAll(); if (nCount && m_Param.pEventSink) { m_Param.pEventSink->On_SelChanged(this); } } FX_BOOL CFDE_TxtEdtEngine::Redo(const CFX_ByteStringC& bsRedo) { if (IsLocked()) { return FALSE; } if (m_Param.dwMode & FDE_TEXTEDITMODE_NoRedoUndo) { return FALSE; } IFDE_TxtEdtDoRecord* pDoRecord = IFDE_TxtEdtDoRecord::Create(bsRedo); FXSYS_assert(pDoRecord); if (pDoRecord == NULL) { return FALSE; } FX_BOOL bOK = pDoRecord->Redo(); pDoRecord->Release(); return bOK; } FX_BOOL CFDE_TxtEdtEngine::Undo(const CFX_ByteStringC& bsUndo) { if (IsLocked()) { return FALSE; } if (m_Param.dwMode & FDE_TEXTEDITMODE_NoRedoUndo) { return FALSE; } IFDE_TxtEdtDoRecord* pDoRecord = IFDE_TxtEdtDoRecord::Create(bsUndo); FXSYS_assert(pDoRecord); if (pDoRecord == NULL) { return FALSE; } FX_BOOL bOK = pDoRecord->Undo(); pDoRecord->Release(); return bOK; } int32_t CFDE_TxtEdtEngine::StartLayout() { Lock(); RemoveAllPages(); m_nLayoutPos = 0; m_nLineCount = 0; return 0; } int32_t CFDE_TxtEdtEngine::DoLayout(IFX_Pause* pPause) { int32_t nCount = m_ParagPtrArray.GetSize(); CFDE_TxtEdtParag* pParag = NULL; int32_t nLineCount = 0; for (; m_nLayoutPos < nCount; m_nLayoutPos++) { pParag = m_ParagPtrArray[m_nLayoutPos]; pParag->CalcLines(); nLineCount += pParag->m_nLineCount; if ((pPause != NULL) && (nLineCount > m_nPageLineCount) && pPause->NeedToPauseNow()) { m_nLineCount += nLineCount; return (++m_nLayoutPos * 100) / nCount; } } m_nLineCount += nLineCount; return 100; } void CFDE_TxtEdtEngine::EndLayout() { UpdatePages(); int32_t nLength = GetTextLength(); if (m_nCaret > nLength) { m_nCaret = nLength; } int32_t nIndex = m_nCaret; if (!m_bBefore) { nIndex--; } m_rtCaret.Set(0, 0, 1, m_Param.fFontSize); Unlock(); } FX_BOOL CFDE_TxtEdtEngine::Optimize(IFX_Pause* pPause) { return m_pTxtBuf->Optimize(pPause); } IFDE_TxtEdtBuf* CFDE_TxtEdtEngine::GetTextBuf() const { return (IFDE_TxtEdtBuf*)m_pTxtBuf; } int32_t CFDE_TxtEdtEngine::GetTextBufLength() const { return m_pTxtBuf->GetTextLength() - 1; } IFX_TxtBreak* CFDE_TxtEdtEngine::GetTextBreak() const { return m_pTextBreak; } int32_t CFDE_TxtEdtEngine::GetLineCount() const { return m_nLineCount; } int32_t CFDE_TxtEdtEngine::GetPageLineCount() const { return m_nPageLineCount; } int32_t CFDE_TxtEdtEngine::CountParags() const { return m_ParagPtrArray.GetSize(); } IFDE_TxtEdtParag* CFDE_TxtEdtEngine::GetParag(int32_t nParagIndex) const { return m_ParagPtrArray[nParagIndex]; } IFX_CharIter* CFDE_TxtEdtEngine::CreateCharIter() { if (!m_pTxtBuf) { return NULL; } return new CFDE_TxtEdtBufIter((CFDE_TxtEdtBuf*)m_pTxtBuf); } int32_t CFDE_TxtEdtEngine::Line2Parag(int32_t nStartParag, int32_t nStartLineofParag, int32_t nLineIndex, int32_t& nStartLine) const { int32_t nLineTotal = nStartLineofParag; int32_t nCount = m_ParagPtrArray.GetSize(); CFDE_TxtEdtParag* pParag = NULL; int32_t i = nStartParag; for (; i < nCount; i++) { pParag = m_ParagPtrArray[i]; nLineTotal += pParag->m_nLineCount; if (nLineTotal > nLineIndex) { break; } } nStartLine = nLineTotal - pParag->m_nLineCount; return i; } void CFDE_TxtEdtEngine::GetPreDeleteText(CFX_WideString& wsText, int32_t nIndex, int32_t nLength) { GetText(wsText, 0, GetTextBufLength()); wsText.Delete(nIndex, nLength); } void CFDE_TxtEdtEngine::GetPreInsertText(CFX_WideString& wsText, int32_t nIndex, const FX_WCHAR* lpText, int32_t nLength) { GetText(wsText, 0, GetTextBufLength()); int32_t nSelIndex = 0; int32_t nSelLength = 0; int32_t nSelCount = CountSelRanges(); while (nSelCount--) { nSelLength = GetSelRange(nSelCount, nSelIndex); wsText.Delete(nSelIndex, nSelLength); nIndex = nSelIndex; } CFX_WideString wsTemp; int32_t nOldLength = wsText.GetLength(); const FX_WCHAR* pOldBuffer = wsText.c_str(); FX_WCHAR* lpBuffer = wsTemp.GetBuffer(nOldLength + nLength); FXSYS_memcpy(lpBuffer, pOldBuffer, (nIndex) * sizeof(FX_WCHAR)); FXSYS_memcpy(lpBuffer + nIndex, lpText, nLength * sizeof(FX_WCHAR)); FXSYS_memcpy(lpBuffer + nIndex + nLength, pOldBuffer + nIndex, (nOldLength - nIndex) * sizeof(FX_WCHAR)); wsTemp.ReleaseBuffer(nOldLength + nLength); wsText = wsTemp; } void CFDE_TxtEdtEngine::GetPreReplaceText(CFX_WideString& wsText, int32_t nIndex, int32_t nOriginLength, const FX_WCHAR* lpText, int32_t nLength) { GetText(wsText, 0, GetTextBufLength()); int32_t nSelIndex = 0; int32_t nSelLength = 0; int32_t nSelCount = CountSelRanges(); while (nSelCount--) { nSelLength = GetSelRange(nSelCount, nSelIndex); wsText.Delete(nSelIndex, nSelLength); } wsText.Delete(nIndex, nOriginLength); int32_t i = 0; for (i = 0; i < nLength; i++) { wsText.Insert(nIndex++, lpText[i]); } } void CFDE_TxtEdtEngine::Inner_Insert(int32_t nStart, const FX_WCHAR* lpText, int32_t nLength) { FXSYS_assert(nLength > 0); FDE_TXTEDTPARAGPOS ParagPos; TextPos2ParagPos(nStart, ParagPos); m_Param.pEventSink->On_PageUnload(this, m_nCaretPage, 0); int32_t nParagCount = m_ParagPtrArray.GetSize(); int32_t i = 0; for (i = ParagPos.nParagIndex + 1; i < nParagCount; i++) { m_ParagPtrArray[i]->m_nCharStart += nLength; } CFDE_TxtEdtParag* pParag = m_ParagPtrArray[ParagPos.nParagIndex]; int32_t nReserveLineCount = pParag->m_nLineCount; int32_t nReserveCharStart = pParag->m_nCharStart; int32_t nLeavePart = ParagPos.nCharIndex; int32_t nCutPart = pParag->m_nCharCount - ParagPos.nCharIndex; int32_t nTextStart = 0; FX_WCHAR wCurChar = L' '; const FX_WCHAR* lpPos = lpText; FX_BOOL bFirst = TRUE; int32_t nParagIndex = ParagPos.nParagIndex; for (i = 0; i < nLength; i++, lpPos++) { wCurChar = *lpPos; if (wCurChar == m_wLineEnd) { if (bFirst) { pParag->m_nCharCount = nLeavePart + (i - nTextStart + 1); pParag->m_nLineCount = -1; nReserveCharStart += pParag->m_nCharCount; bFirst = FALSE; } else { pParag = new CFDE_TxtEdtParag(this); pParag->m_nLineCount = -1; pParag->m_nCharCount = i - nTextStart + 1; pParag->m_nCharStart = nReserveCharStart; m_ParagPtrArray.InsertAt(++nParagIndex, pParag); nReserveCharStart += pParag->m_nCharCount; } nTextStart = i + 1; } } if (bFirst) { pParag->m_nCharCount += nLength; pParag->m_nLineCount = -1; bFirst = FALSE; } else { pParag = new CFDE_TxtEdtParag(this); pParag->m_nLineCount = -1; pParag->m_nCharCount = nLength - nTextStart + nCutPart; pParag->m_nCharStart = nReserveCharStart; m_ParagPtrArray.InsertAt(++nParagIndex, pParag); } m_pTxtBuf->Insert(nStart, lpText, nLength); int32_t nTotalLineCount = 0; for (i = ParagPos.nParagIndex; i <= nParagIndex; i++) { pParag = m_ParagPtrArray[i]; pParag->CalcLines(); nTotalLineCount += pParag->m_nLineCount; } m_nLineCount += nTotalLineCount - nReserveLineCount; m_Param.pEventSink->On_PageLoad(this, m_nCaretPage, 0); UpdatePages(); } #ifdef FDE_USEFORMATBLOCK void CFDE_TxtEdtEngine::RawInsert(int32_t nStart, const FX_WCHAR* lpText, int32_t nLength) { FXSYS_assert(nLength > 0); FDE_TXTEDTPARAGPOS ParagPos; TextPos2ParagPos(nStart, ParagPos); int32_t nParagCount = m_ParagPtrArray.GetSize(); int32_t i = 0; for (i = ParagPos.nParagIndex + 1; i < nParagCount; i++) { m_ParagPtrArray[i]->m_nCharStart += nLength; } CFDE_TxtEdtParag* pParag = m_ParagPtrArray[ParagPos.nParagIndex]; int32_t nReserveLineCount = pParag->m_nLineCount; int32_t nReserveCharStart = pParag->m_nCharStart; int32_t nLeavePart = ParagPos.nCharIndex; int32_t nCutPart = pParag->m_nCharCount - ParagPos.nCharIndex; int32_t nTextStart = 0; FX_WCHAR wCurChar = L' '; const FX_WCHAR* lpPos = lpText; FX_BOOL bFirst = TRUE; int32_t nParagIndex = ParagPos.nParagIndex; for (i = 0; i < nLength; i++, lpPos++) { wCurChar = *lpPos; if (wCurChar == m_wLineEnd) { if (bFirst) { pParag->m_nCharCount = nLeavePart + (i - nTextStart + 1); pParag->m_nLineCount = -1; nReserveCharStart += pParag->m_nCharCount; bFirst = FALSE; } else { pParag = new CFDE_TxtEdtParag(this); pParag->m_nLineCount = -1; pParag->m_nCharCount = i - nTextStart + 1; pParag->m_nCharStart = nReserveCharStart; m_ParagPtrArray.InsertAt(++nParagIndex, pParag); nReserveCharStart += pParag->m_nCharCount; } nTextStart = i + 1; } } if (bFirst) { pParag->m_nCharCount += nLength; pParag->m_nLineCount = -1; bFirst = FALSE; } else { pParag = new CFDE_TxtEdtParag(this); pParag->m_nLineCount = -1; pParag->m_nCharCount = nLength - nTextStart + nCutPart; pParag->m_nCharStart = nReserveCharStart; m_ParagPtrArray.InsertAt(++nParagIndex, pParag); } m_pTxtBuf->Insert(nStart, lpText, nLength); } #endif void CFDE_TxtEdtEngine::Inner_DeleteRange(int32_t nStart, int32_t nCount) { if (nCount == -1) { nCount = m_pTxtBuf->GetTextLength() - nStart; } int32_t nEnd = nStart + nCount - 1; FXSYS_assert(nStart >= 0 && nEnd < m_pTxtBuf->GetTextLength()); m_Param.pEventSink->On_PageUnload(this, m_nCaretPage, 0); FDE_TXTEDTPARAGPOS ParagPosBgn, ParagPosEnd; TextPos2ParagPos(nStart, ParagPosBgn); TextPos2ParagPos(nEnd, ParagPosEnd); CFDE_TxtEdtParag* pParag = m_ParagPtrArray[ParagPosEnd.nParagIndex]; FX_BOOL bLastParag = FALSE; if (ParagPosEnd.nCharIndex == pParag->m_nCharCount - 1) { if (ParagPosEnd.nParagIndex < m_ParagPtrArray.GetSize() - 1) { ParagPosEnd.nParagIndex++; } else { bLastParag = TRUE; } } int32_t nTotalLineCount = 0; int32_t nTotalCharCount = 0; int32_t i = 0; for (i = ParagPosBgn.nParagIndex; i <= ParagPosEnd.nParagIndex; i++) { CFDE_TxtEdtParag* pParag = m_ParagPtrArray[i]; pParag->CalcLines(); nTotalLineCount += pParag->m_nLineCount; nTotalCharCount += pParag->m_nCharCount; } m_pTxtBuf->Delete(nStart, nCount); int32_t nNextParagIndex = (ParagPosBgn.nCharIndex == 0 && bLastParag) ? ParagPosBgn.nParagIndex : (ParagPosBgn.nParagIndex + 1); for (i = nNextParagIndex; i <= ParagPosEnd.nParagIndex; i++) { CFDE_TxtEdtParag* pParag = m_ParagPtrArray[nNextParagIndex]; delete pParag; m_ParagPtrArray.RemoveAt(nNextParagIndex); } if (!(bLastParag && ParagPosBgn.nCharIndex == 0)) { pParag = m_ParagPtrArray[ParagPosBgn.nParagIndex]; pParag->m_nCharCount = nTotalCharCount - nCount; pParag->CalcLines(); nTotalLineCount -= pParag->m_nLineCount; } int32_t nParagCount = m_ParagPtrArray.GetSize(); for (i = nNextParagIndex; i < nParagCount; i++) { m_ParagPtrArray[i]->m_nCharStart -= nCount; } m_nLineCount -= nTotalLineCount; UpdatePages(); int32_t nPageCount = CountPages(); if (m_nCaretPage >= nPageCount) { m_nCaretPage = nPageCount - 1; } m_Param.pEventSink->On_PageLoad(this, m_nCaretPage, 0); } void CFDE_TxtEdtEngine::DeleteRange_DoRecord(int32_t nStart, int32_t nCount, FX_BOOL bSel) { FXSYS_assert(nStart >= 0); if (nCount == -1) { nCount = GetTextLength() - nStart; } FXSYS_assert((nStart + nCount) <= m_pTxtBuf->GetTextLength()); #ifdef FDE_USEFORMATBLOCK int32_t nBlockCount = m_BlockArray.GetSize(); if (nBlockCount > 0) { } #endif if (!(m_Param.dwMode & FDE_TEXTEDITMODE_NoRedoUndo)) { CFX_WideString wsRange; m_pTxtBuf->GetRange(wsRange, nStart, nCount); IFDE_TxtEdtDoRecord* pRecord = new CFDE_TxtEdtDoRecord_DeleteRange( this, nStart, m_nCaret, wsRange, bSel); CFX_ByteString bsDoRecord; pRecord->Serialize(bsDoRecord); m_Param.pEventSink->On_AddDoRecord(this, bsDoRecord); pRecord->Release(); } m_ChangeInfo.nChangeType = FDE_TXTEDT_TEXTCHANGE_TYPE_Delete; GetText(m_ChangeInfo.wsDelete, nStart, nCount); Inner_DeleteRange(nStart, nCount); } void CFDE_TxtEdtEngine::ResetEngine() { RemoveAllPages(); RemoveAllParags(); ClearSelection(); m_nCaret = 0; m_pTxtBuf->Clear(FALSE); m_nCaret = 0; } void CFDE_TxtEdtEngine::RebuildParagraphs() { RemoveAllParags(); FX_WCHAR wChar = L' '; int32_t nParagStart = 0; int32_t nIndex = 0; IFX_CharIter* pIter = new CFDE_TxtEdtBufIter((CFDE_TxtEdtBuf*)m_pTxtBuf); pIter->SetAt(0); do { wChar = pIter->GetChar(); nIndex = pIter->GetAt(); if (wChar == m_wLineEnd) { CFDE_TxtEdtParag* pParag = new CFDE_TxtEdtParag(this); pParag->m_nCharStart = nParagStart; pParag->m_nCharCount = nIndex - nParagStart + 1; pParag->m_nLineCount = -1; m_ParagPtrArray.Add(pParag); nParagStart = nIndex + 1; } } while (pIter->Next()); pIter->Release(); } void CFDE_TxtEdtEngine::RemoveAllParags() { int32_t nCount = m_ParagPtrArray.GetSize(); int32_t i = 0; for (i = 0; i < nCount; i++) { CFDE_TxtEdtParag* pParag = m_ParagPtrArray[i]; if (pParag) { delete pParag; } } m_ParagPtrArray.RemoveAll(); } void CFDE_TxtEdtEngine::RemoveAllPages() { int32_t nCount = m_PagePtrArray.GetSize(); int32_t i = 0; for (i = 0; i < nCount; i++) { IFDE_TxtEdtPage* pPage = m_PagePtrArray[i]; if (pPage) { pPage->Release(); } } m_PagePtrArray.RemoveAll(); } void CFDE_TxtEdtEngine::UpdateParags() { int32_t nCount = m_ParagPtrArray.GetSize(); if (nCount == 0) { return; } CFDE_TxtEdtParag* pParag = NULL; int32_t nLineCount = 0; int32_t i = 0; for (i = 0; i < nCount; i++) { pParag = m_ParagPtrArray[i]; if (pParag->m_nLineCount == -1) { pParag->CalcLines(); } nLineCount += pParag->m_nLineCount; } m_nLineCount = nLineCount; } void CFDE_TxtEdtEngine::UpdatePages() { if (m_nLineCount == 0) { return; } int32_t nPageCount = (m_nLineCount - 1) / (m_nPageLineCount) + 1; int32_t nSize = m_PagePtrArray.GetSize(); if (nSize == nPageCount) { return; } if (nSize > nPageCount) { IFDE_TxtEdtPage* pPage = NULL; int32_t i = 0; for (i = nSize - 1; i >= nPageCount; i--) { pPage = m_PagePtrArray[i]; if (pPage) { pPage->Release(); } m_PagePtrArray.RemoveAt(i); } m_Param.pEventSink->On_PageCountChanged(this); return; } if (nSize < nPageCount) { IFDE_TxtEdtPage* pPage = NULL; int32_t i = 0; for (i = nSize; i < nPageCount; i++) { pPage = IFDE_TxtEdtPage::Create(this, i); m_PagePtrArray.Add(pPage); } m_Param.pEventSink->On_PageCountChanged(this); return; } } void CFDE_TxtEdtEngine::UpdateTxtBreak() { FX_DWORD dwStyle = m_pTextBreak->GetLayoutStyles(); if (m_Param.dwMode & FDE_TEXTEDITMODE_MultiLines) { dwStyle &= ~FX_TXTLAYOUTSTYLE_SingleLine; } else { dwStyle |= FX_TXTLAYOUTSTYLE_SingleLine; } if (m_Param.dwLayoutStyles & FDE_TEXTEDITLAYOUT_DocVertical) { dwStyle |= FX_TXTLAYOUTSTYLE_VerticalLayout; } else { dwStyle &= ~FX_TXTLAYOUTSTYLE_VerticalLayout; } if (m_Param.dwLayoutStyles & FDE_TEXTEDITLAYOUT_LineReserve) { dwStyle |= FX_TXTLAYOUTSTYLE_ReverseLine; } else { dwStyle &= ~FX_TXTLAYOUTSTYLE_ReverseLine; } if (m_Param.dwLayoutStyles & FDE_TEXTEDITLAYOUT_RTL) { dwStyle |= FX_TXTLAYOUTSTYLE_RTLReadingOrder; } else { dwStyle &= ~FX_TXTLAYOUTSTYLE_RTLReadingOrder; } if (m_Param.dwLayoutStyles & FDE_TEXTEDITLAYOUT_CombText) { dwStyle |= FX_TXTLAYOUTSTYLE_CombText; } else { dwStyle &= ~FX_TXTLAYOUTSTYLE_CombText; } if (m_Param.dwLayoutStyles & FDE_TEXTEDITLAYOUT_CharVertial) { dwStyle |= FX_TXTLAYOUTSTYLE_VerticalChars; } else { dwStyle &= ~FX_TXTLAYOUTSTYLE_VerticalChars; } if (m_Param.dwLayoutStyles & FDE_TEXTEDITLAYOUT_ExpandTab) { dwStyle |= FX_TXTLAYOUTSTYLE_ExpandTab; } else { dwStyle &= ~FX_TXTLAYOUTSTYLE_ExpandTab; } if (m_Param.dwLayoutStyles & FDE_TEXTEDITLAYOUT_ArabicContext) { dwStyle |= FX_TXTLAYOUTSTYLE_ArabicContext; } else { dwStyle &= ~FX_TXTLAYOUTSTYLE_ArabicContext; } if (m_Param.dwLayoutStyles & FDE_TEXTEDITLAYOUT_ArabicShapes) { dwStyle |= FX_TXTLAYOUTSTYLE_ArabicShapes; } else { dwStyle &= ~FX_TXTLAYOUTSTYLE_ArabicShapes; } m_pTextBreak->SetLayoutStyles(dwStyle); FX_DWORD dwAligment = 0; if (m_Param.dwAlignment & FDE_TEXTEDITALIGN_Justified) { dwAligment |= FX_TXTLINEALIGNMENT_Justified; } else if (m_Param.dwAlignment & FDE_TEXTEDITALIGN_Distributed) { dwAligment |= FX_TXTLINEALIGNMENT_Distributed; } if (m_Param.dwAlignment & FDE_TEXTEDITALIGN_Center) { dwAligment |= FX_TXTLINEALIGNMENT_Center; } else if (m_Param.dwAlignment & FDE_TEXTEDITALIGN_Right) { dwAligment |= FX_TXTLINEALIGNMENT_Right; } m_pTextBreak->SetAlignment(dwAligment); if (m_Param.dwLayoutStyles & FDE_TEXTEDITLAYOUT_DocVertical) { if (m_Param.dwMode & FDE_TEXTEDITMODE_AutoLineWrap) { m_pTextBreak->SetLineWidth(m_Param.fPlateHeight); } else { m_pTextBreak->SetLineWidth(FDE_PAGEWIDTH_MAX); } } else { if (m_Param.dwMode & FDE_TEXTEDITMODE_AutoLineWrap) { m_pTextBreak->SetLineWidth(m_Param.fPlateWidth); } else { m_pTextBreak->SetLineWidth(FDE_PAGEWIDTH_MAX); } } m_nPageLineCount = m_Param.nLineCount; if (m_Param.dwLayoutStyles & FDE_TEXTEDITLAYOUT_CombText) { FX_FLOAT fCombWidth = m_Param.dwLayoutStyles & FDE_TEXTEDITLAYOUT_DocVertical ? m_Param.fPlateHeight : m_Param.fPlateWidth; if (m_nLimit > 0) { fCombWidth /= m_nLimit; } m_pTextBreak->SetCombWidth(fCombWidth); } m_pTextBreak->SetFont(m_Param.pFont); m_pTextBreak->SetFontSize(m_Param.fFontSize); m_pTextBreak->SetTabWidth(m_Param.fTabWidth, m_Param.bTabEquidistant); m_pTextBreak->SetDefaultChar(m_Param.wDefChar); m_pTextBreak->SetParagraphBreakChar(m_Param.wLineBreakChar); m_pTextBreak->SetCharRotation(m_Param.nCharRotation); m_pTextBreak->SetLineBreakTolerance(m_Param.fFontSize * 0.2f); m_pTextBreak->SetHorizontalScale(m_Param.nHorzScale); m_pTextBreak->SetCharSpace(m_Param.fCharSpace); } FX_BOOL CFDE_TxtEdtEngine::ReplaceParagEnd(FX_WCHAR*& lpText, int32_t& nLength, FX_BOOL bPreIsCR) { for (int32_t i = 0; i < nLength; i++) { FX_WCHAR wc = lpText[i]; switch (wc) { case L'\r': { lpText[i] = m_wLineEnd; bPreIsCR = TRUE; } break; case L'\n': { if (bPreIsCR == TRUE) { int32_t nNext = i + 1; if (nNext < nLength) { FXSYS_memmove(lpText + i, lpText + nNext, (nLength - nNext) * sizeof(FX_WCHAR)); } i--; nLength--; bPreIsCR = FALSE; if (m_bAutoLineEnd) { m_nFirstLineEnd = FDE_TXTEDIT_LINEEND_CRLF; m_bAutoLineEnd = FALSE; } } else { lpText[i] = m_wLineEnd; if (m_bAutoLineEnd) { m_nFirstLineEnd = FDE_TXTEDIT_LINEEND_LF; m_bAutoLineEnd = FALSE; } } } break; default: { if (bPreIsCR && m_bAutoLineEnd) { m_nFirstLineEnd = FDE_TXTEDIT_LINEEND_CR; m_bAutoLineEnd = FALSE; } bPreIsCR = FALSE; } break; } } return bPreIsCR; } void CFDE_TxtEdtEngine::RecoverParagEnd(CFX_WideString& wsText) { FX_WCHAR wc = (m_nFirstLineEnd == FDE_TXTEDIT_LINEEND_CR) ? L'\n' : L'\r'; if (m_nFirstLineEnd == FDE_TXTEDIT_LINEEND_CRLF) { CFX_ArrayTemplate PosArr; int32_t nLength = wsText.GetLength(); int32_t i = 0; FX_WCHAR* lpPos = (FX_WCHAR*)(const FX_WCHAR*)wsText; for (i = 0; i < nLength; i++, lpPos++) { if (*lpPos == m_wLineEnd) { *lpPos = wc; PosArr.Add(i); } } const FX_WCHAR* lpSrcBuf = wsText.c_str(); CFX_WideString wsTemp; int32_t nCount = PosArr.GetSize(); FX_WCHAR* lpDstBuf = wsTemp.GetBuffer(nLength + nCount); int32_t nDstPos = 0; int32_t nSrcPos = 0; for (i = 0; i < nCount; i++) { int32_t nPos = PosArr[i]; int32_t nCopyLen = nPos - nSrcPos + 1; FXSYS_memcpy(lpDstBuf + nDstPos, lpSrcBuf + nSrcPos, nCopyLen * sizeof(FX_WCHAR)); nDstPos += nCopyLen; nSrcPos += nCopyLen; lpDstBuf[nDstPos] = L'\n'; nDstPos++; } if (nSrcPos < nLength) { FXSYS_memcpy(lpDstBuf + nDstPos, lpSrcBuf + nSrcPos, (nLength - nSrcPos) * sizeof(FX_WCHAR)); } wsTemp.ReleaseBuffer(nLength + nCount); wsText = wsTemp; } else { int32_t nLength = wsText.GetLength(); FX_WCHAR* lpBuf = (FX_WCHAR*)(const FX_WCHAR*)wsText; for (int32_t i = 0; i < nLength; i++, lpBuf++) { if (*lpBuf == m_wLineEnd) { *lpBuf = wc; } } } } int32_t CFDE_TxtEdtEngine::MovePage2Char(int32_t nIndex) { FXSYS_assert(nIndex >= 0); FXSYS_assert(nIndex <= m_pTxtBuf->GetTextLength()); if (m_nCaretPage >= 0) { IFDE_TxtEdtPage* pPage = m_PagePtrArray[m_nCaretPage]; m_Param.pEventSink->On_PageLoad(this, m_nCaretPage, 0); int32_t nPageCharStart = pPage->GetCharStart(); int32_t nPageCharCount = pPage->GetCharCount(); if (nIndex >= nPageCharStart && nIndex < nPageCharStart + nPageCharCount) { m_Param.pEventSink->On_PageUnload(this, m_nCaretPage, 0); return m_nCaretPage; } m_Param.pEventSink->On_PageUnload(this, m_nCaretPage, 0); } CFDE_TxtEdtParag* pParag = NULL; int32_t nLineCount = 0; int32_t nParagCount = m_ParagPtrArray.GetSize(); int32_t i = 0; for (i = 0; i < nParagCount; i++) { pParag = m_ParagPtrArray[i]; if (pParag->m_nCharStart <= nIndex && nIndex < (pParag->m_nCharStart + pParag->m_nCharCount)) { break; } nLineCount += pParag->m_nLineCount; } pParag->LoadParag(); int32_t nLineStart = -1; int32_t nLineCharCount = -1; for (i = 0; i < pParag->m_nLineCount; i++) { pParag->GetLineRange(i, nLineStart, nLineCharCount); if (nLineStart <= nIndex && nIndex < (nLineStart + nLineCharCount)) { break; } } FXSYS_assert(i < pParag->m_nLineCount); nLineCount += (i + 1); m_nCaretPage = (nLineCount - 1) / m_nPageLineCount + 1 - 1; m_Param.pEventSink->On_PageChange(this, m_nCaretPage); pParag->UnloadParag(); return m_nCaretPage; } void CFDE_TxtEdtEngine::TextPos2ParagPos(int32_t nIndex, FDE_TXTEDTPARAGPOS& ParagPos) const { FXSYS_assert(nIndex >= 0 && nIndex < m_pTxtBuf->GetTextLength()); int32_t nCount = m_ParagPtrArray.GetSize(); int32_t nBgn = 0; int32_t nMid = 0; int32_t nEnd = nCount - 1; while (nEnd > nBgn) { nMid = (nBgn + nEnd) / 2; CFDE_TxtEdtParag* pParag = m_ParagPtrArray[nMid]; if (nIndex < pParag->m_nCharStart) { nEnd = nMid - 1; } else if (nIndex >= (pParag->m_nCharStart + pParag->m_nCharCount)) { nBgn = nMid + 1; } else { break; } } if (nBgn == nEnd) { nMid = nBgn; } FXSYS_assert(nIndex >= m_ParagPtrArray[nMid]->m_nCharStart && (nIndex < m_ParagPtrArray[nMid]->m_nCharStart + m_ParagPtrArray[nMid]->m_nCharCount)); ParagPos.nParagIndex = nMid; ParagPos.nCharIndex = nIndex - m_ParagPtrArray[nMid]->m_nCharStart; } int32_t CFDE_TxtEdtEngine::MoveForward(FX_BOOL& bBefore) { if (m_nCaret == m_pTxtBuf->GetTextLength() - 1) { return -1; } int32_t nCaret = m_nCaret; if ((nCaret + 1 < m_pTxtBuf->GetTextLength()) && (m_pTxtBuf->GetCharByIndex(nCaret) == L'\r') && (m_pTxtBuf->GetCharByIndex(nCaret + 1) == L'\n')) { nCaret++; } nCaret++; bBefore = TRUE; return nCaret; } int32_t CFDE_TxtEdtEngine::MoveBackward(FX_BOOL& bBefore) { if (m_nCaret == 0) { return FALSE; } int32_t nCaret = m_nCaret; if (nCaret > 2 && m_pTxtBuf->GetCharByIndex(nCaret - 1) == L'\n' && m_pTxtBuf->GetCharByIndex(nCaret - 2) == L'\r') { nCaret--; } nCaret--; bBefore = TRUE; return nCaret; } FX_BOOL CFDE_TxtEdtEngine::MoveUp(CFX_PointF& ptCaret) { IFDE_TxtEdtPage* pPage = GetPage(m_nCaretPage); const CFX_RectF& rtContent = pPage->GetContentsBox(); if (m_Param.dwLayoutStyles & FDE_TEXTEDITLAYOUT_DocVertical) { ptCaret.x = m_rtCaret.left + m_rtCaret.width / 2 - m_Param.fLineSpace; ptCaret.y = m_fCaretPosReserve; FX_BOOL bLineReserve = m_Param.dwLayoutStyles & FDE_TEXTEDITLAYOUT_LineReserve; if (ptCaret.x < rtContent.left) { if (bLineReserve) { if (m_nCaretPage == CountPages() - 1) { return FALSE; } } else { if (m_nCaretPage == 0) { return FALSE; } } if (bLineReserve) { m_nCaretPage++; } else { m_nCaretPage--; } m_Param.pEventSink->On_PageChange(this, m_nCaretPage); ptCaret.x -= rtContent.left; IFDE_TxtEdtPage* pCurPage = GetPage(m_nCaretPage); ptCaret.x += pCurPage->GetContentsBox().right(); } } else { ptCaret.x = m_fCaretPosReserve; ptCaret.y = m_rtCaret.top + m_rtCaret.height / 2 - m_Param.fLineSpace; if (ptCaret.y < rtContent.top) { if (m_nCaretPage == 0) { return FALSE; } ptCaret.y -= rtContent.top; m_nCaretPage--; m_Param.pEventSink->On_PageChange(this, m_nCaretPage); IFDE_TxtEdtPage* pCurPage = GetPage(m_nCaretPage); ptCaret.y += pCurPage->GetContentsBox().bottom(); } } return TRUE; } FX_BOOL CFDE_TxtEdtEngine::MoveDown(CFX_PointF& ptCaret) { IFDE_TxtEdtPage* pPage = GetPage(m_nCaretPage); const CFX_RectF& rtContent = pPage->GetContentsBox(); if (m_Param.dwLayoutStyles & FDE_TEXTEDITLAYOUT_DocVertical) { ptCaret.x = m_rtCaret.left + m_rtCaret.width / 2 + m_Param.fLineSpace; ptCaret.y = m_fCaretPosReserve; if (ptCaret.x >= rtContent.right()) { FX_BOOL bLineReserve = m_Param.dwLayoutStyles & FDE_TEXTEDITLAYOUT_LineReserve; if (bLineReserve) { if (m_nCaretPage == 0) { return FALSE; } } else { if (m_nCaretPage == CountPages() - 1) { return FALSE; } } if (bLineReserve) { m_nCaretPage--; } else { m_nCaretPage++; } m_Param.pEventSink->On_PageChange(this, m_nCaretPage); ptCaret.x -= rtContent.right(); IFDE_TxtEdtPage* pCurPage = GetPage(m_nCaretPage); ptCaret.x += pCurPage->GetContentsBox().left; } } else { ptCaret.x = m_fCaretPosReserve; ptCaret.y = m_rtCaret.top + m_rtCaret.height / 2 + m_Param.fLineSpace; if (ptCaret.y >= rtContent.bottom()) { if (m_nCaretPage == CountPages() - 1) { return FALSE; } ptCaret.y -= rtContent.bottom(); m_nCaretPage++; m_Param.pEventSink->On_PageChange(this, m_nCaretPage); IFDE_TxtEdtPage* pCurPage = GetPage(m_nCaretPage); ptCaret.y += pCurPage->GetContentsBox().top; } } return TRUE; } FX_BOOL CFDE_TxtEdtEngine::MoveLineStart() { int32_t nIndex = m_bBefore ? m_nCaret : m_nCaret - 1; FDE_TXTEDTPARAGPOS ParagPos; TextPos2ParagPos(nIndex, ParagPos); CFDE_TxtEdtParag* pParag = m_ParagPtrArray[ParagPos.nParagIndex]; pParag->LoadParag(); int32_t nLineCount = pParag->m_nLineCount; int32_t i = 0; int32_t nStart = 0; int32_t nCount = 0; for (; i < nLineCount; i++) { pParag->GetLineRange(i, nStart, nCount); if (nIndex >= nStart && nIndex < nStart + nCount) { break; } } UpdateCaretRect(nStart, TRUE); pParag->UnloadParag(); return TRUE; } FX_BOOL CFDE_TxtEdtEngine::MoveLineEnd() { int32_t nIndex = m_bBefore ? m_nCaret : m_nCaret - 1; FDE_TXTEDTPARAGPOS ParagPos; TextPos2ParagPos(nIndex, ParagPos); CFDE_TxtEdtParag* pParag = m_ParagPtrArray[ParagPos.nParagIndex]; pParag->LoadParag(); int32_t nLineCount = pParag->m_nLineCount; int32_t i = 0; int32_t nStart = 0; int32_t nCount = 0; for (; i < nLineCount; i++) { pParag->GetLineRange(i, nStart, nCount); if (nIndex >= nStart && nIndex < nStart + nCount) { break; } } nIndex = nStart + nCount - 1; FXSYS_assert(nIndex <= GetTextBufLength()); FX_WCHAR wChar = m_pTxtBuf->GetCharByIndex(nIndex); FX_BOOL bBefore = FALSE; if (nIndex <= GetTextBufLength()) { if (wChar == L'\r') { bBefore = TRUE; } else if (wChar == L'\n' && nIndex > nStart) { bBefore = TRUE; nIndex--; wChar = m_pTxtBuf->GetCharByIndex(nIndex); if (wChar != L'\r') { nIndex++; } } } UpdateCaretRect(nIndex, bBefore); pParag->UnloadParag(); return TRUE; } FX_BOOL CFDE_TxtEdtEngine::MoveParagStart() { int32_t nIndex = m_bBefore ? m_nCaret : m_nCaret - 1; FDE_TXTEDTPARAGPOS ParagPos; TextPos2ParagPos(nIndex, ParagPos); CFDE_TxtEdtParag* pParag = m_ParagPtrArray[ParagPos.nParagIndex]; UpdateCaretRect(pParag->m_nCharStart, TRUE); return TRUE; } FX_BOOL CFDE_TxtEdtEngine::MoveParagEnd() { int32_t nIndex = m_bBefore ? m_nCaret : m_nCaret - 1; FDE_TXTEDTPARAGPOS ParagPos; TextPos2ParagPos(nIndex, ParagPos); CFDE_TxtEdtParag* pParag = m_ParagPtrArray[ParagPos.nParagIndex]; nIndex = pParag->m_nCharStart + pParag->m_nCharCount - 1; FX_WCHAR wChar = m_pTxtBuf->GetCharByIndex(nIndex); if (wChar == L'\n' && nIndex > 0) { nIndex--; wChar = m_pTxtBuf->GetCharByIndex(nIndex); if (wChar != L'\r') { nIndex++; } } UpdateCaretRect(nIndex, TRUE); return TRUE; } FX_BOOL CFDE_TxtEdtEngine::MoveHome() { UpdateCaretRect(0, TRUE); return TRUE; } FX_BOOL CFDE_TxtEdtEngine::MoveEnd() { UpdateCaretRect(GetTextBufLength(), TRUE); return TRUE; } #ifdef FDE_USEFORMATBLOCK int32_t CFDE_TxtEdtEngine::NormalizeCaretPos(int32_t nIndex, int32_t nFlags, FX_BOOL& bBefore) { bBefore = TRUE; int32_t nBgn = 0, nEnd = 0; int32_t nRecord = -1; CFDE_TxtEdtField* pField = NULL; FX_BOOL bRet = GetFieldBoundary(nIndex, nBgn, nEnd, pField); int32_t nDelta = 0; if (bRet && !pField->IsFix()) { if (nIndex - nBgn < FDE_FORMAT_EDIT_FIELD_HADERSIZE) { if (nFlags == FDE_FORMAT_CARET_BACKWARD) { CFDE_TxtEdtField* pEditableField = NULL; if (FindEditableField(nIndex, nBgn, nEnd, pEditableField, FALSE)) { return pEditableField->NormalizeCaretPos(nEnd - nBgn, FDE_FORMAT_CARET_BACKWARD) + nBgn; } } nIndex = nBgn + FDE_FORMAT_EDIT_FIELD_HADERSIZE; } int32_t nRet = pField->NormalizeCaretPos( nIndex - nBgn, (FDE_FORMAT_CARET_DIRECTION)nFlags); if (nRet >= 0) { return nRet + nBgn; } if (nRet == -2) { int32_t nEditablePosBgn = 0, nEditablePosEnd = 0; pField->GetEditableRange(nEditablePosBgn, nEditablePosEnd); nRecord = nBgn + nEditablePosBgn; nFlags = FDE_FORMAT_CARET_BACKWARD; } else { FXSYS_assert(nRet == -1); int32_t nEditablePosBgn = 0, nEditablePosEnd = 0; pField->GetEditableRange(nEditablePosBgn, nEditablePosEnd); nRecord = nBgn + nEditablePosEnd; nFlags = FDE_FORMAT_CARET_FORWARD; } } else if (!bRet) { nDelta = FDE_FORMAT_EDIT_FIELD_HADERSIZE - FDE_FORMAT_EDIT_FIELD_TAILSIZE; } switch (nFlags) { case FDE_FORMAT_CARET_FORWARD: { if (FindEditableField(nIndex, nBgn, nEnd, pField)) { return pField->NormalizeCaretPos(FDE_FORMAT_EDIT_FIELD_HADERSIZE, FDE_FORMAT_CARET_FORWARD) + nBgn; } else { if (nRecord != -1) { return nRecord; } bRet = FindEditableField(nIndex, nBgn, nEnd, pField, FALSE); FXSYS_assert(bRet); return pField->NormalizeCaretPos(nEnd - nBgn, FDE_FORMAT_CARET_BACKWARD) + nBgn; } } break; case FDE_FORMAT_CARET_MIDDLE: { int32_t nBgn1 = 0, nEnd1 = 0, nBgn2 = 0, nEnd2 = 0; CFDE_TxtEdtField* pEditableField1 = NULL; CFDE_TxtEdtField* pEditableField2 = NULL; FX_BOOL bRet1 = FindEditableField(nIndex, nBgn1, nEnd1, pEditableField1, FALSE); FX_BOOL bRet2 = FindEditableField(nIndex, nBgn2, nEnd2, pEditableField2); if (bRet1 == FALSE) { FXSYS_assert(bRet2); return pEditableField2->NormalizeCaretPos( FDE_FORMAT_EDIT_FIELD_HADERSIZE, FDE_FORMAT_CARET_FORWARD) + nBgn2; } else if (bRet2 == FALSE) { FXSYS_assert(bRet1); return pEditableField1->NormalizeCaretPos(nEnd1 - nBgn1, FDE_FORMAT_CARET_BACKWARD) + nBgn1; } else { int32_t nEditablePosBgn = 0, nEditablePosEnd = 0; if (nIndex - nEnd1 < nBgn2 + nDelta - nIndex) { pEditableField1->GetEditableRange(nEditablePosBgn, nEditablePosEnd); return nEditablePosEnd + nBgn1; } else { pEditableField2->GetEditableRange(nEditablePosBgn, nEditablePosEnd); return nEditablePosBgn + nBgn2; } } } break; case FDE_FORMAT_CARET_BACKWARD: { if (FindEditableField(nIndex, nBgn, nEnd, pField, FALSE)) { return pField->NormalizeCaretPos(nEnd - nBgn, FDE_FORMAT_CARET_BACKWARD) + nBgn; } else { if (nRecord != -1) { return nRecord; } bRet = FindEditableField(nIndex, nBgn, nEnd, pField); FXSYS_assert(bRet); return pField->NormalizeCaretPos(FDE_FORMAT_EDIT_FIELD_HADERSIZE, FDE_FORMAT_CARET_FORWARD) + nBgn; } } break; default: FXSYS_assert(0); return nIndex; } } FX_BOOL CFDE_TxtEdtEngine::GetFieldBoundary(int32_t nIndex, int32_t& nBgn, int32_t& nEnd, CFDE_TxtEdtField*& pField) { CFDE_TxtEdtBufIter* pIter = new CFDE_TxtEdtBufIter((CFDE_TxtEdtBuf*)m_pTxtBuf, FALSE); pIter->SetAt(nIndex); FX_BOOL bFind = FALSE; do { FX_WCHAR wc = pIter->GetChar(); if (wc == FDE_TXTEDT_FORMATBLOCK_END) { nEnd = pIter->GetAt(); bFind = TRUE; nIndex--; break; } if (wc == FDE_TXTEDT_FORMATBLOCK_BGN) { pIter->Release(); return FALSE; } } while (pIter->Next()); if (!bFind) { pIter->Release(); return FALSE; } pIter->SetAt(nIndex); do { FX_WCHAR wc = pIter->GetChar(); if (wc == FDE_TXTEDT_FORMATBLOCK_BGN) { nBgn = pIter->GetAt(); pIter->Next(); FX_DWORD dwPre = (FX_DWORD)pIter->GetChar(); pIter->Next(); FX_DWORD dwCur = (FX_DWORD)pIter->GetChar(); pField = (CFDE_TxtEdtField*)((dwCur << 16) | dwPre); pIter->Release(); return TRUE; } if (wc == FDE_TXTEDT_FORMATBLOCK_END) { pIter->Release(); return FALSE; } } while (pIter->Next(TRUE)); pIter->Release(); return FALSE; } FX_BOOL CFDE_TxtEdtEngine::FindEditableField(int32_t nIndex, int32_t& nBgn, int32_t& nEnd, CFDE_TxtEdtField*& pField, FX_BOOL bForward) { FX_WCHAR wcFirst = FDE_TXTEDT_FORMATBLOCK_BGN; FX_WCHAR wcSecond = FDE_TXTEDT_FORMATBLOCK_END; if (!bForward) { wcFirst = FDE_TXTEDT_FORMATBLOCK_END; wcSecond = FDE_TXTEDT_FORMATBLOCK_BGN; } CFDE_TxtEdtBufIter* pIter = new CFDE_TxtEdtBufIter((CFDE_TxtEdtBuf*)m_pTxtBuf, FALSE); pIter->SetAt(nIndex); int32_t bFind = FALSE; do { FX_WCHAR wc = pIter->GetChar(); if (wc == wcFirst) { nBgn = pIter->GetAt(); bFind = TRUE; break; } } while (pIter->Next(!bForward)); if (!bFind) { pIter->Release(); return FALSE; } bFind = FALSE; do { FX_WCHAR wc = pIter->GetChar(); if (wc == wcSecond) { nEnd = pIter->GetAt(); bFind = TRUE; break; } } while (pIter->Next(!bForward)); FXSYS_assert(bFind); if (!bForward) { int32_t nTemp = nBgn; nBgn = nEnd; nEnd = nTemp; } pIter->SetAt(nBgn + 1); FX_DWORD dwPre = (FX_DWORD)pIter->GetChar(); pIter->Next(); FX_DWORD dwCur = (FX_DWORD)pIter->GetChar(); pField = (CFDE_TxtEdtField*)((dwCur << 16) | dwPre); pIter->Release(); if (!pField->IsFix()) { return TRUE; } return FindEditableField((bForward ? nEnd : nBgn), nBgn, nEnd, pField, bForward); } FX_BOOL CFDE_TxtEdtEngine::Move2NextEditableField(int32_t nIndex, FX_BOOL bForward, FX_BOOL bSelect) { if (m_SelRangePtrArr.GetSize() > 0) { ClearSelection(); m_Param.pEventSink->On_SelChanged(this); } int32_t nBgn = 0, nEnd = 0; CFDE_TxtEdtField* pField = NULL; FX_BOOL bRet = FindEditableField(nIndex, nBgn, nEnd, pField, bForward); if (!bRet) { return FALSE; } int32_t nEditableBgn = 0, nEditableEnd = 0; pField->GetEditableRange(nEditableBgn, nEditableEnd); nEditableBgn += nBgn; nEditableEnd += nBgn; if (bSelect) { int32_t nRangeCount = nEditableEnd - nEditableBgn; if (nRangeCount > 0) { AddSelRange(nEditableBgn, nEditableEnd - nEditableBgn); } } SetCaretPos(nEditableEnd, TRUE); return TRUE; } int32_t CFDE_TxtEdtEngine::GetRealIndex(int32_t nIndex) const { CFDE_TxtEdtBufIter* pIter = new CFDE_TxtEdtBufIter((CFDE_TxtEdtBuf*)m_pTxtBuf, FALSE); pIter->SetAt(0); FX_BOOL bInField = FALSE; int32_t nFieldBgn = 0; int32_t nRealIndex = 0; for (int32_t i = 0; i <= nIndex; i++) { FX_WCHAR wc = pIter->GetChar(); if (bInField) { if (wc == FDE_TXTEDT_FORMATBLOCK_END) { FX_DWORD dwPre = (FX_DWORD)m_pTxtBuf->GetCharByIndex(nFieldBgn + 1); FX_DWORD dwCur = (FX_DWORD)m_pTxtBuf->GetCharByIndex(nFieldBgn + 2); CFDE_TxtEdtField* pField = (CFDE_TxtEdtField*)((dwCur << 16) | dwPre); nRealIndex += pField->GetFieldTextLength(); bInField = FALSE; } } else { if (wc == FDE_TXTEDT_FORMATBLOCK_BGN) { bInField = TRUE; nFieldBgn = pIter->GetAt(); } else { nRealIndex++; } } pIter->Next(); } if (!bInField) { pIter->Release(); return nRealIndex; } pIter->SetAt(nFieldBgn + 1); FX_DWORD dwPre = (FX_DWORD)pIter->GetChar(); pIter->Next(); FX_DWORD dwCur = (FX_DWORD)pIter->GetChar(); CFDE_TxtEdtField* pField = (CFDE_TxtEdtField*)((dwCur << 16) | dwPre); pIter->Release(); if (pField->IsFix()) { int32_t nDelta = nIndex - nFieldBgn - FDE_FORMAT_EDIT_FIELD_HADERSIZE + 1; return nRealIndex + (nDelta > 0 ? nDelta : 0); } else { return nRealIndex + pField->GetRealIndex(nIndex - nFieldBgn); } } #endif FX_BOOL CFDE_TxtEdtEngine::IsFitArea(CFX_WideString& wsText) { IFDE_TextOut* pTextOut = IFDE_TextOut::Create(); pTextOut->SetLineSpace(m_Param.fLineSpace); pTextOut->SetFont(m_Param.pFont); pTextOut->SetFontSize(m_Param.fFontSize); CFX_RectF rcText; FXSYS_memset(&rcText, 0, sizeof(rcText)); FX_DWORD dwStyle = 0; if (!(m_Param.dwMode & FDE_TEXTEDITMODE_MultiLines)) { dwStyle |= FDE_TTOSTYLE_SingleLine; } if (m_Param.dwMode & FDE_TEXTEDITMODE_AutoLineWrap) { dwStyle |= FDE_TTOSTYLE_LineWrap; rcText.width = m_Param.fPlateWidth; } else { rcText.width = 65535; } pTextOut->SetStyles(dwStyle); wsText += L"\n"; pTextOut->CalcLogicSize(wsText, wsText.GetLength(), rcText); pTextOut->Release(); wsText.Delete(wsText.GetLength() - 1); if ((m_Param.dwMode & FDE_TEXTEDITMODE_LimitArea_Horz) && (rcText.width > m_Param.fPlateWidth)) { return FALSE; } if ((m_Param.dwMode & FDE_TEXTEDITMODE_LimitArea_Vert) && (rcText.height > m_Param.fLineSpace * m_Param.nLineCount)) { return FALSE; } return TRUE; } void CFDE_TxtEdtEngine::UpdateCaretRect(int32_t nIndex, FX_BOOL bBefore) { MovePage2Char(nIndex); GetCaretRect(m_rtCaret, m_nCaretPage, nIndex, bBefore); m_nCaret = nIndex; m_bBefore = bBefore; if (!m_bBefore) { m_nCaret++; m_bBefore = TRUE; } m_fCaretPosReserve = (m_Param.dwLayoutStyles & FDE_TEXTEDITLAYOUT_DocVertical) ? m_rtCaret.top : m_rtCaret.left; m_Param.pEventSink->On_CaretChanged(this, m_nCaretPage, 0); } void CFDE_TxtEdtEngine::GetCaretRect(CFX_RectF& rtCaret, int32_t nPageIndex, int32_t nCaret, FX_BOOL bBefore) { IFDE_TxtEdtPage* pPage = m_PagePtrArray[m_nCaretPage]; m_Param.pEventSink->On_PageLoad(this, m_nCaretPage, 0); FX_BOOL bCombText = m_Param.dwLayoutStyles & FDE_TEXTEDITLAYOUT_CombText; int32_t nIndexInpage = nCaret - pPage->GetCharStart(); if (bBefore && bCombText && nIndexInpage > 0) { nIndexInpage--; bBefore = FALSE; } int32_t nBIDILevel = pPage->GetCharRect(nIndexInpage, rtCaret, bCombText); if (m_Param.dwLayoutStyles & FDE_TEXTEDITLAYOUT_DocVertical) { if ((!FX_IsOdd(nBIDILevel) && !bBefore) || (FX_IsOdd(nBIDILevel) && bBefore)) { rtCaret.Offset(0, rtCaret.height - 1.0f); } if (rtCaret.height == 0 && rtCaret.top > 1.0f) { rtCaret.top -= 1.0f; } rtCaret.height = 1.0f; } else { if ((!FX_IsOdd(nBIDILevel) && !bBefore) || (FX_IsOdd(nBIDILevel) && bBefore)) { rtCaret.Offset(rtCaret.width - 1.0f, 0); } if (rtCaret.width == 0 && rtCaret.left > 1.0f) { rtCaret.left -= 1.0f; } rtCaret.width = 1.0f; } m_Param.pEventSink->On_PageUnload(this, m_nCaretPage, 0); } void CFDE_TxtEdtEngine::UpdateCaretIndex(const CFX_PointF& ptCaret) { IFDE_TxtEdtPage* pPage = m_PagePtrArray[m_nCaretPage]; m_Param.pEventSink->On_PageLoad(this, m_nCaretPage, 0); m_nCaret = pPage->GetCharIndex(ptCaret, m_bBefore); GetCaretRect(m_rtCaret, m_nCaretPage, m_nCaret, m_bBefore); if (!m_bBefore) { m_nCaret++; m_bBefore = TRUE; } m_Param.pEventSink->On_CaretChanged(this, m_nCaretPage); m_Param.pEventSink->On_PageUnload(this, m_nCaretPage, 0); } FX_BOOL CFDE_TxtEdtEngine::IsSelect() { return m_SelRangePtrArr.GetSize() > 0; } void CFDE_TxtEdtEngine::DeleteSelect() { int32_t nCountRange = CountSelRanges(); if (nCountRange > 0) { #ifdef FDE_USEFORMATBLOCK int32_t nBlockCount = m_BlockArray.GetSize(); if (nBlockCount > 0) { if (nCountRange > 1) { return; } int32_t nSelStart; int32_t nSelCount; nSelCount = GetSelRange(0, nSelStart); int32_t nSelEnd = nSelStart + nSelCount; int32_t nBgn = 0; int32_t nEnd = 0; CFDE_TxtEdtField* pField = NULL; FX_BOOL bInField = GetFieldBoundary(nSelStart, nBgn, nEnd, pField); int32_t nCaretInField = nSelStart - nBgn; FX_BOOL bBefore = FALSE; if (!bInField || pField->IsFix() || nSelEnd > nEnd) { return; } pField->Backup(); CFX_WideString wsDel; int32_t nCaret = 0; int32_t nRet = pField->Delete(nCaretInField, nSelCount, wsDel, nCaret, bBefore); nCaret += nBgn; switch (nRet) { case FDE_FORMAT_FIELD_DELETE_RET_S: break; case FDE_FORMAT_FIELD_DELETE_RET_F_INVALIDATE: case FDE_FORMAT_FIELD_DELETE_RET_F_BOUNDARY: return; default: FXSYS_assert(0); break; } CFX_WideString wsField; pField->GetFieldText(wsField); if (!m_Param.pEventSink->On_ValidateField( this, pField->GetBlockIndex(), pField->GetIndex(), wsField, 0)) { pField->Restore(); return; } CFX_WideString wsDisplay; pField->GetDisplayText(wsDisplay); Replace(nBgn, nEnd - nBgn + 1, wsDisplay); if (!(m_Param.dwMode & FDE_TEXTEDITMODE_NoRedoUndo)) { IFDE_TxtEdtDoRecord* pRecord = new CFDE_TxtEdtDoRecord_FieldDelete( this, nSelStart, pField, nCaretInField, nBgn, nEnd - nBgn + 1, wsDisplay.GetLength(), wsDel, FALSE); CFX_ByteString bsDoRecord; pRecord->Serialize(bsDoRecord); m_Param.pEventSink->On_AddDoRecord(this, bsDoRecord); pRecord->Release(); } SetCaretPos(nSelStart, bBefore); return; } #endif int32_t nSelStart; int32_t nSelCount; while (nCountRange > 0) { nSelCount = GetSelRange(--nCountRange, nSelStart); FDE_LPTXTEDTSELRANGE lpTemp = m_SelRangePtrArr[nCountRange]; delete lpTemp; m_SelRangePtrArr.RemoveAt(nCountRange); DeleteRange_DoRecord(nSelStart, nSelCount, TRUE); } ClearSelection(); m_Param.pEventSink->On_TextChanged(this, m_ChangeInfo); m_Param.pEventSink->On_SelChanged(this); SetCaretPos(nSelStart, TRUE); return; } } IFDE_TxtEdtDoRecord* IFDE_TxtEdtDoRecord::Create( const CFX_ByteStringC& bsDoRecord) { const FX_CHAR* lpBuf = bsDoRecord.GetCStr(); int32_t nType = *((int32_t*)lpBuf); switch (nType) { case FDE_TXTEDT_DORECORD_INS: return new CFDE_TxtEdtDoRecord_Insert(bsDoRecord); case FDE_TXTEDT_DORECORD_DEL: return new CFDE_TxtEdtDoRecord_DeleteRange(bsDoRecord); #ifdef FDE_USEFORMATBLOCK case FDE_TXTEDT_DORECORD_FORMATINS: return new CFDE_TxtEdtDoRecord_FieldInsert(bsDoRecord); case FDE_TXTEDT_DORECORD_FORMATDEL: return new CFDE_TxtEdtDoRecord_FieldDelete(bsDoRecord); case FDE_TXTEDT_DORECORD_FORMATREP: return new CFDE_TxtEdtDoRecord_FieldReplace(bsDoRecord); #endif default: break; } return NULL; } CFDE_TxtEdtDoRecord_Insert::CFDE_TxtEdtDoRecord_Insert( const CFX_ByteStringC& bsDoRecord) { Deserialize(bsDoRecord); } CFDE_TxtEdtDoRecord_Insert::CFDE_TxtEdtDoRecord_Insert( CFDE_TxtEdtEngine* pEngine, int32_t nCaret, const FX_WCHAR* lpText, int32_t nLength) : m_pEngine(pEngine), m_nCaret(nCaret) { FXSYS_assert(pEngine); FX_WCHAR* lpBuffer = m_wsInsert.GetBuffer(nLength); FXSYS_memcpy(lpBuffer, lpText, nLength * sizeof(FX_WCHAR)); m_wsInsert.ReleaseBuffer(); } CFDE_TxtEdtDoRecord_Insert::~CFDE_TxtEdtDoRecord_Insert() {} void CFDE_TxtEdtDoRecord_Insert::Release() { delete this; } FX_BOOL CFDE_TxtEdtDoRecord_Insert::Undo() { if (m_pEngine->IsSelect()) { m_pEngine->ClearSelection(); } m_pEngine->Inner_DeleteRange(m_nCaret, m_wsInsert.GetLength()); FDE_TXTEDTPARAMS& Param = m_pEngine->m_Param; m_pEngine->m_ChangeInfo.nChangeType = FDE_TXTEDT_TEXTCHANGE_TYPE_Delete; m_pEngine->m_ChangeInfo.wsDelete = m_wsInsert; Param.pEventSink->On_TextChanged(m_pEngine, m_pEngine->m_ChangeInfo); m_pEngine->SetCaretPos(m_nCaret, TRUE); return TRUE; } FX_BOOL CFDE_TxtEdtDoRecord_Insert::Redo() { m_pEngine->Inner_Insert(m_nCaret, m_wsInsert.c_str(), m_wsInsert.GetLength()); FDE_TXTEDTPARAMS& Param = m_pEngine->m_Param; m_pEngine->m_ChangeInfo.nChangeType = FDE_TXTEDT_TEXTCHANGE_TYPE_Insert; m_pEngine->m_ChangeInfo.wsDelete = m_wsInsert; Param.pEventSink->On_TextChanged(m_pEngine, m_pEngine->m_ChangeInfo); m_pEngine->SetCaretPos(m_nCaret, FALSE); return TRUE; } void CFDE_TxtEdtDoRecord_Insert::Serialize(CFX_ByteString& bsDoRecord) const { CFX_ArchiveSaver ArchiveSaver; ArchiveSaver << int32_t(FDE_TXTEDT_DORECORD_INS); ArchiveSaver << (int32_t)(uintptr_t)m_pEngine; ArchiveSaver << m_nCaret; ArchiveSaver << m_wsInsert; int32_t nLength = ArchiveSaver.GetLength(); const uint8_t* lpSrcBuf = ArchiveSaver.GetBuffer(); FX_CHAR* lpDstBuf = bsDoRecord.GetBuffer(nLength); FXSYS_memcpy(lpDstBuf, lpSrcBuf, nLength); bsDoRecord.ReleaseBuffer(nLength); } void CFDE_TxtEdtDoRecord_Insert::Deserialize( const CFX_ByteStringC& bsDoRecord) { CFX_ArchiveLoader ArchiveLoader((const uint8_t*)bsDoRecord.GetCStr(), bsDoRecord.GetLength()); int32_t nType = 0; ArchiveLoader >> nType; FXSYS_assert(nType == FDE_TXTEDT_DORECORD_INS); int32_t nEngine = 0; ArchiveLoader >> nEngine; m_pEngine = (CFDE_TxtEdtEngine*)(uintptr_t)nEngine; ArchiveLoader >> m_nCaret; ArchiveLoader >> m_wsInsert; } CFDE_TxtEdtDoRecord_DeleteRange::CFDE_TxtEdtDoRecord_DeleteRange( const CFX_ByteStringC& bsDoRecord) { Deserialize(bsDoRecord); } CFDE_TxtEdtDoRecord_DeleteRange::CFDE_TxtEdtDoRecord_DeleteRange( CFDE_TxtEdtEngine* pEngine, int32_t nIndex, int32_t nCaret, const CFX_WideString& wsRange, FX_BOOL bSel) : m_pEngine(pEngine), m_bSel(bSel), m_nIndex(nIndex), m_nCaret(nCaret), m_wsRange(wsRange) { FXSYS_assert(pEngine); } CFDE_TxtEdtDoRecord_DeleteRange::~CFDE_TxtEdtDoRecord_DeleteRange() {} void CFDE_TxtEdtDoRecord_DeleteRange::Release() { delete this; } FX_BOOL CFDE_TxtEdtDoRecord_DeleteRange::Undo() { if (m_pEngine->IsSelect()) { m_pEngine->ClearSelection(); } m_pEngine->Inner_Insert(m_nIndex, m_wsRange.c_str(), m_wsRange.GetLength()); if (m_bSel) { m_pEngine->AddSelRange(m_nIndex, m_wsRange.GetLength()); } FDE_TXTEDTPARAMS& Param = m_pEngine->m_Param; m_pEngine->m_ChangeInfo.nChangeType = FDE_TXTEDT_TEXTCHANGE_TYPE_Insert; m_pEngine->m_ChangeInfo.wsDelete = m_wsRange; Param.pEventSink->On_TextChanged(m_pEngine, m_pEngine->m_ChangeInfo); m_pEngine->SetCaretPos(m_nCaret, TRUE); return TRUE; } FX_BOOL CFDE_TxtEdtDoRecord_DeleteRange::Redo() { m_pEngine->Inner_DeleteRange(m_nIndex, m_wsRange.GetLength()); if (m_bSel) { m_pEngine->RemoveSelRange(m_nIndex, m_wsRange.GetLength()); } FDE_TXTEDTPARAMS& Param = m_pEngine->m_Param; m_pEngine->m_ChangeInfo.nChangeType = FDE_TXTEDT_TEXTCHANGE_TYPE_Insert; m_pEngine->m_ChangeInfo.wsDelete = m_wsRange; Param.pEventSink->On_TextChanged(m_pEngine, m_pEngine->m_ChangeInfo); m_pEngine->SetCaretPos(m_nIndex, TRUE); return TRUE; } void CFDE_TxtEdtDoRecord_DeleteRange::Serialize( CFX_ByteString& bsDoRecord) const { CFX_ArchiveSaver ArchiveSaver; ArchiveSaver << int32_t(FDE_TXTEDT_DORECORD_DEL); ArchiveSaver << (int32_t)(uintptr_t)m_pEngine; ArchiveSaver << (int32_t)m_bSel; ArchiveSaver << m_nIndex; ArchiveSaver << m_nCaret; ArchiveSaver << m_wsRange; int32_t nLength = ArchiveSaver.GetLength(); const uint8_t* lpSrcBuf = ArchiveSaver.GetBuffer(); FX_CHAR* lpDstBuf = bsDoRecord.GetBuffer(nLength); FXSYS_memcpy(lpDstBuf, lpSrcBuf, nLength); bsDoRecord.ReleaseBuffer(nLength); } void CFDE_TxtEdtDoRecord_DeleteRange::Deserialize( const CFX_ByteStringC& bsDoRecord) { CFX_ArchiveLoader ArchiveLoader((const uint8_t*)bsDoRecord.GetCStr(), bsDoRecord.GetLength()); int32_t nType = 0; ArchiveLoader >> nType; FXSYS_assert(nType == FDE_TXTEDT_DORECORD_DEL); int32_t nEngine = 0; ArchiveLoader >> nEngine; m_pEngine = (CFDE_TxtEdtEngine*)(uintptr_t)nEngine; int32_t iSel = 0; ArchiveLoader >> iSel; m_bSel = !!iSel; ArchiveLoader >> m_nIndex; ArchiveLoader >> m_nCaret; ArchiveLoader >> m_wsRange; } #ifdef FDE_USEFORMATBLOCK CFDE_TxtEdtDoRecord_FieldInsert::CFDE_TxtEdtDoRecord_FieldInsert( const CFX_ByteStringC& bsDoRecord) { Deserialize(bsDoRecord); } CFDE_TxtEdtDoRecord_FieldInsert::CFDE_TxtEdtDoRecord_FieldInsert( CFDE_TxtEdtEngine* pEngine, int32_t nCaret, CFDE_TxtEdtField* pField, int32_t nIndexInField, int32_t nFieldBgn, int32_t nOldFieldLength, int32_t nNewFieldLength, const CFX_WideString& wsIns, FX_BOOL bSel) : m_pEngine(pEngine), m_nCaret(nCaret), m_pField(pField), m_nIndexInField(nIndexInField), m_nFieldBgn(nFieldBgn), m_nOldFieldLength(nOldFieldLength), m_nNewFieldLength(nNewFieldLength), m_wsIns(wsIns), m_bSel(bSel) { FXSYS_assert(pEngine); FXSYS_assert(pField); } CFDE_TxtEdtDoRecord_FieldInsert::~CFDE_TxtEdtDoRecord_FieldInsert() {} void CFDE_TxtEdtDoRecord_FieldInsert::Release() { delete this; } FX_BOOL CFDE_TxtEdtDoRecord_FieldInsert::Undo() { CFX_WideString wsDel; int32_t nCaret = 0; FX_BOOL bBefore = FALSE; int32_t nRet = m_pField->Delete(m_nIndexInField, m_wsIns.GetLength(), wsDel, nCaret, bBefore); FXSYS_assert(nRet != FDE_FORMAT_FIELD_DELETE_RET_F_INVALIDATE && nRet != FDE_FORMAT_FIELD_DELETE_RET_F_BOUNDARY); CFX_WideString wsDisplay; m_pField->GetDisplayText(wsDisplay); m_pEngine->Replace(m_nFieldBgn, m_nNewFieldLength, wsDisplay); m_pEngine->SetCaretPos(m_nCaret, TRUE); return TRUE; } FX_BOOL CFDE_TxtEdtDoRecord_FieldInsert::Redo() { int32_t nCaret = 0; FX_BOOL bBefore = FALSE; int32_t nRet = m_pField->Insert(m_nIndexInField, m_wsIns, nCaret, bBefore); FXSYS_assert(nRet != FDE_FORMAT_FIELD_INSERT_RET_F_FULL && nRet != FDE_FORMAT_FIELD_INSERT_RET_F_INVALIDATE); CFX_WideString wsDisplay; m_pField->GetDisplayText(wsDisplay); m_pEngine->Replace(m_nFieldBgn, m_nOldFieldLength, wsDisplay); m_pEngine->SetCaretPos(m_nCaret + m_wsIns.GetLength(), TRUE); return TRUE; } void CFDE_TxtEdtDoRecord_FieldInsert::Serialize( CFX_ByteString& bsDoRecord) const { CFX_ArchiveSaver ArchiveSaver; ArchiveSaver << int32_t(FDE_TXTEDT_DORECORD_FORMATINS); ArchiveSaver << int32_t(m_pEngine); ArchiveSaver << m_nCaret; ArchiveSaver << int32_t(m_pField); ArchiveSaver << m_nIndexInField; ArchiveSaver << m_nFieldBgn; ArchiveSaver << m_nOldFieldLength; ArchiveSaver << m_nNewFieldLength; ArchiveSaver << m_wsIns; ArchiveSaver << m_bSel; int32_t nLength = ArchiveSaver.GetLength(); const uint8_t* lpSrcBuf = ArchiveSaver.GetBuffer(); FX_CHAR* lpDstBuf = bsDoRecord.GetBuffer(nLength); FXSYS_memcpy(lpDstBuf, lpSrcBuf, nLength); bsDoRecord.ReleaseBuffer(nLength); } void CFDE_TxtEdtDoRecord_FieldInsert::Deserialize( const CFX_ByteStringC& bsDoRecord) { CFX_ArchiveLoader ArchiveLoader((const uint8_t*)bsDoRecord.GetCStr(), bsDoRecord.GetLength()); int32_t nType = 0; ArchiveLoader >> nType; FXSYS_assert(nType == FDE_TXTEDT_DORECORD_FORMATINS); int32_t nEngine = 0; ArchiveLoader >> nEngine; m_pEngine = (CFDE_TxtEdtEngine*)(uintptr_t)nEngine; ArchiveLoader >> m_nCaret; int32_t nField = 0; ArchiveLoader >> nField; m_pField = (CFDE_TxtEdtField*)nField; ArchiveLoader >> m_nIndexInField; ArchiveLoader >> m_nFieldBgn; ArchiveLoader >> m_nOldFieldLength; ArchiveLoader >> m_nNewFieldLength; ArchiveLoader >> m_wsIns; ArchiveLoader >> m_bSel; } CFDE_TxtEdtDoRecord_FieldDelete::CFDE_TxtEdtDoRecord_FieldDelete( const CFX_ByteStringC& bsDoRecord) { Deserialize(bsDoRecord); } CFDE_TxtEdtDoRecord_FieldDelete::CFDE_TxtEdtDoRecord_FieldDelete( CFDE_TxtEdtEngine* pEngine, int32_t nCaret, CFDE_TxtEdtField* pField, int32_t nIndexInField, int32_t nFieldBgn, int32_t nOldLength, int32_t nNewLength, const CFX_WideString& wsDel, FX_BOOL bSel) : m_pEngine(pEngine), m_nCaret(nCaret), m_pField(pField), m_nIndexInField(nIndexInField), m_nFieldBgn(nFieldBgn), m_nOldFieldLength(nOldLength), m_nNewFieldLength(nNewLength), m_wsDel(wsDel), m_bSel(bSel) { FXSYS_assert(m_pEngine); FXSYS_assert(m_pField); } CFDE_TxtEdtDoRecord_FieldDelete::~CFDE_TxtEdtDoRecord_FieldDelete() {} void CFDE_TxtEdtDoRecord_FieldDelete::Release() { delete this; } FX_BOOL CFDE_TxtEdtDoRecord_FieldDelete::Undo() { int32_t nCaret = 0; FX_BOOL bBefore = FALSE; int32_t nRet = m_pField->Insert(m_nIndexInField, m_wsDel, nCaret, bBefore); FXSYS_assert(nRet != FDE_FORMAT_FIELD_INSERT_RET_F_FULL && nRet != FDE_FORMAT_FIELD_INSERT_RET_F_INVALIDATE); CFX_WideString wsDisplay; m_pField->GetDisplayText(wsDisplay); m_pEngine->Replace(m_nFieldBgn, m_nNewFieldLength, wsDisplay); m_pEngine->SetCaretPos(m_nCaret, TRUE); return TRUE; } FX_BOOL CFDE_TxtEdtDoRecord_FieldDelete::Redo() { int32_t nCaret = 0; FX_BOOL bBefore = 0; CFX_WideString wsDel; int32_t nRet = m_pField->Delete(m_nIndexInField, m_wsDel.GetLength(), wsDel, nCaret, bBefore); FXSYS_assert(nRet != FDE_FORMAT_FIELD_DELETE_RET_F_INVALIDATE && nRet != FDE_FORMAT_FIELD_DELETE_RET_F_BOUNDARY); CFX_WideString wsDisplay; m_pField->GetDisplayText(wsDisplay); m_pEngine->Replace(m_nFieldBgn, m_nOldFieldLength, wsDisplay); m_pEngine->SetCaretPos(m_nCaret - m_wsDel.GetLength(), TRUE); return TRUE; } void CFDE_TxtEdtDoRecord_FieldDelete::Serialize( CFX_ByteString& bsDoRecord) const { CFX_ArchiveSaver ArchiveSaver; ArchiveSaver << int32_t(FDE_TXTEDT_DORECORD_FORMATDEL); ArchiveSaver << int32_t(m_pEngine); ArchiveSaver << m_nCaret; ArchiveSaver << int32_t(m_pField); ArchiveSaver << m_nIndexInField; ArchiveSaver << m_nFieldBgn; ArchiveSaver << m_nOldFieldLength; ArchiveSaver << m_nNewFieldLength; ArchiveSaver << m_wsDel; ArchiveSaver << m_bSel; int32_t nLength = ArchiveSaver.GetLength(); const uint8_t* lpSrcBuf = ArchiveSaver.GetBuffer(); FX_CHAR* lpDstBuf = bsDoRecord.GetBuffer(nLength); FXSYS_memcpy(lpDstBuf, lpSrcBuf, nLength); bsDoRecord.ReleaseBuffer(nLength); } void CFDE_TxtEdtDoRecord_FieldDelete::Deserialize( const CFX_ByteStringC& bsDoRecord) { CFX_ArchiveLoader ArchiveLoader((const uint8_t*)bsDoRecord.GetCStr(), bsDoRecord.GetLength()); int32_t nType = 0; ArchiveLoader >> nType; FXSYS_assert(nType == FDE_TXTEDT_DORECORD_FORMATDEL); int32_t nEngine = 0; ArchiveLoader >> nEngine; m_pEngine = (CFDE_TxtEdtEngine*)(uintptr_t)nEngine; ArchiveLoader >> m_nCaret; int32_t nField = 0; ArchiveLoader >> nField; m_pField = (CFDE_TxtEdtField*)nField; ArchiveLoader >> m_nIndexInField; ArchiveLoader >> m_nFieldBgn; ArchiveLoader >> m_nOldFieldLength; ArchiveLoader >> m_nNewFieldLength; ArchiveLoader >> m_wsDel; ArchiveLoader >> m_bSel; } CFDE_TxtEdtDoRecord_FieldReplace::CFDE_TxtEdtDoRecord_FieldReplace( const CFX_ByteStringC& bsDoRecord) { Deserialize(bsDoRecord); } CFDE_TxtEdtDoRecord_FieldReplace::CFDE_TxtEdtDoRecord_FieldReplace( CFDE_TxtEdtEngine* pEngine, int32_t nCaret, int32_t nNewCaret, CFDE_TxtEdtField* pField, int32_t nIndexInField, int32_t nFieldBgn, int32_t nFieldNewLength, const CFX_WideString& wsDel, const CFX_WideString& wsIns, FX_BOOL bSel) : m_pEngine(pEngine), m_nCaret(nCaret), m_nNewCaret(nNewCaret), m_pField(pField), m_nIndexInField(nIndexInField), m_nFieldBgn(nFieldBgn), m_nFieldNewLength(nFieldNewLength), m_wsDel(wsDel), m_wsIns(wsIns), m_bSel(bSel) { FXSYS_assert(m_pEngine); FXSYS_assert(m_pField); } CFDE_TxtEdtDoRecord_FieldReplace::~CFDE_TxtEdtDoRecord_FieldReplace() {} void CFDE_TxtEdtDoRecord_FieldReplace::Release() { delete this; } FX_BOOL CFDE_TxtEdtDoRecord_FieldReplace::Undo() { CFX_WideString wsDel; int32_t nCaret = 0; FX_BOOL bBefore = FALSE; int32_t nRet = m_pField->Replace(m_nIndexInField, m_wsIns.GetLength(), m_wsDel, wsDel, nCaret, bBefore); FXSYS_assert(nRet != FDE_FORMAT_FIELD_DELETE_RET_F_INVALIDATE && nRet != FDE_FORMAT_FIELD_DELETE_RET_F_BOUNDARY); CFX_WideString wsDisplay; m_pField->GetDisplayText(wsDisplay); m_pEngine->Replace(m_nFieldBgn, m_nFieldNewLength, wsDisplay); m_pEngine->SetCaretPos(m_nCaret, TRUE); return TRUE; } FX_BOOL CFDE_TxtEdtDoRecord_FieldReplace::Redo() { CFX_WideString wsDel; int32_t nCaret = 0; FX_BOOL bBefore = FALSE; int32_t nRet = m_pField->Replace(m_nIndexInField, m_wsDel.GetLength(), m_wsIns, wsDel, nCaret, bBefore); FXSYS_assert(nRet != FDE_FORMAT_FIELD_DELETE_RET_F_INVALIDATE && nRet != FDE_FORMAT_FIELD_DELETE_RET_F_BOUNDARY); CFX_WideString wsDisplay; m_pField->GetDisplayText(wsDisplay); m_pEngine->Replace(m_nFieldBgn, m_nFieldNewLength, wsDisplay); m_pEngine->SetCaretPos(m_nNewCaret, TRUE); return TRUE; } void CFDE_TxtEdtDoRecord_FieldReplace::Serialize( CFX_ByteString& bsDoRecord) const { CFX_ArchiveSaver ArchiveSaver; ArchiveSaver << int32_t(FDE_TXTEDT_DORECORD_FORMATREP); ArchiveSaver << int32_t(m_pEngine); ArchiveSaver << m_nCaret; ArchiveSaver << m_nNewCaret; ArchiveSaver << int32_t(m_pField); ArchiveSaver << m_nIndexInField; ArchiveSaver << m_nFieldBgn; ArchiveSaver << m_nFieldNewLength; ArchiveSaver << m_wsDel; ArchiveSaver << m_wsIns; ArchiveSaver << m_bSel; int32_t nLength = ArchiveSaver.GetLength(); const uint8_t* lpSrcBuf = ArchiveSaver.GetBuffer(); FX_CHAR* lpDstBuf = bsDoRecord.GetBuffer(nLength); FXSYS_memcpy(lpDstBuf, lpSrcBuf, nLength); bsDoRecord.ReleaseBuffer(nLength); } void CFDE_TxtEdtDoRecord_FieldReplace::Deserialize( const CFX_ByteStringC& bsDoRecord) { CFX_ArchiveLoader ArchiveLoader((const uint8_t*)bsDoRecord.GetCStr(), bsDoRecord.GetLength()); int32_t nType = 0; ArchiveLoader >> nType; FXSYS_assert(nType == FDE_TXTEDT_DORECORD_FORMATREP); int32_t nEngine = 0; ArchiveLoader >> nEngine; m_pEngine = (CFDE_TxtEdtEngine*)(uintptr_t)nEngine; ArchiveLoader >> m_nCaret; ArchiveLoader >> m_nNewCaret; int32_t nField = 0; ArchiveLoader >> nField; m_pField = (CFDE_TxtEdtField*)nField; ArchiveLoader >> m_nIndexInField; ArchiveLoader >> m_nFieldBgn; ArchiveLoader >> m_nFieldNewLength; ArchiveLoader >> m_wsDel; ArchiveLoader >> m_wsIns; ArchiveLoader >> m_bSel; } #endif