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