OLD | NEW |
---|---|
1 // Copyright 2014 PDFium Authors. All rights reserved. | 1 // Copyright 2014 PDFium Authors. All rights reserved. |
2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 // Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com | 5 // Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com |
6 | 6 |
7 #include "../../include/fpdfdoc/fpdf_doc.h" | 7 #include "../../include/fpdfdoc/fpdf_doc.h" |
8 #include "doc_utils.h" | 8 #include "doc_utils.h" |
9 | 9 |
10 const int nMaxRecursion = 32; | 10 const int nMaxRecursion = 32; |
(...skipping 235 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
246 } | 246 } |
247 CPDF_Array* pFields = m_pFormDict->GetArray("Fields"); | 247 CPDF_Array* pFields = m_pFormDict->GetArray("Fields"); |
248 if (pFields == NULL) { | 248 if (pFields == NULL) { |
249 return; | 249 return; |
250 } | 250 } |
251 int count = pFields->GetCount(); | 251 int count = pFields->GetCount(); |
252 for (int i = 0; i < count; i++) { | 252 for (int i = 0; i < count; i++) { |
253 LoadField(pFields->GetDict(i)); | 253 LoadField(pFields->GetDict(i)); |
254 } | 254 } |
255 } | 255 } |
256 | |
256 CPDF_InterForm::~CPDF_InterForm() { | 257 CPDF_InterForm::~CPDF_InterForm() { |
257 FX_POSITION pos = m_ControlMap.GetStartPosition(); | 258 for (auto it : m_ControlMap) |
258 while (pos) { | 259 delete it.second; |
259 void* key; | 260 if (m_pFieldTree) { |
260 void* value; | |
261 m_ControlMap.GetNextAssoc(pos, key, value); | |
262 delete (CPDF_FormControl*)value; | |
263 } | |
264 if (m_pFieldTree != NULL) { | |
265 int nCount = m_pFieldTree->m_Root.CountFields(); | 261 int nCount = m_pFieldTree->m_Root.CountFields(); |
266 for (int i = 0; i < nCount; i++) { | 262 for (int i = 0; i < nCount; ++i) { |
267 CPDF_FormField* pField = m_pFieldTree->m_Root.GetField(i); | 263 delete m_pFieldTree->m_Root.GetField(i); |
268 delete pField; | |
269 } | 264 } |
270 delete m_pFieldTree; | 265 delete m_pFieldTree; |
Tom Sepez
2015/08/11 17:25:00
nit: maybe unique_ptr to tree itself?
| |
271 } | 266 } |
272 } | 267 } |
268 | |
273 FX_BOOL CPDF_InterForm::m_bUpdateAP = TRUE; | 269 FX_BOOL CPDF_InterForm::m_bUpdateAP = TRUE; |
274 FX_BOOL CPDF_InterForm::UpdatingAPEnabled() { | 270 FX_BOOL CPDF_InterForm::UpdatingAPEnabled() { |
275 return m_bUpdateAP; | 271 return m_bUpdateAP; |
276 } | 272 } |
277 void CPDF_InterForm::EnableUpdateAP(FX_BOOL bUpdateAP) { | 273 void CPDF_InterForm::EnableUpdateAP(FX_BOOL bUpdateAP) { |
278 m_bUpdateAP = bUpdateAP; | 274 m_bUpdateAP = bUpdateAP; |
279 } | 275 } |
280 CFX_ByteString CPDF_InterForm::GenerateNewResourceName( | 276 CFX_ByteString CPDF_InterForm::GenerateNewResourceName( |
281 const CPDF_Dictionary* pResDict, | 277 const CPDF_Dictionary* pResDict, |
282 const FX_CHAR* csType, | 278 const FX_CHAR* csType, |
(...skipping 498 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
781 return FALSE; | 777 return FALSE; |
782 } | 778 } |
783 CPDF_FormField* CPDF_InterForm::GetFieldByDict( | 779 CPDF_FormField* CPDF_InterForm::GetFieldByDict( |
784 CPDF_Dictionary* pFieldDict) const { | 780 CPDF_Dictionary* pFieldDict) const { |
785 if (pFieldDict == NULL) { | 781 if (pFieldDict == NULL) { |
786 return NULL; | 782 return NULL; |
787 } | 783 } |
788 CFX_WideString csWName = GetFullName(pFieldDict); | 784 CFX_WideString csWName = GetFullName(pFieldDict); |
789 return m_pFieldTree->GetField(csWName); | 785 return m_pFieldTree->GetField(csWName); |
790 } | 786 } |
791 FX_DWORD CPDF_InterForm::CountControls(CFX_WideString csFieldName) { | 787 |
792 if (csFieldName.IsEmpty()) { | |
793 return (FX_DWORD)m_ControlMap.GetCount(); | |
794 } | |
795 CPDF_FormField* pField = m_pFieldTree->GetField(csFieldName); | |
796 if (pField == NULL) { | |
797 return 0; | |
798 } | |
799 return pField->m_ControlList.GetSize(); | |
800 } | |
801 CPDF_FormControl* CPDF_InterForm::GetControl(FX_DWORD index, | |
802 CFX_WideString csFieldName) { | |
803 CPDF_FormField* pField = m_pFieldTree->GetField(csFieldName); | |
804 if (pField == NULL) { | |
805 return NULL; | |
806 } | |
807 if (index < (FX_DWORD)pField->m_ControlList.GetSize()) { | |
808 return (CPDF_FormControl*)pField->m_ControlList.GetAt(index); | |
809 } | |
810 return NULL; | |
811 } | |
812 FX_BOOL CPDF_InterForm::IsValidFormControl(const void* pControl) { | |
813 if (pControl == NULL) { | |
814 return FALSE; | |
815 } | |
816 FX_POSITION pos = m_ControlMap.GetStartPosition(); | |
817 while (pos) { | |
818 CPDF_Dictionary* pWidgetDict = NULL; | |
819 void* pFormControl = NULL; | |
820 m_ControlMap.GetNextAssoc(pos, (void*&)pWidgetDict, pFormControl); | |
821 if (pControl == pFormControl) { | |
822 return TRUE; | |
823 } | |
824 } | |
825 return FALSE; | |
826 } | |
827 int CPDF_InterForm::CountPageControls(CPDF_Page* pPage) const { | |
828 CPDF_Array* pAnnotList = pPage->m_pFormDict->GetArray("Annots"); | |
829 if (pAnnotList == NULL) { | |
830 return 0; | |
831 } | |
832 int count = 0; | |
833 for (FX_DWORD i = 0; i < pAnnotList->GetCount(); i++) { | |
834 CPDF_Dictionary* pAnnot = pAnnotList->GetDict(i); | |
835 if (pAnnot == NULL) { | |
836 continue; | |
837 } | |
838 CPDF_FormControl* pControl; | |
839 if (!m_ControlMap.Lookup(pAnnot, (void*&)pControl)) { | |
840 continue; | |
841 } | |
842 count++; | |
843 } | |
844 return count; | |
845 } | |
846 CPDF_FormControl* CPDF_InterForm::GetPageControl(CPDF_Page* pPage, | |
847 int index) const { | |
848 CPDF_Array* pAnnotList = pPage->m_pFormDict->GetArray("Annots"); | |
849 if (pAnnotList == NULL) { | |
850 return NULL; | |
851 } | |
852 int count = 0; | |
853 for (FX_DWORD i = 0; i < pAnnotList->GetCount(); i++) { | |
854 CPDF_Dictionary* pAnnot = pAnnotList->GetDict(i); | |
855 if (pAnnot == NULL) { | |
856 continue; | |
857 } | |
858 CPDF_FormControl* pControl; | |
859 if (!m_ControlMap.Lookup(pAnnot, (void*&)pControl)) { | |
860 continue; | |
861 } | |
862 if (index == count) { | |
863 return pControl; | |
864 } | |
865 count++; | |
866 } | |
867 return NULL; | |
868 } | |
869 CPDF_FormControl* CPDF_InterForm::GetControlAtPoint(CPDF_Page* pPage, | 788 CPDF_FormControl* CPDF_InterForm::GetControlAtPoint(CPDF_Page* pPage, |
870 FX_FLOAT pdf_x, | 789 FX_FLOAT pdf_x, |
871 FX_FLOAT pdf_y) const { | 790 FX_FLOAT pdf_y, |
791 int* z_order) const { | |
872 CPDF_Array* pAnnotList = pPage->m_pFormDict->GetArray("Annots"); | 792 CPDF_Array* pAnnotList = pPage->m_pFormDict->GetArray("Annots"); |
873 if (pAnnotList == NULL) { | 793 if (!pAnnotList) |
874 return NULL; | 794 return nullptr; |
795 | |
796 for (FX_DWORD i = pAnnotList->GetCount(); i > 0; --i) { | |
797 FX_DWORD annot_index = i - 1; | |
798 CPDF_Dictionary* pAnnot = pAnnotList->GetDict(annot_index); | |
799 if (!pAnnot) | |
800 continue; | |
801 | |
802 const auto it = m_ControlMap.find(pAnnot); | |
803 if (it == m_ControlMap.end()) | |
804 continue; | |
805 | |
806 CPDF_FormControl* pControl = it->second; | |
807 CFX_FloatRect rect = pControl->GetRect(); | |
808 if (!rect.Contains(pdf_x, pdf_y)) | |
809 continue; | |
810 | |
811 if (z_order) | |
812 *z_order = annot_index; | |
813 return pControl; | |
875 } | 814 } |
876 for (FX_DWORD i = pAnnotList->GetCount(); i > 0; i--) { | 815 return nullptr; |
877 CPDF_Dictionary* pAnnot = pAnnotList->GetDict(i - 1); | |
878 if (pAnnot == NULL) { | |
879 continue; | |
880 } | |
881 CPDF_FormControl* pControl; | |
882 if (!m_ControlMap.Lookup(pAnnot, (void*&)pControl)) { | |
883 continue; | |
884 } | |
885 CFX_FloatRect rect = pControl->GetRect(); | |
886 if (rect.Contains(pdf_x, pdf_y)) { | |
887 return pControl; | |
888 } | |
889 } | |
890 return NULL; | |
891 } | 816 } |
817 | |
892 CPDF_FormControl* CPDF_InterForm::GetControlByDict( | 818 CPDF_FormControl* CPDF_InterForm::GetControlByDict( |
893 CPDF_Dictionary* pWidgetDict) const { | 819 CPDF_Dictionary* pWidgetDict) const { |
894 CPDF_FormControl* pControl = NULL; | 820 const auto it = m_ControlMap.find(pWidgetDict); |
895 m_ControlMap.Lookup(pWidgetDict, (void*&)pControl); | 821 return it != m_ControlMap.end() ? it->second : nullptr; |
896 return pControl; | |
897 } | |
898 FX_DWORD CPDF_InterForm::CountInternalFields( | |
899 const CFX_WideString& csFieldName) const { | |
900 if (!m_pFormDict) { | |
901 return 0; | |
902 } | |
903 CPDF_Array* pArray = m_pFormDict->GetArray("Fields"); | |
904 if (!pArray) { | |
905 return 0; | |
906 } | |
907 if (csFieldName.IsEmpty()) { | |
908 return pArray->GetCount(); | |
909 } | |
910 int iLength = csFieldName.GetLength(); | |
911 int iPos = 0; | |
912 CPDF_Dictionary* pDict = NULL; | |
913 while (pArray != NULL) { | |
914 CFX_WideString csSub; | |
915 if (iPos < iLength && csFieldName[iPos] == L'.') { | |
916 iPos++; | |
917 } | |
918 while (iPos < iLength && csFieldName[iPos] != L'.') { | |
919 csSub += csFieldName[iPos++]; | |
920 } | |
921 int iCount = pArray->GetCount(); | |
922 FX_BOOL bFind = FALSE; | |
923 for (int i = 0; i < iCount; i++) { | |
924 pDict = pArray->GetDict(i); | |
925 if (pDict == NULL) { | |
926 continue; | |
927 } | |
928 CFX_WideString csT = pDict->GetUnicodeText("T"); | |
929 if (csT == csSub) { | |
930 bFind = TRUE; | |
931 break; | |
932 } | |
933 } | |
934 if (!bFind) { | |
935 return 0; | |
936 } | |
937 if (iPos >= iLength) { | |
938 break; | |
939 } | |
940 pArray = pDict->GetArray("Kids"); | |
941 } | |
942 if (!pDict) { | |
943 return 0; | |
944 } | |
945 pArray = pDict->GetArray("Kids"); | |
946 return pArray ? pArray->GetCount() : 1; | |
947 } | 822 } |
948 | 823 |
949 CPDF_Dictionary* CPDF_InterForm::GetInternalField( | |
950 FX_DWORD index, | |
951 const CFX_WideString& csFieldName) const { | |
952 if (!m_pFormDict) { | |
953 return nullptr; | |
954 } | |
955 CPDF_Array* pArray = m_pFormDict->GetArray("Fields"); | |
956 if (!pArray) { | |
957 return nullptr; | |
958 } | |
959 if (csFieldName.IsEmpty()) { | |
960 return pArray->GetDict(index); | |
961 } | |
962 int iLength = csFieldName.GetLength(); | |
963 int iPos = 0; | |
964 CPDF_Dictionary* pDict = NULL; | |
965 while (pArray != NULL) { | |
966 CFX_WideString csSub; | |
967 if (iPos < iLength && csFieldName[iPos] == L'.') { | |
968 iPos++; | |
969 } | |
970 while (iPos < iLength && csFieldName[iPos] != L'.') { | |
971 csSub += csFieldName[iPos++]; | |
972 } | |
973 int iCount = pArray->GetCount(); | |
974 FX_BOOL bFind = FALSE; | |
975 for (int i = 0; i < iCount; i++) { | |
976 pDict = pArray->GetDict(i); | |
977 if (pDict == NULL) { | |
978 continue; | |
979 } | |
980 CFX_WideString csT = pDict->GetUnicodeText("T"); | |
981 if (csT == csSub) { | |
982 bFind = TRUE; | |
983 break; | |
984 } | |
985 } | |
986 if (!bFind) { | |
987 return NULL; | |
988 } | |
989 if (iPos >= iLength) { | |
990 break; | |
991 } | |
992 pArray = pDict->GetArray("Kids"); | |
993 } | |
994 if (!pDict) { | |
995 return nullptr; | |
996 } | |
997 pArray = pDict->GetArray("Kids"); | |
998 return pArray ? pArray->GetDict(index) : pDict; | |
999 } | |
1000 FX_BOOL CPDF_InterForm::NeedConstructAP() { | 824 FX_BOOL CPDF_InterForm::NeedConstructAP() { |
1001 if (m_pFormDict == NULL) { | 825 if (m_pFormDict == NULL) { |
1002 return FALSE; | 826 return FALSE; |
1003 } | 827 } |
1004 return m_pFormDict->GetBoolean("NeedAppearances"); | 828 return m_pFormDict->GetBoolean("NeedAppearances"); |
1005 } | 829 } |
1006 void CPDF_InterForm::NeedConstructAP(FX_BOOL bNeedAP) { | 830 void CPDF_InterForm::NeedConstructAP(FX_BOOL bNeedAP) { |
1007 if (m_pFormDict == NULL) { | 831 if (m_pFormDict == NULL) { |
1008 InitInterFormDict(m_pFormDict, m_pDocument); | 832 InitInterFormDict(m_pFormDict, m_pDocument); |
1009 } | 833 } |
(...skipping 155 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1165 if (pField == NULL) { | 989 if (pField == NULL) { |
1166 continue; | 990 continue; |
1167 } | 991 } |
1168 pField->ResetField(bNotify); | 992 pField->ResetField(bNotify); |
1169 } | 993 } |
1170 if (bNotify && m_pFormNotify != NULL) { | 994 if (bNotify && m_pFormNotify != NULL) { |
1171 m_pFormNotify->AfterFormReset(this); | 995 m_pFormNotify->AfterFormReset(this); |
1172 } | 996 } |
1173 return TRUE; | 997 return TRUE; |
1174 } | 998 } |
1175 void CPDF_InterForm::ReloadForm() { | |
1176 FX_POSITION pos = m_ControlMap.GetStartPosition(); | |
1177 while (pos) { | |
1178 CPDF_Dictionary* pWidgetDict; | |
1179 CPDF_FormControl* pControl; | |
1180 m_ControlMap.GetNextAssoc(pos, (void*&)pWidgetDict, (void*&)pControl); | |
1181 delete pControl; | |
1182 } | |
1183 m_ControlMap.RemoveAll(); | |
1184 int nCount = m_pFieldTree->m_Root.CountFields(); | |
1185 for (int k = 0; k < nCount; k++) { | |
1186 CPDF_FormField* pField = m_pFieldTree->m_Root.GetField(k); | |
1187 delete pField; | |
1188 } | |
1189 m_pFieldTree->RemoveAll(); | |
1190 if (m_pFormDict == NULL) { | |
1191 return; | |
1192 } | |
1193 CPDF_Array* pFields = m_pFormDict->GetArray("Fields"); | |
1194 if (pFields == NULL) { | |
1195 return; | |
1196 } | |
1197 int iCount = pFields->GetCount(); | |
1198 for (int i = 0; i < iCount; i++) { | |
1199 LoadField(pFields->GetDict(i)); | |
1200 } | |
1201 } | |
1202 void CPDF_InterForm::LoadField(CPDF_Dictionary* pFieldDict, int nLevel) { | 999 void CPDF_InterForm::LoadField(CPDF_Dictionary* pFieldDict, int nLevel) { |
1203 if (nLevel > nMaxRecursion) { | 1000 if (nLevel > nMaxRecursion) { |
1204 return; | 1001 return; |
1205 } | 1002 } |
1206 if (pFieldDict == NULL) { | 1003 if (pFieldDict == NULL) { |
1207 return; | 1004 return; |
1208 } | 1005 } |
1209 FX_DWORD dwParentObjNum = pFieldDict->GetObjNum(); | 1006 FX_DWORD dwParentObjNum = pFieldDict->GetObjNum(); |
1210 CPDF_Array* pKids = pFieldDict->GetArray("Kids"); | 1007 CPDF_Array* pKids = pFieldDict->GetArray("Kids"); |
1211 if (!pKids) { | 1008 if (!pKids) { |
(...skipping 101 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1313 continue; | 1110 continue; |
1314 } | 1111 } |
1315 AddControl(pField, pKid); | 1112 AddControl(pField, pKid); |
1316 } | 1113 } |
1317 } | 1114 } |
1318 return pField; | 1115 return pField; |
1319 } | 1116 } |
1320 CPDF_FormControl* CPDF_InterForm::AddControl( | 1117 CPDF_FormControl* CPDF_InterForm::AddControl( |
1321 const CPDF_FormField* pField, | 1118 const CPDF_FormField* pField, |
1322 const CPDF_Dictionary* pWidgetDict) { | 1119 const CPDF_Dictionary* pWidgetDict) { |
1323 void* rValue = NULL; | 1120 const auto it = m_ControlMap.find(pWidgetDict); |
1324 if (m_ControlMap.Lookup((CPDF_Dictionary*)pWidgetDict, rValue)) { | 1121 if (it != m_ControlMap.end()) |
1325 return (CPDF_FormControl*)rValue; | 1122 return it->second; |
1326 } | 1123 |
1327 CPDF_FormControl* pControl = new CPDF_FormControl( | 1124 CPDF_FormControl* pControl = new CPDF_FormControl( |
1328 (CPDF_FormField*)pField, (CPDF_Dictionary*)pWidgetDict); | 1125 (CPDF_FormField*)pField, (CPDF_Dictionary*)pWidgetDict); |
Tom Sepez
2015/08/11 17:25:00
nit: not your fault, but maybe these should be con
| |
1329 m_ControlMap.SetAt((CPDF_Dictionary*)pWidgetDict, pControl); | 1126 m_ControlMap[pWidgetDict] = pControl; |
1330 ((CPDF_FormField*)pField)->m_ControlList.Add(pControl); | 1127 ((CPDF_FormField*)pField)->m_ControlList.Add(pControl); |
1331 return pControl; | 1128 return pControl; |
1332 } | 1129 } |
1333 CPDF_FormField* CPDF_InterForm::CheckRequiredFields( | 1130 CPDF_FormField* CPDF_InterForm::CheckRequiredFields( |
1334 const CFX_PtrArray* fields, | 1131 const CFX_PtrArray* fields, |
1335 FX_BOOL bIncludeOrExclude) const { | 1132 FX_BOOL bIncludeOrExclude) const { |
1336 int nCount = m_pFieldTree->m_Root.CountFields(); | 1133 int nCount = m_pFieldTree->m_Root.CountFields(); |
1337 for (int i = 0; i < nCount; i++) { | 1134 for (int i = 0; i < nCount; i++) { |
1338 CPDF_FormField* pField = m_pFieldTree->m_Root.GetField(i); | 1135 CPDF_FormField* pField = m_pFieldTree->m_Root.GetField(i); |
1339 if (pField == NULL) { | 1136 if (pField == NULL) { |
(...skipping 234 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1574 FDF_ImportField(pField, L"", bNotify); | 1371 FDF_ImportField(pField, L"", bNotify); |
1575 } | 1372 } |
1576 if (bNotify && m_pFormNotify != NULL) { | 1373 if (bNotify && m_pFormNotify != NULL) { |
1577 m_pFormNotify->AfterFormImportData(this); | 1374 m_pFormNotify->AfterFormImportData(this); |
1578 } | 1375 } |
1579 return TRUE; | 1376 return TRUE; |
1580 } | 1377 } |
1581 void CPDF_InterForm::SetFormNotify(const CPDF_FormNotify* pNotify) { | 1378 void CPDF_InterForm::SetFormNotify(const CPDF_FormNotify* pNotify) { |
1582 m_pFormNotify = (CPDF_FormNotify*)pNotify; | 1379 m_pFormNotify = (CPDF_FormNotify*)pNotify; |
1583 } | 1380 } |
1584 int CPDF_InterForm::GetPageWithWidget(int iCurPage, FX_BOOL bNext) { | |
1585 if (iCurPage < 0) { | |
1586 return -1; | |
1587 } | |
1588 int iPageCount = m_pDocument->GetPageCount(); | |
1589 if (iCurPage >= iPageCount) { | |
1590 return -1; | |
1591 } | |
1592 int iNewPage = iCurPage; | |
1593 do { | |
1594 iNewPage += bNext ? 1 : -1; | |
1595 if (iNewPage >= iPageCount) { | |
1596 iNewPage = 0; | |
1597 } | |
1598 if (iNewPage < 0) { | |
1599 iNewPage = iPageCount - 1; | |
1600 } | |
1601 if (iNewPage == iCurPage) { | |
1602 break; | |
1603 } | |
1604 CPDF_Dictionary* pPageDict = m_pDocument->GetPage(iNewPage); | |
1605 if (pPageDict == NULL) { | |
1606 continue; | |
1607 } | |
1608 CPDF_Array* pAnnots = pPageDict->GetArray("Annots"); | |
1609 if (pAnnots == NULL) { | |
1610 continue; | |
1611 } | |
1612 FX_DWORD dwCount = pAnnots->GetCount(); | |
1613 for (FX_DWORD i = 0; i < dwCount; i++) { | |
1614 CPDF_Object* pAnnotDict = pAnnots->GetElementValue(i); | |
1615 if (pAnnotDict == NULL) { | |
1616 continue; | |
1617 } | |
1618 CPDF_FormControl* pControl = NULL; | |
1619 if (m_ControlMap.Lookup(pAnnotDict, (void*&)pControl)) { | |
1620 return iNewPage; | |
1621 } | |
1622 } | |
1623 } while (TRUE); | |
1624 return -1; | |
1625 } | |
OLD | NEW |