summaryrefslogtreecommitdiff
path: root/xfa/fde/cfde_txtedtengine.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'xfa/fde/cfde_txtedtengine.cpp')
-rw-r--r--xfa/fde/cfde_txtedtengine.cpp1643
1 files changed, 1643 insertions, 0 deletions
diff --git a/xfa/fde/cfde_txtedtengine.cpp b/xfa/fde/cfde_txtedtengine.cpp
new file mode 100644
index 0000000000..3162d397ee
--- /dev/null
+++ b/xfa/fde/cfde_txtedtengine.cpp
@@ -0,0 +1,1643 @@
+// 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 "xfa/fde/cfde_txtedtengine.h"
+
+#include "xfa/fde/cfde_txtedtbuf.h"
+#include "xfa/fde/cfde_txtedtbufiter.h"
+#include "xfa/fde/ifx_chariter.h"
+#include "xfa/fgas/layout/fgas_textbreak.h"
+#include "xfa/fwl/basewidget/fwl_editimp.h"
+#include "xfa/fde/cfde_txtedtdorecord_deleterange.h"
+#include "xfa/fde/cfde_txtedtdorecord_insert.h"
+#include "xfa/fde/cfde_txtedtparag.h"
+#include "xfa/fde/cfde_txtedtpage.h"
+#include "xfa/fde/tto/fde_textout.h"
+
+namespace {
+
+const uint32_t kPageWidthMax = 0xffff;
+const uint32_t kUnicodeParagraphSeparator = 0x2029;
+
+} // namespace
+
+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'*'),
+ m_nFirstLineEnd(FDE_TXTEDIT_LINEEND_Auto),
+ m_bAutoLineEnd(TRUE),
+ m_wLineEnd(kUnicodeParagraphSeparator) {
+ 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;
+ }
+ RemoveAllParags();
+ RemoveAllPages();
+ m_Param.pEventSink = NULL;
+ ClearSelection();
+}
+
+void CFDE_TxtEdtEngine::Release() {
+ delete this;
+}
+
+void CFDE_TxtEdtEngine::SetEditParams(const FDE_TXTEDTPARAMS& params) {
+ if (!m_pTextBreak)
+ m_pTextBreak = new CFX_TxtBreak(FX_TXTBREAKPOLICY_None);
+
+ FXSYS_memcpy(&m_Param, &params, sizeof(FDE_TXTEDTPARAMS));
+ m_wLineEnd = params.wLineBreakChar;
+ m_bAutoLineEnd = (m_Param.nLineEnd == FDE_TXTEDIT_LINEEND_Auto);
+ UpdateTxtBreak();
+}
+
+FDE_TXTEDTPARAMS* CFDE_TxtEdtEngine::GetEditParams() {
+ 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;
+ }
+ m_pTxtBuf->GetRange(wsText, nStart, nCount);
+ RecoverParagEnd(wsText);
+}
+
+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;
+ }
+ ASSERT(nIndex >= 0 && nIndex <= GetTextBufLength());
+ if (m_PagePtrArray.GetSize() <= m_nCaretPage) {
+ return 0;
+ }
+ 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);
+ 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);
+ if (nIndex >= 0) {
+ UpdateCaretRect(nIndex, bBefore);
+ }
+ }
+ } break;
+ case MC_Up: {
+ if (bVertical) {
+ FX_BOOL bBefore = TRUE;
+ int32_t nIndex = MoveBackward(bBefore);
+ 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);
+ 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;
+ }
+ 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_TXTEDTSELRANGE* 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))
+ m_Param.pEventSink->On_AddDoRecord(
+ this,
+ new CFDE_TxtEdtDoRecord_Insert(this, m_nCaret, lpBuffer, nLength));
+
+ 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;
+ }
+
+ 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);
+ m_Param.pEventSink->On_AddDoRecord(
+ this,
+ new CFDE_TxtEdtDoRecord_DeleteRange(this, nStart, m_nCaret, wsRange));
+ }
+ 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::RemoveSelRange(int32_t nStart, int32_t nCount) {
+ FDE_TXTEDTSELRANGE* lpTemp = nullptr;
+ 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_TXTEDTSELRANGE* lpSelRange = new FDE_TXTEDTSELRANGE;
+ lpSelRange->nStart = nStart;
+ lpSelRange->nCount = nCount;
+ m_SelRangePtrArr.Add(lpSelRange);
+ m_Param.pEventSink->On_SelChanged(this);
+ return;
+ }
+ FDE_TXTEDTSELRANGE* lpTemp = nullptr;
+ lpTemp = m_SelRangePtrArr[nSize - 1];
+ if (nStart >= lpTemp->nStart + lpTemp->nCount) {
+ FDE_TXTEDTSELRANGE* 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_TXTEDTSELRANGE* 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();
+ for (int i = 0; i < nCount; ++i)
+ delete m_SelRangePtrArr[i];
+ m_SelRangePtrArr.RemoveAll();
+ if (nCount && m_Param.pEventSink)
+ m_Param.pEventSink->On_SelChanged(this);
+}
+
+FX_BOOL CFDE_TxtEdtEngine::Redo(const IFDE_TxtEdtDoRecord* pDoRecord) {
+ if (IsLocked())
+ return FALSE;
+ if (m_Param.dwMode & FDE_TEXTEDITMODE_NoRedoUndo)
+ return FALSE;
+ return pDoRecord->Redo();
+}
+
+FX_BOOL CFDE_TxtEdtEngine::Undo(const IFDE_TxtEdtDoRecord* pDoRecord) {
+ if (IsLocked())
+ return FALSE;
+ if (m_Param.dwMode & FDE_TEXTEDITMODE_NoRedoUndo)
+ return FALSE;
+ return pDoRecord->Undo();
+}
+
+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->GetLineCount();
+ 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);
+}
+
+CFDE_TxtEdtBuf* CFDE_TxtEdtEngine::GetTextBuf() const {
+ return m_pTxtBuf;
+}
+
+int32_t CFDE_TxtEdtEngine::GetTextBufLength() const {
+ return m_pTxtBuf->GetTextLength() - 1;
+}
+
+CFX_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();
+}
+
+CFDE_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->GetLineCount();
+ if (nLineTotal > nLineIndex) {
+ break;
+ }
+ }
+ nStartLine = nLineTotal - pParag->GetLineCount();
+ 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) {
+ 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]->IncrementStartIndex(nLength);
+
+ CFDE_TxtEdtParag* pParag = m_ParagPtrArray[ParagPos.nParagIndex];
+ int32_t nReserveLineCount = pParag->GetLineCount();
+ int32_t nReserveCharStart = pParag->GetStartIndex();
+ int32_t nLeavePart = ParagPos.nCharIndex;
+ int32_t nCutPart = pParag->GetTextLength() - 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->SetTextLength(nLeavePart + (i - nTextStart + 1));
+ pParag->SetLineCount(-1);
+ nReserveCharStart += pParag->GetTextLength();
+ bFirst = FALSE;
+ } else {
+ pParag = new CFDE_TxtEdtParag(this);
+ pParag->SetLineCount(-1);
+ pParag->SetTextLength(i - nTextStart + 1);
+ pParag->SetStartIndex(nReserveCharStart);
+ m_ParagPtrArray.InsertAt(++nParagIndex, pParag);
+ nReserveCharStart += pParag->GetTextLength();
+ }
+ nTextStart = i + 1;
+ }
+ }
+ if (bFirst) {
+ pParag->IncrementTextLength(nLength);
+ pParag->SetLineCount(-1);
+ bFirst = FALSE;
+ } else {
+ pParag = new CFDE_TxtEdtParag(this);
+ pParag->SetLineCount(-1);
+ pParag->SetTextLength(nLength - nTextStart + nCutPart);
+ pParag->SetStartIndex(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->GetLineCount();
+ }
+ m_nLineCount += nTotalLineCount - nReserveLineCount;
+ m_Param.pEventSink->On_PageLoad(this, m_nCaretPage, 0);
+ UpdatePages();
+}
+
+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;
+ 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->GetTextLength() - 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->GetLineCount();
+ nTotalCharCount += pParag->GetTextLength();
+ }
+ m_pTxtBuf->Delete(nStart, nCount);
+ int32_t nNextParagIndex = (ParagPosBgn.nCharIndex == 0 && bLastParag)
+ ? ParagPosBgn.nParagIndex
+ : (ParagPosBgn.nParagIndex + 1);
+ for (i = nNextParagIndex; i <= ParagPosEnd.nParagIndex; i++) {
+ delete m_ParagPtrArray[nNextParagIndex];
+ m_ParagPtrArray.RemoveAt(nNextParagIndex);
+ }
+ if (!(bLastParag && ParagPosBgn.nCharIndex == 0)) {
+ pParag = m_ParagPtrArray[ParagPosBgn.nParagIndex];
+ pParag->SetTextLength(nTotalCharCount - nCount);
+ pParag->CalcLines();
+ nTotalLineCount -= pParag->GetTextLength();
+ }
+ int32_t nParagCount = m_ParagPtrArray.GetSize();
+ for (i = nNextParagIndex; i < nParagCount; i++)
+ m_ParagPtrArray[i]->DecrementStartIndex(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) {
+ ASSERT(nStart >= 0);
+ if (nCount == -1) {
+ nCount = GetTextLength() - nStart;
+ }
+ ASSERT((nStart + nCount) <= m_pTxtBuf->GetTextLength());
+
+ if (!(m_Param.dwMode & FDE_TEXTEDITMODE_NoRedoUndo)) {
+ CFX_WideString wsRange;
+ m_pTxtBuf->GetRange(wsRange, nStart, nCount);
+ m_Param.pEventSink->On_AddDoRecord(
+ this, new CFDE_TxtEdtDoRecord_DeleteRange(this, nStart, m_nCaret,
+ wsRange, bSel));
+ }
+ 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;
+ std::unique_ptr<IFX_CharIter> pIter(
+ new CFDE_TxtEdtBufIter(static_cast<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->SetStartIndex(nParagStart);
+ pParag->SetTextLength(nIndex - nParagStart + 1);
+ pParag->SetLineCount(-1);
+ m_ParagPtrArray.Add(pParag);
+ nParagStart = nIndex + 1;
+ }
+ } while (pIter->Next());
+}
+
+void CFDE_TxtEdtEngine::RemoveAllParags() {
+ int32_t nCount = m_ParagPtrArray.GetSize();
+ for (int i = 0; i < nCount; ++i)
+ delete m_ParagPtrArray[i];
+ 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->GetLineCount() == -1)
+ pParag->CalcLines();
+
+ nLineCount += pParag->GetLineCount();
+ }
+ 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);
+ }
+ 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);
+ }
+ return;
+ }
+}
+
+void CFDE_TxtEdtEngine::UpdateTxtBreak() {
+ uint32_t 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);
+ uint32_t 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(kPageWidthMax);
+ }
+ } else {
+ if (m_Param.dwMode & FDE_TEXTEDITMODE_AutoLineWrap) {
+ m_pTextBreak->SetLineWidth(m_Param.fPlateWidth);
+ } else {
+ m_pTextBreak->SetLineWidth(kPageWidthMax);
+ }
+ }
+ 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 = const_cast<FX_WCHAR*>(wsText.c_str());
+ 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 = const_cast<FX_WCHAR*>(wsText.c_str());
+ for (int32_t i = 0; i < nLength; i++, lpBuf++) {
+ if (*lpBuf == m_wLineEnd)
+ *lpBuf = wc;
+ }
+ }
+}
+
+int32_t CFDE_TxtEdtEngine::MovePage2Char(int32_t nIndex) {
+ ASSERT(nIndex >= 0);
+ 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->GetStartIndex() <= nIndex &&
+ nIndex < (pParag->GetStartIndex() + pParag->GetTextLength())) {
+ break;
+ }
+ nLineCount += pParag->GetLineCount();
+ }
+ pParag->LoadParag();
+ int32_t nLineStart = -1;
+ int32_t nLineCharCount = -1;
+ for (i = 0; i < pParag->GetLineCount(); i++) {
+ pParag->GetLineRange(i, nLineStart, nLineCharCount);
+ if (nLineStart <= nIndex && nIndex < (nLineStart + nLineCharCount))
+ break;
+ }
+ ASSERT(i < pParag->GetLineCount());
+ nLineCount += (i + 1);
+ m_nCaretPage = (nLineCount - 1) / m_nPageLineCount + 1 - 1;
+ pParag->UnloadParag();
+ return m_nCaretPage;
+}
+
+void CFDE_TxtEdtEngine::TextPos2ParagPos(int32_t nIndex,
+ FDE_TXTEDTPARAGPOS& ParagPos) const {
+ 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->GetStartIndex())
+ nEnd = nMid - 1;
+ else if (nIndex >= (pParag->GetStartIndex() + pParag->GetTextLength()))
+ nBgn = nMid + 1;
+ else
+ break;
+ }
+ if (nBgn == nEnd)
+ nMid = nBgn;
+
+ ASSERT(nIndex >= m_ParagPtrArray[nMid]->GetStartIndex() &&
+ (nIndex < m_ParagPtrArray[nMid]->GetStartIndex() +
+ m_ParagPtrArray[nMid]->GetTextLength()));
+ ParagPos.nParagIndex = nMid;
+ ParagPos.nCharIndex = nIndex - m_ParagPtrArray[nMid]->GetStartIndex();
+}
+
+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--;
+ }
+ 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--;
+ 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++;
+ }
+ 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++;
+ 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->GetLineCount();
+ 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->GetLineCount();
+ 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;
+ 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->GetStartIndex(), 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->GetStartIndex() + pParag->GetTextLength() - 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;
+}
+
+FX_BOOL CFDE_TxtEdtEngine::IsFitArea(CFX_WideString& wsText) {
+ std::unique_ptr<CFDE_TextOut> pTextOut(new CFDE_TextOut);
+ pTextOut->SetLineSpace(m_Param.fLineSpace);
+ pTextOut->SetFont(m_Param.pFont);
+ pTextOut->SetFontSize(m_Param.fFontSize);
+ CFX_RectF rcText;
+ FXSYS_memset(&rcText, 0, sizeof(rcText));
+ uint32_t 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.c_str(), wsText.GetLength(), rcText);
+ 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) {
+ int32_t nSelStart;
+ int32_t nSelCount;
+ while (nCountRange > 0) {
+ nSelCount = GetSelRange(--nCountRange, nSelStart);
+ delete m_SelRangePtrArr[nCountRange];
+ 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;
+ }
+}