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