Use override in more classes in core/
[pdfium.git] / core / src / fpdfdoc / doc_action.cpp
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 CPDF_Dest CPDF_Action::GetDest(CPDF_Document* pDoc) const {
9   if (!m_pDict) {
10     return CPDF_Dest();
11   }
12   CFX_ByteString type = m_pDict->GetString("S");
13   if (type != "GoTo" && type != "GoToR") {
14     return CPDF_Dest();
15   }
16   CPDF_Object* pDest = m_pDict->GetElementValue("D");
17   if (!pDest) {
18     return CPDF_Dest();
19   }
20   if (pDest->GetType() == PDFOBJ_STRING || pDest->GetType() == PDFOBJ_NAME) {
21     CPDF_NameTree name_tree(pDoc, FX_BSTRC("Dests"));
22     CFX_ByteStringC name = pDest->GetString();
23     return CPDF_Dest(name_tree.LookupNamedDest(pDoc, name));
24   }
25   if (pDest->GetType() == PDFOBJ_ARRAY) {
26     return CPDF_Dest((CPDF_Array*)pDest);
27   }
28   return CPDF_Dest();
29 }
30 const FX_CHAR* g_sATypes[] = {
31     "Unknown",     "GoTo",       "GoToR",     "GoToE",      "Launch",
32     "Thread",      "URI",        "Sound",     "Movie",      "Hide",
33     "Named",       "SubmitForm", "ResetForm", "ImportData", "JavaScript",
34     "SetOCGState", "Rendition",  "Trans",     "GoTo3DView", ""};
35 CPDF_Action::ActionType CPDF_Action::GetType() const {
36   ActionType eType = Unknown;
37   if (m_pDict != NULL) {
38     CFX_ByteString csType = m_pDict->GetString("S");
39     if (!csType.IsEmpty()) {
40       int i = 0;
41       while (g_sATypes[i][0] != '\0') {
42         if (csType == g_sATypes[i]) {
43           return (ActionType)i;
44         }
45         i++;
46       }
47     }
48   }
49   return eType;
50 }
51 CFX_WideString CPDF_Action::GetFilePath() const {
52   CFX_ByteString type = m_pDict->GetString("S");
53   if (type != "GoToR" && type != "Launch" && type != "SubmitForm" &&
54       type != "ImportData") {
55     return CFX_WideString();
56   }
57   CPDF_Object* pFile = m_pDict->GetElementValue("F");
58   CFX_WideString path;
59   if (pFile == NULL) {
60     if (type == "Launch") {
61       CPDF_Dictionary* pWinDict = m_pDict->GetDict(FX_BSTRC("Win"));
62       if (pWinDict) {
63         return CFX_WideString::FromLocal(pWinDict->GetString(FX_BSTRC("F")));
64       }
65     }
66     return path;
67   }
68   CPDF_FileSpec filespec(pFile);
69   filespec.GetFileName(path);
70   return path;
71 }
72 CFX_ByteString CPDF_Action::GetURI(CPDF_Document* pDoc) const {
73   CFX_ByteString csURI;
74   if (m_pDict == NULL) {
75     return csURI;
76   }
77   if (m_pDict->GetString("S") != "URI") {
78     return csURI;
79   }
80   csURI = m_pDict->GetString("URI");
81   CPDF_Dictionary* pRoot = pDoc->GetRoot();
82   CPDF_Dictionary* pURI = pRoot->GetDict("URI");
83   if (pURI != NULL) {
84     if (csURI.Find(FX_BSTRC(":"), 0) < 1) {
85       csURI = pURI->GetString("Base") + csURI;
86     }
87   }
88   return csURI;
89 }
90 FX_DWORD CPDF_ActionFields::GetFieldsCount() const {
91   if (m_pAction == NULL) {
92     return 0;
93   }
94   CPDF_Dictionary* pDict = m_pAction->GetDict();
95   if (pDict == NULL) {
96     return 0;
97   }
98   CFX_ByteString csType = pDict->GetString("S");
99   CPDF_Object* pFields = NULL;
100   if (csType == "Hide") {
101     pFields = pDict->GetElementValue("T");
102   } else {
103     pFields = pDict->GetArray("Fields");
104   }
105   if (pFields == NULL) {
106     return 0;
107   }
108   int iType = pFields->GetType();
109   if (iType == PDFOBJ_DICTIONARY) {
110     return 1;
111   }
112   if (iType == PDFOBJ_STRING) {
113     return 1;
114   }
115   if (iType == PDFOBJ_ARRAY) {
116     return ((CPDF_Array*)pFields)->GetCount();
117   }
118   return 0;
119 }
120 void CPDF_ActionFields::GetAllFields(CFX_PtrArray& fieldObjects) const {
121   fieldObjects.RemoveAll();
122   if (m_pAction == NULL) {
123     return;
124   }
125   CPDF_Dictionary* pDict = m_pAction->GetDict();
126   if (pDict == NULL) {
127     return;
128   }
129   CFX_ByteString csType = pDict->GetString("S");
130   CPDF_Object* pFields = NULL;
131   if (csType == "Hide") {
132     pFields = pDict->GetElementValue("T");
133   } else {
134     pFields = pDict->GetArray("Fields");
135   }
136   if (pFields == NULL) {
137     return;
138   }
139   int iType = pFields->GetType();
140   if (iType == PDFOBJ_DICTIONARY || iType == PDFOBJ_STRING) {
141     fieldObjects.Add(pFields);
142   } else if (iType == PDFOBJ_ARRAY) {
143     CPDF_Array* pArray = (CPDF_Array*)pFields;
144     FX_DWORD iCount = pArray->GetCount();
145     for (FX_DWORD i = 0; i < iCount; i++) {
146       CPDF_Object* pObj = pArray->GetElementValue(i);
147       if (pObj != NULL) {
148         fieldObjects.Add(pObj);
149       }
150     }
151   }
152 }
153 CPDF_Object* CPDF_ActionFields::GetField(FX_DWORD iIndex) const {
154   if (m_pAction == NULL) {
155     return NULL;
156   }
157   CPDF_Dictionary* pDict = m_pAction->GetDict();
158   if (pDict == NULL) {
159     return NULL;
160   }
161   CFX_ByteString csType = pDict->GetString("S");
162   CPDF_Object* pFields = NULL;
163   if (csType == "Hide") {
164     pFields = pDict->GetElementValue("T");
165   } else {
166     pFields = pDict->GetArray("Fields");
167   }
168   if (pFields == NULL) {
169     return NULL;
170   }
171   CPDF_Object* pFindObj = NULL;
172   int iType = pFields->GetType();
173   if (iType == PDFOBJ_DICTIONARY || iType == PDFOBJ_STRING) {
174     if (iIndex == 0) {
175       pFindObj = pFields;
176     }
177   } else if (iType == PDFOBJ_ARRAY) {
178     pFindObj = ((CPDF_Array*)pFields)->GetElementValue(iIndex);
179   }
180   return pFindObj;
181 }
182 CPDF_LWinParam CPDF_Action::GetWinParam() const {
183   if (m_pDict == NULL) {
184     return NULL;
185   }
186   if (m_pDict->GetString("S") != "Launch") {
187     return NULL;
188   }
189   return m_pDict->GetDict("Win");
190 }
191 CFX_WideString CPDF_Action::GetJavaScript() const {
192   CFX_WideString csJS;
193   if (m_pDict == NULL) {
194     return csJS;
195   }
196   CPDF_Object* pJS = m_pDict->GetElementValue("JS");
197   if (pJS != NULL) {
198     return pJS->GetUnicodeText();
199   }
200   return csJS;
201 }
202 CPDF_Dictionary* CPDF_Action::GetAnnot() const {
203   if (!m_pDict) {
204     return nullptr;
205   }
206   CFX_ByteString csType = m_pDict->GetString("S");
207   if (csType == FX_BSTRC("Rendition")) {
208     return m_pDict->GetDict("AN");
209   }
210   if (csType == FX_BSTRC("Movie")) {
211     return m_pDict->GetDict("Annotation");
212   }
213   return nullptr;
214 }
215 int32_t CPDF_Action::GetOperationType() const {
216   if (m_pDict == NULL) {
217     return 0;
218   }
219   CFX_ByteString csType = m_pDict->GetString("S");
220   if (csType == FX_BSTRC("Rendition")) {
221     return m_pDict->GetInteger("OP");
222   }
223   if (csType == FX_BSTRC("Movie")) {
224     CFX_ByteString csOP = m_pDict->GetString("Operation");
225     if (csOP == FX_BSTRC("Play")) {
226       return 0;
227     }
228     if (csOP == FX_BSTRC("Stop")) {
229       return 1;
230     }
231     if (csOP == FX_BSTRC("Pause")) {
232       return 2;
233     }
234     if (csOP == FX_BSTRC("Resume")) {
235       return 3;
236     }
237   }
238   return 0;
239 }
240 FX_DWORD CPDF_Action::GetSubActionsCount() const {
241   if (m_pDict == NULL || !m_pDict->KeyExist("Next")) {
242     return 0;
243   }
244   CPDF_Object* pNext = m_pDict->GetElementValue("Next");
245   if (!pNext) {
246     return 0;
247   }
248   int iObjType = pNext->GetType();
249   if (iObjType == PDFOBJ_DICTIONARY) {
250     return 1;
251   }
252   if (iObjType == PDFOBJ_ARRAY) {
253     return ((CPDF_Array*)pNext)->GetCount();
254   }
255   return 0;
256 }
257 CPDF_Action CPDF_Action::GetSubAction(FX_DWORD iIndex) const {
258   if (m_pDict == NULL || !m_pDict->KeyExist("Next")) {
259     return CPDF_Action();
260   }
261   CPDF_Object* pNext = m_pDict->GetElementValue("Next");
262   int iObjType = pNext->GetType();
263   if (iObjType == PDFOBJ_DICTIONARY) {
264     CPDF_Dictionary* pDict = static_cast<CPDF_Dictionary*>(pNext);
265     if (iIndex == 0) {
266       return CPDF_Action(pDict);
267     }
268   } else if (iObjType == PDFOBJ_ARRAY) {
269     CPDF_Array* pArray = static_cast<CPDF_Array*>(pNext);
270     return CPDF_Action(pArray->GetDict(iIndex));
271   }
272   return CPDF_Action();
273 }
274 const FX_CHAR* g_sAATypes[] = {"E",  "X",  "D",  "U",  "Fo", "Bl", "PO", "PC",
275                                "PV", "PI", "O",  "C",  "K",  "F",  "V",  "C",
276                                "WC", "WS", "DS", "WP", "DP", ""};
277 FX_BOOL CPDF_AAction::ActionExist(AActionType eType) const {
278   if (m_pDict == NULL) {
279     return FALSE;
280   }
281   return m_pDict->KeyExist(g_sAATypes[(int)eType]);
282 }
283 CPDF_Action CPDF_AAction::GetAction(AActionType eType) const {
284   if (!m_pDict) {
285     return CPDF_Action();
286   }
287   return CPDF_Action(m_pDict->GetDict(g_sAATypes[(int)eType]));
288 }
289 FX_POSITION CPDF_AAction::GetStartPos() const {
290   if (m_pDict == NULL) {
291     return NULL;
292   }
293   return m_pDict->GetStartPos();
294 }
295 CPDF_Action CPDF_AAction::GetNextAction(FX_POSITION& pos,
296                                         AActionType& eType) const {
297   if (m_pDict == NULL) {
298     return CPDF_Action();
299   }
300   CFX_ByteString csKey;
301   CPDF_Object* pObj = m_pDict->GetNextElement(pos, csKey);
302   if (!pObj) {
303     return CPDF_Action();
304   }
305   CPDF_Object* pDirect = pObj->GetDirect();
306   if (!pDirect || pDirect->GetType() != PDFOBJ_DICTIONARY) {
307     return CPDF_Action();
308   }
309   int i = 0;
310   while (g_sAATypes[i][0] != '\0') {
311     if (csKey == g_sAATypes[i]) {
312       break;
313     }
314     i++;
315   }
316   eType = (AActionType)i;
317   return CPDF_Action(static_cast<CPDF_Dictionary*>(pDirect));
318 }
319 CPDF_DocJSActions::CPDF_DocJSActions(CPDF_Document* pDoc) {
320   m_pDocument = pDoc;
321 }
322 int CPDF_DocJSActions::CountJSActions() const {
323   ASSERT(m_pDocument != NULL);
324   CPDF_NameTree name_tree(m_pDocument, FX_BSTRC("JavaScript"));
325   return name_tree.GetCount();
326 }
327 CPDF_Action CPDF_DocJSActions::GetJSAction(int index,
328                                            CFX_ByteString& csName) const {
329   ASSERT(m_pDocument != NULL);
330   CPDF_NameTree name_tree(m_pDocument, FX_BSTRC("JavaScript"));
331   CPDF_Object* pAction = name_tree.LookupValue(index, csName);
332   if (pAction == NULL || pAction->GetType() != PDFOBJ_DICTIONARY) {
333     return CPDF_Action();
334   }
335   return CPDF_Action(pAction->GetDict());
336 }
337 CPDF_Action CPDF_DocJSActions::GetJSAction(const CFX_ByteString& csName) const {
338   ASSERT(m_pDocument != NULL);
339   CPDF_NameTree name_tree(m_pDocument, FX_BSTRC("JavaScript"));
340   CPDF_Object* pAction = name_tree.LookupValue(csName);
341   if (pAction == NULL || pAction->GetType() != PDFOBJ_DICTIONARY) {
342     return CPDF_Action();
343   }
344   return CPDF_Action(pAction->GetDict());
345 }
346 int CPDF_DocJSActions::FindJSAction(const CFX_ByteString& csName) const {
347   ASSERT(m_pDocument != NULL);
348   CPDF_NameTree name_tree(m_pDocument, FX_BSTRC("JavaScript"));
349   return name_tree.GetIndex(csName);
350 }