xref: /plan9/sys/src/cmd/aux/antiword/chartrans.c (revision 25b329d522281a8cdd35da0dcc08c3fc621059a9)
1f5736e95SDavid du Colombier /*
2f5736e95SDavid du Colombier  * chartrans.c
3*25b329d5SDavid du Colombier  * Copyright (C) 1999-2004 A.J. van Os; Released under GNU GPL
4f5736e95SDavid du Colombier  *
5f5736e95SDavid du Colombier  * Description:
6f5736e95SDavid du Colombier  * Translate Word characters to local representation
7f5736e95SDavid du Colombier  */
8f5736e95SDavid du Colombier 
9f5736e95SDavid du Colombier #include <stdlib.h>
10f5736e95SDavid du Colombier #include <string.h>
11f5736e95SDavid du Colombier #include <ctype.h>
12f5736e95SDavid du Colombier #if defined(__STDC_ISO_10646__)
13f5736e95SDavid du Colombier #include <wctype.h>
14f5736e95SDavid du Colombier #endif /* __STDC_ISO_10646__ */
15f5736e95SDavid du Colombier #include "antiword.h"
16f5736e95SDavid du Colombier 
17*25b329d5SDavid du Colombier static const USHORT usCp850[] = {	/* DOS implementation of Latin1 */
18f5736e95SDavid du Colombier 	0x00c7, 0x00fc, 0x00e9, 0x00e2, 0x00e4, 0x00e0, 0x00e5, 0x00e7,
19f5736e95SDavid du Colombier 	0x00ea, 0x00eb, 0x00e8, 0x00ef, 0x00ee, 0x00ec, 0x00c4, 0x00c5,
20f5736e95SDavid du Colombier 	0x00c9, 0x00e6, 0x00c6, 0x00f4, 0x00f6, 0x00f2, 0x00fb, 0x00f9,
21f5736e95SDavid du Colombier 	0x00ff, 0x00d6, 0x00dc, 0x00f8, 0x00a3, 0x00d8, 0x00d7, 0x0192,
22f5736e95SDavid du Colombier 	0x00e1, 0x00ed, 0x00f3, 0x00fa, 0x00f1, 0x00d1, 0x00aa, 0x00ba,
23f5736e95SDavid du Colombier 	0x00bf, 0x00ae, 0x00ac, 0x00bd, 0x00bc, 0x00a1, 0x00ab, 0x00bb,
24f5736e95SDavid du Colombier 	0x2591, 0x2592, 0x2593, 0x2502, 0x2524, 0x00c1, 0x00c2, 0x00c0,
25f5736e95SDavid du Colombier 	0x00a9, 0x2563, 0x2551, 0x2557, 0x255d, 0x00a2, 0x00a5, 0x2510,
26f5736e95SDavid du Colombier 	0x2514, 0x2534, 0x252c, 0x251c, 0x2500, 0x253c, 0x00e3, 0x00c3,
27f5736e95SDavid du Colombier 	0x255a, 0x2554, 0x2569, 0x2566, 0x2560, 0x2550, 0x256c, 0x00a4,
28f5736e95SDavid du Colombier 	0x00f0, 0x00d0, 0x00ca, 0x00cb, 0x00c8, 0x0131, 0x00cd, 0x00ce,
29f5736e95SDavid du Colombier 	0x00cf, 0x2518, 0x250c, 0x2588, 0x2584, 0x00a6, 0x00cc, 0x2580,
30f5736e95SDavid du Colombier 	0x00d3, 0x00df, 0x00d4, 0x00d2, 0x00f5, 0x00d5, 0x00b5, 0x00fe,
31f5736e95SDavid du Colombier 	0x00de, 0x00da, 0x00db, 0x00d9, 0x00fd, 0x00dd, 0x00af, 0x00b4,
32f5736e95SDavid du Colombier 	0x00ad, 0x00b1, 0x2017, 0x00be, 0x00b6, 0x00a7, 0x00f7, 0x00b8,
33f5736e95SDavid du Colombier 	0x00b0, 0x00a8, 0x00b7, 0x00b9, 0x00b3, 0x00b2, 0x25a0, 0x00a0,
34f5736e95SDavid du Colombier };
35f5736e95SDavid du Colombier 
36*25b329d5SDavid du Colombier static const USHORT usCp1250[] = {	/* Windows implementation of Latin2 */
37f5736e95SDavid du Colombier 	0x20ac, 0x003f, 0x201a, 0x003f, 0x201e, 0x2026, 0x2020, 0x2021,
38f5736e95SDavid du Colombier 	0x003f, 0x2030, 0x0160, 0x2039, 0x015a, 0x0164, 0x017d, 0x0179,
39f5736e95SDavid du Colombier 	0x003f, 0x2018, 0x2019, 0x201c, 0x201d, 0x2022, 0x2013, 0x2014,
40f5736e95SDavid du Colombier 	0x003f, 0x2122, 0x0161, 0x203a, 0x015b, 0x0165, 0x017e, 0x017a,
41f5736e95SDavid du Colombier 	0x00a0, 0x02c7, 0x02d8, 0x0141, 0x00a4, 0x0104, 0x00a6, 0x00a7,
42f5736e95SDavid du Colombier 	0x00a8, 0x00a9, 0x015e, 0x00ab, 0x00ac, 0x00ad, 0x00ae, 0x017b,
43f5736e95SDavid du Colombier 	0x00b0, 0x00b1, 0x02db, 0x0142, 0x00b4, 0x00b5, 0x00b6, 0x00b7,
44f5736e95SDavid du Colombier 	0x00b8, 0x0105, 0x015f, 0x00bb, 0x013d, 0x02dd, 0x013e, 0x017c,
45f5736e95SDavid du Colombier 	0x0154, 0x00c1, 0x00c2, 0x0102, 0x00c4, 0x0139, 0x0106, 0x00c7,
46f5736e95SDavid du Colombier 	0x010c, 0x00c9, 0x0118, 0x00cb, 0x011a, 0x00cd, 0x00ce, 0x010e,
47f5736e95SDavid du Colombier 	0x0110, 0x0143, 0x0147, 0x00d3, 0x00d4, 0x0150, 0x00d6, 0x00d7,
48f5736e95SDavid du Colombier 	0x0158, 0x016e, 0x00da, 0x0170, 0x00dc, 0x00dd, 0x0162, 0x00df,
49f5736e95SDavid du Colombier 	0x0155, 0x00e1, 0x00e2, 0x0103, 0x00e4, 0x013a, 0x0107, 0x00e7,
50f5736e95SDavid du Colombier 	0x010d, 0x00e9, 0x0119, 0x00eb, 0x011b, 0x00ed, 0x00ee, 0x010f,
51f5736e95SDavid du Colombier 	0x0111, 0x0144, 0x0148, 0x00f3, 0x00f4, 0x0151, 0x00f6, 0x00f7,
52f5736e95SDavid du Colombier 	0x0159, 0x016f, 0x00fa, 0x0171, 0x00fc, 0x00fd, 0x0163, 0x02d9,
53f5736e95SDavid du Colombier };
54f5736e95SDavid du Colombier 
55*25b329d5SDavid du Colombier static const USHORT usCp1251[] = {	/* Windows implementation of Cyrillic */
56*25b329d5SDavid du Colombier 	0x0402, 0x0403, 0x201a, 0x0453, 0x201e, 0x2026, 0x2020, 0x2021,
57*25b329d5SDavid du Colombier 	0x20ac, 0x2030, 0x0409, 0x2039, 0x040a, 0x040c, 0x040b, 0x040f,
58*25b329d5SDavid du Colombier 	0x0452, 0x2018, 0x2019, 0x201c, 0x201d, 0x2022, 0x2013, 0x2014,
59*25b329d5SDavid du Colombier 	0x00f3, 0x2122, 0x0459, 0x203a, 0x045a, 0x045c, 0x045b, 0x045f,
60*25b329d5SDavid du Colombier 	0x00a0, 0x040e, 0x045e, 0x0408, 0x00a4, 0x0490, 0x00a6, 0x00a7,
61*25b329d5SDavid du Colombier 	0x0401, 0x00a9, 0x0404, 0x00ab, 0x00ac, 0x00ad, 0x00ae, 0x0407,
62*25b329d5SDavid du Colombier 	0x00b0, 0x00b1, 0x0406, 0x0456, 0x0491, 0x00b5, 0x00b6, 0x00b7,
63*25b329d5SDavid du Colombier 	0x0451, 0x2116, 0x0454, 0x00bb, 0x0458, 0x0405, 0x0455, 0x0457,
64*25b329d5SDavid du Colombier 	0x0410, 0x0411, 0x0412, 0x0413, 0x0414, 0x0415, 0x0416, 0x0417,
65*25b329d5SDavid du Colombier 	0x0418, 0x0419, 0x041a, 0x041b, 0x041c, 0x041d, 0x041e, 0x041f,
66*25b329d5SDavid du Colombier 	0x0420, 0x0421, 0x0422, 0x0423, 0x0424, 0x0425, 0x0426, 0x0427,
67*25b329d5SDavid du Colombier 	0x0428, 0x0429, 0x042a, 0x042b, 0x042c, 0x042d, 0x042e, 0x042f,
68*25b329d5SDavid du Colombier 	0x0430, 0x0431, 0x0432, 0x0433, 0x0434, 0x0435, 0x0436, 0x0437,
69*25b329d5SDavid du Colombier 	0x0438, 0x0439, 0x043a, 0x043b, 0x043c, 0x043d, 0x043e, 0x043f,
70*25b329d5SDavid du Colombier 	0x0440, 0x0441, 0x0442, 0x0443, 0x0444, 0x0445, 0x0446, 0x0447,
71*25b329d5SDavid du Colombier 	0x0448, 0x0449, 0x044a, 0x044b, 0x044c, 0x044d, 0x044e, 0x044f,
72*25b329d5SDavid du Colombier };
73*25b329d5SDavid du Colombier 
74*25b329d5SDavid du Colombier static const USHORT usCp1252[] = {	/* Windows implementation of Latin1 */
75f5736e95SDavid du Colombier 	0x20ac, 0x003f, 0x201a, 0x0192, 0x201e, 0x2026, 0x2020, 0x2021,
76f5736e95SDavid du Colombier 	0x02c6, 0x2030, 0x0160, 0x2039, 0x0152, 0x003f, 0x017d, 0x003f,
77f5736e95SDavid du Colombier 	0x003f, 0x2018, 0x2019, 0x201c, 0x201d, 0x2022, 0x2013, 0x2014,
78f5736e95SDavid du Colombier 	0x02dc, 0x2122, 0x0161, 0x203a, 0x0153, 0x003f, 0x017e, 0x0178,
79*25b329d5SDavid du Colombier 	0x00a0, 0x00a1, 0x00a2, 0x00a3, 0x00a4, 0x00a5, 0x00a6, 0x00a7,
80*25b329d5SDavid du Colombier 	0x00a8, 0x00a9, 0x00aa, 0x00ab, 0x00ac, 0x00ad, 0x00ae, 0x00af,
81*25b329d5SDavid du Colombier 	0x00b0, 0x00b1, 0x00b2, 0x00b3, 0x00b4, 0x00b5, 0x00b6, 0x00b7,
82*25b329d5SDavid du Colombier 	0x00b8, 0x00b9, 0x00ba, 0x00bb, 0x00bc, 0x00bd, 0x00be, 0x00bf,
83*25b329d5SDavid du Colombier 	0x00c0, 0x00c1, 0x00c2, 0x00c3, 0x00c4, 0x00c5, 0x00c6, 0x00c7,
84*25b329d5SDavid du Colombier 	0x00c8, 0x00c9, 0x00ca, 0x00cb, 0x00cc, 0x00cd, 0x00ce, 0x00cf,
85*25b329d5SDavid du Colombier 	0x00d0, 0x00d1, 0x00d2, 0x00d3, 0x00d4, 0x00d5, 0x00d6, 0x00d7,
86*25b329d5SDavid du Colombier 	0x00d8, 0x00d9, 0x00da, 0x00db, 0x00dc, 0x00dd, 0x00de, 0x00df,
87*25b329d5SDavid du Colombier 	0x00e0, 0x00e1, 0x00e2, 0x00e3, 0x00e4, 0x00e5, 0x00e6, 0x00e7,
88*25b329d5SDavid du Colombier 	0x00e8, 0x00e9, 0x00ea, 0x00eb, 0x00ec, 0x00ed, 0x00ee, 0x00ef,
89*25b329d5SDavid du Colombier 	0x00f0, 0x00f1, 0x00f2, 0x00f3, 0x00f4, 0x00f5, 0x00f6, 0x00f7,
90*25b329d5SDavid du Colombier 	0x00f8, 0x00f9, 0x00fa, 0x00fb, 0x00fc, 0x00fd, 0x00fe, 0x00ff,
91f5736e95SDavid du Colombier };
92f5736e95SDavid du Colombier 
93*25b329d5SDavid du Colombier static const USHORT usMacRoman[] = {	/* Apple implementation of Latin1 */
94f5736e95SDavid du Colombier 	0x00c4, 0x00c5, 0x00c7, 0x00c9, 0x00d1, 0x00d6, 0x00dc, 0x00e1,
95f5736e95SDavid du Colombier 	0x00e0, 0x00e2, 0x00e4, 0x00e3, 0x00e5, 0x00e7, 0x00e9, 0x00e8,
96f5736e95SDavid du Colombier 	0x00ea, 0x00eb, 0x00ed, 0x00ec, 0x00ee, 0x00ef, 0x00f1, 0x00f3,
97f5736e95SDavid du Colombier 	0x00f2, 0x00f4, 0x00f6, 0x00f5, 0x00fa, 0x00f9, 0x00fb, 0x00fc,
98f5736e95SDavid du Colombier 	0x2020, 0x00b0, 0x00a2, 0x00a3, 0x00a7, 0x2022, 0x00b6, 0x00df,
99f5736e95SDavid du Colombier 	0x00ae, 0x00a9, 0x2122, 0x00b4, 0x00a8, 0x2260, 0x00c6, 0x00d8,
100f5736e95SDavid du Colombier 	0x221e, 0x00b1, 0x2264, 0x2265, 0x00a5, 0x00b5, 0x2202, 0x2211,
101f5736e95SDavid du Colombier 	0x220f, 0x03c0, 0x222b, 0x00aa, 0x00ba, 0x2126, 0x00e6, 0x00f8,
102f5736e95SDavid du Colombier 	0x00bf, 0x00a1, 0x00ac, 0x221a, 0x0192, 0x2248, 0x2206, 0x00ab,
103f5736e95SDavid du Colombier 	0x00bb, 0x2026, 0x00a0, 0x00c0, 0x00c3, 0x00d5, 0x0152, 0x0153,
104f5736e95SDavid du Colombier 	0x2013, 0x2014, 0x201c, 0x201d, 0x2018, 0x2019, 0x00f7, 0x25ca,
105f5736e95SDavid du Colombier 	0x00ff, 0x0178, 0x2044, 0x00a4, 0x2039, 0x203a, 0xfb01, 0xfb02,
106f5736e95SDavid du Colombier 	0x2021, 0x00b7, 0x201a, 0x201e, 0x2030, 0x00c2, 0x00ca, 0x00c1,
107f5736e95SDavid du Colombier 	0x00cb, 0x00c8, 0x00cd, 0x00ce, 0x00cf, 0x00cc, 0x00d3, 0x00d4,
108f5736e95SDavid du Colombier 	0x003f, 0x00d2, 0x00da, 0x00db, 0x00d9, 0x0131, 0x02c6, 0x02dc,
109f5736e95SDavid du Colombier 	0x00af, 0x02d8, 0x02d9, 0x02da, 0x00b8, 0x02dd, 0x02db, 0x02c7,
110f5736e95SDavid du Colombier };
111f5736e95SDavid du Colombier 
112f5736e95SDavid du Colombier static const USHORT usPrivateArea[] = {
113f5736e95SDavid du Colombier 	0x0020, 0x0021, 0x2200, 0x0023, 0x2203, 0x0025, 0x0026, 0x220d,
114f5736e95SDavid du Colombier 	0x0028, 0x0029, 0x2217, 0x002b, 0x002c, 0x2212, 0x002e, 0x002f,
115f5736e95SDavid du Colombier 	0x0030, 0x0031, 0x0032, 0x0033, 0x0034, 0x0035, 0x0036, 0x0037,
116f5736e95SDavid du Colombier 	0x0038, 0x0039, 0x003a, 0x003b, 0x003c, 0x2019, 0x003e, 0x003f,
117f5736e95SDavid du Colombier 	0x201d, 0x201c, 0x0392, 0x03a7, 0x0394, 0x0395, 0x03a6, 0x0393,
118f5736e95SDavid du Colombier 	0x0397, 0x0399, 0x03d1, 0x039a, 0x039b, 0x039c, 0x039d, 0x039f,
119f5736e95SDavid du Colombier 	0x03a0, 0x0398, 0x03a1, 0x03a3, 0x03a4, 0x03a5, 0x03c2, 0x03a9,
120f5736e95SDavid du Colombier 	0x039e, 0x03a8, 0x0396, 0x005b, 0x2234, 0x005d, 0x22a5, 0x005f,
121f5736e95SDavid du Colombier 	0x003f, 0x03b1, 0x03b2, 0x03c7, 0x03b4, 0x03b5, 0x03c6, 0x03b3,
122f5736e95SDavid du Colombier 	0x03b7, 0x03b9, 0x03d5, 0x03ba, 0x03bb, 0x03bc, 0x03bd, 0x03bf,
123f5736e95SDavid du Colombier 	0x03c0, 0x03b8, 0x03c1, 0x03c3, 0x03c4, 0x03c5, 0x03d6, 0x03c9,
124f5736e95SDavid du Colombier 	0x03be, 0x03c8, 0x03b6, 0x007b, 0x007c, 0x007d, 0x223c, 0x003f,
125f5736e95SDavid du Colombier 	0x003f, 0x003f, 0x003f, 0x003f, 0x003f, 0x003f, 0x003f, 0x003f,
126f5736e95SDavid du Colombier 	0x003f, 0x003f, 0x003f, 0x003f, 0x003f, 0x003f, 0x003f, 0x003f,
127f5736e95SDavid du Colombier 	0x003f, 0x003f, 0x003f, 0x2022, 0x003f, 0x003f, 0x003f, 0x003f,
128f5736e95SDavid du Colombier 	0x003f, 0x003f, 0x003f, 0x003f, 0x003f, 0x003f, 0x003f, 0x003f,
129f5736e95SDavid du Colombier 	0x20ac, 0x03d2, 0x2032, 0x2264, 0x2044, 0x221e, 0x0192, 0x2663,
130f5736e95SDavid du Colombier 	0x2666, 0x2665, 0x2660, 0x2194, 0x2190, 0x2191, 0x2192, 0x2193,
131f5736e95SDavid du Colombier 	0x00b0, 0x00b1, 0x2033, 0x2265, 0x00d7, 0x221d, 0x2202, 0x2022,
132f5736e95SDavid du Colombier 	0x00f7, 0x2260, 0x2261, 0x2248, 0x2026, 0x007c, 0x23af, 0x21b5,
133f5736e95SDavid du Colombier 	0x2135, 0x2111, 0x211c, 0x2118, 0x2297, 0x2295, 0x2205, 0x2229,
134f5736e95SDavid du Colombier 	0x222a, 0x2283, 0x2287, 0x2284, 0x2282, 0x2286, 0x2208, 0x2209,
135f5736e95SDavid du Colombier 	0x2220, 0x2207, 0x00ae, 0x00a9, 0x2122, 0x220f, 0x221a, 0x22c5,
136f5736e95SDavid du Colombier 	0x00ac, 0x2227, 0x2228, 0x21d4, 0x21d0, 0x21d1, 0x21d2, 0x21d3,
137f5736e95SDavid du Colombier 	0x22c4, 0x3008, 0x00ae, 0x00a9, 0x2122, 0x2211, 0x239b, 0x239c,
138f5736e95SDavid du Colombier 	0x239d, 0x23a1, 0x23a2, 0x23a3, 0x23a7, 0x23a8, 0x23a9, 0x23aa,
139f5736e95SDavid du Colombier 	0x003f, 0x3009, 0x222b, 0x2320, 0x23ae, 0x2321, 0x239e, 0x239f,
140f5736e95SDavid du Colombier 	0x23a0, 0x23a4, 0x23a5, 0x23a6, 0x23ab, 0x23ac, 0x23ad, 0x003f,
141f5736e95SDavid du Colombier };
142f5736e95SDavid du Colombier 
143f5736e95SDavid du Colombier typedef struct char_table_tag {
144*25b329d5SDavid du Colombier 	UCHAR	ucLocal;
145f5736e95SDavid du Colombier 	USHORT	usUnicode;
146f5736e95SDavid du Colombier } char_table_type;
147f5736e95SDavid du Colombier 
148*25b329d5SDavid du Colombier static char_table_type	atCharTable[256];
149*25b329d5SDavid du Colombier static size_t		tNextPosFree = 0;
150f5736e95SDavid du Colombier 
151f5736e95SDavid du Colombier 
152f5736e95SDavid du Colombier /*
153f5736e95SDavid du Colombier  * iCompare - compare two records
154f5736e95SDavid du Colombier  *
155f5736e95SDavid du Colombier  * Compares two records. For use by qsort(3C) and bsearch(3C).
156f5736e95SDavid du Colombier  *
157f5736e95SDavid du Colombier  * returns -1 if rec1 < rec2, 0 if rec1 == rec2, 1 if rec1 > rec2
158f5736e95SDavid du Colombier  */
159f5736e95SDavid du Colombier static int
iCompare(const void * pvRecord1,const void * pvRecord2)160f5736e95SDavid du Colombier iCompare(const void *pvRecord1, const void *pvRecord2)
161f5736e95SDavid du Colombier {
162f5736e95SDavid du Colombier 	USHORT	usUnicode1, usUnicode2;
163f5736e95SDavid du Colombier 
164f5736e95SDavid du Colombier 	usUnicode1 = ((char_table_type *)pvRecord1)->usUnicode;
165f5736e95SDavid du Colombier 	usUnicode2 = ((char_table_type *)pvRecord2)->usUnicode;
166f5736e95SDavid du Colombier 
167f5736e95SDavid du Colombier 	if (usUnicode1 < usUnicode2) {
168f5736e95SDavid du Colombier 		return -1;
169f5736e95SDavid du Colombier 	}
170f5736e95SDavid du Colombier 	if (usUnicode1 > usUnicode2) {
171f5736e95SDavid du Colombier 		return 1;
172f5736e95SDavid du Colombier 	}
173f5736e95SDavid du Colombier 	return 0;
174f5736e95SDavid du Colombier } /* end of iCompare */
175f5736e95SDavid du Colombier 
176f5736e95SDavid du Colombier /*
177f5736e95SDavid du Colombier  * pGetCharTableRecord - get the character table record
178f5736e95SDavid du Colombier  *
179f5736e95SDavid du Colombier  * returns a pointer to the record when found, otherwise NULL
180f5736e95SDavid du Colombier  */
181f5736e95SDavid du Colombier static const char_table_type *
pGetCharTableRecord(USHORT usUnicode)182f5736e95SDavid du Colombier pGetCharTableRecord(USHORT usUnicode)
183f5736e95SDavid du Colombier {
184f5736e95SDavid du Colombier 	char_table_type	tKey;
185f5736e95SDavid du Colombier 
186*25b329d5SDavid du Colombier 	if (tNextPosFree == 0) {
187*25b329d5SDavid du Colombier 		return NULL;
188*25b329d5SDavid du Colombier 	}
189f5736e95SDavid du Colombier 	tKey.usUnicode = usUnicode;
190*25b329d5SDavid du Colombier 	tKey.ucLocal = 0;
191f5736e95SDavid du Colombier 	return (char_table_type *)bsearch(&tKey,
192f5736e95SDavid du Colombier 			atCharTable,
193*25b329d5SDavid du Colombier 			tNextPosFree, sizeof(atCharTable[0]),
194f5736e95SDavid du Colombier 			iCompare);
195f5736e95SDavid du Colombier } /* end of pGetCharTableRecord */
196f5736e95SDavid du Colombier 
197f5736e95SDavid du Colombier /*
198*25b329d5SDavid du Colombier  * ucGetBulletCharacter - get the local representation of the bullet
199f5736e95SDavid du Colombier  */
200f5736e95SDavid du Colombier UCHAR
ucGetBulletCharacter(conversion_type eConversionType,encoding_type eEncoding)201*25b329d5SDavid du Colombier ucGetBulletCharacter(conversion_type eConversionType, encoding_type eEncoding)
202*25b329d5SDavid du Colombier {
203*25b329d5SDavid du Colombier #if defined(__riscos)
204*25b329d5SDavid du Colombier 	return 0x8f;
205*25b329d5SDavid du Colombier #else
206*25b329d5SDavid du Colombier 	const char_table_type	*pRec;
207*25b329d5SDavid du Colombier 
208*25b329d5SDavid du Colombier 	fail(eEncoding == encoding_utf_8);
209*25b329d5SDavid du Colombier 
210*25b329d5SDavid du Colombier 	if (eEncoding == encoding_latin_1 &&
211*25b329d5SDavid du Colombier 	    (eConversionType == conversion_ps ||
212*25b329d5SDavid du Colombier 	     eConversionType == conversion_pdf)) {
213*25b329d5SDavid du Colombier 		/* Ugly, but it makes the PostScript and PDF look better */
214*25b329d5SDavid du Colombier 		return (UCHAR)143;
215*25b329d5SDavid du Colombier 	}
216*25b329d5SDavid du Colombier 	if (eConversionType != conversion_text &&
217*25b329d5SDavid du Colombier 	    eConversionType != conversion_fmt_text) {
218*25b329d5SDavid du Colombier 		pRec = pGetCharTableRecord(UNICODE_BULLET);
219*25b329d5SDavid du Colombier 		if (pRec != NULL) {
220*25b329d5SDavid du Colombier 			return pRec->ucLocal;
221*25b329d5SDavid du Colombier 		}
222*25b329d5SDavid du Colombier 		pRec = pGetCharTableRecord(UNICODE_BULLET_OPERATOR);
223*25b329d5SDavid du Colombier 		if (pRec != NULL) {
224*25b329d5SDavid du Colombier 			return pRec->ucLocal;
225*25b329d5SDavid du Colombier 		}
226*25b329d5SDavid du Colombier 		pRec = pGetCharTableRecord(UNICODE_MIDDLE_DOT);
227*25b329d5SDavid du Colombier 		if (pRec != NULL) {
228*25b329d5SDavid du Colombier 			return pRec->ucLocal;
229*25b329d5SDavid du Colombier 		}
230*25b329d5SDavid du Colombier 	}
231*25b329d5SDavid du Colombier 	return (UCHAR)'.';
232*25b329d5SDavid du Colombier #endif /* __riscos */
233*25b329d5SDavid du Colombier } /* end of ucGetBulletCharacter */
234*25b329d5SDavid du Colombier 
235*25b329d5SDavid du Colombier /*
236*25b329d5SDavid du Colombier  * ucGetNbspCharacter - get the local representation of the non-breaking space
237*25b329d5SDavid du Colombier  */
238*25b329d5SDavid du Colombier UCHAR
ucGetNbspCharacter(void)239*25b329d5SDavid du Colombier ucGetNbspCharacter(void)
240f5736e95SDavid du Colombier {
241f5736e95SDavid du Colombier 	const char_table_type	*pRec;
242f5736e95SDavid du Colombier 
243f5736e95SDavid du Colombier 	pRec = pGetCharTableRecord(0x00a0);	/* Unicode non-breaking space */
244*25b329d5SDavid du Colombier 	if (pRec == NULL) {
245*25b329d5SDavid du Colombier 		DBG_MSG("Non-breaking space record not found");
246f5736e95SDavid du Colombier 		/* No value found, use the best guess */
247f5736e95SDavid du Colombier 		return (UCHAR)0xa0;
248f5736e95SDavid du Colombier 	}
249*25b329d5SDavid du Colombier 	return pRec->ucLocal;
250*25b329d5SDavid du Colombier } /* end of ucGetNbspCharacter */
251f5736e95SDavid du Colombier 
252f5736e95SDavid du Colombier /*
253f5736e95SDavid du Colombier  * bReadCharacterMappingTable - read the mapping table
254f5736e95SDavid du Colombier  *
255f5736e95SDavid du Colombier  * Read the character mapping table from file and have the contents sorted
256f5736e95SDavid du Colombier  *
257f5736e95SDavid du Colombier  * returns TRUE if successful, otherwise FALSE
258f5736e95SDavid du Colombier  */
259f5736e95SDavid du Colombier BOOL
bReadCharacterMappingTable(FILE * pFile)260*25b329d5SDavid du Colombier bReadCharacterMappingTable(FILE *pFile)
261f5736e95SDavid du Colombier {
262f5736e95SDavid du Colombier 	char	*pcTmp;
263f5736e95SDavid du Colombier 	ULONG	ulUnicode;
264f5736e95SDavid du Colombier 	UINT	uiLocal;
265f5736e95SDavid du Colombier 	int	iFields;
266f5736e95SDavid du Colombier 	char	szLine[81];
267f5736e95SDavid du Colombier 
268f5736e95SDavid du Colombier 	if (pFile == NULL) {
269f5736e95SDavid du Colombier 		return FALSE;
270f5736e95SDavid du Colombier 	}
271*25b329d5SDavid du Colombier 
272*25b329d5SDavid du Colombier 	/* Clean the table first */
273f5736e95SDavid du Colombier 	(void)memset(atCharTable, 0, sizeof(atCharTable));
274f5736e95SDavid du Colombier 
275*25b329d5SDavid du Colombier 	/* Fill the table */
276f5736e95SDavid du Colombier 	while (fgets(szLine, (int)sizeof(szLine), pFile)) {
277f5736e95SDavid du Colombier 		if (szLine[0] == '#' ||
278f5736e95SDavid du Colombier 		    szLine[0] == '\r' ||
279f5736e95SDavid du Colombier 		    szLine[0] == '\n') {
280f5736e95SDavid du Colombier 			/* Comment or empty line */
281f5736e95SDavid du Colombier 			continue;
282f5736e95SDavid du Colombier 		}
283f5736e95SDavid du Colombier 		iFields = sscanf(szLine, "%x %lx %*s", &uiLocal, &ulUnicode);
284f5736e95SDavid du Colombier 		if (iFields != 2) {
285f5736e95SDavid du Colombier 			pcTmp = strchr(szLine, '\r');
286f5736e95SDavid du Colombier 			if (pcTmp != NULL) {
287f5736e95SDavid du Colombier 				*pcTmp = '\0';
288f5736e95SDavid du Colombier 			}
289f5736e95SDavid du Colombier 			pcTmp = strchr(szLine, '\n');
290f5736e95SDavid du Colombier 			if (pcTmp != NULL) {
291f5736e95SDavid du Colombier 				*pcTmp = '\0';
292f5736e95SDavid du Colombier 			}
293f5736e95SDavid du Colombier 			werr(0, "Syntax error in: '%s'", szLine);
294f5736e95SDavid du Colombier 			continue;
295f5736e95SDavid du Colombier 		}
296f5736e95SDavid du Colombier 		if (uiLocal > 0xff || ulUnicode > 0xffff) {
297f5736e95SDavid du Colombier 			werr(0, "Syntax error in: '%02x %04lx'",
298f5736e95SDavid du Colombier 					uiLocal, ulUnicode);
299f5736e95SDavid du Colombier 			continue;
300f5736e95SDavid du Colombier 		}
301*25b329d5SDavid du Colombier 		/* Store only the relevant entries */
302*25b329d5SDavid du Colombier 		if (uiLocal != ulUnicode || uiLocal >= 0x80) {
303*25b329d5SDavid du Colombier 			atCharTable[tNextPosFree].ucLocal = (UCHAR)uiLocal;
304*25b329d5SDavid du Colombier 			atCharTable[tNextPosFree].usUnicode = (USHORT)ulUnicode;
305*25b329d5SDavid du Colombier 			tNextPosFree++;
306*25b329d5SDavid du Colombier 		}
307*25b329d5SDavid du Colombier 		if (tNextPosFree >= elementsof(atCharTable)) {
308*25b329d5SDavid du Colombier 			werr(0, "Too many entries in the character mapping "
309*25b329d5SDavid du Colombier 				"file. Ignoring the rest.");
310*25b329d5SDavid du Colombier 			break;
311f5736e95SDavid du Colombier 		}
312f5736e95SDavid du Colombier 	}
313f5736e95SDavid du Colombier 
314*25b329d5SDavid du Colombier 	if (tNextPosFree != 0) {
315f5736e95SDavid du Colombier 		DBG_HEX(atCharTable[0].usUnicode);
316*25b329d5SDavid du Colombier 		DBG_HEX(atCharTable[tNextPosFree - 1].usUnicode);
317f5736e95SDavid du Colombier 
318f5736e95SDavid du Colombier 		qsort(atCharTable,
319*25b329d5SDavid du Colombier 			tNextPosFree, sizeof(atCharTable[0]),
320f5736e95SDavid du Colombier 			iCompare);
321f5736e95SDavid du Colombier 
322f5736e95SDavid du Colombier 		DBG_HEX(atCharTable[0].usUnicode);
323*25b329d5SDavid du Colombier 		DBG_HEX(atCharTable[tNextPosFree - 1].usUnicode);
324*25b329d5SDavid du Colombier 	}
325f5736e95SDavid du Colombier 
326f5736e95SDavid du Colombier 	return TRUE;
327f5736e95SDavid du Colombier } /* end of bReadCharacterMappingTable */
328f5736e95SDavid du Colombier 
329f5736e95SDavid du Colombier /*
330f5736e95SDavid du Colombier  * ulTranslateCharacters - Translate characters to local representation
331f5736e95SDavid du Colombier  *
332f5736e95SDavid du Colombier  * Translate all characters to local representation
333f5736e95SDavid du Colombier  *
334f5736e95SDavid du Colombier  * returns the translated character
335f5736e95SDavid du Colombier  */
336f5736e95SDavid du Colombier ULONG
ulTranslateCharacters(USHORT usChar,ULONG ulFileOffset,int iWordVersion,conversion_type eConversionType,encoding_type eEncoding,BOOL bUseMacCharSet)337f5736e95SDavid du Colombier ulTranslateCharacters(USHORT usChar, ULONG ulFileOffset, int iWordVersion,
338f5736e95SDavid du Colombier 	conversion_type eConversionType, encoding_type eEncoding,
339f5736e95SDavid du Colombier 	BOOL bUseMacCharSet)
340f5736e95SDavid du Colombier {
341f5736e95SDavid du Colombier 	const char_table_type	*pTmp;
342*25b329d5SDavid du Colombier 	const USHORT	*usCharSet;
343f5736e95SDavid du Colombier 
344*25b329d5SDavid du Colombier 	usCharSet = NULL;
345f5736e95SDavid du Colombier 	if (bUseMacCharSet) {
346*25b329d5SDavid du Colombier 		/* Macintosh character set */
347*25b329d5SDavid du Colombier 		usCharSet = usMacRoman;
348f5736e95SDavid du Colombier 	} else if (iWordVersion == 0) {
349*25b329d5SDavid du Colombier 		/* DOS character set */
350*25b329d5SDavid du Colombier 		usCharSet = usCp850;
351f5736e95SDavid du Colombier 	} else {
352*25b329d5SDavid du Colombier 		/* Windows character set */
353*25b329d5SDavid du Colombier 		switch (eEncoding) {
354*25b329d5SDavid du Colombier 		case encoding_latin_2:
355*25b329d5SDavid du Colombier 			usCharSet = usCp1250;
356*25b329d5SDavid du Colombier 			break;
357*25b329d5SDavid du Colombier 		case encoding_cyrillic:
358*25b329d5SDavid du Colombier 			usCharSet = usCp1251;
359*25b329d5SDavid du Colombier 			break;
360*25b329d5SDavid du Colombier 		case encoding_latin_1:
361*25b329d5SDavid du Colombier 		default:
362*25b329d5SDavid du Colombier 			usCharSet = usCp1252;
363*25b329d5SDavid du Colombier 			break;
364*25b329d5SDavid du Colombier 		}
365*25b329d5SDavid du Colombier 	}
366*25b329d5SDavid du Colombier 	fail(usCharSet == NULL);
367f5736e95SDavid du Colombier 	if (usChar >= 0x80 && usChar <= 0x9f) {
368f5736e95SDavid du Colombier 		/* Translate implementation defined characters */
369*25b329d5SDavid du Colombier 		usChar = usCharSet[usChar - 0x80];
370*25b329d5SDavid du Colombier 	} else if (iWordVersion < 8 && usChar >= 0xa0 && usChar <= 0xff) {
371*25b329d5SDavid du Colombier 		/* Translate old character set to Unixcode */
372*25b329d5SDavid du Colombier 		usChar = usCharSet[usChar - 0x80];
373f5736e95SDavid du Colombier 	}
374f5736e95SDavid du Colombier 
375f5736e95SDavid du Colombier 	/* Microsoft Unicode to real Unicode */
376f5736e95SDavid du Colombier 	if (usChar >= 0xf020 && usChar <= 0xf0ff) {
377f5736e95SDavid du Colombier 		DBG_HEX_C(usPrivateArea[usChar - 0xf020] == 0x003f, usChar);
378f5736e95SDavid du Colombier 		usChar = usPrivateArea[usChar - 0xf020];
379f5736e95SDavid du Colombier 	}
380f5736e95SDavid du Colombier 
381f5736e95SDavid du Colombier 	/* Characters with a special meaning in Word */
382f5736e95SDavid du Colombier 	switch (usChar) {
383f5736e95SDavid du Colombier 	case IGNORE_CHARACTER:
384f5736e95SDavid du Colombier 	case FOOTNOTE_SEPARATOR:
385f5736e95SDavid du Colombier 	case FOOTNOTE_CONTINUATION:
386f5736e95SDavid du Colombier 	case ANNOTATION:
387f5736e95SDavid du Colombier 	case FRAME:
388f5736e95SDavid du Colombier 	case LINE_FEED:
389f5736e95SDavid du Colombier 	case WORD_SOFT_HYPHEN:
390f5736e95SDavid du Colombier 	case UNICODE_HYPHENATION_POINT:
391f5736e95SDavid du Colombier 		return IGNORE_CHARACTER;
392f5736e95SDavid du Colombier 	case PICTURE:
393f5736e95SDavid du Colombier 	case TABLE_SEPARATOR:
394f5736e95SDavid du Colombier 	case TAB:
395f5736e95SDavid du Colombier 	case HARD_RETURN:
396f5736e95SDavid du Colombier 	case PAGE_BREAK:
397f5736e95SDavid du Colombier 	case PAR_END:
398f5736e95SDavid du Colombier 	case COLUMN_FEED:
399f5736e95SDavid du Colombier 		return (ULONG)usChar;
400f5736e95SDavid du Colombier 	case FOOTNOTE_OR_ENDNOTE:
401f5736e95SDavid du Colombier 		NO_DBG_HEX(ulFileOffset);
402f5736e95SDavid du Colombier 		switch (eGetNotetype(ulFileOffset)) {
403f5736e95SDavid du Colombier 		case notetype_is_footnote:
404f5736e95SDavid du Colombier 			return FOOTNOTE_CHAR;
405f5736e95SDavid du Colombier 		case notetype_is_endnote:
406f5736e95SDavid du Colombier 			return ENDNOTE_CHAR;
407f5736e95SDavid du Colombier 		default:
408f5736e95SDavid du Colombier 			return UNKNOWN_NOTE_CHAR;
409f5736e95SDavid du Colombier 		}
410f5736e95SDavid du Colombier 	case WORD_UNBREAKABLE_JOIN:
411f5736e95SDavid du Colombier 		return (ULONG)OUR_UNBREAKABLE_JOIN;
412f5736e95SDavid du Colombier 	default:
413f5736e95SDavid du Colombier 		break;
414f5736e95SDavid du Colombier 	}
415f5736e95SDavid du Colombier 
416*25b329d5SDavid du Colombier 	if (eEncoding != encoding_utf_8) {
417f5736e95SDavid du Colombier 		/* Latin characters in an oriental text */
418f5736e95SDavid du Colombier 		if (usChar >= 0xff01 && usChar <= 0xff5e) {
419f5736e95SDavid du Colombier 			usChar -= 0xfee0;
420f5736e95SDavid du Colombier 		}
421f5736e95SDavid du Colombier 	}
422f5736e95SDavid du Colombier 
423*25b329d5SDavid du Colombier 	if (eEncoding == encoding_latin_1 &&
424*25b329d5SDavid du Colombier 	    (eConversionType == conversion_ps ||
425*25b329d5SDavid du Colombier 	     eConversionType == conversion_pdf)) {
426*25b329d5SDavid du Colombier 		/* Ugly, but it makes the PostScript and PDF look better */
427f5736e95SDavid du Colombier 		switch (usChar) {
428f5736e95SDavid du Colombier 		case UNICODE_ELLIPSIS:
429f5736e95SDavid du Colombier 			return 140;
430f5736e95SDavid du Colombier 		case UNICODE_TRADEMARK_SIGN:
431f5736e95SDavid du Colombier 			return 141;
432f5736e95SDavid du Colombier 		case UNICODE_PER_MILLE_SIGN:
433f5736e95SDavid du Colombier 			return 142;
434f5736e95SDavid du Colombier 		case UNICODE_BULLET:
435*25b329d5SDavid du Colombier 		case UNICODE_BULLET_OPERATOR:
436f5736e95SDavid du Colombier 		case UNICODE_BLACK_CLUB_SUIT:
437*25b329d5SDavid du Colombier 			return 143;
438f5736e95SDavid du Colombier 		case UNICODE_LEFT_SINGLE_QMARK:
439f5736e95SDavid du Colombier 			return 144;
440f5736e95SDavid du Colombier 		case UNICODE_RIGHT_SINGLE_QMARK:
441f5736e95SDavid du Colombier 			return 145;
442f5736e95SDavid du Colombier 		case UNICODE_SINGLE_LEFT_ANGLE_QMARK:
443f5736e95SDavid du Colombier 			return 146;
444f5736e95SDavid du Colombier 		case UNICODE_SINGLE_RIGHT_ANGLE_QMARK:
445f5736e95SDavid du Colombier 			return 147;
446f5736e95SDavid du Colombier 		case UNICODE_LEFT_DOUBLE_QMARK:
447f5736e95SDavid du Colombier 			return 148;
448f5736e95SDavid du Colombier 		case UNICODE_RIGHT_DOUBLE_QMARK:
449f5736e95SDavid du Colombier 			return 149;
450f5736e95SDavid du Colombier 		case UNICODE_DOUBLE_LOW_9_QMARK:
451f5736e95SDavid du Colombier 			return 150;
452f5736e95SDavid du Colombier 		case UNICODE_EN_DASH:
453f5736e95SDavid du Colombier 			return 151;
454f5736e95SDavid du Colombier 		case UNICODE_EM_DASH:
455f5736e95SDavid du Colombier 			return 152;
456f5736e95SDavid du Colombier 		case UNICODE_MINUS_SIGN:
457f5736e95SDavid du Colombier 			return 153;
458f5736e95SDavid du Colombier 		case UNICODE_CAPITAL_LIGATURE_OE:
459f5736e95SDavid du Colombier 			return 154;
460f5736e95SDavid du Colombier 		case UNICODE_SMALL_LIGATURE_OE:
461f5736e95SDavid du Colombier 			return 155;
462f5736e95SDavid du Colombier 		case UNICODE_DAGGER:
463f5736e95SDavid du Colombier 			return 156;
464f5736e95SDavid du Colombier 		case UNICODE_DOUBLE_DAGGER:
465f5736e95SDavid du Colombier 			return 157;
466f5736e95SDavid du Colombier 		case UNICODE_SMALL_LIGATURE_FI:
467f5736e95SDavid du Colombier 			return 158;
468f5736e95SDavid du Colombier 		case UNICODE_SMALL_LIGATURE_FL:
469f5736e95SDavid du Colombier 			return 159;
470f5736e95SDavid du Colombier 		default:
471f5736e95SDavid du Colombier 			break;
472f5736e95SDavid du Colombier 		}
473f5736e95SDavid du Colombier 	}
474f5736e95SDavid du Colombier 
475*25b329d5SDavid du Colombier 	if (eConversionType == conversion_pdf) {
476*25b329d5SDavid du Colombier 		if (eEncoding == encoding_latin_1) {
477*25b329d5SDavid du Colombier 			switch (usChar) {
478*25b329d5SDavid du Colombier 			case UNICODE_EURO_SIGN:
479*25b329d5SDavid du Colombier 				return 128;
480*25b329d5SDavid du Colombier 			default:
481*25b329d5SDavid du Colombier 				break;
482*25b329d5SDavid du Colombier 			}
483*25b329d5SDavid du Colombier 		} else if (eEncoding == encoding_latin_2) {
484*25b329d5SDavid du Colombier 			switch (usChar) {
485*25b329d5SDavid du Colombier 			case UNICODE_CAPITAL_D_WITH_STROKE:
486*25b329d5SDavid du Colombier 			case UNICODE_SMALL_D_WITH_STROKE:
487*25b329d5SDavid du Colombier 				return 0x3f;
488*25b329d5SDavid du Colombier 			default:
489*25b329d5SDavid du Colombier 				break;
490*25b329d5SDavid du Colombier 			}
491*25b329d5SDavid du Colombier 		}
492*25b329d5SDavid du Colombier 	}
493*25b329d5SDavid du Colombier 
494f5736e95SDavid du Colombier 	if (usChar < 0x80) {
495f5736e95SDavid du Colombier 		/* US ASCII */
496f5736e95SDavid du Colombier 		if (usChar < 0x20 || usChar == 0x7f) {
497f5736e95SDavid du Colombier 			/* Ignore control characters */
498f5736e95SDavid du Colombier 			DBG_HEX(usChar);
499f5736e95SDavid du Colombier 			DBG_FIXME();
500f5736e95SDavid du Colombier 			return IGNORE_CHARACTER;
501f5736e95SDavid du Colombier 		}
502f5736e95SDavid du Colombier 		return (ULONG)usChar;
503f5736e95SDavid du Colombier 	}
504f5736e95SDavid du Colombier 
505*25b329d5SDavid du Colombier 	if (eEncoding == encoding_utf_8) {
506f5736e95SDavid du Colombier 		/* No need to convert Unicode characters */
507f5736e95SDavid du Colombier 		return (ULONG)usChar;
508f5736e95SDavid du Colombier 	}
509f5736e95SDavid du Colombier 
510f5736e95SDavid du Colombier 	/* Unicode to local representation */
511f5736e95SDavid du Colombier 	pTmp = pGetCharTableRecord(usChar);
512f5736e95SDavid du Colombier 	if (pTmp != NULL) {
513f5736e95SDavid du Colombier 		DBG_HEX_C(usChar >= 0x7f && usChar <= 0x9f, usChar);
514*25b329d5SDavid du Colombier 		return (ULONG)pTmp->ucLocal;
515f5736e95SDavid du Colombier 	}
516f5736e95SDavid du Colombier 
517f5736e95SDavid du Colombier 	/* Fancy characters to simple US ASCII */
518f5736e95SDavid du Colombier 	switch (usChar) {
519f5736e95SDavid du Colombier 	case UNICODE_SMALL_F_HOOK:
520f5736e95SDavid du Colombier 		return (ULONG)'f';
521f5736e95SDavid du Colombier 	case UNICODE_GREEK_CAPITAL_CHI:
522f5736e95SDavid du Colombier 		return (ULONG)'X';
523f5736e95SDavid du Colombier 	case UNICODE_GREEK_SMALL_UPSILON:
524f5736e95SDavid du Colombier 		return (ULONG)'v';
525f5736e95SDavid du Colombier 	case UNICODE_MODIFIER_CIRCUMFLEX:
526f5736e95SDavid du Colombier 	case UNICODE_UPWARDS_ARROW:
527f5736e95SDavid du Colombier 		return (ULONG)'^';
528f5736e95SDavid du Colombier 	case UNICODE_SMALL_TILDE:
529f5736e95SDavid du Colombier 	case UNICODE_TILDE_OPERATOR:
530f5736e95SDavid du Colombier 		return (ULONG)'~';
531f5736e95SDavid du Colombier 	case UNICODE_EN_QUAD:
532f5736e95SDavid du Colombier 	case UNICODE_EM_QUAD:
533f5736e95SDavid du Colombier 	case UNICODE_EN_SPACE:
534f5736e95SDavid du Colombier 	case UNICODE_EM_SPACE:
535f5736e95SDavid du Colombier 	case UNICODE_THREE_PER_EM_SPACE:
536f5736e95SDavid du Colombier 	case UNICODE_FOUR_PER_EM_SPACE:
537f5736e95SDavid du Colombier 	case UNICODE_SIX_PER_EM_SPACE:
538f5736e95SDavid du Colombier 	case UNICODE_FIGURE_SPACE:
539f5736e95SDavid du Colombier 	case UNICODE_PUNCTUATION_SPACE:
540f5736e95SDavid du Colombier 	case UNICODE_THIN_SPACE:
541*25b329d5SDavid du Colombier 	case UNICODE_NARROW_NO_BREAK_SPACE:
542f5736e95SDavid du Colombier 	case UNICODE_LIGHT_SHADE:
543f5736e95SDavid du Colombier 	case UNICODE_MEDIUM_SHADE:
544f5736e95SDavid du Colombier 	case UNICODE_DARK_SHADE:
545f5736e95SDavid du Colombier 		return (ULONG)' ';
546f5736e95SDavid du Colombier 	case UNICODE_LEFT_DOUBLE_QMARK:
547f5736e95SDavid du Colombier 	case UNICODE_RIGHT_DOUBLE_QMARK:
548f5736e95SDavid du Colombier 	case UNICODE_DOUBLE_LOW_9_QMARK:
549f5736e95SDavid du Colombier 	case UNICODE_DOUBLE_HIGH_REV_9_QMARK:
550f5736e95SDavid du Colombier 	case UNICODE_DOUBLE_PRIME:
551f5736e95SDavid du Colombier 		return (ULONG)'"';
552f5736e95SDavid du Colombier 	case UNICODE_LEFT_SINGLE_QMARK:
553f5736e95SDavid du Colombier 	case UNICODE_RIGHT_SINGLE_QMARK:
554f5736e95SDavid du Colombier 	case UNICODE_SINGLE_LOW_9_QMARK:
555f5736e95SDavid du Colombier 	case UNICODE_SINGLE_HIGH_REV_9_QMARK:
556f5736e95SDavid du Colombier 	case UNICODE_PRIME:
557f5736e95SDavid du Colombier 		return (ULONG)'\'';
558f5736e95SDavid du Colombier 	case UNICODE_HYPHEN:
559f5736e95SDavid du Colombier 	case UNICODE_NON_BREAKING_HYPHEN:
560f5736e95SDavid du Colombier 	case UNICODE_FIGURE_DASH:
561f5736e95SDavid du Colombier 	case UNICODE_EN_DASH:
562f5736e95SDavid du Colombier 	case UNICODE_EM_DASH:
563f5736e95SDavid du Colombier 	case UNICODE_HORIZONTAL_BAR:
564f5736e95SDavid du Colombier 	case UNICODE_MINUS_SIGN:
565f5736e95SDavid du Colombier 	case UNICODE_BD_LIGHT_HORIZONTAL:
566f5736e95SDavid du Colombier 	case UNICODE_BD_DOUBLE_HORIZONTAL:
567f5736e95SDavid du Colombier 		return (ULONG)'-';
568f5736e95SDavid du Colombier 	case UNICODE_DOUBLE_VERTICAL_LINE:
569f5736e95SDavid du Colombier 	case UNICODE_BD_LIGHT_VERTICAL:
570f5736e95SDavid du Colombier 	case UNICODE_BD_DOUBLE_VERTICAL:
571f5736e95SDavid du Colombier 		return (ULONG)'|';
572f5736e95SDavid du Colombier 	case UNICODE_DOUBLE_LOW_LINE:
573f5736e95SDavid du Colombier 		return (ULONG)'_';
574f5736e95SDavid du Colombier 	case UNICODE_DAGGER:
575f5736e95SDavid du Colombier 		return (ULONG)'+';
576f5736e95SDavid du Colombier 	case UNICODE_DOUBLE_DAGGER:
577f5736e95SDavid du Colombier 		return (ULONG)'#';
578f5736e95SDavid du Colombier 	case UNICODE_BULLET:
579*25b329d5SDavid du Colombier 	case UNICODE_BULLET_OPERATOR:
580f5736e95SDavid du Colombier 	case UNICODE_BLACK_CLUB_SUIT:
581*25b329d5SDavid du Colombier 		return (ULONG)ucGetBulletCharacter(eConversionType, eEncoding);
582f5736e95SDavid du Colombier 	case UNICODE_ONE_DOT_LEADER:
583*25b329d5SDavid du Colombier 	case UNICODE_TWO_DOT_LEADER:
584f5736e95SDavid du Colombier 		return (ULONG)'.';
585f5736e95SDavid du Colombier 	case UNICODE_ELLIPSIS:
586*25b329d5SDavid du Colombier #if defined(__riscos)
587f5736e95SDavid du Colombier 		return (ULONG)OUR_ELLIPSIS;
588*25b329d5SDavid du Colombier #else
589*25b329d5SDavid du Colombier 		if (ulFileOffset == 0) {
590*25b329d5SDavid du Colombier 			return (ULONG)OUR_ELLIPSIS;
591*25b329d5SDavid du Colombier 		}
592*25b329d5SDavid du Colombier 		return UNICODE_ELLIPSIS;
593*25b329d5SDavid du Colombier #endif /* __riscos */
594*25b329d5SDavid du Colombier 	case UNICODE_DOUBLE_LEFT_ANGLE_QMARK:
595f5736e95SDavid du Colombier 	case UNICODE_TRIANGULAR_BULLET:
596f5736e95SDavid du Colombier 	case UNICODE_SINGLE_LEFT_ANGLE_QMARK:
597f5736e95SDavid du Colombier 	case UNICODE_LEFTWARDS_ARROW:
598f5736e95SDavid du Colombier 		return (ULONG)'<';
599*25b329d5SDavid du Colombier 	case UNICODE_DOUBLE_RIGHT_ANGLE_QMARK:
600f5736e95SDavid du Colombier 	case UNICODE_SINGLE_RIGHT_ANGLE_QMARK:
601f5736e95SDavid du Colombier 	case UNICODE_RIGHTWARDS_ARROW:
602f5736e95SDavid du Colombier 		return (ULONG)'>';
603f5736e95SDavid du Colombier 	case UNICODE_UNDERTIE:
604f5736e95SDavid du Colombier 		return (ULONG)'-';
605f5736e95SDavid du Colombier 	case UNICODE_N_ARY_SUMMATION:
606f5736e95SDavid du Colombier 		return (ULONG)'S';
607f5736e95SDavid du Colombier 	case UNICODE_EURO_SIGN:
608f5736e95SDavid du Colombier 		return (ULONG)'E';
609f5736e95SDavid du Colombier 	case UNICODE_CIRCLE:
610f5736e95SDavid du Colombier 	case UNICODE_SQUARE:
611f5736e95SDavid du Colombier 		return (ULONG)'O';
612f5736e95SDavid du Colombier 	case UNICODE_DIAMOND:
613f5736e95SDavid du Colombier 		return (ULONG)OUR_DIAMOND;
614*25b329d5SDavid du Colombier 	case UNICODE_NUMERO_SIGN:
615*25b329d5SDavid du Colombier 		return (ULONG)'N';
616f5736e95SDavid du Colombier 	case UNICODE_KELVIN_SIGN:
617f5736e95SDavid du Colombier 		return (ULONG)'K';
618f5736e95SDavid du Colombier 	case UNICODE_DOWNWARDS_ARROW:
619f5736e95SDavid du Colombier 		return (ULONG)'v';
620f5736e95SDavid du Colombier 	case UNICODE_FRACTION_SLASH:
621f5736e95SDavid du Colombier 	case UNICODE_DIVISION_SLASH:
622f5736e95SDavid du Colombier 		return (ULONG)'/';
623f5736e95SDavid du Colombier 	case UNICODE_ASTERISK_OPERATOR:
624f5736e95SDavid du Colombier 		return (ULONG)'*';
625f5736e95SDavid du Colombier 	case UNICODE_RATIO:
626f5736e95SDavid du Colombier 		return (ULONG)':';
627f5736e95SDavid du Colombier 	case UNICODE_BD_LIGHT_DOWN_RIGHT:
628f5736e95SDavid du Colombier 	case UNICODE_BD_LIGHT_DOWN_AND_LEFT:
629f5736e95SDavid du Colombier 	case UNICODE_BD_LIGHT_UP_AND_RIGHT:
630f5736e95SDavid du Colombier 	case UNICODE_BD_LIGHT_UP_AND_LEFT:
631f5736e95SDavid du Colombier 	case UNICODE_BD_LIGHT_VERTICAL_AND_RIGHT:
632f5736e95SDavid du Colombier 	case UNICODE_BD_LIGHT_VERTICAL_AND_LEFT:
633f5736e95SDavid du Colombier 	case UNICODE_BD_LIGHT_DOWN_AND_HORIZONTAL:
634f5736e95SDavid du Colombier 	case UNICODE_BD_LIGHT_UP_AND_HORIZONTAL:
635f5736e95SDavid du Colombier 	case UNICODE_BD_LIGHT_VERTICAL_AND_HORIZONTAL:
636f5736e95SDavid du Colombier 	case UNICODE_BD_DOUBLE_DOWN_AND_RIGHT:
637f5736e95SDavid du Colombier 	case UNICODE_BD_DOUBLE_DOWN_AND_LEFT:
638f5736e95SDavid du Colombier 	case UNICODE_BD_DOUBLE_UP_AND_RIGHT:
639f5736e95SDavid du Colombier 	case UNICODE_BD_DOUBLE_UP_AND_LEFT:
640f5736e95SDavid du Colombier 	case UNICODE_BD_DOUBLE_VERTICAL_AND_RIGHT:
641f5736e95SDavid du Colombier 	case UNICODE_BD_DOUBLE_VERTICAL_AND_LEFT:
642f5736e95SDavid du Colombier 	case UNICODE_BD_DOUBLE_DOWN_AND_HORIZONTAL:
643f5736e95SDavid du Colombier 	case UNICODE_BD_DOUBLE_UP_AND_HORIZONTAL:
644f5736e95SDavid du Colombier 	case UNICODE_BD_DOUBLE_VERTICAL_AND_HORIZONTAL:
645f5736e95SDavid du Colombier 	case UNICODE_BLACK_SQUARE:
646f5736e95SDavid du Colombier 		return (ULONG)'+';
647f5736e95SDavid du Colombier 	case UNICODE_HAIR_SPACE:
648f5736e95SDavid du Colombier 	case UNICODE_ZERO_WIDTH_SPACE:
649f5736e95SDavid du Colombier 	case UNICODE_ZERO_WIDTH_NON_JOINER:
650f5736e95SDavid du Colombier 	case UNICODE_ZERO_WIDTH_JOINER:
651f5736e95SDavid du Colombier 	case UNICODE_LEFT_TO_RIGHT_MARK:
652f5736e95SDavid du Colombier 	case UNICODE_RIGHT_TO_LEFT_MARK:
653f5736e95SDavid du Colombier 	case UNICODE_LEFT_TO_RIGHT_EMBEDDING:
654f5736e95SDavid du Colombier 	case UNICODE_RIGHT_TO_LEFT_EMBEDDING:
655*25b329d5SDavid du Colombier 	case UNICODE_POP_DIRECTIONAL_FORMATTING:
656*25b329d5SDavid du Colombier 	case UNICODE_LEFT_TO_RIGHT_OVERRIDE:
657*25b329d5SDavid du Colombier 	case UNICODE_RIGHT_TO_LEFT_OVERRIDE:
658*25b329d5SDavid du Colombier 	case UNICODE_ZERO_WIDTH_NO_BREAK_SPACE:
659f5736e95SDavid du Colombier 		return IGNORE_CHARACTER;
660f5736e95SDavid du Colombier 	default:
661f5736e95SDavid du Colombier 		break;
662f5736e95SDavid du Colombier 	}
663f5736e95SDavid du Colombier 
664f5736e95SDavid du Colombier 	if (usChar == UNICODE_TRADEMARK_SIGN) {
665f5736e95SDavid du Colombier 		/*
666f5736e95SDavid du Colombier 		 * No local representation, it doesn't look like anything in
667f5736e95SDavid du Colombier 		 * US-ASCII and a question mark does more harm than good.
668f5736e95SDavid du Colombier 		 */
669f5736e95SDavid du Colombier 		return IGNORE_CHARACTER;
670f5736e95SDavid du Colombier 	}
671f5736e95SDavid du Colombier 
672f5736e95SDavid du Colombier 	if (usChar >= 0xa0 && usChar <= 0xff) {
673f5736e95SDavid du Colombier 		/* Before Word 97, Word did't use Unicode */
674f5736e95SDavid du Colombier 		return (ULONG)usChar;
675f5736e95SDavid du Colombier 	}
676f5736e95SDavid du Colombier 
677f5736e95SDavid du Colombier 	DBG_HEX_C(usChar < 0x3000 || usChar >= 0xd800, ulFileOffset);
678f5736e95SDavid du Colombier 	DBG_HEX_C(usChar < 0x3000 || usChar >= 0xd800, usChar);
679f5736e95SDavid du Colombier 	DBG_MSG_C(usChar >= 0xe000 && usChar < 0xf900, "Private Use Area");
680f5736e95SDavid du Colombier 
681f5736e95SDavid du Colombier 	/* Untranslated Unicode character */
682f5736e95SDavid du Colombier 	return 0x3f;
683f5736e95SDavid du Colombier } /* end of ulTranslateCharacters */
684f5736e95SDavid du Colombier 
685f5736e95SDavid du Colombier /*
686f5736e95SDavid du Colombier  * ulToUpper - convert letter to upper case
687f5736e95SDavid du Colombier  *
688f5736e95SDavid du Colombier  * This function converts a letter to upper case. Unlike toupper(3) this
689f5736e95SDavid du Colombier  * function is independent from the settings of locale. This comes in handy
690f5736e95SDavid du Colombier  * for people who have to read Word documents in more than one language or
691f5736e95SDavid du Colombier  * contain more than one language.
692f5736e95SDavid du Colombier  *
693f5736e95SDavid du Colombier  * returns the converted letter, or ulChar if the conversion was not possible.
694f5736e95SDavid du Colombier  */
695f5736e95SDavid du Colombier ULONG
ulToUpper(ULONG ulChar)696f5736e95SDavid du Colombier ulToUpper(ULONG ulChar)
697f5736e95SDavid du Colombier {
698f5736e95SDavid du Colombier 	if (ulChar < 0x80) {
699f5736e95SDavid du Colombier 		/* US ASCII: use standard function */
700f5736e95SDavid du Colombier 		return (ULONG)toupper((int)ulChar);
701f5736e95SDavid du Colombier 	}
702f5736e95SDavid du Colombier 	if (ulChar >= 0xe0 && ulChar <= 0xfe && ulChar != 0xf7) {
703f5736e95SDavid du Colombier 		/*
704f5736e95SDavid du Colombier 		 * Lower case accented characters
705f5736e95SDavid du Colombier 		 * 0xf7 is Division sign; 0xd7 is Multiplication sign
706f5736e95SDavid du Colombier 		 * 0xff is y with diaeresis; 0xdf is Sharp s
707f5736e95SDavid du Colombier 		 */
708f5736e95SDavid du Colombier 		return ulChar & ~0x20;
709f5736e95SDavid du Colombier 	}
710f5736e95SDavid du Colombier #if defined(__STDC_ISO_10646__)
711f5736e95SDavid du Colombier 	/*
712f5736e95SDavid du Colombier 	 * If this is ISO C99 and all locales have wchar_t = ISO 10646
713f5736e95SDavid du Colombier 	 * (e.g., glibc 2.2 or newer), then use standard function
714f5736e95SDavid du Colombier 	 */
715f5736e95SDavid du Colombier 	if (ulChar > 0xff) {
716f5736e95SDavid du Colombier 		return (ULONG)towupper((wint_t)ulChar);
717f5736e95SDavid du Colombier 	}
718f5736e95SDavid du Colombier #endif /* __STDC_ISO_10646__ */
719f5736e95SDavid du Colombier 	return ulChar;
720f5736e95SDavid du Colombier } /* end of ulToUpper */
721