// 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 <algorithm> | |
#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<int32_t> 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 |