diff options
Diffstat (limited to 'xfa/fde/cfde_txtedtbuf.cpp')
-rw-r--r-- | xfa/fde/cfde_txtedtbuf.cpp | 328 |
1 files changed, 328 insertions, 0 deletions
diff --git a/xfa/fde/cfde_txtedtbuf.cpp b/xfa/fde/cfde_txtedtbuf.cpp new file mode 100644 index 0000000000..8bd5c1d37b --- /dev/null +++ b/xfa/fde/cfde_txtedtbuf.cpp @@ -0,0 +1,328 @@ +// 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_txtedtbuf.h" + +#include "xfa/fgas/crt/fgas_memory.h" + +namespace { + +const int kDefaultChunkSize = 1024; +const int kDefaultChunkCount = 2; + +} // namespace + +CFDE_TxtEdtBuf::CFDE_TxtEdtBuf() + : m_nChunkSize(kDefaultChunkSize), + m_nTotal(0), + m_bChanged(FALSE), + m_pAllocator(NULL) { + ASSERT(m_nChunkSize); + ResetChunkBuffer(kDefaultChunkCount, m_nChunkSize); +} + +void CFDE_TxtEdtBuf::Release() { + delete this; +} + +CFDE_TxtEdtBuf::~CFDE_TxtEdtBuf() { + Clear(TRUE); + delete m_pAllocator; + m_Chunks.RemoveAll(); +} + +FX_BOOL CFDE_TxtEdtBuf::SetChunkSize(int32_t nChunkSize) { + ASSERT(nChunkSize); + ResetChunkBuffer(kDefaultChunkCount, 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) { + 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_CHUNKHEADER* lpChunk = + static_cast<FDE_CHUNKHEADER*>(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_CHUNKHEADER* lpChunk = 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 { + ASSERT(nIndex >= 0 && nIndex < GetTextLength()); + FDE_CHUNKHEADER* pChunkHeader = nullptr; + int32_t nTotal = 0; + int32_t nCount = m_Chunks.GetSize(); + int32_t i = 0; + for (i = 0; i < nCount; i++) { + pChunkHeader = m_Chunks[i]; + nTotal += pChunkHeader->nUsed; + if (nTotal > nIndex) { + break; + } + } + 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_CHUNKHEADER* 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 = 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) { + ASSERT(nPos >= 0 && nPos <= m_nTotal); + FDE_CHUNKPLACE cp; + Index2CP(nPos, cp); + int32_t nLengthTemp = nLength; + if (cp.nCharIndex != 0) { + FDE_CHUNKHEADER* lpNewChunk = + static_cast<FDE_CHUNKHEADER*>(m_pAllocator->Alloc( + sizeof(FDE_CHUNKHEADER) + (m_nChunkSize - 1) * sizeof(FX_WCHAR))); + FDE_CHUNKHEADER* lpChunk = 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_CHUNKHEADER* lpChunk = 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_CHUNKHEADER* lpChunk = + static_cast<FDE_CHUNKHEADER*>(m_pAllocator->Alloc( + sizeof(FDE_CHUNKHEADER) + (m_nChunkSize - 1) * sizeof(FX_WCHAR))); + 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) { + ASSERT(nLength > 0 && nIndex >= 0 && nIndex + nLength <= m_nTotal); + FDE_CHUNKPLACE cpEnd; + Index2CP(nIndex + nLength - 1, cpEnd); + m_nTotal -= nLength; + FDE_CHUNKHEADER* lpChunk = 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 = 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) { + 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_CHUNKHEADER* lpChunk = m_Chunks[i]; + if (lpChunk->nUsed == 0) { + m_pAllocator->Free(lpChunk); + m_Chunks.RemoveAt(i); + --i; + --nCount; + } + } + if (pPause && pPause->NeedToPauseNow()) + return FALSE; + + FDE_CHUNKHEADER* lpPreChunk = m_Chunks[0]; + FDE_CHUNKHEADER* lpCurChunk = nullptr; + for (i = 1; i < nCount; i++) { + lpCurChunk = 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) { + ASSERT(nChunkSize); + ASSERT(nDefChunkCount); + delete m_pAllocator; + m_pAllocator = nullptr; + m_Chunks.RemoveAll(); + m_nChunkSize = nChunkSize; + int32_t nChunkLength = + sizeof(FDE_CHUNKHEADER) + (m_nChunkSize - 1) * sizeof(FX_WCHAR); + m_pAllocator = IFX_MemoryAllocator::Create(FX_ALLOCTYPE_Fixed, nDefChunkCount, + nChunkLength); + FDE_CHUNKHEADER* lpChunkHeader = + static_cast<FDE_CHUNKHEADER*>(m_pAllocator->Alloc(nChunkLength)); + 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 += m_Chunks[i]->nUsed; + } + return nTotal; +} + +void CFDE_TxtEdtBuf::Index2CP(int32_t nIndex, FDE_CHUNKPLACE& cp) const { + ASSERT(nIndex <= GetTextLength()); + if (nIndex == m_nTotal) { + cp.nChunkIndex = m_Chunks.GetSize() - 1; + cp.nCharIndex = 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 += m_Chunks[i]->nUsed; + if (nTotal > nIndex) { + break; + } + } + cp.nChunkIndex = i; + cp.nCharIndex = m_Chunks[i]->nUsed - (nTotal - nIndex); +} |