| Index: xfa/src/fee/src/fee/fde_txtedtbuf.cpp
|
| diff --git a/xfa/src/fee/src/fee/fde_txtedtbuf.cpp b/xfa/src/fee/src/fee/fde_txtedtbuf.cpp
|
| index bdef8d2a9f0d7c18ad2fb19fb29471db947e6978..2135b3613c155dcd1c2de49720aae37ef5d6b209 100644
|
| --- a/xfa/src/fee/src/fee/fde_txtedtbuf.cpp
|
| +++ b/xfa/src/fee/src/fee/fde_txtedtbuf.cpp
|
| @@ -1,438 +1,438 @@
|
| -// 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_txtedtbuf.h"
|
| -#include "xfa/src/fee/include/ifde_txtedtengine.h"
|
| -#include "fde_txtedtbuf.h"
|
| -#define FDE_DEFCHUNKCOUNT 2
|
| -#define FDE_TXTEDT_FORMATBLOCK_BGN 0xFFF9
|
| -#define FDE_TXTEDT_FORMATBLOCK_END 0xFFFB
|
| -#define FDE_TXTEDT_ZEROWIDTHSPACE 0x200B
|
| -#ifdef FDE_USEFORMATBLOCK
|
| -CFDE_TxtEdtBufIter::CFDE_TxtEdtBufIter(CFDE_TxtEdtBuf* pBuf,
|
| - FX_BOOL bForDisplay)
|
| -#else
|
| -CFDE_TxtEdtBufIter::CFDE_TxtEdtBufIter(CFDE_TxtEdtBuf* pBuf, FX_WCHAR wcAlias)
|
| -#endif
|
| - : m_pBuf(pBuf),
|
| - m_nCurChunk(0),
|
| - m_nCurIndex(0),
|
| - m_nIndex(0),
|
| -#ifdef FDE_USEFORMATBLOCK
|
| - m_bForDisplay(bForDisplay),
|
| - m_nAliasCount(0),
|
| -#endif
|
| - m_Alias(wcAlias) {
|
| - FXSYS_assert(m_pBuf);
|
| -}
|
| -CFDE_TxtEdtBufIter::~CFDE_TxtEdtBufIter() {}
|
| -void CFDE_TxtEdtBufIter::Release() {
|
| - delete this;
|
| -}
|
| -FX_BOOL CFDE_TxtEdtBufIter::Next(FX_BOOL bPrev) {
|
| - if (bPrev) {
|
| - if (m_nIndex == 0) {
|
| - return FALSE;
|
| - }
|
| - FXSYS_assert(m_nCurChunk < m_pBuf->m_Chunks.GetSize());
|
| - CFDE_TxtEdtBuf::FDE_LPCHUNKHEADER lpChunk = NULL;
|
| - if (m_nCurIndex > 0) {
|
| - m_nCurIndex--;
|
| - } else {
|
| - while (m_nCurChunk > 0) {
|
| - --m_nCurChunk;
|
| - lpChunk =
|
| - (CFDE_TxtEdtBuf::FDE_LPCHUNKHEADER)m_pBuf->m_Chunks[m_nCurChunk];
|
| - if (lpChunk->nUsed > 0) {
|
| - m_nCurIndex = lpChunk->nUsed - 1;
|
| - break;
|
| - }
|
| - }
|
| - }
|
| - FXSYS_assert(m_nCurChunk >= 0);
|
| - m_nIndex--;
|
| - return TRUE;
|
| - } else {
|
| - if (m_nIndex >= (m_pBuf->m_nTotal - 1)) {
|
| - return FALSE;
|
| - }
|
| - FXSYS_assert(m_nCurChunk < m_pBuf->m_Chunks.GetSize());
|
| - CFDE_TxtEdtBuf::FDE_LPCHUNKHEADER lpChunk =
|
| - (CFDE_TxtEdtBuf::FDE_LPCHUNKHEADER)m_pBuf->m_Chunks[m_nCurChunk];
|
| - if (lpChunk->nUsed != (m_nCurIndex + 1)) {
|
| - m_nCurIndex++;
|
| - } else {
|
| - int32_t nEnd = m_pBuf->m_Chunks.GetSize() - 1;
|
| - while (m_nCurChunk < nEnd) {
|
| - m_nCurChunk++;
|
| - CFDE_TxtEdtBuf::FDE_LPCHUNKHEADER lpChunkTemp =
|
| - (CFDE_TxtEdtBuf::FDE_LPCHUNKHEADER)m_pBuf->m_Chunks[m_nCurChunk];
|
| - if (lpChunkTemp->nUsed > 0) {
|
| - m_nCurIndex = 0;
|
| - break;
|
| - }
|
| - }
|
| - }
|
| - m_nIndex++;
|
| - return TRUE;
|
| - }
|
| -}
|
| -void CFDE_TxtEdtBufIter::SetAt(int32_t nIndex) {
|
| - FXSYS_assert(nIndex >= 0 && nIndex < m_pBuf->m_nTotal);
|
| - CFDE_TxtEdtBuf::FDE_CHUNKPLACE cp;
|
| - m_pBuf->Index2CP(nIndex, cp);
|
| - m_nIndex = nIndex;
|
| - m_nCurChunk = cp.nChunkIndex;
|
| - m_nCurIndex = cp.nCharIndex;
|
| -}
|
| -int32_t CFDE_TxtEdtBufIter::GetAt() const {
|
| - return m_nIndex;
|
| -}
|
| -FX_WCHAR CFDE_TxtEdtBufIter::GetChar() {
|
| - FXSYS_assert(m_nIndex >= 0 && m_nIndex < m_pBuf->m_nTotal);
|
| -#ifdef FDE_USEFORMATBLOCK
|
| - if (m_bForDisplay) {
|
| - if (m_bInField) {
|
| - FXSYS_assert(m_nAliasCount >= 0 && m_nAliasCount <= 2);
|
| - if (m_nAliasCount > 0) {
|
| - m_nAliasCount--;
|
| - return FDE_TXTEDT_ZEROWIDTHSPACE;
|
| - }
|
| - FX_WCHAR wc =
|
| - ((CFDE_TxtEdtBuf::FDE_LPCHUNKHEADER)m_pBuf->m_Chunks[m_nCurChunk])
|
| - ->wChars[m_nCurIndex];
|
| - if (wc == FDE_TXTEDT_FORMATBLOCK_END) {
|
| - m_nAliasCount = 0;
|
| - m_bInField = FALSE;
|
| - }
|
| - return wc;
|
| - } else {
|
| - FX_WCHAR wc =
|
| - ((CFDE_TxtEdtBuf::FDE_LPCHUNKHEADER)m_pBuf->m_Chunks[m_nCurChunk])
|
| - ->wChars[m_nCurIndex];
|
| - if (wc == FDE_TXTEDT_FORMATBLOCK_BGN) {
|
| - m_nAliasCount = 2;
|
| - m_bInField = TRUE;
|
| - }
|
| - return wc;
|
| - }
|
| - }
|
| -#endif
|
| - if (m_Alias == 0 || m_nIndex == (m_pBuf->m_nTotal - 1)) {
|
| - return ((CFDE_TxtEdtBuf::FDE_LPCHUNKHEADER)m_pBuf->m_Chunks[m_nCurChunk])
|
| - ->wChars[m_nCurIndex];
|
| - }
|
| - return m_Alias;
|
| -}
|
| -FX_BOOL CFDE_TxtEdtBufIter::IsEOF(FX_BOOL bTail) const {
|
| - return bTail ? m_nIndex == (m_pBuf->GetTextLength() - 2) : m_nIndex == 0;
|
| -}
|
| -IFX_CharIter* CFDE_TxtEdtBufIter::Clone() {
|
| - CFDE_TxtEdtBufIter* pIter = new CFDE_TxtEdtBufIter(m_pBuf);
|
| - pIter->m_nCurChunk = m_nCurChunk;
|
| - pIter->m_nCurIndex = m_nCurIndex;
|
| - pIter->m_nIndex = m_nIndex;
|
| - pIter->m_Alias = m_Alias;
|
| - return pIter;
|
| -}
|
| -CFDE_TxtEdtBuf::CFDE_TxtEdtBuf(int32_t nDefChunkSize)
|
| - : m_nChunkSize(nDefChunkSize),
|
| - m_nTotal(0),
|
| - m_bChanged(FALSE),
|
| - m_pAllocator(NULL) {
|
| - FXSYS_assert(m_nChunkSize);
|
| - ResetChunkBuffer(FDE_DEFCHUNKCOUNT, m_nChunkSize);
|
| -}
|
| -void CFDE_TxtEdtBuf::Release() {
|
| - delete this;
|
| -}
|
| -CFDE_TxtEdtBuf::~CFDE_TxtEdtBuf() {
|
| - Clear(TRUE);
|
| - m_pAllocator->Release();
|
| - m_Chunks.RemoveAll();
|
| -}
|
| -FX_BOOL CFDE_TxtEdtBuf::SetChunkSize(int32_t nChunkSize) {
|
| - FXSYS_assert(nChunkSize);
|
| - ResetChunkBuffer(FDE_DEFCHUNKCOUNT, nChunkSize);
|
| - return TRUE;
|
| -}
|
| -int32_t CFDE_TxtEdtBuf::GetChunkSize() const {
|
| - return m_nChunkSize;
|
| -}
|
| -int32_t CFDE_TxtEdtBuf::GetTextLength() const {
|
| - return m_nTotal;
|
| -}
|
| -void CFDE_TxtEdtBuf::SetText(const CFX_WideString& wsText) {
|
| - FXSYS_assert(!wsText.IsEmpty());
|
| - Clear(FALSE);
|
| - int32_t nTextLength = wsText.GetLength();
|
| - int32_t nNeedCount =
|
| - ((nTextLength - 1) / m_nChunkSize + 1) - m_Chunks.GetSize();
|
| - int32_t i = 0;
|
| - for (i = 0; i < nNeedCount; i++) {
|
| - FDE_LPCHUNKHEADER lpChunk = (FDE_LPCHUNKHEADER)m_pAllocator->Alloc(
|
| - sizeof(FDE_CHUNKHEADER) + (m_nChunkSize - 1) * sizeof(FX_WCHAR));
|
| - lpChunk->nUsed = 0;
|
| - m_Chunks.Add(lpChunk);
|
| - }
|
| - int32_t nTotalCount = m_Chunks.GetSize();
|
| - const FX_WCHAR* lpSrcBuf = wsText.c_str();
|
| - int32_t nLeave = nTextLength;
|
| - int32_t nCopyedLength = m_nChunkSize;
|
| - for (i = 0; i < nTotalCount && nLeave > 0; i++) {
|
| - if (nLeave < nCopyedLength) {
|
| - nCopyedLength = nLeave;
|
| - }
|
| - FDE_LPCHUNKHEADER lpChunk = (FDE_LPCHUNKHEADER)m_Chunks[i];
|
| - FXSYS_memcpy(lpChunk->wChars, lpSrcBuf, nCopyedLength * sizeof(FX_WCHAR));
|
| - nLeave -= nCopyedLength;
|
| - lpSrcBuf += nCopyedLength;
|
| - lpChunk->nUsed = nCopyedLength;
|
| - }
|
| - m_nTotal = nTextLength;
|
| - m_bChanged = TRUE;
|
| -}
|
| -void CFDE_TxtEdtBuf::GetText(CFX_WideString& wsText) const {
|
| - GetRange(wsText, 0, m_nTotal);
|
| -}
|
| -FX_WCHAR CFDE_TxtEdtBuf::GetCharByIndex(int32_t nIndex) const {
|
| - FXSYS_assert(nIndex >= 0 && nIndex < GetTextLength());
|
| - FDE_LPCHUNKHEADER pChunkHeader = NULL;
|
| - int32_t nTotal = 0;
|
| - int32_t nCount = m_Chunks.GetSize();
|
| - int32_t i = 0;
|
| - for (i = 0; i < nCount; i++) {
|
| - pChunkHeader = (FDE_LPCHUNKHEADER)m_Chunks[i];
|
| - nTotal += pChunkHeader->nUsed;
|
| - if (nTotal > nIndex) {
|
| - break;
|
| - }
|
| - }
|
| - FXSYS_assert(pChunkHeader);
|
| - return pChunkHeader->wChars[pChunkHeader->nUsed - (nTotal - nIndex)];
|
| -}
|
| -void CFDE_TxtEdtBuf::GetRange(CFX_WideString& wsText,
|
| - int32_t nBegin,
|
| - int32_t nLength) const {
|
| - FDE_CHUNKPLACE cp;
|
| - Index2CP(nBegin, cp);
|
| - int32_t nLeave = nLength;
|
| - int32_t nCount = m_Chunks.GetSize();
|
| - FX_WCHAR* lpDstBuf = wsText.GetBuffer(nLength);
|
| - int32_t nChunkIndex = cp.nChunkIndex;
|
| - FDE_LPCHUNKHEADER lpChunkHeader = (FDE_LPCHUNKHEADER)m_Chunks[nChunkIndex];
|
| - int32_t nCopyLength = lpChunkHeader->nUsed - cp.nCharIndex;
|
| - FX_WCHAR* lpSrcBuf = lpChunkHeader->wChars + cp.nCharIndex;
|
| - while (nLeave > 0) {
|
| - if (nLeave <= nCopyLength) {
|
| - nCopyLength = nLeave;
|
| - }
|
| - FXSYS_memcpy(lpDstBuf, lpSrcBuf, nCopyLength * sizeof(FX_WCHAR));
|
| - nChunkIndex++;
|
| - if (nChunkIndex >= nCount) {
|
| - break;
|
| - }
|
| - lpChunkHeader = (FDE_LPCHUNKHEADER)m_Chunks[nChunkIndex];
|
| - lpSrcBuf = lpChunkHeader->wChars;
|
| - nLeave -= nCopyLength;
|
| - lpDstBuf += nCopyLength;
|
| - nCopyLength = lpChunkHeader->nUsed;
|
| - }
|
| - wsText.ReleaseBuffer();
|
| -}
|
| -void CFDE_TxtEdtBuf::Insert(int32_t nPos,
|
| - const FX_WCHAR* lpText,
|
| - int32_t nLength) {
|
| - FXSYS_assert(nPos >= 0 && nPos <= m_nTotal);
|
| - FDE_CHUNKPLACE cp;
|
| - Index2CP(nPos, cp);
|
| - int32_t nLengthTemp = nLength;
|
| - if (cp.nCharIndex != 0) {
|
| - FDE_LPCHUNKHEADER lpNewChunk = (FDE_LPCHUNKHEADER)m_pAllocator->Alloc(
|
| - sizeof(FDE_CHUNKHEADER) + (m_nChunkSize - 1) * sizeof(FX_WCHAR));
|
| - FDE_LPCHUNKHEADER lpChunk = (FDE_LPCHUNKHEADER)m_Chunks[cp.nChunkIndex];
|
| - int32_t nCopy = lpChunk->nUsed - cp.nCharIndex;
|
| - FXSYS_memcpy(lpNewChunk->wChars, lpChunk->wChars + cp.nCharIndex,
|
| - nCopy * sizeof(FX_WCHAR));
|
| - lpChunk->nUsed -= nCopy;
|
| - cp.nChunkIndex++;
|
| - m_Chunks.InsertAt(cp.nChunkIndex, lpNewChunk);
|
| - lpNewChunk->nUsed = nCopy;
|
| - cp.nCharIndex = 0;
|
| - }
|
| - if (cp.nChunkIndex != 0) {
|
| - FDE_LPCHUNKHEADER lpChunk = (FDE_LPCHUNKHEADER)m_Chunks[cp.nChunkIndex - 1];
|
| - if (lpChunk->nUsed != m_nChunkSize) {
|
| - cp.nChunkIndex--;
|
| - int32_t nFree = m_nChunkSize - lpChunk->nUsed;
|
| - int32_t nCopy = std::min(nLengthTemp, nFree);
|
| - FXSYS_memcpy(lpChunk->wChars + lpChunk->nUsed, lpText,
|
| - nCopy * sizeof(FX_WCHAR));
|
| - lpText += nCopy;
|
| - nLengthTemp -= nCopy;
|
| - lpChunk->nUsed += nCopy;
|
| - cp.nChunkIndex++;
|
| - }
|
| - }
|
| - while (nLengthTemp > 0) {
|
| - FDE_LPCHUNKHEADER lpChunk = (FDE_LPCHUNKHEADER)m_pAllocator->Alloc(
|
| - sizeof(FDE_CHUNKHEADER) + (m_nChunkSize - 1) * sizeof(FX_WCHAR));
|
| - FXSYS_assert(lpChunk);
|
| - int32_t nCopy = std::min(nLengthTemp, m_nChunkSize);
|
| - FXSYS_memcpy(lpChunk->wChars, lpText, nCopy * sizeof(FX_WCHAR));
|
| - lpText += nCopy;
|
| - nLengthTemp -= nCopy;
|
| - lpChunk->nUsed = nCopy;
|
| - m_Chunks.InsertAt(cp.nChunkIndex, lpChunk);
|
| - cp.nChunkIndex++;
|
| - }
|
| - m_nTotal += nLength;
|
| - m_bChanged = TRUE;
|
| -}
|
| -void CFDE_TxtEdtBuf::Delete(int32_t nIndex, int32_t nLength) {
|
| - FXSYS_assert(nLength > 0 && nIndex >= 0 && nIndex + nLength <= m_nTotal);
|
| - FDE_CHUNKPLACE cpEnd;
|
| - Index2CP(nIndex + nLength - 1, cpEnd);
|
| - m_nTotal -= nLength;
|
| - FDE_LPCHUNKHEADER lpChunk = (FDE_LPCHUNKHEADER)m_Chunks[cpEnd.nChunkIndex];
|
| - int32_t nFirstPart = cpEnd.nCharIndex + 1;
|
| - int32_t nMovePart = lpChunk->nUsed - nFirstPart;
|
| - if (nMovePart != 0) {
|
| - int32_t nDelete = std::min(nFirstPart, nLength);
|
| - FXSYS_memmove(lpChunk->wChars + nFirstPart - nDelete,
|
| - lpChunk->wChars + nFirstPart, nMovePart * sizeof(FX_WCHAR));
|
| - lpChunk->nUsed -= nDelete;
|
| - nLength -= nDelete;
|
| - cpEnd.nChunkIndex--;
|
| - }
|
| - while (nLength > 0) {
|
| - lpChunk = (FDE_LPCHUNKHEADER)m_Chunks[cpEnd.nChunkIndex];
|
| - int32_t nDeleted = std::min(lpChunk->nUsed, nLength);
|
| - lpChunk->nUsed -= nDeleted;
|
| - if (lpChunk->nUsed == 0) {
|
| - m_pAllocator->Free(lpChunk);
|
| - m_Chunks.RemoveAt(cpEnd.nChunkIndex);
|
| - lpChunk = NULL;
|
| - }
|
| - nLength -= nDeleted;
|
| - cpEnd.nChunkIndex--;
|
| - }
|
| - m_bChanged = TRUE;
|
| -}
|
| -void CFDE_TxtEdtBuf::Clear(FX_BOOL bRelease) {
|
| - int32_t i = 0;
|
| - int32_t nCount = m_Chunks.GetSize();
|
| - if (bRelease) {
|
| - while (i < nCount) {
|
| - m_pAllocator->Free(m_Chunks[i++]);
|
| - }
|
| - m_Chunks.RemoveAll();
|
| - } else {
|
| - while (i < nCount) {
|
| - ((FDE_LPCHUNKHEADER)m_Chunks[i++])->nUsed = 0;
|
| - }
|
| - }
|
| - m_nTotal = 0;
|
| - m_bChanged = TRUE;
|
| -}
|
| -FX_BOOL CFDE_TxtEdtBuf::Optimize(IFX_Pause* pPause) {
|
| - if (m_bChanged == FALSE) {
|
| - return TRUE;
|
| - }
|
| - if (m_nTotal == 0) {
|
| - return TRUE;
|
| - }
|
| - int32_t nCount = m_Chunks.GetSize();
|
| - if (nCount == 0) {
|
| - return TRUE;
|
| - }
|
| - int32_t i = 0;
|
| - for (; i < nCount; i++) {
|
| - FDE_LPCHUNKHEADER lpChunk = (FDE_LPCHUNKHEADER)m_Chunks[i];
|
| - if (lpChunk->nUsed == 0) {
|
| - m_pAllocator->Free(lpChunk);
|
| - m_Chunks.RemoveAt(i);
|
| - --i;
|
| - --nCount;
|
| - }
|
| - }
|
| - if (pPause != NULL && pPause->NeedToPauseNow()) {
|
| - return FALSE;
|
| - }
|
| - FDE_LPCHUNKHEADER lpPreChunk = (FDE_LPCHUNKHEADER)m_Chunks[0];
|
| - FDE_LPCHUNKHEADER lpCurChunk = NULL;
|
| - for (i = 1; i < nCount; i++) {
|
| - lpCurChunk = (FDE_LPCHUNKHEADER)m_Chunks[i];
|
| - if (lpPreChunk->nUsed + lpCurChunk->nUsed <= m_nChunkSize) {
|
| - FXSYS_memcpy(lpPreChunk->wChars + lpPreChunk->nUsed, lpCurChunk->wChars,
|
| - lpCurChunk->nUsed * sizeof(FX_WCHAR));
|
| - lpPreChunk->nUsed += lpCurChunk->nUsed;
|
| - m_pAllocator->Free(lpCurChunk);
|
| - m_Chunks.RemoveAt(i);
|
| - --i;
|
| - --nCount;
|
| - } else {
|
| - lpPreChunk = lpCurChunk;
|
| - }
|
| - if (pPause != NULL && pPause->NeedToPauseNow()) {
|
| - return FALSE;
|
| - }
|
| - }
|
| - m_bChanged = FALSE;
|
| - return TRUE;
|
| -}
|
| -void CFDE_TxtEdtBuf::ResetChunkBuffer(int32_t nDefChunkCount,
|
| - int32_t nChunkSize) {
|
| - FXSYS_assert(nChunkSize);
|
| - FXSYS_assert(nDefChunkCount);
|
| - if (m_pAllocator) {
|
| - m_pAllocator->Release();
|
| - m_pAllocator = NULL;
|
| - }
|
| - m_Chunks.RemoveAll();
|
| - m_nChunkSize = nChunkSize;
|
| - int32_t nChunkLength =
|
| - sizeof(FDE_CHUNKHEADER) + (m_nChunkSize - 1) * sizeof(FX_WCHAR);
|
| - m_pAllocator =
|
| - FX_CreateAllocator(FX_ALLOCTYPE_Fixed, nDefChunkCount, nChunkLength);
|
| - FXSYS_assert(m_pAllocator);
|
| - FDE_LPCHUNKHEADER lpChunkHeader =
|
| - (FDE_LPCHUNKHEADER)m_pAllocator->Alloc(nChunkLength);
|
| - FXSYS_assert(lpChunkHeader);
|
| - lpChunkHeader->nUsed = 0;
|
| - m_Chunks.Add(lpChunkHeader);
|
| - m_nTotal = 0;
|
| -}
|
| -int32_t CFDE_TxtEdtBuf::CP2Index(const FDE_CHUNKPLACE& cp) const {
|
| - int32_t nTotal = cp.nCharIndex;
|
| - int32_t i = 0;
|
| - for (i = 0; i < cp.nChunkIndex; i++) {
|
| - nTotal += ((FDE_LPCHUNKHEADER)m_Chunks[i])->nUsed;
|
| - }
|
| - return nTotal;
|
| -}
|
| -void CFDE_TxtEdtBuf::Index2CP(int32_t nIndex, FDE_CHUNKPLACE& cp) const {
|
| - FXSYS_assert(nIndex <= GetTextLength());
|
| - if (nIndex == m_nTotal) {
|
| - cp.nChunkIndex = m_Chunks.GetSize() - 1;
|
| - cp.nCharIndex = ((FDE_LPCHUNKHEADER)m_Chunks[cp.nChunkIndex])->nUsed;
|
| - return;
|
| - }
|
| - int32_t i = 0;
|
| - int32_t nTotal = 0;
|
| - int32_t nCount = m_Chunks.GetSize();
|
| - for (; i < nCount; i++) {
|
| - nTotal += ((FDE_LPCHUNKHEADER)m_Chunks[i])->nUsed;
|
| - if (nTotal > nIndex) {
|
| - break;
|
| - }
|
| - }
|
| - cp.nChunkIndex = i;
|
| - cp.nCharIndex = ((FDE_LPCHUNKHEADER)m_Chunks[i])->nUsed - (nTotal - nIndex);
|
| -}
|
| +// 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_txtedtbuf.h"
|
| +#include "xfa/src/fee/include/ifde_txtedtengine.h"
|
| +#include "fde_txtedtbuf.h"
|
| +#define FDE_DEFCHUNKCOUNT 2
|
| +#define FDE_TXTEDT_FORMATBLOCK_BGN 0xFFF9
|
| +#define FDE_TXTEDT_FORMATBLOCK_END 0xFFFB
|
| +#define FDE_TXTEDT_ZEROWIDTHSPACE 0x200B
|
| +#ifdef FDE_USEFORMATBLOCK
|
| +CFDE_TxtEdtBufIter::CFDE_TxtEdtBufIter(CFDE_TxtEdtBuf* pBuf,
|
| + FX_BOOL bForDisplay)
|
| +#else
|
| +CFDE_TxtEdtBufIter::CFDE_TxtEdtBufIter(CFDE_TxtEdtBuf* pBuf, FX_WCHAR wcAlias)
|
| +#endif
|
| + : m_pBuf(pBuf),
|
| + m_nCurChunk(0),
|
| + m_nCurIndex(0),
|
| + m_nIndex(0),
|
| +#ifdef FDE_USEFORMATBLOCK
|
| + m_bForDisplay(bForDisplay),
|
| + m_nAliasCount(0),
|
| +#endif
|
| + m_Alias(wcAlias) {
|
| + FXSYS_assert(m_pBuf);
|
| +}
|
| +CFDE_TxtEdtBufIter::~CFDE_TxtEdtBufIter() {}
|
| +void CFDE_TxtEdtBufIter::Release() {
|
| + delete this;
|
| +}
|
| +FX_BOOL CFDE_TxtEdtBufIter::Next(FX_BOOL bPrev) {
|
| + if (bPrev) {
|
| + if (m_nIndex == 0) {
|
| + return FALSE;
|
| + }
|
| + FXSYS_assert(m_nCurChunk < m_pBuf->m_Chunks.GetSize());
|
| + CFDE_TxtEdtBuf::FDE_LPCHUNKHEADER lpChunk = NULL;
|
| + if (m_nCurIndex > 0) {
|
| + m_nCurIndex--;
|
| + } else {
|
| + while (m_nCurChunk > 0) {
|
| + --m_nCurChunk;
|
| + lpChunk =
|
| + (CFDE_TxtEdtBuf::FDE_LPCHUNKHEADER)m_pBuf->m_Chunks[m_nCurChunk];
|
| + if (lpChunk->nUsed > 0) {
|
| + m_nCurIndex = lpChunk->nUsed - 1;
|
| + break;
|
| + }
|
| + }
|
| + }
|
| + FXSYS_assert(m_nCurChunk >= 0);
|
| + m_nIndex--;
|
| + return TRUE;
|
| + } else {
|
| + if (m_nIndex >= (m_pBuf->m_nTotal - 1)) {
|
| + return FALSE;
|
| + }
|
| + FXSYS_assert(m_nCurChunk < m_pBuf->m_Chunks.GetSize());
|
| + CFDE_TxtEdtBuf::FDE_LPCHUNKHEADER lpChunk =
|
| + (CFDE_TxtEdtBuf::FDE_LPCHUNKHEADER)m_pBuf->m_Chunks[m_nCurChunk];
|
| + if (lpChunk->nUsed != (m_nCurIndex + 1)) {
|
| + m_nCurIndex++;
|
| + } else {
|
| + int32_t nEnd = m_pBuf->m_Chunks.GetSize() - 1;
|
| + while (m_nCurChunk < nEnd) {
|
| + m_nCurChunk++;
|
| + CFDE_TxtEdtBuf::FDE_LPCHUNKHEADER lpChunkTemp =
|
| + (CFDE_TxtEdtBuf::FDE_LPCHUNKHEADER)m_pBuf->m_Chunks[m_nCurChunk];
|
| + if (lpChunkTemp->nUsed > 0) {
|
| + m_nCurIndex = 0;
|
| + break;
|
| + }
|
| + }
|
| + }
|
| + m_nIndex++;
|
| + return TRUE;
|
| + }
|
| +}
|
| +void CFDE_TxtEdtBufIter::SetAt(int32_t nIndex) {
|
| + FXSYS_assert(nIndex >= 0 && nIndex < m_pBuf->m_nTotal);
|
| + CFDE_TxtEdtBuf::FDE_CHUNKPLACE cp;
|
| + m_pBuf->Index2CP(nIndex, cp);
|
| + m_nIndex = nIndex;
|
| + m_nCurChunk = cp.nChunkIndex;
|
| + m_nCurIndex = cp.nCharIndex;
|
| +}
|
| +int32_t CFDE_TxtEdtBufIter::GetAt() const {
|
| + return m_nIndex;
|
| +}
|
| +FX_WCHAR CFDE_TxtEdtBufIter::GetChar() {
|
| + FXSYS_assert(m_nIndex >= 0 && m_nIndex < m_pBuf->m_nTotal);
|
| +#ifdef FDE_USEFORMATBLOCK
|
| + if (m_bForDisplay) {
|
| + if (m_bInField) {
|
| + FXSYS_assert(m_nAliasCount >= 0 && m_nAliasCount <= 2);
|
| + if (m_nAliasCount > 0) {
|
| + m_nAliasCount--;
|
| + return FDE_TXTEDT_ZEROWIDTHSPACE;
|
| + }
|
| + FX_WCHAR wc =
|
| + ((CFDE_TxtEdtBuf::FDE_LPCHUNKHEADER)m_pBuf->m_Chunks[m_nCurChunk])
|
| + ->wChars[m_nCurIndex];
|
| + if (wc == FDE_TXTEDT_FORMATBLOCK_END) {
|
| + m_nAliasCount = 0;
|
| + m_bInField = FALSE;
|
| + }
|
| + return wc;
|
| + } else {
|
| + FX_WCHAR wc =
|
| + ((CFDE_TxtEdtBuf::FDE_LPCHUNKHEADER)m_pBuf->m_Chunks[m_nCurChunk])
|
| + ->wChars[m_nCurIndex];
|
| + if (wc == FDE_TXTEDT_FORMATBLOCK_BGN) {
|
| + m_nAliasCount = 2;
|
| + m_bInField = TRUE;
|
| + }
|
| + return wc;
|
| + }
|
| + }
|
| +#endif
|
| + if (m_Alias == 0 || m_nIndex == (m_pBuf->m_nTotal - 1)) {
|
| + return ((CFDE_TxtEdtBuf::FDE_LPCHUNKHEADER)m_pBuf->m_Chunks[m_nCurChunk])
|
| + ->wChars[m_nCurIndex];
|
| + }
|
| + return m_Alias;
|
| +}
|
| +FX_BOOL CFDE_TxtEdtBufIter::IsEOF(FX_BOOL bTail) const {
|
| + return bTail ? m_nIndex == (m_pBuf->GetTextLength() - 2) : m_nIndex == 0;
|
| +}
|
| +IFX_CharIter* CFDE_TxtEdtBufIter::Clone() {
|
| + CFDE_TxtEdtBufIter* pIter = new CFDE_TxtEdtBufIter(m_pBuf);
|
| + pIter->m_nCurChunk = m_nCurChunk;
|
| + pIter->m_nCurIndex = m_nCurIndex;
|
| + pIter->m_nIndex = m_nIndex;
|
| + pIter->m_Alias = m_Alias;
|
| + return pIter;
|
| +}
|
| +CFDE_TxtEdtBuf::CFDE_TxtEdtBuf(int32_t nDefChunkSize)
|
| + : m_nChunkSize(nDefChunkSize),
|
| + m_nTotal(0),
|
| + m_bChanged(FALSE),
|
| + m_pAllocator(NULL) {
|
| + FXSYS_assert(m_nChunkSize);
|
| + ResetChunkBuffer(FDE_DEFCHUNKCOUNT, m_nChunkSize);
|
| +}
|
| +void CFDE_TxtEdtBuf::Release() {
|
| + delete this;
|
| +}
|
| +CFDE_TxtEdtBuf::~CFDE_TxtEdtBuf() {
|
| + Clear(TRUE);
|
| + m_pAllocator->Release();
|
| + m_Chunks.RemoveAll();
|
| +}
|
| +FX_BOOL CFDE_TxtEdtBuf::SetChunkSize(int32_t nChunkSize) {
|
| + FXSYS_assert(nChunkSize);
|
| + ResetChunkBuffer(FDE_DEFCHUNKCOUNT, nChunkSize);
|
| + return TRUE;
|
| +}
|
| +int32_t CFDE_TxtEdtBuf::GetChunkSize() const {
|
| + return m_nChunkSize;
|
| +}
|
| +int32_t CFDE_TxtEdtBuf::GetTextLength() const {
|
| + return m_nTotal;
|
| +}
|
| +void CFDE_TxtEdtBuf::SetText(const CFX_WideString& wsText) {
|
| + FXSYS_assert(!wsText.IsEmpty());
|
| + Clear(FALSE);
|
| + int32_t nTextLength = wsText.GetLength();
|
| + int32_t nNeedCount =
|
| + ((nTextLength - 1) / m_nChunkSize + 1) - m_Chunks.GetSize();
|
| + int32_t i = 0;
|
| + for (i = 0; i < nNeedCount; i++) {
|
| + FDE_LPCHUNKHEADER lpChunk = (FDE_LPCHUNKHEADER)m_pAllocator->Alloc(
|
| + sizeof(FDE_CHUNKHEADER) + (m_nChunkSize - 1) * sizeof(FX_WCHAR));
|
| + lpChunk->nUsed = 0;
|
| + m_Chunks.Add(lpChunk);
|
| + }
|
| + int32_t nTotalCount = m_Chunks.GetSize();
|
| + const FX_WCHAR* lpSrcBuf = wsText.c_str();
|
| + int32_t nLeave = nTextLength;
|
| + int32_t nCopyedLength = m_nChunkSize;
|
| + for (i = 0; i < nTotalCount && nLeave > 0; i++) {
|
| + if (nLeave < nCopyedLength) {
|
| + nCopyedLength = nLeave;
|
| + }
|
| + FDE_LPCHUNKHEADER lpChunk = (FDE_LPCHUNKHEADER)m_Chunks[i];
|
| + FXSYS_memcpy(lpChunk->wChars, lpSrcBuf, nCopyedLength * sizeof(FX_WCHAR));
|
| + nLeave -= nCopyedLength;
|
| + lpSrcBuf += nCopyedLength;
|
| + lpChunk->nUsed = nCopyedLength;
|
| + }
|
| + m_nTotal = nTextLength;
|
| + m_bChanged = TRUE;
|
| +}
|
| +void CFDE_TxtEdtBuf::GetText(CFX_WideString& wsText) const {
|
| + GetRange(wsText, 0, m_nTotal);
|
| +}
|
| +FX_WCHAR CFDE_TxtEdtBuf::GetCharByIndex(int32_t nIndex) const {
|
| + FXSYS_assert(nIndex >= 0 && nIndex < GetTextLength());
|
| + FDE_LPCHUNKHEADER pChunkHeader = NULL;
|
| + int32_t nTotal = 0;
|
| + int32_t nCount = m_Chunks.GetSize();
|
| + int32_t i = 0;
|
| + for (i = 0; i < nCount; i++) {
|
| + pChunkHeader = (FDE_LPCHUNKHEADER)m_Chunks[i];
|
| + nTotal += pChunkHeader->nUsed;
|
| + if (nTotal > nIndex) {
|
| + break;
|
| + }
|
| + }
|
| + FXSYS_assert(pChunkHeader);
|
| + return pChunkHeader->wChars[pChunkHeader->nUsed - (nTotal - nIndex)];
|
| +}
|
| +void CFDE_TxtEdtBuf::GetRange(CFX_WideString& wsText,
|
| + int32_t nBegin,
|
| + int32_t nLength) const {
|
| + FDE_CHUNKPLACE cp;
|
| + Index2CP(nBegin, cp);
|
| + int32_t nLeave = nLength;
|
| + int32_t nCount = m_Chunks.GetSize();
|
| + FX_WCHAR* lpDstBuf = wsText.GetBuffer(nLength);
|
| + int32_t nChunkIndex = cp.nChunkIndex;
|
| + FDE_LPCHUNKHEADER lpChunkHeader = (FDE_LPCHUNKHEADER)m_Chunks[nChunkIndex];
|
| + int32_t nCopyLength = lpChunkHeader->nUsed - cp.nCharIndex;
|
| + FX_WCHAR* lpSrcBuf = lpChunkHeader->wChars + cp.nCharIndex;
|
| + while (nLeave > 0) {
|
| + if (nLeave <= nCopyLength) {
|
| + nCopyLength = nLeave;
|
| + }
|
| + FXSYS_memcpy(lpDstBuf, lpSrcBuf, nCopyLength * sizeof(FX_WCHAR));
|
| + nChunkIndex++;
|
| + if (nChunkIndex >= nCount) {
|
| + break;
|
| + }
|
| + lpChunkHeader = (FDE_LPCHUNKHEADER)m_Chunks[nChunkIndex];
|
| + lpSrcBuf = lpChunkHeader->wChars;
|
| + nLeave -= nCopyLength;
|
| + lpDstBuf += nCopyLength;
|
| + nCopyLength = lpChunkHeader->nUsed;
|
| + }
|
| + wsText.ReleaseBuffer();
|
| +}
|
| +void CFDE_TxtEdtBuf::Insert(int32_t nPos,
|
| + const FX_WCHAR* lpText,
|
| + int32_t nLength) {
|
| + FXSYS_assert(nPos >= 0 && nPos <= m_nTotal);
|
| + FDE_CHUNKPLACE cp;
|
| + Index2CP(nPos, cp);
|
| + int32_t nLengthTemp = nLength;
|
| + if (cp.nCharIndex != 0) {
|
| + FDE_LPCHUNKHEADER lpNewChunk = (FDE_LPCHUNKHEADER)m_pAllocator->Alloc(
|
| + sizeof(FDE_CHUNKHEADER) + (m_nChunkSize - 1) * sizeof(FX_WCHAR));
|
| + FDE_LPCHUNKHEADER lpChunk = (FDE_LPCHUNKHEADER)m_Chunks[cp.nChunkIndex];
|
| + int32_t nCopy = lpChunk->nUsed - cp.nCharIndex;
|
| + FXSYS_memcpy(lpNewChunk->wChars, lpChunk->wChars + cp.nCharIndex,
|
| + nCopy * sizeof(FX_WCHAR));
|
| + lpChunk->nUsed -= nCopy;
|
| + cp.nChunkIndex++;
|
| + m_Chunks.InsertAt(cp.nChunkIndex, lpNewChunk);
|
| + lpNewChunk->nUsed = nCopy;
|
| + cp.nCharIndex = 0;
|
| + }
|
| + if (cp.nChunkIndex != 0) {
|
| + FDE_LPCHUNKHEADER lpChunk = (FDE_LPCHUNKHEADER)m_Chunks[cp.nChunkIndex - 1];
|
| + if (lpChunk->nUsed != m_nChunkSize) {
|
| + cp.nChunkIndex--;
|
| + int32_t nFree = m_nChunkSize - lpChunk->nUsed;
|
| + int32_t nCopy = std::min(nLengthTemp, nFree);
|
| + FXSYS_memcpy(lpChunk->wChars + lpChunk->nUsed, lpText,
|
| + nCopy * sizeof(FX_WCHAR));
|
| + lpText += nCopy;
|
| + nLengthTemp -= nCopy;
|
| + lpChunk->nUsed += nCopy;
|
| + cp.nChunkIndex++;
|
| + }
|
| + }
|
| + while (nLengthTemp > 0) {
|
| + FDE_LPCHUNKHEADER lpChunk = (FDE_LPCHUNKHEADER)m_pAllocator->Alloc(
|
| + sizeof(FDE_CHUNKHEADER) + (m_nChunkSize - 1) * sizeof(FX_WCHAR));
|
| + FXSYS_assert(lpChunk);
|
| + int32_t nCopy = std::min(nLengthTemp, m_nChunkSize);
|
| + FXSYS_memcpy(lpChunk->wChars, lpText, nCopy * sizeof(FX_WCHAR));
|
| + lpText += nCopy;
|
| + nLengthTemp -= nCopy;
|
| + lpChunk->nUsed = nCopy;
|
| + m_Chunks.InsertAt(cp.nChunkIndex, lpChunk);
|
| + cp.nChunkIndex++;
|
| + }
|
| + m_nTotal += nLength;
|
| + m_bChanged = TRUE;
|
| +}
|
| +void CFDE_TxtEdtBuf::Delete(int32_t nIndex, int32_t nLength) {
|
| + FXSYS_assert(nLength > 0 && nIndex >= 0 && nIndex + nLength <= m_nTotal);
|
| + FDE_CHUNKPLACE cpEnd;
|
| + Index2CP(nIndex + nLength - 1, cpEnd);
|
| + m_nTotal -= nLength;
|
| + FDE_LPCHUNKHEADER lpChunk = (FDE_LPCHUNKHEADER)m_Chunks[cpEnd.nChunkIndex];
|
| + int32_t nFirstPart = cpEnd.nCharIndex + 1;
|
| + int32_t nMovePart = lpChunk->nUsed - nFirstPart;
|
| + if (nMovePart != 0) {
|
| + int32_t nDelete = std::min(nFirstPart, nLength);
|
| + FXSYS_memmove(lpChunk->wChars + nFirstPart - nDelete,
|
| + lpChunk->wChars + nFirstPart, nMovePart * sizeof(FX_WCHAR));
|
| + lpChunk->nUsed -= nDelete;
|
| + nLength -= nDelete;
|
| + cpEnd.nChunkIndex--;
|
| + }
|
| + while (nLength > 0) {
|
| + lpChunk = (FDE_LPCHUNKHEADER)m_Chunks[cpEnd.nChunkIndex];
|
| + int32_t nDeleted = std::min(lpChunk->nUsed, nLength);
|
| + lpChunk->nUsed -= nDeleted;
|
| + if (lpChunk->nUsed == 0) {
|
| + m_pAllocator->Free(lpChunk);
|
| + m_Chunks.RemoveAt(cpEnd.nChunkIndex);
|
| + lpChunk = NULL;
|
| + }
|
| + nLength -= nDeleted;
|
| + cpEnd.nChunkIndex--;
|
| + }
|
| + m_bChanged = TRUE;
|
| +}
|
| +void CFDE_TxtEdtBuf::Clear(FX_BOOL bRelease) {
|
| + int32_t i = 0;
|
| + int32_t nCount = m_Chunks.GetSize();
|
| + if (bRelease) {
|
| + while (i < nCount) {
|
| + m_pAllocator->Free(m_Chunks[i++]);
|
| + }
|
| + m_Chunks.RemoveAll();
|
| + } else {
|
| + while (i < nCount) {
|
| + ((FDE_LPCHUNKHEADER)m_Chunks[i++])->nUsed = 0;
|
| + }
|
| + }
|
| + m_nTotal = 0;
|
| + m_bChanged = TRUE;
|
| +}
|
| +FX_BOOL CFDE_TxtEdtBuf::Optimize(IFX_Pause* pPause) {
|
| + if (m_bChanged == FALSE) {
|
| + return TRUE;
|
| + }
|
| + if (m_nTotal == 0) {
|
| + return TRUE;
|
| + }
|
| + int32_t nCount = m_Chunks.GetSize();
|
| + if (nCount == 0) {
|
| + return TRUE;
|
| + }
|
| + int32_t i = 0;
|
| + for (; i < nCount; i++) {
|
| + FDE_LPCHUNKHEADER lpChunk = (FDE_LPCHUNKHEADER)m_Chunks[i];
|
| + if (lpChunk->nUsed == 0) {
|
| + m_pAllocator->Free(lpChunk);
|
| + m_Chunks.RemoveAt(i);
|
| + --i;
|
| + --nCount;
|
| + }
|
| + }
|
| + if (pPause != NULL && pPause->NeedToPauseNow()) {
|
| + return FALSE;
|
| + }
|
| + FDE_LPCHUNKHEADER lpPreChunk = (FDE_LPCHUNKHEADER)m_Chunks[0];
|
| + FDE_LPCHUNKHEADER lpCurChunk = NULL;
|
| + for (i = 1; i < nCount; i++) {
|
| + lpCurChunk = (FDE_LPCHUNKHEADER)m_Chunks[i];
|
| + if (lpPreChunk->nUsed + lpCurChunk->nUsed <= m_nChunkSize) {
|
| + FXSYS_memcpy(lpPreChunk->wChars + lpPreChunk->nUsed, lpCurChunk->wChars,
|
| + lpCurChunk->nUsed * sizeof(FX_WCHAR));
|
| + lpPreChunk->nUsed += lpCurChunk->nUsed;
|
| + m_pAllocator->Free(lpCurChunk);
|
| + m_Chunks.RemoveAt(i);
|
| + --i;
|
| + --nCount;
|
| + } else {
|
| + lpPreChunk = lpCurChunk;
|
| + }
|
| + if (pPause != NULL && pPause->NeedToPauseNow()) {
|
| + return FALSE;
|
| + }
|
| + }
|
| + m_bChanged = FALSE;
|
| + return TRUE;
|
| +}
|
| +void CFDE_TxtEdtBuf::ResetChunkBuffer(int32_t nDefChunkCount,
|
| + int32_t nChunkSize) {
|
| + FXSYS_assert(nChunkSize);
|
| + FXSYS_assert(nDefChunkCount);
|
| + if (m_pAllocator) {
|
| + m_pAllocator->Release();
|
| + m_pAllocator = NULL;
|
| + }
|
| + m_Chunks.RemoveAll();
|
| + m_nChunkSize = nChunkSize;
|
| + int32_t nChunkLength =
|
| + sizeof(FDE_CHUNKHEADER) + (m_nChunkSize - 1) * sizeof(FX_WCHAR);
|
| + m_pAllocator =
|
| + FX_CreateAllocator(FX_ALLOCTYPE_Fixed, nDefChunkCount, nChunkLength);
|
| + FXSYS_assert(m_pAllocator);
|
| + FDE_LPCHUNKHEADER lpChunkHeader =
|
| + (FDE_LPCHUNKHEADER)m_pAllocator->Alloc(nChunkLength);
|
| + FXSYS_assert(lpChunkHeader);
|
| + lpChunkHeader->nUsed = 0;
|
| + m_Chunks.Add(lpChunkHeader);
|
| + m_nTotal = 0;
|
| +}
|
| +int32_t CFDE_TxtEdtBuf::CP2Index(const FDE_CHUNKPLACE& cp) const {
|
| + int32_t nTotal = cp.nCharIndex;
|
| + int32_t i = 0;
|
| + for (i = 0; i < cp.nChunkIndex; i++) {
|
| + nTotal += ((FDE_LPCHUNKHEADER)m_Chunks[i])->nUsed;
|
| + }
|
| + return nTotal;
|
| +}
|
| +void CFDE_TxtEdtBuf::Index2CP(int32_t nIndex, FDE_CHUNKPLACE& cp) const {
|
| + FXSYS_assert(nIndex <= GetTextLength());
|
| + if (nIndex == m_nTotal) {
|
| + cp.nChunkIndex = m_Chunks.GetSize() - 1;
|
| + cp.nCharIndex = ((FDE_LPCHUNKHEADER)m_Chunks[cp.nChunkIndex])->nUsed;
|
| + return;
|
| + }
|
| + int32_t i = 0;
|
| + int32_t nTotal = 0;
|
| + int32_t nCount = m_Chunks.GetSize();
|
| + for (; i < nCount; i++) {
|
| + nTotal += ((FDE_LPCHUNKHEADER)m_Chunks[i])->nUsed;
|
| + if (nTotal > nIndex) {
|
| + break;
|
| + }
|
| + }
|
| + cp.nChunkIndex = i;
|
| + cp.nCharIndex = ((FDE_LPCHUNKHEADER)m_Chunks[i])->nUsed - (nTotal - nIndex);
|
| +}
|
|
|