summaryrefslogtreecommitdiff
path: root/xfa/fde/cfde_txtedtbuf.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'xfa/fde/cfde_txtedtbuf.cpp')
-rw-r--r--xfa/fde/cfde_txtedtbuf.cpp328
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);
+}