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