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
11const int nMaxRecursion = 32;
12
13class _CFieldNameExtractor
14{
15public:
16    _CFieldNameExtractor(const CFX_WideString& full_name)
17    {
18        m_pStart = full_name.c_str();
19        m_pEnd = m_pStart + full_name.GetLength();
20        m_pCur = m_pStart;
21    }
22    void GetNext(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    }
33protected:
34    FX_LPCWSTR m_pStart;
35    FX_LPCWSTR m_pEnd;
36    FX_LPCWSTR m_pCur;
37};
38class CFieldTree
39{
40public:
41    struct _Node  {
42        _Node *parent;
43        CFX_PtrArray children;
44        CFX_WideString short_name;
45        CPDF_FormField *field_ptr;
46        int CountFields(int nLevel = 0)
47        {
48            if (nLevel > nMaxRecursion) {
49                return 0;
50            }
51            if (field_ptr) {
52                return 1;
53            }
54            int count = 0;
55            for (int i = 0; i < children.GetSize(); i ++) {
56                count += ((_Node *)children.GetAt(i))->CountFields(nLevel + 1);
57            }
58            return count;
59        }
60        CPDF_FormField* GetField(int* fields_to_go)
61        {
62            if (field_ptr) {
63                if (*fields_to_go == 0) {
64                    return field_ptr;
65                }
66                --*fields_to_go;
67                return NULL;
68            }
69            for (int i = 0; i < children.GetSize(); i++) {
70                _Node *pNode = (_Node *)children.GetAt(i);
71                CPDF_FormField* pField = pNode->GetField(fields_to_go);
72                if (pField) {
73                    return pField;
74                }
75            }
76            return NULL;
77        }
78        CPDF_FormField* GetField(int index)
79        {
80            int fields_to_go = index;
81            return GetField(&fields_to_go);
82        }
83    };
84    CFieldTree();
85    ~CFieldTree();
86    void SetField(const CFX_WideString &full_name, CPDF_FormField *field_ptr);
87    CPDF_FormField *GetField(const CFX_WideString &full_name);
88    CPDF_FormField *RemoveField(const CFX_WideString &full_name);
89    void RemoveAll();
90    _Node *FindNode(const CFX_WideString &full_name);
91    _Node * AddChild(_Node *pParent, const CFX_WideString &short_name, CPDF_FormField *field_ptr);
92    void RemoveNode(_Node *pNode, int nLevel = 0);
93    _Node *_Lookup(_Node *pParent, const CFX_WideString &short_name);
94    _Node m_Root;
95};
96CFieldTree::CFieldTree()
97{
98    m_Root.parent = NULL;
99    m_Root.field_ptr = NULL;
100}
101CFieldTree::~CFieldTree()
102{
103    RemoveAll();
104}
105CFieldTree::_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}
117void 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}
133CFieldTree::_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}
148void 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}
156void 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}
179CPDF_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}
197CPDF_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}
227CFieldTree::_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}
245CPDF_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}
266CPDF_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}
283FX_BOOL	CPDF_InterForm::m_bUpdateAP = TRUE;
284FX_BOOL CPDF_InterForm::UpdatingAPEnabled()
285{
286    return m_bUpdateAP;
287}
288void CPDF_InterForm::EnableUpdateAP(FX_BOOL bUpdateAP)
289{
290    m_bUpdateAP = bUpdateAP;
291}
292CFX_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_
345typedef struct _PDF_FONTDATA {
346    FX_BOOL		bFind;
347    LOGFONTA	lf;
348} PDF_FONTDATA, FAR* LPDF_FONTDATA;
349static 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}
364static 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}
376static 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}
386static 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
399CPDF_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}
418CPDF_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}
440CPDF_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}
462CPDF_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}
476CFX_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}
513CFX_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}
522FX_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}
582CPDF_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}
601CPDF_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}
611FX_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}
677FX_BOOL CPDF_InterForm::ValidateFieldName(CFX_WideString& csNewFieldName, int iType)
678{
679    return ValidateFieldName(csNewFieldName, iType, NULL, NULL);
680}
681FX_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}
688FX_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}
696int 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}
715int 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}
735FX_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}
746CPDF_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}
757void 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}
769FX_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}
783CPDF_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}
791FX_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}
802CPDF_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}
813FX_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}
829int 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}
849CPDF_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}
872CPDF_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}
894CPDF_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}
900FX_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}
956CPDF_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}
1012FX_BOOL CPDF_InterForm::NeedConstructAP()
1013{
1014    if (m_pFormDict == NULL) {
1015        return FALSE;
1016    }
1017    return m_pFormDict->GetBoolean("NeedAppearances");
1018}
1019void 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}
1027int 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}
1038CPDF_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}
1053int 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}
1070FX_DWORD CPDF_InterForm::CountFormFonts()
1071{
1072    return CountInterFormFonts(m_pFormDict);
1073}
1074CPDF_Font* CPDF_InterForm::GetFormFont(FX_DWORD index, CFX_ByteString& csNameTag)
1075{
1076    return GetInterFormFont(m_pFormDict, m_pDocument, index, csNameTag);
1077}
1078CPDF_Font* CPDF_InterForm::GetFormFont(CFX_ByteString csNameTag)
1079{
1080    return GetInterFormFont(m_pFormDict, m_pDocument, csNameTag);
1081}
1082CPDF_Font* CPDF_InterForm::GetFormFont(CFX_ByteString csFontName, CFX_ByteString& csNameTag)
1083{
1084    return GetInterFormFont(m_pFormDict, m_pDocument, csFontName, csNameTag);
1085}
1086CPDF_Font* CPDF_InterForm::GetNativeFormFont(FX_BYTE charSet, CFX_ByteString& csNameTag)
1087{
1088    return GetNativeInterFormFont(m_pFormDict, m_pDocument, charSet, csNameTag);
1089}
1090CPDF_Font* CPDF_InterForm::GetNativeFormFont(CFX_ByteString& csNameTag)
1091{
1092    return GetNativeInterFormFont(m_pFormDict, m_pDocument, csNameTag);
1093}
1094FX_BOOL CPDF_InterForm::FindFormFont(const CPDF_Font* pFont, CFX_ByteString& csNameTag)
1095{
1096    return FindInterFormFont(m_pFormDict, pFont, csNameTag);
1097}
1098FX_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}
1102void CPDF_InterForm::AddFormFont(const CPDF_Font* pFont, CFX_ByteString& csNameTag)
1103{
1104    AddInterFormFont(m_pFormDict, m_pDocument, pFont, csNameTag);
1105    m_bUpdated = TRUE;
1106}
1107CPDF_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}
1112CPDF_Font* CPDF_InterForm::AddNativeFormFont(CFX_ByteString& csNameTag)
1113{
1114    m_bUpdated = TRUE;
1115    return AddNativeInterFormFont(m_pFormDict, m_pDocument, csNameTag);
1116}
1117void CPDF_InterForm::RemoveFormFont(const CPDF_Font* pFont)
1118{
1119    m_bUpdated = TRUE;
1120    RemoveInterFormFont(m_pFormDict, pFont);
1121}
1122void CPDF_InterForm::RemoveFormFont(CFX_ByteString csNameTag)
1123{
1124    m_bUpdated = TRUE;
1125    RemoveInterFormFont(m_pFormDict, csNameTag);
1126}
1127CPDF_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}
1136CPDF_Font* CPDF_InterForm::GetDefaultFormFont()
1137{
1138    return GetDefaultInterFormFont(m_pFormDict, m_pDocument);
1139}
1140int CPDF_InterForm::GetFormAlignment()
1141{
1142    if (m_pFormDict == NULL) {
1143        return 0;
1144    }
1145    return m_pFormDict->GetInteger("Q", 0);
1146}
1147FX_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}
1178FX_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}
1199void 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}
1227void 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}
1258FX_BOOL CPDF_InterForm::HasXFAForm() const
1259{
1260    return m_pFormDict && m_pFormDict->GetArray(FX_BSTRC("XFA")) != NULL;
1261}
1262void 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}
1281CPDF_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}
1347CPDF_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}
1358CPDF_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}
1387CFDF_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}
1397CFX_WideString FILESPEC_EncodeFileName(FX_WSTR filepath);
1398CFDF_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}
1467const 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};
1476static 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}
1499void 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}
1562FX_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}
1594void CPDF_InterForm::SetFormNotify(const CPDF_FormNotify* pNotify)
1595{
1596    m_pFormNotify = (CPDF_FormNotify*)pNotify;
1597}
1598int 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