beta-0.89.2
[luatex.git] / source / libs / poppler / poppler-src / poppler / PageLabelInfo.cc
blob3153377f6d3b5a29d9a9443cf07e6429b26daf53
1 //========================================================================
2 //
3 // This file is under the GPLv2 or later license
4 //
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>
9 //
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 //========================================================================
15 #include <config.h>
16 #include <limits.h>
17 #include <stdlib.h>
18 #include <stdio.h>
19 #include <assert.h>
21 #include "PageLabelInfo.h"
22 #include "PageLabelInfo_p.h"
24 PageLabelInfo::Interval::Interval(Object *dict, int baseA) {
25 Object obj;
27 style = None;
28 if (dict->dictLookup("S", &obj)->isName()) {
29 if (obj.isName("D")) {
30 style = Arabic;
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;
41 obj.free();
43 if (dict->dictLookup("P", &obj)->isString())
44 prefix = obj.getString()->copy();
45 else
46 prefix = new GooString("");
47 obj.free();
49 if (dict->dictLookup("St", &obj)->isInt())
50 first = obj.getInt();
51 else
52 first = 1;
53 obj.free();
55 base = baseA;
58 PageLabelInfo::Interval::~Interval() {
59 delete prefix;
62 PageLabelInfo::PageLabelInfo(Object *tree, int numPages) {
63 int i;
64 Interval *interval, *next;
66 parse(tree);
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;
74 } else {
75 interval->length = numPages - interval->base;
77 if (interval->length < 0) interval->length = 0;
81 PageLabelInfo::~PageLabelInfo() {
82 int i;
83 for (i = 0; i < intervals.getLength(); ++i) {
84 delete (Interval*)intervals.get(i);
88 void PageLabelInfo::parse(Object *tree) {
89 Object nums, obj;
90 Object kids, kid, limits, low, high;
91 int i, base;
92 Interval *interval;
94 // leaf node
95 if (tree->dictLookup("Nums", &nums)->isArray()) {
96 for (i = 0; i < nums.arrayGetLength(); i += 2) {
97 if (!nums.arrayGet(i, &obj)->isInt()) {
98 obj.free();
99 continue;
101 base = obj.getInt();
102 obj.free();
103 if (!nums.arrayGet(i + 1, &obj)->isDict()) {
104 obj.free();
105 continue;
108 interval = new Interval(&obj, base);
109 obj.free();
110 intervals.append(interval);
113 nums.free();
115 if (tree->dictLookup("Kids", &kids)->isArray()) {
116 for (i = 0; i < kids.arrayGetLength(); ++i) {
117 if (kids.arrayGet(i, &kid)->isDict())
118 parse(&kid);
119 kid.free();
122 kids.free();
125 GBool PageLabelInfo::labelToIndex(GooString *label, int *index)
127 Interval *interval;
128 char *str = label->getCString(), *end;
129 int prefixLength;
130 int i, number;
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)
137 continue;
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;
144 return gTrue;
146 break;
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;
152 return gTrue;
154 break;
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;
160 return gTrue;
162 break;
163 case Interval::None:
164 break;
168 return gFalse;
171 GBool PageLabelInfo::indexToLabel(int index, GooString *label)
173 char buffer[32];
174 int i, base, number;
175 Interval *interval;
176 GooString number_string;
178 base = 0;
179 interval = NULL;
180 for (i = 0; i < intervals.getLength(); i++) {
181 interval = (Interval *) intervals.get(i);
182 if (base <= index && index < base + interval->length)
183 break;
184 base += interval->length;
187 if (i == intervals.getLength())
188 return gFalse;
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);
195 break;
196 case Interval::LowercaseRoman:
197 toRoman(number, &number_string, gFalse);
198 break;
199 case Interval::UppercaseRoman:
200 toRoman(number, &number_string, gTrue);
201 break;
202 case Interval::LowercaseLatin:
203 toLatin(number, &number_string, gFalse);
204 break;
205 case Interval::UppercaseLatin:
206 toLatin(number, &number_string, gTrue);
207 break;
208 case Interval::None:
209 break;
212 label->clear();
213 label->append(interval->prefix);
214 if (label->hasUnicodeMarker()) {
215 int i, len;
216 char ucs2_char[2];
218 /* Convert the ascii number string to ucs2 and append. */
219 len = number_string.getLength ();
220 ucs2_char[0] = 0;
221 for (i = 0; i < len; ++i) {
222 ucs2_char[1] = number_string.getChar(i);
223 label->append(ucs2_char, 2);
225 } else {
226 label->append(&number_string);
229 return gTrue;