// 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_txtedtparag.h"
|
|
#include "xfa/fde/cfde_txtedtbuf.h"
|
#include "xfa/fde/cfde_txtedtbufiter.h"
|
#include "xfa/fde/cfde_txtedtengine.h"
|
#include "xfa/fde/ifde_txtedtengine.h"
|
#include "xfa/fgas/layout/fgas_textbreak.h"
|
#include "xfa/fde/ifx_chariter.h"
|
|
CFDE_TxtEdtParag::CFDE_TxtEdtParag(CFDE_TxtEdtEngine* pEngine)
|
: m_nCharStart(0),
|
m_nCharCount(0),
|
m_nLineCount(0),
|
m_lpData(nullptr),
|
m_pEngine(pEngine) {
|
ASSERT(m_pEngine);
|
}
|
|
CFDE_TxtEdtParag::~CFDE_TxtEdtParag() {
|
if (m_lpData)
|
FX_Free(m_lpData);
|
}
|
|
void CFDE_TxtEdtParag::LoadParag() {
|
if (m_lpData) {
|
m_lpData[0]++;
|
return;
|
}
|
CFX_TxtBreak* pTxtBreak = m_pEngine->GetTextBreak();
|
CFDE_TxtEdtBuf* pTxtBuf = m_pEngine->GetTextBuf();
|
const FDE_TXTEDTPARAMS* pParam = m_pEngine->GetEditParams();
|
FX_WCHAR wcAlias = 0;
|
if (pParam->dwMode & FDE_TEXTEDITMODE_Password) {
|
wcAlias = m_pEngine->GetAliasChar();
|
}
|
std::unique_ptr<IFX_CharIter> pIter(
|
new CFDE_TxtEdtBufIter(static_cast<CFDE_TxtEdtBuf*>(pTxtBuf), wcAlias));
|
pIter->SetAt(m_nCharStart);
|
int32_t nEndIndex = m_nCharStart + m_nCharCount;
|
CFX_ArrayTemplate<int32_t> LineBaseArr;
|
FX_BOOL bReload = FALSE;
|
uint32_t dwBreakStatus = FX_TXTBREAK_None;
|
do {
|
if (bReload) {
|
dwBreakStatus = pTxtBreak->EndBreak(FX_TXTBREAK_ParagraphBreak);
|
} else {
|
FX_WCHAR wAppend = pIter->GetChar();
|
dwBreakStatus = pTxtBreak->AppendChar(wAppend);
|
}
|
if (pIter->GetAt() + 1 == nEndIndex &&
|
dwBreakStatus < FX_TXTBREAK_LineBreak) {
|
dwBreakStatus = pTxtBreak->EndBreak(FX_TXTBREAK_ParagraphBreak);
|
}
|
if (dwBreakStatus > FX_TXTBREAK_PieceBreak) {
|
int32_t nCount = pTxtBreak->CountBreakPieces();
|
int32_t nTotal = 0;
|
for (int32_t j = 0; j < nCount; j++) {
|
const CFX_TxtPiece* Piece = pTxtBreak->GetBreakPiece(j);
|
nTotal += Piece->GetLength();
|
}
|
LineBaseArr.Add(nTotal);
|
pTxtBreak->ClearBreakPieces();
|
}
|
if ((pIter->GetAt() + 1 == nEndIndex) &&
|
(dwBreakStatus == FX_TXTBREAK_LineBreak)) {
|
bReload = TRUE;
|
pIter->Next(TRUE);
|
}
|
} while (pIter->Next(FALSE) && (pIter->GetAt() < nEndIndex));
|
pTxtBreak->EndBreak(FX_TXTBREAK_ParagraphBreak);
|
pTxtBreak->ClearBreakPieces();
|
int32_t nLineCount = LineBaseArr.GetSize();
|
m_nLineCount = nLineCount;
|
if (m_lpData) {
|
m_lpData = FX_Realloc(int32_t, m_lpData, nLineCount + 1);
|
} else {
|
m_lpData = FX_Alloc(int32_t, nLineCount + 1);
|
}
|
int32_t* pIntArr = m_lpData;
|
pIntArr[0] = 1;
|
m_nLineCount = nLineCount;
|
pIntArr++;
|
for (int32_t j = 0; j < nLineCount; j++, pIntArr++) {
|
*pIntArr = LineBaseArr[j];
|
}
|
LineBaseArr.RemoveAll();
|
}
|
|
void CFDE_TxtEdtParag::UnloadParag() {
|
m_lpData[0]--;
|
ASSERT(m_lpData[0] >= 0);
|
if (m_lpData[0] == 0) {
|
FX_Free(m_lpData);
|
m_lpData = nullptr;
|
}
|
}
|
|
void CFDE_TxtEdtParag::CalcLines() {
|
CFX_TxtBreak* pTxtBreak = m_pEngine->GetTextBreak();
|
CFDE_TxtEdtBuf* pTxtBuf = m_pEngine->GetTextBuf();
|
int32_t nCount = 0;
|
uint32_t dwBreakStatus = FX_TXTBREAK_None;
|
int32_t nEndIndex = m_nCharStart + m_nCharCount;
|
std::unique_ptr<IFX_CharIter> pIter(
|
new CFDE_TxtEdtBufIter(static_cast<CFDE_TxtEdtBuf*>(pTxtBuf)));
|
pIter->SetAt(m_nCharStart);
|
FX_BOOL bReload = FALSE;
|
do {
|
if (bReload) {
|
dwBreakStatus = pTxtBreak->EndBreak(FX_TXTBREAK_ParagraphBreak);
|
} else {
|
FX_WCHAR wAppend = pIter->GetChar();
|
dwBreakStatus = pTxtBreak->AppendChar(wAppend);
|
}
|
if (pIter->GetAt() + 1 == nEndIndex &&
|
dwBreakStatus < FX_TXTBREAK_LineBreak) {
|
dwBreakStatus = pTxtBreak->EndBreak(FX_TXTBREAK_ParagraphBreak);
|
}
|
if (dwBreakStatus > FX_TXTBREAK_PieceBreak) {
|
nCount++;
|
pTxtBreak->ClearBreakPieces();
|
}
|
if ((pIter->GetAt() + 1 == nEndIndex) &&
|
(dwBreakStatus == FX_TXTBREAK_LineBreak)) {
|
bReload = TRUE;
|
pIter->Next(TRUE);
|
}
|
} while (pIter->Next(FALSE) && (pIter->GetAt() < nEndIndex));
|
pTxtBreak->EndBreak(FX_TXTBREAK_ParagraphBreak);
|
pTxtBreak->ClearBreakPieces();
|
m_nLineCount = nCount;
|
}
|
|
void CFDE_TxtEdtParag::GetLineRange(int32_t nLineIndex,
|
int32_t& nStart,
|
int32_t& nCount) const {
|
int32_t* pLineBaseArr = m_lpData;
|
ASSERT(nLineIndex < m_nLineCount);
|
nStart = m_nCharStart;
|
pLineBaseArr++;
|
for (int32_t i = 0; i < nLineIndex; i++) {
|
nStart += *pLineBaseArr;
|
pLineBaseArr++;
|
}
|
nCount = *pLineBaseArr;
|
}
|