OLD | NEW |
| (Empty) |
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 <vector> | |
8 | |
9 #include "core/fpdfapi/fpdf_font/include/cpdf_fontencoding.h" | |
10 #include "core/fpdfapi/fpdf_page/include/cpdf_page.h" | |
11 #include "core/fpdfapi/fpdf_parser/include/cfdf_document.h" | |
12 #include "core/fpdfapi/fpdf_parser/include/cpdf_array.h" | |
13 #include "core/fpdfapi/fpdf_parser/include/cpdf_document.h" | |
14 #include "core/fpdfapi/fpdf_parser/include/cpdf_string.h" | |
15 #include "core/fpdfdoc/include/cpdf_filespec.h" | |
16 #include "core/fpdfdoc/include/cpdf_formcontrol.h" | |
17 #include "core/fpdfdoc/include/cpdf_interform.h" | |
18 #include "core/fpdfdoc/doc_utils.h" | |
19 #include "third_party/base/stl_util.h" | |
20 | |
21 namespace { | |
22 | |
23 const int nMaxRecursion = 32; | |
24 | |
25 const struct SupportFieldEncoding { | |
26 const FX_CHAR* m_name; | |
27 uint16_t m_codePage; | |
28 } g_fieldEncoding[] = { | |
29 {"BigFive", 950}, | |
30 {"GBK", 936}, | |
31 {"Shift-JIS", 932}, | |
32 {"UHC", 949}, | |
33 }; | |
34 | |
35 CFX_WideString FPDFDOC_FDF_GetFieldValue(const CPDF_Dictionary& pFieldDict, | |
36 const CFX_ByteString& bsEncoding) { | |
37 const CFX_ByteString csBValue = pFieldDict.GetStringBy("V"); | |
38 for (const auto& encoding : g_fieldEncoding) { | |
39 if (bsEncoding == encoding.m_name) | |
40 return CFX_WideString::FromCodePage(csBValue.AsStringC(), | |
41 encoding.m_codePage); | |
42 } | |
43 CFX_ByteString csTemp = csBValue.Left(2); | |
44 if (csTemp == "\xFF\xFE" || csTemp == "\xFE\xFF") | |
45 return PDF_DecodeText(csBValue); | |
46 return CFX_WideString::FromLocal(csBValue.AsStringC()); | |
47 } | |
48 | |
49 } // namespace | |
50 | |
51 class CFieldNameExtractor { | |
52 public: | |
53 explicit CFieldNameExtractor(const CFX_WideString& full_name) | |
54 : m_FullName(full_name) { | |
55 m_pCur = m_FullName.c_str(); | |
56 m_pEnd = m_pCur + m_FullName.GetLength(); | |
57 } | |
58 | |
59 void GetNext(const FX_WCHAR*& pSubName, FX_STRSIZE& size) { | |
60 pSubName = m_pCur; | |
61 while (m_pCur < m_pEnd && m_pCur[0] != L'.') { | |
62 m_pCur++; | |
63 } | |
64 size = (FX_STRSIZE)(m_pCur - pSubName); | |
65 if (m_pCur < m_pEnd && m_pCur[0] == L'.') { | |
66 m_pCur++; | |
67 } | |
68 } | |
69 | |
70 protected: | |
71 CFX_WideString m_FullName; | |
72 const FX_WCHAR* m_pCur; | |
73 const FX_WCHAR* m_pEnd; | |
74 }; | |
75 | |
76 class CFieldTree { | |
77 public: | |
78 struct _Node { | |
79 _Node* parent; | |
80 CFX_ArrayTemplate<_Node*> children; | |
81 CFX_WideString short_name; | |
82 CPDF_FormField* field_ptr; | |
83 int CountFields(int nLevel = 0) { | |
84 if (nLevel > nMaxRecursion) { | |
85 return 0; | |
86 } | |
87 if (field_ptr) { | |
88 return 1; | |
89 } | |
90 int count = 0; | |
91 for (int i = 0; i < children.GetSize(); i++) { | |
92 count += children.GetAt(i)->CountFields(nLevel + 1); | |
93 } | |
94 return count; | |
95 } | |
96 CPDF_FormField* GetField(int* fields_to_go) { | |
97 if (field_ptr) { | |
98 if (*fields_to_go == 0) { | |
99 return field_ptr; | |
100 } | |
101 --*fields_to_go; | |
102 return nullptr; | |
103 } | |
104 for (int i = 0; i < children.GetSize(); i++) { | |
105 if (CPDF_FormField* pField = children.GetAt(i)->GetField(fields_to_go)) | |
106 return pField; | |
107 } | |
108 return nullptr; | |
109 } | |
110 CPDF_FormField* GetField(int index) { | |
111 int fields_to_go = index; | |
112 return GetField(&fields_to_go); | |
113 } | |
114 }; | |
115 CFieldTree(); | |
116 ~CFieldTree(); | |
117 void SetField(const CFX_WideString& full_name, CPDF_FormField* field_ptr); | |
118 CPDF_FormField* GetField(const CFX_WideString& full_name); | |
119 CPDF_FormField* RemoveField(const CFX_WideString& full_name); | |
120 void RemoveAll(); | |
121 _Node* FindNode(const CFX_WideString& full_name); | |
122 _Node* AddChild(_Node* pParent, | |
123 const CFX_WideString& short_name, | |
124 CPDF_FormField* field_ptr); | |
125 void RemoveNode(_Node* pNode, int nLevel = 0); | |
126 _Node* _Lookup(_Node* pParent, const CFX_WideString& short_name); | |
127 _Node m_Root; | |
128 }; | |
129 CFieldTree::CFieldTree() { | |
130 m_Root.parent = nullptr; | |
131 m_Root.field_ptr = nullptr; | |
132 } | |
133 CFieldTree::~CFieldTree() { | |
134 RemoveAll(); | |
135 } | |
136 CFieldTree::_Node* CFieldTree::AddChild(_Node* pParent, | |
137 const CFX_WideString& short_name, | |
138 CPDF_FormField* field_ptr) { | |
139 if (!pParent) { | |
140 return nullptr; | |
141 } | |
142 _Node* pNode = new _Node; | |
143 pNode->parent = pParent; | |
144 pNode->short_name = short_name; | |
145 pNode->field_ptr = field_ptr; | |
146 pParent->children.Add(pNode); | |
147 return pNode; | |
148 } | |
149 void CFieldTree::RemoveNode(_Node* pNode, int nLevel) { | |
150 if (!pNode) { | |
151 return; | |
152 } | |
153 if (nLevel <= nMaxRecursion) { | |
154 for (int i = 0; i < pNode->children.GetSize(); i++) { | |
155 RemoveNode(pNode->children[i], nLevel + 1); | |
156 } | |
157 } | |
158 delete pNode; | |
159 } | |
160 CFieldTree::_Node* CFieldTree::_Lookup(_Node* pParent, | |
161 const CFX_WideString& short_name) { | |
162 if (!pParent) { | |
163 return nullptr; | |
164 } | |
165 for (int i = 0; i < pParent->children.GetSize(); i++) { | |
166 _Node* pNode = pParent->children[i]; | |
167 if (pNode->short_name.GetLength() == short_name.GetLength() && | |
168 FXSYS_memcmp(pNode->short_name.c_str(), short_name.c_str(), | |
169 short_name.GetLength() * sizeof(FX_WCHAR)) == 0) { | |
170 return pNode; | |
171 } | |
172 } | |
173 return nullptr; | |
174 } | |
175 void CFieldTree::RemoveAll() { | |
176 for (int i = 0; i < m_Root.children.GetSize(); i++) { | |
177 RemoveNode(m_Root.children[i]); | |
178 } | |
179 } | |
180 void CFieldTree::SetField(const CFX_WideString& full_name, | |
181 CPDF_FormField* field_ptr) { | |
182 if (full_name == L"") { | |
183 return; | |
184 } | |
185 CFieldNameExtractor name_extractor(full_name); | |
186 const FX_WCHAR* pName; | |
187 FX_STRSIZE nLength; | |
188 name_extractor.GetNext(pName, nLength); | |
189 _Node *pNode = &m_Root, *pLast = nullptr; | |
190 while (nLength > 0) { | |
191 pLast = pNode; | |
192 CFX_WideString name = CFX_WideString(pName, nLength); | |
193 pNode = _Lookup(pLast, name); | |
194 if (!pNode) { | |
195 pNode = AddChild(pLast, name, nullptr); | |
196 } | |
197 name_extractor.GetNext(pName, nLength); | |
198 } | |
199 if (pNode != &m_Root) { | |
200 pNode->field_ptr = field_ptr; | |
201 } | |
202 } | |
203 CPDF_FormField* CFieldTree::GetField(const CFX_WideString& full_name) { | |
204 if (full_name == L"") { | |
205 return nullptr; | |
206 } | |
207 CFieldNameExtractor name_extractor(full_name); | |
208 const FX_WCHAR* pName; | |
209 FX_STRSIZE nLength; | |
210 name_extractor.GetNext(pName, nLength); | |
211 _Node *pNode = &m_Root, *pLast = nullptr; | |
212 while (nLength > 0 && pNode) { | |
213 pLast = pNode; | |
214 CFX_WideString name = CFX_WideString(pName, nLength); | |
215 pNode = _Lookup(pLast, name); | |
216 name_extractor.GetNext(pName, nLength); | |
217 } | |
218 return pNode ? pNode->field_ptr : nullptr; | |
219 } | |
220 CPDF_FormField* CFieldTree::RemoveField(const CFX_WideString& full_name) { | |
221 if (full_name == L"") { | |
222 return nullptr; | |
223 } | |
224 CFieldNameExtractor name_extractor(full_name); | |
225 const FX_WCHAR* pName; | |
226 FX_STRSIZE nLength; | |
227 name_extractor.GetNext(pName, nLength); | |
228 _Node* pNode = &m_Root; | |
229 _Node* pLast = nullptr; | |
230 while (nLength > 0 && pNode) { | |
231 pLast = pNode; | |
232 CFX_WideString name = CFX_WideString(pName, nLength); | |
233 pNode = _Lookup(pLast, name); | |
234 name_extractor.GetNext(pName, nLength); | |
235 } | |
236 if (pNode && pNode != &m_Root) { | |
237 for (int i = 0; i < pLast->children.GetSize(); i++) { | |
238 if (pNode == pLast->children[i]) { | |
239 pLast->children.RemoveAt(i); | |
240 break; | |
241 } | |
242 } | |
243 CPDF_FormField* pField = pNode->field_ptr; | |
244 RemoveNode(pNode); | |
245 return pField; | |
246 } | |
247 return nullptr; | |
248 } | |
249 CFieldTree::_Node* CFieldTree::FindNode(const CFX_WideString& full_name) { | |
250 if (full_name == L"") { | |
251 return nullptr; | |
252 } | |
253 CFieldNameExtractor name_extractor(full_name); | |
254 const FX_WCHAR* pName; | |
255 FX_STRSIZE nLength; | |
256 name_extractor.GetNext(pName, nLength); | |
257 _Node *pNode = &m_Root, *pLast = nullptr; | |
258 while (nLength > 0 && pNode) { | |
259 pLast = pNode; | |
260 CFX_WideString name = CFX_WideString(pName, nLength); | |
261 pNode = _Lookup(pLast, name); | |
262 name_extractor.GetNext(pName, nLength); | |
263 } | |
264 return pNode; | |
265 } | |
266 | |
267 CPDF_InterForm::CPDF_InterForm(CPDF_Document* pDocument) | |
268 : m_pDocument(pDocument), | |
269 m_pFormDict(nullptr), | |
270 m_pFieldTree(new CFieldTree), | |
271 m_pFormNotify(nullptr) { | |
272 CPDF_Dictionary* pRoot = m_pDocument->GetRoot(); | |
273 if (!pRoot) | |
274 return; | |
275 | |
276 m_pFormDict = pRoot->GetDictBy("AcroForm"); | |
277 if (!m_pFormDict) | |
278 return; | |
279 | |
280 CPDF_Array* pFields = m_pFormDict->GetArrayBy("Fields"); | |
281 if (!pFields) | |
282 return; | |
283 | |
284 for (size_t i = 0; i < pFields->GetCount(); i++) | |
285 LoadField(pFields->GetDictAt(i)); | |
286 } | |
287 | |
288 CPDF_InterForm::~CPDF_InterForm() { | |
289 for (auto it : m_ControlMap) | |
290 delete it.second; | |
291 | |
292 int nCount = m_pFieldTree->m_Root.CountFields(); | |
293 for (int i = 0; i < nCount; ++i) { | |
294 delete m_pFieldTree->m_Root.GetField(i); | |
295 } | |
296 } | |
297 | |
298 FX_BOOL CPDF_InterForm::s_bUpdateAP = TRUE; | |
299 | |
300 FX_BOOL CPDF_InterForm::IsUpdateAPEnabled() { | |
301 return s_bUpdateAP; | |
302 } | |
303 | |
304 void CPDF_InterForm::SetUpdateAP(FX_BOOL bUpdateAP) { | |
305 s_bUpdateAP = bUpdateAP; | |
306 } | |
307 | |
308 CFX_ByteString CPDF_InterForm::GenerateNewResourceName( | |
309 const CPDF_Dictionary* pResDict, | |
310 const FX_CHAR* csType, | |
311 int iMinLen, | |
312 const FX_CHAR* csPrefix) { | |
313 CFX_ByteString csStr = csPrefix; | |
314 CFX_ByteString csBType = csType; | |
315 if (csStr.IsEmpty()) { | |
316 if (csBType == "ExtGState") { | |
317 csStr = "GS"; | |
318 } else if (csBType == "ColorSpace") { | |
319 csStr = "CS"; | |
320 } else if (csBType == "Font") { | |
321 csStr = "ZiTi"; | |
322 } else { | |
323 csStr = "Res"; | |
324 } | |
325 } | |
326 CFX_ByteString csTmp = csStr; | |
327 int iCount = csStr.GetLength(); | |
328 int m = 0; | |
329 if (iMinLen > 0) { | |
330 csTmp = ""; | |
331 while (m < iMinLen && m < iCount) { | |
332 csTmp += csStr[m++]; | |
333 } | |
334 while (m < iMinLen) { | |
335 csTmp += '0' + m % 10; | |
336 m++; | |
337 } | |
338 } else { | |
339 m = iCount; | |
340 } | |
341 if (!pResDict) { | |
342 return csTmp; | |
343 } | |
344 CPDF_Dictionary* pDict = pResDict->GetDictBy(csType); | |
345 if (!pDict) { | |
346 return csTmp; | |
347 } | |
348 int num = 0; | |
349 CFX_ByteString bsNum; | |
350 while (TRUE) { | |
351 CFX_ByteString csKey = csTmp + bsNum; | |
352 if (!pDict->KeyExist(csKey)) { | |
353 return csKey; | |
354 } | |
355 if (m < iCount) { | |
356 csTmp += csStr[m++]; | |
357 } else { | |
358 bsNum.Format("%d", num++); | |
359 } | |
360 m++; | |
361 } | |
362 return csTmp; | |
363 } | |
364 #if _FXM_PLATFORM_ == _FXM_PLATFORM_WINDOWS_ | |
365 typedef struct PDF_FONTDATA_ { | |
366 FX_BOOL bFind; | |
367 LOGFONTA lf; | |
368 } PDF_FONTDATA, FAR* LPDF_FONTDATA; | |
369 static int CALLBACK EnumFontFamExProc(ENUMLOGFONTEXA* lpelfe, | |
370 NEWTEXTMETRICEX* lpntme, | |
371 DWORD FontType, | |
372 LPARAM lParam) { | |
373 if (FontType != 0x004 || strchr(lpelfe->elfLogFont.lfFaceName, '@')) { | |
374 return 1; | |
375 } | |
376 LPDF_FONTDATA pData = (LPDF_FONTDATA)lParam; | |
377 memcpy(&pData->lf, &lpelfe->elfLogFont, sizeof(LOGFONTA)); | |
378 pData->bFind = TRUE; | |
379 return 0; | |
380 } | |
381 static FX_BOOL RetrieveSpecificFont(LOGFONTA& lf) { | |
382 PDF_FONTDATA fd; | |
383 memset(&fd, 0, sizeof(PDF_FONTDATA)); | |
384 HDC hDC = ::GetDC(nullptr); | |
385 EnumFontFamiliesExA(hDC, &lf, (FONTENUMPROCA)EnumFontFamExProc, (LPARAM)&fd, | |
386 0); | |
387 ::ReleaseDC(nullptr, hDC); | |
388 if (fd.bFind) { | |
389 memcpy(&lf, &fd.lf, sizeof(LOGFONTA)); | |
390 } | |
391 return fd.bFind; | |
392 } | |
393 static FX_BOOL RetrieveSpecificFont(uint8_t charSet, | |
394 uint8_t pitchAndFamily, | |
395 LPCSTR pcsFontName, | |
396 LOGFONTA& lf) { | |
397 memset(&lf, 0, sizeof(LOGFONTA)); | |
398 lf.lfCharSet = charSet; | |
399 lf.lfPitchAndFamily = pitchAndFamily; | |
400 if (pcsFontName) { | |
401 // TODO(dsinclair): Should this be strncpy? | |
402 strcpy(lf.lfFaceName, pcsFontName); | |
403 } | |
404 return RetrieveSpecificFont(lf); | |
405 } | |
406 #endif // _FXM_PLATFORM_ == _FXM_PLATFORM_WINDOWS_ | |
407 | |
408 CPDF_Font* CPDF_InterForm::AddStandardFont(CPDF_Document* pDocument, | |
409 CFX_ByteString csFontName) { | |
410 if (!pDocument || csFontName.IsEmpty()) | |
411 return nullptr; | |
412 | |
413 if (csFontName == "ZapfDingbats") | |
414 return pDocument->AddStandardFont(csFontName.c_str(), nullptr); | |
415 | |
416 CPDF_FontEncoding encoding(PDFFONT_ENCODING_WINANSI); | |
417 return pDocument->AddStandardFont(csFontName.c_str(), &encoding); | |
418 } | |
419 | |
420 CFX_ByteString CPDF_InterForm::GetNativeFont(uint8_t charSet, void* pLogFont) { | |
421 CFX_ByteString csFontName; | |
422 #if _FXM_PLATFORM_ == _FXM_PLATFORM_WINDOWS_ | |
423 LOGFONTA lf = {}; | |
424 if (charSet == ANSI_CHARSET) { | |
425 csFontName = "Helvetica"; | |
426 return csFontName; | |
427 } | |
428 FX_BOOL bRet = FALSE; | |
429 if (charSet == SHIFTJIS_CHARSET) { | |
430 bRet = RetrieveSpecificFont(charSet, DEFAULT_PITCH | FF_DONTCARE, | |
431 "MS Mincho", lf); | |
432 } else if (charSet == GB2312_CHARSET) { | |
433 bRet = RetrieveSpecificFont(charSet, DEFAULT_PITCH | FF_DONTCARE, "SimSun", | |
434 lf); | |
435 } else if (charSet == CHINESEBIG5_CHARSET) { | |
436 bRet = RetrieveSpecificFont(charSet, DEFAULT_PITCH | FF_DONTCARE, "MingLiU", | |
437 lf); | |
438 } | |
439 if (!bRet) { | |
440 bRet = RetrieveSpecificFont(charSet, DEFAULT_PITCH | FF_DONTCARE, | |
441 "Arial Unicode MS", lf); | |
442 } | |
443 if (!bRet) { | |
444 bRet = RetrieveSpecificFont(charSet, DEFAULT_PITCH | FF_DONTCARE, | |
445 "Microsoft Sans Serif", lf); | |
446 } | |
447 if (!bRet) { | |
448 bRet = | |
449 RetrieveSpecificFont(charSet, DEFAULT_PITCH | FF_DONTCARE, nullptr, lf); | |
450 } | |
451 if (bRet) { | |
452 if (pLogFont) { | |
453 memcpy(pLogFont, &lf, sizeof(LOGFONTA)); | |
454 } | |
455 csFontName = lf.lfFaceName; | |
456 return csFontName; | |
457 } | |
458 #endif | |
459 return csFontName; | |
460 } | |
461 | |
462 CFX_ByteString CPDF_InterForm::GetNativeFont(void* pLogFont) { | |
463 #if _FXM_PLATFORM_ == _FXM_PLATFORM_WINDOWS_ | |
464 return GetNativeFont(GetNativeCharSet(), pLogFont); | |
465 #else | |
466 return CFX_ByteString(); | |
467 #endif | |
468 } | |
469 | |
470 // static | |
471 uint8_t CPDF_InterForm::GetNativeCharSet() { | |
472 #if _FXM_PLATFORM_ == _FXM_PLATFORM_WINDOWS_ | |
473 uint8_t charSet = ANSI_CHARSET; | |
474 UINT iCodePage = ::GetACP(); | |
475 switch (iCodePage) { | |
476 case 932: | |
477 charSet = SHIFTJIS_CHARSET; | |
478 break; | |
479 case 936: | |
480 charSet = GB2312_CHARSET; | |
481 break; | |
482 case 950: | |
483 charSet = CHINESEBIG5_CHARSET; | |
484 break; | |
485 case 1252: | |
486 charSet = ANSI_CHARSET; | |
487 break; | |
488 case 874: | |
489 charSet = THAI_CHARSET; | |
490 break; | |
491 case 949: | |
492 charSet = HANGUL_CHARSET; | |
493 break; | |
494 case 1200: | |
495 charSet = ANSI_CHARSET; | |
496 break; | |
497 case 1250: | |
498 charSet = EASTEUROPE_CHARSET; | |
499 break; | |
500 case 1251: | |
501 charSet = RUSSIAN_CHARSET; | |
502 break; | |
503 case 1253: | |
504 charSet = GREEK_CHARSET; | |
505 break; | |
506 case 1254: | |
507 charSet = TURKISH_CHARSET; | |
508 break; | |
509 case 1255: | |
510 charSet = HEBREW_CHARSET; | |
511 break; | |
512 case 1256: | |
513 charSet = ARABIC_CHARSET; | |
514 break; | |
515 case 1257: | |
516 charSet = BALTIC_CHARSET; | |
517 break; | |
518 case 1258: | |
519 charSet = VIETNAMESE_CHARSET; | |
520 break; | |
521 case 1361: | |
522 charSet = JOHAB_CHARSET; | |
523 break; | |
524 } | |
525 return charSet; | |
526 #else | |
527 return 0; | |
528 #endif | |
529 } | |
530 | |
531 CPDF_Font* CPDF_InterForm::AddNativeFont(uint8_t charSet, | |
532 CPDF_Document* pDocument) { | |
533 if (!pDocument) | |
534 return nullptr; | |
535 | |
536 #if _FXM_PLATFORM_ == _FXM_PLATFORM_WINDOWS_ | |
537 LOGFONTA lf; | |
538 CFX_ByteString csFontName = GetNativeFont(charSet, &lf); | |
539 if (!csFontName.IsEmpty()) { | |
540 if (csFontName == "Helvetica") | |
541 return AddStandardFont(pDocument, csFontName); | |
542 return pDocument->AddWindowsFont(&lf, FALSE, TRUE); | |
543 } | |
544 #endif | |
545 return nullptr; | |
546 } | |
547 | |
548 CPDF_Font* CPDF_InterForm::AddNativeFont(CPDF_Document* pDocument) { | |
549 return pDocument ? AddNativeFont(GetNativeCharSet(), pDocument) : nullptr; | |
550 } | |
551 | |
552 FX_BOOL CPDF_InterForm::ValidateFieldName( | |
553 CFX_WideString& csNewFieldName, | |
554 int iType, | |
555 const CPDF_FormField* pExcludedField, | |
556 const CPDF_FormControl* pExcludedControl) { | |
557 if (csNewFieldName.IsEmpty()) { | |
558 return FALSE; | |
559 } | |
560 int iPos = 0; | |
561 int iLength = csNewFieldName.GetLength(); | |
562 CFX_WideString csSub; | |
563 while (TRUE) { | |
564 while (iPos < iLength && | |
565 (csNewFieldName[iPos] == L'.' || csNewFieldName[iPos] == L' ')) { | |
566 iPos++; | |
567 } | |
568 if (iPos < iLength && !csSub.IsEmpty()) { | |
569 csSub += L'.'; | |
570 } | |
571 while (iPos < iLength && csNewFieldName[iPos] != L'.') { | |
572 csSub += csNewFieldName[iPos++]; | |
573 } | |
574 for (int i = csSub.GetLength() - 1; i > -1; i--) { | |
575 if (csSub[i] == L' ' || csSub[i] == L'.') { | |
576 csSub.SetAt(i, L'\0'); | |
577 } else { | |
578 break; | |
579 } | |
580 } | |
581 uint32_t dwCount = m_pFieldTree->m_Root.CountFields(); | |
582 for (uint32_t m = 0; m < dwCount; m++) { | |
583 CPDF_FormField* pField = m_pFieldTree->m_Root.GetField(m); | |
584 if (!pField) { | |
585 continue; | |
586 } | |
587 if (pField == pExcludedField) { | |
588 if (pExcludedControl) { | |
589 if (pField->CountControls() < 2) { | |
590 continue; | |
591 } | |
592 } else { | |
593 continue; | |
594 } | |
595 } | |
596 CFX_WideString csFullName = pField->GetFullName(); | |
597 int iRet = CompareFieldName(csSub, csFullName); | |
598 if (iRet == 1) { | |
599 if (pField->GetFieldType() != iType) { | |
600 return FALSE; | |
601 } | |
602 } else if (iRet == 2 && csSub == csNewFieldName) { | |
603 if (csFullName[iPos] == L'.') { | |
604 return FALSE; | |
605 } | |
606 } else if (iRet == 3 && csSub == csNewFieldName) { | |
607 if (csNewFieldName[csFullName.GetLength()] == L'.') { | |
608 return FALSE; | |
609 } | |
610 } | |
611 } | |
612 if (iPos >= iLength) { | |
613 break; | |
614 } | |
615 } | |
616 if (csSub.IsEmpty()) { | |
617 return FALSE; | |
618 } | |
619 csNewFieldName = csSub; | |
620 return TRUE; | |
621 } | |
622 FX_BOOL CPDF_InterForm::ValidateFieldName(CFX_WideString& csNewFieldName, | |
623 int iType) { | |
624 return ValidateFieldName(csNewFieldName, iType, nullptr, nullptr); | |
625 } | |
626 FX_BOOL CPDF_InterForm::ValidateFieldName(const CPDF_FormField* pField, | |
627 CFX_WideString& csNewFieldName) { | |
628 return pField && !csNewFieldName.IsEmpty() && | |
629 ValidateFieldName(csNewFieldName, pField->GetFieldType(), pField, | |
630 nullptr); | |
631 } | |
632 FX_BOOL CPDF_InterForm::ValidateFieldName(const CPDF_FormControl* pControl, | |
633 CFX_WideString& csNewFieldName) { | |
634 if (!pControl || csNewFieldName.IsEmpty()) { | |
635 return FALSE; | |
636 } | |
637 CPDF_FormField* pField = pControl->GetField(); | |
638 return ValidateFieldName(csNewFieldName, pField->GetFieldType(), pField, | |
639 pControl); | |
640 } | |
641 int CPDF_InterForm::CompareFieldName(const CFX_ByteString& name1, | |
642 const CFX_ByteString& name2) { | |
643 if (name1.GetLength() == name2.GetLength()) { | |
644 return name1 == name2 ? 1 : 0; | |
645 } | |
646 const FX_CHAR* ptr1 = name1.c_str(); | |
647 const FX_CHAR* ptr2 = name2.c_str(); | |
648 int i = 0; | |
649 while (ptr1[i] == ptr2[i]) { | |
650 i++; | |
651 } | |
652 if (i == name1.GetLength()) { | |
653 return 2; | |
654 } | |
655 if (i == name2.GetLength()) { | |
656 return 3; | |
657 } | |
658 return 0; | |
659 } | |
660 int CPDF_InterForm::CompareFieldName(const CFX_WideString& name1, | |
661 const CFX_WideString& name2) { | |
662 const FX_WCHAR* ptr1 = name1.c_str(); | |
663 const FX_WCHAR* ptr2 = name2.c_str(); | |
664 if (name1.GetLength() == name2.GetLength()) { | |
665 return name1 == name2 ? 1 : 0; | |
666 } | |
667 int i = 0; | |
668 while (ptr1[i] == ptr2[i]) { | |
669 i++; | |
670 } | |
671 if (i == name1.GetLength()) { | |
672 return 2; | |
673 } | |
674 if (i == name2.GetLength()) { | |
675 return 3; | |
676 } | |
677 return 0; | |
678 } | |
679 uint32_t CPDF_InterForm::CountFields(const CFX_WideString& csFieldName) { | |
680 if (csFieldName.IsEmpty()) { | |
681 return (uint32_t)m_pFieldTree->m_Root.CountFields(); | |
682 } | |
683 CFieldTree::_Node* pNode = m_pFieldTree->FindNode(csFieldName); | |
684 return pNode ? pNode->CountFields() : 0; | |
685 } | |
686 CPDF_FormField* CPDF_InterForm::GetField(uint32_t index, | |
687 const CFX_WideString& csFieldName) { | |
688 if (csFieldName == L"") { | |
689 return m_pFieldTree->m_Root.GetField(index); | |
690 } | |
691 CFieldTree::_Node* pNode = m_pFieldTree->FindNode(csFieldName); | |
692 return pNode ? pNode->GetField(index) : nullptr; | |
693 } | |
694 | |
695 CPDF_FormField* CPDF_InterForm::GetFieldByDict( | |
696 CPDF_Dictionary* pFieldDict) const { | |
697 if (!pFieldDict) { | |
698 return nullptr; | |
699 } | |
700 CFX_WideString csWName = GetFullName(pFieldDict); | |
701 return m_pFieldTree->GetField(csWName); | |
702 } | |
703 | |
704 CPDF_FormControl* CPDF_InterForm::GetControlAtPoint(CPDF_Page* pPage, | |
705 FX_FLOAT pdf_x, | |
706 FX_FLOAT pdf_y, | |
707 int* z_order) const { | |
708 CPDF_Array* pAnnotList = pPage->m_pFormDict->GetArrayBy("Annots"); | |
709 if (!pAnnotList) | |
710 return nullptr; | |
711 | |
712 for (size_t i = pAnnotList->GetCount(); i > 0; --i) { | |
713 size_t annot_index = i - 1; | |
714 CPDF_Dictionary* pAnnot = pAnnotList->GetDictAt(annot_index); | |
715 if (!pAnnot) | |
716 continue; | |
717 | |
718 const auto it = m_ControlMap.find(pAnnot); | |
719 if (it == m_ControlMap.end()) | |
720 continue; | |
721 | |
722 CPDF_FormControl* pControl = it->second; | |
723 CFX_FloatRect rect = pControl->GetRect(); | |
724 if (!rect.Contains(pdf_x, pdf_y)) | |
725 continue; | |
726 | |
727 if (z_order) | |
728 *z_order = static_cast<int>(annot_index); | |
729 return pControl; | |
730 } | |
731 return nullptr; | |
732 } | |
733 | |
734 CPDF_FormControl* CPDF_InterForm::GetControlByDict( | |
735 const CPDF_Dictionary* pWidgetDict) const { | |
736 const auto it = m_ControlMap.find(pWidgetDict); | |
737 return it != m_ControlMap.end() ? it->second : nullptr; | |
738 } | |
739 | |
740 FX_BOOL CPDF_InterForm::NeedConstructAP() const { | |
741 return m_pFormDict && m_pFormDict->GetBooleanBy("NeedAppearances"); | |
742 } | |
743 | |
744 int CPDF_InterForm::CountFieldsInCalculationOrder() { | |
745 if (!m_pFormDict) | |
746 return 0; | |
747 | |
748 CPDF_Array* pArray = m_pFormDict->GetArrayBy("CO"); | |
749 return pArray ? pArray->GetCount() : 0; | |
750 } | |
751 | |
752 CPDF_FormField* CPDF_InterForm::GetFieldInCalculationOrder(int index) { | |
753 if (!m_pFormDict || index < 0) | |
754 return nullptr; | |
755 | |
756 CPDF_Array* pArray = m_pFormDict->GetArrayBy("CO"); | |
757 if (!pArray) | |
758 return nullptr; | |
759 | |
760 CPDF_Dictionary* pElement = ToDictionary(pArray->GetDirectObjectAt(index)); | |
761 return pElement ? GetFieldByDict(pElement) : nullptr; | |
762 } | |
763 | |
764 int CPDF_InterForm::FindFieldInCalculationOrder(const CPDF_FormField* pField) { | |
765 if (!m_pFormDict || !pField) | |
766 return -1; | |
767 | |
768 CPDF_Array* pArray = m_pFormDict->GetArrayBy("CO"); | |
769 if (!pArray) | |
770 return -1; | |
771 | |
772 for (size_t i = 0; i < pArray->GetCount(); i++) { | |
773 CPDF_Object* pElement = pArray->GetDirectObjectAt(i); | |
774 if (pElement == pField->m_pDict) { | |
775 return i; | |
776 } | |
777 } | |
778 return -1; | |
779 } | |
780 | |
781 uint32_t CPDF_InterForm::CountFormFonts() { | |
782 return CountInterFormFonts(m_pFormDict); | |
783 } | |
784 | |
785 CPDF_Font* CPDF_InterForm::GetFormFont(uint32_t index, | |
786 CFX_ByteString& csNameTag) { | |
787 return GetInterFormFont(m_pFormDict, m_pDocument, index, csNameTag); | |
788 } | |
789 CPDF_Font* CPDF_InterForm::GetFormFont(CFX_ByteString csNameTag) { | |
790 return GetInterFormFont(m_pFormDict, m_pDocument, csNameTag); | |
791 } | |
792 CPDF_Font* CPDF_InterForm::GetFormFont(CFX_ByteString csFontName, | |
793 CFX_ByteString& csNameTag) { | |
794 return GetInterFormFont(m_pFormDict, m_pDocument, csFontName, csNameTag); | |
795 } | |
796 CPDF_Font* CPDF_InterForm::GetNativeFormFont(uint8_t charSet, | |
797 CFX_ByteString& csNameTag) { | |
798 return GetNativeInterFormFont(m_pFormDict, m_pDocument, charSet, csNameTag); | |
799 } | |
800 CPDF_Font* CPDF_InterForm::GetNativeFormFont(CFX_ByteString& csNameTag) { | |
801 return GetNativeInterFormFont(m_pFormDict, m_pDocument, csNameTag); | |
802 } | |
803 FX_BOOL CPDF_InterForm::FindFormFont(const CPDF_Font* pFont, | |
804 CFX_ByteString& csNameTag) { | |
805 return FindInterFormFont(m_pFormDict, pFont, csNameTag); | |
806 } | |
807 FX_BOOL CPDF_InterForm::FindFormFont(CFX_ByteString csFontName, | |
808 CPDF_Font*& pFont, | |
809 CFX_ByteString& csNameTag) { | |
810 return FindInterFormFont(m_pFormDict, m_pDocument, csFontName, pFont, | |
811 csNameTag); | |
812 } | |
813 void CPDF_InterForm::AddFormFont(const CPDF_Font* pFont, | |
814 CFX_ByteString& csNameTag) { | |
815 AddInterFormFont(m_pFormDict, m_pDocument, pFont, csNameTag); | |
816 } | |
817 | |
818 CPDF_Font* CPDF_InterForm::AddNativeFormFont(uint8_t charSet, | |
819 CFX_ByteString& csNameTag) { | |
820 return AddNativeInterFormFont(m_pFormDict, m_pDocument, charSet, csNameTag); | |
821 } | |
822 | |
823 CPDF_Font* CPDF_InterForm::AddNativeFormFont(CFX_ByteString& csNameTag) { | |
824 return AddNativeInterFormFont(m_pFormDict, m_pDocument, csNameTag); | |
825 } | |
826 | |
827 void CPDF_InterForm::RemoveFormFont(const CPDF_Font* pFont) { | |
828 RemoveInterFormFont(m_pFormDict, pFont); | |
829 } | |
830 | |
831 void CPDF_InterForm::RemoveFormFont(CFX_ByteString csNameTag) { | |
832 RemoveInterFormFont(m_pFormDict, csNameTag); | |
833 } | |
834 | |
835 CPDF_DefaultAppearance CPDF_InterForm::GetDefaultAppearance() { | |
836 if (!m_pFormDict) | |
837 return CPDF_DefaultAppearance(); | |
838 return CPDF_DefaultAppearance(m_pFormDict->GetStringBy("DA")); | |
839 } | |
840 | |
841 CPDF_Font* CPDF_InterForm::GetDefaultFormFont() { | |
842 return GetDefaultInterFormFont(m_pFormDict, m_pDocument); | |
843 } | |
844 int CPDF_InterForm::GetFormAlignment() { | |
845 return m_pFormDict ? m_pFormDict->GetIntegerBy("Q", 0) : 0; | |
846 } | |
847 | |
848 bool CPDF_InterForm::ResetForm(const std::vector<CPDF_FormField*>& fields, | |
849 bool bIncludeOrExclude, | |
850 bool bNotify) { | |
851 if (bNotify && m_pFormNotify && m_pFormNotify->BeforeFormReset(this) < 0) | |
852 return false; | |
853 | |
854 int nCount = m_pFieldTree->m_Root.CountFields(); | |
855 for (int i = 0; i < nCount; ++i) { | |
856 CPDF_FormField* pField = m_pFieldTree->m_Root.GetField(i); | |
857 if (!pField) | |
858 continue; | |
859 | |
860 if (bIncludeOrExclude == pdfium::ContainsValue(fields, pField)) | |
861 pField->ResetField(bNotify); | |
862 } | |
863 if (bNotify && m_pFormNotify) | |
864 m_pFormNotify->AfterFormReset(this); | |
865 return true; | |
866 } | |
867 | |
868 bool CPDF_InterForm::ResetForm(bool bNotify) { | |
869 if (bNotify && m_pFormNotify && m_pFormNotify->BeforeFormReset(this) < 0) | |
870 return false; | |
871 | |
872 int nCount = m_pFieldTree->m_Root.CountFields(); | |
873 for (int i = 0; i < nCount; ++i) { | |
874 CPDF_FormField* pField = m_pFieldTree->m_Root.GetField(i); | |
875 if (!pField) | |
876 continue; | |
877 | |
878 pField->ResetField(bNotify); | |
879 } | |
880 if (bNotify && m_pFormNotify) | |
881 m_pFormNotify->AfterFormReset(this); | |
882 return true; | |
883 } | |
884 | |
885 void CPDF_InterForm::LoadField(CPDF_Dictionary* pFieldDict, int nLevel) { | |
886 if (nLevel > nMaxRecursion) { | |
887 return; | |
888 } | |
889 if (!pFieldDict) { | |
890 return; | |
891 } | |
892 uint32_t dwParentObjNum = pFieldDict->GetObjNum(); | |
893 CPDF_Array* pKids = pFieldDict->GetArrayBy("Kids"); | |
894 if (!pKids) { | |
895 AddTerminalField(pFieldDict); | |
896 return; | |
897 } | |
898 CPDF_Dictionary* pFirstKid = pKids->GetDictAt(0); | |
899 if (!pFirstKid) { | |
900 return; | |
901 } | |
902 if (pFirstKid->KeyExist("T") || pFirstKid->KeyExist("Kids")) { | |
903 for (size_t i = 0; i < pKids->GetCount(); i++) { | |
904 CPDF_Dictionary* pChildDict = pKids->GetDictAt(i); | |
905 if (pChildDict) { | |
906 if (pChildDict->GetObjNum() != dwParentObjNum) { | |
907 LoadField(pChildDict, nLevel + 1); | |
908 } | |
909 } | |
910 } | |
911 } else { | |
912 AddTerminalField(pFieldDict); | |
913 } | |
914 } | |
915 FX_BOOL CPDF_InterForm::HasXFAForm() const { | |
916 return m_pFormDict && m_pFormDict->GetArrayBy("XFA"); | |
917 } | |
918 void CPDF_InterForm::FixPageFields(const CPDF_Page* pPage) { | |
919 CPDF_Dictionary* pPageDict = pPage->m_pFormDict; | |
920 if (!pPageDict) { | |
921 return; | |
922 } | |
923 CPDF_Array* pAnnots = pPageDict->GetArrayBy("Annots"); | |
924 if (!pAnnots) { | |
925 return; | |
926 } | |
927 for (size_t i = 0; i < pAnnots->GetCount(); i++) { | |
928 CPDF_Dictionary* pAnnot = pAnnots->GetDictAt(i); | |
929 if (pAnnot && pAnnot->GetStringBy("Subtype") == "Widget") { | |
930 LoadField(pAnnot); | |
931 } | |
932 } | |
933 } | |
934 CPDF_FormField* CPDF_InterForm::AddTerminalField(CPDF_Dictionary* pFieldDict) { | |
935 if (!pFieldDict->KeyExist("T")) { | |
936 return nullptr; | |
937 } | |
938 CPDF_Dictionary* pDict = pFieldDict; | |
939 CFX_WideString csWName = GetFullName(pFieldDict); | |
940 if (csWName.IsEmpty()) { | |
941 return nullptr; | |
942 } | |
943 CPDF_FormField* pField = nullptr; | |
944 pField = m_pFieldTree->GetField(csWName); | |
945 if (!pField) { | |
946 CPDF_Dictionary* pParent = pFieldDict; | |
947 if (!pFieldDict->KeyExist("T") && | |
948 pFieldDict->GetStringBy("Subtype") == "Widget") { | |
949 pParent = pFieldDict->GetDictBy("Parent"); | |
950 if (!pParent) { | |
951 pParent = pFieldDict; | |
952 } | |
953 } | |
954 if (pParent && pParent != pFieldDict && !pParent->KeyExist("FT")) { | |
955 if (pFieldDict->KeyExist("FT")) { | |
956 CPDF_Object* pFTValue = pFieldDict->GetDirectObjectBy("FT"); | |
957 if (pFTValue) { | |
958 pParent->SetAt("FT", pFTValue->Clone()); | |
959 } | |
960 } | |
961 if (pFieldDict->KeyExist("Ff")) { | |
962 CPDF_Object* pFfValue = pFieldDict->GetDirectObjectBy("Ff"); | |
963 if (pFfValue) { | |
964 pParent->SetAt("Ff", pFfValue->Clone()); | |
965 } | |
966 } | |
967 } | |
968 pField = new CPDF_FormField(this, pParent); | |
969 CPDF_Object* pTObj = pDict->GetObjectBy("T"); | |
970 if (ToReference(pTObj)) { | |
971 CPDF_Object* pClone = pTObj->Clone(TRUE); | |
972 if (pClone) | |
973 pDict->SetAt("T", pClone); | |
974 else | |
975 pDict->SetAtName("T", ""); | |
976 } | |
977 m_pFieldTree->SetField(csWName, pField); | |
978 } | |
979 CPDF_Array* pKids = pFieldDict->GetArrayBy("Kids"); | |
980 if (!pKids) { | |
981 if (pFieldDict->GetStringBy("Subtype") == "Widget") { | |
982 AddControl(pField, pFieldDict); | |
983 } | |
984 } else { | |
985 for (size_t i = 0; i < pKids->GetCount(); i++) { | |
986 CPDF_Dictionary* pKid = pKids->GetDictAt(i); | |
987 if (!pKid) { | |
988 continue; | |
989 } | |
990 if (pKid->GetStringBy("Subtype") != "Widget") { | |
991 continue; | |
992 } | |
993 AddControl(pField, pKid); | |
994 } | |
995 } | |
996 return pField; | |
997 } | |
998 CPDF_FormControl* CPDF_InterForm::AddControl(CPDF_FormField* pField, | |
999 CPDF_Dictionary* pWidgetDict) { | |
1000 const auto it = m_ControlMap.find(pWidgetDict); | |
1001 if (it != m_ControlMap.end()) | |
1002 return it->second; | |
1003 | |
1004 CPDF_FormControl* pControl = new CPDF_FormControl(pField, pWidgetDict); | |
1005 m_ControlMap[pWidgetDict] = pControl; | |
1006 pField->m_ControlList.Add(pControl); | |
1007 return pControl; | |
1008 } | |
1009 | |
1010 CPDF_FormField* CPDF_InterForm::CheckRequiredFields( | |
1011 const std::vector<CPDF_FormField*>* fields, | |
1012 bool bIncludeOrExclude) const { | |
1013 int nCount = m_pFieldTree->m_Root.CountFields(); | |
1014 for (int i = 0; i < nCount; ++i) { | |
1015 CPDF_FormField* pField = m_pFieldTree->m_Root.GetField(i); | |
1016 if (!pField) | |
1017 continue; | |
1018 | |
1019 int32_t iType = pField->GetType(); | |
1020 if (iType == CPDF_FormField::PushButton || | |
1021 iType == CPDF_FormField::CheckBox || iType == CPDF_FormField::ListBox) { | |
1022 continue; | |
1023 } | |
1024 uint32_t dwFlags = pField->GetFieldFlags(); | |
1025 // TODO(thestig): Look up these magic numbers and add constants for them. | |
1026 if (dwFlags & 0x04) | |
1027 continue; | |
1028 | |
1029 bool bFind = true; | |
1030 if (fields) | |
1031 bFind = pdfium::ContainsValue(*fields, pField); | |
1032 if (bIncludeOrExclude == bFind) { | |
1033 CPDF_Dictionary* pFieldDict = pField->m_pDict; | |
1034 if ((dwFlags & 0x02) != 0 && pFieldDict->GetStringBy("V").IsEmpty()) { | |
1035 return pField; | |
1036 } | |
1037 } | |
1038 } | |
1039 return nullptr; | |
1040 } | |
1041 | |
1042 CFDF_Document* CPDF_InterForm::ExportToFDF(const CFX_WideStringC& pdf_path, | |
1043 bool bSimpleFileSpec) const { | |
1044 std::vector<CPDF_FormField*> fields; | |
1045 int nCount = m_pFieldTree->m_Root.CountFields(); | |
1046 for (int i = 0; i < nCount; ++i) | |
1047 fields.push_back(m_pFieldTree->m_Root.GetField(i)); | |
1048 return ExportToFDF(pdf_path, fields, true, bSimpleFileSpec); | |
1049 } | |
1050 | |
1051 CFDF_Document* CPDF_InterForm::ExportToFDF( | |
1052 const CFX_WideStringC& pdf_path, | |
1053 const std::vector<CPDF_FormField*>& fields, | |
1054 bool bIncludeOrExclude, | |
1055 bool bSimpleFileSpec) const { | |
1056 CFDF_Document* pDoc = CFDF_Document::CreateNewDoc(); | |
1057 if (!pDoc) { | |
1058 return nullptr; | |
1059 } | |
1060 CPDF_Dictionary* pMainDict = pDoc->GetRoot()->GetDictBy("FDF"); | |
1061 if (!pdf_path.IsEmpty()) { | |
1062 if (bSimpleFileSpec) { | |
1063 CFX_WideString wsFilePath = CPDF_FileSpec::EncodeFileName(pdf_path); | |
1064 pMainDict->SetAtString("F", CFX_ByteString::FromUnicode(wsFilePath)); | |
1065 pMainDict->SetAtString("UF", PDF_EncodeText(wsFilePath)); | |
1066 } else { | |
1067 CPDF_FileSpec filespec; | |
1068 filespec.SetFileName(pdf_path); | |
1069 pMainDict->SetAt("F", filespec.GetObj()); | |
1070 } | |
1071 } | |
1072 CPDF_Array* pFields = new CPDF_Array; | |
1073 pMainDict->SetAt("Fields", pFields); | |
1074 int nCount = m_pFieldTree->m_Root.CountFields(); | |
1075 for (int i = 0; i < nCount; i++) { | |
1076 CPDF_FormField* pField = m_pFieldTree->m_Root.GetField(i); | |
1077 if (!pField || pField->GetType() == CPDF_FormField::PushButton) { | |
1078 continue; | |
1079 } | |
1080 uint32_t dwFlags = pField->GetFieldFlags(); | |
1081 if (dwFlags & 0x04) | |
1082 continue; | |
1083 | |
1084 if (bIncludeOrExclude == pdfium::ContainsValue(fields, pField)) { | |
1085 if ((dwFlags & 0x02) != 0 && pField->m_pDict->GetStringBy("V").IsEmpty()) | |
1086 continue; | |
1087 | |
1088 CFX_WideString fullname = GetFullName(pField->GetFieldDict()); | |
1089 CPDF_Dictionary* pFieldDict = new CPDF_Dictionary; | |
1090 pFieldDict->SetAt("T", new CPDF_String(fullname)); | |
1091 if (pField->GetType() == CPDF_FormField::CheckBox || | |
1092 pField->GetType() == CPDF_FormField::RadioButton) { | |
1093 CFX_WideString csExport = pField->GetCheckValue(FALSE); | |
1094 CFX_ByteString csBExport = PDF_EncodeText(csExport); | |
1095 CPDF_Object* pOpt = FPDF_GetFieldAttr(pField->m_pDict, "Opt"); | |
1096 if (pOpt) | |
1097 pFieldDict->SetAtString("V", csBExport); | |
1098 else | |
1099 pFieldDict->SetAtName("V", csBExport); | |
1100 } else { | |
1101 CPDF_Object* pV = FPDF_GetFieldAttr(pField->m_pDict, "V"); | |
1102 if (pV) | |
1103 pFieldDict->SetAt("V", pV->Clone(TRUE)); | |
1104 } | |
1105 pFields->Add(pFieldDict); | |
1106 } | |
1107 } | |
1108 return pDoc; | |
1109 } | |
1110 | |
1111 void CPDF_InterForm::FDF_ImportField(CPDF_Dictionary* pFieldDict, | |
1112 const CFX_WideString& parent_name, | |
1113 FX_BOOL bNotify, | |
1114 int nLevel) { | |
1115 CFX_WideString name; | |
1116 if (!parent_name.IsEmpty()) { | |
1117 name = parent_name + L"."; | |
1118 } | |
1119 name += pFieldDict->GetUnicodeTextBy("T"); | |
1120 CPDF_Array* pKids = pFieldDict->GetArrayBy("Kids"); | |
1121 if (pKids) { | |
1122 for (size_t i = 0; i < pKids->GetCount(); i++) { | |
1123 CPDF_Dictionary* pKid = pKids->GetDictAt(i); | |
1124 if (!pKid) { | |
1125 continue; | |
1126 } | |
1127 if (nLevel <= nMaxRecursion) { | |
1128 FDF_ImportField(pKid, name, bNotify, nLevel + 1); | |
1129 } | |
1130 } | |
1131 return; | |
1132 } | |
1133 if (!pFieldDict->KeyExist("V")) { | |
1134 return; | |
1135 } | |
1136 CPDF_FormField* pField = m_pFieldTree->GetField(name); | |
1137 if (!pField) { | |
1138 return; | |
1139 } | |
1140 CFX_WideString csWValue = | |
1141 FPDFDOC_FDF_GetFieldValue(*pFieldDict, m_bsEncoding); | |
1142 int iType = pField->GetFieldType(); | |
1143 if (bNotify && m_pFormNotify) { | |
1144 int iRet = 0; | |
1145 if (iType == FIELDTYPE_LISTBOX) { | |
1146 iRet = m_pFormNotify->BeforeSelectionChange(pField, csWValue); | |
1147 } else if (iType == FIELDTYPE_COMBOBOX || iType == FIELDTYPE_TEXTFIELD) { | |
1148 iRet = m_pFormNotify->BeforeValueChange(pField, csWValue); | |
1149 } | |
1150 if (iRet < 0) { | |
1151 return; | |
1152 } | |
1153 } | |
1154 pField->SetValue(csWValue); | |
1155 CPDF_FormField::Type eType = pField->GetType(); | |
1156 if ((eType == CPDF_FormField::ListBox || eType == CPDF_FormField::ComboBox) && | |
1157 pFieldDict->KeyExist("Opt")) { | |
1158 pField->m_pDict->SetAt("Opt", | |
1159 pFieldDict->GetDirectObjectBy("Opt")->Clone(TRUE)); | |
1160 } | |
1161 if (bNotify && m_pFormNotify) { | |
1162 if (iType == FIELDTYPE_CHECKBOX || iType == FIELDTYPE_RADIOBUTTON) { | |
1163 m_pFormNotify->AfterCheckedStatusChange(pField); | |
1164 } else if (iType == FIELDTYPE_LISTBOX) { | |
1165 m_pFormNotify->AfterSelectionChange(pField); | |
1166 } else if (iType == FIELDTYPE_COMBOBOX || iType == FIELDTYPE_TEXTFIELD) { | |
1167 m_pFormNotify->AfterValueChange(pField); | |
1168 } | |
1169 } | |
1170 } | |
1171 | |
1172 FX_BOOL CPDF_InterForm::ImportFromFDF(const CFDF_Document* pFDF, | |
1173 FX_BOOL bNotify) { | |
1174 if (!pFDF) | |
1175 return FALSE; | |
1176 | |
1177 CPDF_Dictionary* pMainDict = pFDF->GetRoot()->GetDictBy("FDF"); | |
1178 if (!pMainDict) | |
1179 return FALSE; | |
1180 | |
1181 CPDF_Array* pFields = pMainDict->GetArrayBy("Fields"); | |
1182 if (!pFields) | |
1183 return FALSE; | |
1184 | |
1185 m_bsEncoding = pMainDict->GetStringBy("Encoding"); | |
1186 if (bNotify && m_pFormNotify && m_pFormNotify->BeforeFormImportData(this) < 0) | |
1187 return FALSE; | |
1188 | |
1189 for (size_t i = 0; i < pFields->GetCount(); i++) { | |
1190 CPDF_Dictionary* pField = pFields->GetDictAt(i); | |
1191 if (!pField) | |
1192 continue; | |
1193 | |
1194 FDF_ImportField(pField, L"", bNotify); | |
1195 } | |
1196 if (bNotify && m_pFormNotify) | |
1197 m_pFormNotify->AfterFormImportData(this); | |
1198 return TRUE; | |
1199 } | |
1200 | |
1201 void CPDF_InterForm::SetFormNotify(IPDF_FormNotify* pNotify) { | |
1202 m_pFormNotify = pNotify; | |
1203 } | |
OLD | NEW |