Home | History | Annotate | Download | only in fpdfdoc
      1 // Copyright 2014 PDFium Authors. All rights reserved.
      2 // Use of this source code is governed by a BSD-style license that can be
      3 // found in the LICENSE file.
      4 
      5 // Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com
      6 
      7 #include "../../include/fpdfdoc/fpdf_doc.h"
      8 #include "../../include/fxcrt/fx_xml.h"
      9 CFX_WideString	GetFullName(CPDF_Dictionary* pFieldDict);
     10 void			InitInterFormDict(CPDF_Dictionary*& pFormDict, CPDF_Document* pDocument);
     11 FX_DWORD		CountInterFormFonts(CPDF_Dictionary* pFormDict);
     12 CPDF_Font*		GetInterFormFont(CPDF_Dictionary* pFormDict, CPDF_Document* pDocument, FX_DWORD index, CFX_ByteString& csNameTag);
     13 CPDF_Font*		GetInterFormFont(CPDF_Dictionary* pFormDict, CPDF_Document* pDocument, CFX_ByteString csNameTag);
     14 CPDF_Font*		GetInterFormFont(CPDF_Dictionary* pFormDict, CPDF_Document* pDocument, CFX_ByteString csFontName, CFX_ByteString& csNameTag);
     15 CPDF_Font*		GetNativeInterFormFont(CPDF_Dictionary* pFormDict, CPDF_Document* pDocument, FX_BYTE charSet, CFX_ByteString& csNameTag);
     16 CPDF_Font*		GetNativeInterFormFont(CPDF_Dictionary* pFormDict, CPDF_Document* pDocument, CFX_ByteString& csNameTag);
     17 FX_BOOL			FindInterFormFont(CPDF_Dictionary* pFormDict, const CPDF_Font* pFont, CFX_ByteString& csNameTag);
     18 FX_BOOL			FindInterFormFont(CPDF_Dictionary* pFormDict, CPDF_Document* pDocument, CFX_ByteString csFontName, CPDF_Font*& pFont, CFX_ByteString& csNameTag);
     19 void			AddInterFormFont(CPDF_Dictionary*& pFormDict, CPDF_Document* pDocument, const CPDF_Font* pFont, CFX_ByteString& csNameTag);
     20 CPDF_Font*		AddNativeInterFormFont(CPDF_Dictionary*& pFormDict, CPDF_Document* pDocument, FX_BYTE charSet, CFX_ByteString& csNameTag);
     21 CPDF_Font*		AddNativeInterFormFont(CPDF_Dictionary*& pFormDict, CPDF_Document* pDocument, CFX_ByteString& csNameTag);
     22 void			RemoveInterFormFont(CPDF_Dictionary* pFormDict, const CPDF_Font* pFont);
     23 void			RemoveInterFormFont(CPDF_Dictionary* pFormDict, CFX_ByteString csNameTag);
     24 CPDF_Font*		GetDefaultInterFormFont(CPDF_Dictionary* pFormDict, CPDF_Document* pDocument);
     25 void			SetDefaultInterFormFont(CPDF_Dictionary*& pFormDict, CPDF_Document* pDocument, const CPDF_Font* pFont);
     26 void			SaveCheckedFieldStatus(CPDF_FormField* pField, CFX_ByteArray& statusArray);
     27 FX_BOOL			NeedPDFEncodeForFieldFullName(const CFX_WideString& csFieldName);
     28 FX_BOOL			NeedPDFEncodeForFieldTree(CPDF_Dictionary* pFieldDict, int nLevel = 0);
     29 void			EncodeFieldName(const CFX_WideString& csName, CFX_ByteString& csT);
     30 void			UpdateEncodeFieldName(CPDF_Dictionary* pFieldDict, int nLevel = 0);
     31 const int nMaxRecursion = 32;
     32 class _CFieldNameExtractor : public CFX_Object
     33 {
     34 public:
     35     _CFieldNameExtractor(const CFX_WideString& full_name)
     36     {
     37         m_pStart = full_name;
     38         m_pEnd = m_pStart + full_name.GetLength();
     39         m_pCur = m_pStart;
     40     }
     41     void GetNext(FX_LPCWSTR &pSubName, FX_STRSIZE& size)
     42     {
     43         pSubName = m_pCur;
     44         while (m_pCur < m_pEnd && m_pCur[0] != L'.') {
     45             m_pCur++;
     46         }
     47         size = (FX_STRSIZE)(m_pCur - pSubName);
     48         if (m_pCur < m_pEnd && m_pCur[0] == L'.') {
     49             m_pCur++;
     50         }
     51     }
     52 protected:
     53     FX_LPCWSTR m_pStart;
     54     FX_LPCWSTR m_pEnd;
     55     FX_LPCWSTR m_pCur;
     56 };
     57 class CFieldTree : public CFX_Object
     58 {
     59 public:
     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 };
    115 CFieldTree::CFieldTree()
    116 {
    117     m_Root.parent = NULL;
    118     m_Root.field_ptr = NULL;
    119 }
    120 CFieldTree::~CFieldTree()
    121 {
    122     RemoveAll();
    123 }
    124 CFieldTree::_Node *CFieldTree::AddChild(_Node *pParent, const CFX_WideString &short_name, CPDF_FormField *field_ptr)
    125 {
    126     if (pParent == NULL) {
    127         return NULL;
    128     }
    129     _Node *pNode = 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 }
    139 void 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 }
    155 CFieldTree::_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 }
    170 void 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 }
    178 void 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 }
    201 CPDF_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 }
    219 CPDF_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 }
    249 CFieldTree::_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 }
    267 CPDF_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 }
    288 CPDF_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 }
    305 FX_BOOL	CPDF_InterForm::m_bUpdateAP = TRUE;
    306 FX_BOOL CPDF_InterForm::UpdatingAPEnabled()
    307 {
    308     return m_bUpdateAP;
    309 }
    310 void CPDF_InterForm::EnableUpdateAP(FX_BOOL bUpdateAP)
    311 {
    312     m_bUpdateAP = bUpdateAP;
    313 }
    314 CFX_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_
    367 typedef struct _PDF_FONTDATA {
    368     FX_BOOL		bFind;
    369     LOGFONTA	lf;
    370 } PDF_FONTDATA, FAR* LPDF_FONTDATA;
    371 static 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 }
    386 static 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 }
    398 static 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 }
    408 static 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
    421 CPDF_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 }
    440 CPDF_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 }
    462 CPDF_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 }
    484 CPDF_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 }
    498 CFX_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 }
    535 CFX_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 }
    544 FX_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 }
    604 CPDF_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 }
    623 CPDF_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 }
    633 FX_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 }
    699 FX_BOOL CPDF_InterForm::ValidateFieldName(CFX_WideString& csNewFieldName, int iType)
    700 {
    701     return ValidateFieldName(csNewFieldName, iType, NULL, NULL);
    702 }
    703 FX_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 }
    710 FX_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 }
    718 int 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 }
    737 int 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 }
    756 FX_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 }
    767 CPDF_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 }
    778 void 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 }
    790 FX_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 }
    804 CPDF_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 }
    812 FX_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 }
    823 CPDF_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 }
    834 FX_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 }
    850 int 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 }
    870 CPDF_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 }
    893 CPDF_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 }
    915 CPDF_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 }
    921 FX_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 }
    977 CPDF_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 }
   1033 FX_BOOL CPDF_InterForm::NeedConstructAP()
   1034 {
   1035     if (m_pFormDict == NULL) {
   1036         return FALSE;
   1037     }
   1038     return m_pFormDict->GetBoolean("NeedAppearances");
   1039 }
   1040 void 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 }
   1048 int 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 }
   1059 CPDF_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 }
   1074 int 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 }
   1091 FX_DWORD CPDF_InterForm::CountFormFonts()
   1092 {
   1093     return CountInterFormFonts(m_pFormDict);
   1094 }
   1095 CPDF_Font* CPDF_InterForm::GetFormFont(FX_DWORD index, CFX_ByteString& csNameTag)
   1096 {
   1097     return GetInterFormFont(m_pFormDict, m_pDocument, index, csNameTag);
   1098 }
   1099 CPDF_Font* CPDF_InterForm::GetFormFont(CFX_ByteString csNameTag)
   1100 {
   1101     return GetInterFormFont(m_pFormDict, m_pDocument, csNameTag);
   1102 }
   1103 CPDF_Font* CPDF_InterForm::GetFormFont(CFX_ByteString csFontName, CFX_ByteString& csNameTag)
   1104 {
   1105     return GetInterFormFont(m_pFormDict, m_pDocument, csFontName, csNameTag);
   1106 }
   1107 CPDF_Font* CPDF_InterForm::GetNativeFormFont(FX_BYTE charSet, CFX_ByteString& csNameTag)
   1108 {
   1109     return GetNativeInterFormFont(m_pFormDict, m_pDocument, charSet, csNameTag);
   1110 }
   1111 CPDF_Font* CPDF_InterForm::GetNativeFormFont(CFX_ByteString& csNameTag)
   1112 {
   1113     return GetNativeInterFormFont(m_pFormDict, m_pDocument, csNameTag);
   1114 }
   1115 FX_BOOL CPDF_InterForm::FindFormFont(const CPDF_Font* pFont, CFX_ByteString& csNameTag)
   1116 {
   1117     return FindInterFormFont(m_pFormDict, pFont, csNameTag);
   1118 }
   1119 FX_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 }
   1123 void CPDF_InterForm::AddFormFont(const CPDF_Font* pFont, CFX_ByteString& csNameTag)
   1124 {
   1125     AddInterFormFont(m_pFormDict, m_pDocument, pFont, csNameTag);
   1126     m_bUpdated = TRUE;
   1127 }
   1128 CPDF_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 }
   1133 CPDF_Font* CPDF_InterForm::AddNativeFormFont(CFX_ByteString& csNameTag)
   1134 {
   1135     m_bUpdated = TRUE;
   1136     return AddNativeInterFormFont(m_pFormDict, m_pDocument, csNameTag);
   1137 }
   1138 void CPDF_InterForm::RemoveFormFont(const CPDF_Font* pFont)
   1139 {
   1140     m_bUpdated = TRUE;
   1141     RemoveInterFormFont(m_pFormDict, pFont);
   1142 }
   1143 void CPDF_InterForm::RemoveFormFont(CFX_ByteString csNameTag)
   1144 {
   1145     m_bUpdated = TRUE;
   1146     RemoveInterFormFont(m_pFormDict, csNameTag);
   1147 }
   1148 CPDF_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 }
   1157 CPDF_Font* CPDF_InterForm::GetDefaultFormFont()
   1158 {
   1159     return GetDefaultInterFormFont(m_pFormDict, m_pDocument);
   1160 }
   1161 int CPDF_InterForm::GetFormAlignment()
   1162 {
   1163     if (m_pFormDict == NULL) {
   1164         return 0;
   1165     }
   1166     return m_pFormDict->GetInteger("Q", 0);
   1167 }
   1168 FX_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 }
   1199 FX_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 }
   1220 void 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 }
   1248 void 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 }
   1279 FX_BOOL CPDF_InterForm::HasXFAForm() const
   1280 {
   1281     return m_pFormDict && m_pFormDict->GetArray(FX_BSTRC("XFA")) != NULL;
   1282 }
   1283 void 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 }
   1302 CPDF_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 }
   1368 CPDF_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 }
   1382 CPDF_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 }
   1411 CFDF_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 }
   1421 CFX_WideString FILESPEC_EncodeFileName(FX_WSTR filepath);
   1422 CFDF_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 }
   1491 const 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 };
   1500 static 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 }
   1523 void 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 }
   1586 FX_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 }
   1618 void CPDF_InterForm::SetFormNotify(const CPDF_FormNotify* pNotify)
   1619 {
   1620     m_pFormNotify = (CPDF_FormNotify*)pNotify;
   1621 }
   1622 int 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