Original 2.4
[marc4j.git] / src / org / marc4j / converter / impl / Iso6937ToUnicode.java
1 // $Id: Iso6937ToUnicode.java,v 1.3 2008/10/17 06:47:06 haschart Exp $\r
2 /**\r
3  * Copyright (C) 2002 Bas  Peters  (mail@bpeters.com)\r
4  * Copyright (C) 2002 Yves Pratter (ypratter@club-internet.fr)\r
5  *\r
6  * This file is part of MARC4J\r
7  *\r
8  * MARC4J is free software; you can redistribute it and/or\r
9  * modify it under the terms of the GNU Lesser General Public \r
10  * License as published by the Free Software Foundation; either \r
11  * version 2.1 of the License, or (at your option) any later version.\r
12  *\r
13  * MARC4J is distributed in the hope that it will be useful,\r
14  * but WITHOUT ANY WARRANTY; without even the implied warranty of\r
15  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU\r
16  * Lesser General Public License for more details.\r
17  *\r
18  * You should have received a copy of the GNU Lesser General Public \r
19  * License along with MARC4J; if not, write to the Free Software\r
20  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA\r
21  */\r
22 package org.marc4j.converter.impl;\r
23 \r
24 import org.marc4j.converter.CharConverter;\r
25 \r
26 /**\r
27  * <p>\r
28  * A utility to convert ISO 6937 data to UCS/Unicode.\r
29  * </p>\r
30  * \r
31  * @author Bas Peters\r
32  * @author Yves Pratter\r
33  * @version $Revision: 1.3 $\r
34  */\r
35 public class Iso6937ToUnicode extends CharConverter {\r
36 \r
37   /**\r
38    * <p>\r
39    * Converts ISO 6937 data to UCS/Unicode.\r
40    * </p>\r
41    * \r
42    * @param data - the ISO 6937 data in an array of char\r
43    * @return {@link String}- the UCS/Unicode data\r
44    */\r
45   public String convert(char data[]) {\r
46     StringBuffer sb = new StringBuffer();\r
47 \r
48     for (int i = 0; i < data.length; i++) {\r
49       char c = data[i];\r
50       int len = data.length;\r
51       if (isAscii(c))\r
52         sb.append(c);\r
53       else if (isCombining(c) && hasNext(i, len)) {\r
54         char d = getCombiningChar(c * 256 + data[i + 1]);\r
55         if (d != 0) {\r
56           sb.append(d);\r
57           i++;\r
58         } else {\r
59           sb.append(getChar(c));\r
60         }\r
61       } else\r
62         sb.append(getChar(c));\r
63     }\r
64     return sb.toString();\r
65   }\r
66 \r
67   private boolean hasNext(int pos, int len) {\r
68     if (pos < (len - 1))\r
69       return true;\r
70     return false;\r
71   }\r
72 \r
73   private boolean isAscii(int i) {\r
74     if (i >= 0x00 && i <= 0x7F)\r
75       return true;\r
76     return false;\r
77   }\r
78 \r
79   private boolean isCombining(int i) {\r
80     if (i >= 0xC0 && i <= 0xDF)\r
81       return true;\r
82     return false;\r
83   }\r
84 \r
85   // Source : http://anubis.dkuug.dk/JTC1/SC2/WG3/docs/6937cd.pdf\r
86   private char getChar(int i) {\r
87     switch (i) {\r
88     case 0xA0:\r
89       return 0x00A0; // 10/00 NO-BREAK SPACE\r
90     case 0xA1:\r
91       return 0x00A1; // 10/01 INVERTED EXCLAMATION MARK\r
92     case 0xA2:\r
93       return 0x00A2; // 10/02 CENT SIGN\r
94     case 0xA3:\r
95       return 0x00A3; // 10/03 POUND SIGN\r
96     // 10/04 (This position shall not be used)\r
97     case 0xA5:\r
98       return 0x00A5; // 10/05 YEN SIGN\r
99     // 10/06 (This position shall not be used)\r
100     case 0xA7:\r
101       return 0x00A7; // 10/07 SECTION SIGN\r
102     case 0xA8:\r
103       return 0x00A4; // 10/08 CURRENCY SIGN\r
104     case 0xA9:\r
105       return 0x2018; // 10/09 LEFT SINGLE QUOTATION MARK\r
106     case 0xAA:\r
107       return 0x201C; // 10/10 LEFT DOUBLE QUOTATION MARK\r
108     case 0xAB:\r
109       return 0x00AB; // 10/11 LEFT-POINTING DOUBLE ANGLE QUOTATION MARK\r
110     case 0xAC:\r
111       return 0x2190; // 10/12 LEFTWARDS ARROW\r
112     case 0xAD:\r
113       return 0x2191; // 10/13 UPWARDS ARROW\r
114     case 0xAE:\r
115       return 0x2192; // 10/14 RIGHTWARDS ARROW\r
116     case 0xAF:\r
117       return 0x2193; // 10/15 DOWNWARDS ARROW\r
118 \r
119     case 0xB0:\r
120       return 0x00B0; // 11/00 DEGREE SIGN\r
121     case 0xB1:\r
122       return 0x00B1; // 11/01 PLUS-MINUS SIGN\r
123     case 0xB2:\r
124       return 0x00B2; // 11/02 SUPERSCRIPT TWO\r
125     case 0xB3:\r
126       return 0x00B3; // 11/03 SUPERSCRIPT THREE\r
127     case 0xB4:\r
128       return 0x00D7; // 11/04 MULTIPLICATION SIGN\r
129     case 0xB5:\r
130       return 0x00B5; // 11/05 MICRO SIGN\r
131     case 0xB6:\r
132       return 0x00B6; // 11/06 PILCROW SIGN\r
133     case 0xB7:\r
134       return 0x00B7; // 11/07 MIDDLE DOT\r
135     case 0xB8:\r
136       return 0x00F7; // 11/08 DIVISION SIGN\r
137     case 0xB9:\r
138       return 0x2019; // 11/09 RIGHT SINGLE QUOTATION MARK\r
139     case 0xBA:\r
140       return 0x201D; // 11/10 RIGHT DOUBLE QUOTATION MARK\r
141     case 0xBB:\r
142       return 0x00BB; // 11/11 RIGHT-POINTING DOUBLE ANGLE QUOTATION MARK\r
143     case 0xBC:\r
144       return 0x00BC; // 11/12 VULGAR FRACTION ONE QUARTER\r
145     case 0xBD:\r
146       return 0x00BD; // 11/13 VULGAR FRACTION ONE HALF\r
147     case 0xBE:\r
148       return 0x00BE; // 11/14 VULGAR FRACTION THREE QUARTERS\r
149     case 0xBF:\r
150       return 0x00BF; // 11/15 INVERTED QUESTION MARK\r
151 \r
152     // 4/0 to 5/15 diacritic characters\r
153 \r
154     case 0xD0:\r
155       return 0x2015; // 13/00 HORIZONTAL BAR\r
156     case 0xD1:\r
157       return 0x00B9; // 13/01 SUPERSCRIPT ONE\r
158     case 0xD2:\r
159       return 0x2117; // 13/02 REGISTERED SIGN\r
160     case 0xD3:\r
161       return 0x00A9; // 13/03 COPYRIGHT SIGN\r
162     case 0xD4:\r
163       return 0x00AE; // 13/04 TRADE MARK SIGN\r
164     case 0xD5:\r
165       return 0x266A; // 13/05 EIGHTH NOTE\r
166     case 0xD6:\r
167       return 0x00AC; // 13/06 NOT SIGN\r
168     case 0xD7:\r
169       return 0x00A6; // 13/07 BROKEN BAR\r
170     // 13/08 (This position shall not be used)\r
171     // 13/09 (This position shall not be used)\r
172     // 13/10 (This position shall not be used)\r
173     // 13/11 (This position shall not be used)\r
174     case 0xDC:\r
175       return 0x215B; // 13/12 VULGAR FRACTION ONE EIGHTH\r
176     case 0xDF:\r
177       return 0x215E; // 13/15 VULGAR FRACTION SEVEN EIGHTHS\r
178 \r
179     case 0xE0:\r
180       return 0x2126; // 14/00 OHM SIGN\r
181     case 0xE1:\r
182       return 0x00C6; // 14/01 LATIN CAPITAL LETTER AE\r
183     case 0xE2:\r
184       return 0x0110; // 14/02 LATIN CAPITAL LETTER D WITH STROKE\r
185     case 0xE3:\r
186       return 0x00AA; // 14/03 FEMININE ORDINAL INDICATOR\r
187     case 0xE4:\r
188       return 0x0126; // 14/04 LATIN CAPITAL LETTER H WITH STROKE\r
189     // 14/05 (This position shall not be used)\r
190     case 0xE6:\r
191       return 0x0132; // 14/06 LATIN CAPITAL LIGATURE IJ\r
192     case 0xE7:\r
193       return 0x013F; // 14/07 LATIN CAPITAL LETTER L WITH MIDDLE DOT\r
194     case 0xE8:\r
195       return 0x0141; // 14/08 LATIN CAPITAL LETTER L WITH STROKE\r
196     case 0xE9:\r
197       return 0x00D8; // 14/09 LATIN CAPITAL LETTER O WITH STROKE\r
198     case 0xEA:\r
199       return 0x0152; // 14/10 LATIN CAPITAL LIGATURE OE\r
200     case 0xEB:\r
201       return 0x00BA; // 14/11 MASCULINE ORDINAL INDICATOR\r
202     case 0xEC:\r
203       return 0x00DE; // 14/12 LATIN CAPITAL LETTER THORN\r
204     case 0xED:\r
205       return 0x0166; // 14/13 LATIN CAPITAL LETTER T WITH STROKE\r
206     case 0xEE:\r
207       return 0x014A; // 14/14 LATIN CAPITAL LETTER ENG\r
208     case 0xEF:\r
209       return 0x0149; // 14/15 LATIN SMALL LETTER N PRECEDED BY APOSTROPHE\r
210 \r
211     case 0xF0:\r
212       return 0x0138; // 15/00 LATIN SMALL LETTER KRA\r
213     case 0xF1:\r
214       return 0x00E6; // 15/01 LATIN SMALL LETTER AE\r
215     case 0xF2:\r
216       return 0x0111; // 15/02 LATIN SMALL LETTER D WITH STROKE\r
217     case 0xF3:\r
218       return 0x00F0; // 15/03 LATIN SMALL LETTER ETH\r
219     case 0xF4:\r
220       return 0x0127; // 15/04 LATIN SMALL LETTER H WITH STROKE\r
221     case 0xF5:\r
222       return 0x0131; // 15/05 LATIN SMALL LETTER DOTLESS I\r
223     case 0xF6:\r
224       return 0x0133; // 15/06 LATIN SMALL LIGATURE IJ\r
225     case 0xF7:\r
226       return 0x0140; // 15/07 LATIN SMALL LETTER L WITH MIDDLE DOT\r
227     case 0xF8:\r
228       return 0x0142; // 15/08 LATIN SMALL LETTER L WITH STROKE\r
229     case 0xF9:\r
230       return 0x00F8; // 15/09 LATIN SMALL LETTER O WITH STROKE\r
231     case 0xFA:\r
232       return 0x0153; // 15/10 LATIN SMALL LIGATURE OE\r
233     case 0xFB:\r
234       return 0x00DF; // 15/11 LATIN SMALL LETTER SHARP S\r
235     case 0xFC:\r
236       return 0x00FE; // 15/12 LATIN SMALL LETTER THORN\r
237     case 0xFD:\r
238       return 0x0167; // 15/13 LATIN SMALL LETTER T WITH STROKE\r
239     case 0xFE:\r
240       return 0x014B; // 15/14 LATIN SMALL LETTER ENG\r
241     case 0xFF:\r
242       return 0x00AD; // 15/15 SOFT HYPHEN$\r
243 \r
244     default:\r
245       return (char) i;\r
246     }\r
247   }\r
248 \r
249   private char getCombiningChar(int i) {\r
250     switch (i) {\r
251     // 12/00 (This position shall not be used)\r
252 \r
253     // 12/01 non-spacing grave accent\r
254     case 0xC141:\r
255       return 0x00C0; // LATIN CAPITAL LETTER A WITH GRAVE\r
256     case 0xC145:\r
257       return 0x00C8; // LATIN CAPITAL LETTER E WITH GRAVE\r
258     case 0xC149:\r
259       return 0x00CC; // LATIN CAPITAL LETTER I WITH GRAVE\r
260     case 0xC14F:\r
261       return 0x00D2; // LATIN CAPITAL LETTER O WITH GRAVE\r
262     case 0xC155:\r
263       return 0x00D9; // LATIN CAPITAL LETTER U WITH GRAVE\r
264     case 0xC161:\r
265       return 0x00E0; // LATIN SMALL LETTER A WITH GRAVE\r
266     case 0xC165:\r
267       return 0x00E8; // LATIN SMALL LETTER E WITH GRAVE\r
268     case 0xC169:\r
269       return 0x00EC; // LATIN SMALL LETTER I WITH GRAVE\r
270     case 0xC16F:\r
271       return 0x00F2; // LATIN SMALL LETTER O WITH GRAVE\r
272     case 0xC175:\r
273       return 0x00F9; // LATIN SMALL LETTER U WITH GRAVE\r
274 \r
275     // 12/02 non-spacing acute accent\r
276     case 0xC220:\r
277       return 0x00B4; // ACUTE ACCENT\r
278     case 0xC241:\r
279       return 0x00C1; // LATIN CAPITAL LETTER A WITH ACUTE\r
280     case 0xC243:\r
281       return 0x0106; // LATIN CAPITAL LETTER C WITH ACUTE\r
282     case 0xC245:\r
283       return 0x00C9; // LATIN CAPITAL LETTER E WITH ACUTE\r
284     case 0xC249:\r
285       return 0x00CD; // LATIN CAPITAL LETTER I WITH ACUTE\r
286     case 0xC24C:\r
287       return 0x0139; // LATIN CAPITAL LETTER L WITH ACUTE\r
288     case 0xC24E:\r
289       return 0x0143; // LATIN CAPITAL LETTER N WITH ACUTE\r
290     case 0xC24F:\r
291       return 0x00D3; // LATIN CAPITAL LETTER O WITH ACUTE\r
292     case 0xC252:\r
293       return 0x0154; // LATIN CAPITAL LETTER R WITH ACUTE\r
294     case 0xC253:\r
295       return 0x015A; // LATIN CAPITAL LETTER S WITH ACUTE\r
296     case 0xC255:\r
297       return 0x00DA; // LATIN CAPITAL LETTER U WITH ACUTE\r
298     case 0xC259:\r
299       return 0x00DD; // LATIN CAPITAL LETTER Y WITH ACUTE\r
300     case 0xC25A:\r
301       return 0x0179; // LATIN CAPITAL LETTER Z WITH ACUTE\r
302     case 0xC261:\r
303       return 0x00E1; // LATIN SMALL LETTER A WITH ACUTE\r
304     case 0xC263:\r
305       return 0x0107; // LATIN SMALL LETTER C WITH ACUTE\r
306     case 0xC265:\r
307       return 0x00E9; // LATIN SMALL LETTER E WITH ACUTE\r
308     case 0xC267:\r
309       return 0x01F5; // LATIN SMALL LETTER G WITH CEDILLA(4)\r
310     case 0xC269:\r
311       return 0x00ED; // LATIN SMALL LETTER I WITH ACUTE\r
312     case 0xC26C:\r
313       return 0x013A; // LATIN SMALL LETTER L WITH ACUTE\r
314     case 0xC26E:\r
315       return 0x0144; // LATIN SMALL LETTER N WITH ACUTE\r
316     case 0xC26F:\r
317       return 0x00F3; // LATIN SMALL LETTER O WITH ACUTE\r
318     case 0xC272:\r
319       return 0x0155; // LATIN SMALL LETTER R WITH ACUTE\r
320     case 0xC273:\r
321       return 0x015B; // LATIN SMALL LETTER S WITH ACUTE\r
322     case 0xC275:\r
323       return 0x00FA; // LATIN SMALL LETTER U WITH ACUTE\r
324     case 0xC279:\r
325       return 0x00FD; // LATIN SMALL LETTER Y WITH ACUTE\r
326     case 0xC27A:\r
327       return 0x017A; // LATIN SMALL LETTER Z WITH ACUTE\r
328 \r
329     // 12/03 non-spacing circumflex accent\r
330     case 0xC341:\r
331       return 0x00C2; // LATIN CAPITAL LETTER A WITH CIRCUMFLEX\r
332     case 0xC343:\r
333       return 0x0108; // LATIN CAPITAL LETTER C WITH CIRCUMFLEX\r
334     case 0xC345:\r
335       return 0x00CA; // LATIN CAPITAL LETTER E WITH CIRCUMFLEX\r
336     case 0xC347:\r
337       return 0x011C; // LATIN CAPITAL LETTER G WITH CIRCUMFLEX\r
338     case 0xC348:\r
339       return 0x0124; // LATIN CAPITAL LETTER H WITH CIRCUMFLEX\r
340     case 0xC349:\r
341       return 0x00CE; // LATIN CAPITAL LETTER I WITH CIRCUMFLEX\r
342     case 0xC34A:\r
343       return 0x0134; // LATIN CAPITAL LETTER J WITH CIRCUMFLEX\r
344     case 0xC34F:\r
345       return 0x00D4; // LATIN CAPITAL LETTER O WITH CIRCUMFLEX\r
346     case 0xC353:\r
347       return 0x015C; // LATIN CAPITAL LETTER S WITH CIRCUMFLEX\r
348     case 0xC355:\r
349       return 0x00DB; // LATIN CAPITAL LETTER U WITH CIRCUMFLEX\r
350     case 0xC357:\r
351       return 0x0174; // LATIN CAPITAL LETTER W WITH CIRCUMFLEX\r
352     case 0xC359:\r
353       return 0x0176; // LATIN CAPITAL LETTER Y WITH CIRCUMFLEX\r
354     case 0xC361:\r
355       return 0x00E2; // LATIN SMALL LETTER A WITH CIRCUMFLEX\r
356     case 0xC363:\r
357       return 0x0109; // LATIN SMALL LETTER C WITH CIRCUMFLEX\r
358     case 0xC365:\r
359       return 0x00EA; // LATIN SMALL LETTER E WITH CIRCUMFLEX\r
360     case 0xC367:\r
361       return 0x011D; // LATIN SMALL LETTER G WITH CIRCUMFLEX\r
362     case 0xC368:\r
363       return 0x0125; // LATIN SMALL LETTER H WITH CIRCUMFLEX\r
364     case 0xC369:\r
365       return 0x00EE; // LATIN SMALL LETTER I WITH CIRCUMFLEX\r
366     case 0xC36A:\r
367       return 0x0135; // LATIN SMALL LETTER J WITH CIRCUMFLEX\r
368     case 0xC36F:\r
369       return 0x00F4; // LATIN SMALL LETTER O WITH CIRCUMFLEX\r
370     case 0xC373:\r
371       return 0x015D; // LATIN SMALL LETTER S WITH CIRCUMFLEX\r
372     case 0xC375:\r
373       return 0x00FB; // LATIN SMALL LETTER U WITH CIRCUMFLEX\r
374     case 0xC377:\r
375       return 0x0175; // LATIN SMALL LETTER W WITH CIRCUMFLEX\r
376     case 0xC379:\r
377       return 0x0177; // LATIN SMALL LETTER Y WITH CIRCUMFLEX\r
378 \r
379     // 12/04 non-spacing tilde\r
380     case 0xC441:\r
381       return 0x00C3; // LATIN CAPITAL LETTER A WITH TILDE\r
382     case 0xC449:\r
383       return 0x0128; // LATIN CAPITAL LETTER I WITH TILDE\r
384     case 0xC44E:\r
385       return 0x00D1; // LATIN CAPITAL LETTER N WITH TILDE\r
386     case 0xC44F:\r
387       return 0x00D5; // LATIN CAPITAL LETTER O WITH TILDE\r
388     case 0xC455:\r
389       return 0x0168; // LATIN CAPITAL LETTER U WITH TILDE\r
390     case 0xC461:\r
391       return 0x00E3; // LATIN SMALL LETTER A WITH TILDE\r
392     case 0xC469:\r
393       return 0x0129; // LATIN SMALL LETTER I WITH TILDE\r
394     case 0xC46E:\r
395       return 0x00F1; // LATIN SMALL LETTER N WITH TILDE\r
396     case 0xC46F:\r
397       return 0x00F5; // LATIN SMALL LETTER O WITH TILDE\r
398     case 0xC475:\r
399       return 0x0169; // LATIN SMALL LETTER U WITH TILDE\r
400 \r
401     // 12/05 non-spacing macron\r
402     case 0xC541:\r
403       return 0x0100; // LATIN CAPITAL LETTER A WITH MACRON\r
404     case 0xC545:\r
405       return 0x0112; // LATIN CAPITAL LETTER E WITH MACRON\r
406     case 0xC549:\r
407       return 0x012A; // LATIN CAPITAL LETTER I WITH MACRON\r
408     case 0xC54F:\r
409       return 0x014C; // LATIN CAPITAL LETTER O WITH MACRON\r
410     case 0xC555:\r
411       return 0x016A; // LATIN CAPITAL LETTER U WITH MACRON\r
412     case 0xC561:\r
413       return 0x0101; // LATIN SMALL LETTER A WITH MACRON\r
414     case 0xC565:\r
415       return 0x0113; // LATIN SMALL LETTER E WITH MACRON\r
416     case 0xC569:\r
417       return 0x012B; // LATIN SMALL LETTER I WITH MACRON\r
418     case 0xC56F:\r
419       return 0x014D; // LATIN SMALL LETTER O WITH MACRON\r
420     case 0xC575:\r
421       return 0x016B; // LATIN SMALL LETTER U WITH MACRON\r
422 \r
423     // 12/06 non-spacing breve\r
424     case 0xC620:\r
425       return 0x02D8; // BREVE\r
426     case 0xC641:\r
427       return 0x0102; // LATIN CAPITAL LETTER A WITH BREVE\r
428     case 0xC647:\r
429       return 0x011E; // LATIN CAPITAL LETTER G WITH BREVE\r
430     case 0xC655:\r
431       return 0x016C; // LATIN CAPITAL LETTER U WITH BREVE\r
432     case 0xC661:\r
433       return 0x0103; // LATIN SMALL LETTER A WITH BREVE\r
434     case 0xC667:\r
435       return 0x011F; // LATIN SMALL LETTER G WITH BREVE\r
436     case 0xC675:\r
437       return 0x016D; // LATIN SMALL LETTER U WITH BREVE\r
438 \r
439     // 12/07 non-spacing dot above\r
440     case 0xC743:\r
441       return 0x010A; // LATIN CAPITAL LETTER C WITH DOT ABOVE\r
442     case 0xC745:\r
443       return 0x0116; // LATIN CAPITAL LETTER E WITH DOT ABOVE\r
444     case 0xC747:\r
445       return 0x0120; // LATIN CAPITAL LETTER G WITH DOT ABOVE\r
446     case 0xC749:\r
447       return 0x0130; // LATIN CAPITAL LETTER I WITH DOT ABOVE\r
448     case 0xC75A:\r
449       return 0x017B; // LATIN CAPITAL LETTER Z WITH DOT ABOVE\r
450     case 0xC763:\r
451       return 0x010B; // LATIN SMALL LETTER C WITH DOT ABOVE\r
452     case 0xC765:\r
453       return 0x0117; // LATIN SMALL LETTER E WITH DOT ABOVE\r
454     case 0xC767:\r
455       return 0x0121; // LATIN SMALL LETTER G WITH DOT ABOVE\r
456     case 0xC77A:\r
457       return 0x017C; // LATIN SMALL LETTER Z WITH DOT ABOVE\r
458 \r
459     // 12/08 non-spacing diaeresis\r
460     case 0xC820:\r
461       return 0x00A8; // DIAERESIS\r
462     case 0xC841:\r
463       return 0x00C4; // LATIN CAPITAL LETTER A WITH DIAERESIS\r
464     case 0xC845:\r
465       return 0x00CB; // LATIN CAPITAL LETTER E WITH DIAERESIS\r
466     case 0xC849:\r
467       return 0x00CF; // LATIN CAPITAL LETTER I WITH DIAERESIS\r
468     case 0xC84F:\r
469       return 0x00D6; // LATIN CAPITAL LETTER O WITH DIAERESIS\r
470     case 0xC855:\r
471       return 0x00DC; // LATIN CAPITAL LETTER U WITH DIAERESIS\r
472     case 0xC859:\r
473       return 0x0178; // LATIN CAPITAL LETTER Y WITH DIAERESIS\r
474     case 0xC861:\r
475       return 0x00E4; // LATIN SMALL LETTER A WITH DIAERESIS\r
476     case 0xC865:\r
477       return 0x00EB; // LATIN SMALL LETTER E WITH DIAERESIS\r
478     case 0xC869:\r
479       return 0x00EF; // LATIN SMALL LETTER I WITH DIAERESIS\r
480     case 0xC86F:\r
481       return 0x00F6; // LATIN SMALL LETTER O WITH DIAERESIS\r
482     case 0xC875:\r
483       return 0x00FC; // LATIN SMALL LETTER U WITH DIAERESIS\r
484     case 0xC879:\r
485       return 0x00FF; // LATIN SMALL LETTER Y WITH DIAERESIS\r
486 \r
487     // 12/09 (This position shall not be used)\r
488 \r
489     // 12/10 non-spacing ring above\r
490     case 0xCA20:\r
491       return 0x02DA; // RING ABOVE\r
492     case 0xCA41:\r
493       return 0x00C5; // LATIN CAPITAL LETTER A WITH RING ABOVE\r
494     case 0xCAAD:\r
495       return 0x016E; // LATIN CAPITAL LETTER U WITH RING ABOVE\r
496     case 0xCA61:\r
497       return 0x00E5; // LATIN SMALL LETTER A WITH RING ABOVE\r
498     case 0xCA75:\r
499       return 0x016F; // LATIN SMALL LETTER U WITH RING ABOVE\r
500 \r
501     // 12/11 non-spacing cedilla\r
502     case 0xCB20:\r
503       return 0x00B8; // CEDILLA\r
504     case 0xCB43:\r
505       return 0x00C7; // LATIN CAPITAL LETTER C WITH CEDILLA\r
506     case 0xCB47:\r
507       return 0x0122; // LATIN CAPITAL LETTER G WITH CEDILLA\r
508     case 0xCB4B:\r
509       return 0x0136; // LATIN CAPITAL LETTER K WITH CEDILLA\r
510     case 0xCB4C:\r
511       return 0x013B; // LATIN CAPITAL LETTER L WITH CEDILLA\r
512     case 0xCB4E:\r
513       return 0x0145; // LATIN CAPITAL LETTER N WITH CEDILLA\r
514     case 0xCB52:\r
515       return 0x0156; // LATIN CAPITAL LETTER R WITH CEDILLA\r
516     case 0xCB53:\r
517       return 0x015E; // LATIN CAPITAL LETTER S WITH CEDILLA\r
518     case 0xCB54:\r
519       return 0x0162; // LATIN CAPITAL LETTER T WITH CEDILLA\r
520     case 0xCB63:\r
521       return 0x00E7; // LATIN SMALL LETTER C WITH CEDILLA\r
522     //          case 0xCB67: return 0x0123; // small g with cedilla\r
523     case 0xCB6B:\r
524       return 0x0137; // LATIN SMALL LETTER K WITH CEDILLA\r
525     case 0xCB6C:\r
526       return 0x013C; // LATIN SMALL LETTER L WITH CEDILLA\r
527     case 0xCB6E:\r
528       return 0x0146; // LATIN SMALL LETTER N WITH CEDILLA\r
529     case 0xCB72:\r
530       return 0x0157; // LATIN SMALL LETTER R WITH CEDILLA\r
531     case 0xCB73:\r
532       return 0x015F; // LATIN SMALL LETTER S WITH CEDILLA\r
533     case 0xCB74:\r
534       return 0x0163; // LATIN SMALL LETTER T WITH CEDILLA\r
535 \r
536     // 12/12 (This position shall not be used)\r
537 \r
538     // 12/13 non-spacing double acute accent\r
539     case 0xCD4F:\r
540       return 0x0150; // LATIN CAPITAL LETTER O WITH DOUBLE ACUTE\r
541     case 0xCD55:\r
542       return 0x0170; // LATIN CAPITAL LETTER U WITH DOUBLE ACUTE\r
543     case 0xCD6F:\r
544       return 0x0151; // LATIN SMALL LETTER O WITH DOUBLE ACUTE\r
545     case 0xCD75:\r
546       return 0x0171; // LATIN SMALL LETTER U WITH DOUBLE ACUTE\r
547 \r
548     // 12/14 non-spacing ogonek\r
549     case 0xCE20:\r
550       return 0x02DB; // ogonek\r
551     case 0xCE41:\r
552       return 0x0104; // LATIN CAPITAL LETTER A WITH OGONEK\r
553     case 0xCE45:\r
554       return 0x0118; // LATIN CAPITAL LETTER E WITH OGONEK\r
555     case 0xCE49:\r
556       return 0x012E; // LATIN CAPITAL LETTER I WITH OGONEK\r
557     case 0xCE55:\r
558       return 0x0172; // LATIN CAPITAL LETTER U WITH OGONEK\r
559     case 0xCE61:\r
560       return 0x0105; // LATIN SMALL LETTER A WITH OGONEK\r
561     case 0xCE65:\r
562       return 0x0119; // LATIN SMALL LETTER E WITH OGONEK\r
563     case 0xCE69:\r
564       return 0x012F; // LATIN SMALL LETTER I WITH OGONEK\r
565     case 0xCE75:\r
566       return 0x0173; // LATIN SMALL LETTER U WITH OGONEK\r
567 \r
568     // 12/15 non-spacing caron\r
569     case 0xCF20:\r
570       return 0x02C7; // CARON\r
571     case 0xCF43:\r
572       return 0x010C; // LATIN CAPITAL LETTER C WITH CARON\r
573     case 0xCF44:\r
574       return 0x010E; // LATIN CAPITAL LETTER D WITH CARON\r
575     case 0xCF45:\r
576       return 0x011A; // LATIN CAPITAL LETTER E WITH CARON\r
577     case 0xCF4C:\r
578       return 0x013D; // LATIN CAPITAL LETTER L WITH CARON\r
579     case 0xCF4E:\r
580       return 0x0147; // LATIN CAPITAL LETTER N WITH CARON\r
581     case 0xCF52:\r
582       return 0x0158; // LATIN CAPITAL LETTER R WITH CARON\r
583     case 0xCF53:\r
584       return 0x0160; // LATIN CAPITAL LETTER S WITH CARON\r
585     case 0xCF54:\r
586       return 0x0164; // LATIN CAPITAL LETTER T WITH CARON\r
587     case 0xCF5A:\r
588       return 0x017D; // LATIN CAPITAL LETTER Z WITH CARON\r
589     case 0xCF63:\r
590       return 0x010D; // LATIN SMALL LETTER C WITH CARON\r
591     case 0xCF64:\r
592       return 0x010F; // LATIN SMALL LETTER D WITH CARON\r
593     case 0xCF65:\r
594       return 0x011B; // LATIN SMALL LETTER E WITH CARON\r
595     case 0xCF6C:\r
596       return 0x013E; // LATIN SMALL LETTER L WITH CARON\r
597     case 0xCF6E:\r
598       return 0x0148; // LATIN SMALL LETTER N WITH CARON\r
599     case 0xCF72:\r
600       return 0x0159; // LATIN SMALL LETTER R WITH CARON\r
601     case 0xCF73:\r
602       return 0x0161; // LATIN SMALL LETTER S WITH CARON\r
603     case 0xCF74:\r
604       return 0x0165; // LATIN SMALL LETTER T WITH CARON\r
605     case 0xCF7A:\r
606       return 0x017E; // LATIN SMALL LETTER Z WITH CARON\r
607 \r
608     default:\r
609       return 0;\r
610     }\r
611   }\r
612 }