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