Bringing apdf from vendor into main branch.
[AROS-Contrib.git] / apdf / xpdf / PageLabel.cc
blob9e153c273897d72e8e3251b40582817cc462adca
1 //========================================================================
2 //
3 // PageLabel.cc
4 //
5 // Copyright 1999-2001 Emmanuel Lesueur
6 //
7 //========================================================================
9 #ifdef __GNUC__
10 #pragma implementation
11 #endif
13 #include <stddef.h>
14 #include <string.h>
15 #include "gmem.h"
16 #include "GString.h"
17 #include "Error.h"
18 #include "Object.h"
19 #include "Array.h"
20 #include "Dict.h"
21 #include "PageLabel.h"
23 extern GString *toLatin1(GString *);
25 //------------------------------------------------------------------------
26 // PageLabelLeaf
27 //------------------------------------------------------------------------
29 PageLabelLeaf::~PageLabelLeaf() {
30 delete prefix;
34 //------------------------------------------------------------------------
35 // PageLabelParser
36 //------------------------------------------------------------------------
38 NumberTreeLeaf *PageLabelParser::parse(int n, Object *obj) {
39 PageLabelLeaf *r = NULL;
40 if (obj->isDict()) {
41 PageLabelLeaf::Style style = PageLabelLeaf::StNoNum;
42 GString *prefix = NULL;
43 int start = 1;
44 Object obj2;
46 if (obj->dictLookup("S", &obj2)->isName()) {
47 if (!strcmp(obj2.getName(), "D"))
48 style = PageLabelLeaf::StDecimal;
49 else if (!strcmp(obj2.getName(), "R"))
50 style = PageLabelLeaf::StUpperCaseRoman;
51 else if (!strcmp(obj2.getName(), "r"))
52 style = PageLabelLeaf::StLowerCaseRoman;
53 else if (!strcmp(obj2.getName(), "A"))
54 style = PageLabelLeaf::StUpperCaseAlpha;
55 else if (!strcmp(obj2.getName(), "a"))
56 style = PageLabelLeaf::StLowerCaseAlpha;
58 obj2.free();
59 if (obj->dictLookup("P", &obj2)->isString())
60 prefix = toLatin1(obj2.getString());
61 obj2.free();
62 if (obj->dictLookup("St", &obj2)->isInt())
63 start = obj2.getInt();
64 obj2.free();
66 r = new PageLabelLeaf(n, style, prefix, start, labels);
67 labels = r;
70 return r;
74 //------------------------------------------------------------------------
75 // PageLabels
76 //------------------------------------------------------------------------
78 PageLabels::PageLabels(Object *dict) : tree(dict, &parser) {
81 static char *addRomanDigit(char *q, unsigned n, char d1, char d5, char d10) {
82 n %= 10;
83 if (n == 9) {
84 *--q = d10;
85 *--q = d1;
86 } else if (n == 4) {
87 *--q = d5;
88 *--q = d1;
89 } else {
90 bool f = false;
91 if (n >= 5) {
92 f = true;
93 n -= 5;
95 switch (n) {
96 case 3: *--q = d1;
97 case 2: *--q = d1;
98 case 1: *--q = d1;
100 if (f)
101 *--q = d5;
103 return q;
106 GString *PageLabels::getPageLabel(int index) {
107 PageLabelLeaf *label = (PageLabelLeaf *)tree.getLeaf(index);
108 GString *s = new GString;
109 if (label) {
110 int offset = 0;
111 char buf[32];
112 char *q = buf + sizeof(buf);
113 int n = index - label->getKey() + label->getStart();
114 GBool neg = gFalse;
116 if (n < 0) {
117 n = -n;
118 neg = gTrue;
121 *--q = '\0';
123 if (label->getPrefix())
124 s->append(label->getPrefix());
126 switch (label->getStyle()) {
127 case PageLabelLeaf::StUpperCaseRoman:
128 offset = 'A' - 'a';
129 // fall through
130 case PageLabelLeaf::StLowerCaseRoman:
131 if (n > 0 && n < 4000) {
132 q = addRomanDigit(q, n, 'i' + offset, 'v' + offset, 'x' + offset);
133 n /= 10;
134 q = addRomanDigit(q, n, 'x' + offset, 'l' + offset, 'c' + offset);
135 n /= 10;
136 q = addRomanDigit(q, n, 'c' + offset, 'd' + offset, 'm' + offset);
137 n /= 10;
138 q = addRomanDigit(q, n, 'm' + offset, '?', '?');
139 break;
141 // fall through
142 case PageLabelLeaf::StDecimal:
143 do {
144 *--q = '0' + (n % 10);
145 n /= 10;
146 } while (n != 0);
147 break;
150 case PageLabelLeaf::StUpperCaseAlpha:
151 offset = 'A' - 'a';
152 // fall through
153 case PageLabelLeaf::StLowerCaseAlpha:
154 do {
155 *--q = 'a' + (n % 26) + offset;
156 n /= 26;
157 } while (n != 0);
158 break;
161 if (neg)
162 *--q = '-';
164 s->append(q);
166 return s;
169 int PageLabels::getPageIndex(const char *label) {
170 PageLabelLeaf *leaf;
171 for (leaf = parser.getFirst(); leaf != NULL; leaf = leaf->getNext()) {
172 GString *p = leaf->getPrefix();
173 const char *l = label;
174 int n = 0;
175 if (p) {
176 if (!p->cmpN((char*)l, p->getLength()))
177 l += p->getLength();
178 else
179 continue;
181 switch (leaf->getStyle()) {
182 case PageLabelLeaf::StNoNum:
183 n = leaf->getStart();
184 break;
185 case PageLabelLeaf::StDecimal:
186 while(*l >= '0' && *l <= '9') {
187 n *= 10;
188 n += *l - '0';
189 ++l;
191 break;
192 case PageLabelLeaf::StUpperCaseRoman:
193 while (*l && n >= 0) {
194 switch (*l++) {
195 case 'I':
196 if (*l == 'V') {
197 n += 4;
198 ++l;
199 } else if (*l == 'X') {
200 n += 9;
201 ++l;
202 } else
203 ++n;
204 break;
205 case 'V':
206 n += 5;
207 break;
208 case 'X':
209 if (*l == 'L') {
210 n += 40;
211 ++l;
212 } else if (*l == 'C') {
213 n += 90;
214 ++l;
215 } else
216 n += 10;
217 break;
218 case 'L':
219 n += 50;
220 break;
221 case 'C':
222 if (*l == 'D') {
223 n += 400;
224 ++l;
225 } else if (*l == 'M') {
226 n += 900;
227 ++l;
228 } else
229 n += 100;
230 break;
231 case 'D':
232 n += 500;
233 break;
234 case 'M':
235 n += 1000;
236 break;
237 default:
238 n = -1;
239 break;
242 break;
243 case PageLabelLeaf::StLowerCaseRoman:
244 while (*l && n >= 0) {
245 switch (*l++) {
246 case 'i':
247 if (*l == 'v') {
248 n += 4;
249 ++l;
250 } else if (*l == 'x') {
251 n += 9;
252 ++l;
253 } else
254 ++n;
255 break;
256 case 'v':
257 n += 5;
258 break;
259 case 'x':
260 if (*l == 'l') {
261 n += 40;
262 ++l;
263 } else if (*l == 'c') {
264 n += 90;
265 ++l;
266 } else
267 n += 10;
268 break;
269 case 'l':
270 n += 50;
271 break;
272 case 'c':
273 if (*l == 'd') {
274 n += 400;
275 ++l;
276 } else if (*l == 'm') {
277 n += 900;
278 ++l;
279 } else
280 n += 100;
281 break;
282 case 'd':
283 n += 500;
284 break;
285 case 'm':
286 n += 1000;
287 break;
288 default:
289 n = -1;
290 break;
293 break;
294 case PageLabelLeaf::StUpperCaseAlpha:
295 while(*l >= 'A' && *l <= 'Z') {
296 n *= 26;
297 n += *l - 'A';
298 ++l;
300 break;
301 case PageLabelLeaf::StLowerCaseAlpha:
302 while(*l >= 'a' && *l <= 'z') {
303 n *= 26;
304 n += *l - 'a';
305 ++l;
307 break;
309 if (*l == '\0')
310 return n - leaf->getStart() + leaf->getKey();
312 return -1;