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