1 // Copyright 2014 PDFium Authors. All rights reserved. 2 // Use of this source code is governed by a BSD-style license that can be 3 // found in the LICENSE file. 4 5 // Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com 6 7 #include "xfa/src/foxitlib.h" 8 #include "xfa/src/fee/include/ifde_txtedtbuf.h" 9 #include "xfa/src/fee/include/ifde_txtedtengine.h" 10 #include "xfa/src/fee/include/fx_wordbreak.h" 11 #include "fde_txtedtparag.h" 12 #include "fde_txtedtengine.h" 13 #include "fde_txtedtbuf.h" 14 CFDE_TxtEdtParag::CFDE_TxtEdtParag(CFDE_TxtEdtEngine* pEngine) 15 : m_nCharStart(0), 16 m_nCharCount(0), 17 m_nLineCount(0), 18 m_lpData(NULL), 19 m_pEngine(pEngine) { 20 FXSYS_assert(m_pEngine); 21 } 22 CFDE_TxtEdtParag::~CFDE_TxtEdtParag() { 23 if (m_lpData != NULL) { 24 FX_Free(m_lpData); 25 } 26 } 27 void CFDE_TxtEdtParag::LoadParag() { 28 if (m_lpData != NULL) { 29 ((int32_t*)m_lpData)[0]++; 30 return; 31 } 32 IFX_TxtBreak* pTxtBreak = m_pEngine->GetTextBreak(); 33 IFDE_TxtEdtBuf* pTxtBuf = m_pEngine->GetTextBuf(); 34 const FDE_TXTEDTPARAMS* pParam = m_pEngine->GetEditParams(); 35 FX_WCHAR wcAlias = 0; 36 if (pParam->dwMode & FDE_TEXTEDITMODE_Password) { 37 wcAlias = m_pEngine->GetAliasChar(); 38 } 39 IFX_CharIter* pIter = 40 new CFDE_TxtEdtBufIter((CFDE_TxtEdtBuf*)pTxtBuf, wcAlias); 41 pIter->SetAt(m_nCharStart); 42 int32_t nEndIndex = m_nCharStart + m_nCharCount; 43 CFX_ArrayTemplate<int32_t> LineBaseArr; 44 FX_BOOL bReload = FALSE; 45 FX_DWORD dwBreakStatus = FX_TXTBREAK_None; 46 do { 47 if (bReload) { 48 dwBreakStatus = pTxtBreak->EndBreak(FX_TXTBREAK_ParagraphBreak); 49 } else { 50 FX_WCHAR wAppend = pIter->GetChar(); 51 dwBreakStatus = pTxtBreak->AppendChar(wAppend); 52 } 53 if (pIter->GetAt() + 1 == nEndIndex && 54 dwBreakStatus < FX_TXTBREAK_LineBreak) { 55 dwBreakStatus = pTxtBreak->EndBreak(FX_TXTBREAK_ParagraphBreak); 56 } 57 if (dwBreakStatus > FX_TXTBREAK_PieceBreak) { 58 int32_t nCount = pTxtBreak->CountBreakPieces(); 59 int32_t nTotal = 0; 60 for (int32_t j = 0; j < nCount; j++) { 61 const CFX_TxtPiece* Piece = pTxtBreak->GetBreakPiece(j); 62 nTotal += Piece->GetLength(); 63 } 64 LineBaseArr.Add(nTotal); 65 pTxtBreak->ClearBreakPieces(); 66 } 67 if ((pIter->GetAt() + 1 == nEndIndex) && 68 (dwBreakStatus == FX_TXTBREAK_LineBreak)) { 69 bReload = TRUE; 70 pIter->Next(TRUE); 71 } 72 } while (pIter->Next(FALSE) && (pIter->GetAt() < nEndIndex)); 73 pIter->Release(); 74 pTxtBreak->EndBreak(FX_TXTBREAK_ParagraphBreak); 75 pTxtBreak->ClearBreakPieces(); 76 int32_t nLineCount = LineBaseArr.GetSize(); 77 m_nLineCount = nLineCount; 78 if (m_lpData == NULL) { 79 m_lpData = FX_Alloc(int32_t, nLineCount + 1); 80 } else { 81 m_lpData = FX_Realloc(int32_t, m_lpData, (nLineCount + 1)); 82 } 83 int32_t* pIntArr = (int32_t*)m_lpData; 84 pIntArr[0] = 1; 85 m_nLineCount = nLineCount; 86 pIntArr++; 87 for (int32_t j = 0; j < nLineCount; j++, pIntArr++) { 88 *pIntArr = LineBaseArr[j]; 89 } 90 LineBaseArr.RemoveAll(); 91 } 92 void CFDE_TxtEdtParag::UnloadParag() { 93 FXSYS_assert(m_lpData != NULL); 94 ((int32_t*)m_lpData)[0]--; 95 FXSYS_assert(((int32_t*)m_lpData)[0] >= 0); 96 if (((int32_t*)m_lpData)[0] == 0) { 97 FX_Free(m_lpData); 98 m_lpData = NULL; 99 } 100 } 101 void CFDE_TxtEdtParag::CalcLines() { 102 IFX_TxtBreak* pTxtBreak = m_pEngine->GetTextBreak(); 103 IFDE_TxtEdtBuf* pTxtBuf = m_pEngine->GetTextBuf(); 104 IFX_CharIter* pIter = new CFDE_TxtEdtBufIter((CFDE_TxtEdtBuf*)pTxtBuf); 105 int32_t nCount = 0; 106 FX_DWORD dwBreakStatus = FX_TXTBREAK_None; 107 int32_t nEndIndex = m_nCharStart + m_nCharCount; 108 pIter->SetAt(m_nCharStart); 109 FX_BOOL bReload = FALSE; 110 do { 111 if (bReload) { 112 dwBreakStatus = pTxtBreak->EndBreak(FX_TXTBREAK_ParagraphBreak); 113 } else { 114 FX_WCHAR wAppend = pIter->GetChar(); 115 dwBreakStatus = pTxtBreak->AppendChar(wAppend); 116 } 117 if (pIter->GetAt() + 1 == nEndIndex && 118 dwBreakStatus < FX_TXTBREAK_LineBreak) { 119 dwBreakStatus = pTxtBreak->EndBreak(FX_TXTBREAK_ParagraphBreak); 120 } 121 if (dwBreakStatus > FX_TXTBREAK_PieceBreak) { 122 nCount++; 123 pTxtBreak->ClearBreakPieces(); 124 } 125 if ((pIter->GetAt() + 1 == nEndIndex) && 126 (dwBreakStatus == FX_TXTBREAK_LineBreak)) { 127 bReload = TRUE; 128 pIter->Next(TRUE); 129 } 130 } while (pIter->Next(FALSE) && (pIter->GetAt() < nEndIndex)); 131 pIter->Release(); 132 pTxtBreak->EndBreak(FX_TXTBREAK_ParagraphBreak); 133 pTxtBreak->ClearBreakPieces(); 134 m_nLineCount = nCount; 135 } 136 void CFDE_TxtEdtParag::GetLineRange(int32_t nLineIndex, 137 int32_t& nStart, 138 int32_t& nCount) const { 139 int32_t* pLineBaseArr = (int32_t*)m_lpData; 140 FXSYS_assert(nLineIndex < m_nLineCount); 141 nStart = m_nCharStart; 142 pLineBaseArr++; 143 for (int32_t i = 0; i < nLineIndex; i++) { 144 nStart += *pLineBaseArr; 145 pLineBaseArr++; 146 } 147 nCount = *pLineBaseArr; 148 } 149