1 //========================================================================
3 // This file is under the GPLv2 or later license
5 // Copyright (C) 2005-2006 Kristian Høgsberg <krh@redhat.com>
6 // Copyright (C) 2005, 2009, 2013 Albert Astals Cid <aacid@kde.org>
7 // Copyright (C) 2011 Simon Kellner <kellner@kit.edu>
8 // Copyright (C) 2012 Fabio D'Urso <fabiodurso@hotmail.it>
10 // To see a description of the changes please see the Changelog file that
11 // came with your tarball or type make ChangeLog if you are building from git
13 //========================================================================
21 #include "PageLabelInfo.h"
22 #include "PageLabelInfo_p.h"
24 PageLabelInfo::Interval::Interval(Object
*dict
, int baseA
) {
28 if (dict
->dictLookup("S", &obj
)->isName()) {
29 if (obj
.isName("D")) {
31 } else if (obj
.isName("R")) {
32 style
= UppercaseRoman
;
33 } else if (obj
.isName("r")) {
34 style
= LowercaseRoman
;
35 } else if (obj
.isName("A")) {
36 style
= UppercaseLatin
;
37 } else if (obj
.isName("a")) {
38 style
= LowercaseLatin
;
43 if (dict
->dictLookup("P", &obj
)->isString())
44 prefix
= obj
.getString()->copy();
46 prefix
= new GooString("");
49 if (dict
->dictLookup("St", &obj
)->isInt())
58 PageLabelInfo::Interval::~Interval() {
62 PageLabelInfo::PageLabelInfo(Object
*tree
, int numPages
) {
64 Interval
*interval
, *next
;
68 for (i
= 0; i
< intervals
.getLength(); i
++) {
69 interval
= (Interval
*) intervals
.get(i
);
71 if (i
+ 1 < intervals
.getLength()) {
72 next
= (Interval
*) intervals
.get(i
+ 1);
73 interval
->length
= next
->base
- interval
->base
;
75 interval
->length
= numPages
- interval
->base
;
77 if (interval
->length
< 0) interval
->length
= 0;
81 PageLabelInfo::~PageLabelInfo() {
83 for (i
= 0; i
< intervals
.getLength(); ++i
) {
84 delete (Interval
*)intervals
.get(i
);
88 void PageLabelInfo::parse(Object
*tree
) {
90 Object kids
, kid
, limits
, low
, high
;
95 if (tree
->dictLookup("Nums", &nums
)->isArray()) {
96 for (i
= 0; i
< nums
.arrayGetLength(); i
+= 2) {
97 if (!nums
.arrayGet(i
, &obj
)->isInt()) {
103 if (!nums
.arrayGet(i
+ 1, &obj
)->isDict()) {
108 interval
= new Interval(&obj
, base
);
110 intervals
.append(interval
);
115 if (tree
->dictLookup("Kids", &kids
)->isArray()) {
116 for (i
= 0; i
< kids
.arrayGetLength(); ++i
) {
117 if (kids
.arrayGet(i
, &kid
)->isDict())
125 GBool
PageLabelInfo::labelToIndex(GooString
*label
, int *index
)
128 char *str
= label
->getCString(), *end
;
132 for (i
= 0; i
< intervals
.getLength(); i
++) {
133 interval
= (Interval
*) intervals
.get(i
);
134 const int base
= interval
->base
;
135 prefixLength
= interval
->prefix
->getLength();
136 if (label
->cmpN(interval
->prefix
, prefixLength
) != 0)
139 switch (interval
->style
) {
140 case Interval::Arabic
:
141 number
= strtol(str
+ prefixLength
, &end
, 10);
142 if (*end
== '\0' && number
- interval
->first
< interval
->length
) {
143 *index
= base
+ number
- interval
->first
;
147 case Interval::LowercaseRoman
:
148 case Interval::UppercaseRoman
:
149 number
= fromRoman(str
+ prefixLength
);
150 if (number
>= 0 && number
- interval
->first
< interval
->length
) {
151 *index
= base
+ number
- interval
->first
;
155 case Interval::UppercaseLatin
:
156 case Interval::LowercaseLatin
:
157 number
= fromLatin(str
+ prefixLength
);
158 if (number
>= 0 && number
- interval
->first
< interval
->length
) {
159 *index
= base
+ number
- interval
->first
;
171 GBool
PageLabelInfo::indexToLabel(int index
, GooString
*label
)
176 GooString number_string
;
180 for (i
= 0; i
< intervals
.getLength(); i
++) {
181 interval
= (Interval
*) intervals
.get(i
);
182 if (base
<= index
&& index
< base
+ interval
->length
)
184 base
+= interval
->length
;
187 if (i
== intervals
.getLength())
190 number
= index
- base
+ interval
->first
;
191 switch (interval
->style
) {
192 case Interval::Arabic
:
193 snprintf (buffer
, sizeof(buffer
), "%d", number
);
194 number_string
.append(buffer
);
196 case Interval::LowercaseRoman
:
197 toRoman(number
, &number_string
, gFalse
);
199 case Interval::UppercaseRoman
:
200 toRoman(number
, &number_string
, gTrue
);
202 case Interval::LowercaseLatin
:
203 toLatin(number
, &number_string
, gFalse
);
205 case Interval::UppercaseLatin
:
206 toLatin(number
, &number_string
, gTrue
);
213 label
->append(interval
->prefix
);
214 if (label
->hasUnicodeMarker()) {
218 /* Convert the ascii number string to ucs2 and append. */
219 len
= number_string
.getLength ();
221 for (i
= 0; i
< len
; ++i
) {
222 ucs2_char
[1] = number_string
.getChar(i
);
223 label
->append(ucs2_char
, 2);
226 label
->append(&number_string
);