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