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/fde/cfde_txtedtparag.h"
8
9 #include <memory>
10
11 #include "xfa/fde/cfde_txtedtbuf.h"
12 #include "xfa/fde/cfde_txtedtengine.h"
13 #include "xfa/fde/ifde_txtedtengine.h"
14 #include "xfa/fde/ifx_chariter.h"
15 #include "xfa/fgas/layout/fgas_textbreak.h"
16
CFDE_TxtEdtParag(CFDE_TxtEdtEngine * pEngine)17 CFDE_TxtEdtParag::CFDE_TxtEdtParag(CFDE_TxtEdtEngine* pEngine)
18 : m_nCharStart(0),
19 m_nCharCount(0),
20 m_nLineCount(0),
21 m_lpData(nullptr),
22 m_pEngine(pEngine) {
23 ASSERT(m_pEngine);
24 }
25
~CFDE_TxtEdtParag()26 CFDE_TxtEdtParag::~CFDE_TxtEdtParag() {
27 if (m_lpData)
28 FX_Free(m_lpData);
29 }
30
LoadParag()31 void CFDE_TxtEdtParag::LoadParag() {
32 if (m_lpData) {
33 m_lpData[0]++;
34 return;
35 }
36 CFX_TxtBreak* pTxtBreak = m_pEngine->GetTextBreak();
37 CFDE_TxtEdtBuf* pTxtBuf = m_pEngine->GetTextBuf();
38 const FDE_TXTEDTPARAMS* pParam = m_pEngine->GetEditParams();
39 FX_WCHAR wcAlias = 0;
40 if (pParam->dwMode & FDE_TEXTEDITMODE_Password) {
41 wcAlias = m_pEngine->GetAliasChar();
42 }
43 std::unique_ptr<IFX_CharIter> pIter(new CFDE_TxtEdtBuf::Iterator(
44 static_cast<CFDE_TxtEdtBuf*>(pTxtBuf), wcAlias));
45 pIter->SetAt(m_nCharStart);
46 int32_t nEndIndex = m_nCharStart + m_nCharCount;
47 CFX_ArrayTemplate<int32_t> LineBaseArr;
48 bool bReload = false;
49 uint32_t dwBreakStatus = FX_TXTBREAK_None;
50 do {
51 if (bReload) {
52 dwBreakStatus = pTxtBreak->EndBreak(FX_TXTBREAK_ParagraphBreak);
53 } else {
54 FX_WCHAR wAppend = pIter->GetChar();
55 dwBreakStatus = pTxtBreak->AppendChar(wAppend);
56 }
57 if (pIter->GetAt() + 1 == nEndIndex &&
58 dwBreakStatus < FX_TXTBREAK_LineBreak) {
59 dwBreakStatus = pTxtBreak->EndBreak(FX_TXTBREAK_ParagraphBreak);
60 }
61 if (dwBreakStatus > FX_TXTBREAK_PieceBreak) {
62 int32_t nCount = pTxtBreak->CountBreakPieces();
63 int32_t nTotal = 0;
64 for (int32_t j = 0; j < nCount; j++) {
65 const CFX_TxtPiece* Piece = pTxtBreak->GetBreakPiece(j);
66 nTotal += Piece->GetLength();
67 }
68 LineBaseArr.Add(nTotal);
69 pTxtBreak->ClearBreakPieces();
70 }
71 if ((pIter->GetAt() + 1 == nEndIndex) &&
72 (dwBreakStatus == FX_TXTBREAK_LineBreak)) {
73 bReload = true;
74 pIter->Next(true);
75 }
76 } while (pIter->Next(false) && (pIter->GetAt() < nEndIndex));
77 pTxtBreak->EndBreak(FX_TXTBREAK_ParagraphBreak);
78 pTxtBreak->ClearBreakPieces();
79 int32_t nLineCount = LineBaseArr.GetSize();
80 m_nLineCount = nLineCount;
81 if (m_lpData) {
82 m_lpData = FX_Realloc(int32_t, m_lpData, nLineCount + 1);
83 } else {
84 m_lpData = FX_Alloc(int32_t, nLineCount + 1);
85 }
86 int32_t* pIntArr = m_lpData;
87 pIntArr[0] = 1;
88 m_nLineCount = nLineCount;
89 pIntArr++;
90 for (int32_t j = 0; j < nLineCount; j++, pIntArr++) {
91 *pIntArr = LineBaseArr[j];
92 }
93 LineBaseArr.RemoveAll();
94 }
95
UnloadParag()96 void CFDE_TxtEdtParag::UnloadParag() {
97 m_lpData[0]--;
98 ASSERT(m_lpData[0] >= 0);
99 if (m_lpData[0] == 0) {
100 FX_Free(m_lpData);
101 m_lpData = nullptr;
102 }
103 }
104
CalcLines()105 void CFDE_TxtEdtParag::CalcLines() {
106 CFX_TxtBreak* pTxtBreak = m_pEngine->GetTextBreak();
107 CFDE_TxtEdtBuf* pTxtBuf = m_pEngine->GetTextBuf();
108 int32_t nCount = 0;
109 uint32_t dwBreakStatus = FX_TXTBREAK_None;
110 int32_t nEndIndex = m_nCharStart + m_nCharCount;
111 std::unique_ptr<IFX_CharIter> pIter(
112 new CFDE_TxtEdtBuf::Iterator(static_cast<CFDE_TxtEdtBuf*>(pTxtBuf)));
113 pIter->SetAt(m_nCharStart);
114 bool bReload = false;
115 do {
116 if (bReload) {
117 dwBreakStatus = pTxtBreak->EndBreak(FX_TXTBREAK_ParagraphBreak);
118 } else {
119 FX_WCHAR wAppend = pIter->GetChar();
120 dwBreakStatus = pTxtBreak->AppendChar(wAppend);
121 }
122 if (pIter->GetAt() + 1 == nEndIndex &&
123 dwBreakStatus < FX_TXTBREAK_LineBreak) {
124 dwBreakStatus = pTxtBreak->EndBreak(FX_TXTBREAK_ParagraphBreak);
125 }
126 if (dwBreakStatus > FX_TXTBREAK_PieceBreak) {
127 nCount++;
128 pTxtBreak->ClearBreakPieces();
129 }
130 if ((pIter->GetAt() + 1 == nEndIndex) &&
131 (dwBreakStatus == FX_TXTBREAK_LineBreak)) {
132 bReload = true;
133 pIter->Next(true);
134 }
135 } while (pIter->Next(false) && (pIter->GetAt() < nEndIndex));
136 pTxtBreak->EndBreak(FX_TXTBREAK_ParagraphBreak);
137 pTxtBreak->ClearBreakPieces();
138 m_nLineCount = nCount;
139 }
140
GetLineRange(int32_t nLineIndex,int32_t & nStart,int32_t & nCount) const141 void CFDE_TxtEdtParag::GetLineRange(int32_t nLineIndex,
142 int32_t& nStart,
143 int32_t& nCount) const {
144 int32_t* pLineBaseArr = m_lpData;
145 ASSERT(nLineIndex < m_nLineCount);
146 nStart = m_nCharStart;
147 pLineBaseArr++;
148 for (int32_t i = 0; i < nLineIndex; i++) {
149 nStart += *pLineBaseArr;
150 pLineBaseArr++;
151 }
152 nCount = *pLineBaseArr;
153 }
154