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"
CFDE_TxtEdtParag(CFDE_TxtEdtEngine * pEngine)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 }
~CFDE_TxtEdtParag()22 CFDE_TxtEdtParag::~CFDE_TxtEdtParag() {
23   if (m_lpData != NULL) {
24     FX_Free(m_lpData);
25   }
26 }
LoadParag()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 }
UnloadParag()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 }
CalcLines()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 }
GetLineRange(int32_t nLineIndex,int32_t & nStart,int32_t & nCount) const136 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