1 /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
2 /*
3 * This file is part of the libe-book project.
4 *
5 * This Source Code Form is subject to the terms of the Mozilla Public
6 * License, v. 2.0. If a copy of the MPL was not distributed with this
7 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
8 */
9
10 #include <string>
11
12 #include "libebook_utils.h"
13 #include "EBOOKCharsetConverter.h"
14 #include "EBOOKMemoryStream.h"
15 #include "EBOOKZlibStream.h"
16 #include "PDBLZ77Stream.h"
17 #include "PluckerParser.h"
18
19 using std::unique_ptr;
20 using std::shared_ptr;
21
22 using std::vector;
23
24 namespace libebook
25 {
26
27 namespace
28 {
29
30 static const uint32_t PLUCKER_TYPE = PDB_CODE("Data");
31 static const uint32_t PLUCKER_CREATOR = PDB_CODE("Plkr");
32
33 static const uint32_t APPINFO_SIGNATURE = 0x6c6e6368;
34
35 enum Compression
36 {
37 COMPRESSION_UNKNOWN,
38 COMPRESSION_LZ77,
39 COMPRESSION_ZLIB
40 };
41
42 enum DataType
43 {
44 DATA_TYPE_PHTML,
45 DATA_TYPE_PHTML_COMPRESSED,
46 DATA_TYPE_TBMP,
47 DATA_TYPE_TBMP_COMPRESSED,
48 DATA_TYPE_MAILTO,
49 DATA_TYPE_LINK_INDEX,
50 DATA_TYPE_LINKS,
51 DATA_TYPE_LINKS_COMPRESSED,
52 DATA_TYPE_BOOKMARKS,
53 DATA_TYPE_CATEGORY,
54 DATA_TYPE_METADATA,
55 DATA_TYPE_LAST = DATA_TYPE_METADATA,
56 DATA_TYPE_UNKNOWN = 0xff
57 };
58
59 enum FunctionCode
60 {
61 LINK_END = 0x8,
62 PAGE_LINK_BEGIN = 0xa,
63 PARAGRAPH_LINK_BEGIN = 0xc,
64 SET_FONT = 0x11,
65 EMBEDDED_IMAGE = 0x1a,
66 SET_MARGIN = 0x22,
67 TEXT_ALIGNMENT = 0x29,
68 HORIZONTAL_RULE = 0x33,
69 NEW_LINE = 0x38,
70 ITALIC_BEGIN = 0x40,
71 ITALIC_END = 0x48,
72 UNKNOWN_53 = 0x53,
73 MULTIPLE_EMBEDDED_IMAGE = 0x5c,
74 UNDERLINE_BEGIN = 0x60,
75 UNDERLINE_END = 0x68,
76 STRIKETHROUGH_BEGIN = 0x70,
77 STRIKETHROUGH_END = 0x78
78 };
79
80 enum TextAlignment
81 {
82 TEXT_ALIGNMENT_LEFT,
83 TEXT_ALIGNMENT_RIGHT,
84 TEXT_ALIGNMENT_CENTER,
85 TEXT_ALIGNMENT_LAST = TEXT_ALIGNMENT_CENTER
86 };
87
88 enum Font
89 {
90 FONT_REGULAR,
91 FONT_H1,
92 FONT_H2,
93 FONT_H3,
94 FONT_H4,
95 FONT_H5,
96 FONT_H6,
97 FONT_BOLD,
98 FONT_FIXED_WIDTH,
99 FONT_LAST = FONT_FIXED_WIDTH
100 };
101
102 typedef std::map<unsigned, unsigned> ExceptionalCharsetMap_t;
103
104 // source: http://www.iana.org/assignments/character-sets/character-sets.xhtml (2013)
105 static const char *const IANA_CHARSETS[] =
106 {
107 /* 0 */
108 nullptr, nullptr, nullptr,
109 "US-ASCII",
110 "ISO_8859-1:1987",
111 "ISO_8859-2:1987",
112 "ISO_8859-3:1988",
113 "ISO_8859-4:1988",
114 "ISO_8859-5:1988",
115 "ISO_8859-6:1987",
116 /* 10 */
117 "ISO_8859-7:1987",
118 "ISO_8859-8:1988",
119 "ISO_8859-9:1989",
120 "ISO-8859-10",
121 "ISO_6937-2-add",
122 "JIS_X0201",
123 "JIS_Encoding",
124 "Shift_JIS",
125 "Extended_UNIX_Code_Packed_Format_for_Japanese",
126 "Extended_UNIX_Code_Fixed_Width_for_Japanese",
127 /* 20 */
128 "BS_4730",
129 "SEN_850200_C",
130 "IT",
131 "ES",
132 "DIN_66003",
133 "NS_4551-1",
134 "NF_Z_62-010",
135 "ISO-10646-UTF-1",
136 "ISO_646.basic:1983",
137 "INVARIANT",
138 /* 30 */
139 "ISO_646.irv:1983",
140 "NATS-SEFI",
141 "NATS-SEFI-ADD",
142 "NATS-DANO",
143 "NATS-DANO-ADD",
144 "SEN_850200_B",
145 "KS_C_5601-1987",
146 "ISO-2022-KR",
147 "EUC-KR",
148 "ISO-2022-JP",
149 /* 40 */
150 "ISO-2022-JP-2",
151 "JIS_C6220-1969-jp",
152 "JIS_C6220-1969-ro",
153 "PT",
154 "greek7-old",
155 "latin-greek",
156 "NF_Z_62-010_(1973)",
157 "Latin-greek-1",
158 "ISO_5427",
159 "JIS_C6226-1978",
160 /* 50 */
161 "BS_viewdata",
162 "INIS",
163 "INIS-8",
164 "INIS-cyrillic",
165 "ISO_5427:1981",
166 "ISO_5428:1980",
167 "GB_1988-80",
168 "GB_2312-80",
169 "NS_4551-2",
170 "videotex-suppl",
171 /* 60 */
172 "PT2",
173 "ES2",
174 "MSZ_7795.3",
175 "JIS_C6226-1983",
176 "greek7",
177 "ASMO_449",
178 "iso-ir-90",
179 "JIS_C6229-1984-a",
180 "JIS_C6229-1984-b",
181 "JIS_C6229-1984-b-add",
182 /* 70 */
183 "JIS_C6229-1984-hand",
184 "JIS_C6229-1984-hand-add",
185 "JIS_C6229-1984-kana",
186 "ISO_2033-1983",
187 "ANSI_X3.110-1983",
188 "T.61-7bit",
189 "T.61-8bit",
190 "ECMA-cyrillic",
191 "CSA_Z243.4-1985-1",
192 "CSA_Z243.4-1985-2",
193 /* 80 */
194 "CSA_Z243.4-1985-gr",
195 "ISO_8859-6-E",
196 "ISO_8859-6-I",
197 "T.101-G2",
198 "ISO_8859-8-E",
199 "ISO_8859-8-I",
200 "CSN_369103",
201 "JUS_I.B1.002",
202 "IEC_P27-1",
203 "JUS_I.B1.003-serb",
204 /* 90 */
205 "JUS_I.B1.003-mac",
206 "greek-ccitt",
207 "NC_NC00-10:81",
208 "ISO_6937-2-25",
209 "GOST_19768-74",
210 "ISO_8859-supp",
211 "ISO_10367-box",
212 "latin-lap",
213 "JIS_X0212-1990",
214 "DS_2089",
215 /* 100 */
216 "us-dk",
217 "dk-us",
218 "KSC5636",
219 "UNICODE-1-1-UTF-7",
220 "ISO-2022-CN",
221 "ISO-2022-CN-EXT",
222 "UTF-8",
223 nullptr, nullptr,
224 "ISO-8859-13",
225 /* 110 */
226 "ISO-8859-14",
227 "ISO-8859-15",
228 "ISO-8859-16",
229 "GBK",
230 "GB18030",
231 "OSD_EBCDIC_DF04_15",
232 "OSD_EBCDIC_DF03_IRV",
233 "OSD_EBCDIC_DF04_1",
234 "ISO-11548-1",
235 "KZ-1048",
236 /* 120 */
237 nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr,
238 /* 130 */
239 nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr,
240 /* 140 */
241 nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr,
242 /* 150 */
243 nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr,
244 /* 160 */
245 nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr,
246 /* 170 */
247 nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr,
248 /* 180 */
249 nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr,
250 /* 190 */
251 nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr,
252 /* 200 */
253 nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr,
254 /* 210 */
255 nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr,
256 /* 220 */
257 nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr,
258 /* 230 */
259 nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr,
260 /* 240 */
261 nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr,
262 /* 250 */
263 nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr,
264 /* 260 */
265 nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr,
266 /* 270 */
267 nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr,
268 /* 280 */
269 nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr,
270 /* 290 */
271 nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr,
272 /* 300 */
273 nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr,
274 /* 310 */
275 nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr,
276 /* 320 */
277 nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr,
278 /* 330 */
279 nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr,
280 /* 340 */
281 nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr,
282 /* 350 */
283 nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr,
284 /* 360 */
285 nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr,
286 /* 370 */
287 nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr,
288 /* 380 */
289 nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr,
290 /* 390 */
291 nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr,
292 /* 400 */
293 nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr,
294 /* 410 */
295 nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr,
296 /* 420 */
297 nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr,
298 /* 430 */
299 nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr,
300 /* 440 */
301 nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr,
302 /* 450 */
303 nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr,
304 /* 460 */
305 nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr,
306 /* 470 */
307 nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr,
308 /* 480 */
309 nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr,
310 /* 490 */
311 nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr,
312 /* 500 */
313 nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr,
314 /* 510 */
315 nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr,
316 /* 520 */
317 nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr,
318 /* 530 */
319 nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr,
320 /* 540 */
321 nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr,
322 /* 550 */
323 nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr,
324 /* 560 */
325 nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr,
326 /* 570 */
327 nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr,
328 /* 580 */
329 nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr,
330 /* 590 */
331 nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr,
332 /* 600 */
333 nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr,
334 /* 610 */
335 nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr,
336 /* 620 */
337 nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr,
338 /* 630 */
339 nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr,
340 /* 640 */
341 nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr,
342 /* 650 */
343 nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr,
344 /* 660 */
345 nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr,
346 /* 670 */
347 nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr,
348 /* 680 */
349 nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr,
350 /* 690 */
351 nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr,
352 /* 700 */
353 nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr,
354 /* 710 */
355 nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr,
356 /* 720 */
357 nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr,
358 /* 730 */
359 nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr,
360 /* 740 */
361 nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr,
362 /* 750 */
363 nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr,
364 /* 760 */
365 nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr,
366 /* 770 */
367 nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr,
368 /* 780 */
369 nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr,
370 /* 790 */
371 nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr,
372 /* 800 */
373 nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr,
374 /* 810 */
375 nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr,
376 /* 820 */
377 nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr,
378 /* 830 */
379 nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr,
380 /* 840 */
381 nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr,
382 /* 850 */
383 nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr,
384 /* 860 */
385 nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr,
386 /* 870 */
387 nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr,
388 /* 880 */
389 nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr,
390 /* 890 */
391 nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr,
392 /* 900 */
393 nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr,
394 /* 910 */
395 nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr,
396 /* 920 */
397 nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr,
398 /* 930 */
399 nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr,
400 /* 940 */
401 nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr,
402 /* 950 */
403 nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr,
404 /* 960 */
405 nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr,
406 /* 970 */
407 nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr,
408 /* 980 */
409 nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr,
410 /* 990 */
411 nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr,
412 /* 1000 */
413 "ISO-10646-UCS-2",
414 "ISO-10646-UCS-4",
415 "ISO-10646-UCS-Basic",
416 "ISO-10646-Unicode-Latin1",
417 "ISO-10646-J-1",
418 "ISO-Unicode-IBM-1261",
419 "ISO-Unicode-IBM-1268",
420 "ISO-Unicode-IBM-1276",
421 "ISO-Unicode-IBM-1264",
422 "ISO-Unicode-IBM-1265",
423 /* 1010 */
424 "UNICODE-1-1",
425 "SCSU",
426 "UTF-7",
427 "UTF-16BE",
428 "UTF-16LE",
429 "UTF-16",
430 "CESU-8",
431 "UTF-32",
432 "UTF-32BE",
433 "UTF-32LE",
434 /* 1020 */
435 "BOCU-1",
436 nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr,
437 /* 1030 */
438 nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr,
439 /* 1040 */
440 nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr,
441 /* 1050 */
442 nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr,
443 /* 1060 */
444 nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr,
445 /* 1070 */
446 nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr,
447 /* 1080 */
448 nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr,
449 /* 1090 */
450 nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr,
451 /* 1100 */
452 nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr,
453 /* 1110 */
454 nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr,
455 /* 1120 */
456 nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr,
457 /* 1130 */
458 nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr,
459 /* 1140 */
460 nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr,
461 /* 1150 */
462 nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr,
463 /* 1160 */
464 nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr,
465 /* 1170 */
466 nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr,
467 /* 1180 */
468 nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr,
469 /* 1190 */
470 nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr,
471 /* 1200 */
472 nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr,
473 /* 1210 */
474 nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr,
475 /* 1220 */
476 nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr,
477 /* 1230 */
478 nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr,
479 /* 1240 */
480 nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr,
481 /* 1250 */
482 nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr,
483 /* 1260 */
484 nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr,
485 /* 1270 */
486 nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr,
487 /* 1280 */
488 nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr,
489 /* 1290 */
490 nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr,
491 /* 1300 */
492 nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr,
493 /* 1310 */
494 nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr,
495 /* 1320 */
496 nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr,
497 /* 1330 */
498 nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr,
499 /* 1340 */
500 nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr,
501 /* 1350 */
502 nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr,
503 /* 1360 */
504 nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr,
505 /* 1370 */
506 nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr,
507 /* 1380 */
508 nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr,
509 /* 1390 */
510 nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr,
511 /* 1400 */
512 nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr,
513 /* 1410 */
514 nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr,
515 /* 1420 */
516 nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr,
517 /* 1430 */
518 nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr,
519 /* 1440 */
520 nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr,
521 /* 1450 */
522 nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr,
523 /* 1460 */
524 nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr,
525 /* 1470 */
526 nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr,
527 /* 1480 */
528 nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr,
529 /* 1490 */
530 nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr,
531 /* 1500 */
532 nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr,
533 /* 1510 */
534 nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr,
535 /* 1520 */
536 nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr,
537 /* 1530 */
538 nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr,
539 /* 1540 */
540 nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr,
541 /* 1550 */
542 nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr,
543 /* 1560 */
544 nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr,
545 /* 1570 */
546 nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr,
547 /* 1580 */
548 nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr,
549 /* 1590 */
550 nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr,
551 /* 1600 */
552 nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr,
553 /* 1610 */
554 nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr,
555 /* 1620 */
556 nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr,
557 /* 1630 */
558 nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr,
559 /* 1640 */
560 nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr,
561 /* 1650 */
562 nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr,
563 /* 1660 */
564 nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr,
565 /* 1670 */
566 nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr,
567 /* 1680 */
568 nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr,
569 /* 1690 */
570 nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr,
571 /* 1700 */
572 nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr,
573 /* 1710 */
574 nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr,
575 /* 1720 */
576 nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr,
577 /* 1730 */
578 nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr,
579 /* 1740 */
580 nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr,
581 /* 1750 */
582 nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr,
583 /* 1760 */
584 nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr,
585 /* 1770 */
586 nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr,
587 /* 1780 */
588 nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr,
589 /* 1790 */
590 nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr,
591 /* 1800 */
592 nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr,
593 /* 1810 */
594 nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr,
595 /* 1820 */
596 nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr,
597 /* 1830 */
598 nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr,
599 /* 1840 */
600 nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr,
601 /* 1850 */
602 nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr,
603 /* 1860 */
604 nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr,
605 /* 1870 */
606 nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr,
607 /* 1880 */
608 nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr,
609 /* 1890 */
610 nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr,
611 /* 1900 */
612 nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr,
613 /* 1910 */
614 nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr,
615 /* 1920 */
616 nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr,
617 /* 1930 */
618 nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr,
619 /* 1940 */
620 nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr,
621 /* 1950 */
622 nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr,
623 /* 1960 */
624 nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr,
625 /* 1970 */
626 nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr,
627 /* 1980 */
628 nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr,
629 /* 1990 */
630 nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr,
631 /* 2000 */
632 "ISO-8859-1-Windows-3.0-Latin-1",
633 "ISO-8859-1-Windows-3.1-Latin-1",
634 "ISO-8859-2-Windows-Latin-2",
635 "ISO-8859-9-Windows-Latin-5",
636 "hp-roman8",
637 "Adobe-Standard-Encoding",
638 "Ventura-US",
639 "Ventura-International",
640 "DEC-MCS",
641 "IBM850",
642 /* 2010 */
643 "IBM852",
644 "IBM437",
645 "PC8-Danish-Norwegian",
646 "IBM862",
647 "PC8-Turkish",
648 "IBM-Symbols",
649 "IBM-Thai",
650 "HP-Legal",
651 "HP-Pi-font",
652 "HP-Math8",
653 /* 2020 */
654 "Adobe-Symbol-Encoding",
655 "HP-DeskTop",
656 "Ventura-Math",
657 "Microsoft-Publishing",
658 "Windows-31J",
659 "GB2312",
660 "Big5",
661 "macintosh",
662 "IBM037",
663 "IBM038",
664 /* 2030 */
665 "IBM273",
666 "IBM274",
667 "IBM275",
668 "IBM277",
669 "IBM278",
670 "IBM280",
671 "IBM281",
672 "IBM284",
673 "IBM285",
674 "IBM290",
675 /* 2040 */
676 "IBM297",
677 "IBM420",
678 "IBM423",
679 "IBM424",
680 "IBM500",
681 "IBM851",
682 "IBM855",
683 "IBM857",
684 "IBM860",
685 "IBM861",
686 /* 2050 */
687 "IBM863",
688 "IBM864",
689 "IBM865",
690 "IBM868",
691 "IBM869",
692 "IBM870",
693 "IBM871",
694 "IBM880",
695 "IBM891",
696 "IBM903",
697 /* 2060 */
698 "IBM904",
699 "IBM905",
700 "IBM918",
701 "IBM1026",
702 "EBCDIC-AT-DE",
703 "EBCDIC-AT-DE-A",
704 "EBCDIC-CA-FR",
705 "EBCDIC-DK-NO",
706 "EBCDIC-DK-NO-A",
707 "EBCDIC-FI-SE",
708 /* 2070 */
709 "EBCDIC-FI-SE-A",
710 "EBCDIC-FR",
711 "EBCDIC-IT",
712 "EBCDIC-PT",
713 "EBCDIC-ES",
714 "EBCDIC-ES-A",
715 "EBCDIC-ES-S",
716 "EBCDIC-UK",
717 "EBCDIC-US",
718 "UNKNOWN-8BIT",
719 /* 2080 */
720 "MNEMONIC",
721 "MNEM",
722 "VISCII",
723 "VIQR",
724 "KOI8-R",
725 "HZ-GB-2312",
726 "IBM866",
727 "IBM775",
728 "KOI8-U",
729 "IBM00858",
730 /* 2090 */
731 "IBM00924",
732 "IBM01140",
733 "IBM01141",
734 "IBM01142",
735 "IBM01143",
736 "IBM01144",
737 "IBM01145",
738 "IBM01146",
739 "IBM01147",
740 "IBM01148",
741 /* 2100 */
742 "IBM01149",
743 "Big5-HKSCS",
744 "IBM1047",
745 "PTCP154",
746 "Amiga-1251",
747 "KOI7-switched",
748 "BRF",
749 "TSCII",
750 "CP51932",
751 "windows-874",
752 /* 2110 */
753 nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr,
754 /* 2120 */
755 nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr,
756 /* 2130 */
757 nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr,
758 /* 2140 */
759 nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr,
760 /* 2150 */
761 nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr,
762 /* 2160 */
763 nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr,
764 /* 2170 */
765 nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr,
766 /* 2180 */
767 nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr,
768 /* 2190 */
769 nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr,
770 /* 2200 */
771 nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr,
772 /* 2210 */
773 nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr,
774 /* 2220 */
775 nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr,
776 /* 2230 */
777 nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr,
778 /* 2240 */
779 nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr,
780 /* 2250 */
781 "windows-1250",
782 "windows-1251",
783 "windows-1252",
784 "windows-1253",
785 "windows-1254",
786 "windows-1255",
787 "windows-1256",
788 "windows-1257",
789 "windows-1258",
790 "TIS-620",
791 /* 2260 */
792 "CP50220",
793 };
794
795 }
796
797 }
798
799 namespace libebook
800 {
801 namespace
802 {
803
804 struct PluckerAttributes
805 {
806 PluckerAttributes();
807
808 Font font;
809 unsigned leftMargin;
810 unsigned rightMargin;
811 TextAlignment textAlignment;
812 bool italic;
813 bool underline;
814 bool strikethrough;
815 };
816
PluckerAttributes()817 PluckerAttributes::PluckerAttributes()
818 : font(FONT_REGULAR)
819 , leftMargin(0)
820 , rightMargin(0)
821 , textAlignment(TEXT_ALIGNMENT_LEFT)
822 , italic(false)
823 , underline(false)
824 , strikethrough(false)
825 {
826 }
827
makeParagraphProperties(const PluckerAttributes & attributes)828 librevenge::RVNGPropertyList makeParagraphProperties(const PluckerAttributes &attributes)
829 {
830 librevenge::RVNGPropertyList props;
831
832 switch (attributes.textAlignment)
833 {
834 case TEXT_ALIGNMENT_LEFT :
835 props.insert("fo:text-align", "left");
836 break;
837 case TEXT_ALIGNMENT_RIGHT :
838 props.insert("fo:text-align", "end");
839 break;
840 case TEXT_ALIGNMENT_CENTER :
841 props.insert("fo:text-align", "center");
842 break;
843 default:
844 break;
845 }
846
847 return props;
848 }
849
makeCharacterProperties(const PluckerAttributes & attributes)850 librevenge::RVNGPropertyList makeCharacterProperties(const PluckerAttributes &attributes)
851 {
852 librevenge::RVNGPropertyList props;
853
854 if (attributes.italic)
855 props.insert("fo:font-style", "italic");
856
857 if (attributes.underline)
858 props.insert("style:text-underline-type", "single");
859
860 if (attributes.strikethrough)
861 props.insert("style:text-line-through-type", "single");
862
863 if (((FONT_H1 <= attributes.font) && (FONT_H6 >= attributes.font)) || (FONT_BOLD == attributes.font))
864 props.insert("fo:font-weight", "bold");
865
866 return props;
867 }
868
869 class MarkupParser
870 {
871 // -Weffc++
872 MarkupParser(const MarkupParser &other);
873 MarkupParser &operator=(const MarkupParser &other);
874
875 public:
876 MarkupParser(librevenge::RVNGTextInterface *document, const PluckerImageMap_t &imageMap);
877 ~MarkupParser();
878
879 /** Parse an input stream.
880 *
881 * The function can be called more than once. In that case, the
882 * parsing continues with the old state.
883 *
884 * @arg[in] input input stream
885 * @arg[in] paragraphLengths lengths of paragraphs in the text block
886 */
887 void parse(librevenge::RVNGInputStream *input, const vector<unsigned> ¶graphLengths);
888
889 private:
890 void flushText(bool endOfParagraph = false);
891
892 void closeParagraph();
893
894 /** Insert a line break.
895 *
896 * Only line breaks in the middle of a paragraph (e.g., separators of
897 * verses in a poem) are really inserted. Line breaks at the
898 * beginning of a paragraph (before any text) and at the end of a
899 * paragraph (after all text) are ignored.
900 */
901 void insertLineBreak();
902
903 void insertImage(unsigned id);
904
905 private:
906 librevenge::RVNGTextInterface *m_document;
907 const PluckerImageMap_t &m_imageMap;
908
909 librevenge::RVNGInputStream *m_input;
910
911 PluckerAttributes m_attributes;
912
913 std::string m_text;
914
915 unsigned m_lineBreaks;
916
917 bool m_paragraphOpened;
918 };
919
MarkupParser(librevenge::RVNGTextInterface * const document,const PluckerImageMap_t & imageMap)920 MarkupParser::MarkupParser(librevenge::RVNGTextInterface *const document, const PluckerImageMap_t &imageMap)
921 : m_document(document)
922 , m_imageMap(imageMap)
923 , m_input(nullptr)
924 , m_attributes()
925 , m_text()
926 , m_lineBreaks(0)
927 , m_paragraphOpened(false)
928 {
929 }
930
~MarkupParser()931 MarkupParser::~MarkupParser()
932 {
933 closeParagraph();
934 }
935
parse(librevenge::RVNGInputStream * const input,const vector<unsigned> & paragraphLengths)936 void MarkupParser::parse(librevenge::RVNGInputStream *const input, const vector<unsigned> ¶graphLengths)
937 {
938 unsigned para = 0;
939 unsigned chars = 0;
940
941 while (!input->isEnd())
942 {
943 const unsigned char c = readU8(input);
944 ++chars;
945
946 if (0 == c)
947 {
948 const unsigned char function = readU8(input);
949 ++chars;
950
951 switch (function)
952 {
953 case PAGE_LINK_BEGIN :
954 skip(input, 2);
955 chars += 2;
956 break;
957 case PARAGRAPH_LINK_BEGIN :
958 skip(input, 4);
959 chars += 4;
960 break;
961 case LINK_END :
962 break;
963 case SET_FONT :
964 {
965 const unsigned char font = readU8(input);
966 ++chars;
967 if (FONT_LAST >= font)
968 m_attributes.font = static_cast<Font>(font);
969 else
970 {
971 EBOOK_DEBUG_MSG(("unknown font specifier %d\n", font));
972 }
973 break;
974 }
975 case EMBEDDED_IMAGE :
976 {
977 const unsigned imageID = readU16(input, true);
978 chars += 2;
979 insertImage(imageID);
980 break;
981 }
982 case SET_MARGIN :
983 m_attributes.leftMargin = readU8(input);
984 m_attributes.rightMargin = readU8(input);
985 chars += 2;
986 break;
987 case TEXT_ALIGNMENT :
988 {
989 const unsigned alignmnent = readU8(input);
990 ++chars;
991 if (TEXT_ALIGNMENT_LAST >= alignmnent)
992 m_attributes.textAlignment = static_cast<TextAlignment>(alignmnent);
993 else
994 {
995 EBOOK_DEBUG_MSG(("unknown text alignment %d\n", (int) alignmnent));
996 }
997 break;
998 }
999 case HORIZONTAL_RULE :
1000 // ignore
1001 skip(input, 3);
1002 chars += 3;
1003 break;
1004 case NEW_LINE :
1005 flushText();
1006 insertLineBreak();
1007 break;
1008 case ITALIC_BEGIN :
1009 flushText();
1010 m_attributes.italic = true;
1011 break;
1012 case ITALIC_END :
1013 flushText();
1014 m_attributes.italic = false;
1015 break;
1016 case UNKNOWN_53 :
1017 // TODO: find what this is
1018 skip(input, 3);
1019 chars += 3;
1020 break;
1021 case MULTIPLE_EMBEDDED_IMAGE :
1022 // TODO: implement me
1023 skip(input, 4);
1024 chars += 4;
1025 break;
1026 case UNDERLINE_BEGIN :
1027 flushText();
1028 m_attributes.underline = true;
1029 break;
1030 case UNDERLINE_END :
1031 flushText();
1032 m_attributes.underline = false;
1033 break;
1034 case STRIKETHROUGH_BEGIN :
1035 flushText();
1036 m_attributes.strikethrough = true;
1037 break;
1038 case STRIKETHROUGH_END :
1039 flushText();
1040 m_attributes.strikethrough = false;
1041 break;
1042 default :
1043 EBOOK_DEBUG_MSG(("unknown function code %x\n", function));
1044 break;
1045 }
1046 }
1047 else
1048 {
1049 m_text.push_back((char) c);
1050 }
1051
1052 if ((paragraphLengths.size() > para) && (paragraphLengths[para] <= chars))
1053 {
1054 closeParagraph();
1055 ++para;
1056 chars = 0;
1057 }
1058 }
1059 }
1060
flushText(bool endOfParagraph)1061 void MarkupParser::flushText(bool endOfParagraph)
1062 {
1063 if (!m_paragraphOpened)
1064 {
1065 m_document->openParagraph(makeParagraphProperties(m_attributes));
1066 m_paragraphOpened = true;
1067 m_lineBreaks = 0;
1068 }
1069
1070 // Many files I have seen have a line break followed by a space at the
1071 // end of paragraphs. IMHO that might be safely thrown away.
1072 if (!m_text.empty() && (!endOfParagraph || (std::string::npos != m_text.find_first_not_of(" "))))
1073 {
1074 // pending line break(s)
1075 if (0 != m_lineBreaks)
1076 {
1077 for (unsigned i = 0; i != m_lineBreaks; ++i)
1078 m_document->insertLineBreak();
1079 m_lineBreaks = 0;
1080 }
1081
1082 m_document->openSpan(makeCharacterProperties(m_attributes));
1083 m_document->insertText(librevenge::RVNGString(m_text.c_str()));
1084 m_text.clear();
1085 m_document->closeSpan();
1086 }
1087 }
1088
closeParagraph()1089 void MarkupParser::closeParagraph()
1090 {
1091 flushText(true);
1092
1093 m_document->closeParagraph();
1094 m_paragraphOpened = false;
1095 }
1096
insertLineBreak()1097 void MarkupParser::insertLineBreak()
1098 {
1099 ++m_lineBreaks;
1100 }
1101
insertImage(const unsigned id)1102 void MarkupParser::insertImage(const unsigned id)
1103 {
1104 const PluckerImageMap_t::const_iterator it = m_imageMap.find(id);
1105 if (m_imageMap.end() != it)
1106 {
1107 librevenge::RVNGPropertyList props;
1108 const librevenge::RVNGBinaryData data(&(it->second)[0], it->second.size());
1109 props.insert("office:binary-data", data);
1110 m_document->insertBinaryObject(props);
1111 }
1112 }
1113
1114 }
1115 }
1116
1117 namespace libebook
1118 {
1119
1120 struct PluckerHeader
1121 {
1122 PluckerHeader();
1123
1124 bool isValid() const;
1125
1126 Compression compression;
1127 bool valid;
1128 bool validAppInfo;
1129 };
1130
1131 struct PluckerParserState
1132 {
1133 PluckerParserState();
1134
1135 PluckerImageMap_t m_imageMap;
1136 shared_ptr<MarkupParser> markupParser;
1137 shared_ptr<EBOOKCharsetConverter> charsetConverter;
1138 bool knownEncoding;
1139 ExceptionalCharsetMap_t exceptionalCharsetMap;
1140 };
1141
1142 struct PluckerRecordHeader
1143 {
1144 PluckerRecordHeader();
1145
1146 unsigned number;
1147 unsigned uid;
1148 unsigned paragraphs;
1149 unsigned size;
1150 DataType type;
1151 };
1152
PluckerHeader()1153 PluckerHeader::PluckerHeader()
1154 : compression(COMPRESSION_UNKNOWN)
1155 , valid(false)
1156 , validAppInfo(true)
1157 {
1158 }
1159
isValid() const1160 bool PluckerHeader::isValid() const
1161 {
1162 return (COMPRESSION_UNKNOWN != compression) && valid && validAppInfo;
1163 }
1164
PluckerParserState()1165 PluckerParserState::PluckerParserState()
1166 : m_imageMap()
1167 , markupParser()
1168 , charsetConverter()
1169 , knownEncoding(false)
1170 , exceptionalCharsetMap()
1171 {
1172 }
1173
PluckerRecordHeader()1174 PluckerRecordHeader::PluckerRecordHeader()
1175 : number(0)
1176 , uid(0)
1177 , paragraphs(0)
1178 , size(0)
1179 , type(DATA_TYPE_UNKNOWN)
1180 {
1181 }
1182
1183 }
1184
1185 namespace libebook
1186 {
1187
PluckerParser(librevenge::RVNGInputStream * const input,librevenge::RVNGTextInterface * const document)1188 PluckerParser::PluckerParser(librevenge::RVNGInputStream *const input, librevenge::RVNGTextInterface *const document)
1189 : PDBParser(input, document, PLUCKER_TYPE, PLUCKER_CREATOR)
1190 , m_header()
1191 , m_state(new PluckerParserState())
1192 {
1193 if (!m_header)
1194 m_header.reset(new PluckerHeader());
1195
1196 const std::unique_ptr<librevenge::RVNGInputStream> record(getIndexRecord());
1197 readIndexRecord(record.get());
1198
1199 if (!m_header->isValid())
1200 throw UnsupportedFormat();
1201 }
1202
checkType(const unsigned type,const unsigned creator)1203 bool PluckerParser::checkType(const unsigned type, const unsigned creator)
1204 {
1205 return (PLUCKER_TYPE == type) && (PLUCKER_CREATOR == creator);
1206 }
1207
readAppInfoRecord(librevenge::RVNGInputStream * const record)1208 void PluckerParser::readAppInfoRecord(librevenge::RVNGInputStream *const record)
1209 {
1210 const uint32_t signature = readU32(record, true);
1211 const unsigned version = readU16(record, true);
1212 const unsigned encoding = readU16(record, true);
1213
1214 m_header->validAppInfo = (APPINFO_SIGNATURE == signature) && (3 == version) && (0 == encoding);
1215 }
1216
readSortInfoRecord(librevenge::RVNGInputStream *)1217 void PluckerParser::readSortInfoRecord(librevenge::RVNGInputStream *)
1218 {
1219 // there is no sortInfo record in Plucker
1220 }
1221
readIndexRecord(librevenge::RVNGInputStream * const record)1222 void PluckerParser::readIndexRecord(librevenge::RVNGInputStream *const record)
1223 {
1224 if (!m_header)
1225 m_header.reset(new PluckerHeader());
1226
1227 m_header->valid = 1 == readU16(record, true);
1228
1229 const unsigned version = readU16(record, true);
1230 switch (version)
1231 {
1232 case 1 :
1233 m_header->compression = COMPRESSION_LZ77;
1234 break;
1235 case 2 :
1236 m_header->compression = COMPRESSION_ZLIB;
1237 break;
1238 default :
1239 EBOOK_DEBUG_MSG(("unknown compression %d\n", (int) version));
1240 break;
1241 }
1242 }
1243
readDataRecord(librevenge::RVNGInputStream * const record,bool)1244 void PluckerParser::readDataRecord(librevenge::RVNGInputStream *const record, bool)
1245 {
1246 // TODO: implement me
1247 (void) record;
1248 }
1249
readDataRecords()1250 void PluckerParser::readDataRecords()
1251 {
1252 vector<PluckerRecordHeader> textRecords;
1253
1254 // Process in two phases:
1255
1256 // 1. save images, process metadata and (since we are reading the
1257 // record headers anyway) save data about text records
1258 for (unsigned i = 0; i < getDataRecordCount(); ++i)
1259 {
1260 const unique_ptr<librevenge::RVNGInputStream> record(getDataRecord(i));
1261
1262 PluckerRecordHeader header;
1263 header.number = i;
1264 header.uid = readU16(record.get(), true);
1265 header.paragraphs = readU16(record.get(), true);
1266 header.size = readU16(record.get(), true);
1267 const unsigned typeNum = readU8(record.get(), true);
1268 header.type = DATA_TYPE_UNKNOWN;
1269
1270 if (DATA_TYPE_LAST >= typeNum)
1271 header.type = static_cast<DataType>(typeNum);
1272
1273 switch (header.type)
1274 {
1275 case DATA_TYPE_PHTML :
1276 case DATA_TYPE_PHTML_COMPRESSED :
1277 textRecords.push_back(header);
1278 break;
1279 case DATA_TYPE_TBMP :
1280 case DATA_TYPE_TBMP_COMPRESSED :
1281 {
1282 librevenge::RVNGInputStream *input = record.get();
1283
1284 std::shared_ptr<librevenge::RVNGInputStream> uncompressed;
1285 if (DATA_TYPE_TBMP_COMPRESSED == header.type)
1286 {
1287 uncompressed = getUncompressedStream(input);
1288 input = uncompressed.get();
1289 }
1290
1291 readImage(input, header);
1292
1293 break;
1294 }
1295 case DATA_TYPE_METADATA :
1296 readMetadata(record.get(), header);
1297 break;
1298 case DATA_TYPE_MAILTO:
1299 case DATA_TYPE_LINK_INDEX:
1300 case DATA_TYPE_LINKS:
1301 case DATA_TYPE_LINKS_COMPRESSED:
1302 case DATA_TYPE_BOOKMARKS:
1303 case DATA_TYPE_CATEGORY:
1304 case DATA_TYPE_UNKNOWN:
1305 default :
1306 // not interesting
1307 break;
1308 }
1309 }
1310
1311 // 2. process text records and generate output
1312 getDocument()->startDocument(librevenge::RVNGPropertyList());
1313 getDocument()->setDocumentMetaData(librevenge::RVNGPropertyList());
1314 getDocument()->openPageSpan(getDefaultPageSpanPropList());
1315
1316 // create markup parser
1317 m_state->markupParser.reset(new MarkupParser(getDocument(), m_state->m_imageMap));
1318
1319 for (vector<PluckerRecordHeader>::const_iterator it = textRecords.begin(); it != textRecords.end(); ++it)
1320 {
1321 const unique_ptr<librevenge::RVNGInputStream> record(getDataRecord(it->number));
1322
1323 if (it->type==DATA_TYPE_PHTML || it->type==DATA_TYPE_PHTML_COMPRESSED)
1324 {
1325 librevenge::RVNGInputStream *input = record.get();
1326
1327 skip(input, 8);
1328
1329 vector<unsigned> paraLengths;
1330 for (unsigned i = 0; i != it->paragraphs; ++i)
1331 {
1332 paraLengths.push_back(readU16(input, true));
1333 skip(input, 2);
1334 }
1335
1336 shared_ptr<librevenge::RVNGInputStream> uncompressed;
1337 if (DATA_TYPE_PHTML_COMPRESSED == it->type)
1338 {
1339 uncompressed = getUncompressedStream(input);
1340 input = uncompressed.get();
1341 }
1342
1343 readText(input, *it, paraLengths);
1344
1345 break;
1346 }
1347 else
1348 {
1349 // how comes?
1350 EBOOK_DEBUG_MSG(("unknown data type %d for text record\n", it->type));
1351 }
1352 }
1353
1354 m_state->markupParser.reset();
1355
1356 getDocument()->closePageSpan();
1357 getDocument()->endDocument();
1358 }
1359
readMetadata(librevenge::RVNGInputStream * const input,const PluckerRecordHeader &)1360 void PluckerParser::readMetadata(librevenge::RVNGInputStream *const input, const PluckerRecordHeader &)
1361 {
1362 const unsigned count = readU16(input, true);
1363 for (unsigned i = 0; count != i; ++i)
1364 {
1365 const unsigned typeCode = readU16(input, true);
1366 const unsigned length = readU16(input, true);
1367
1368 switch (typeCode)
1369 {
1370 case 1 : // charset
1371 if (1 == length)
1372 {
1373 const unsigned mib = readU16(input, true);
1374 const char *charset = nullptr;
1375 if (EBOOK_NUM_ELEMENTS(IANA_CHARSETS) > mib)
1376 charset = IANA_CHARSETS[mib];
1377 m_state->charsetConverter.reset(new EBOOKCharsetConverter(charset));
1378 m_state->knownEncoding = nullptr != charset;
1379 }
1380 else
1381 {
1382 EBOOK_DEBUG_MSG(("invalid record length %d for charset record\n", (int) length));
1383 }
1384 break;
1385 case 2 : // exceptional charsets
1386 for (unsigned j = 0; length != j; j += 2)
1387 {
1388 const unsigned id = readU16(input, true);
1389 const unsigned mib = readU16(input, true);
1390 m_state->exceptionalCharsetMap[id] = mib;
1391 }
1392 break;
1393 default :
1394 EBOOK_DEBUG_MSG(("unknown type code %d in metadata record\n", (int) typeCode));
1395 }
1396 }
1397 }
1398
readImage(librevenge::RVNGInputStream * const input,const PluckerRecordHeader & header)1399 void PluckerParser::readImage(librevenge::RVNGInputStream *const input, const PluckerRecordHeader &header)
1400 {
1401 vector<unsigned char> data;
1402 while (!input->isEnd())
1403 data.push_back(readU8(input));
1404
1405 m_state->m_imageMap.insert(PluckerImageMap_t::value_type(header.uid, data));
1406 }
1407
readText(librevenge::RVNGInputStream * const input,const PluckerRecordHeader &,const std::vector<unsigned> & paragraphLengths)1408 void PluckerParser::readText(librevenge::RVNGInputStream *const input, const PluckerRecordHeader &, const std::vector<unsigned> ¶graphLengths)
1409 {
1410 m_state->markupParser->parse(input, paragraphLengths);
1411 }
1412
getUncompressedStream(librevenge::RVNGInputStream * const input) const1413 std::shared_ptr<librevenge::RVNGInputStream> PluckerParser::getUncompressedStream(librevenge::RVNGInputStream *const input) const
1414 {
1415 const auto pos = (unsigned long) input->tell();
1416 input->seek(0, librevenge::RVNG_SEEK_END);
1417 const unsigned long length = (unsigned long) input->tell() - pos;
1418 input->seek((long) pos, librevenge::RVNG_SEEK_SET);
1419 const unsigned char *bytes = readNBytes(input, length);
1420
1421 EBOOKMemoryStream data(bytes, static_cast<unsigned>(length));
1422
1423 shared_ptr<librevenge::RVNGInputStream> uncompressed;
1424 switch (m_header->compression)
1425 {
1426 case COMPRESSION_LZ77 :
1427 uncompressed.reset(new PDBLZ77Stream(&data));
1428 break;
1429 case COMPRESSION_ZLIB :
1430 uncompressed.reset(new EBOOKZlibStream(&data));
1431 break;
1432 case COMPRESSION_UNKNOWN:
1433 default :
1434 // not possible
1435 break;
1436 }
1437
1438 return uncompressed;
1439 }
1440
1441 } // namespace libebook
1442
1443 /* vim:set shiftwidth=2 softtabstop=2 expandtab: */
1444