parser.cpp
1/* This file is part of the KDE project
2 Copyright (C) 2001 Ariya Hidayat <ariyahidayat@yahoo.de>
3
4 This library is free software; you can redistribute it and/or
5 modify it under the terms of the GNU Library General Public
6 License as published by the Free Software Foundation; either
7 version 2 of the License, or (at your option) any later version.
8
9 This library is distributed in the hope that it will be useful,
10 but WITHOUT ANY WARRANTY; without even the implied warranty of
11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 Library General Public License for more details.
13
14 You should have received a copy of the GNU Library General Public License
15 along with this library; see the file COPYING.LIB. If not, write to
16 the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
17 * Boston, MA 02110-1301, USA.
18*/
19
20#include "parser.h"
21
22#include <tqmemarray.h>
23#include <tqdatastream.h>
24#include <tqfile.h>
25#include <tqptrlist.h>
26#include <tqstring.h>
27
28using namespace WP;
29
30static Token::Attr
31mapToAttr (int data)
32{
33 switch (data)
34 {
35 case 0:
36 return Token::ExtraLarge;
37 case 1:
38 return Token::VeryLarge;
39 case 2:
40 return Token::Large;
41 case 3:
42 return Token::Small;
43 case 4:
44 return Token::Fine;
45 case 5:
46 return Token::Superscript;
47 case 6:
48 return Token::Subscript;
49 case 7:
50 return Token::Outline;
51 case 8:
52 return Token::Italic;
53 case 9:
54 return Token::Shadow;
55 case 10:
56 return Token::Redline;
57 case 11:
58 return Token::DoubleUnderline;
59 case 12:
60 return Token::Bold;
61 case 13:
62 return Token::StrikedOut;
63 case 14:
64 return Token::Underline;
65 case 15:
66 return Token::SmallCaps;
67 case 16:
68 return Token::Blink;
69 };
70 return Token::None;
71}
72
73static Token::Align
74mapToAlign (int data)
75{
76 switch (data)
77 {
78 case 0:
79 return Token::Left;
80 case 1:
81 return Token::Full;
82 case 2:
83 return Token::Center;
84 case 3:
85 return Token::Right;
86 case 4:
87 return Token::All;
88 };
89 return Token::Left;
90}
91
92Parser::Parser ()
93{
94 tokens.setAutoDelete( true );
95 packets.setAutoDelete( true );
96}
97
98bool
99Parser::parse (const TQString & filename)
100{
101 // initialize
102 tokens.clear();
103 packets.clear();
104 docTitle = docAuthor = docAbstract = "";
105
106 // open input file and assign the stream
107 TQDataStream stream;
108 TQFile in (filename);
109 if (!in.open (IO_ReadOnly))
110 return false;
111 stream.setDevice (&in);
112
113 // must be little-endian
114 stream.setByteOrder (TQDataStream::LittleEndian);
115
116 // read 16-bytes document header
117 TQ_UINT8 header[16];
118 for (int k = 0; k < 16; k++)
119 stream >> header[k];
120
121 // check first 4 bytes, must be (in hex): 0xFF, 0x57, 0x50, 0x43
122 if ((header[0] != 0xFF) || (header[1] != 0x57) ||
123 (header[2] != 0x50) || (header[3] != 0x43))
124 return false;
125
126 // get document start
127 unsigned m_docstart = header[4] + (header[5] << 8) +
128 (header[6] << 16) + (header[7] << 24);
129 if (m_docstart > stream.device ()->size ())
130 return false;
131
132 // check document type
133 unsigned product_type = header[8];
134 unsigned file_type = header[9];
135 if ((product_type != 1) || (file_type != 10))
136 return false;
137
138 // check document format version: for WP 5.x or WP 6/7/8
139 // major 0 means WP 5.x, otherwise WP 6/7/8
140 unsigned major_version = header[10];
141 unsigned minor_version = header[11];
142 version = (major_version<<8) + minor_version;
143
144 // do not accept other than 0 (WP 5.x) and 2 (WP 6/7/8)
145 if ( (major_version != 0) && (major_version != 2) )
146 return false;
147
148 // check if this is encrypted
149 unsigned encrypt_hash = header[12] + (header[13] << 8);
150 if ( encrypt_hash ) return false;
151
152 in.close ();
153
154 // parse packets in prefix area
155 if( major_version==0 ) parsePacketWP5( filename );
156 else parsePacketWP6( filename );
157
158 // parse document area
159 if ( major_version == 0 ) parseDocWP5 ( filename, m_docstart );
160 else parseDocWP6 ( filename, m_docstart );
161
162 return true;
163}
164
165void
166Parser::parsePacketWP5( const TQString & filename )
167{
168 // open input file and assign the stream
169 TQDataStream stream;
170 TQFile in (filename);
171 if (!in.open (IO_ReadOnly))
172 return;
173 stream.setDevice (&in);
174
175 unsigned filesize = stream.device()->size();
176
177 // must be little-endian
178 stream.setByteOrder (TQDataStream::LittleEndian);
179
180 for( unsigned next_block=16; next_block>0; )
181 {
182 TQMemArray<TQ_UINT8> buf( 10 );
183 stream.device()->at( next_block );
184 for( int c=0; c<10; c++ )
185 stream >> buf.at( c );
186
187 unsigned type = buf[0] + (buf[1]<<8);
188 unsigned count = buf[2]+ (buf[3]<<8);
189 unsigned size = buf[4] + (buf[5]<<8);
190 next_block = buf[6] + (buf[7] << 8) + (buf[8] << 16) + (buf[9] << 24);
191
192 if( type != 0xfffb ) break;
193 if( size != 10*count ) break;
194
195 for( unsigned v=0; v<count; v++ )
196 {
197 TQ_UINT16 packet_type;
198 TQ_UINT32 packet_size, packet_pos;
199 stream >> packet_type;
200 stream >> packet_size;
201 stream >> packet_pos;
202
203 if( packet_type == 0 ) break;
204 if( packet_pos <= 0 ) continue;
205 if( packet_size < 0 ) continue;
206 if( packet_pos + packet_size > filesize ) continue;
207
208 Packet* p = new Packet;
209 p->type = packet_type;
210 p->pos = packet_pos;
211 p->size = packet_size;
212 packets.append( p );
213 }
214
215 }
216
217 // load all packets
218 for( TQPtrListIterator<Packet> it(packets); it; ++it )
219 {
220 Packet* p = it.current();
221 stream.device()->at( p->pos );
222 p->data.resize( p->size );
223 for( unsigned q = 0; q < p->size; q++ )
224 stream >> p->data.at(q );
225 }
226
227 in.close();
228
229 // process all known packets
230 for( TQPtrListIterator<Packet> i(packets); i; ++i )
231 {
232 Packet* p = i.current();
233 if( p->data.size()==0 ) continue;
234
235 // document sumary
236 if( p->type== 1 )
237 {
238 unsigned c;
239 TQString desc, desc_type, subject, author, typist, abstract;
240
241 // handle difference between WP 5.0 and WP 5.1
242 unsigned limit = (p->data[p->data.size()-1]==0xff) ? 94 : 57;
243
244 for( c=26; c<limit; c++)
245 desc.append( p->data[c] );
246 if( limit==94 )
247 for( c=94; (c<p->data.size())&&(p->data[c]); c++ )
248 desc_type.append( p->data[c] );
249
250 for( c++; (c<p->data.size())&&(p->data[c]); c++)
251 subject.append( p->data[c] );
252 for( c++; (c<p->data.size())&&(p->data[c]); c++)
253 author.append( p->data[c] );
254 for( c++; (c<p->data.size())&&(p->data[c]); c++)
255 typist.append( p->data[c] );
256 for( c++; (c<p->data.size())&&(p->data[c]); c++)
257 abstract.append( p->data[c] );
258
259 docTitle = desc.stripWhiteSpace();
260 docAuthor = author.stripWhiteSpace();
261 docAbstract = abstract.stripWhiteSpace();
262 }
263
264 }
265}
266
267void
268Parser::parsePacketWP6( const TQString & filename )
269{
270 // open input file and assign the stream
271 TQDataStream stream;
272 TQFile in (filename);
273 if (!in.open (IO_ReadOnly))
274 return;
275 stream.setDevice (&in);
276
277 unsigned filesize = stream.device()->size();
278
279 // must be little-endian
280 stream.setByteOrder (TQDataStream::LittleEndian);
281
282 TQ_UINT16 flag, count;
283 stream.device()->at( 0x200 );
284
285 stream >> flag; // FIXME should be checked == 2 ?
286 stream >> count;
287
288 stream.device()->at( 0x20e );
289 for( unsigned c=0; c<count; c++ )
290 {
291 TQ_UINT8 packet_type, packet_flag;
292 TQ_UINT16 count, hidcount;
293 TQ_UINT32 packet_size, packet_pos;
294
295 stream >> packet_flag;
296 stream >> packet_type;
297 stream >> count;
298 stream >> hidcount;
299 stream >> packet_size;
300 stream >> packet_pos;
301
302 if( packet_pos + packet_size > filesize ) continue;
303
304 Packet* p = new Packet;
305 p->type = packet_type;
306 p->pos = packet_pos;
307 p->size = packet_size;
308 packets.append( p );
309 }
310
311 // load all packets
312 for( TQPtrListIterator<Packet> it(packets); it; ++it )
313 {
314 Packet* p = it.current();
315 stream.device()->at( p->pos );
316 p->data.resize( p->size );
317 for( unsigned q = 0; q < p->size; q++ )
318 stream >> p->data.at(q );
319 }
320
321 in.close();
322
323 // process all known packets
324 for( TQPtrListIterator<Packet> i(packets); i; ++i )
325 {
326 Packet* p = i.current();
327 if( p->data.size()==0 ) continue;
328
329 // extended document summary
330 if( p->type == 18 )
331 {
332 for( unsigned j=0; j<p->data.size();)
333 {
334 unsigned size = p->data[j] + (p->data[j+1]<<8);
335 unsigned tag = p->data[j+2] + (p->data[j+3]<<8);
336 TQString str;
337 for( unsigned k=0; k<size-8; k++)
338 if(!((j+8+k)&1))
339 if( p->data[j+8+k]==0 ) break;
340 else str.append( p->data[j+8+k] );
341
342 str = str.stripWhiteSpace();
343
344 if( tag==1 ) docAbstract = str;
345 if( tag==5 ) docAuthor = str;
346 if( tag==17 ) docTitle = str;
347
348 j+= size;
349 }
350 }
351
352 }
353
354}
355
356void
357Parser::parseDocWP5( const TQString & filename, int start )
358{
359 // open input file and assign the stream
360 TQDataStream stream;
361 TQFile in (filename);
362 if (!in.open (IO_ReadOnly))
363 return;
364 stream.setDevice (&in);
365
366 // sentinel
367 if ( start < 0 ) return;
368 if ( start >= stream.device ()->size () ) return;
369
370 // must be little-endian
371 stream.setByteOrder (TQDataStream::LittleEndian);
372
373 // seek to start of document area
374 stream.device ()->at (start);
375
376 // main loop
377 TQString text;
378 while (!stream.atEnd ())
379 {
380
381 // read one byte
382 TQ_UINT8 code;
383 stream >> code;
384
385 // ASCII printable characters ?
386 if ((code >= 33) && (code <= 127))
387 text.append ((char) code);
388 else
389 {
390 // either fixed-length or variable-length function
391
392 TQMemArray < TQ_UINT8 > data;
393 TQMemArray < TQ_UINT16 > pid;
394 TQ_UINT8 subfunction = 0;
395
396 if ((code >= 0xC0) && (code <= 0xCF))
397 {
398 TQ_UINT8 dummy;
399 unsigned lentab[] =
400 { 2, 7, 9, 1, 1, 3, 4, 5, 2, 3, 4, 4, 6, 8, 8, 10 };
401 unsigned length = lentab[code & 0x0F];
402 data.resize (length);
403 for (unsigned c = 0; c < length; c++)
404 stream >> data.at (c);
405 stream >> dummy; // FIXME should be checked == code ?
406 }
407 else if ((code >= 0xD0) && (code <= 0xFF))
408 {
409 TQ_UINT16 length;
410 stream >> subfunction;
411 stream >> length;
412
413 data.resize (length);
414 for (unsigned c = 0; (c < length) && !stream.atEnd (); c++)
415 stream >> data.at (c);
416 }
417
418 // NOTE: code < 32 is single-byte function
419
420 // this is to simplify
421 unsigned function = (code << 8) + subfunction;
422
423 // flush previous text first
424 if (!text.isEmpty ())
425 {
426 tokens.append (new Token (text));
427 text = "";
428 }
429
430 switch (function)
431 {
432
433 case 0x2000:
434 case 0x0d00:
435 case 0x0b00:
436 tokens.append (new Token (Token::SoftSpace));
437 break;
438
439 case 0xa900:
440 tokens.append (new Token (Token::HardHyphen));
441 break;
442
443 case 0x0a00:
444 case 0x9900:
445 case 0x8c00:
446 tokens.append (new Token (Token::HardReturn));
447 break;
448
449 case 0xc000:
450 tokens.append (new Token (Token::ExtChar, data[1], data[0]));
451 break;
452
453 case 0xc300:
454 tokens.append (new Token (Token::AttrOn, mapToAttr (data[0])));
455 break;
456
457 case 0xc400:
458 tokens.append (new Token (Token::AttrOff, mapToAttr (data[0])));
459 break;
460
461 case 0xd001:
462 tokens.append (new Token (Token::LeftMargin,
463 data[4] + (data[5] << 8)));
464 tokens.append (new Token (Token::RightMargin,
465 data[6] + (data[7] << 8)));
466 break;
467
468 case 0xd005:
469 tokens.append (new Token (Token::TopMargin,
470 data[4] + (data[5] << 8)));
471 tokens.append (new Token (Token::BottomMargin,
472 data[6] + (data[7] << 8)));
473 break;
474
475 // NOTE we store linespace as 1/65536th, i.e 655536 means single space
476 // on WP 5.x, (data[3]<<8)+data[2] is in 1/256th, so make 8-bit adjustment
477 case 0xd002:
478 tokens.append (new Token (Token::Linespace,
479 (data[2] << 8) + (data[3] << 16)));
480 break;
481
482 case 0xd006:
483 tokens.append (new Token (Token::Justification,
484 mapToAlign (data[1])));
485 break;
486
487 case 0xd100:
488 tokens.append (new Token (Token::FontColor,
489 data[3], data[4], data[5]));
490 break;
491
492 case 0xd101:
493 tokens.append (new Token (Token::FontSize,
494 (data[29] << 8) + data[28]));
495 break;
496
497 case 0x8300:
498 tokens.append (new Token (Token::SoftReturn));
499 // FIXME this is actually Soft End of Center/Align
500 break;
501
502 case 0xc500:
503 // TODO block protect on/off
504 break;
505
506 case 0xd311:
507 // TODO set language [Lang]
508 break;
509
510 case 0xd301:
511 // TODO set underline mode
512 break;
513
514 case 0xd700:
515 tokens.append (new Token (Token::MarkTocStart));
516 break;
517
518 case 0xd701:
519 tokens.append (new Token (Token::MarkTocEnd));
520 break;
521
522 case 0xdb00:
523 // TODO begin style on
524 break;
525
526 case 0xdb01:
527 // TODO end style on
528 break;
529
530 case 0xdb02:
531 // TODO global on
532 break;
533
534 case 0xdb03:
535 // TODO style off
536 break;
537
538 case 0xdc00:
539 tokens.append (new Token (Token::TableCell));
540 break;
541
542 case 0xdc01:
543 tokens.append (new Token (Token::TableRow));
544 break;
545
546 case 0xdc02:
547 tokens.append (new Token (Token::TableOff));
548 break;
549
550 default:
551 tokens.append (new Token (Token::Function, function));
552 }
553
554 }
555 }
556
557 // flush left-over text if any
558 if (!text.isEmpty ())
559 {
560 tokens.append (new Token (text));
561 text = "";
562 }
563}
564
565void
566Parser::parseDocWP6 (const TQString & filename, int start)
567{
568 // open input file and assign the stream
569 TQDataStream stream;
570 TQFile in (filename);
571 if (!in.open (IO_ReadOnly))
572 return;
573 stream.setDevice (&in);
574
575 // sentinel
576 if ( start < 0 ) return;
577 if ( start >= stream.device ()->size () ) return;
578
579 // must be little-endian
580 stream.setByteOrder (TQDataStream::LittleEndian);
581
582 // seek to start of document area
583 stream.device ()->at (start);
584
585 // main loop
586 TQString text;
587 while (!stream.atEnd ())
588 {
589
590 // read one byte
591 TQ_UINT8 code;
592 stream >> code;
593
594 // ASCII printable characters ?
595 if ((code >= 33) && (code <= 127))
596 text.append ((char) code);
597
598 // WP default extended international characters ?
599 else if ((code >= 1) && (code <= 32))
600 {
601 // flush previous text first
602 if (!text.isEmpty ())
603 {
604 tokens.append (new Token (text));
605 text = "";
606 }
607
608 int xlate[] = {
609 35, 34, 7, 36, 31, 30, 27, 33, 29, 77, 76, 39, 38, 45, 41, 40,
610 47, 43, 49, 57, 56, 81, 80, 83, 82, 63, 62, 71, 70, 67, 73, 23
611 };
612 tokens.append (new Token (Token::ExtChar, 1, xlate[code - 1]));
613 }
614
615
616 else
617 {
618 // either fixed-length or variable-length function
619
620 TQMemArray < TQ_UINT8 > data;
621 TQMemArray < TQ_UINT16 > pid;
622 TQ_UINT8 subfunction = 0;
623
624 if ((code >= 0xF0) && (code <= 0xFF))
625 {
626 TQ_UINT8 dummy;
627 unsigned lentab[] =
628 { 2, 3, 1, 1, 1, 1, 2, 2, 2, 3, 3, 4, 4, 6, 6, 0 };
629 unsigned length = lentab[code & 0x0F];
630 data.resize (length);
631 for (unsigned c = 0; c < length; c++)
632 stream >> data.at (c);
633 stream >> dummy; // FIXME should be checked == code ?
634 }
635 else if ((code >= 0xD0) && (code <= 0xFF))
636 {
637 TQ_UINT16 length;
638 TQ_UINT8 flag = 0, numpid = 0;
639 stream >> subfunction;
640 stream >> length;
641 stream >> flag;
642 length -= 10;
643
644 if (flag & 0x80)
645 {
646 stream >> numpid;
647 pid.resize (numpid);
648 for (unsigned n = 0; n < numpid; n++)
649 stream >> pid.at (n);
650 length = length - 1 - numpid * 2;
651 }
652
653 TQ_UINT16 nondel;
654 stream >> nondel;
655
656 data.resize (length);
657 for (int c = 0; length && !stream.atEnd (); length--, c++)
658 stream >> data[c];
659
660 TQ_UINT16 dummy_length;
661 TQ_UINT8 dummy_code;
662 stream >> dummy_length; // FIXME should be checked == length ?
663 stream >> dummy_code; // FIXME should be checked == code ?
664
665 }
666
667 // this is to simplify
668 unsigned function = (code << 8) + subfunction;
669
670 // flush previous text first
671 if (!text.isEmpty ())
672 {
673 tokens.append (new Token (text));
674 text = "";
675 }
676
677 int val;
678
679 switch (function)
680 {
681
682 case 0x8000:
683 tokens.append (new Token (Token::SoftSpace));
684 break;
685
686 case 0x8100:
687 tokens.append (new Token (Token::HardSpace));
688 break;
689
690 case 0x8400:
691 tokens.append (new Token (Token::HardHyphen));
692 break;
693
694 case 0x8700:
695 tokens.append (new Token (Token::DormantHardReturn));
696 break;
697
698 case 0x8800:
699 tokens.append (new Token (Token::SoftReturn));
700 // FIXME this is actually Soft End of Center/Align
701 break;
702
703 case 0xcc00:
704 tokens.append (new Token (Token::HardReturn));
705 break;
706
707 case 0xd001:
708 case 0xd014:
709 tokens.append (new Token (Token::SoftReturn));
710 break;
711
712 case 0xd004:
713 tokens.append (new Token (Token::HardReturn));
714 break;
715
716 case 0xd00a:
717 tokens.append (new Token (Token::TableCell));
718 break;
719
720 case 0xd00b:
721 case 0xd00c:
722 case 0xd00d:
723 case 0xd00e:
724 case 0xd00f:
725 case 0xd010:
726 tokens.append (new Token (Token::TableRow));
727 break;
728
729 case 0xd011:
730 case 0xd012:
731 case 0xd013:
732 tokens.append (new Token (Token::TableOff));
733 break;
734
735 case 0xd100:
736 tokens.append (new Token (Token::TopMargin,
737 data[0] + (data[1] << 8)));
738 break;
739
740 case 0xd101:
741 tokens.append (new Token (Token::BottomMargin,
742 data[0] + (data[1] << 8)));
743 break;
744
745 case 0xd200:
746 tokens.append (new Token (Token::LeftMargin,
747 data[0] + (data[1] << 8)));
748 break;
749
750 case 0xd201:
751 tokens.append (new Token (Token::RightMargin,
752 data[0] + (data[1] << 8)));
753 break;
754
755 case 0xd301:
756 tokens.append (new Token (Token::Linespace,
757 (data[2] << 16) + (data[1] << 8) +
758 data[0]));
759 break;
760
761 case 0xd304:
762 handleTab (data);
763 break;
764
765 case 0xd305:
766 tokens.append (new Token (Token::Justification,
767 mapToAlign (data[0])));
768 break;
769
770 case 0xd30a:
771 // TODO spacing after paragraph
772 break;
773
774 case 0xd30b:
775 tokens.append (new Token (Token::ParagraphIndent,
776 data[0] + (data[1] << 8)));
777 break;
778
779 case 0xd30c:
780 val = data[0] + (data[1] << 8);
781 if (val > 32767)
782 val = val - 65536;
783 tokens.append (new Token (Token::LeftMarginAdjust, val));
784 break;
785
786 case 0xd30d:
787 val = data[0] + (data[1] << 8);
788 if (val > 32767)
789 val = val - 65536;
790 tokens.append (new Token (Token::RightMarginAdjust, val));
791 break;
792
793 case 0xd402:
794 case 0xd403:
795 // TODO underline spaces ? tabs ?
796 break;
797
798 case 0xd40a:
799 tokens.append (new Token (Token::MarkTocStart));
800 break;
801
802 case 0xd40b:
803 tokens.append (new Token (Token::MarkTocEnd));
804 break;
805
806 case 0xd418:
807 tokens.append (new Token (Token::FontColor,
808 data[0], data[1], data[2]));
809 break;
810
811 case 0xd41b:
812 tokens.append (new Token (Token::FontSize,
813 (data[1] << 8) + data[0]));
814 break;
815
816 case 0xd41c:
817 // TODO set language [Lang]
818 break;
819
820 case 0xd41a:
821 {
822 unsigned fontpid = pid[0];
823 if( fontpid == 0 || fontpid > packets.count() ) continue;
824 Packet* p = packets.at( fontpid-1 );
825 if( p->type==85 )
826 {
827 // read the typeface (stored as WP word-string)
828 TQString typeface;
829 unsigned strlen = p->data[22];
830 for( unsigned i=24; strlen && (i<p->data.size()); i+=2, strlen-=2 )
831 if( p->data[i]) typeface.append( p->data[i] );
832 else break;
833 typeface = typeface.stripWhiteSpace();
834
835 // hack: get rid of "Regular" as font name suffix
836 TQString suffix = "Regular";
837 if( typeface.right( suffix.length() ) == suffix )
838 typeface = typeface.left( typeface.length() - suffix.length() ).stripWhiteSpace();
839
840 tokens.append( new Token( Token::FontFace, typeface ) );
841 }
842 }
843 break;
844
845 case 0xd426:
846 case 0xd427:
847 // TODO block protect on/off
848 break;
849
850 case 0xd42a:
851 tokens.append (new Token (Token::TableOn));
852 break;
853
854 case 0xd42b:
855 tokens.append (new Token (Token::TableEnd));
856 break;
857
858 case 0xd42c:
859 tokens.append (new Token (Token::TableColumn));
860 break;
861
862 case 0xd45f:
863 // FIXME check what it does
864 // this always appears within table cell
865 break;
866
867 case 0xdd0a:
868 case 0xdd0b:
869 // TODO global on/off
870 break;
871
872 case 0xf000:
873 tokens.append (new Token (Token::ExtChar, data[1], data[0]));
874 break;
875
876 case 0xf200:
877 tokens.append (new Token (Token::AttrOn, mapToAttr (data[0])));
878 break;
879
880 case 0xf300:
881 tokens.append (new Token (Token::AttrOff, mapToAttr (data[0])));
882 break;
883
884 case 0xdd00:
885 case 0xdd01:
886 // TODO style begin on/off
887 break;
888
889 case 0xdd02:
890 case 0xdd03:
891 // TODO style end on/off
892 break;
893
894 case 0xe011:
895 // TODO soft left-tab
896 break;
897
898 case 0xe040:
899 // TODO center on margin
900 break;
901
902 case 0xe080:
903 tokens.append (new Token (Token::TabHardFlushRight));
904 break;
905
906 case 0xd111:
907 // FIXME unknown functions
908 break;
909
910 case 0xfb00:
911 // text highlight (or background color)
912 tokens.append (new Token (Token::HighlightOn,
913 data[0], data[1], data[2]));
914 break;
915
916 case 0xfc00:
917 // turn off highlight, data is last highlight color
918 tokens.append (new Token (Token::HighlightOff,
919 data[0], data[1], data[2]));
920 break;
921
922 default:
923 tokens.append (new Token (Token::Function, function));
924 break;
925
926 };
927
928
929 }
930
931 }
932
933 // flush left-over text if any
934 if (!text.isEmpty ())
935 {
936 tokens.append (new Token (text));
937 text = "";
938 }
939}
940
941
942static Token::TabType
943mapToTabType (int t)
944{
945 switch (t)
946 {
947 case 0:
948 return Token::LeftTab;
949 case 1:
950 return Token::CenterTab;
951 case 2:
952 return Token::RightTab;
953 case 3:
954 return Token::DecimalTab;
955 case 4:
956 return Token::VerticalTab;
957 }
958 return Token::LeftTab;
959}
960
961void
962Parser::handleTab (TQMemArray < TQ_UINT8 > data)
963{
964 TQPtrList < Token::Tab > tabs;
965 bool relative = data[0];
966 int adjust = data[1] + (data[2] << 8);
967 int num = data[3];
968 int p = 4;
969 int tabtype = 0;
970 int tabpos = 0;
971
972 for (int i = 0; i < num; i++)
973 {
974 int tt = data[p];
975
976 if (tt & 0x80)
977 {
978 int rep = tt & 0x7F;
979 p++;
980 for (int c = 0; c < rep; c++)
981 {
982 int diff = data[p] + (data[p + 1] << 8);
983 tabs.
984 append (new Token::
985 Tab (mapToTabType (tabtype), tabpos + diff));
986 p += 2;
987 }
988 }
989 else
990 {
991 tabtype = tt & 0x7f;
992 tabpos = data[p + 1] + (data[p + 2] << 8);
993 tabs.append (new Token::Tab (mapToTabType (tabtype), tabpos));
994 p += 3;
995 }
996
997 }
998
999
1000 if (tabs.count ())
1001 tokens.append (new Token (tabs));
1002
1003}
1004
1005// the following tables maps WP charset/charcode to unicode character
1006
1007// WP multinational characters (charset 1)
1008static unsigned multinational_map[] = {
1009 0x0300, 0x00b7, 0x0303, 0x0302, 0x0335, 0x0338, 0x0301, 0x0308,
1010 0x0304, 0x0313, 0x0315, 0x02bc, 0x0326, 0x0315, 0x030a, 0x0307,
1011 0x030b, 0x0327, 0x0328, 0x030c, 0x0337, 0x0305, 0x0306, 0x00df,
1012 0x0138, 0xf801, 0x00c1, 0x00e1, 0x00c2, 0x00e2, 0x00c4, 0x00e4,
1013 0x00c0, 0x00e0, 0x00c5, 0x00e5, 0x00c6, 0x00e6, 0x00c7, 0x00e7,
1014 0x00c9, 0x00e9, 0x00ca, 0x00ea, 0x00cb, 0x00eb, 0x00c8, 0x00e8,
1015 0x00cd, 0x00ed, 0x00ce, 0x00ee, 0x00cf, 0x00ef, 0x00cc, 0x00ec,
1016 0x00d1, 0x00f1, 0x00d3, 0x00f3, 0x00d4, 0x00f4, 0x00d6, 0x00f6,
1017 0x00d2, 0x00f2, 0x00da, 0x00fa, 0x00db, 0x00fb, 0x00dc, 0x00fc,
1018 0x00d9, 0x00f9, 0x0178, 0x00ff, 0x00c3, 0x00e3, 0x0110, 0x0111,
1019 0x00d8, 0x00f8, 0x00d5, 0x00f5, 0x00dd, 0x00fd, 0x00d0, 0x00f0,
1020 0x00de, 0x00fe, 0x0102, 0x0103, 0x0100, 0x0101, 0x0104, 0x0105,
1021 0x0106, 0x0107, 0x010c, 0x010d, 0x0108, 0x0109, 0x010a, 0x010b,
1022 0x010e, 0x010f, 0x011a, 0x011b, 0x0116, 0x0117, 0x0112, 0x0113,
1023 0x0118, 0x0119, 0x0047, 0x0067, 0x011e, 0x011f, 0x0047, 0x0067,
1024 0x0122, 0x0123, 0x011c, 0x011d, 0x0120, 0x0121, 0x0124, 0x0125,
1025 0x0126, 0x0127, 0x0130, 0x0069, 0x012a, 0x012b, 0x012e, 0x012f,
1026 0x0128, 0x0129, 0x0132, 0x0133, 0x0134, 0x0135, 0x0136, 0x0137,
1027 0x0139, 0x013a, 0x013d, 0x013e, 0x013b, 0x013c, 0x013f, 0x0140,
1028 0x0141, 0x0142, 0x0143, 0x0144, 0xf802, 0x0149, 0x0147, 0x0148,
1029 0x0145, 0x0146, 0x0150, 0x0151, 0x014c, 0x014d, 0x0152, 0x0153,
1030 0x0154, 0x0155, 0x0158, 0x0159, 0x0156, 0x0157, 0x015a, 0x015b,
1031 0x0160, 0x0161, 0x015e, 0x015f, 0x015c, 0x015d, 0x0164, 0x0165,
1032 0x0162, 0x0163, 0x0166, 0x0167, 0x016c, 0x016d, 0x0170, 0x0171,
1033 0x016a, 0x016b, 0x0172, 0x0173, 0x016e, 0x016f, 0x0168, 0x0169,
1034 0x0174, 0x0175, 0x0176, 0x0177, 0x0179, 0x017a, 0x017d, 0x017e,
1035 0x017b, 0x017c, 0x014a, 0x014b, 0xf000, 0xf001, 0xf002, 0xf003,
1036 0xf004, 0xf005, 0xf006, 0xf007, 0xf008, 0xf009, 0xf00a, 0xf00b,
1037 0xf00c, 0xf00d, 0xf00e, 0xf00f, 0x010e, 0x010f, 0x01a0, 0x01a1,
1038 0x01af, 0x01b0, 0x0114, 0x0115, 0x012c, 0x012d, 0x0049, 0x0131,
1039 0x014e, 0x014f
1040};
1041
1042// WP phonetic symbol (charset 2)
1043static unsigned phonetic_map[] = {
1044 0x02b9, 0x02ba, 0x02bb, 0xf813, 0x02bd, 0x02bc, 0xf814, 0x02be,
1045 0x02bf, 0x0310, 0x02d0, 0x02d1, 0x0306, 0x032e, 0x0329, 0x02c8,
1046 0x02cc, 0x02c9, 0x02ca, 0x02cb, 0x02cd, 0x02ce, 0x02cf, 0x02c6,
1047 0x02c7, 0x02dc, 0x0325, 0x02da, 0x032d, 0x032c, 0x0323, 0x0308,
1048 0x0324, 0x031c, 0x031d, 0x031e, 0x031f, 0x0320, 0x0321, 0x0322,
1049 0x032a, 0x032b, 0x02d2, 0x02d3, 0xf815, 0xf816, 0x005f, 0x2017,
1050 0x033e, 0x02db, 0x0327, 0x0233, 0x030d, 0x02b0, 0x02b6, 0x0250,
1051 0x0251, 0x0252, 0x0253, 0x0299, 0x0254, 0x0255, 0x0297, 0x0256,
1052 0x0257, 0x0258, 0x0259, 0x025a, 0x025b, 0x025c, 0x025d, 0x029a,
1053 0x025e, 0x025f, 0x0278, 0x0261, 0x0260, 0x0262, 0x029b, 0x0263,
1054 0x0264, 0x0265, 0x0266, 0x0267, 0x029c, 0x0268, 0x026a, 0x0269,
1055 0x029d, 0x029e, 0x026b, 0x026c, 0x026d, 0x029f, 0x026e, 0x028e,
1056 0x026f, 0x0270, 0x0271, 0x0272, 0x0273, 0x0274, 0x0276, 0x0277,
1057 0x02a0, 0x0279, 0x027a, 0x027b, 0x027c, 0x027d, 0x027e, 0x027f,
1058 0x0280, 0x0281, 0x0282, 0x0283, 0x0284, 0x0285, 0x0286, 0x0287,
1059 0x0288, 0x0275, 0x0289, 0x028a, 0x028c, 0x028b, 0x028d, 0x03c7,
1060 0x028f, 0x0290, 0x0291, 0x0292, 0x0293, 0x0294, 0x0295, 0x0296,
1061 0x02a1, 0x02a2, 0x0298, 0x02a3, 0x02a4, 0x02a5, 0x02a6, 0x02a7,
1062 0x02a8
1063};
1064
1065// WP typographic symbol (charset 4)
1066static unsigned typographic_map[] = {
1067 0x25cf, 0x25cb, 0x25a0, 0x2022, 0xf817, 0x00b6, 0x00a7, 0x00a1,
1068 0x00bf, 0x00ab, 0x00bb, 0x00a3, 0x00a5, 0x20a7, 0x0192, 0x00aa,
1069 0x00ba, 0x00bd, 0x00bc, 0x00a2, 0x00b2, 0x207f, 0x00ae, 0x00a9,
1070 0x00a4, 0x00be, 0x00b3, 0x201b, 0x2019, 0x2018, 0x201f, 0x201d,
1071 0x201c, 0x2013, 0x2014, 0x2039, 0x203a, 0x25cb, 0x25a1, 0x2020,
1072 0x2021, 0x2122, 0x2120, 0x211e, 0x25cf, 0x25e6, 0x25a0, 0x25aa,
1073 0x25a1, 0x25ab, 0x2012, 0xfb00, 0xfb03, 0xfb04, 0xfb01, 0xfb02,
1074 0x2026, 0x0024, 0x20a3, 0x20a2, 0x20a0, 0x20a4, 0x201a, 0x201e,
1075 0x2153, 0x2154, 0x215b, 0x215c, 0x215d, 0x215e, 0x24c2, 0x24c5,
1076 0x20ac, 0x2105, 0x2106, 0x2030, 0x2116, 0xf818, 0x00b9, 0x2409,
1077 0x240c, 0x240d, 0x240a, 0x2424, 0x240b, 0xf819, 0x20a9, 0x20a6,
1078 0x20a8, 0xf81a, 0xf81b, 0xf81c, 0xf81d, 0xf81e, 0xf81f, 0xf820,
1079 0xf821, 0xf822, 0xf823, 0xf824, 0xf825, 0xf826
1080};
1081
1082// WP iconic symbol (charset 5)
1083static unsigned iconic_map[] = {
1084 0x2661, 0x2662, 0x2667, 0x2664, 0x2642, 0x2640, 0x263c, 0x263a,
1085 0x263b, 0x266a, 0x266c, 0x25ac, 0x2302, 0x203c, 0x221a, 0x21a8,
1086 0x2310, 0x2319, 0x25d8, 0x25d9, 0x21b5, 0x2104, 0x261c, 0x2007,
1087 0x2610, 0x2612, 0x2639, 0x266f, 0x266d, 0x266e, 0x260e, 0x231a,
1088 0x231b, 0x2701, 0x2702, 0x2703, 0x2704, 0x260e, 0x2706, 0x2707,
1089 0x2708, 0x2709, 0x261b, 0x261e, 0x270c, 0x270d, 0x270e, 0x270f,
1090 0x2710, 0x2711, 0x2712, 0x2713, 0x2714, 0x2715, 0x2716, 0x2717,
1091 0x2718, 0x2719, 0x271a, 0x271b, 0x271c, 0x271d, 0x271e, 0x271f,
1092 0x2720, 0x2721, 0x2722, 0x2723, 0x2724, 0x2725, 0x2726, 0x2727,
1093 0x2605, 0x2606, 0x272a, 0x272b, 0x272c, 0x272d, 0x272e, 0x272f,
1094 0x2730, 0x2731, 0x2732, 0x2733, 0x2734, 0x2735, 0x2736, 0x2737,
1095 0x2738, 0x2739, 0x273a, 0x273b, 0x273c, 0x273d, 0x273e, 0x273f,
1096 0x2740, 0x2741, 0x2742, 0x2743, 0x2744, 0x2745, 0x2746, 0x2747,
1097 0x2748, 0x2749, 0x274a, 0x274b, 0x25cf, 0x274d, 0x25a0, 0x274f,
1098 0x2750, 0x2751, 0x2752, 0x25b2, 0x25bc, 0x25c6, 0x2756, 0x25d7,
1099 0x2758, 0x2759, 0x275a, 0x275b, 0x275c, 0x275d, 0x275e, 0x2036,
1100 0x2033, 0xf827, 0xf828, 0xf829, 0xf82a, 0x2329, 0x232a, 0x005b,
1101 0x005d, 0xf82b, 0xf82c, 0xf82d, 0xf82e, 0xf82f, 0xf830, 0xf831,
1102 0x2190, 0xf832, 0xf833, 0xf834, 0xf835, 0xf836, 0x21e8, 0x21e6,
1103 0x2794, 0xf838, 0xf839, 0xf83a, 0xf83b, 0xf83c, 0x25d6, 0xf83d,
1104 0xf83e, 0x2761, 0x2762, 0x2763, 0x2764, 0x2765, 0x2766, 0x2767,
1105 0x2663, 0x2666, 0x2665, 0x2660, 0x2780, 0x2781, 0x2782, 0x2783,
1106 0x2784, 0x2785, 0x2786, 0x2787, 0x2788, 0x2789, 0x2776, 0x2777,
1107 0x2778, 0x2779, 0x277a, 0x277b, 0x277c, 0x277d, 0x277e, 0x277f,
1108 0x2780, 0x2781, 0x2782, 0x2783, 0x2784, 0x2785, 0x2786, 0x2787,
1109 0x2788, 0x2789, 0x278a, 0x278b, 0x278c, 0x278d, 0x278e, 0x278f,
1110 0x2790, 0x2791, 0x2792, 0x2793, 0x2794, 0x2192, 0x2194, 0x2195,
1111 0x2798, 0x2799, 0x279a, 0x279b, 0x279c, 0x279d, 0x279e, 0x279f,
1112 0x27a0, 0x27a1, 0x27a2, 0x27a3, 0x27a4, 0x27a5, 0x27a6, 0x27a7,
1113 0x27a8, 0x27a9, 0x27aa, 0x27ab, 0x27ac, 0x27ad, 0x27ae, 0x27af,
1114 0xf83f, 0x27b1, 0x27b2, 0x27b3, 0x27b4, 0x27b5, 0x27b6, 0x27b7,
1115 0x27b8, 0x27b9, 0x27ba, 0x27bb, 0x27bc, 0x27bd, 0x27be
1116};
1117
1118// WP math/scientific (charset 6)
1119static unsigned math_map[] = {
1120 0x2212, 0x00b1, 0x2264, 0x2265, 0x221d, 0x01c0, 0x2215, 0x2216,
1121 0x00f7, 0x2223, 0x2329, 0x232a, 0x223c, 0x2248, 0x2261, 0x2208,
1122 0x2229, 0x2225, 0x2211, 0x221e, 0x00ac, 0x2192, 0x2190, 0x2191,
1123 0x2193, 0x2194, 0x2195, 0x25b8, 0x25c2, 0x25b4, 0x25be, 0x22c5,
1124 0xf850, 0x2218, 0x2219, 0x212b, 0x00b0, 0x00b5, 0x203e, 0x00d7,
1125 0x222b, 0x220f, 0x2213, 0x2207, 0x2202, 0x02b9, 0x02ba, 0x2192,
1126 0x212f, 0x2113, 0x210f, 0x2111, 0x211c, 0x2118, 0x21c4, 0x21c6,
1127 0x21d2, 0x21d0, 0x21d1, 0x21d3, 0x21d4, 0x21d5, 0x2197, 0x2198,
1128 0x2196, 0x2199, 0x222a, 0x2282, 0x2283, 0x2286, 0x2287, 0x220d,
1129 0x2205, 0x2308, 0x2309, 0x230a, 0x230b, 0x226a, 0x226b, 0x2220,
1130 0x2297, 0x2295, 0x2296, 0xf851, 0x2299, 0x2227, 0x2228, 0x22bb,
1131 0x22a4, 0x22a5, 0x2312, 0x22a2, 0x22a3, 0x25a1, 0x25a0, 0x25ca,
1132 0xf852, 0xf853, 0xf854, 0x2260, 0x2262, 0x2235, 0x2234, 0x2237,
1133 0x222e, 0x2112, 0x212d, 0x2128, 0x2118, 0x20dd, 0xf855, 0x25c7,
1134 0x22c6, 0x2034, 0x2210, 0x2243, 0x2245, 0x227a, 0x227c, 0x227b,
1135 0x227d, 0x2203, 0x2200, 0x22d8, 0x22d9, 0x228e, 0x228a, 0x228b,
1136 0x2293, 0x2294, 0x228f, 0x2291, 0x22e4, 0x2290, 0x2292, 0x22e5,
1137 0x25b3, 0x25bd, 0x25c3, 0x25b9, 0x22c8, 0x2323, 0x2322, 0xf856,
1138 0x219d, 0x21a9, 0x21aa, 0x21a3, 0x21bc, 0x21bd, 0x21c0, 0x21c1,
1139 0x21cc, 0x21cb, 0x21bf, 0x21be, 0x21c3, 0x21c2, 0x21c9, 0x21c7,
1140 0x22d3, 0x22d2, 0x22d0, 0x22d1, 0x229a, 0x229b, 0x229d, 0x2127,
1141 0x2221, 0x2222, 0x25c3, 0x25b9, 0x25b5, 0x25bf, 0x2214, 0x2250,
1142 0x2252, 0x2253, 0x224e, 0x224d, 0x22a8, 0xf857, 0x226c, 0x0285,
1143 0x2605, 0x226e, 0x2270, 0x226f, 0x2271, 0x2241, 0x2244, 0x2247,
1144 0x2249, 0x2280, 0x22e0, 0x2281, 0x22e1, 0x2284, 0x2285, 0x2288,
1145 0x2289, 0xf858, 0xf859, 0x22e2, 0x22e3, 0x2226, 0x2224, 0x226d,
1146 0x2204, 0x2209, 0xf85a, 0x2130, 0x2131, 0x2102, 0xf85b, 0x2115,
1147 0x211d, 0x225f, 0x221f, 0x220b, 0x22ef, 0xf85c, 0x22ee, 0x22f1,
1148 0xf85d, 0x20e1, 0x002b, 0x002d, 0x003d, 0x002a, 0xf85e, 0xf85f,
1149 0xf860, 0x210c, 0x2118, 0x2272, 0x2273, 0xf861
1150};
1151
1152// WP math/scientific extended (charset 6)
1153static unsigned mathext_map[] = {
1154 0x2320, 0x2321, 0xf702, 0xf703, 0x221a, 0xf705, 0xf706, 0xf707,
1155 0xf708, 0xf709, 0xf70a, 0xf70b, 0xf70c, 0xf70d, 0xf70e, 0xf70f,
1156 0xf710, 0xf711, 0xf712, 0xf713, 0xf714, 0xf715, 0xf716, 0xf717,
1157 0xf718, 0xf719, 0xf71a, 0xf71b, 0xf71c, 0xf71d, 0xf71e, 0xf71f,
1158 0xf720, 0xf721, 0xf722, 0xf723, 0xf724, 0xf725, 0xf726, 0xf727,
1159 0xf728, 0xf729, 0xf72a, 0xf72b, 0xf72c, 0xf72d, 0xf72e, 0xf72f,
1160 0xf730, 0xf731, 0xf732, 0xf733, 0xf734, 0xf735, 0xf736, 0xf737,
1161 0xf738, 0xf739, 0xf73a, 0xf73b, 0xf73c, 0xf73d, 0xf73e, 0xf73f,
1162 0xf740, 0xf741, 0xf742, 0xf743, 0xf744, 0xf745, 0xf746, 0xf747,
1163 0xf748, 0xf749, 0xf74a, 0xf74b, 0xf74c, 0xf74d, 0xf74e, 0xf74f,
1164 0xf750, 0xf751, 0xf752, 0xf753, 0xf754, 0xf755, 0xf756, 0xf757,
1165 0xf758, 0xf759, 0xf75a, 0xf75b, 0xf75c, 0xf75d, 0xf75e, 0xf75f,
1166 0xf760, 0xf761, 0xf762, 0xf763, 0xf764, 0xf765, 0xf766, 0xf767,
1167 0xf768, 0xf769, 0xf76a, 0xf76b, 0xf76c, 0xf76d, 0xf76e, 0xf76f,
1168 0xf770, 0xf771, 0xf772, 0xf773, 0xf774, 0xf775, 0xf776, 0xf777,
1169 0xf778, 0xf779, 0x20aa, 0xf77b, 0xf77c, 0xf77d, 0xf77e, 0xf77f,
1170 0xf780, 0xf781, 0xf782, 0xf783, 0xf784, 0xf785, 0xf786, 0xf787,
1171 0xf788, 0xf789, 0xf78a, 0xf78b, 0xf78c, 0xf78d, 0xf78e, 0xf78f,
1172 0xf790, 0xf791, 0xf792, 0xf793, 0xf794, 0xf795, 0xf796, 0xf797,
1173 0xf798, 0xf799, 0xf79a, 0xf79b, 0xf79c, 0xf79d, 0xf79e, 0xf79f,
1174 0xf7a0, 0xf7a1, 0xf7a2, 0xf7a3, 0xf7a4, 0xf7a5, 0xf7a6, 0xf7a7,
1175 0xf7a8, 0xf7a9, 0xf7aa, 0xf7ab, 0xf7ac, 0xf7ad, 0xf7ae, 0xf7af,
1176 0xf7b0, 0xf7b1, 0xf7b2, 0xf7b3, 0xf7b4, 0xf7b5, 0xf7b6, 0xf7b7,
1177 0xf7b8, 0xf7b9, 0xf7ba, 0xf7bb, 0xf7bc, 0xf7bd, 0xf7be, 0xf7bf,
1178 0xf7c0, 0xf7c1, 0xf7c2, 0xf7c3, 0xf7c4, 0xf7c5, 0xf7c6, 0xf7c7
1179};
1180
1181// WP greek (charset 8)
1182static unsigned int greek_map[] = {
1183 0x0391, 0x03b1, 0x0392, 0x03b2, 0x0392, 0x03d0, 0x0393, 0x03b3,
1184 0x0394, 0x03b4, 0x0395, 0x03b5, 0x0396, 0x03b6, 0x0397, 0x03b7,
1185 0x0398, 0x03b8, 0x0399, 0x03b9, 0x039a, 0x03ba, 0x039b, 0x03bb,
1186 0x039c, 0x03bc, 0x039d, 0x03bd, 0x039e, 0x03be, 0x039f, 0x03bf,
1187 0x03a0, 0x03c0, 0x03a1, 0x03c1, 0x03a3, 0x03c3, 0x03a3, 0x03c2,
1188 0x03a4, 0x03c4, 0x03a5, 0x03c5, 0x03a6, 0x03c6, 0x03a7, 0x03c7,
1189 0x03a8, 0x03c8, 0x03a9, 0x03c9, 0x0386, 0x03ac, 0x0388, 0x03ad,
1190 0x0389, 0x03ae, 0x038a, 0x03af, 0x03aa, 0x03ca, 0x038c, 0x03cc,
1191 0x038e, 0x03cd, 0x03ab, 0x03cb, 0x038f, 0x03ce, 0x03b5, 0x03d1,
1192 0x03f0, 0x03d6, 0x03f1, 0x03db, 0x03d2, 0x03d5, 0x03d6, 0x03d7,
1193 0x00b7, 0x0374, 0x0375, 0x0301, 0x0308, 0xf216, 0xf217, 0x0300,
1194 0x0311, 0x0313, 0x0314, 0x0345, 0x1fce, 0x1fde, 0x1fcd, 0x1fdd,
1195 0xf200, 0xf201, 0xf022, 0xf021, 0xf202, 0xf203, 0xf204, 0xf300,
1196 0xf301, 0xf302, 0xf303, 0xf304, 0xf305, 0x1f70, 0xf100, 0x1fb3,
1197 0x1fb4, 0x1fb2, 0xf205, 0x1f00, 0x1f04, 0x1f02, 0xf206, 0x1f80,
1198 0x1f84, 0x1f82, 0xf306, 0x1f01, 0x1f05, 0x1f03, 0xf207, 0x1f81,
1199 0x1f85, 0x1f83, 0xf307, 0x1f72, 0x1f10, 0x1f14, 0x1f12, 0x1f11,
1200 0x1f15, 0x1f13, 0x1f74, 0xf101, 0x1fc3, 0x1fc4, 0x1fc2, 0xf208,
1201 0x1f20, 0x1f24, 0x1f22, 0xf209, 0x1f90, 0x1f94, 0x1f92, 0xf308,
1202 0x1f21, 0x1f25, 0x1f23, 0xf20a, 0x1f91, 0x1f95, 0x1f93, 0xf309,
1203 0x1f76, 0xf102, 0xf20b, 0xf20c, 0x1f30, 0x1f34, 0x1f32, 0xf20d,
1204 0x1f31, 0x1f35, 0x1f33, 0xf20e, 0x1f78, 0x1f40, 0x1f44, 0x1f42,
1205 0x1f41, 0x1f45, 0x1f43, 0x1fe5, 0x1fe4, 0x1f7a, 0xf103, 0xf20f,
1206 0xf210, 0x1f50, 0x1f54, 0x1f52, 0xf211, 0x1f51, 0x1f55, 0x1f53,
1207 0xf212, 0x1f7c, 0xf104, 0x1ff3, 0x1ff4, 0x1ff2, 0xf213, 0x1f60,
1208 0x1f64, 0x1f62, 0xf214, 0x1fa0, 0x1fa4, 0x1fa2, 0xf30a, 0x1f61,
1209 0x1f65, 0x1f63, 0xf215, 0x1fa1, 0x1fa5, 0x1fa3, 0xf30b, 0x03da,
1210 0x03dc, 0x03de, 0x03e0
1211};
1212
1213// WP hebrew (charset 9)
1214static unsigned hebrew_map[] = {
1215 0x05d0, 0x05d1, 0x05d2, 0x05d3, 0x05d4, 0x05d5, 0x05d6, 0x05d7,
1216 0x05d8, 0x05d9, 0x05da, 0x05db, 0x05dc, 0x05dd, 0x05de, 0x05df,
1217 0x05e0, 0x05e1, 0x05e2, 0x05e3, 0x05e4, 0x05e5, 0x05e6, 0x05e7,
1218 0x05e8, 0x05e9, 0x05ea, 0xf862, 0x05c0, 0x05c3, 0x05f3, 0x05f4,
1219 0x05b0, 0x05b1, 0x05b2, 0x05b3, 0x05b4, 0x05b5, 0x05b6, 0x05b7,
1220 0x05b8, 0x05b9, 0x05b9, 0x05bb, 0x05bc, 0x05bd, 0x05bf, 0x05b7,
1221 0xfb1e, 0x05f0, 0x05f1, 0x05f2, 0xf114, 0xf8b0, 0xf863, 0xf864,
1222 0xf865, 0xf866, 0xf867, 0xf868, 0xf869, 0xf86a, 0xf86b, 0xf86c,
1223 0xf86d, 0xf86e, 0xf86f, 0xf870, 0xf871, 0xf872, 0xf873, 0xf874,
1224 0x05f3, 0x05f3, 0x05f4, 0xf876, 0xf877, 0xf878, 0xf879, 0xf87a,
1225 0xf87b, 0xf87c, 0xf87d, 0xf87e, 0xf115, 0xf116, 0xf87f, 0xf117,
1226 0xf118, 0xf119, 0xf11a, 0xf11b, 0xf11c, 0xf11d, 0xf11e, 0xf11f,
1227 0xf120, 0xf121, 0xf122, 0xf123, 0xf124, 0xf125, 0xf126, 0xf127,
1228 0xf218, 0xf128, 0xf129, 0xf12a, 0xf12b, 0xf12c, 0xf12d, 0xf880,
1229 0xf12e, 0xf12f, 0xf130, 0xf219, 0x05e9, 0xf131, 0xf132, 0xf140,
1230 0xf141, 0xf142, 0x20aa
1231};
1232
1233// WP cyrillic (charset 10)
1234static unsigned cyrillic_map[] = {
1235 0x0410, 0x0430, 0x0411, 0x0431, 0x0412, 0x0432, 0x0413, 0x0433,
1236 0x0414, 0x0434, 0x0415, 0x0435, 0x0401, 0x0451, 0x0416, 0x0436,
1237 0x0417, 0x0437, 0x0418, 0x0438, 0x0419, 0x0439, 0x041a, 0x043a,
1238 0x041b, 0x043b, 0x041c, 0x043c, 0x041d, 0x043d, 0x041e, 0x043e,
1239 0x041f, 0x043f, 0x0420, 0x0440, 0x0421, 0x0441, 0x0422, 0x0442,
1240 0x0423, 0x0443, 0x0424, 0x0444, 0x0425, 0x0445, 0x0426, 0x0446,
1241 0x0427, 0x0447, 0x0428, 0x0448, 0x0429, 0x0449, 0x042a, 0x044a,
1242 0x042b, 0x044b, 0x042c, 0x044c, 0x042d, 0x044d, 0x042e, 0x044e,
1243 0x042f, 0x044f, 0x04d8, 0x04d9, 0x0403, 0x0453, 0x0490, 0x0491,
1244 0x0492, 0x0493, 0x0402, 0x0452, 0x0404, 0x0454, 0x0404, 0x0454,
1245 0x0496, 0x0497, 0x0405, 0x0455, 0xf159, 0xf889, 0xf15e, 0xf15f,
1246 0x0406, 0x0456, 0x0407, 0x0457, 0xf88c, 0xf88d, 0x0408, 0x0458,
1247 0x040c, 0x045c, 0x049a, 0x049b, 0xf160, 0xf161, 0x049c, 0x049d,
1248 0x0409, 0x0459, 0x04a2, 0x04a3, 0x040a, 0x045a, 0x047a, 0x047b,
1249 0x0460, 0x0461, 0x040b, 0x045b, 0x040e, 0x045e, 0x04ee, 0x04ef,
1250 0x04ae, 0x04af, 0x04b0, 0x04b1, 0x0194, 0x0263, 0x04b2, 0x04b3,
1251 0xf162, 0xf163, 0x04ba, 0x04bb, 0x047e, 0x047f, 0x040f, 0x045f,
1252 0x04b6, 0x04b7, 0x04b8, 0x04b9, 0xf164, 0xf165, 0x0462, 0x0463,
1253 0x0466, 0x0467, 0x046a, 0x046b, 0x046e, 0x046f, 0x0470, 0x0471,
1254 0x0472, 0x0473, 0x0474, 0x0475, 0xf400, 0xf401, 0xf402, 0xf403,
1255 0xf404, 0xf405, 0xf406, 0xf407, 0xf408, 0xf409, 0xf40a, 0xf40b,
1256 0xf40c, 0xf40d, 0xf40e, 0xf40f, 0xf410, 0xf411, 0xf412, 0xf413,
1257 0xf414, 0xf415, 0xf416, 0xf417, 0xf418, 0xf419, 0xf41a, 0xf41b,
1258 0xf41c, 0xf41d, 0xf41e, 0xf41f, 0xf420, 0xf421, 0xf422, 0xf423,
1259 0xf424, 0xf425, 0xf426, 0xf427, 0xf428, 0xf429, 0xf42a, 0xf42b,
1260 0x0301, 0x0300, 0x0308, 0x0306, 0x0326, 0x0328, 0x0304, 0xf893,
1261 0x201e, 0x201c, 0x10d0, 0x10d1, 0x10d2, 0x10d3, 0x10d4, 0x10d5,
1262 0x10d6, 0x10f1, 0x10d7, 0x10d8, 0x10d9, 0x10da, 0x10db, 0x10dc,
1263 0x10f2, 0x10dd, 0x10de, 0x10df, 0x10e0, 0x10e1, 0x10e2, 0x10e3,
1264 0x10f3, 0x10e4, 0x10e5, 0x10e6, 0x10e7, 0x10e8, 0x10e9, 0x10ea,
1265 0x10eb, 0x10ec, 0x10ed, 0x10ee, 0x10f4, 0x10ef, 0x10f0, 0x10f5,
1266 0x10f6, 0xf42c
1267};
1268
1269// WP japanese (charset 11)
1270static unsigned japanese_map[] = {
1271 0xff61, 0xff62, 0xff63, 0xff64, 0xff65, 0xff66, 0xff67, 0xff68,
1272 0xff69, 0xff6a, 0xff6b, 0xff6c, 0xff6d, 0xff6e, 0xff6f, 0xff70,
1273 0xff71, 0xff72, 0xff73, 0xff74, 0xff75, 0xff76, 0xff77, 0xff78,
1274 0xff79, 0xff7a, 0xff7b, 0xff7c, 0xff7d, 0xff7e, 0xff7f, 0xff80,
1275 0xff81, 0xff82, 0xff83, 0xff84, 0xff85, 0xff86, 0xff87, 0xff88,
1276 0xff89, 0xff8a, 0xff8b, 0xff8c, 0xff8d, 0xff8e, 0xff8f, 0xff90,
1277 0xff91, 0xff92, 0xff93, 0xff94, 0xff95, 0xff96, 0xff97, 0xff98,
1278 0xff99, 0xff9a, 0xff9b, 0xff9c, 0xff9d, 0xff9e, 0xff9f
1279};
1280
1281unsigned
1282Parser::ExtCharToUnicode (int charset, int charcode)
1283{
1284 unsigned ucode = 0;
1285 int cmax;
1286
1287 if (charcode < 0)
1288 return 0;
1289
1290 switch (charset)
1291 {
1292 case 1:
1293 // multinatinal character
1294 cmax = sizeof (multinational_map) / sizeof (multinational_map[0]);
1295 if (charcode < cmax)
1296 ucode = multinational_map[charcode];
1297 break;
1298 case 2:
1299 // phonetic symbol
1300 cmax = sizeof (phonetic_map) / sizeof (phonetic_map[0]);
1301 if (charcode < cmax)
1302 ucode = phonetic_map[charcode];
1303 break;
1304 case 3:
1305 // TODO box drawing
1306 break;
1307 case 4:
1308 // typographic symbol
1309 cmax = sizeof (typographic_map) / sizeof (typographic_map[0]);
1310 if (charcode < cmax)
1311 ucode = typographic_map[charcode];
1312 break;
1313 case 5:
1314 // iconic symbol
1315 cmax = sizeof (iconic_map) / sizeof (iconic_map[0]);
1316 if (charcode < cmax)
1317 ucode = iconic_map[charcode];
1318 break;
1319 case 6:
1320 // math/scientific
1321 cmax = sizeof (math_map) / sizeof (math_map[0]);
1322 if (charcode < cmax)
1323 ucode = math_map[charcode];
1324 break;
1325 case 7:
1326 // math/scientific extended
1327 cmax = sizeof (mathext_map) / sizeof (mathext_map[0]);
1328 if (charcode < cmax)
1329 ucode = mathext_map[charcode];
1330 break;
1331 case 8:
1332 // greek
1333 cmax = sizeof (greek_map) / sizeof (greek_map[0]);
1334 if (charcode < cmax)
1335 ucode = greek_map[charcode];
1336 break;
1337 case 9:
1338 // hebrew
1339 cmax = sizeof (hebrew_map) / sizeof (hebrew_map[0]);
1340 if (charcode < cmax)
1341 ucode = hebrew_map[charcode];
1342 break;
1343 case 10:
1344 // cyrillic
1345 cmax = sizeof (cyrillic_map) / sizeof (cyrillic_map[0]);
1346 if (charcode < cmax)
1347 ucode = cyrillic_map[charcode];
1348 break;
1349 case 11:
1350 // japanese
1351 cmax = sizeof (japanese_map) / sizeof (japanese_map[0]);
1352 if (charcode < cmax)
1353 ucode = japanese_map[charcode];
1354 break;
1355 }
1356
1357 // FIXME not sure about this but I think codepoint >= 0xf000 is really
1358 // specific only to WP
1359 if( ucode >= 0xf000 ) ucode = 0;
1360
1361 return ucode;
1362}
This class is an abstract encapsulation of a token to be use in the parser.
Definition parser.h:37