| OLD | NEW |
| (Empty) |
| 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 <vector> | |
| 8 | |
| 9 #include "core/fpdfapi/fpdf_font/include/cpdf_fontencoding.h" | |
| 10 #include "core/fpdfapi/fpdf_page/include/cpdf_page.h" | |
| 11 #include "core/fpdfapi/fpdf_parser/include/cfdf_document.h" | |
| 12 #include "core/fpdfapi/fpdf_parser/include/cpdf_array.h" | |
| 13 #include "core/fpdfapi/fpdf_parser/include/cpdf_document.h" | |
| 14 #include "core/fpdfapi/fpdf_parser/include/cpdf_string.h" | |
| 15 #include "core/fpdfdoc/include/cpdf_filespec.h" | |
| 16 #include "core/fpdfdoc/include/cpdf_formcontrol.h" | |
| 17 #include "core/fpdfdoc/include/cpdf_interform.h" | |
| 18 #include "core/fpdfdoc/doc_utils.h" | |
| 19 #include "third_party/base/stl_util.h" | |
| 20 | |
| 21 namespace { | |
| 22 | |
| 23 const int nMaxRecursion = 32; | |
| 24 | |
| 25 const struct SupportFieldEncoding { | |
| 26 const FX_CHAR* m_name; | |
| 27 uint16_t m_codePage; | |
| 28 } g_fieldEncoding[] = { | |
| 29 {"BigFive", 950}, | |
| 30 {"GBK", 936}, | |
| 31 {"Shift-JIS", 932}, | |
| 32 {"UHC", 949}, | |
| 33 }; | |
| 34 | |
| 35 CFX_WideString FPDFDOC_FDF_GetFieldValue(const CPDF_Dictionary& pFieldDict, | |
| 36 const CFX_ByteString& bsEncoding) { | |
| 37 const CFX_ByteString csBValue = pFieldDict.GetStringBy("V"); | |
| 38 for (const auto& encoding : g_fieldEncoding) { | |
| 39 if (bsEncoding == encoding.m_name) | |
| 40 return CFX_WideString::FromCodePage(csBValue.AsStringC(), | |
| 41 encoding.m_codePage); | |
| 42 } | |
| 43 CFX_ByteString csTemp = csBValue.Left(2); | |
| 44 if (csTemp == "\xFF\xFE" || csTemp == "\xFE\xFF") | |
| 45 return PDF_DecodeText(csBValue); | |
| 46 return CFX_WideString::FromLocal(csBValue.AsStringC()); | |
| 47 } | |
| 48 | |
| 49 } // namespace | |
| 50 | |
| 51 class CFieldNameExtractor { | |
| 52 public: | |
| 53 explicit CFieldNameExtractor(const CFX_WideString& full_name) | |
| 54 : m_FullName(full_name) { | |
| 55 m_pCur = m_FullName.c_str(); | |
| 56 m_pEnd = m_pCur + m_FullName.GetLength(); | |
| 57 } | |
| 58 | |
| 59 void GetNext(const FX_WCHAR*& pSubName, FX_STRSIZE& size) { | |
| 60 pSubName = m_pCur; | |
| 61 while (m_pCur < m_pEnd && m_pCur[0] != L'.') { | |
| 62 m_pCur++; | |
| 63 } | |
| 64 size = (FX_STRSIZE)(m_pCur - pSubName); | |
| 65 if (m_pCur < m_pEnd && m_pCur[0] == L'.') { | |
| 66 m_pCur++; | |
| 67 } | |
| 68 } | |
| 69 | |
| 70 protected: | |
| 71 CFX_WideString m_FullName; | |
| 72 const FX_WCHAR* m_pCur; | |
| 73 const FX_WCHAR* m_pEnd; | |
| 74 }; | |
| 75 | |
| 76 class CFieldTree { | |
| 77 public: | |
| 78 struct _Node { | |
| 79 _Node* parent; | |
| 80 CFX_ArrayTemplate<_Node*> children; | |
| 81 CFX_WideString short_name; | |
| 82 CPDF_FormField* field_ptr; | |
| 83 int CountFields(int nLevel = 0) { | |
| 84 if (nLevel > nMaxRecursion) { | |
| 85 return 0; | |
| 86 } | |
| 87 if (field_ptr) { | |
| 88 return 1; | |
| 89 } | |
| 90 int count = 0; | |
| 91 for (int i = 0; i < children.GetSize(); i++) { | |
| 92 count += children.GetAt(i)->CountFields(nLevel + 1); | |
| 93 } | |
| 94 return count; | |
| 95 } | |
| 96 CPDF_FormField* GetField(int* fields_to_go) { | |
| 97 if (field_ptr) { | |
| 98 if (*fields_to_go == 0) { | |
| 99 return field_ptr; | |
| 100 } | |
| 101 --*fields_to_go; | |
| 102 return nullptr; | |
| 103 } | |
| 104 for (int i = 0; i < children.GetSize(); i++) { | |
| 105 if (CPDF_FormField* pField = children.GetAt(i)->GetField(fields_to_go)) | |
| 106 return pField; | |
| 107 } | |
| 108 return nullptr; | |
| 109 } | |
| 110 CPDF_FormField* GetField(int index) { | |
| 111 int fields_to_go = index; | |
| 112 return GetField(&fields_to_go); | |
| 113 } | |
| 114 }; | |
| 115 CFieldTree(); | |
| 116 ~CFieldTree(); | |
| 117 void SetField(const CFX_WideString& full_name, CPDF_FormField* field_ptr); | |
| 118 CPDF_FormField* GetField(const CFX_WideString& full_name); | |
| 119 CPDF_FormField* RemoveField(const CFX_WideString& full_name); | |
| 120 void RemoveAll(); | |
| 121 _Node* FindNode(const CFX_WideString& full_name); | |
| 122 _Node* AddChild(_Node* pParent, | |
| 123 const CFX_WideString& short_name, | |
| 124 CPDF_FormField* field_ptr); | |
| 125 void RemoveNode(_Node* pNode, int nLevel = 0); | |
| 126 _Node* _Lookup(_Node* pParent, const CFX_WideString& short_name); | |
| 127 _Node m_Root; | |
| 128 }; | |
| 129 CFieldTree::CFieldTree() { | |
| 130 m_Root.parent = nullptr; | |
| 131 m_Root.field_ptr = nullptr; | |
| 132 } | |
| 133 CFieldTree::~CFieldTree() { | |
| 134 RemoveAll(); | |
| 135 } | |
| 136 CFieldTree::_Node* CFieldTree::AddChild(_Node* pParent, | |
| 137 const CFX_WideString& short_name, | |
| 138 CPDF_FormField* field_ptr) { | |
| 139 if (!pParent) { | |
| 140 return nullptr; | |
| 141 } | |
| 142 _Node* pNode = new _Node; | |
| 143 pNode->parent = pParent; | |
| 144 pNode->short_name = short_name; | |
| 145 pNode->field_ptr = field_ptr; | |
| 146 pParent->children.Add(pNode); | |
| 147 return pNode; | |
| 148 } | |
| 149 void CFieldTree::RemoveNode(_Node* pNode, int nLevel) { | |
| 150 if (!pNode) { | |
| 151 return; | |
| 152 } | |
| 153 if (nLevel <= nMaxRecursion) { | |
| 154 for (int i = 0; i < pNode->children.GetSize(); i++) { | |
| 155 RemoveNode(pNode->children[i], nLevel + 1); | |
| 156 } | |
| 157 } | |
| 158 delete pNode; | |
| 159 } | |
| 160 CFieldTree::_Node* CFieldTree::_Lookup(_Node* pParent, | |
| 161 const CFX_WideString& short_name) { | |
| 162 if (!pParent) { | |
| 163 return nullptr; | |
| 164 } | |
| 165 for (int i = 0; i < pParent->children.GetSize(); i++) { | |
| 166 _Node* pNode = pParent->children[i]; | |
| 167 if (pNode->short_name.GetLength() == short_name.GetLength() && | |
| 168 FXSYS_memcmp(pNode->short_name.c_str(), short_name.c_str(), | |
| 169 short_name.GetLength() * sizeof(FX_WCHAR)) == 0) { | |
| 170 return pNode; | |
| 171 } | |
| 172 } | |
| 173 return nullptr; | |
| 174 } | |
| 175 void CFieldTree::RemoveAll() { | |
| 176 for (int i = 0; i < m_Root.children.GetSize(); i++) { | |
| 177 RemoveNode(m_Root.children[i]); | |
| 178 } | |
| 179 } | |
| 180 void CFieldTree::SetField(const CFX_WideString& full_name, | |
| 181 CPDF_FormField* field_ptr) { | |
| 182 if (full_name == L"") { | |
| 183 return; | |
| 184 } | |
| 185 CFieldNameExtractor name_extractor(full_name); | |
| 186 const FX_WCHAR* pName; | |
| 187 FX_STRSIZE nLength; | |
| 188 name_extractor.GetNext(pName, nLength); | |
| 189 _Node *pNode = &m_Root, *pLast = nullptr; | |
| 190 while (nLength > 0) { | |
| 191 pLast = pNode; | |
| 192 CFX_WideString name = CFX_WideString(pName, nLength); | |
| 193 pNode = _Lookup(pLast, name); | |
| 194 if (!pNode) { | |
| 195 pNode = AddChild(pLast, name, nullptr); | |
| 196 } | |
| 197 name_extractor.GetNext(pName, nLength); | |
| 198 } | |
| 199 if (pNode != &m_Root) { | |
| 200 pNode->field_ptr = field_ptr; | |
| 201 } | |
| 202 } | |
| 203 CPDF_FormField* CFieldTree::GetField(const CFX_WideString& full_name) { | |
| 204 if (full_name == L"") { | |
| 205 return nullptr; | |
| 206 } | |
| 207 CFieldNameExtractor name_extractor(full_name); | |
| 208 const FX_WCHAR* pName; | |
| 209 FX_STRSIZE nLength; | |
| 210 name_extractor.GetNext(pName, nLength); | |
| 211 _Node *pNode = &m_Root, *pLast = nullptr; | |
| 212 while (nLength > 0 && pNode) { | |
| 213 pLast = pNode; | |
| 214 CFX_WideString name = CFX_WideString(pName, nLength); | |
| 215 pNode = _Lookup(pLast, name); | |
| 216 name_extractor.GetNext(pName, nLength); | |
| 217 } | |
| 218 return pNode ? pNode->field_ptr : nullptr; | |
| 219 } | |
| 220 CPDF_FormField* CFieldTree::RemoveField(const CFX_WideString& full_name) { | |
| 221 if (full_name == L"") { | |
| 222 return nullptr; | |
| 223 } | |
| 224 CFieldNameExtractor name_extractor(full_name); | |
| 225 const FX_WCHAR* pName; | |
| 226 FX_STRSIZE nLength; | |
| 227 name_extractor.GetNext(pName, nLength); | |
| 228 _Node* pNode = &m_Root; | |
| 229 _Node* pLast = nullptr; | |
| 230 while (nLength > 0 && pNode) { | |
| 231 pLast = pNode; | |
| 232 CFX_WideString name = CFX_WideString(pName, nLength); | |
| 233 pNode = _Lookup(pLast, name); | |
| 234 name_extractor.GetNext(pName, nLength); | |
| 235 } | |
| 236 if (pNode && pNode != &m_Root) { | |
| 237 for (int i = 0; i < pLast->children.GetSize(); i++) { | |
| 238 if (pNode == pLast->children[i]) { | |
| 239 pLast->children.RemoveAt(i); | |
| 240 break; | |
| 241 } | |
| 242 } | |
| 243 CPDF_FormField* pField = pNode->field_ptr; | |
| 244 RemoveNode(pNode); | |
| 245 return pField; | |
| 246 } | |
| 247 return nullptr; | |
| 248 } | |
| 249 CFieldTree::_Node* CFieldTree::FindNode(const CFX_WideString& full_name) { | |
| 250 if (full_name == L"") { | |
| 251 return nullptr; | |
| 252 } | |
| 253 CFieldNameExtractor name_extractor(full_name); | |
| 254 const FX_WCHAR* pName; | |
| 255 FX_STRSIZE nLength; | |
| 256 name_extractor.GetNext(pName, nLength); | |
| 257 _Node *pNode = &m_Root, *pLast = nullptr; | |
| 258 while (nLength > 0 && pNode) { | |
| 259 pLast = pNode; | |
| 260 CFX_WideString name = CFX_WideString(pName, nLength); | |
| 261 pNode = _Lookup(pLast, name); | |
| 262 name_extractor.GetNext(pName, nLength); | |
| 263 } | |
| 264 return pNode; | |
| 265 } | |
| 266 | |
| 267 CPDF_InterForm::CPDF_InterForm(CPDF_Document* pDocument) | |
| 268 : m_pDocument(pDocument), | |
| 269 m_pFormDict(nullptr), | |
| 270 m_pFieldTree(new CFieldTree), | |
| 271 m_pFormNotify(nullptr) { | |
| 272 CPDF_Dictionary* pRoot = m_pDocument->GetRoot(); | |
| 273 if (!pRoot) | |
| 274 return; | |
| 275 | |
| 276 m_pFormDict = pRoot->GetDictBy("AcroForm"); | |
| 277 if (!m_pFormDict) | |
| 278 return; | |
| 279 | |
| 280 CPDF_Array* pFields = m_pFormDict->GetArrayBy("Fields"); | |
| 281 if (!pFields) | |
| 282 return; | |
| 283 | |
| 284 for (size_t i = 0; i < pFields->GetCount(); i++) | |
| 285 LoadField(pFields->GetDictAt(i)); | |
| 286 } | |
| 287 | |
| 288 CPDF_InterForm::~CPDF_InterForm() { | |
| 289 for (auto it : m_ControlMap) | |
| 290 delete it.second; | |
| 291 | |
| 292 int nCount = m_pFieldTree->m_Root.CountFields(); | |
| 293 for (int i = 0; i < nCount; ++i) { | |
| 294 delete m_pFieldTree->m_Root.GetField(i); | |
| 295 } | |
| 296 } | |
| 297 | |
| 298 FX_BOOL CPDF_InterForm::s_bUpdateAP = TRUE; | |
| 299 | |
| 300 FX_BOOL CPDF_InterForm::IsUpdateAPEnabled() { | |
| 301 return s_bUpdateAP; | |
| 302 } | |
| 303 | |
| 304 void CPDF_InterForm::SetUpdateAP(FX_BOOL bUpdateAP) { | |
| 305 s_bUpdateAP = bUpdateAP; | |
| 306 } | |
| 307 | |
| 308 CFX_ByteString CPDF_InterForm::GenerateNewResourceName( | |
| 309 const CPDF_Dictionary* pResDict, | |
| 310 const FX_CHAR* csType, | |
| 311 int iMinLen, | |
| 312 const FX_CHAR* csPrefix) { | |
| 313 CFX_ByteString csStr = csPrefix; | |
| 314 CFX_ByteString csBType = csType; | |
| 315 if (csStr.IsEmpty()) { | |
| 316 if (csBType == "ExtGState") { | |
| 317 csStr = "GS"; | |
| 318 } else if (csBType == "ColorSpace") { | |
| 319 csStr = "CS"; | |
| 320 } else if (csBType == "Font") { | |
| 321 csStr = "ZiTi"; | |
| 322 } else { | |
| 323 csStr = "Res"; | |
| 324 } | |
| 325 } | |
| 326 CFX_ByteString csTmp = csStr; | |
| 327 int iCount = csStr.GetLength(); | |
| 328 int m = 0; | |
| 329 if (iMinLen > 0) { | |
| 330 csTmp = ""; | |
| 331 while (m < iMinLen && m < iCount) { | |
| 332 csTmp += csStr[m++]; | |
| 333 } | |
| 334 while (m < iMinLen) { | |
| 335 csTmp += '0' + m % 10; | |
| 336 m++; | |
| 337 } | |
| 338 } else { | |
| 339 m = iCount; | |
| 340 } | |
| 341 if (!pResDict) { | |
| 342 return csTmp; | |
| 343 } | |
| 344 CPDF_Dictionary* pDict = pResDict->GetDictBy(csType); | |
| 345 if (!pDict) { | |
| 346 return csTmp; | |
| 347 } | |
| 348 int num = 0; | |
| 349 CFX_ByteString bsNum; | |
| 350 while (TRUE) { | |
| 351 CFX_ByteString csKey = csTmp + bsNum; | |
| 352 if (!pDict->KeyExist(csKey)) { | |
| 353 return csKey; | |
| 354 } | |
| 355 if (m < iCount) { | |
| 356 csTmp += csStr[m++]; | |
| 357 } else { | |
| 358 bsNum.Format("%d", num++); | |
| 359 } | |
| 360 m++; | |
| 361 } | |
| 362 return csTmp; | |
| 363 } | |
| 364 #if _FXM_PLATFORM_ == _FXM_PLATFORM_WINDOWS_ | |
| 365 typedef struct PDF_FONTDATA_ { | |
| 366 FX_BOOL bFind; | |
| 367 LOGFONTA lf; | |
| 368 } PDF_FONTDATA, FAR* LPDF_FONTDATA; | |
| 369 static int CALLBACK EnumFontFamExProc(ENUMLOGFONTEXA* lpelfe, | |
| 370 NEWTEXTMETRICEX* lpntme, | |
| 371 DWORD FontType, | |
| 372 LPARAM lParam) { | |
| 373 if (FontType != 0x004 || strchr(lpelfe->elfLogFont.lfFaceName, '@')) { | |
| 374 return 1; | |
| 375 } | |
| 376 LPDF_FONTDATA pData = (LPDF_FONTDATA)lParam; | |
| 377 memcpy(&pData->lf, &lpelfe->elfLogFont, sizeof(LOGFONTA)); | |
| 378 pData->bFind = TRUE; | |
| 379 return 0; | |
| 380 } | |
| 381 static FX_BOOL RetrieveSpecificFont(LOGFONTA& lf) { | |
| 382 PDF_FONTDATA fd; | |
| 383 memset(&fd, 0, sizeof(PDF_FONTDATA)); | |
| 384 HDC hDC = ::GetDC(nullptr); | |
| 385 EnumFontFamiliesExA(hDC, &lf, (FONTENUMPROCA)EnumFontFamExProc, (LPARAM)&fd, | |
| 386 0); | |
| 387 ::ReleaseDC(nullptr, hDC); | |
| 388 if (fd.bFind) { | |
| 389 memcpy(&lf, &fd.lf, sizeof(LOGFONTA)); | |
| 390 } | |
| 391 return fd.bFind; | |
| 392 } | |
| 393 static FX_BOOL RetrieveSpecificFont(uint8_t charSet, | |
| 394 uint8_t pitchAndFamily, | |
| 395 LPCSTR pcsFontName, | |
| 396 LOGFONTA& lf) { | |
| 397 memset(&lf, 0, sizeof(LOGFONTA)); | |
| 398 lf.lfCharSet = charSet; | |
| 399 lf.lfPitchAndFamily = pitchAndFamily; | |
| 400 if (pcsFontName) { | |
| 401 // TODO(dsinclair): Should this be strncpy? | |
| 402 strcpy(lf.lfFaceName, pcsFontName); | |
| 403 } | |
| 404 return RetrieveSpecificFont(lf); | |
| 405 } | |
| 406 #endif // _FXM_PLATFORM_ == _FXM_PLATFORM_WINDOWS_ | |
| 407 | |
| 408 CPDF_Font* CPDF_InterForm::AddStandardFont(CPDF_Document* pDocument, | |
| 409 CFX_ByteString csFontName) { | |
| 410 if (!pDocument || csFontName.IsEmpty()) | |
| 411 return nullptr; | |
| 412 | |
| 413 if (csFontName == "ZapfDingbats") | |
| 414 return pDocument->AddStandardFont(csFontName.c_str(), nullptr); | |
| 415 | |
| 416 CPDF_FontEncoding encoding(PDFFONT_ENCODING_WINANSI); | |
| 417 return pDocument->AddStandardFont(csFontName.c_str(), &encoding); | |
| 418 } | |
| 419 | |
| 420 CFX_ByteString CPDF_InterForm::GetNativeFont(uint8_t charSet, void* pLogFont) { | |
| 421 CFX_ByteString csFontName; | |
| 422 #if _FXM_PLATFORM_ == _FXM_PLATFORM_WINDOWS_ | |
| 423 LOGFONTA lf = {}; | |
| 424 if (charSet == ANSI_CHARSET) { | |
| 425 csFontName = "Helvetica"; | |
| 426 return csFontName; | |
| 427 } | |
| 428 FX_BOOL bRet = FALSE; | |
| 429 if (charSet == SHIFTJIS_CHARSET) { | |
| 430 bRet = RetrieveSpecificFont(charSet, DEFAULT_PITCH | FF_DONTCARE, | |
| 431 "MS Mincho", lf); | |
| 432 } else if (charSet == GB2312_CHARSET) { | |
| 433 bRet = RetrieveSpecificFont(charSet, DEFAULT_PITCH | FF_DONTCARE, "SimSun", | |
| 434 lf); | |
| 435 } else if (charSet == CHINESEBIG5_CHARSET) { | |
| 436 bRet = RetrieveSpecificFont(charSet, DEFAULT_PITCH | FF_DONTCARE, "MingLiU", | |
| 437 lf); | |
| 438 } | |
| 439 if (!bRet) { | |
| 440 bRet = RetrieveSpecificFont(charSet, DEFAULT_PITCH | FF_DONTCARE, | |
| 441 "Arial Unicode MS", lf); | |
| 442 } | |
| 443 if (!bRet) { | |
| 444 bRet = RetrieveSpecificFont(charSet, DEFAULT_PITCH | FF_DONTCARE, | |
| 445 "Microsoft Sans Serif", lf); | |
| 446 } | |
| 447 if (!bRet) { | |
| 448 bRet = | |
| 449 RetrieveSpecificFont(charSet, DEFAULT_PITCH | FF_DONTCARE, nullptr, lf); | |
| 450 } | |
| 451 if (bRet) { | |
| 452 if (pLogFont) { | |
| 453 memcpy(pLogFont, &lf, sizeof(LOGFONTA)); | |
| 454 } | |
| 455 csFontName = lf.lfFaceName; | |
| 456 return csFontName; | |
| 457 } | |
| 458 #endif | |
| 459 return csFontName; | |
| 460 } | |
| 461 | |
| 462 CFX_ByteString CPDF_InterForm::GetNativeFont(void* pLogFont) { | |
| 463 #if _FXM_PLATFORM_ == _FXM_PLATFORM_WINDOWS_ | |
| 464 return GetNativeFont(GetNativeCharSet(), pLogFont); | |
| 465 #else | |
| 466 return CFX_ByteString(); | |
| 467 #endif | |
| 468 } | |
| 469 | |
| 470 // static | |
| 471 uint8_t CPDF_InterForm::GetNativeCharSet() { | |
| 472 #if _FXM_PLATFORM_ == _FXM_PLATFORM_WINDOWS_ | |
| 473 uint8_t charSet = ANSI_CHARSET; | |
| 474 UINT iCodePage = ::GetACP(); | |
| 475 switch (iCodePage) { | |
| 476 case 932: | |
| 477 charSet = SHIFTJIS_CHARSET; | |
| 478 break; | |
| 479 case 936: | |
| 480 charSet = GB2312_CHARSET; | |
| 481 break; | |
| 482 case 950: | |
| 483 charSet = CHINESEBIG5_CHARSET; | |
| 484 break; | |
| 485 case 1252: | |
| 486 charSet = ANSI_CHARSET; | |
| 487 break; | |
| 488 case 874: | |
| 489 charSet = THAI_CHARSET; | |
| 490 break; | |
| 491 case 949: | |
| 492 charSet = HANGUL_CHARSET; | |
| 493 break; | |
| 494 case 1200: | |
| 495 charSet = ANSI_CHARSET; | |
| 496 break; | |
| 497 case 1250: | |
| 498 charSet = EASTEUROPE_CHARSET; | |
| 499 break; | |
| 500 case 1251: | |
| 501 charSet = RUSSIAN_CHARSET; | |
| 502 break; | |
| 503 case 1253: | |
| 504 charSet = GREEK_CHARSET; | |
| 505 break; | |
| 506 case 1254: | |
| 507 charSet = TURKISH_CHARSET; | |
| 508 break; | |
| 509 case 1255: | |
| 510 charSet = HEBREW_CHARSET; | |
| 511 break; | |
| 512 case 1256: | |
| 513 charSet = ARABIC_CHARSET; | |
| 514 break; | |
| 515 case 1257: | |
| 516 charSet = BALTIC_CHARSET; | |
| 517 break; | |
| 518 case 1258: | |
| 519 charSet = VIETNAMESE_CHARSET; | |
| 520 break; | |
| 521 case 1361: | |
| 522 charSet = JOHAB_CHARSET; | |
| 523 break; | |
| 524 } | |
| 525 return charSet; | |
| 526 #else | |
| 527 return 0; | |
| 528 #endif | |
| 529 } | |
| 530 | |
| 531 CPDF_Font* CPDF_InterForm::AddNativeFont(uint8_t charSet, | |
| 532 CPDF_Document* pDocument) { | |
| 533 if (!pDocument) | |
| 534 return nullptr; | |
| 535 | |
| 536 #if _FXM_PLATFORM_ == _FXM_PLATFORM_WINDOWS_ | |
| 537 LOGFONTA lf; | |
| 538 CFX_ByteString csFontName = GetNativeFont(charSet, &lf); | |
| 539 if (!csFontName.IsEmpty()) { | |
| 540 if (csFontName == "Helvetica") | |
| 541 return AddStandardFont(pDocument, csFontName); | |
| 542 return pDocument->AddWindowsFont(&lf, FALSE, TRUE); | |
| 543 } | |
| 544 #endif | |
| 545 return nullptr; | |
| 546 } | |
| 547 | |
| 548 CPDF_Font* CPDF_InterForm::AddNativeFont(CPDF_Document* pDocument) { | |
| 549 return pDocument ? AddNativeFont(GetNativeCharSet(), pDocument) : nullptr; | |
| 550 } | |
| 551 | |
| 552 FX_BOOL CPDF_InterForm::ValidateFieldName( | |
| 553 CFX_WideString& csNewFieldName, | |
| 554 int iType, | |
| 555 const CPDF_FormField* pExcludedField, | |
| 556 const CPDF_FormControl* pExcludedControl) { | |
| 557 if (csNewFieldName.IsEmpty()) { | |
| 558 return FALSE; | |
| 559 } | |
| 560 int iPos = 0; | |
| 561 int iLength = csNewFieldName.GetLength(); | |
| 562 CFX_WideString csSub; | |
| 563 while (TRUE) { | |
| 564 while (iPos < iLength && | |
| 565 (csNewFieldName[iPos] == L'.' || csNewFieldName[iPos] == L' ')) { | |
| 566 iPos++; | |
| 567 } | |
| 568 if (iPos < iLength && !csSub.IsEmpty()) { | |
| 569 csSub += L'.'; | |
| 570 } | |
| 571 while (iPos < iLength && csNewFieldName[iPos] != L'.') { | |
| 572 csSub += csNewFieldName[iPos++]; | |
| 573 } | |
| 574 for (int i = csSub.GetLength() - 1; i > -1; i--) { | |
| 575 if (csSub[i] == L' ' || csSub[i] == L'.') { | |
| 576 csSub.SetAt(i, L'\0'); | |
| 577 } else { | |
| 578 break; | |
| 579 } | |
| 580 } | |
| 581 uint32_t dwCount = m_pFieldTree->m_Root.CountFields(); | |
| 582 for (uint32_t m = 0; m < dwCount; m++) { | |
| 583 CPDF_FormField* pField = m_pFieldTree->m_Root.GetField(m); | |
| 584 if (!pField) { | |
| 585 continue; | |
| 586 } | |
| 587 if (pField == pExcludedField) { | |
| 588 if (pExcludedControl) { | |
| 589 if (pField->CountControls() < 2) { | |
| 590 continue; | |
| 591 } | |
| 592 } else { | |
| 593 continue; | |
| 594 } | |
| 595 } | |
| 596 CFX_WideString csFullName = pField->GetFullName(); | |
| 597 int iRet = CompareFieldName(csSub, csFullName); | |
| 598 if (iRet == 1) { | |
| 599 if (pField->GetFieldType() != iType) { | |
| 600 return FALSE; | |
| 601 } | |
| 602 } else if (iRet == 2 && csSub == csNewFieldName) { | |
| 603 if (csFullName[iPos] == L'.') { | |
| 604 return FALSE; | |
| 605 } | |
| 606 } else if (iRet == 3 && csSub == csNewFieldName) { | |
| 607 if (csNewFieldName[csFullName.GetLength()] == L'.') { | |
| 608 return FALSE; | |
| 609 } | |
| 610 } | |
| 611 } | |
| 612 if (iPos >= iLength) { | |
| 613 break; | |
| 614 } | |
| 615 } | |
| 616 if (csSub.IsEmpty()) { | |
| 617 return FALSE; | |
| 618 } | |
| 619 csNewFieldName = csSub; | |
| 620 return TRUE; | |
| 621 } | |
| 622 FX_BOOL CPDF_InterForm::ValidateFieldName(CFX_WideString& csNewFieldName, | |
| 623 int iType) { | |
| 624 return ValidateFieldName(csNewFieldName, iType, nullptr, nullptr); | |
| 625 } | |
| 626 FX_BOOL CPDF_InterForm::ValidateFieldName(const CPDF_FormField* pField, | |
| 627 CFX_WideString& csNewFieldName) { | |
| 628 return pField && !csNewFieldName.IsEmpty() && | |
| 629 ValidateFieldName(csNewFieldName, pField->GetFieldType(), pField, | |
| 630 nullptr); | |
| 631 } | |
| 632 FX_BOOL CPDF_InterForm::ValidateFieldName(const CPDF_FormControl* pControl, | |
| 633 CFX_WideString& csNewFieldName) { | |
| 634 if (!pControl || csNewFieldName.IsEmpty()) { | |
| 635 return FALSE; | |
| 636 } | |
| 637 CPDF_FormField* pField = pControl->GetField(); | |
| 638 return ValidateFieldName(csNewFieldName, pField->GetFieldType(), pField, | |
| 639 pControl); | |
| 640 } | |
| 641 int CPDF_InterForm::CompareFieldName(const CFX_ByteString& name1, | |
| 642 const CFX_ByteString& name2) { | |
| 643 if (name1.GetLength() == name2.GetLength()) { | |
| 644 return name1 == name2 ? 1 : 0; | |
| 645 } | |
| 646 const FX_CHAR* ptr1 = name1.c_str(); | |
| 647 const FX_CHAR* ptr2 = name2.c_str(); | |
| 648 int i = 0; | |
| 649 while (ptr1[i] == ptr2[i]) { | |
| 650 i++; | |
| 651 } | |
| 652 if (i == name1.GetLength()) { | |
| 653 return 2; | |
| 654 } | |
| 655 if (i == name2.GetLength()) { | |
| 656 return 3; | |
| 657 } | |
| 658 return 0; | |
| 659 } | |
| 660 int CPDF_InterForm::CompareFieldName(const CFX_WideString& name1, | |
| 661 const CFX_WideString& name2) { | |
| 662 const FX_WCHAR* ptr1 = name1.c_str(); | |
| 663 const FX_WCHAR* ptr2 = name2.c_str(); | |
| 664 if (name1.GetLength() == name2.GetLength()) { | |
| 665 return name1 == name2 ? 1 : 0; | |
| 666 } | |
| 667 int i = 0; | |
| 668 while (ptr1[i] == ptr2[i]) { | |
| 669 i++; | |
| 670 } | |
| 671 if (i == name1.GetLength()) { | |
| 672 return 2; | |
| 673 } | |
| 674 if (i == name2.GetLength()) { | |
| 675 return 3; | |
| 676 } | |
| 677 return 0; | |
| 678 } | |
| 679 uint32_t CPDF_InterForm::CountFields(const CFX_WideString& csFieldName) { | |
| 680 if (csFieldName.IsEmpty()) { | |
| 681 return (uint32_t)m_pFieldTree->m_Root.CountFields(); | |
| 682 } | |
| 683 CFieldTree::_Node* pNode = m_pFieldTree->FindNode(csFieldName); | |
| 684 return pNode ? pNode->CountFields() : 0; | |
| 685 } | |
| 686 CPDF_FormField* CPDF_InterForm::GetField(uint32_t index, | |
| 687 const CFX_WideString& csFieldName) { | |
| 688 if (csFieldName == L"") { | |
| 689 return m_pFieldTree->m_Root.GetField(index); | |
| 690 } | |
| 691 CFieldTree::_Node* pNode = m_pFieldTree->FindNode(csFieldName); | |
| 692 return pNode ? pNode->GetField(index) : nullptr; | |
| 693 } | |
| 694 | |
| 695 CPDF_FormField* CPDF_InterForm::GetFieldByDict( | |
| 696 CPDF_Dictionary* pFieldDict) const { | |
| 697 if (!pFieldDict) { | |
| 698 return nullptr; | |
| 699 } | |
| 700 CFX_WideString csWName = GetFullName(pFieldDict); | |
| 701 return m_pFieldTree->GetField(csWName); | |
| 702 } | |
| 703 | |
| 704 CPDF_FormControl* CPDF_InterForm::GetControlAtPoint(CPDF_Page* pPage, | |
| 705 FX_FLOAT pdf_x, | |
| 706 FX_FLOAT pdf_y, | |
| 707 int* z_order) const { | |
| 708 CPDF_Array* pAnnotList = pPage->m_pFormDict->GetArrayBy("Annots"); | |
| 709 if (!pAnnotList) | |
| 710 return nullptr; | |
| 711 | |
| 712 for (size_t i = pAnnotList->GetCount(); i > 0; --i) { | |
| 713 size_t annot_index = i - 1; | |
| 714 CPDF_Dictionary* pAnnot = pAnnotList->GetDictAt(annot_index); | |
| 715 if (!pAnnot) | |
| 716 continue; | |
| 717 | |
| 718 const auto it = m_ControlMap.find(pAnnot); | |
| 719 if (it == m_ControlMap.end()) | |
| 720 continue; | |
| 721 | |
| 722 CPDF_FormControl* pControl = it->second; | |
| 723 CFX_FloatRect rect = pControl->GetRect(); | |
| 724 if (!rect.Contains(pdf_x, pdf_y)) | |
| 725 continue; | |
| 726 | |
| 727 if (z_order) | |
| 728 *z_order = static_cast<int>(annot_index); | |
| 729 return pControl; | |
| 730 } | |
| 731 return nullptr; | |
| 732 } | |
| 733 | |
| 734 CPDF_FormControl* CPDF_InterForm::GetControlByDict( | |
| 735 const CPDF_Dictionary* pWidgetDict) const { | |
| 736 const auto it = m_ControlMap.find(pWidgetDict); | |
| 737 return it != m_ControlMap.end() ? it->second : nullptr; | |
| 738 } | |
| 739 | |
| 740 FX_BOOL CPDF_InterForm::NeedConstructAP() const { | |
| 741 return m_pFormDict && m_pFormDict->GetBooleanBy("NeedAppearances"); | |
| 742 } | |
| 743 | |
| 744 int CPDF_InterForm::CountFieldsInCalculationOrder() { | |
| 745 if (!m_pFormDict) | |
| 746 return 0; | |
| 747 | |
| 748 CPDF_Array* pArray = m_pFormDict->GetArrayBy("CO"); | |
| 749 return pArray ? pArray->GetCount() : 0; | |
| 750 } | |
| 751 | |
| 752 CPDF_FormField* CPDF_InterForm::GetFieldInCalculationOrder(int index) { | |
| 753 if (!m_pFormDict || index < 0) | |
| 754 return nullptr; | |
| 755 | |
| 756 CPDF_Array* pArray = m_pFormDict->GetArrayBy("CO"); | |
| 757 if (!pArray) | |
| 758 return nullptr; | |
| 759 | |
| 760 CPDF_Dictionary* pElement = ToDictionary(pArray->GetDirectObjectAt(index)); | |
| 761 return pElement ? GetFieldByDict(pElement) : nullptr; | |
| 762 } | |
| 763 | |
| 764 int CPDF_InterForm::FindFieldInCalculationOrder(const CPDF_FormField* pField) { | |
| 765 if (!m_pFormDict || !pField) | |
| 766 return -1; | |
| 767 | |
| 768 CPDF_Array* pArray = m_pFormDict->GetArrayBy("CO"); | |
| 769 if (!pArray) | |
| 770 return -1; | |
| 771 | |
| 772 for (size_t i = 0; i < pArray->GetCount(); i++) { | |
| 773 CPDF_Object* pElement = pArray->GetDirectObjectAt(i); | |
| 774 if (pElement == pField->m_pDict) { | |
| 775 return i; | |
| 776 } | |
| 777 } | |
| 778 return -1; | |
| 779 } | |
| 780 | |
| 781 uint32_t CPDF_InterForm::CountFormFonts() { | |
| 782 return CountInterFormFonts(m_pFormDict); | |
| 783 } | |
| 784 | |
| 785 CPDF_Font* CPDF_InterForm::GetFormFont(uint32_t index, | |
| 786 CFX_ByteString& csNameTag) { | |
| 787 return GetInterFormFont(m_pFormDict, m_pDocument, index, csNameTag); | |
| 788 } | |
| 789 CPDF_Font* CPDF_InterForm::GetFormFont(CFX_ByteString csNameTag) { | |
| 790 return GetInterFormFont(m_pFormDict, m_pDocument, csNameTag); | |
| 791 } | |
| 792 CPDF_Font* CPDF_InterForm::GetFormFont(CFX_ByteString csFontName, | |
| 793 CFX_ByteString& csNameTag) { | |
| 794 return GetInterFormFont(m_pFormDict, m_pDocument, csFontName, csNameTag); | |
| 795 } | |
| 796 CPDF_Font* CPDF_InterForm::GetNativeFormFont(uint8_t charSet, | |
| 797 CFX_ByteString& csNameTag) { | |
| 798 return GetNativeInterFormFont(m_pFormDict, m_pDocument, charSet, csNameTag); | |
| 799 } | |
| 800 CPDF_Font* CPDF_InterForm::GetNativeFormFont(CFX_ByteString& csNameTag) { | |
| 801 return GetNativeInterFormFont(m_pFormDict, m_pDocument, csNameTag); | |
| 802 } | |
| 803 FX_BOOL CPDF_InterForm::FindFormFont(const CPDF_Font* pFont, | |
| 804 CFX_ByteString& csNameTag) { | |
| 805 return FindInterFormFont(m_pFormDict, pFont, csNameTag); | |
| 806 } | |
| 807 FX_BOOL CPDF_InterForm::FindFormFont(CFX_ByteString csFontName, | |
| 808 CPDF_Font*& pFont, | |
| 809 CFX_ByteString& csNameTag) { | |
| 810 return FindInterFormFont(m_pFormDict, m_pDocument, csFontName, pFont, | |
| 811 csNameTag); | |
| 812 } | |
| 813 void CPDF_InterForm::AddFormFont(const CPDF_Font* pFont, | |
| 814 CFX_ByteString& csNameTag) { | |
| 815 AddInterFormFont(m_pFormDict, m_pDocument, pFont, csNameTag); | |
| 816 } | |
| 817 | |
| 818 CPDF_Font* CPDF_InterForm::AddNativeFormFont(uint8_t charSet, | |
| 819 CFX_ByteString& csNameTag) { | |
| 820 return AddNativeInterFormFont(m_pFormDict, m_pDocument, charSet, csNameTag); | |
| 821 } | |
| 822 | |
| 823 CPDF_Font* CPDF_InterForm::AddNativeFormFont(CFX_ByteString& csNameTag) { | |
| 824 return AddNativeInterFormFont(m_pFormDict, m_pDocument, csNameTag); | |
| 825 } | |
| 826 | |
| 827 void CPDF_InterForm::RemoveFormFont(const CPDF_Font* pFont) { | |
| 828 RemoveInterFormFont(m_pFormDict, pFont); | |
| 829 } | |
| 830 | |
| 831 void CPDF_InterForm::RemoveFormFont(CFX_ByteString csNameTag) { | |
| 832 RemoveInterFormFont(m_pFormDict, csNameTag); | |
| 833 } | |
| 834 | |
| 835 CPDF_DefaultAppearance CPDF_InterForm::GetDefaultAppearance() { | |
| 836 if (!m_pFormDict) | |
| 837 return CPDF_DefaultAppearance(); | |
| 838 return CPDF_DefaultAppearance(m_pFormDict->GetStringBy("DA")); | |
| 839 } | |
| 840 | |
| 841 CPDF_Font* CPDF_InterForm::GetDefaultFormFont() { | |
| 842 return GetDefaultInterFormFont(m_pFormDict, m_pDocument); | |
| 843 } | |
| 844 int CPDF_InterForm::GetFormAlignment() { | |
| 845 return m_pFormDict ? m_pFormDict->GetIntegerBy("Q", 0) : 0; | |
| 846 } | |
| 847 | |
| 848 bool CPDF_InterForm::ResetForm(const std::vector<CPDF_FormField*>& fields, | |
| 849 bool bIncludeOrExclude, | |
| 850 bool bNotify) { | |
| 851 if (bNotify && m_pFormNotify && m_pFormNotify->BeforeFormReset(this) < 0) | |
| 852 return false; | |
| 853 | |
| 854 int nCount = m_pFieldTree->m_Root.CountFields(); | |
| 855 for (int i = 0; i < nCount; ++i) { | |
| 856 CPDF_FormField* pField = m_pFieldTree->m_Root.GetField(i); | |
| 857 if (!pField) | |
| 858 continue; | |
| 859 | |
| 860 if (bIncludeOrExclude == pdfium::ContainsValue(fields, pField)) | |
| 861 pField->ResetField(bNotify); | |
| 862 } | |
| 863 if (bNotify && m_pFormNotify) | |
| 864 m_pFormNotify->AfterFormReset(this); | |
| 865 return true; | |
| 866 } | |
| 867 | |
| 868 bool CPDF_InterForm::ResetForm(bool bNotify) { | |
| 869 if (bNotify && m_pFormNotify && m_pFormNotify->BeforeFormReset(this) < 0) | |
| 870 return false; | |
| 871 | |
| 872 int nCount = m_pFieldTree->m_Root.CountFields(); | |
| 873 for (int i = 0; i < nCount; ++i) { | |
| 874 CPDF_FormField* pField = m_pFieldTree->m_Root.GetField(i); | |
| 875 if (!pField) | |
| 876 continue; | |
| 877 | |
| 878 pField->ResetField(bNotify); | |
| 879 } | |
| 880 if (bNotify && m_pFormNotify) | |
| 881 m_pFormNotify->AfterFormReset(this); | |
| 882 return true; | |
| 883 } | |
| 884 | |
| 885 void CPDF_InterForm::LoadField(CPDF_Dictionary* pFieldDict, int nLevel) { | |
| 886 if (nLevel > nMaxRecursion) { | |
| 887 return; | |
| 888 } | |
| 889 if (!pFieldDict) { | |
| 890 return; | |
| 891 } | |
| 892 uint32_t dwParentObjNum = pFieldDict->GetObjNum(); | |
| 893 CPDF_Array* pKids = pFieldDict->GetArrayBy("Kids"); | |
| 894 if (!pKids) { | |
| 895 AddTerminalField(pFieldDict); | |
| 896 return; | |
| 897 } | |
| 898 CPDF_Dictionary* pFirstKid = pKids->GetDictAt(0); | |
| 899 if (!pFirstKid) { | |
| 900 return; | |
| 901 } | |
| 902 if (pFirstKid->KeyExist("T") || pFirstKid->KeyExist("Kids")) { | |
| 903 for (size_t i = 0; i < pKids->GetCount(); i++) { | |
| 904 CPDF_Dictionary* pChildDict = pKids->GetDictAt(i); | |
| 905 if (pChildDict) { | |
| 906 if (pChildDict->GetObjNum() != dwParentObjNum) { | |
| 907 LoadField(pChildDict, nLevel + 1); | |
| 908 } | |
| 909 } | |
| 910 } | |
| 911 } else { | |
| 912 AddTerminalField(pFieldDict); | |
| 913 } | |
| 914 } | |
| 915 FX_BOOL CPDF_InterForm::HasXFAForm() const { | |
| 916 return m_pFormDict && m_pFormDict->GetArrayBy("XFA"); | |
| 917 } | |
| 918 void CPDF_InterForm::FixPageFields(const CPDF_Page* pPage) { | |
| 919 CPDF_Dictionary* pPageDict = pPage->m_pFormDict; | |
| 920 if (!pPageDict) { | |
| 921 return; | |
| 922 } | |
| 923 CPDF_Array* pAnnots = pPageDict->GetArrayBy("Annots"); | |
| 924 if (!pAnnots) { | |
| 925 return; | |
| 926 } | |
| 927 for (size_t i = 0; i < pAnnots->GetCount(); i++) { | |
| 928 CPDF_Dictionary* pAnnot = pAnnots->GetDictAt(i); | |
| 929 if (pAnnot && pAnnot->GetStringBy("Subtype") == "Widget") { | |
| 930 LoadField(pAnnot); | |
| 931 } | |
| 932 } | |
| 933 } | |
| 934 CPDF_FormField* CPDF_InterForm::AddTerminalField(CPDF_Dictionary* pFieldDict) { | |
| 935 if (!pFieldDict->KeyExist("T")) { | |
| 936 return nullptr; | |
| 937 } | |
| 938 CPDF_Dictionary* pDict = pFieldDict; | |
| 939 CFX_WideString csWName = GetFullName(pFieldDict); | |
| 940 if (csWName.IsEmpty()) { | |
| 941 return nullptr; | |
| 942 } | |
| 943 CPDF_FormField* pField = nullptr; | |
| 944 pField = m_pFieldTree->GetField(csWName); | |
| 945 if (!pField) { | |
| 946 CPDF_Dictionary* pParent = pFieldDict; | |
| 947 if (!pFieldDict->KeyExist("T") && | |
| 948 pFieldDict->GetStringBy("Subtype") == "Widget") { | |
| 949 pParent = pFieldDict->GetDictBy("Parent"); | |
| 950 if (!pParent) { | |
| 951 pParent = pFieldDict; | |
| 952 } | |
| 953 } | |
| 954 if (pParent && pParent != pFieldDict && !pParent->KeyExist("FT")) { | |
| 955 if (pFieldDict->KeyExist("FT")) { | |
| 956 CPDF_Object* pFTValue = pFieldDict->GetDirectObjectBy("FT"); | |
| 957 if (pFTValue) { | |
| 958 pParent->SetAt("FT", pFTValue->Clone()); | |
| 959 } | |
| 960 } | |
| 961 if (pFieldDict->KeyExist("Ff")) { | |
| 962 CPDF_Object* pFfValue = pFieldDict->GetDirectObjectBy("Ff"); | |
| 963 if (pFfValue) { | |
| 964 pParent->SetAt("Ff", pFfValue->Clone()); | |
| 965 } | |
| 966 } | |
| 967 } | |
| 968 pField = new CPDF_FormField(this, pParent); | |
| 969 CPDF_Object* pTObj = pDict->GetObjectBy("T"); | |
| 970 if (ToReference(pTObj)) { | |
| 971 CPDF_Object* pClone = pTObj->Clone(TRUE); | |
| 972 if (pClone) | |
| 973 pDict->SetAt("T", pClone); | |
| 974 else | |
| 975 pDict->SetAtName("T", ""); | |
| 976 } | |
| 977 m_pFieldTree->SetField(csWName, pField); | |
| 978 } | |
| 979 CPDF_Array* pKids = pFieldDict->GetArrayBy("Kids"); | |
| 980 if (!pKids) { | |
| 981 if (pFieldDict->GetStringBy("Subtype") == "Widget") { | |
| 982 AddControl(pField, pFieldDict); | |
| 983 } | |
| 984 } else { | |
| 985 for (size_t i = 0; i < pKids->GetCount(); i++) { | |
| 986 CPDF_Dictionary* pKid = pKids->GetDictAt(i); | |
| 987 if (!pKid) { | |
| 988 continue; | |
| 989 } | |
| 990 if (pKid->GetStringBy("Subtype") != "Widget") { | |
| 991 continue; | |
| 992 } | |
| 993 AddControl(pField, pKid); | |
| 994 } | |
| 995 } | |
| 996 return pField; | |
| 997 } | |
| 998 CPDF_FormControl* CPDF_InterForm::AddControl(CPDF_FormField* pField, | |
| 999 CPDF_Dictionary* pWidgetDict) { | |
| 1000 const auto it = m_ControlMap.find(pWidgetDict); | |
| 1001 if (it != m_ControlMap.end()) | |
| 1002 return it->second; | |
| 1003 | |
| 1004 CPDF_FormControl* pControl = new CPDF_FormControl(pField, pWidgetDict); | |
| 1005 m_ControlMap[pWidgetDict] = pControl; | |
| 1006 pField->m_ControlList.Add(pControl); | |
| 1007 return pControl; | |
| 1008 } | |
| 1009 | |
| 1010 CPDF_FormField* CPDF_InterForm::CheckRequiredFields( | |
| 1011 const std::vector<CPDF_FormField*>* fields, | |
| 1012 bool bIncludeOrExclude) const { | |
| 1013 int nCount = m_pFieldTree->m_Root.CountFields(); | |
| 1014 for (int i = 0; i < nCount; ++i) { | |
| 1015 CPDF_FormField* pField = m_pFieldTree->m_Root.GetField(i); | |
| 1016 if (!pField) | |
| 1017 continue; | |
| 1018 | |
| 1019 int32_t iType = pField->GetType(); | |
| 1020 if (iType == CPDF_FormField::PushButton || | |
| 1021 iType == CPDF_FormField::CheckBox || iType == CPDF_FormField::ListBox) { | |
| 1022 continue; | |
| 1023 } | |
| 1024 uint32_t dwFlags = pField->GetFieldFlags(); | |
| 1025 // TODO(thestig): Look up these magic numbers and add constants for them. | |
| 1026 if (dwFlags & 0x04) | |
| 1027 continue; | |
| 1028 | |
| 1029 bool bFind = true; | |
| 1030 if (fields) | |
| 1031 bFind = pdfium::ContainsValue(*fields, pField); | |
| 1032 if (bIncludeOrExclude == bFind) { | |
| 1033 CPDF_Dictionary* pFieldDict = pField->m_pDict; | |
| 1034 if ((dwFlags & 0x02) != 0 && pFieldDict->GetStringBy("V").IsEmpty()) { | |
| 1035 return pField; | |
| 1036 } | |
| 1037 } | |
| 1038 } | |
| 1039 return nullptr; | |
| 1040 } | |
| 1041 | |
| 1042 CFDF_Document* CPDF_InterForm::ExportToFDF(const CFX_WideStringC& pdf_path, | |
| 1043 bool bSimpleFileSpec) const { | |
| 1044 std::vector<CPDF_FormField*> fields; | |
| 1045 int nCount = m_pFieldTree->m_Root.CountFields(); | |
| 1046 for (int i = 0; i < nCount; ++i) | |
| 1047 fields.push_back(m_pFieldTree->m_Root.GetField(i)); | |
| 1048 return ExportToFDF(pdf_path, fields, true, bSimpleFileSpec); | |
| 1049 } | |
| 1050 | |
| 1051 CFDF_Document* CPDF_InterForm::ExportToFDF( | |
| 1052 const CFX_WideStringC& pdf_path, | |
| 1053 const std::vector<CPDF_FormField*>& fields, | |
| 1054 bool bIncludeOrExclude, | |
| 1055 bool bSimpleFileSpec) const { | |
| 1056 CFDF_Document* pDoc = CFDF_Document::CreateNewDoc(); | |
| 1057 if (!pDoc) { | |
| 1058 return nullptr; | |
| 1059 } | |
| 1060 CPDF_Dictionary* pMainDict = pDoc->GetRoot()->GetDictBy("FDF"); | |
| 1061 if (!pdf_path.IsEmpty()) { | |
| 1062 if (bSimpleFileSpec) { | |
| 1063 CFX_WideString wsFilePath = CPDF_FileSpec::EncodeFileName(pdf_path); | |
| 1064 pMainDict->SetAtString("F", CFX_ByteString::FromUnicode(wsFilePath)); | |
| 1065 pMainDict->SetAtString("UF", PDF_EncodeText(wsFilePath)); | |
| 1066 } else { | |
| 1067 CPDF_FileSpec filespec; | |
| 1068 filespec.SetFileName(pdf_path); | |
| 1069 pMainDict->SetAt("F", filespec.GetObj()); | |
| 1070 } | |
| 1071 } | |
| 1072 CPDF_Array* pFields = new CPDF_Array; | |
| 1073 pMainDict->SetAt("Fields", pFields); | |
| 1074 int nCount = m_pFieldTree->m_Root.CountFields(); | |
| 1075 for (int i = 0; i < nCount; i++) { | |
| 1076 CPDF_FormField* pField = m_pFieldTree->m_Root.GetField(i); | |
| 1077 if (!pField || pField->GetType() == CPDF_FormField::PushButton) { | |
| 1078 continue; | |
| 1079 } | |
| 1080 uint32_t dwFlags = pField->GetFieldFlags(); | |
| 1081 if (dwFlags & 0x04) | |
| 1082 continue; | |
| 1083 | |
| 1084 if (bIncludeOrExclude == pdfium::ContainsValue(fields, pField)) { | |
| 1085 if ((dwFlags & 0x02) != 0 && pField->m_pDict->GetStringBy("V").IsEmpty()) | |
| 1086 continue; | |
| 1087 | |
| 1088 CFX_WideString fullname = GetFullName(pField->GetFieldDict()); | |
| 1089 CPDF_Dictionary* pFieldDict = new CPDF_Dictionary; | |
| 1090 pFieldDict->SetAt("T", new CPDF_String(fullname)); | |
| 1091 if (pField->GetType() == CPDF_FormField::CheckBox || | |
| 1092 pField->GetType() == CPDF_FormField::RadioButton) { | |
| 1093 CFX_WideString csExport = pField->GetCheckValue(FALSE); | |
| 1094 CFX_ByteString csBExport = PDF_EncodeText(csExport); | |
| 1095 CPDF_Object* pOpt = FPDF_GetFieldAttr(pField->m_pDict, "Opt"); | |
| 1096 if (pOpt) | |
| 1097 pFieldDict->SetAtString("V", csBExport); | |
| 1098 else | |
| 1099 pFieldDict->SetAtName("V", csBExport); | |
| 1100 } else { | |
| 1101 CPDF_Object* pV = FPDF_GetFieldAttr(pField->m_pDict, "V"); | |
| 1102 if (pV) | |
| 1103 pFieldDict->SetAt("V", pV->Clone(TRUE)); | |
| 1104 } | |
| 1105 pFields->Add(pFieldDict); | |
| 1106 } | |
| 1107 } | |
| 1108 return pDoc; | |
| 1109 } | |
| 1110 | |
| 1111 void CPDF_InterForm::FDF_ImportField(CPDF_Dictionary* pFieldDict, | |
| 1112 const CFX_WideString& parent_name, | |
| 1113 FX_BOOL bNotify, | |
| 1114 int nLevel) { | |
| 1115 CFX_WideString name; | |
| 1116 if (!parent_name.IsEmpty()) { | |
| 1117 name = parent_name + L"."; | |
| 1118 } | |
| 1119 name += pFieldDict->GetUnicodeTextBy("T"); | |
| 1120 CPDF_Array* pKids = pFieldDict->GetArrayBy("Kids"); | |
| 1121 if (pKids) { | |
| 1122 for (size_t i = 0; i < pKids->GetCount(); i++) { | |
| 1123 CPDF_Dictionary* pKid = pKids->GetDictAt(i); | |
| 1124 if (!pKid) { | |
| 1125 continue; | |
| 1126 } | |
| 1127 if (nLevel <= nMaxRecursion) { | |
| 1128 FDF_ImportField(pKid, name, bNotify, nLevel + 1); | |
| 1129 } | |
| 1130 } | |
| 1131 return; | |
| 1132 } | |
| 1133 if (!pFieldDict->KeyExist("V")) { | |
| 1134 return; | |
| 1135 } | |
| 1136 CPDF_FormField* pField = m_pFieldTree->GetField(name); | |
| 1137 if (!pField) { | |
| 1138 return; | |
| 1139 } | |
| 1140 CFX_WideString csWValue = | |
| 1141 FPDFDOC_FDF_GetFieldValue(*pFieldDict, m_bsEncoding); | |
| 1142 int iType = pField->GetFieldType(); | |
| 1143 if (bNotify && m_pFormNotify) { | |
| 1144 int iRet = 0; | |
| 1145 if (iType == FIELDTYPE_LISTBOX) { | |
| 1146 iRet = m_pFormNotify->BeforeSelectionChange(pField, csWValue); | |
| 1147 } else if (iType == FIELDTYPE_COMBOBOX || iType == FIELDTYPE_TEXTFIELD) { | |
| 1148 iRet = m_pFormNotify->BeforeValueChange(pField, csWValue); | |
| 1149 } | |
| 1150 if (iRet < 0) { | |
| 1151 return; | |
| 1152 } | |
| 1153 } | |
| 1154 pField->SetValue(csWValue); | |
| 1155 CPDF_FormField::Type eType = pField->GetType(); | |
| 1156 if ((eType == CPDF_FormField::ListBox || eType == CPDF_FormField::ComboBox) && | |
| 1157 pFieldDict->KeyExist("Opt")) { | |
| 1158 pField->m_pDict->SetAt("Opt", | |
| 1159 pFieldDict->GetDirectObjectBy("Opt")->Clone(TRUE)); | |
| 1160 } | |
| 1161 if (bNotify && m_pFormNotify) { | |
| 1162 if (iType == FIELDTYPE_CHECKBOX || iType == FIELDTYPE_RADIOBUTTON) { | |
| 1163 m_pFormNotify->AfterCheckedStatusChange(pField); | |
| 1164 } else if (iType == FIELDTYPE_LISTBOX) { | |
| 1165 m_pFormNotify->AfterSelectionChange(pField); | |
| 1166 } else if (iType == FIELDTYPE_COMBOBOX || iType == FIELDTYPE_TEXTFIELD) { | |
| 1167 m_pFormNotify->AfterValueChange(pField); | |
| 1168 } | |
| 1169 } | |
| 1170 } | |
| 1171 | |
| 1172 FX_BOOL CPDF_InterForm::ImportFromFDF(const CFDF_Document* pFDF, | |
| 1173 FX_BOOL bNotify) { | |
| 1174 if (!pFDF) | |
| 1175 return FALSE; | |
| 1176 | |
| 1177 CPDF_Dictionary* pMainDict = pFDF->GetRoot()->GetDictBy("FDF"); | |
| 1178 if (!pMainDict) | |
| 1179 return FALSE; | |
| 1180 | |
| 1181 CPDF_Array* pFields = pMainDict->GetArrayBy("Fields"); | |
| 1182 if (!pFields) | |
| 1183 return FALSE; | |
| 1184 | |
| 1185 m_bsEncoding = pMainDict->GetStringBy("Encoding"); | |
| 1186 if (bNotify && m_pFormNotify && m_pFormNotify->BeforeFormImportData(this) < 0) | |
| 1187 return FALSE; | |
| 1188 | |
| 1189 for (size_t i = 0; i < pFields->GetCount(); i++) { | |
| 1190 CPDF_Dictionary* pField = pFields->GetDictAt(i); | |
| 1191 if (!pField) | |
| 1192 continue; | |
| 1193 | |
| 1194 FDF_ImportField(pField, L"", bNotify); | |
| 1195 } | |
| 1196 if (bNotify && m_pFormNotify) | |
| 1197 m_pFormNotify->AfterFormImportData(this); | |
| 1198 return TRUE; | |
| 1199 } | |
| 1200 | |
| 1201 void CPDF_InterForm::SetFormNotify(IPDF_FormNotify* pNotify) { | |
| 1202 m_pFormNotify = pNotify; | |
| 1203 } | |
| OLD | NEW |