Initial commit.
[pdfium.git] / core / src / fpdfdoc / doc_basic.cpp
1 // Copyright 2014 PDFium Authors. All rights reserved.\r
2 // Use of this source code is governed by a BSD-style license that can be\r
3 // found in the LICENSE file.\r
4  \r
5 // Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com\r
6 \r
7 #include "../../include/fpdfdoc/fpdf_doc.h"\r
8 const int nMaxRecursion = 32;\r
9 int CPDF_Dest::GetPageIndex(CPDF_Document* pDoc)\r
10 {\r
11     if (m_pObj == NULL || m_pObj->GetType() != PDFOBJ_ARRAY) {\r
12         return 0;\r
13     }\r
14     CPDF_Object* pPage = ((CPDF_Array*)m_pObj)->GetElementValue(0);\r
15     if (pPage == NULL) {\r
16         return 0;\r
17     }\r
18     if (pPage->GetType() == PDFOBJ_NUMBER) {\r
19         return pPage->GetInteger();\r
20     }\r
21     if (pPage->GetType() != PDFOBJ_DICTIONARY) {\r
22         return 0;\r
23     }\r
24     return pDoc->GetPageIndex(pPage->GetObjNum());\r
25 }\r
26 FX_DWORD CPDF_Dest::GetPageObjNum()\r
27 {\r
28     if (m_pObj == NULL || m_pObj->GetType() != PDFOBJ_ARRAY) {\r
29         return 0;\r
30     }\r
31     CPDF_Object* pPage = ((CPDF_Array*)m_pObj)->GetElementValue(0);\r
32     if (pPage == NULL) {\r
33         return 0;\r
34     }\r
35     if (pPage->GetType() == PDFOBJ_NUMBER) {\r
36         return pPage->GetInteger();\r
37     }\r
38     if (pPage->GetType() == PDFOBJ_DICTIONARY) {\r
39         return pPage->GetObjNum();\r
40     }\r
41     return 0;\r
42 }\r
43 const FX_CHAR* g_sZoomModes[] = {"XYZ", "Fit", "FitH", "FitV", "FitR", "FitB", "FitBH", "FitBV", ""};\r
44 int CPDF_Dest::GetZoomMode()\r
45 {\r
46     if (m_pObj == NULL || m_pObj->GetType() != PDFOBJ_ARRAY) {\r
47         return 0;\r
48     }\r
49     CFX_ByteString mode = ((CPDF_Array*)m_pObj)->GetElementValue(1)->GetString();\r
50     int i = 0;\r
51     while (g_sZoomModes[i][0] != '\0') {\r
52         if (mode == g_sZoomModes[i]) {\r
53             return i + 1;\r
54         }\r
55         i ++;\r
56     }\r
57     return 0;\r
58 }\r
59 FX_FLOAT CPDF_Dest::GetParam(int index)\r
60 {\r
61     if (m_pObj == NULL || m_pObj->GetType() != PDFOBJ_ARRAY) {\r
62         return 0;\r
63     }\r
64     return ((CPDF_Array*)m_pObj)->GetNumber(2 + index);\r
65 }\r
66 CFX_ByteString CPDF_Dest::GetRemoteName()\r
67 {\r
68     if (m_pObj == NULL) {\r
69         return CFX_ByteString();\r
70     }\r
71     return m_pObj->GetString();\r
72 }\r
73 CPDF_NameTree::CPDF_NameTree(CPDF_Document* pDoc, FX_BSTR category)\r
74 {\r
75     m_pRoot = pDoc->GetRoot()->GetDict(FX_BSTRC("Names"))->GetDict(category);\r
76 }\r
77 static CPDF_Object* SearchNameNode(CPDF_Dictionary* pNode, const CFX_ByteString& csName,\r
78                                    int& nIndex, CPDF_Array** ppFind, int nLevel = 0)\r
79 {\r
80     if (nLevel > nMaxRecursion) {\r
81         return NULL;\r
82     }\r
83     CPDF_Array* pLimits = pNode->GetArray(FX_BSTRC("Limits"));\r
84     if (pLimits != NULL) {\r
85         CFX_ByteString csLeft = pLimits->GetString(0);\r
86         CFX_ByteString csRight = pLimits->GetString(1);\r
87         if (csLeft.Compare(csRight) > 0) {\r
88             CFX_ByteString csTmp = csRight;\r
89             csRight = csLeft;\r
90             csLeft = csTmp;\r
91         }\r
92         if (csName.Compare(csLeft) < 0 || csName.Compare(csRight) > 0) {\r
93             return NULL;\r
94         }\r
95     }\r
96     CPDF_Array* pNames = pNode->GetArray(FX_BSTRC("Names"));\r
97     if (pNames) {\r
98         FX_DWORD dwCount = pNames->GetCount() / 2;\r
99         for (FX_DWORD i = 0; i < dwCount; i ++) {\r
100             CFX_ByteString csValue = pNames->GetString(i * 2);\r
101             FX_INT32 iCompare = csValue.Compare(csName);\r
102             if (iCompare <= 0) {\r
103                 if (ppFind != NULL) {\r
104                     *ppFind = pNames;\r
105                 }\r
106                 if (iCompare < 0) {\r
107                     continue;\r
108                 }\r
109             } else {\r
110                 break;\r
111             }\r
112             nIndex += i;\r
113             return pNames->GetElementValue(i * 2 + 1);\r
114         }\r
115         nIndex += dwCount;\r
116         return NULL;\r
117     }\r
118     CPDF_Array* pKids = pNode->GetArray(FX_BSTRC("Kids"));\r
119     if (pKids == NULL) {\r
120         return NULL;\r
121     }\r
122     for (FX_DWORD i = 0; i < pKids->GetCount(); i ++) {\r
123         CPDF_Dictionary* pKid = pKids->GetDict(i);\r
124         if (pKid == NULL) {\r
125             continue;\r
126         }\r
127         CPDF_Object* pFound = SearchNameNode(pKid, csName, nIndex, ppFind, nLevel + 1);\r
128         if (pFound) {\r
129             return pFound;\r
130         }\r
131     }\r
132     return NULL;\r
133 }\r
134 static CPDF_Object* SearchNameNode(CPDF_Dictionary* pNode, int nIndex, int& nCurIndex,\r
135                                    CFX_ByteString& csName, CPDF_Array** ppFind, int nLevel = 0)\r
136 {\r
137     if (nLevel > nMaxRecursion) {\r
138         return NULL;\r
139     }\r
140     CPDF_Array* pNames = pNode->GetArray(FX_BSTRC("Names"));\r
141     if (pNames) {\r
142         int nCount = pNames->GetCount() / 2;\r
143         if (nIndex >= nCurIndex + nCount) {\r
144             nCurIndex += nCount;\r
145             return NULL;\r
146         } else {\r
147             if (ppFind != NULL) {\r
148                 *ppFind = pNames;\r
149             }\r
150             csName = pNames->GetString((nIndex - nCurIndex) * 2);\r
151             return pNames->GetElementValue((nIndex - nCurIndex) * 2 + 1);\r
152         }\r
153     }\r
154     CPDF_Array* pKids = pNode->GetArray(FX_BSTRC("Kids"));\r
155     if (pKids == NULL) {\r
156         return NULL;\r
157     }\r
158     for (FX_DWORD i = 0; i < pKids->GetCount(); i ++) {\r
159         CPDF_Dictionary* pKid = pKids->GetDict(i);\r
160         if (pKid == NULL) {\r
161             continue;\r
162         }\r
163         CPDF_Object* pFound = SearchNameNode(pKid, nIndex, nCurIndex, csName, ppFind, nLevel + 1);\r
164         if (pFound) {\r
165             return pFound;\r
166         }\r
167     }\r
168     return NULL;\r
169 }\r
170 static int CountNames(CPDF_Dictionary* pNode, int nLevel = 0)\r
171 {\r
172     if (nLevel > nMaxRecursion) {\r
173         return 0;\r
174     }\r
175     CPDF_Array* pNames = pNode->GetArray(FX_BSTRC("Names"));\r
176     if (pNames) {\r
177         return pNames->GetCount() / 2;\r
178     }\r
179     CPDF_Array* pKids = pNode->GetArray(FX_BSTRC("Kids"));\r
180     if (pKids == NULL) {\r
181         return 0;\r
182     }\r
183     int nCount = 0;\r
184     for (FX_DWORD i = 0; i < pKids->GetCount(); i ++) {\r
185         CPDF_Dictionary* pKid = pKids->GetDict(i);\r
186         if (pKid == NULL) {\r
187             continue;\r
188         }\r
189         nCount += CountNames(pKid, nLevel + 1);\r
190     }\r
191     return nCount;\r
192 }\r
193 int CPDF_NameTree::GetCount() const\r
194 {\r
195     if (m_pRoot == NULL) {\r
196         return 0;\r
197     }\r
198     return ::CountNames(m_pRoot);\r
199 }\r
200 int CPDF_NameTree::GetIndex(const CFX_ByteString& csName) const\r
201 {\r
202     if (m_pRoot == NULL) {\r
203         return -1;\r
204     }\r
205     int nIndex = 0;\r
206     if (SearchNameNode(m_pRoot, csName, nIndex, NULL) == NULL) {\r
207         return -1;\r
208     }\r
209     return nIndex;\r
210 }\r
211 CPDF_Object* CPDF_NameTree::LookupValue(int nIndex, CFX_ByteString& csName) const\r
212 {\r
213     if (m_pRoot == NULL) {\r
214         return NULL;\r
215     }\r
216     int nCurIndex = 0;\r
217     return SearchNameNode(m_pRoot, nIndex, nCurIndex, csName, NULL);\r
218 }\r
219 CPDF_Object* CPDF_NameTree::LookupValue(const CFX_ByteString& csName) const\r
220 {\r
221     if (m_pRoot == NULL) {\r
222         return NULL;\r
223     }\r
224     int nIndex = 0;\r
225     return SearchNameNode(m_pRoot, csName, nIndex, NULL);\r
226 }\r
227 CPDF_Array*     CPDF_NameTree::LookupNamedDest(CPDF_Document* pDoc, FX_BSTR sName)\r
228 {\r
229     CPDF_Object* pValue = LookupValue(sName);\r
230     if (pValue == NULL) {\r
231         CPDF_Dictionary* pDests = pDoc->GetRoot()->GetDict(FX_BSTRC("Dests"));\r
232         if (pDests == NULL) {\r
233             return NULL;\r
234         }\r
235         pValue = pDests->GetElementValue(sName);\r
236     }\r
237     if (pValue == NULL) {\r
238         return NULL;\r
239     }\r
240     if (pValue->GetType() == PDFOBJ_ARRAY) {\r
241         return (CPDF_Array*)pValue;\r
242     }\r
243     if (pValue->GetType() == PDFOBJ_DICTIONARY) {\r
244         return ((CPDF_Dictionary*)pValue)->GetArray(FX_BSTRC("D"));\r
245     }\r
246     return NULL;\r
247 }\r
248 static CFX_WideString ChangeSlashToPlatform(FX_LPCWSTR str)\r
249 {\r
250     CFX_WideString result;\r
251     while (*str) {\r
252         if (*str == '/') {\r
253 #if _FXM_PLATFORM_  == _FXM_PLATFORM_APPLE_\r
254             result += ':';\r
255 #elif _FXM_PLATFORM_  == _FXM_PLATFORM_WINDOWS_\r
256             result += '\\';\r
257 #else\r
258             result += *str;\r
259 #endif\r
260         } else {\r
261             result += *str;\r
262         }\r
263         str++;\r
264     }\r
265     return result;\r
266 }\r
267 static CFX_WideString FILESPEC_DecodeFileName(FX_WSTR filepath)\r
268 {\r
269     if (filepath.GetLength() <= 1) {\r
270         return CFX_WideString();\r
271     }\r
272 #if _FXM_PLATFORM_  == _FXM_PLATFORM_APPLE_\r
273     if (filepath.Left(sizeof("/Mac") - 1) == CFX_WideStringC(L"/Mac")) {\r
274         return ChangeSlashToPlatform(filepath.GetPtr() + 1);\r
275     }\r
276     return ChangeSlashToPlatform(filepath.GetPtr());\r
277 #elif _FXM_PLATFORM_  == _FXM_PLATFORM_WINDOWS_\r
278     if (filepath.GetAt(0) != '/') {\r
279         return ChangeSlashToPlatform(filepath.GetPtr());\r
280     }\r
281     if (filepath.GetAt(1) == '/') {\r
282         return ChangeSlashToPlatform(filepath.GetPtr() + 1);\r
283     }\r
284     if (filepath.GetAt(2) == '/') {\r
285         CFX_WideString result;\r
286         result += filepath.GetAt(1);\r
287         result += ':';\r
288         result += ChangeSlashToPlatform(filepath.GetPtr() + 2);\r
289         return result;\r
290     }\r
291     CFX_WideString result;\r
292     result += '\\';\r
293     result += ChangeSlashToPlatform(filepath.GetPtr());\r
294     return result;\r
295 #else\r
296     return filepath;\r
297 #endif\r
298 }\r
299 FX_BOOL CPDF_FileSpec::GetFileName(CFX_WideString &csFileName) const\r
300 {\r
301     if (m_pObj == NULL) {\r
302         return FALSE;\r
303     }\r
304     if (m_pObj->GetType() == PDFOBJ_DICTIONARY) {\r
305         CPDF_Dictionary* pDict = (CPDF_Dictionary*)m_pObj;\r
306         csFileName = pDict->GetUnicodeText(FX_BSTRC("UF"));\r
307         if (csFileName.IsEmpty()) {\r
308             csFileName = CFX_WideString::FromLocal(pDict->GetString(FX_BSTRC("F")));\r
309         }\r
310         if (pDict->GetString(FX_BSTRC("FS")) == FX_BSTRC("URL")) {\r
311             return TRUE;\r
312         }\r
313         if (csFileName.IsEmpty()) {\r
314             if (pDict->KeyExist(FX_BSTRC("DOS"))) {\r
315                 csFileName = CFX_WideString::FromLocal(pDict->GetString(FX_BSTRC("DOS")));\r
316             } else if (pDict->KeyExist(FX_BSTRC("Mac"))) {\r
317                 csFileName = CFX_WideString::FromLocal(pDict->GetString(FX_BSTRC("Mac")));\r
318             } else if (pDict->KeyExist(FX_BSTRC("Unix"))) {\r
319                 csFileName = CFX_WideString::FromLocal(pDict->GetString(FX_BSTRC("Unix")));\r
320             } else {\r
321                 return FALSE;\r
322             }\r
323         }\r
324     } else {\r
325         csFileName = CFX_WideString::FromLocal(m_pObj->GetString());\r
326     }\r
327     csFileName = FILESPEC_DecodeFileName(csFileName);\r
328     return TRUE;\r
329 }\r
330 CPDF_FileSpec::CPDF_FileSpec()\r
331 {\r
332     m_pObj = CPDF_Dictionary::Create();\r
333     if (m_pObj != NULL) {\r
334         ((CPDF_Dictionary*)m_pObj)->SetAtName(FX_BSTRC("Type"), FX_BSTRC("Filespec"));\r
335     }\r
336 }\r
337 FX_BOOL CPDF_FileSpec::IsURL() const\r
338 {\r
339     if (m_pObj == NULL) {\r
340         return FALSE;\r
341     }\r
342     if (m_pObj->GetType() != PDFOBJ_DICTIONARY) {\r
343         return FALSE;\r
344     }\r
345     return ((CPDF_Dictionary*)m_pObj)->GetString(FX_BSTRC("FS")) == FX_BSTRC("URL");\r
346 }\r
347 static CFX_WideString ChangeSlashToPDF(FX_LPCWSTR str)\r
348 {\r
349     CFX_WideString result;\r
350     while (*str) {\r
351         if (*str == '\\' || *str == ':') {\r
352             result += '/';\r
353         } else {\r
354             result += *str;\r
355         }\r
356         str++;\r
357     }\r
358     return result;\r
359 }\r
360 CFX_WideString FILESPEC_EncodeFileName(FX_WSTR filepath)\r
361 {\r
362     if (filepath.GetLength() <= 1) {\r
363         return CFX_WideString();\r
364     }\r
365 #if _FXM_PLATFORM_  == _FXM_PLATFORM_WINDOWS_\r
366     if (filepath.GetAt(1) == ':') {\r
367         CFX_WideString result;\r
368         result = '/';\r
369         result += filepath.GetAt(0);\r
370         if (filepath.GetAt(2) != '\\') {\r
371             result += '/';\r
372         }\r
373         result += ChangeSlashToPDF(filepath.GetPtr() + 2);\r
374         return result;\r
375     }\r
376     if (filepath.GetAt(0) == '\\' && filepath.GetAt(1) == '\\') {\r
377         return ChangeSlashToPDF(filepath.GetPtr() + 1);\r
378     }\r
379     if (filepath.GetAt(0) == '\\') {\r
380         CFX_WideString result;\r
381         result = '/';\r
382         result += ChangeSlashToPDF(filepath.GetPtr());\r
383         return result;\r
384     }\r
385     return ChangeSlashToPDF(filepath.GetPtr());\r
386 #elif _FXM_PLATFORM_  == _FXM_PLATFORM_APPLE_\r
387     if (filepath.Left(sizeof("Mac") - 1) == FX_WSTRC(L"Mac")) {\r
388         CFX_WideString result;\r
389         result = '/';\r
390         result += ChangeSlashToPDF(filepath.GetPtr());\r
391         return result;\r
392     }\r
393     return ChangeSlashToPDF(filepath.GetPtr());\r
394 #else\r
395     return filepath;\r
396 #endif\r
397 }\r
398 CPDF_Stream* CPDF_FileSpec::GetFileStream() const\r
399 {\r
400     if (m_pObj == NULL) {\r
401         return NULL;\r
402     }\r
403     FX_INT32 iType = m_pObj->GetType();\r
404     if (iType == PDFOBJ_STREAM) {\r
405         return (CPDF_Stream*)m_pObj;\r
406     } else if (iType == PDFOBJ_DICTIONARY) {\r
407         CPDF_Dictionary *pEF = ((CPDF_Dictionary*)m_pObj)->GetDict(FX_BSTRC("EF"));\r
408         if (pEF == NULL) {\r
409             return NULL;\r
410         }\r
411         return pEF->GetStream(FX_BSTRC("F"));\r
412     }\r
413     return NULL;\r
414 }\r
415 static void FPDFDOC_FILESPEC_SetFileName(CPDF_Object *pObj, FX_WSTR wsFileName, FX_BOOL bURL)\r
416 {\r
417     ASSERT(pObj != NULL);\r
418     CFX_WideString wsStr;\r
419     if (bURL) {\r
420         wsStr = wsFileName;\r
421     } else {\r
422         wsStr = FILESPEC_EncodeFileName(wsFileName);\r
423     }\r
424     FX_INT32 iType = pObj->GetType();\r
425     if (iType == PDFOBJ_STRING) {\r
426         pObj->SetString(CFX_ByteString::FromUnicode(wsStr));\r
427     } else if (iType == PDFOBJ_DICTIONARY) {\r
428         CPDF_Dictionary* pDict = (CPDF_Dictionary*)pObj;\r
429         pDict->SetAtString(FX_BSTRC("F"), CFX_ByteString::FromUnicode(wsStr));\r
430         pDict->SetAtString(FX_BSTRC("UF"), PDF_EncodeText(wsStr));\r
431     }\r
432 }\r
433 void CPDF_FileSpec::SetFileName(FX_WSTR wsFileName, FX_BOOL bURL)\r
434 {\r
435     ASSERT(m_pObj != NULL);\r
436     if (m_pObj->GetType() == PDFOBJ_DICTIONARY && bURL) {\r
437         ((CPDF_Dictionary*)m_pObj)->SetAtName(FX_BSTRC("FS"), "URL");\r
438     }\r
439     FPDFDOC_FILESPEC_SetFileName(m_pObj, wsFileName, bURL);\r
440 }\r
441 static CFX_WideString _MakeRoman(int num)\r
442 {\r
443     const int arabic[] = {\r
444         1000, 900, 500, 400, 100, 90, 50, 40, 10, 9, 5, 4, 1\r
445     };\r
446     const CFX_WideString roman[] = {\r
447         L"m", L"cm", L"d", L"cd", L"c", L"xc", L"l", L"xl", L"x", L"ix", L"v", L"iv", L"i"\r
448     };\r
449     const int nMaxNum = 1000000;\r
450     num %= nMaxNum;\r
451     int i = 0;\r
452     CFX_WideString wsRomanNumber;\r
453     while (num > 0) {\r
454         while (num >= arabic[i]) {\r
455             num = num - arabic[i];\r
456             wsRomanNumber += roman[i];\r
457         }\r
458         i = i + 1;\r
459     }\r
460     return wsRomanNumber;\r
461 }\r
462 static CFX_WideString _MakeLetters(int num)\r
463 {\r
464     if (num == 0) {\r
465         return CFX_WideString();\r
466     }\r
467     CFX_WideString wsLetters;\r
468     const int nMaxCount = 1000;\r
469     const int nLetterCount = 26;\r
470     num -= 1;\r
471     int count = num / nLetterCount + 1;\r
472     count %= nMaxCount;\r
473     FX_WCHAR ch = L'a' + num % nLetterCount;\r
474     for (int i = 0; i < count; i++) {\r
475         wsLetters += ch;\r
476     }\r
477     return wsLetters;\r
478 }\r
479 static CFX_WideString _GetLabelNumPortion(int num, const CFX_ByteString& bsStyle)\r
480 {\r
481     CFX_WideString wsNumPortion;\r
482     if          (bsStyle.IsEmpty()) {\r
483         return wsNumPortion;\r
484     }\r
485     if (bsStyle == "D") {\r
486         wsNumPortion.Format((FX_LPCWSTR)L"%d", num);\r
487     } else if (bsStyle == "R") {\r
488         wsNumPortion = _MakeRoman(num);\r
489         wsNumPortion.MakeUpper();\r
490     } else if (bsStyle == "r") {\r
491         wsNumPortion = _MakeRoman(num);\r
492     } else if (bsStyle == "A") {\r
493         wsNumPortion = _MakeLetters(num);\r
494         wsNumPortion.MakeUpper();\r
495     } else if (bsStyle == "a") {\r
496         wsNumPortion = _MakeLetters(num);\r
497     }\r
498     return wsNumPortion;\r
499 }\r
500 CFX_WideString CPDF_PageLabel::GetLabel(int nPage) const\r
501 {\r
502     CFX_WideString wsLabel;\r
503     if (m_pDocument == NULL) {\r
504         return wsLabel;\r
505     }\r
506     CPDF_Dictionary* pPDFRoot = m_pDocument->GetRoot();\r
507     if (pPDFRoot == NULL) {\r
508         return wsLabel;\r
509     }\r
510     CPDF_Dictionary* pLabels = pPDFRoot->GetDict(FX_BSTRC("PageLabels"));\r
511     CPDF_NumberTree numberTree(pLabels);\r
512     CPDF_Object* pValue = NULL;\r
513     int n = nPage;\r
514     while (n >= 0) {\r
515         pValue = numberTree.LookupValue(n);\r
516         if (pValue != NULL) {\r
517             break;\r
518         }\r
519         n--;\r
520     }\r
521     if (pValue != NULL) {\r
522         pValue = pValue->GetDirect();\r
523         if (pValue->GetType() == PDFOBJ_DICTIONARY) {\r
524             CPDF_Dictionary* pLabel = (CPDF_Dictionary*)pValue;\r
525             if (pLabel->KeyExist(FX_BSTRC("P"))) {\r
526                 wsLabel += pLabel->GetUnicodeText(FX_BSTRC("P"));\r
527             }\r
528             CFX_ByteString bsNumberingStyle = pLabel->GetString(FX_BSTRC("S"), NULL);\r
529             int nLabelNum = nPage - n + pLabel->GetInteger(FX_BSTRC("St"), 1);\r
530             CFX_WideString wsNumPortion = _GetLabelNumPortion(nLabelNum, bsNumberingStyle);\r
531             wsLabel += wsNumPortion;\r
532             return wsLabel;\r
533         }\r
534     }\r
535     wsLabel.Format((FX_LPCWSTR)L"%d", nPage + 1);\r
536     return wsLabel;\r
537 }\r
538 FX_INT32 CPDF_PageLabel::GetPageByLabel(FX_BSTR bsLabel) const\r
539 {\r
540     if (m_pDocument == NULL) {\r
541         return -1;\r
542     }\r
543     CPDF_Dictionary* pPDFRoot = m_pDocument->GetRoot();\r
544     if (pPDFRoot == NULL) {\r
545         return -1;\r
546     }\r
547     int nPages = m_pDocument->GetPageCount();\r
548     CFX_ByteString bsLbl;\r
549     CFX_ByteString bsOrig = bsLabel;\r
550     for (int i = 0; i < nPages; i++) {\r
551         bsLbl = PDF_EncodeText(GetLabel(i));\r
552         if (!bsLbl.Compare(bsOrig)) {\r
553             return i;\r
554         }\r
555     }\r
556     bsLbl = bsOrig;\r
557     int nPage = FXSYS_atoi(bsLbl);\r
558     if (nPage > 0 && nPage <= nPages) {\r
559         return nPage;\r
560     }\r
561     return -1;\r
562 }\r
563 FX_INT32 CPDF_PageLabel::GetPageByLabel(FX_WSTR wsLabel) const\r
564 {\r
565     CFX_ByteString bsLabel = PDF_EncodeText((CFX_WideString)wsLabel);\r
566     return GetPageByLabel(bsLabel);\r
567 }\r