Merge to XFA: Kill FXSYS_mem{cpy,cmp,set.move}{32,8}.
[pdfium.git] / core / src / fpdfdoc / doc_form.cpp
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 "../../include/fpdfdoc/fpdf_doc.h"
8 #include "../../include/fxcrt/fx_xml.h"
9 #include "doc_utils.h"
10
11 const int nMaxRecursion = 32;
12
13 class _CFieldNameExtractor 
14 {
15 public:
16     _CFieldNameExtractor(const CFX_WideString& full_name)
17     {
18         m_pStart = full_name.c_str();
19         m_pEnd = m_pStart + full_name.GetLength();
20         m_pCur = m_pStart;
21     }
22     void GetNext(const FX_WCHAR* &pSubName, FX_STRSIZE& size)
23     {
24         pSubName = m_pCur;
25         while (m_pCur < m_pEnd && m_pCur[0] != L'.') {
26             m_pCur++;
27         }
28         size = (FX_STRSIZE)(m_pCur - pSubName);
29         if (m_pCur < m_pEnd && m_pCur[0] == L'.') {
30             m_pCur++;
31         }
32     }
33 protected:
34     const FX_WCHAR* m_pStart;
35     const FX_WCHAR* m_pEnd;
36     const FX_WCHAR* m_pCur;
37 };
38 class CFieldTree 
39 {
40 public:
41     struct _Node  {
42         _Node *parent;
43         CFX_PtrArray children;
44         CFX_WideString short_name;
45         CPDF_FormField *field_ptr;
46         int CountFields(int nLevel = 0)
47         {
48             if (nLevel > nMaxRecursion) {
49                 return 0;
50             }
51             if (field_ptr) {
52                 return 1;
53             }
54             int count = 0;
55             for (int i = 0; i < children.GetSize(); i ++) {
56                 count += ((_Node *)children.GetAt(i))->CountFields(nLevel + 1);
57             }
58             return count;
59         }
60         CPDF_FormField* GetField(int* fields_to_go)
61         {
62             if (field_ptr) {
63                 if (*fields_to_go == 0) {
64                     return field_ptr;
65                 }
66                 --*fields_to_go;
67                 return NULL;
68             }
69             for (int i = 0; i < children.GetSize(); i++) {
70                 _Node *pNode = (_Node *)children.GetAt(i);
71                 CPDF_FormField* pField = pNode->GetField(fields_to_go);
72                 if (pField) {
73                     return pField;
74                 }
75             }
76             return NULL;
77         }
78         CPDF_FormField* GetField(int index)
79         {
80             int fields_to_go = index;
81             return GetField(&fields_to_go);
82         }
83     };
84     CFieldTree();
85     ~CFieldTree();
86     void SetField(const CFX_WideString &full_name, CPDF_FormField *field_ptr);
87     CPDF_FormField *GetField(const CFX_WideString &full_name);
88     CPDF_FormField *RemoveField(const CFX_WideString &full_name);
89     void RemoveAll();
90     _Node *FindNode(const CFX_WideString &full_name);
91     _Node * AddChild(_Node *pParent, const CFX_WideString &short_name, CPDF_FormField *field_ptr);
92     void RemoveNode(_Node *pNode, int nLevel = 0);
93     _Node *_Lookup(_Node *pParent, const CFX_WideString &short_name);
94     _Node m_Root;
95 };
96 CFieldTree::CFieldTree()
97 {
98     m_Root.parent = NULL;
99     m_Root.field_ptr = NULL;
100 }
101 CFieldTree::~CFieldTree()
102 {
103     RemoveAll();
104 }
105 CFieldTree::_Node *CFieldTree::AddChild(_Node *pParent, const CFX_WideString &short_name, CPDF_FormField *field_ptr)
106 {
107     if (pParent == NULL) {
108         return NULL;
109     }
110     _Node *pNode = FX_NEW _Node;
111     if (pNode == NULL) {
112         return NULL;
113     }
114     pNode->parent = pParent;
115     pNode->short_name = short_name;
116     pNode->field_ptr = field_ptr;
117     pParent->children.Add(pNode);
118     return pNode;
119 }
120 void CFieldTree::RemoveNode(_Node *pNode, int nLevel)
121 {
122     if (pNode == NULL) {
123         return ;
124     }
125     if (nLevel > nMaxRecursion) {
126         delete pNode;
127         return ;
128     }
129     CFX_PtrArray& ptr_array = pNode->children;
130     for (int i = 0; i < ptr_array.GetSize(); i ++) {
131         _Node *pChild = (_Node *)ptr_array[i];
132         RemoveNode(pChild, nLevel + 1);
133     }
134     delete pNode;
135 }
136 CFieldTree::_Node *CFieldTree::_Lookup(_Node *pParent, const CFX_WideString &short_name)
137 {
138     if (pParent == NULL) {
139         return NULL;
140     }
141     CFX_PtrArray& ptr_array = pParent->children;
142     for (int i = 0; i < ptr_array.GetSize(); i ++) {
143         _Node *pNode = (_Node *)ptr_array[i];
144         if (pNode->short_name.GetLength() == short_name.GetLength() &&
145                 FXSYS_memcmp(pNode->short_name.c_str(), short_name.c_str(), short_name.GetLength()*sizeof(FX_WCHAR)) == 0) {
146             return pNode;
147         }
148     }
149     return NULL;
150 }
151 void CFieldTree::RemoveAll()
152 {
153     CFX_PtrArray& ptr_array = m_Root.children;
154     for (int i = 0; i < ptr_array.GetSize(); i ++) {
155         _Node *pNode = (_Node *)ptr_array[i];
156         RemoveNode(pNode);
157     }
158 }
159 void CFieldTree::SetField(const CFX_WideString &full_name, CPDF_FormField *field_ptr)
160 {
161     if (full_name == L"") {
162         return;
163     }
164     _CFieldNameExtractor name_extractor(full_name);
165     const FX_WCHAR* pName;
166     FX_STRSIZE nLength;
167     name_extractor.GetNext(pName, nLength);
168     _Node *pNode = &m_Root, *pLast = NULL;
169     while (nLength > 0) {
170         pLast = pNode;
171         CFX_WideString name = CFX_WideString(pName, nLength);
172         pNode = _Lookup(pLast, name);
173         if (pNode == NULL) {
174             pNode = AddChild(pLast, name, NULL);
175         }
176         name_extractor.GetNext(pName, nLength);
177     }
178     if (pNode != &m_Root) {
179         pNode->field_ptr = field_ptr;
180     }
181 }
182 CPDF_FormField *CFieldTree::GetField(const CFX_WideString &full_name)
183 {
184     if (full_name == L"") {
185         return NULL;
186     }
187     _CFieldNameExtractor name_extractor(full_name);
188     const FX_WCHAR* pName;
189     FX_STRSIZE nLength;
190     name_extractor.GetNext(pName, nLength);
191     _Node *pNode = &m_Root, *pLast = NULL;
192     while (nLength > 0 && pNode) {
193         pLast = pNode;
194         CFX_WideString name = CFX_WideString(pName, nLength);
195         pNode = _Lookup(pLast, name);
196         name_extractor.GetNext(pName, nLength);
197     }
198     return pNode ? pNode->field_ptr : NULL;
199 }
200 CPDF_FormField *CFieldTree::RemoveField(const CFX_WideString & full_name)
201 {
202     if (full_name == L"") {
203         return NULL;
204     }
205     _CFieldNameExtractor name_extractor(full_name);
206     const FX_WCHAR* pName;
207     FX_STRSIZE nLength;
208     name_extractor.GetNext(pName, nLength);
209     _Node *pNode = &m_Root, *pLast = NULL;
210     while (nLength > 0 && pNode) {
211         pLast = pNode;
212         CFX_WideString name = CFX_WideString(pName, nLength);
213         pNode = _Lookup(pLast, name);
214         name_extractor.GetNext(pName, nLength);
215     }
216     if (pNode && pNode != &m_Root) {
217         CFX_PtrArray& ptr_array = pLast->children;
218         for (int i = 0; i < ptr_array.GetSize(); i ++) {
219             if (pNode == (_Node *)ptr_array[i]) {
220                 ptr_array.RemoveAt(i);
221                 break;
222             }
223         }
224         CPDF_FormField *pField = pNode->field_ptr;
225         RemoveNode(pNode);
226         return pField;
227     }
228     return NULL;
229 }
230 CFieldTree::_Node *CFieldTree::FindNode(const CFX_WideString& full_name)
231 {
232     if (full_name == L"") {
233         return NULL;
234     }
235     _CFieldNameExtractor name_extractor(full_name);
236     const FX_WCHAR* pName;
237     FX_STRSIZE nLength;
238     name_extractor.GetNext(pName, nLength);
239     _Node *pNode = &m_Root, *pLast = NULL;
240     while (nLength > 0 && pNode) {
241         pLast = pNode;
242         CFX_WideString name = CFX_WideString(pName, nLength);
243         pNode = _Lookup(pLast, name);
244         name_extractor.GetNext(pName, nLength);
245     }
246     return pNode;
247 }
248 CPDF_InterForm::CPDF_InterForm(CPDF_Document* pDocument, FX_BOOL bGenerateAP) : CFX_PrivateData()
249 {
250     m_pDocument = pDocument;
251     m_bGenerateAP = bGenerateAP;
252     m_pFormNotify = NULL;
253     m_bUpdated = FALSE;
254     m_pFieldTree = FX_NEW CFieldTree;
255     CPDF_Dictionary* pRoot = m_pDocument->GetRoot();
256     m_pFormDict = pRoot->GetDict("AcroForm");
257     if (m_pFormDict == NULL) {
258         return;
259     }
260     CPDF_Array* pFields = m_pFormDict->GetArray("Fields");
261     if (pFields == NULL) {
262         return;
263     }
264     int count = pFields->GetCount();
265     for (int i = 0; i < count; i ++) {
266         LoadField(pFields->GetDict(i));
267     }
268 }
269 CPDF_InterForm::~CPDF_InterForm()
270 {
271     FX_POSITION pos = m_ControlMap.GetStartPosition();
272     while (pos) {
273         void* key;
274         void* value;
275         m_ControlMap.GetNextAssoc(pos, key, value);
276         delete (CPDF_FormControl*)value;
277     }
278     if (m_pFieldTree != NULL) {
279         int nCount = m_pFieldTree->m_Root.CountFields();
280         for (int i = 0; i < nCount; i++) {
281             CPDF_FormField *pField = m_pFieldTree->m_Root.GetField(i);
282             delete pField;
283         }
284         delete m_pFieldTree;
285     }
286 }
287 FX_BOOL CPDF_InterForm::m_bUpdateAP = TRUE;
288 FX_BOOL CPDF_InterForm::UpdatingAPEnabled()
289 {
290     return m_bUpdateAP;
291 }
292 void CPDF_InterForm::EnableUpdateAP(FX_BOOL bUpdateAP)
293 {
294     m_bUpdateAP = bUpdateAP;
295 }
296 CFX_ByteString CPDF_InterForm::GenerateNewResourceName(const CPDF_Dictionary* pResDict, const FX_CHAR* csType, int iMinLen, const FX_CHAR* csPrefix)
297 {
298     CFX_ByteString csStr = csPrefix;
299     CFX_ByteString csBType = csType;
300     if (csStr.IsEmpty()) {
301         if (csBType == "ExtGState") {
302             csStr = "GS";
303         } else if (csBType == "ColorSpace") {
304             csStr = "CS";
305         } else if (csBType == "Font") {
306             csStr = "ZiTi";
307         } else {
308             csStr = "Res";
309         }
310     }
311     CFX_ByteString csTmp = csStr;
312     int iCount = csStr.GetLength();
313     int m = 0;
314     if (iMinLen > 0) {
315         csTmp = "";
316         while (m < iMinLen && m < iCount) {
317             csTmp += csStr[m ++];
318         }
319         while (m < iMinLen) {
320             csTmp += '0' + m % 10;
321             m ++;
322         }
323     } else {
324         m = iCount;
325     }
326     if (pResDict == NULL) {
327         return csTmp;
328     }
329     CPDF_Dictionary* pDict = pResDict->GetDict(csType);
330     if (pDict == NULL) {
331         return csTmp;
332     }
333     int num = 0;
334     CFX_ByteString bsNum;
335     while (TRUE) {
336         if (!pDict->KeyExist(csTmp + bsNum)) {
337             return csTmp + bsNum;
338         }
339         if (m < iCount) {
340             csTmp += csStr[m ++];
341         } else {
342             bsNum.Format("%d", num++);
343         }
344         m ++;
345     }
346     return csTmp;
347 }
348 #if _FXM_PLATFORM_ == _FXM_PLATFORM_WINDOWS_
349 typedef struct _PDF_FONTDATA {
350     FX_BOOL             bFind;
351     LOGFONTA    lf;
352 } PDF_FONTDATA, FAR* LPDF_FONTDATA;
353 static int CALLBACK EnumFontFamExProc(  ENUMLOGFONTEXA *lpelfe,
354                                         NEWTEXTMETRICEX *lpntme,
355                                         DWORD FontType,
356                                         LPARAM lParam
357                                      )
358 {
359     if (FontType != 0x004 || strchr(lpelfe->elfLogFont.lfFaceName, '@') != NULL) {
360         return 1;
361     } else {
362         LPDF_FONTDATA pData = (LPDF_FONTDATA)lParam;
363         memcpy(&pData->lf, &lpelfe->elfLogFont, sizeof(LOGFONTA));
364         pData->bFind = TRUE;
365         return 0;
366     }
367 }
368 static FX_BOOL RetrieveSpecificFont(LOGFONTA& lf)
369 {
370     PDF_FONTDATA fd;
371     memset(&fd, 0, sizeof(PDF_FONTDATA));
372     HDC hDC = ::GetDC(NULL);
373     EnumFontFamiliesExA(hDC, &lf, (FONTENUMPROCA)EnumFontFamExProc, (LPARAM)&fd, 0);
374     ::ReleaseDC(NULL, hDC);
375     if (fd.bFind) {
376         memcpy(&lf, &fd.lf, sizeof(LOGFONTA));
377     }
378     return fd.bFind;
379 }
380 static FX_BOOL RetrieveSpecificFont(uint8_t charSet, uint8_t pitchAndFamily, LPCSTR pcsFontName, LOGFONTA& lf)
381 {
382     memset(&lf, 0, sizeof(LOGFONTA));
383     lf.lfCharSet = charSet;
384     lf.lfPitchAndFamily = pitchAndFamily;
385     if (pcsFontName != NULL) {
386         strcpy(lf.lfFaceName, pcsFontName);
387     }
388     return RetrieveSpecificFont(lf);
389 }
390 static FX_BOOL RetrieveStockFont(int iFontObject, uint8_t charSet, LOGFONTA& lf)
391 {
392     HFONT hFont = (HFONT)::GetStockObject(iFontObject);
393     if (hFont != NULL) {
394         memset(&lf, 0, sizeof(LOGFONTA));
395         int iRet = ::GetObject(hFont, sizeof(LOGFONTA), &lf);
396         if (iRet > 0 && (lf.lfCharSet == charSet || charSet == 255)) {
397             return RetrieveSpecificFont(lf);
398         }
399     }
400     return FALSE;
401 }
402 #endif
403 CPDF_Font* CPDF_InterForm::AddSystemDefaultFont(const CPDF_Document* pDocument)
404 {
405     if (pDocument == NULL) {
406         return NULL;
407     }
408     CPDF_Font* pFont = NULL;
409 #if _FXM_PLATFORM_ == _FXM_PLATFORM_WINDOWS_
410     LOGFONTA lf;
411     FX_BOOL bRet;
412     bRet = RetrieveStockFont(DEFAULT_GUI_FONT, 255, lf);
413     if (!bRet) {
414         bRet = RetrieveStockFont(SYSTEM_FONT, 255, lf);
415     }
416     if (bRet) {
417         pFont = ((CPDF_Document*)pDocument)->AddWindowsFont(&lf, FALSE, TRUE);
418     }
419 #endif
420     return pFont;
421 }
422 CPDF_Font* CPDF_InterForm::AddSystemFont(const CPDF_Document* pDocument, CFX_ByteString csFontName, uint8_t iCharSet)
423 {
424     if (pDocument == NULL || csFontName.IsEmpty()) {
425         return NULL;
426     }
427 #if _FXM_PLATFORM_ == _FXM_PLATFORM_WINDOWS_
428     if (iCharSet == 1) {
429         iCharSet = GetNativeCharSet();
430     }
431     HFONT hFont = ::CreateFontA(0, 0, 0, 0, 0, 0, 0, 0, iCharSet, OUT_DEFAULT_PRECIS, CLIP_DEFAULT_PRECIS, DEFAULT_QUALITY, DEFAULT_PITCH | FF_DONTCARE, csFontName.c_str());
432     if (hFont != NULL) {
433         LOGFONTA lf;
434         memset(&lf, 0, sizeof(LOGFONTA));
435         ::GetObjectA(hFont, sizeof(LOGFONTA), &lf);
436         ::DeleteObject(hFont);
437         if (strlen(lf.lfFaceName) > 0) {
438             return ((CPDF_Document*)pDocument)->AddWindowsFont(&lf, FALSE, TRUE);
439         }
440     }
441 #endif
442     return NULL;
443 }
444 CPDF_Font* CPDF_InterForm::AddSystemFont(const CPDF_Document* pDocument, CFX_WideString csFontName, uint8_t iCharSet)
445 {
446     if (pDocument == NULL || csFontName.IsEmpty()) {
447         return NULL;
448     }
449 #if _FXM_PLATFORM_ == _FXM_PLATFORM_WINDOWS_
450     if (iCharSet == 1) {
451         iCharSet = GetNativeCharSet();
452     }
453     HFONT hFont = ::CreateFontW(0, 0, 0, 0, 0, 0, 0, 0, iCharSet, OUT_DEFAULT_PRECIS, CLIP_DEFAULT_PRECIS, DEFAULT_QUALITY, DEFAULT_PITCH | FF_DONTCARE, csFontName.c_str());
454     if (hFont != NULL) {
455         LOGFONTA lf;
456         memset(&lf, 0, sizeof(LOGFONTA));
457         ::GetObject(hFont, sizeof(LOGFONTA), &lf);
458         ::DeleteObject(hFont);
459         if (strlen(lf.lfFaceName) > 0) {
460             return ((CPDF_Document*)pDocument)->AddWindowsFont(&lf, FALSE, TRUE);
461         }
462     }
463 #endif
464     return NULL;
465 }
466 CPDF_Font* CPDF_InterForm::AddStandardFont(const CPDF_Document* pDocument, CFX_ByteString csFontName)
467 {
468     if (pDocument == NULL || csFontName.IsEmpty()) {
469         return NULL;
470     }
471     CPDF_Font* pFont = NULL;
472     if (csFontName == "ZapfDingbats") {
473         pFont = ((CPDF_Document*)pDocument)->AddStandardFont(csFontName, NULL);
474     } else {
475         CPDF_FontEncoding encoding(PDFFONT_ENCODING_WINANSI);
476         pFont = ((CPDF_Document*)pDocument)->AddStandardFont(csFontName, &encoding);
477     }
478     return pFont;
479 }
480 CFX_ByteString CPDF_InterForm::GetNativeFont(uint8_t charSet, void* pLogFont)
481 {
482     CFX_ByteString csFontName;
483 #if _FXM_PLATFORM_ == _FXM_PLATFORM_WINDOWS_
484     LOGFONTA lf;
485     FX_BOOL bRet;
486     if (charSet == ANSI_CHARSET) {
487         csFontName = "Helvetica";
488         return csFontName;
489     }
490     bRet = FALSE;
491     if (charSet == SHIFTJIS_CHARSET) {
492         bRet = RetrieveSpecificFont(charSet, DEFAULT_PITCH | FF_DONTCARE, "MS Mincho", lf);
493     } else if (charSet == GB2312_CHARSET) {
494         bRet = RetrieveSpecificFont(charSet, DEFAULT_PITCH | FF_DONTCARE, "SimSun", lf);
495     } else if (charSet == CHINESEBIG5_CHARSET) {
496         bRet = RetrieveSpecificFont(charSet, DEFAULT_PITCH | FF_DONTCARE, "MingLiU", lf);
497     }
498     if (!bRet) {
499         bRet = RetrieveSpecificFont(charSet, DEFAULT_PITCH | FF_DONTCARE, "Arial Unicode MS", lf);
500     }
501     if (!bRet) {
502         bRet = RetrieveSpecificFont(charSet, DEFAULT_PITCH | FF_DONTCARE, "Microsoft Sans Serif", lf);
503     }
504     if (!bRet) {
505         bRet = RetrieveSpecificFont(charSet, DEFAULT_PITCH | FF_DONTCARE, NULL, lf);
506     }
507     if (bRet) {
508         if (pLogFont != NULL) {
509             memcpy(pLogFont, &lf, sizeof(LOGFONTA));
510         }
511         csFontName = lf.lfFaceName;
512         return csFontName;
513     }
514 #endif
515     return csFontName;
516 }
517 CFX_ByteString CPDF_InterForm::GetNativeFont(void* pLogFont)
518 {
519 #if _FXM_PLATFORM_ == _FXM_PLATFORM_WINDOWS_
520     uint8_t charSet = GetNativeCharSet();
521     return GetNativeFont(charSet, pLogFont);
522 #else
523     return CFX_ByteString();
524 #endif
525 }
526 uint8_t CPDF_InterForm::GetNativeCharSet()
527 {
528 #if _FXM_PLATFORM_ == _FXM_PLATFORM_WINDOWS_
529     uint8_t charSet = ANSI_CHARSET;
530     UINT iCodePage = ::GetACP();
531     switch (iCodePage) {
532         case 932:
533             charSet = SHIFTJIS_CHARSET;
534             break;
535         case 936:
536             charSet = GB2312_CHARSET;
537             break;
538         case 950:
539             charSet = CHINESEBIG5_CHARSET;
540             break;
541         case 1252:
542             charSet = ANSI_CHARSET;
543             break;
544         case 874:
545             charSet = THAI_CHARSET;
546             break;
547         case 949:
548             charSet = HANGUL_CHARSET;
549             break;
550         case 1200:
551             charSet = ANSI_CHARSET;
552             break;
553         case 1250:
554             charSet = EASTEUROPE_CHARSET;
555             break;
556         case 1251:
557             charSet = RUSSIAN_CHARSET;
558             break;
559         case 1253:
560             charSet = GREEK_CHARSET;
561             break;
562         case 1254:
563             charSet = TURKISH_CHARSET;
564             break;
565         case 1255:
566             charSet = HEBREW_CHARSET;
567             break;
568         case 1256:
569             charSet = ARABIC_CHARSET;
570             break;
571         case 1257:
572             charSet = BALTIC_CHARSET;
573             break;
574         case 1258:
575             charSet = VIETNAMESE_CHARSET;
576             break;
577         case 1361:
578             charSet = JOHAB_CHARSET;
579             break;
580     }
581     return charSet;
582 #else
583     return 0;
584 #endif
585 }
586 CPDF_Font* CPDF_InterForm::AddNativeFont(uint8_t charSet, const CPDF_Document* pDocument)
587 {
588     if (pDocument == NULL) {
589         return NULL;
590     }
591     CPDF_Font* pFont = NULL;
592 #if _FXM_PLATFORM_ == _FXM_PLATFORM_WINDOWS_
593     LOGFONTA lf;
594     CFX_ByteString csFontName = GetNativeFont(charSet, &lf);
595     if (!csFontName.IsEmpty()) {
596         if (csFontName == "Helvetica") {
597             pFont = AddStandardFont(pDocument, csFontName);
598         } else {
599             pFont = ((CPDF_Document*)pDocument)->AddWindowsFont(&lf, FALSE, TRUE);
600         }
601     }
602 #endif
603     return pFont;
604 }
605 CPDF_Font* CPDF_InterForm::AddNativeFont(const CPDF_Document* pDocument)
606 {
607     if (pDocument == NULL) {
608         return NULL;
609     }
610     CPDF_Font* pFont = NULL;
611     uint8_t charSet = GetNativeCharSet();
612     pFont = AddNativeFont(charSet, pDocument);
613     return pFont;
614 }
615 FX_BOOL CPDF_InterForm::ValidateFieldName(CFX_WideString& csNewFieldName, int iType, const CPDF_FormField* pExcludedField, const CPDF_FormControl* pExcludedControl)
616 {
617     if (csNewFieldName.IsEmpty()) {
618         return FALSE;
619     }
620     int iPos = 0;
621     int iLength = csNewFieldName.GetLength();
622     CFX_WideString csSub;
623     while (TRUE) {
624         while (iPos < iLength && (csNewFieldName[iPos] == L'.' || csNewFieldName[iPos] == L' ')) {
625             iPos ++;
626         }
627         if (iPos < iLength && !csSub.IsEmpty()) {
628             csSub += L'.';
629         }
630         while (iPos < iLength && csNewFieldName[iPos] != L'.') {
631             csSub += csNewFieldName[iPos ++];
632         }
633         for (int i = csSub.GetLength() - 1; i > -1; i --) {
634             if (csSub[i] == L' ' || csSub[i] == L'.') {
635                 csSub.SetAt(i, L'\0');
636             } else {
637                 break;
638             }
639         }
640         FX_DWORD dwCount = m_pFieldTree->m_Root.CountFields();
641         for (FX_DWORD m = 0; m < dwCount; m ++) {
642             CPDF_FormField* pField = m_pFieldTree->m_Root.GetField(m);
643             if (pField == NULL) {
644                 continue;
645             }
646             if (pField == pExcludedField) {
647                 if (pExcludedControl != NULL) {
648                     if (pField->CountControls() < 2) {
649                         continue;
650                     }
651                 } else {
652                     continue;
653                 }
654             }
655             CFX_WideString csFullName = pField->GetFullName();
656             int iRet = CompareFieldName(csSub, csFullName);
657             if (iRet == 1) {
658                 if (pField->GetFieldType() != iType) {
659                     return FALSE;
660                 }
661             } else if (iRet == 2 && csSub == csNewFieldName) {
662                 if (csFullName[iPos] == L'.') {
663                     return FALSE;
664                 }
665             } else if (iRet == 3 && csSub == csNewFieldName) {
666                 if (csNewFieldName[csFullName.GetLength()] == L'.') {
667                     return FALSE;
668                 }
669             }
670         }
671         if (iPos >= iLength) {
672             break;
673         }
674     }
675     if (csSub.IsEmpty()) {
676         return FALSE;
677     }
678     csNewFieldName = csSub;
679     return TRUE;
680 }
681 FX_BOOL CPDF_InterForm::ValidateFieldName(CFX_WideString& csNewFieldName, int iType)
682 {
683     return ValidateFieldName(csNewFieldName, iType, NULL, NULL);
684 }
685 FX_BOOL CPDF_InterForm::ValidateFieldName(const CPDF_FormField* pField, CFX_WideString& csNewFieldName)
686 {
687     if (pField == NULL || csNewFieldName.IsEmpty()) {
688         return FALSE;
689     }
690     return ValidateFieldName(csNewFieldName, ((CPDF_FormField*)pField)->GetFieldType(), pField, NULL);
691 }
692 FX_BOOL CPDF_InterForm::ValidateFieldName(const CPDF_FormControl* pControl, CFX_WideString& csNewFieldName)
693 {
694     if (pControl == NULL || csNewFieldName.IsEmpty()) {
695         return FALSE;
696     }
697     CPDF_FormField* pField = ((CPDF_FormControl*)pControl)->GetField();
698     return ValidateFieldName(csNewFieldName, pField->GetFieldType(), pField, pControl);
699 }
700 int CPDF_InterForm::CompareFieldName(const CFX_ByteString& name1, const CFX_ByteString& name2)
701 {
702     const FX_CHAR* ptr1 = name1;
703     const FX_CHAR* ptr2 = name2;
704     if (name1.GetLength() != name2.GetLength()) {
705         int i = 0;
706         while (ptr1[i] == ptr2[i]) {
707             i ++;
708         }
709         if (i == name1.GetLength()) {
710             return 2;
711         }
712         if (i == name2.GetLength()) {
713             return 3;
714         }
715         return 0;
716     } else {
717         return name1 == name2 ? 1 : 0;
718     }
719 }
720 int CPDF_InterForm::CompareFieldName(const CFX_WideString& name1, const CFX_WideString& name2)
721 {
722     const FX_WCHAR* ptr1 = name1.c_str();
723     const FX_WCHAR* ptr2 = name2.c_str();
724     if (name1.GetLength() != name2.GetLength()) {
725         int i = 0;
726         while (ptr1[i] == ptr2[i]) {
727             i ++;
728         }
729         if (i == name1.GetLength()) {
730             return 2;
731         }
732         if (i == name2.GetLength()) {
733             return 3;
734         }
735         return 0;
736     } else {
737         return name1 == name2 ? 1 : 0;
738     }
739 }
740 FX_DWORD CPDF_InterForm::CountFields(const CFX_WideString &csFieldName)
741 {
742     if (csFieldName.IsEmpty()) {
743         return (FX_DWORD)m_pFieldTree->m_Root.CountFields();
744     }
745     CFieldTree::_Node *pNode = m_pFieldTree->FindNode(csFieldName);
746     if (pNode == NULL) {
747         return 0;
748     }
749     return pNode->CountFields();
750 }
751 CPDF_FormField* CPDF_InterForm::GetField(FX_DWORD index, const CFX_WideString &csFieldName)
752 {
753     if (csFieldName == L"") {
754         return m_pFieldTree->m_Root.GetField(index);
755     }
756     CFieldTree::_Node *pNode = m_pFieldTree->FindNode(csFieldName);
757     if (pNode == NULL) {
758         return NULL;
759     }
760     return pNode->GetField(index);
761 }
762 void CPDF_InterForm::GetAllFieldNames(CFX_WideStringArray& allFieldNames)
763 {
764     allFieldNames.RemoveAll();
765     int nCount = m_pFieldTree->m_Root.CountFields();
766     for (int i = 0; i < nCount; i ++) {
767         CPDF_FormField *pField = m_pFieldTree->m_Root.GetField(i);
768         if (pField) {
769             CFX_WideString full_name = GetFullName(pField->GetFieldDict());
770             allFieldNames.Add(full_name);
771         }
772     }
773 }
774 FX_BOOL CPDF_InterForm::IsValidFormField(const void* pField)
775 {
776     if (pField == NULL) {
777         return FALSE;
778     }
779     int nCount = m_pFieldTree->m_Root.CountFields();
780     for (int i = 0; i < nCount; i++) {
781         CPDF_FormField *pFormField = m_pFieldTree->m_Root.GetField(i);
782         if (pField == pFormField) {
783             return TRUE;
784         }
785     }
786     return FALSE;
787 }
788 CPDF_FormField* CPDF_InterForm::GetFieldByDict(CPDF_Dictionary* pFieldDict) const
789 {
790     if (pFieldDict == NULL) {
791         return NULL;
792     }
793     CFX_WideString csWName = GetFullName(pFieldDict);
794     return m_pFieldTree->GetField(csWName);
795 }
796 FX_DWORD CPDF_InterForm::CountControls(CFX_WideString csFieldName)
797 {
798     if (csFieldName.IsEmpty()) {
799         return (FX_DWORD)m_ControlMap.GetCount();
800     }
801     CPDF_FormField *pField = m_pFieldTree->GetField(csFieldName);
802     if (pField == NULL) {
803         return 0;
804     }
805     return pField->m_ControlList.GetSize();
806 }
807 CPDF_FormControl* CPDF_InterForm::GetControl(FX_DWORD index, CFX_WideString csFieldName)
808 {
809     CPDF_FormField *pField = m_pFieldTree->GetField(csFieldName);
810     if (pField == NULL) {
811         return NULL;
812     }
813     if (index < (FX_DWORD)pField->m_ControlList.GetSize()) {
814         return (CPDF_FormControl *)pField->m_ControlList.GetAt(index);
815     }
816     return NULL;
817 }
818 FX_BOOL CPDF_InterForm::IsValidFormControl(const void* pControl)
819 {
820     if (pControl == NULL) {
821         return FALSE;
822     }
823     FX_POSITION pos = m_ControlMap.GetStartPosition();
824     while (pos) {
825         CPDF_Dictionary* pWidgetDict = NULL;
826         void* pFormControl = NULL;
827         m_ControlMap.GetNextAssoc(pos, (void*&)pWidgetDict, pFormControl);
828         if (pControl == pFormControl) {
829             return TRUE;
830         }
831     }
832     return FALSE;
833 }
834 int CPDF_InterForm::CountPageControls(CPDF_Page* pPage) const
835 {
836     CPDF_Array* pAnnotList = pPage->m_pFormDict->GetArray("Annots");
837     if (pAnnotList == NULL) {
838         return 0;
839     }
840     int count = 0;
841     for (FX_DWORD i = 0; i < pAnnotList->GetCount(); i ++) {
842         CPDF_Dictionary* pAnnot = pAnnotList->GetDict(i);
843         if (pAnnot == NULL) {
844             continue;
845         }
846         CPDF_FormControl* pControl;
847         if (!m_ControlMap.Lookup(pAnnot, (void*&)pControl)) {
848             continue;
849         }
850         count ++;
851     }
852     return count;
853 }
854 CPDF_FormControl* CPDF_InterForm::GetPageControl(CPDF_Page* pPage, int index) const
855 {
856     CPDF_Array* pAnnotList = pPage->m_pFormDict->GetArray("Annots");
857     if (pAnnotList == NULL) {
858         return NULL;
859     }
860     int count = 0;
861     for (FX_DWORD i = 0; i < pAnnotList->GetCount(); i ++) {
862         CPDF_Dictionary* pAnnot = pAnnotList->GetDict(i);
863         if (pAnnot == NULL) {
864             continue;
865         }
866         CPDF_FormControl* pControl;
867         if (!m_ControlMap.Lookup(pAnnot, (void*&)pControl)) {
868             continue;
869         }
870         if (index == count) {
871             return pControl;
872         }
873         count ++;
874     }
875     return NULL;
876 }
877 CPDF_FormControl* CPDF_InterForm::GetControlAtPoint(CPDF_Page* pPage, FX_FLOAT pdf_x, FX_FLOAT pdf_y) const
878 {
879     CPDF_Array* pAnnotList = pPage->m_pFormDict->GetArray("Annots");
880     if (pAnnotList == NULL) {
881         return NULL;
882     }
883     for (FX_DWORD i = pAnnotList->GetCount(); i > 0; i --) {
884         CPDF_Dictionary* pAnnot = pAnnotList->GetDict(i - 1);
885         if (pAnnot == NULL) {
886             continue;
887         }
888         CPDF_FormControl* pControl;
889         if (!m_ControlMap.Lookup(pAnnot, (void*&)pControl)) {
890             continue;
891         }
892         CFX_FloatRect rect = pControl->GetRect();
893         if (rect.Contains(pdf_x, pdf_y)) {
894             return pControl;
895         }
896     }
897     return NULL;
898 }
899 CPDF_FormControl* CPDF_InterForm::GetControlByDict(CPDF_Dictionary* pWidgetDict) const
900 {
901     CPDF_FormControl* pControl = NULL;
902     m_ControlMap.Lookup(pWidgetDict, (void*&)pControl);
903     return pControl;
904 }
905 FX_DWORD CPDF_InterForm::CountInternalFields(const CFX_WideString& csFieldName) const
906 {
907     if (m_pFormDict == NULL) {
908         return 0;
909     }
910     CPDF_Array* pArray = m_pFormDict->GetArray("Fields");
911     if (pArray == NULL) {
912         return 0;
913     }
914     if (csFieldName.IsEmpty()) {
915         return pArray->GetCount();
916     } else {
917         int iLength = csFieldName.GetLength();
918         int iPos = 0;
919         CPDF_Dictionary* pDict = NULL;
920         while (pArray != NULL) {
921             CFX_WideString csSub;
922             if (iPos < iLength && csFieldName[iPos] == L'.') {
923                 iPos ++;
924             }
925             while (iPos < iLength && csFieldName[iPos] != L'.') {
926                 csSub += csFieldName[iPos ++];
927             }
928             int iCount = pArray->GetCount();
929             FX_BOOL bFind = FALSE;
930             for (int i = 0; i < iCount; i ++) {
931                 pDict = pArray->GetDict(i);
932                 if (pDict == NULL) {
933                     continue;
934                 }
935                 CFX_WideString csT = pDict->GetUnicodeText("T");
936                 if (csT == csSub) {
937                     bFind = TRUE;
938                     break;
939                 }
940             }
941             if (!bFind) {
942                 return 0;
943             }
944             if (iPos >= iLength) {
945                 break;
946             }
947             pArray = pDict->GetArray("Kids");
948         }
949         if (pDict == NULL) {
950             return 0;
951         } else {
952             pArray = pDict->GetArray("Kids");
953             if (pArray == NULL) {
954                 return 1;
955             } else {
956                 return pArray->GetCount();
957             }
958         }
959     }
960 }
961 CPDF_Dictionary* CPDF_InterForm::GetInternalField(FX_DWORD index, const CFX_WideString& csFieldName) const
962 {
963     if (m_pFormDict == NULL) {
964         return NULL;
965     }
966     CPDF_Array* pArray = m_pFormDict->GetArray("Fields");
967     if (pArray == NULL) {
968         return 0;
969     }
970     if (csFieldName.IsEmpty()) {
971         return pArray->GetDict(index);
972     } else {
973         int iLength = csFieldName.GetLength();
974         int iPos = 0;
975         CPDF_Dictionary* pDict = NULL;
976         while (pArray != NULL) {
977             CFX_WideString csSub;
978             if (iPos < iLength && csFieldName[iPos] == L'.') {
979                 iPos ++;
980             }
981             while (iPos < iLength && csFieldName[iPos] != L'.') {
982                 csSub += csFieldName[iPos ++];
983             }
984             int iCount = pArray->GetCount();
985             FX_BOOL bFind = FALSE;
986             for (int i = 0; i < iCount; i ++) {
987                 pDict = pArray->GetDict(i);
988                 if (pDict == NULL) {
989                     continue;
990                 }
991                 CFX_WideString csT = pDict->GetUnicodeText("T");
992                 if (csT == csSub) {
993                     bFind = TRUE;
994                     break;
995                 }
996             }
997             if (!bFind) {
998                 return NULL;
999             }
1000             if (iPos >= iLength) {
1001                 break;
1002             }
1003             pArray = pDict->GetArray("Kids");
1004         }
1005         if (pDict == NULL) {
1006             return NULL;
1007         } else {
1008             pArray = pDict->GetArray("Kids");
1009             if (pArray == NULL) {
1010                 return pDict;
1011             } else {
1012                 return pArray->GetDict(index);
1013             }
1014         }
1015     }
1016 }
1017 FX_BOOL CPDF_InterForm::NeedConstructAP()
1018 {
1019     if (m_pFormDict == NULL) {
1020         return FALSE;
1021     }
1022     return m_pFormDict->GetBoolean("NeedAppearances");
1023 }
1024 void CPDF_InterForm::NeedConstructAP(FX_BOOL bNeedAP)
1025 {
1026     if (m_pFormDict == NULL) {
1027         InitInterFormDict(m_pFormDict, m_pDocument);
1028     }
1029     m_pFormDict->SetAtBoolean("NeedAppearances", bNeedAP);
1030     m_bGenerateAP = bNeedAP;
1031 }
1032 int CPDF_InterForm::CountFieldsInCalculationOrder()
1033 {
1034     if (m_pFormDict == NULL) {
1035         return 0;
1036     }
1037     CPDF_Array* pArray = m_pFormDict->GetArray("CO");
1038     if (pArray == NULL) {
1039         return 0;
1040     }
1041     return pArray->GetCount();
1042 }
1043 CPDF_FormField* CPDF_InterForm::GetFieldInCalculationOrder(int index)
1044 {
1045     if (m_pFormDict == NULL || index < 0) {
1046         return NULL;
1047     }
1048     CPDF_Array* pArray = m_pFormDict->GetArray("CO");
1049     if (pArray == NULL) {
1050         return NULL;
1051     }
1052     CPDF_Object* pElement = pArray->GetElementValue(index);
1053     if (pElement != NULL && pElement->GetType() == PDFOBJ_DICTIONARY) {
1054         return GetFieldByDict((CPDF_Dictionary*)pElement);
1055     }
1056     return NULL;
1057 }
1058 int CPDF_InterForm::FindFieldInCalculationOrder(const CPDF_FormField* pField)
1059 {
1060     if (m_pFormDict == NULL || pField == NULL) {
1061         return -1;
1062     }
1063     CPDF_Array* pArray = m_pFormDict->GetArray("CO");
1064     if (pArray == NULL) {
1065         return -1;
1066     }
1067     for (FX_DWORD i = 0; i < pArray->GetCount(); i ++) {
1068         CPDF_Object* pElement = pArray->GetElementValue(i);
1069         if (pElement == pField->m_pDict) {
1070             return i;
1071         }
1072     }
1073     return -1;
1074 }
1075 FX_DWORD CPDF_InterForm::CountFormFonts()
1076 {
1077     return CountInterFormFonts(m_pFormDict);
1078 }
1079 CPDF_Font* CPDF_InterForm::GetFormFont(FX_DWORD index, CFX_ByteString& csNameTag)
1080 {
1081     return GetInterFormFont(m_pFormDict, m_pDocument, index, csNameTag);
1082 }
1083 CPDF_Font* CPDF_InterForm::GetFormFont(CFX_ByteString csNameTag)
1084 {
1085     return GetInterFormFont(m_pFormDict, m_pDocument, csNameTag);
1086 }
1087 CPDF_Font* CPDF_InterForm::GetFormFont(CFX_ByteString csFontName, CFX_ByteString& csNameTag)
1088 {
1089     return GetInterFormFont(m_pFormDict, m_pDocument, csFontName, csNameTag);
1090 }
1091 CPDF_Font* CPDF_InterForm::GetNativeFormFont(uint8_t charSet, CFX_ByteString& csNameTag)
1092 {
1093     return GetNativeInterFormFont(m_pFormDict, m_pDocument, charSet, csNameTag);
1094 }
1095 CPDF_Font* CPDF_InterForm::GetNativeFormFont(CFX_ByteString& csNameTag)
1096 {
1097     return GetNativeInterFormFont(m_pFormDict, m_pDocument, csNameTag);
1098 }
1099 FX_BOOL CPDF_InterForm::FindFormFont(const CPDF_Font* pFont, CFX_ByteString& csNameTag)
1100 {
1101     return FindInterFormFont(m_pFormDict, pFont, csNameTag);
1102 }
1103 FX_BOOL CPDF_InterForm::FindFormFont(CFX_ByteString csFontName, CPDF_Font*& pFont, CFX_ByteString& csNameTag)
1104 {
1105     return FindInterFormFont(m_pFormDict, m_pDocument, csFontName, pFont, csNameTag);
1106 }
1107 void CPDF_InterForm::AddFormFont(const CPDF_Font* pFont, CFX_ByteString& csNameTag)
1108 {
1109     AddInterFormFont(m_pFormDict, m_pDocument, pFont, csNameTag);
1110     m_bUpdated = TRUE;
1111 }
1112 CPDF_Font* CPDF_InterForm::AddNativeFormFont(uint8_t charSet, CFX_ByteString& csNameTag)
1113 {
1114     m_bUpdated = TRUE;
1115     return AddNativeInterFormFont(m_pFormDict, m_pDocument, charSet, csNameTag);
1116 }
1117 CPDF_Font* CPDF_InterForm::AddNativeFormFont(CFX_ByteString& csNameTag)
1118 {
1119     m_bUpdated = TRUE;
1120     return AddNativeInterFormFont(m_pFormDict, m_pDocument, csNameTag);
1121 }
1122 void CPDF_InterForm::RemoveFormFont(const CPDF_Font* pFont)
1123 {
1124     m_bUpdated = TRUE;
1125     RemoveInterFormFont(m_pFormDict, pFont);
1126 }
1127 void CPDF_InterForm::RemoveFormFont(CFX_ByteString csNameTag)
1128 {
1129     m_bUpdated = TRUE;
1130     RemoveInterFormFont(m_pFormDict, csNameTag);
1131 }
1132 CPDF_DefaultAppearance CPDF_InterForm::GetDefaultAppearance()
1133 {
1134     CFX_ByteString csDA;
1135     if (m_pFormDict == NULL) {
1136         return csDA;
1137     }
1138     csDA = m_pFormDict->GetString("DA");
1139     return csDA;
1140 }
1141 CPDF_Font* CPDF_InterForm::GetDefaultFormFont()
1142 {
1143     return GetDefaultInterFormFont(m_pFormDict, m_pDocument);
1144 }
1145 int CPDF_InterForm::GetFormAlignment()
1146 {
1147     if (m_pFormDict == NULL) {
1148         return 0;
1149     }
1150     return m_pFormDict->GetInteger("Q", 0);
1151 }
1152 FX_BOOL CPDF_InterForm::ResetForm(const CFX_PtrArray& fields, FX_BOOL bIncludeOrExclude, FX_BOOL bNotify)
1153 {
1154     if (bNotify && m_pFormNotify != NULL) {
1155         int iRet = m_pFormNotify->BeforeFormReset(this);
1156         if (iRet < 0) {
1157             return FALSE;
1158         }
1159     }
1160     int nCount = m_pFieldTree->m_Root.CountFields();
1161     for (int i = 0; i < nCount; i++) {
1162         CPDF_FormField* pField = m_pFieldTree->m_Root.GetField(i);
1163         if (pField == NULL) {
1164             continue;
1165         }
1166         FX_BOOL bFind = FALSE;
1167         int iCount = fields.GetSize();
1168         for (int i = 0; i < iCount; i ++) {
1169             if (pField == (CPDF_FormField*)fields[i]) {
1170                 bFind = TRUE;
1171                 break;
1172             }
1173         }
1174         if ((bIncludeOrExclude && bFind) || (!bIncludeOrExclude && !bFind)) {
1175             pField->ResetField(bNotify);
1176         }
1177     }
1178     if (bNotify && m_pFormNotify != NULL) {
1179         m_pFormNotify->AfterFormReset(this);
1180     }
1181     return TRUE;
1182 }
1183 FX_BOOL CPDF_InterForm::ResetForm(FX_BOOL bNotify)
1184 {
1185     if (bNotify && m_pFormNotify != NULL) {
1186         int iRet = m_pFormNotify->BeforeFormReset(this);
1187         if (iRet < 0) {
1188             return FALSE;
1189         }
1190     }
1191     int nCount = m_pFieldTree->m_Root.CountFields();
1192     for (int i = 0; i < nCount; i++) {
1193         CPDF_FormField* pField = m_pFieldTree->m_Root.GetField(i);
1194         if (pField == NULL) {
1195             continue;
1196         }
1197         pField->ResetField(bNotify);
1198     }
1199     if (bNotify && m_pFormNotify != NULL) {
1200         m_pFormNotify->AfterFormReset(this);
1201     }
1202     return TRUE;
1203 }
1204 void CPDF_InterForm::ReloadForm()
1205 {
1206     FX_POSITION pos = m_ControlMap.GetStartPosition();
1207     while (pos) {
1208         CPDF_Dictionary* pWidgetDict;
1209         CPDF_FormControl* pControl;
1210         m_ControlMap.GetNextAssoc(pos, (void*&)pWidgetDict, (void*&)pControl);
1211         delete pControl;
1212     }
1213     m_ControlMap.RemoveAll();
1214     int nCount = m_pFieldTree->m_Root.CountFields();
1215     for (int k = 0; k < nCount; k ++) {
1216         CPDF_FormField* pField = m_pFieldTree->m_Root.GetField(k);
1217         delete pField;
1218     }
1219     m_pFieldTree->RemoveAll();
1220     if (m_pFormDict == NULL) {
1221         return;
1222     }
1223     CPDF_Array* pFields = m_pFormDict->GetArray("Fields");
1224     if (pFields == NULL) {
1225         return;
1226     }
1227     int iCount = pFields->GetCount();
1228     for (int i = 0; i < iCount; i ++) {
1229         LoadField(pFields->GetDict(i));
1230     }
1231 }
1232 void CPDF_InterForm::LoadField(CPDF_Dictionary* pFieldDict, int nLevel)
1233 {
1234     if (nLevel > nMaxRecursion) {
1235         return;
1236     }
1237     if (pFieldDict == NULL) {
1238         return;
1239     }
1240     FX_DWORD dwParentObjNum = pFieldDict->GetObjNum();
1241     CPDF_Array* pKids = pFieldDict->GetArray("Kids");
1242     if (!pKids) {
1243         AddTerminalField(pFieldDict);
1244         return;
1245     }
1246     CPDF_Dictionary* pFirstKid = pKids->GetDict(0);
1247     if (pFirstKid == NULL) {
1248         return;
1249     }
1250     if (pFirstKid->KeyExist("T") || pFirstKid->KeyExist("Kids")) {
1251         for (FX_DWORD i = 0; i < pKids->GetCount(); i ++) {
1252             CPDF_Dictionary * pChildDict = pKids->GetDict(i);
1253             if (pChildDict) {
1254                 if (pChildDict->GetObjNum() != dwParentObjNum) {
1255                     LoadField(pChildDict, nLevel + 1);
1256                 }
1257             }
1258         }
1259     } else {
1260         AddTerminalField(pFieldDict);
1261     }
1262 }
1263 FX_BOOL CPDF_InterForm::HasXFAForm() const
1264 {
1265     return m_pFormDict && m_pFormDict->GetArray(FX_BSTRC("XFA")) != NULL;
1266 }
1267 void CPDF_InterForm::FixPageFields(const CPDF_Page* pPage)
1268 {
1269     ASSERT(pPage != NULL);
1270     CPDF_Dictionary* pPageDict = pPage->m_pFormDict;
1271     if (pPageDict == NULL) {
1272         return;
1273     }
1274     CPDF_Array* pAnnots = pPageDict->GetArray(FX_BSTRC("Annots"));
1275     if (pAnnots == NULL) {
1276         return;
1277     }
1278     int iAnnotCount = pAnnots->GetCount();
1279     for (int i = 0; i < iAnnotCount; i++) {
1280         CPDF_Dictionary* pAnnot = pAnnots->GetDict(i);
1281         if (pAnnot != NULL && pAnnot->GetString(FX_BSTRC("Subtype")) == "Widget") {
1282             LoadField(pAnnot);
1283         }
1284     }
1285 }
1286 CPDF_FormField* CPDF_InterForm::AddTerminalField(const CPDF_Dictionary* pFieldDict)
1287 {
1288     if (!pFieldDict->KeyExist(FX_BSTRC("T"))) {
1289         return NULL;
1290     }
1291     CPDF_Dictionary* pDict = (CPDF_Dictionary*)pFieldDict;
1292     CFX_WideString csWName = GetFullName(pDict);
1293     if (csWName.IsEmpty()) {
1294         return NULL;
1295     }
1296     CPDF_FormField* pField = NULL;
1297     pField = m_pFieldTree->GetField(csWName);
1298     if (pField == NULL) {
1299         CPDF_Dictionary *pParent = (CPDF_Dictionary*)pFieldDict;
1300         if (!pFieldDict->KeyExist(FX_BSTRC("T")) &&
1301             pFieldDict->GetString(FX_BSTRC("Subtype")) == FX_BSTRC("Widget")) {
1302             pParent = pFieldDict->GetDict(FX_BSTRC("Parent"));
1303             if (!pParent) {
1304                 pParent = (CPDF_Dictionary*)pFieldDict;
1305             }
1306         }
1307         if (pParent && pParent != pFieldDict && !pParent->KeyExist(FX_BSTRC("FT"))) {
1308             if (pFieldDict->KeyExist(FX_BSTRC("FT"))) {
1309                 CPDF_Object *pFTValue = pFieldDict->GetElementValue(FX_BSTRC("FT"));
1310                 if (pFTValue) {
1311                     pParent->SetAt(FX_BSTRC("FT"), pFTValue->Clone());
1312                 }
1313             }
1314             if (pFieldDict->KeyExist(FX_BSTRC("Ff"))) {
1315                 CPDF_Object *pFfValue = pFieldDict->GetElementValue(FX_BSTRC("Ff"));
1316                 if (pFfValue) {
1317                     pParent->SetAt(FX_BSTRC("Ff"), pFfValue->Clone());
1318                 }
1319             }
1320         }
1321         pField = FX_NEW CPDF_FormField(this, pParent);
1322         CPDF_Object* pTObj = pDict->GetElement("T");
1323         if (pTObj && pTObj->GetType() == PDFOBJ_REFERENCE) {
1324             CPDF_Object* pClone = pTObj->Clone(TRUE);
1325             if (pClone) {
1326                 pDict->SetAt("T", pClone);
1327             } else {
1328                 pDict->SetAtName("T", "");
1329             }
1330         }
1331         m_pFieldTree->SetField(csWName, pField);
1332     }
1333     CPDF_Array* pKids = pFieldDict->GetArray("Kids");
1334     if (pKids == NULL) {
1335         if (pFieldDict->GetString("Subtype") == "Widget") {
1336             AddControl(pField, pFieldDict);
1337         }
1338     } else {
1339         for (FX_DWORD i = 0; i < pKids->GetCount(); i ++) {
1340             CPDF_Dictionary* pKid = pKids->GetDict(i);
1341             if (pKid == NULL) {
1342                 continue;
1343             }
1344             if (pKid->GetString("Subtype") != "Widget") {
1345                 continue;
1346             }
1347             AddControl(pField, pKid);
1348         }
1349     }
1350     return pField;
1351 }
1352 CPDF_FormControl* CPDF_InterForm::AddControl(const CPDF_FormField* pField, const CPDF_Dictionary* pWidgetDict)
1353 {
1354     void *rValue = NULL;
1355     if (m_ControlMap.Lookup((CPDF_Dictionary*)pWidgetDict, rValue)) {
1356         return (CPDF_FormControl*)rValue;
1357     }
1358     CPDF_FormControl* pControl = FX_NEW CPDF_FormControl((CPDF_FormField*)pField, (CPDF_Dictionary*)pWidgetDict);
1359     if (pControl == NULL) {
1360         return NULL;
1361     }
1362     m_ControlMap.SetAt((CPDF_Dictionary*)pWidgetDict, pControl);
1363     ((CPDF_FormField*)pField)->m_ControlList.Add(pControl);
1364     return pControl;
1365 }
1366 CPDF_FormField* CPDF_InterForm::CheckRequiredFields(const CFX_PtrArray *fields, FX_BOOL bIncludeOrExclude) const
1367 {
1368     int nCount = m_pFieldTree->m_Root.CountFields();
1369     for (int i = 0; i < nCount; i++) {
1370         CPDF_FormField* pField = m_pFieldTree->m_Root.GetField(i);
1371         if (pField == NULL) {
1372             continue;
1373         }
1374         int32_t iType = pField->GetType();
1375         if (iType == CPDF_FormField::PushButton || iType == CPDF_FormField::CheckBox || iType == CPDF_FormField::ListBox) {
1376             continue;
1377         }
1378         FX_DWORD dwFlags = pField->GetFieldFlags();
1379         if (dwFlags & 0x04) {
1380             continue;
1381         }
1382         FX_BOOL bFind = TRUE;
1383         if (fields != NULL) {
1384             bFind = fields->Find(pField, 0) >= 0;
1385         }
1386         if ((bIncludeOrExclude && bFind) || (!bIncludeOrExclude && !bFind)) {
1387             CPDF_Dictionary *pFieldDict = pField->m_pDict;
1388             if ((dwFlags & 0x02) != 0 && pFieldDict->GetString("V").IsEmpty()) {
1389                 return pField;
1390             }
1391         }
1392     }
1393     return NULL;
1394 }
1395 CFDF_Document* CPDF_InterForm::ExportToFDF(const CFX_WideStringC& pdf_path, FX_BOOL bSimpleFileSpec) const
1396 {
1397     CFX_PtrArray fields;
1398     int nCount = m_pFieldTree->m_Root.CountFields();
1399     for (int i = 0; i < nCount; i ++) {
1400         CPDF_FormField* pField = m_pFieldTree->m_Root.GetField(i);
1401         fields.Add(pField);
1402     }
1403     return ExportToFDF(pdf_path, fields, TRUE, bSimpleFileSpec);
1404 }
1405 CFX_WideString FILESPEC_EncodeFileName(const CFX_WideStringC& filepath);
1406 CFDF_Document* CPDF_InterForm::ExportToFDF(const CFX_WideStringC& pdf_path, CFX_PtrArray& fields, FX_BOOL bIncludeOrExclude, FX_BOOL bSimpleFileSpec) const
1407 {
1408     CFDF_Document* pDoc = CFDF_Document::CreateNewDoc();
1409     if (pDoc == NULL) {
1410         return NULL;
1411     }
1412     CPDF_Dictionary* pMainDict = pDoc->GetRoot()->GetDict("FDF");
1413     if (!pdf_path.IsEmpty()) {
1414         if (bSimpleFileSpec) {
1415             CFX_WideString wsFilePath = FILESPEC_EncodeFileName(pdf_path);
1416             pMainDict->SetAtString(FX_BSTRC("F"), CFX_ByteString::FromUnicode(wsFilePath));
1417             pMainDict->SetAtString(FX_BSTRC("UF"), PDF_EncodeText(wsFilePath));
1418         } else {
1419             CPDF_FileSpec filespec;
1420             filespec.SetFileName(pdf_path);
1421             pMainDict->SetAt("F", (CPDF_Object*)filespec);
1422         }
1423     }
1424     CPDF_Array* pFields = CPDF_Array::Create();
1425     if (pFields == NULL) {
1426         return NULL;
1427     }
1428     pMainDict->SetAt("Fields", pFields);
1429     int nCount = m_pFieldTree->m_Root.CountFields();
1430     for (int i = 0; i < nCount; i ++) {
1431         CPDF_FormField* pField = m_pFieldTree->m_Root.GetField(i);
1432         if (pField == NULL || pField->GetType() == CPDF_FormField::PushButton) {
1433             continue;
1434         }
1435         FX_DWORD dwFlags = pField->GetFieldFlags();
1436         if (dwFlags & 0x04) {
1437             continue;
1438         }
1439         FX_BOOL bFind = fields.Find(pField, 0) >= 0;
1440         if ((bIncludeOrExclude && bFind) || (!bIncludeOrExclude && !bFind)) {
1441             if ((dwFlags & 0x02) != 0 && pField->m_pDict->GetString("V").IsEmpty()) {
1442                 continue;
1443             }
1444             CFX_WideString fullname = GetFullName(pField->GetFieldDict());
1445             CPDF_Dictionary* pFieldDict = CPDF_Dictionary::Create();
1446             if (pFieldDict == NULL) {
1447                 return NULL;
1448             }
1449             CPDF_String* pString = CPDF_String::Create(fullname);
1450             if (pString == NULL) {
1451                 pFieldDict->Release();
1452                 return NULL;
1453             }
1454             pFieldDict->SetAt("T", pString);
1455             if (pField->GetType() == CPDF_FormField::CheckBox || pField->GetType() == CPDF_FormField::RadioButton) {
1456                 CFX_WideString csExport = pField->GetCheckValue(FALSE);
1457                 CFX_ByteString csBExport = PDF_EncodeText(csExport);
1458                 CPDF_Object* pOpt = FPDF_GetFieldAttr(pField->m_pDict, "Opt");
1459                 if (pOpt == NULL) {
1460                     pFieldDict->SetAtName("V", csBExport);
1461                 } else {
1462                     pFieldDict->SetAtString("V", csBExport);
1463                 }
1464             } else {
1465                 CPDF_Object* pV = FPDF_GetFieldAttr(pField->m_pDict, "V");
1466                 if (pV != NULL) {
1467                     pFieldDict->SetAt("V", pV->Clone(TRUE));
1468                 }
1469             }
1470             pFields->Add(pFieldDict);
1471         }
1472     }
1473     return pDoc;
1474 }
1475 const struct _SupportFieldEncoding {
1476     const FX_CHAR* m_name;
1477     int32_t m_codePage;
1478 } g_fieldEncoding[] = {
1479     { "BigFive", 950 },
1480     { "GBK", 936 },
1481     { "Shift-JIS", 932 },
1482     { "UHC", 949 },
1483 };
1484 static void FPDFDOC_FDF_GetFieldValue(CPDF_Dictionary *pFieldDict, CFX_WideString &csValue, CFX_ByteString &bsEncoding)
1485 {
1486     ASSERT(pFieldDict != NULL);
1487     CFX_ByteString csBValue = pFieldDict->GetString("V");
1488     int32_t iCount = sizeof(g_fieldEncoding) / sizeof(g_fieldEncoding[0]);
1489     int32_t i = 0;
1490     for (; i < iCount; ++i)
1491         if (bsEncoding == g_fieldEncoding[i].m_name) {
1492             break;
1493         }
1494     if (i < iCount) {
1495         CFX_CharMap *pCharMap = CFX_CharMap::GetDefaultMapper(g_fieldEncoding[i].m_codePage);
1496         FXSYS_assert(pCharMap != NULL);
1497         csValue.ConvertFrom(csBValue, pCharMap);
1498         return;
1499     }
1500     CFX_ByteString csTemp = csBValue.Left(2);
1501     if (csTemp == "\xFF\xFE" || csTemp == "\xFE\xFF") {
1502         csValue = PDF_DecodeText(csBValue);
1503     } else {
1504         csValue = CFX_WideString::FromLocal(csBValue);
1505     }
1506 }
1507 void CPDF_InterForm::FDF_ImportField(CPDF_Dictionary* pFieldDict, const CFX_WideString& parent_name, FX_BOOL bNotify, int nLevel)
1508 {
1509     CFX_WideString name;
1510     if (!parent_name.IsEmpty()) {
1511         name = parent_name + L".";
1512     }
1513     name += pFieldDict->GetUnicodeText("T");
1514     CPDF_Array* pKids = pFieldDict->GetArray("Kids");
1515     if (pKids) {
1516         for (FX_DWORD i = 0; i < pKids->GetCount(); i ++) {
1517             CPDF_Dictionary* pKid = pKids->GetDict(i);
1518             if (pKid == NULL) {
1519                 continue;
1520             }
1521             if (nLevel <= nMaxRecursion) {
1522                 FDF_ImportField(pKid, name, bNotify, nLevel + 1);
1523             }
1524         }
1525         return;
1526     }
1527     if (!pFieldDict->KeyExist("V")) {
1528         return;
1529     }
1530     CPDF_FormField* pField = m_pFieldTree->GetField(name);
1531     if (pField == NULL) {
1532         return;
1533     }
1534     CFX_WideString csWValue;
1535     FPDFDOC_FDF_GetFieldValue(pFieldDict, csWValue, m_bsEncoding);
1536     int iType = pField->GetFieldType();
1537     if (bNotify && m_pFormNotify != NULL) {
1538         int iRet = 0;
1539         if (iType == FIELDTYPE_LISTBOX) {
1540             iRet = m_pFormNotify->BeforeSelectionChange(pField, csWValue);
1541         } else if (iType == FIELDTYPE_COMBOBOX || iType == FIELDTYPE_TEXTFIELD) {
1542             iRet = m_pFormNotify->BeforeValueChange(pField, csWValue);
1543         }
1544         if (iRet < 0) {
1545             return;
1546         }
1547     }
1548     CFX_ByteArray statusArray;
1549     if (iType == FIELDTYPE_CHECKBOX || iType == FIELDTYPE_RADIOBUTTON) {
1550         SaveCheckedFieldStatus(pField, statusArray);
1551     }
1552     pField->SetValue(csWValue);
1553     CPDF_FormField::Type eType = pField->GetType();
1554     if ((eType == CPDF_FormField::ListBox || eType == CPDF_FormField::ComboBox) && pFieldDict->KeyExist("Opt")) {
1555         pField->m_pDict->SetAt("Opt", pFieldDict->GetElementValue("Opt")->Clone(TRUE));
1556     }
1557     if (bNotify && m_pFormNotify != NULL) {
1558         if (iType == FIELDTYPE_CHECKBOX || iType == FIELDTYPE_RADIOBUTTON) {
1559             m_pFormNotify->AfterCheckedStatusChange(pField, statusArray);
1560         } else if (iType == FIELDTYPE_LISTBOX) {
1561             m_pFormNotify->AfterSelectionChange(pField);
1562         } else if (iType == FIELDTYPE_COMBOBOX || iType == FIELDTYPE_TEXTFIELD) {
1563             m_pFormNotify->AfterValueChange(pField);
1564         }
1565     }
1566     if (CPDF_InterForm::m_bUpdateAP) {
1567         pField->UpdateAP(NULL);
1568     }
1569 }
1570 FX_BOOL CPDF_InterForm::ImportFromFDF(const CFDF_Document* pFDF, FX_BOOL bNotify)
1571 {
1572     if (pFDF == NULL) {
1573         return FALSE;
1574     }
1575     CPDF_Dictionary* pMainDict = pFDF->GetRoot()->GetDict("FDF");
1576     if (pMainDict == NULL) {
1577         return FALSE;
1578     }
1579     CPDF_Array* pFields = pMainDict->GetArray("Fields");
1580     if (pFields == NULL) {
1581         return FALSE;
1582     }
1583     m_bsEncoding = pMainDict->GetString(FX_BSTRC("Encoding"));
1584     if (bNotify && m_pFormNotify != NULL) {
1585         int iRet = m_pFormNotify->BeforeFormImportData(this);
1586         if (iRet < 0) {
1587             return FALSE;
1588         }
1589     }
1590     for (FX_DWORD i = 0; i < pFields->GetCount(); i ++) {
1591         CPDF_Dictionary* pField = pFields->GetDict(i);
1592         if (pField == NULL) {
1593             continue;
1594         }
1595         FDF_ImportField(pField, L"", bNotify);
1596     }
1597     if (bNotify && m_pFormNotify != NULL) {
1598         m_pFormNotify->AfterFormImportData(this);
1599     }
1600     return TRUE;
1601 }
1602 void CPDF_InterForm::SetFormNotify(const CPDF_FormNotify* pNotify)
1603 {
1604     m_pFormNotify = (CPDF_FormNotify*)pNotify;
1605 }
1606 int CPDF_InterForm::GetPageWithWidget(int iCurPage, FX_BOOL bNext)
1607 {
1608     if (iCurPage < 0) {
1609         return -1;
1610     }
1611     int iPageCount = m_pDocument->GetPageCount();
1612     if (iCurPage >= iPageCount) {
1613         return -1;
1614     }
1615     int iNewPage = iCurPage;
1616     do {
1617         iNewPage += bNext ? 1 : -1;
1618         if (iNewPage >= iPageCount) {
1619             iNewPage = 0;
1620         }
1621         if (iNewPage < 0) {
1622             iNewPage = iPageCount - 1;
1623         }
1624         if (iNewPage == iCurPage) {
1625             break;
1626         }
1627         CPDF_Dictionary* pPageDict = m_pDocument->GetPage(iNewPage);
1628         if (pPageDict == NULL) {
1629             continue;
1630         }
1631         CPDF_Array* pAnnots = pPageDict->GetArray("Annots");
1632         if (pAnnots == NULL) {
1633             continue;
1634         }
1635         FX_DWORD dwCount = pAnnots->GetCount();
1636         for (FX_DWORD i = 0; i < dwCount; i ++) {
1637             CPDF_Object* pAnnotDict = pAnnots->GetElementValue(i);
1638             if (pAnnotDict == NULL) {
1639                 continue;
1640             }
1641             CPDF_FormControl* pControl = NULL;
1642             if (m_ControlMap.Lookup(pAnnotDict, (void*&)pControl)) {
1643                 return iNewPage;
1644             }
1645         }
1646     } while (TRUE);
1647     return -1;
1648 }