]> gitweb.fperrin.net Git - Dictionary.git/blob - jars/icu4j-4_4_2-src/demos/src/com/ibm/icu/dev/demo/translit/Demo.java
go
[Dictionary.git] / jars / icu4j-4_4_2-src / demos / src / com / ibm / icu / dev / demo / translit / Demo.java
1 /*\r
2  *******************************************************************************\r
3  * Copyright (C) 1996-2010, International Business Machines Corporation and    *\r
4  * others. All Rights Reserved.                                                *\r
5  *******************************************************************************\r
6  */\r
7 package com.ibm.icu.dev.demo.translit;\r
8 \r
9 import java.awt.Button;\r
10 import java.awt.CheckboxMenuItem;\r
11 import java.awt.FileDialog;\r
12 import java.awt.Font;\r
13 import java.awt.Frame;\r
14 import java.awt.GraphicsEnvironment;\r
15 import java.awt.Label;\r
16 import java.awt.Menu;\r
17 import java.awt.MenuBar;\r
18 import java.awt.MenuItem;\r
19 import java.awt.MenuShortcut;\r
20 import java.awt.TextField;\r
21 import java.awt.event.ActionEvent;\r
22 import java.awt.event.ActionListener;\r
23 import java.awt.event.ItemEvent;\r
24 import java.awt.event.ItemListener;\r
25 import java.awt.event.KeyEvent;\r
26 import java.awt.event.WindowAdapter;\r
27 import java.awt.event.WindowEvent;\r
28 import java.io.BufferedReader;\r
29 import java.io.BufferedWriter;\r
30 import java.io.File;\r
31 import java.io.FileInputStream;\r
32 import java.io.FileOutputStream;\r
33 import java.io.InputStreamReader;\r
34 import java.io.OutputStreamWriter;\r
35 import java.io.PrintWriter;\r
36 import java.text.CharacterIterator;\r
37 import java.util.Comparator;\r
38 import java.util.Enumeration;\r
39 import java.util.HashMap;\r
40 import java.util.Iterator;\r
41 import java.util.Map;\r
42 import java.util.Set;\r
43 import java.util.TreeSet;\r
44 \r
45 import com.ibm.icu.impl.Differ;\r
46 import com.ibm.icu.lang.UCharacter;\r
47 import com.ibm.icu.text.BreakIterator;\r
48 import com.ibm.icu.text.CanonicalIterator;\r
49 import com.ibm.icu.text.Normalizer;\r
50 import com.ibm.icu.text.ReplaceableString;\r
51 import com.ibm.icu.text.Transliterator;\r
52 import com.ibm.icu.text.UTF16;\r
53 import com.ibm.icu.text.UnicodeSet;\r
54 import com.ibm.icu.text.UnicodeSetIterator;\r
55 \r
56 /**\r
57  * A frame that allows the user to experiment with keyboard\r
58  * transliteration.  This class has a main() method so it can be run\r
59  * as an application.  The frame contains an editable text component\r
60  * and uses keyboard transliteration to process keyboard events.\r
61  *\r
62  * <p>Copyright (c) IBM Corporation 1999.  All rights reserved.\r
63  *\r
64  * @author Alan Liu\r
65  */\r
66 public class Demo extends Frame {\r
67 \r
68     /**\r
69      * For serialization\r
70      */\r
71     private static final long serialVersionUID = 1L;\r
72     static final boolean DEBUG = false;\r
73     static final String START_TEXT = "(cut,\u03BA\u03C5\u03C4,\u05D0,\u30AF\u30C8,\u4E80,\u091A\u0941\u0924\u094D)";\r
74 \r
75     Transliterator translit = null;\r
76     String fontName = "Arial Unicode MS";\r
77     int fontSize = 18;\r
78     \r
79     \r
80 \r
81     /*\r
82     boolean compound = false;\r
83     Transliterator[] compoundTranslit = new Transliterator[MAX_COMPOUND];\r
84     static final int MAX_COMPOUND = 128;\r
85     int compoundCount = 0;\r
86     */\r
87 \r
88     TransliteratingTextComponent text = null;\r
89 \r
90     Menu translitMenu;\r
91     CheckboxMenuItem translitItem;\r
92     CheckboxMenuItem noTranslitItem;\r
93 \r
94     static final String NO_TRANSLITERATOR = "None";\r
95 \r
96     //private static final String COPYRIGHT =\r
97     //    "\u00A9 IBM Corporation 1999. All rights reserved.";\r
98 \r
99     public static void main(String[] args) {\r
100         Frame f = new Demo(600, 200);\r
101         f.addWindowListener(new WindowAdapter() {\r
102             public void windowClosing(WindowEvent e) {\r
103                 com.ibm.icu.dev.demo.impl.DemoApplet.demoFrameClosed();\r
104 //                System.exit(0);\r
105             }\r
106         });\r
107         f.setVisible(true);\r
108         com.ibm.icu.dev.demo.impl.DemoApplet.demoFrameOpened();\r
109     }\r
110 \r
111     public Demo(int width, int height) {\r
112         super("Transliteration Demo");\r
113 \r
114         initMenus();\r
115 \r
116         addWindowListener(new WindowAdapter() {\r
117             public void windowClosing(WindowEvent e) {\r
118                 handleClose();\r
119             }\r
120         });\r
121         \r
122         text = new TransliteratingTextComponent();\r
123         Font font = new Font(fontName, Font.PLAIN, fontSize);\r
124         text.setFont(font);\r
125         text.setSize(width, height);\r
126         text.setVisible(true);\r
127         text.setText(START_TEXT);\r
128         add(text);\r
129 \r
130         setSize(width, height);\r
131         setTransliterator("Latin-Greek", null);\r
132     }\r
133 \r
134     private void initMenus() {\r
135         MenuBar mbar;\r
136         Menu menu;\r
137         MenuItem mitem;\r
138         //CheckboxMenuItem citem;\r
139         \r
140         setMenuBar(mbar = new MenuBar());\r
141         mbar.add(menu = new Menu("File"));\r
142         menu.add(mitem = new MenuItem("Quit"));\r
143         mitem.addActionListener(new ActionListener() {\r
144             public void actionPerformed(ActionEvent e) {\r
145                 handleClose();\r
146             }\r
147         });\r
148 /*\r
149         final ItemListener setTransliteratorListener = new ItemListener() {\r
150             public void itemStateChanged(ItemEvent e) {\r
151                 CheckboxMenuItem item = (CheckboxMenuItem) e.getSource();\r
152                 if (e.getStateChange() == ItemEvent.DESELECTED) {\r
153                     // Don't let the current transliterator be deselected.\r
154                     // Just reselect it.\r
155                     item.setState(true);\r
156                 } else if (compound) {\r
157                     // Adding an item to a compound transliterator\r
158                     handleAddToCompound(item.getLabel());\r
159                 } else if (item != translitItem) {\r
160                     // Deselect previous choice.  Don't need to call\r
161                     // setState(true) on new choice.\r
162                     translitItem.setState(false);\r
163                     translitItem = item;\r
164                     handleSetTransliterator(item.getLabel());\r
165                 }\r
166             }\r
167         };\r
168 */\r
169         /*\r
170         translitMenu.add(translitItem = noTranslitItem =\r
171                          new CheckboxMenuItem(NO_TRANSLITERATOR, true));\r
172         noTranslitItem.addItemListener(new ItemListener() {\r
173             public void itemStateChanged(ItemEvent e) {\r
174                 // Can't uncheck None -- any action here sets None to true\r
175                 setNoTransliterator();\r
176             }\r
177         });\r
178 \r
179         translitMenu.addSeparator();\r
180         */\r
181 \r
182 /*\r
183         translitMenu.add(citem = new CheckboxMenuItem("Compound"));\r
184         citem.addItemListener(new ItemListener() {\r
185             public void itemStateChanged(ItemEvent e) {\r
186                 CheckboxMenuItem item = (CheckboxMenuItem) e.getSource();\r
187                 if (e.getStateChange() == ItemEvent.DESELECTED) {\r
188                     // If compound gets deselected, then select NONE\r
189                     setNoTransliterator();\r
190                 } else if (!compound) {\r
191                     // Switching from non-compound to compound\r
192                     translitItem.setState(false);\r
193                     translitItem = item;\r
194                     translit = null;\r
195                     compound = true;\r
196                     compoundCount = 0;\r
197                     for (int i=0; i<MAX_COMPOUND; ++i) {\r
198                         compoundTranslit[i] = null;\r
199                     }\r
200                 }\r
201             }\r
202         });\r
203       \r
204         translitMenu.addSeparator();\r
205        */\r
206 \r
207         /*\r
208         for (Enumeration e=getSystemTransliteratorNames().elements();\r
209              e.hasMoreElements(); ) {\r
210             String s = (String) e.nextElement();\r
211             translitMenu.add(citem = new CheckboxMenuItem(s));\r
212             citem.addItemListener(setTransliteratorListener);\r
213         }\r
214         */\r
215         \r
216         Menu fontMenu = new Menu("Font");\r
217         String[] fonts = GraphicsEnvironment.getLocalGraphicsEnvironment().getAvailableFontFamilyNames();\r
218         for (int i = 0; i < fonts.length; ++i) {\r
219             MenuItem mItem = new MenuItem(fonts[i]);\r
220             mItem.addActionListener(new FontActionListener(fonts[i]));\r
221             fontMenu.add(mItem);\r
222         }\r
223         mbar.add(fontMenu);\r
224         \r
225         Menu sizeMenu = new Menu("Size");\r
226         int[] sizes = {9, 10, 12, 14, 18, 24, 36, 48, 72};\r
227         for (int i = 0; i < sizes.length; ++i) {\r
228             MenuItem mItem = new MenuItem("" + sizes[i]);\r
229             mItem.addActionListener(new SizeActionListener(sizes[i]));\r
230             sizeMenu.add(mItem);\r
231         }\r
232         mbar.add(sizeMenu);\r
233         \r
234         translit = null;\r
235         \r
236         mbar.add(translitMenu = new Menu("Transliterator"));\r
237         \r
238         translitMenu.add(convertSelectionItem = new MenuItem("Transliterate", \r
239             new MenuShortcut(KeyEvent.VK_K)));\r
240         convertSelectionItem.addActionListener(new ActionListener() {\r
241             public void actionPerformed(ActionEvent e) {\r
242                 handleBatchTransliterate(translit);\r
243             }\r
244         });\r
245         \r
246         translitMenu.add(swapSelectionItem = new MenuItem("Reverse", \r
247             new MenuShortcut(KeyEvent.VK_S)));\r
248         swapSelectionItem.addActionListener(new ActionListener() {\r
249             public void actionPerformed(ActionEvent e) {\r
250                 Transliterator inv;\r
251                 try {\r
252                     inv = translit.getInverse();\r
253                 } catch (Exception x) {\r
254                     inv = Transliterator.getInstance("null");\r
255                 }\r
256                 setTransliterator(inv.getID(), null);\r
257             }\r
258         });\r
259         \r
260         translitMenu.add(convertTypingItem = new MenuItem("No Typing Conversion",\r
261             new MenuShortcut(KeyEvent.VK_T)));\r
262         convertTypingItem.addActionListener(new ActionListener() {\r
263             public void actionPerformed(ActionEvent e) {\r
264                 if (!transliterateTyping) {\r
265                     text.setTransliterator(translit);\r
266                     convertTypingItem.setLabel("No Typing Conversion");\r
267                 } else {\r
268                     text.flush();\r
269                     text.setTransliterator(null);\r
270                     convertTypingItem.setLabel("Convert Typing");\r
271                 }\r
272                 transliterateTyping = !transliterateTyping;\r
273             }\r
274         });\r
275         \r
276         translitMenu.add(historyMenu = new Menu("Recent"));\r
277         \r
278         helpDialog = new InfoDialog(this, "Simple Demo", "Instructions",\r
279            "CTL A, X, C, V have customary meanings.\n"\r
280          + "Arrow keys, delete and backspace work.\n"\r
281          + "To get a character from its control point, type the hex, then hit CTL Q"\r
282         );\r
283         helpDialog.getArea().setEditable(false);\r
284         \r
285        \r
286         Menu helpMenu;\r
287         mbar.add(helpMenu = new Menu("Extras"));\r
288         helpMenu.add(mitem = new MenuItem("Help"));\r
289         mitem.addActionListener(new ActionListener() {\r
290             public void actionPerformed(ActionEvent e) {\r
291                 helpDialog.show();\r
292             }\r
293         });   \r
294         \r
295         hexDialog = new InfoDialog(this, "Hex Entry", "Use U+..., \\u..., \\x{...}, or &#x...;",\r
296            "\\u00E1"\r
297         );\r
298         Button button = new Button("Insert");\r
299         button.addActionListener(new ActionListener() {\r
300             public void actionPerformed(ActionEvent e) {\r
301                 String hexValue = hexDialog.getArea().getText();\r
302                 text.insertText(fromHex.transliterate(hexValue));\r
303             }\r
304         });\r
305         hexDialog.getBottom().add(button);\r
306         \r
307         helpMenu.add(mitem = new MenuItem("Hex...", \r
308             new MenuShortcut(KeyEvent.VK_H)));\r
309         mitem.addActionListener(new ActionListener() {\r
310             public void actionPerformed(ActionEvent e) {\r
311                 hexDialog.show();\r
312             }\r
313         });\r
314         \r
315         // Compound Transliterator\r
316         \r
317         compoundDialog = new InfoDialog(this, "Compound Transliterator", "",\r
318            "[^\\u0000-\\u00FF] hex"\r
319         );\r
320         button = new Button("Set");\r
321         button.addActionListener(new ActionListener() {\r
322             public void actionPerformed(ActionEvent e) {\r
323                 String compound = "";\r
324                 try {\r
325                     compound = compoundDialog.getArea().getText();\r
326                     setTransliterator(compound, null);\r
327                 } catch (RuntimeException ex) {\r
328                     compoundDialog.getArea().setText(compound + "\n" + ex.getMessage());\r
329                 }\r
330             }\r
331         });\r
332         compoundDialog.getBottom().add(button);\r
333         \r
334         translitMenu.add(mitem = new MenuItem("Multiple...", \r
335             new MenuShortcut(KeyEvent.VK_M)));\r
336         mitem.addActionListener(new ActionListener() {\r
337             public void actionPerformed(ActionEvent e) {\r
338                 compoundDialog.show();\r
339             }\r
340         });\r
341         \r
342         // RuleBased Transliterator\r
343         \r
344         rulesDialog = new InfoDialog(this, "Rule-Based Transliterator", "",\r
345            "([A-Z]) > &Hex($1) &Name($1);\r\n" \r
346             + "&Hex-Any($1) < ('\\' [uU] [a-fA-F0-9]*);\r\n" \r
347             + "&Name-Any($1) < ('{' [^\\}]* '}');"\r
348         );\r
349         button = new Button("Set");\r
350         button.addActionListener(new ActionListener() {\r
351             public void actionPerformed(ActionEvent e) {\r
352                 String compound = "";\r
353                 try {\r
354                     compound = rulesDialog.getArea().getText();\r
355                     String id = ruleId.getText();\r
356                     setTransliterator(compound, id);\r
357                 } catch (RuntimeException ex) {\r
358                     rulesDialog.getArea().setText(compound + "\n#" + ex.getMessage());\r
359                 }\r
360             }\r
361         });\r
362         rulesDialog.getBottom().add(button);\r
363         ruleId = new TextField("test1", 20);\r
364         Label temp = new Label(" Name:");\r
365         rulesDialog.getBottom().add(temp);\r
366         rulesDialog.getBottom().add(ruleId);\r
367         \r
368         \r
369         translitMenu.add(mitem = new MenuItem("From Rules...", \r
370             new MenuShortcut(KeyEvent.VK_R)));\r
371         mitem.addActionListener(new ActionListener() {\r
372             public void actionPerformed(ActionEvent e) {\r
373                 rulesDialog.show();\r
374             }\r
375         });\r
376         \r
377         \r
378         translitMenu.add(mitem = new MenuItem("From File...", \r
379             new MenuShortcut(KeyEvent.VK_F)));\r
380         mitem.addActionListener(new FileListener(this, RULE_FILE));\r
381         \r
382         translitMenu.add(mitem = new MenuItem("Test File..."));\r
383         mitem.addActionListener(new FileListener(this, TEST_FILE));\r
384         \r
385         // Flesh out the menu with the installed transliterators\r
386         \r
387         translitMenu.addSeparator();\r
388         \r
389         Iterator sources = add(new TreeSet(), Transliterator.getAvailableSources()).iterator();\r
390         while(sources.hasNext()) {\r
391             String source = (String) sources.next();\r
392             Iterator targets = add(new TreeSet(), Transliterator.getAvailableTargets(source)).iterator();\r
393             Menu targetMenu = new Menu(source);\r
394             while(targets.hasNext()) {\r
395                 String target = (String) targets.next();\r
396                 Set variantSet = add(new TreeSet(), Transliterator.getAvailableVariants(source, target));\r
397                 if (variantSet.size() < 2) {\r
398                     mitem = new MenuItem(target);\r
399                     mitem.addActionListener(new TransliterationListener(source + "-" + target));\r
400                     targetMenu.add(mitem);\r
401                 } else {\r
402                     Iterator variants = variantSet.iterator();\r
403                     Menu variantMenu = new Menu(target);\r
404                     while(variants.hasNext()) {\r
405                         String variant = (String) variants.next();\r
406                         String menuName = variant.length() == 0 ? "<default>" : variant;\r
407                         //System.out.println("<" + source + "-" + target + "/" + variant + ">, <" + menuName + ">");\r
408                         mitem = new MenuItem(menuName);\r
409                         mitem.addActionListener(new TransliterationListener(source + "-" + target + "/" + variant));\r
410                         variantMenu.add(mitem);\r
411                     }\r
412                     targetMenu.add(variantMenu);\r
413                 }\r
414             }\r
415             translitMenu.add(targetMenu);\r
416         }\r
417         \r
418         \r
419     }\r
420     \r
421     static final int RULE_FILE = 0, TEST_FILE = 1;\r
422     //\r
423     static class FileListener implements ActionListener {\r
424         Demo frame;\r
425         int choice;\r
426         \r
427         FileListener(Demo frame, int choice) {\r
428             this.frame = frame;\r
429             this.choice = choice;\r
430         }\r
431         \r
432         public void actionPerformed(ActionEvent e) {\r
433             String id = frame.translit.getID();\r
434             int slashPos = id.indexOf('/');\r
435             String variant = "";\r
436             if (slashPos >= 0) {\r
437                 variant = "_" + id.substring(slashPos+1);\r
438                 id = id.substring(0, slashPos);\r
439             }\r
440             \r
441             FileDialog fileDialog = new FileDialog(frame, "Input File");\r
442             fileDialog.setFile("Test_" + id + ".txt");\r
443             fileDialog.show();\r
444             String fileName = fileDialog.getFile();\r
445             String fileDirectory = fileDialog.getDirectory();\r
446             if (fileName != null) {\r
447                 try {\r
448                     File f = new File(fileDirectory, fileName);\r
449                     if (choice == RULE_FILE) {\r
450                         \r
451                         // read stuff into buffer\r
452                         \r
453                         StringBuffer buffer = new StringBuffer();\r
454                         FileInputStream fis = new FileInputStream(f);\r
455                         InputStreamReader isr = new InputStreamReader(fis, "UTF8");\r
456                         BufferedReader br = new BufferedReader(isr, 32*1024);\r
457                         while (true) {\r
458                             String line = br.readLine();\r
459                             if (line == null) break;\r
460                             if (line.length() > 0 && line.charAt(0) == '\uFEFF') line = line.substring(1); // strip BOM\r
461                             buffer.append('\n');\r
462                             buffer.append(line);\r
463                         }\r
464                         br.close();\r
465                         \r
466                         // Transform file name into id\r
467                         if (fileName.startsWith("Transliterator_")) {\r
468                             fileName = fileName.substring("Transliterator_".length());\r
469                         }\r
470                         int pos = fileName.indexOf('_');\r
471                         if (pos < 0) {\r
472                             id = fileName;\r
473                         } else {\r
474                             id = fileName.substring(0, pos) + "-";\r
475                             int pos2 = fileName.indexOf('_', pos+1);\r
476                             if (pos2 < 0) {\r
477                                 id += fileName.substring(pos+1);\r
478                             } else {\r
479                                 id += fileName.substring(pos+1, pos2) + "/" + fileName.substring(pos2 + 1);\r
480                             }\r
481                         }                        \r
482                         pos = id.lastIndexOf('.');\r
483                         if (pos >= 0) id = id.substring(0, pos);\r
484                         \r
485                         // Now set\r
486                         \r
487                         frame.setTransliterator(buffer.toString(), id);\r
488                     } else if (choice == TEST_FILE) {\r
489                         genTestFile(f, frame.translit, variant);\r
490                     }\r
491                 } catch (Exception e2) {\r
492                     e2.printStackTrace();\r
493                     System.out.println("Problem opening/reading: " + fileDirectory + ", " + fileName);\r
494                 }\r
495             }\r
496             fileDialog.dispose();\r
497         }\r
498     }\r
499     \r
500 \r
501     boolean transliterateTyping = true;\r
502     Transliterator fromHex = Transliterator.getInstance("Hex-Any");\r
503     InfoDialog helpDialog;\r
504     InfoDialog hexDialog;\r
505     InfoDialog compoundDialog;\r
506     InfoDialog rulesDialog;\r
507     TextField ruleId;\r
508     MenuItem convertSelectionItem = null;\r
509     MenuItem swapSelectionItem = null;\r
510     MenuItem convertTypingItem = null;\r
511     Menu historyMenu;\r
512     Map historyMap = new HashMap();\r
513     Set historySet = new TreeSet(new Comparator() {\r
514             public int compare(Object a, Object b) {\r
515                 MenuItem aa = (MenuItem)a;\r
516                 MenuItem bb = (MenuItem)b;\r
517                 return aa.getLabel().compareTo(bb.getLabel());\r
518             }\r
519         });\r
520         \r
521     // ADD Factory since otherwise getInverse blows out\r
522     static class DummyFactory implements Transliterator.Factory {\r
523         static DummyFactory singleton = new DummyFactory();\r
524         static HashMap m = new HashMap();\r
525 \r
526         // Since Transliterators are immutable, we don't have to clone on set & get\r
527         static void add(String ID, Transliterator t) {\r
528             m.put(ID, t);\r
529             System.out.println("Registering: " + ID + ", " + t.toRules(true));\r
530             Transliterator.registerFactory(ID, singleton);\r
531         }\r
532         public Transliterator getInstance(String ID) {\r
533             return (Transliterator) m.get(ID);\r
534         }\r
535     }\r
536     \r
537     static void printBreaks(int num, String testSource, BreakIterator brkItr) {\r
538         String result = "";\r
539         int lastPos = 0;\r
540         while (true) {\r
541             int pos = brkItr.next();\r
542             if (pos == BreakIterator.DONE) break;\r
543             result += testSource.substring(lastPos, pos) + "&";\r
544             lastPos = pos;\r
545             System.out.println(pos);\r
546         }\r
547         System.out.println("Test" + num + ": " + result);\r
548     }\r
549     \r
550     static void printIteration(int num, String testSource, CharacterIterator ci) {\r
551         String result = "";\r
552         while (true) {\r
553             char ch = ci.next();\r
554             if (ch == CharacterIterator.DONE) break;\r
555             result += ch + "(" + ci.getIndex() + ")";\r
556         }\r
557         System.out.println("Test" + num + ": " + result);\r
558     }\r
559     \r
560     static void printSources() {\r
561         String[] list = {"Latin-ThaiLogical", "ThaiLogical-Latin", "Thai-ThaiLogical", "ThaiLogical-Thai"};\r
562         UnicodeSet all = new UnicodeSet();\r
563         for (int i = 0; i < list.length; ++i) {\r
564             Transliterator tr = Transliterator.getInstance(list[i]);\r
565             UnicodeSet src = tr.getSourceSet();\r
566             System.out.println(list[i] + ": " + src.toPattern(true));\r
567             all.addAll(src);\r
568         }\r
569         System.out.println("All: " + all.toPattern(true));\r
570         UnicodeSet rem = new UnicodeSet("[[:latin:][:thai:]]");\r
571         System.out.println("missing from [:latin:][:thai:]: " + all.removeAll(rem).toPattern(true));\r
572     }\r
573     \r
574     // 200E;LEFT-TO-RIGHT MARK;Cf;0;L;;;;;N;;;;;\r
575 \r
576     static Transliterator title = Transliterator.getInstance("title");\r
577     static String hexAndNameRules = "    ([:c:]) > \\u200E &hex/unicode($1) ' ( ) ' &name($1) \\u200E ' ';"\r
578         + "([:mark:]) > \\u200E &hex/unicode($1) ' ( ' \\u200E \u25CC $1 \\u200E ' ) ' &name($1) \\u200E ' ';"\r
579         + "(.) > \\u200E &hex/unicode($1) ' ( ' \\u200E $1 \\u200E ' ) ' &name($1) ' ' \\u200E;";\r
580 \r
581     static Transliterator hexAndName = Transliterator.createFromRules("any-hexAndName", \r
582         hexAndNameRules, Transliterator.FORWARD);\r
583     \r
584 \r
585 \r
586     //static Transliterator upper = Transliterator.getInstance("upper");\r
587      \r
588     static final byte NONE = 0, TITLEWORD = 1, TITLELINE = 2;\r
589     \r
590     static void genTestFile(File sourceFile, Transliterator translit, String variant) {\r
591         try {\r
592             \r
593             System.out.println("Reading: " + sourceFile.getCanonicalPath());\r
594             BufferedReader in = new BufferedReader(\r
595                 new InputStreamReader(\r
596                     new FileInputStream(sourceFile), "UTF-8"));\r
597             String targetFile = sourceFile.getCanonicalPath();\r
598             int dotPos = targetFile.lastIndexOf('.');\r
599             if (dotPos >= 0) targetFile = targetFile.substring(0,dotPos);\r
600             targetFile += variant;\r
601             \r
602             File outFile = new File(targetFile + ".html");\r
603             System.out.println("Writing: " + outFile.getCanonicalPath());\r
604             \r
605             PrintWriter out = new PrintWriter(\r
606                 new BufferedWriter(\r
607                     new OutputStreamWriter(\r
608                         new FileOutputStream(outFile), "UTF-8")));\r
609                         \r
610             String direction = "";\r
611             String id = translit.getID();\r
612             if (id.indexOf("Arabic") >= 0 || id.indexOf("Hebrew") >= 0) {\r
613                 direction = " direction: rtl;";\r
614             }\r
615             boolean testRoundTrip = true;\r
616             boolean generateSets = true;\r
617             if (id.startsWith("Han-") || id.startsWith("ja-")) {\r
618                 testRoundTrip = false;\r
619                 generateSets = false;\r
620             }\r
621             out.println("<head><meta http-equiv='Content-Type' content='text/html; charset=utf-8'>");\r
622             out.println("<style><!--");\r
623             out.println("td, th       { vertical-align: top; border: 1px solid black }");\r
624             out.println("td.s       { background-color: #EEEEEE;" + direction + " }");\r
625             out.println("td.r       { background-color: #CCCCCC;" + direction + " }");\r
626             out.println("td.n       { background-color: #FFFFCC; }");\r
627             out.println("td.title       { border: 0px solid black}");\r
628             out.println("span.d       { background-color: #FF6666 }");\r
629             out.println("span.r       { background-color: #66FF66 }");\r
630 \r
631             out.println("body         { font-family: 'Arial Unicode MS', 'Lucida Sans Unicode', Arial, sans-serif; margin: 5 }");\r
632             out.println("--></style>");\r
633             out.println("<title>" + id + " Transliteration Check</title></head>");\r
634             out.println("<body bgcolor='#FFFFFF'><p>See <a href='Test_Instructions.html'>Test_Instructions.html</a> for details.</p>");\r
635             out.println("<table>");\r
636             \r
637             //out.println("<tr><th width='33%'>Thai</th><th width='33%'>Latin</th><th width='33%'>Thai</th></tr>");\r
638   \r
639             Transliterator tl = translit;\r
640             Transliterator lt = tl.getInverse();\r
641             \r
642             Transliterator ltFilter = tl.getInverse();\r
643             ltFilter.setFilter(new UnicodeSet("[:^Lu:]"));\r
644             Transliterator tlFilter = lt.getInverse();\r
645             tlFilter.setFilter(new UnicodeSet("[:^Lu:]"));\r
646             \r
647             //Transliterator.getInstance("[:^Lu:]" +  lt.getID());\r
648             \r
649             BreakIterator sentenceBreak = BreakIterator.getSentenceInstance();\r
650             \r
651             byte titleSetting = TITLELINE;\r
652             //boolean upperfilter = false;\r
653             boolean first = true;\r
654             while (true) {\r
655                 String line = in.readLine();\r
656                 if (line == null) break;\r
657                 line = line.trim();\r
658                 if (line.length() == 0) continue;\r
659                 if (line.charAt(0) == '\uFEFF') line = line.substring(1); // remove BOM\r
660                 \r
661                 if (line.charAt(0) == '#') continue; // comments\r
662                 \r
663                 if (line.equals("@TITLECASE@")) {\r
664                     titleSetting = TITLEWORD;\r
665                     out.println("<tr><td colspan='2' class='title'><b>Names</b></td></tr>");\r
666                     continue;\r
667                 } else if (line.equals("@UPPERFILTER@")) {\r
668                     //upperfilter = true;\r
669                     continue;\r
670                 } else if (line.startsWith("@SET")) {\r
671                     UnicodeSet s = new UnicodeSet(line.substring(4).trim());\r
672                     out.println("<tr><td colspan='2' class='title'><b>Characters</b></td></tr>");\r
673                     UnicodeSetIterator it = new UnicodeSetIterator(s);\r
674                     while (it.next()) {\r
675                         addSentenceToTable(out, it.codepoint != UnicodeSetIterator.IS_STRING \r
676                             ? UTF16.valueOf(it.codepoint)\r
677                             : it.string,\r
678                             NONE, true, testRoundTrip, first, tl, lt);\r
679                     }\r
680                     continue;\r
681                 }\r
682                         \r
683                 sentenceBreak.setText(line);\r
684                 int start = 0;\r
685                 while (true) {\r
686                     int end = sentenceBreak.next();\r
687                     if (end == BreakIterator.DONE) break;\r
688                     String coreSentence = line.substring(start, end);\r
689                     //System.out.println("Core: " + hex.transliterate(coreSentence));\r
690                     end = start;\r
691                     \r
692                     int oldPos = 0;\r
693                     while (oldPos < coreSentence.length()) {\r
694                         // hack, because sentence doesn't seem to be working right\r
695                         int pos = coreSentence.indexOf(". ", oldPos);\r
696                         if (pos < 0) pos = coreSentence.length(); else pos = pos+2;\r
697                         int pos2 = coreSentence.indexOf('\u3002', oldPos);\r
698                         if (pos2 < 0) pos2 = coreSentence.length(); else pos2 = pos2 + 1;\r
699                         if (pos > pos2) pos = pos2;\r
700                         String sentence = coreSentence.substring(oldPos, pos).trim();\r
701                         //System.out.println("Sentence: " + hex.transliterate(coreSentence));\r
702                         oldPos = pos;\r
703                         \r
704                         addSentenceToTable(out, sentence,\r
705                             titleSetting, false, testRoundTrip, first, tl, lt);\r
706                         \r
707                         first = false;\r
708                     }\r
709                 }\r
710             }\r
711             out.println("</table></body>");\r
712             out.close();\r
713             \r
714             // Now write the source/target sets\r
715             if (generateSets) {\r
716                 outFile = new File(targetFile + "_Sets.html");\r
717                 System.out.println("Writing: " + outFile.getCanonicalPath());\r
718                 \r
719                 out = new PrintWriter(\r
720                     new BufferedWriter(\r
721                         new OutputStreamWriter(\r
722                             new FileOutputStream(outFile), "UTF-8")));\r
723                 out.println("<head><meta http-equiv='Content-Type' content='text/html; charset=utf-8'>");\r
724                 out.println("<style><!--");\r
725                 out.println("body         { font-family: 'Arial Unicode MS', 'Lucida Sans Unicode', Arial, sans-serif; margin: 5 }");\r
726                 out.println("--></style>");\r
727                 out.println("<title>" + id + " Transliteration Sets</title></head>");\r
728                 out.println("<body bgcolor='#FFFFFF'>");\r
729                 \r
730                 int dashPos = id.indexOf('-');\r
731                 int slashPos = id.indexOf('/');\r
732                 if (slashPos < 0) slashPos = id.length();\r
733                 UnicodeSet sourceSuper = null;\r
734                 try {\r
735                     String temp = id.substring(0,dashPos);\r
736                     if (temp.equals("ja")) sourceSuper = new UnicodeSet("[[:Han:][:hiragana:][:katakana:]]");\r
737                     else sourceSuper = new UnicodeSet("[[:" + temp + ":][:Mn:][:Me:]]");\r
738                 } catch (Exception e) {}\r
739                 \r
740                 UnicodeSet targetSuper = null;\r
741                 try {\r
742                     targetSuper = new UnicodeSet("[[:" + id.substring(dashPos+1, slashPos) + ":][:Mn:][:Me:]]");\r
743                 } catch (Exception e) {}\r
744                 \r
745                 int nfdStyle = CLOSE_CASE | CLOSE_FLATTEN | CLOSE_CANONICAL;\r
746                 int nfkdStyle = nfdStyle | CLOSE_COMPATIBILITY;\r
747                 out.println("<ul>");\r
748                 out.println("<p><b>None</b></p>");\r
749                 showSets(out, translit, lt, null, null, 0);\r
750                 out.println("<p><b>NFD</b></p>");\r
751                 showSets(out, translit, lt, sourceSuper, targetSuper, nfdStyle);\r
752                 out.println("<p><b>NFKD</b></p>");\r
753                 showSets(out, translit, lt, sourceSuper, targetSuper, nfkdStyle);\r
754                 out.println("</ul></body>");\r
755                 out.close();\r
756             }\r
757             System.out.println("Done Writing");\r
758         } catch (Exception e) {\r
759             e.printStackTrace();\r
760         }\r
761     }\r
762     \r
763     static void addSentenceToTable(PrintWriter out, String sentence, \r
764             byte titleSetting, boolean addName, boolean testRoundTrip, boolean first,\r
765             Transliterator tl, Transliterator lt) {\r
766         if (sentence.length() == 0) return; // skip empty lines\r
767         \r
768         String originalShow = sentence;\r
769         String latin;\r
770         latin = tl.transliterate(saveAscii.transliterate(sentence));\r
771 \r
772         String latinShow = latin;\r
773         if (titleSetting == TITLEWORD) {\r
774             latinShow = title.transliterate(latin);\r
775         } else if (titleSetting == TITLELINE) {\r
776             latinShow = titlecaseFirstWord(latinShow);\r
777         }\r
778         latinShow = restoreAscii.transliterate(latinShow);\r
779                         \r
780         String reverse;\r
781         reverse = restoreAscii.transliterate(lt.transliterate(latin));\r
782                         \r
783         String NFKDSentence = Normalizer.normalize(sentence, Normalizer.NFKD);\r
784         String NFKDLatin = Normalizer.normalize(latin, Normalizer.NFKD);\r
785         String NFKDReverse = Normalizer.normalize(reverse, Normalizer.NFKD);\r
786         \r
787         if (latinShow.length() == 0) {\r
788             latinShow = "<i>empty</i>";\r
789         } else if (NFKDSentence.equals(NFKDLatin)) {\r
790             latinShow = "<span class='r'>" + latinShow + "</span>";\r
791         }\r
792         String reverseShow = reverse;\r
793         \r
794         if (testRoundTrip && !NFKDReverse.equals(NFKDSentence)) {\r
795             int minLen = reverse.length();\r
796             if (minLen > sentence.length()) minLen = sentence.length();\r
797             int i;\r
798             for (i = 0; i < minLen; ++i) {\r
799                 if (reverse.charAt(i) != sentence.charAt(i)) break;\r
800             }\r
801             //originalShow = sentence.substring(0,i) + "<span class='d'>" + sentence.substring(i) + "</span>";\r
802             reverseShow = reverseShow.length() == 0 \r
803                 ? "<i>empty</i>" \r
804                 //: reverse.substring(0,i) + "<span class='d'>" + reverse.substring(i) + "</span>";\r
805                 : showDifference(sentence, reverse);\r
806             out.println("<tr><td class='s'" + (first ? " width='50%'>" : ">") + originalShow \r
807                 + "</td><td rowSpan='2'>" + latinShow\r
808                 + "</td></tr><tr><td class='r'>" + reverseShow\r
809                 + "</td></tr>");\r
810         } else {\r
811             out.println("<tr><td class='s'" + (first ? " width='50%'>" : ">") + originalShow \r
812                 + "</td><td>" + latinShow\r
813                 + "</td></tr>");\r
814         }\r
815         if (addName) {\r
816             latinShow = hexAndName.transliterate(latin);\r
817             if (latinShow.length() == 0) latinShow = "<i>empty</i>";\r
818             originalShow = hexAndName.transliterate(sentence);\r
819             if (originalShow.length() == 0) originalShow = "<i>empty</i>";\r
820 \r
821             out.println("<tr><td class='n'>" + originalShow\r
822                 + "</td><td class='n'>" + latinShow\r
823                 + "</td></tr>");\r
824         }\r
825         out.println("<tr><td></td></tr>");\r
826         \r
827     }\r
828     \r
829     static String showDifference(String as, String bs) {\r
830         Differ differ = new Differ(300, 3);\r
831         StringBuffer out = new StringBuffer();\r
832         int max = as.length();\r
833         if (max < bs.length()) max = bs.length();\r
834         for (int j = 0; j <= max; ++j) {\r
835             if (j < as.length()) differ.addA(as.substring(j, j+1));\r
836             if (j < bs.length()) differ.addB(bs.substring(j, j+1));\r
837             differ.checkMatch(j == max);\r
838 \r
839             if (differ.getACount() != 0 || differ.getBCount() != 0) {\r
840                 out.append("...");\r
841                 if (differ.getACount() != 0) {\r
842                     out.append("<span class='r'>");\r
843                     for (int i = 0; i < differ.getACount(); ++i) {\r
844                         out.append(differ.getA(i));\r
845                     }\r
846                     out.append("</span>");\r
847                 }\r
848                 if (differ.getBCount() != 0) {\r
849                     out.append("<span class='d'>");\r
850                     for (int i = 0; i < differ.getBCount(); ++i) {\r
851                         out.append(differ.getB(i));\r
852                     }\r
853                     out.append("</span>");\r
854                 }\r
855                 out.append("...");\r
856             }\r
857         }\r
858         return out.toString();\r
859     }\r
860     \r
861     static void showSets(PrintWriter out, Transliterator translit, Transliterator inverse,\r
862       UnicodeSet sourceSuper, UnicodeSet targetSuper, int options) {\r
863         out.println("<li>Source Set:<ul><li>" +         toPattern(closeUnicodeSet(translit.getSourceSet(), options), sourceSuper) + "</li></ul></li>");\r
864         out.println("<li>Reverse Target Set:<ul><li>" + toPattern(closeUnicodeSet(inverse.getTargetSet(),  options), sourceSuper) + "</li></ul></li>");\r
865         out.println("<li>Target Set:<ul><li>" +         toPattern(closeUnicodeSet(translit.getTargetSet(), options), targetSuper) + "</li></ul></li>");\r
866         out.println("<li>Reverse Source Set:<ul><li>" + toPattern(closeUnicodeSet(inverse.getSourceSet(),  options), targetSuper) + "</li></ul></li>");\r
867     }\r
868         \r
869     static final int CLOSE_CASE = 1, CLOSE_FLATTEN = 2, CLOSE_CANONICAL = 4, CLOSE_COMPATIBILITY = 8;\r
870     \r
871     static UnicodeSet closeUnicodeSet(UnicodeSet source, int options) {\r
872         if (options == 0) return source;\r
873         \r
874         UnicodeSetIterator it = new UnicodeSetIterator(source);\r
875         UnicodeSet additions = new UnicodeSet(); // to avoid messing up iterator\r
876         UnicodeSet removals = new UnicodeSet(); // to avoid messing up iterator\r
877         String base;\r
878         int cp;\r
879         \r
880         // Add all case equivalents\r
881         if ((options & CLOSE_CASE) != 0) {\r
882             while (it.next()) {\r
883                 cp = it.codepoint;\r
884                 if (cp == UnicodeSetIterator.IS_STRING) continue;\r
885                 int type = UCharacter.getType(cp);\r
886                 if (type == Character.UPPERCASE_LETTER || type == Character.LOWERCASE_LETTER || type == Character.TITLECASE_LETTER) {\r
887                     additions.add(UCharacter.toLowerCase(UTF16.valueOf(cp)));\r
888                     additions.add(UCharacter.toUpperCase(UTF16.valueOf(cp)));\r
889                 }\r
890             }\r
891             source.addAll(additions);\r
892         }\r
893        \r
894         // Add the canonical closure of all strings and characters in source\r
895         if ((options & CLOSE_CANONICAL) != 0) {\r
896             it.reset();\r
897             additions.clear();\r
898             CanonicalIterator ci = new CanonicalIterator(".");\r
899             while (it.next()) {\r
900                 if (it.codepoint == UnicodeSetIterator.IS_STRING) base = it.string;\r
901                 else base = UTF16.valueOf(it.codepoint);\r
902                 ci.setSource(base);\r
903                 while (true) {\r
904                     String trial = ci.next();\r
905                     if (trial == null) break;\r
906                     if (trial.equals(base)) continue;\r
907                     additions.add(trial);\r
908                 }\r
909             }\r
910             source.addAll(additions);\r
911         }\r
912 \r
913         // flatten strings\r
914         if ((options & CLOSE_FLATTEN) != 0) {\r
915             it.reset();\r
916             additions.clear();\r
917             while (it.next()) {\r
918                 if (it.codepoint != UnicodeSetIterator.IS_STRING) continue;\r
919                 additions.addAll(it.string);\r
920                 removals.add(it.string);\r
921                 //System.out.println("flattening '" + hex.transliterate(it.string) + "'");\r
922             }\r
923             source.addAll(additions);\r
924             source.removeAll(removals);\r
925         }\r
926        \r
927         // Now add decompositions of characters in source\r
928         if ((options & CLOSE_COMPATIBILITY) != 0) {\r
929             it.reset(source);\r
930             additions.clear();\r
931             while (it.next()) {\r
932                 if (it.codepoint == UnicodeSetIterator.IS_STRING) base = it.string;\r
933                 else base = UTF16.valueOf(it.codepoint);\r
934                 if (Normalizer.isNormalized(base, Normalizer.NFKD,0)) continue;\r
935                 String decomp = Normalizer.normalize(base, Normalizer.NFKD);\r
936                 additions.add(decomp);\r
937             }\r
938             source.addAll(additions);\r
939             \r
940             // Now add any other character that decomposes to a character in source\r
941             for (cp = 0; cp < 0x10FFFF; ++cp) {\r
942                 if (!UCharacter.isDefined(cp)) continue;\r
943                 if (Normalizer.isNormalized(cp, Normalizer.NFKD,0)) continue;\r
944                 if (source.contains(cp)) continue;\r
945                 \r
946                 String decomp = Normalizer.normalize(cp, Normalizer.NFKD);\r
947                 if (source.containsAll(decomp)) {\r
948                     // System.out.println("Adding: " + Integer.toString(cp,16) + " " + UCharacter.getName(cp));\r
949                     source.add(cp);\r
950                 }\r
951             }\r
952         }\r
953         \r
954         return source;\r
955     }\r
956     \r
957     static String toPattern(UnicodeSet source, UnicodeSet superset) {\r
958         if (superset != null) {\r
959             source.removeAll(superset);\r
960             return "[" + superset.toPattern(true) + " " + source.toPattern(true) + "]";\r
961         }\r
962         return source.toPattern(true);\r
963     }\r
964     \r
965     static BreakIterator bi = BreakIterator.getWordInstance();\r
966     \r
967     static String titlecaseFirstWord(String line) {\r
968         // search for first word with letters. If the first letter is lower, then titlecase it.\r
969         bi.setText(line);\r
970         int start = 0;\r
971         while (true) {\r
972             int end = bi.next();\r
973             if (end == BreakIterator.DONE) break;\r
974             int firstLetterType = getFirstLetterType(line, start, end);\r
975             if (firstLetterType != Character.UNASSIGNED) {\r
976                 if (firstLetterType != Character.LOWERCASE_LETTER) break;\r
977                 line = line.substring(0, start) \r
978                     + UCharacter.toTitleCase(line.substring(start, end), bi)\r
979                     + line.substring(end);\r
980                 break;\r
981             }\r
982             end = start;\r
983         }\r
984         return line;\r
985     }\r
986     \r
987     static final int LETTER_MASK = \r
988           (1<<Character.UPPERCASE_LETTER)\r
989         | (1<<Character.LOWERCASE_LETTER)\r
990         | (1<<Character.TITLECASE_LETTER)\r
991         | (1<<Character.MODIFIER_LETTER)\r
992         | (1<<Character.OTHER_LETTER)\r
993         ;\r
994     \r
995     static int getFirstLetterType(String line, int start, int end) {\r
996         int cp;\r
997         for (int i = start; i < end; i += UTF16.getCharCount(cp)) {\r
998             cp = UTF16.charAt(line, i);\r
999             int type = UCharacter.getType(cp);\r
1000             if (((1<<type) & LETTER_MASK) != 0) return type;\r
1001         }\r
1002         return Character.UNASSIGNED;\r
1003     }\r
1004     \r
1005     static void printNames(UnicodeSet s, String targetFile) {\r
1006         try {\r
1007             File outFile = new File(targetFile);\r
1008             System.out.println("Writing: " + outFile.getCanonicalPath());\r
1009                 \r
1010             PrintWriter out = new PrintWriter(\r
1011                 new BufferedWriter(\r
1012                     new OutputStreamWriter(\r
1013                         new FileOutputStream(outFile), "UTF-8")));\r
1014             UnicodeSet main = new UnicodeSet();\r
1015             \r
1016             UnicodeSet others = new UnicodeSet();\r
1017             UnicodeSetIterator it = new UnicodeSetIterator(s);\r
1018             while (it.next()) {\r
1019                 if (!UCharacter.isDefined(it.codepoint)) continue;\r
1020                 if (!Normalizer.isNormalized(it.codepoint, Normalizer.NFD,0)) {\r
1021                     String decomp = Normalizer.normalize(it.codepoint, Normalizer.NFD);\r
1022                     others.addAll(decomp);\r
1023                     continue;\r
1024                 }\r
1025                 out.println(" " + UTF16.valueOf(it.codepoint) + " <> XXX # " + UCharacter.getName(it.codepoint));\r
1026                 main.add(it.codepoint);\r
1027             }\r
1028             \r
1029             if (others.size() != 0) {\r
1030                 out.println("Decomposed characters found above: ");\r
1031                 others.removeAll(main);\r
1032                 it.reset(others);\r
1033                 while (it.next()) {\r
1034                     out.println(" " + UTF16.valueOf(it.codepoint) + " <> XXX # " + UCharacter.getName(it.codepoint));\r
1035                 }\r
1036             }\r
1037             \r
1038             out.close();\r
1039             System.out.println("Done Writing");\r
1040         } catch (Exception e) {\r
1041             e.printStackTrace();\r
1042         }\r
1043     }\r
1044     \r
1045     static Transliterator hex = Transliterator.getInstance("[^\\u0020-\\u007E] hex");\r
1046     static final String saveRules = \r
1047           "A <> \uEA41; B <> \uEA42; C <> \uEA43; D <> \uEA44; E <> \uEA45; F <> \uEA46; G <> \uEA47; H <> \uEA48; I <> \uEA49; "\r
1048         + "J <> \uEA4A; K <> \uEA4B; L <> \uEA4C; M <> \uEA4D; N <> \uEA4E; O <> \uEA4F; P <> \uEA50; Q <> \uEA51; R <> \uEA52; "\r
1049         + "S <> \uEA53; T <> \uEA54; U <> \uEA55; V <> \uEA56; W <> \uEA57; X <> \uEA58; Y <> \uEA59; Z <> \uEA5A; "\r
1050         + "a <> \uEA61; b <> \uEA62; c <> \uEA63; d <> \uEA64; e <> \uEA65; f <> \uEA66; g <> \uEA67; h <> \uEA68; i <> \uEA69; "\r
1051         + "j <> \uEA6A; k <> \uEA6B; l <> \uEA6C; m <> \uEA6D; n <> \uEA6E; o <> \uEA6F; p <> \uEA70; q <> \uEA71; r <> \uEA72; "\r
1052         + "s <> \uEA73; t <> \uEA74; u <> \uEA75; v <> \uEA76; w <> \uEA77; x <> \uEA78; y <> \uEA79; z <> \uEA7A;";\r
1053         \r
1054     static Transliterator saveAscii = Transliterator.createFromRules("ascii-saved", saveRules, Transliterator.FORWARD);\r
1055     static Transliterator restoreAscii = Transliterator.createFromRules("ascii-saved", saveRules, Transliterator.REVERSE);\r
1056     \r
1057     static {\r
1058         \r
1059         if (false) {\r
1060         \r
1061         for (char i = 'A'; i <= 'z'; ++i) {\r
1062             System.out.print(i + " <> " + hex.transliterate(String.valueOf((char)(0xEA00 + i))) + "; ");\r
1063         }\r
1064 \r
1065         UnicodeSet x = new UnicodeSet("[[:^ccc=0:]&[:^ccc=230:]]");\r
1066         x = x.complement();\r
1067         x = x.complement();\r
1068         System.out.println("Test: " + x.toPattern(true));\r
1069         \r
1070         Transliterator y = Transliterator.createFromRules("xxx", "$notAbove = [[:^ccc=0:]&[:^ccc=230:]]; u ($notAbove*) \u0308 > XXX | $1; ", Transliterator.FORWARD);\r
1071         \r
1072         String[] testList = {"u\u0308", "u\u0316\u0308", "u\u0308\u0316", "u\u0301\u0308", "u\u0308\u0301"};\r
1073         for (int i = 0; i < testList.length; ++i) {\r
1074             String yy = y.transliterate(testList[i]);\r
1075             System.out.println(hex.transliterate(testList[i]) + " => " + hex.transliterate(yy));\r
1076         }\r
1077         \r
1078         //printNames(new UnicodeSet("[\u0600-\u06FF]"), "Arabic-Latin.txt");\r
1079         \r
1080         \r
1081         /*  \r
1082         BreakTransliterator.register();\r
1083         \r
1084         BreakTransliterator testTrans = new BreakTransliterator("Any-XXX", null, null, "$");\r
1085         String testSource = "The Quick:   Brown fox--jumped.";\r
1086         BreakIterator bi = testTrans.getBreakIterator();\r
1087         bi.setText(new StringCharacterIterator(testSource));\r
1088         printBreaks(0, testSource, bi);\r
1089         //bi.setText(UCharacterIterator.getInstance(testSource));\r
1090         //printBreaks(1, testSource, bi);\r
1091         \r
1092         printIteration(2, testSource, new StringCharacterIterator(testSource));\r
1093         //printIteration(3, testSource, UCharacterIterator.getInstance(testSource));\r
1094         \r
1095         \r
1096         \r
1097         String test = testTrans.transliterate(testSource);\r
1098         System.out.println("Test3: " + test);\r
1099         DummyFactory.add(testTrans.getID(), testTrans);\r
1100         */\r
1101         \r
1102         // AnyTransliterator.ScriptRunIterator.registerAnyToScript();\r
1103         \r
1104         AnyTransliterator at = new AnyTransliterator("Greek", null);\r
1105         at.transliterate("(cat,\u03b1,\u0915)");\r
1106         DummyFactory.add(at.getID(), at);\r
1107         \r
1108         at = new AnyTransliterator("Devanagari", null);\r
1109         at.transliterate("(cat,\u03b1,\u0915)");\r
1110         DummyFactory.add(at.getID(), at);\r
1111         \r
1112         at = new AnyTransliterator("Latin", null);\r
1113         at.transliterate("(cat,\u03b1,\u0915)");\r
1114         DummyFactory.add(at.getID(), at);\r
1115         \r
1116         DummyFactory.add("Any-gif", Transliterator.createFromRules("gif", "'\\'u(..)(..) > '<img src=\"http://www.unicode.org/gifs/24/' $1 '/U' $1$2 '.gif\">';", Transliterator.FORWARD));        \r
1117         DummyFactory.add("gif-Any", Transliterator.getInstance("Any-Null"));        \r
1118 \r
1119         DummyFactory.add("Any-RemoveCurly", Transliterator.createFromRules("RemoveCurly", "[\\{\\}] > ;", Transliterator.FORWARD));        \r
1120         DummyFactory.add("RemoveCurly-Any", Transliterator.getInstance("Any-Null"));\r
1121         \r
1122         System.out.println("Trying &hex");\r
1123         Transliterator t = Transliterator.createFromRules("hex2", "(.) > &hex($1);", Transliterator.FORWARD);\r
1124         System.out.println("Registering");\r
1125         DummyFactory.add("Any-hex2", t);        \r
1126         \r
1127         System.out.println("Trying &gif");\r
1128         t = Transliterator.createFromRules("gif2", "(.) > &any-gif($1);", Transliterator.FORWARD);\r
1129         System.out.println("Registering");\r
1130         DummyFactory.add("Any-gif2", t);    \r
1131         }\r
1132     }\r
1133     \r
1134     \r
1135     void setTransliterator(String name, String id) {\r
1136         if (DEBUG) System.out.println("Got: " + name);\r
1137         if (id == null) {\r
1138             translit = Transliterator.getInstance(name);\r
1139         } else {\r
1140             String reverseId = "";\r
1141             int pos = id.indexOf('-');\r
1142             if (pos < 0) {\r
1143                 reverseId = id + "-Any";\r
1144                 id = "Any-" + id;\r
1145             } else {\r
1146                 int pos2 = id.indexOf("/", pos);\r
1147                 if (pos2 < 0) {\r
1148                     reverseId = id.substring(pos+1) + "-" + id.substring(0,pos);\r
1149                 } else {\r
1150                     reverseId = id.substring(pos+1, pos2) + "-" + id.substring(0,pos) + id.substring(pos2);\r
1151                 }\r
1152             }\r
1153             \r
1154             \r
1155             translit = Transliterator.createFromRules(id, name, Transliterator.FORWARD);\r
1156             if (DEBUG) {\r
1157                 System.out.println("***Forward Rules");\r
1158                 System.out.println(translit.toRules(true));\r
1159                 System.out.println("***Source Set");\r
1160                 System.out.println(translit.getSourceSet().toPattern(true));\r
1161             }\r
1162                 System.out.println("***Target Set");\r
1163                 UnicodeSet target = translit.getTargetSet();\r
1164                 System.out.println(target.toPattern(true));\r
1165                 UnicodeSet rest = new UnicodeSet("[a-z]").removeAll(target);\r
1166                 System.out.println("***ASCII - Target Set");\r
1167                 System.out.println(rest.toPattern(true));\r
1168                 \r
1169             DummyFactory.add(id, translit);\r
1170             \r
1171             Transliterator translit2 = Transliterator.createFromRules(reverseId, name, Transliterator.REVERSE);\r
1172             if (DEBUG) {\r
1173                 System.out.println("***Backward Rules");\r
1174                 System.out.println(translit2.toRules(true));\r
1175             }\r
1176             DummyFactory.add(reverseId, translit2);\r
1177             \r
1178             Transliterator rev = translit.getInverse();\r
1179             if (DEBUG) System.out.println("***Inverse Rules");\r
1180             if (DEBUG) System.out.println(rev.toRules(true));\r
1181             \r
1182         }\r
1183         text.flush();\r
1184         text.setTransliterator(translit);\r
1185         convertSelectionItem.setLabel(Transliterator.getDisplayName(translit.getID()));\r
1186         \r
1187         addHistory(translit);\r
1188         \r
1189         Transliterator inv;\r
1190         try {\r
1191             inv = translit.getInverse();\r
1192         } catch (Exception ex) {\r
1193             inv = null;\r
1194         }\r
1195         if (inv != null) {\r
1196             addHistory(inv);\r
1197             swapSelectionItem.setEnabled(true);\r
1198         } else {\r
1199             swapSelectionItem.setEnabled(false);\r
1200         }\r
1201         System.out.println("Set transliterator: " + translit.getID()\r
1202             + (inv != null ? " and " + inv.getID() : ""));\r
1203     }\r
1204     \r
1205     void addHistory(Transliterator trans) {\r
1206         String name = trans.getID();\r
1207         MenuItem cmi = (MenuItem) historyMap.get(name);\r
1208         if (cmi == null) {\r
1209             cmi = new MenuItem(Transliterator.getDisplayName(name));\r
1210             cmi.addActionListener(new TransliterationListener(name));\r
1211             historyMap.put(name, cmi);\r
1212             historySet.add(cmi);\r
1213             historyMenu.removeAll();\r
1214             Iterator it = historySet.iterator();\r
1215             while (it.hasNext()) {\r
1216                 historyMenu.add((MenuItem)it.next());\r
1217             }\r
1218         }\r
1219     }\r
1220     \r
1221     class TransliterationListener implements ActionListener, ItemListener {\r
1222         String name;\r
1223         public TransliterationListener(String name) {\r
1224             this.name = name;\r
1225         }\r
1226         public void actionPerformed(ActionEvent e) {\r
1227             setTransliterator(name, null);\r
1228         }\r
1229         public void itemStateChanged(ItemEvent e) {\r
1230             if (e.getStateChange() == ItemEvent.SELECTED) {\r
1231                 setTransliterator(name, null);\r
1232             } else {\r
1233                 setTransliterator("Any-Null", null);\r
1234             }\r
1235         }\r
1236     }\r
1237     \r
1238     class FontActionListener implements ActionListener {\r
1239         String name;\r
1240         public FontActionListener(String name) {\r
1241             this.name = name;\r
1242         }\r
1243         public void actionPerformed(ActionEvent e) {\r
1244             if (DEBUG) System.out.println("Font: " + name);\r
1245             fontName = name;\r
1246             text.setFont(new Font(fontName, Font.PLAIN, fontSize));\r
1247         }\r
1248     }\r
1249     \r
1250     class SizeActionListener implements ActionListener {\r
1251         int size;\r
1252         public SizeActionListener(int size) {\r
1253             this.size = size;\r
1254         }\r
1255         public void actionPerformed(ActionEvent e) {\r
1256             if (DEBUG) System.out.println("Size: " + size);\r
1257             fontSize = size;\r
1258             text.setFont(new Font(fontName, Font.PLAIN, fontSize));\r
1259         }\r
1260     }\r
1261     \r
1262     Set add(Set s, Enumeration enumeration) {\r
1263         while(enumeration.hasMoreElements()) {\r
1264             s.add(enumeration.nextElement());\r
1265         }\r
1266         return s;\r
1267     }\r
1268 \r
1269     /**\r
1270      * Get a sorted list of the system transliterators.\r
1271      */\r
1272      /*\r
1273     private static Vector getSystemTransliteratorNames() {\r
1274         Vector v = new Vector();\r
1275         for (Enumeration e=Transliterator.getAvailableIDs();\r
1276              e.hasMoreElements(); ) {\r
1277             v.addElement(e.nextElement());\r
1278         }\r
1279         // Insertion sort, O(n^2) acceptable for small n\r
1280         for (int i=0; i<(v.size()-1); ++i) {\r
1281             String a = (String) v.elementAt(i);\r
1282             for (int j=i+1; j<v.size(); ++j) {\r
1283                 String b = (String) v.elementAt(j);\r
1284                 if (a.compareTo(b) > 0) {\r
1285                     v.setElementAt(b, i);\r
1286                     v.setElementAt(a, j);\r
1287                     a = b;\r
1288                 }\r
1289             }\r
1290         }\r
1291         return v;\r
1292     }\r
1293     */\r
1294 \r
1295 /*\r
1296     private void setNoTransliterator() {\r
1297         translitItem = noTranslitItem;\r
1298         noTranslitItem.setState(true);\r
1299         handleSetTransliterator(noTranslitItem.getLabel());\r
1300         compound = false;\r
1301         for (int i=0; i<translitMenu.getItemCount(); ++i) {\r
1302             MenuItem it = translitMenu.getItem(i);\r
1303             if (it != noTranslitItem && it instanceof CheckboxMenuItem) {\r
1304                 ((CheckboxMenuItem) it).setState(false);\r
1305             }\r
1306         }\r
1307     }\r
1308 */\r
1309 /*\r
1310     private void handleAddToCompound(String name) {\r
1311         if (compoundCount < MAX_COMPOUND) {\r
1312             compoundTranslit[compoundCount] = decodeTranslitItem(name);\r
1313             ++compoundCount;\r
1314             Transliterator t[] = new Transliterator[compoundCount];\r
1315             System.arraycopy(compoundTranslit, 0, t, 0, compoundCount);\r
1316             translit = new CompoundTransliterator(t);\r
1317             text.setTransliterator(translit);\r
1318         }\r
1319     }\r
1320 */\r
1321 /*\r
1322     private void handleSetTransliterator(String name) {\r
1323         translit = decodeTranslitItem(name);\r
1324         text.setTransliterator(translit);\r
1325     }\r
1326     */\r
1327 \r
1328     /**\r
1329      * Decode a menu item that looks like <translit name>.\r
1330      */\r
1331      /*\r
1332     private static Transliterator decodeTranslitItem(String name) {\r
1333         return (name.equals(NO_TRANSLITERATOR))\r
1334             ? null : Transliterator.getInstance(name);\r
1335     }\r
1336     */\r
1337 \r
1338     private void handleBatchTransliterate(Transliterator trans) {\r
1339         if (trans == null) {\r
1340             return;\r
1341         }\r
1342 \r
1343         int start = text.getSelectionStart();\r
1344         int end = text.getSelectionEnd();\r
1345         ReplaceableString s =\r
1346             new ReplaceableString(text.getText().substring(start, end));\r
1347 \r
1348         StringBuffer log = null;\r
1349         if (DEBUG) {\r
1350             log = new StringBuffer();\r
1351             log.append('"' + s.toString() + "\" (start " + start +\r
1352                        ", end " + end + ") -> \"");\r
1353         }\r
1354 \r
1355         trans.transliterate(s);\r
1356         String str = s.toString();\r
1357 \r
1358         if (DEBUG) {\r
1359             log.append(str + "\"");\r
1360             System.out.println("Batch " + trans.getID() + ": " + log.toString());\r
1361         }\r
1362 \r
1363         text.replaceRange(str, start, end);\r
1364         text.select(start, start + str.length());\r
1365     }\r
1366 \r
1367     private void handleClose() {\r
1368         helpDialog.dispose();\r
1369         dispose();\r
1370     }\r
1371     \r
1372     /*\r
1373     class InfoDialog extends Dialog {\r
1374         protected Button button;\r
1375         protected TextArea area;\r
1376         protected Dialog me;\r
1377         protected Panel bottom;\r
1378         \r
1379         public TextArea getArea() {\r
1380             return area;\r
1381         }\r
1382         \r
1383         public Panel getBottom() {\r
1384             return bottom;\r
1385         }\r
1386         \r
1387         InfoDialog(Frame parent, String title, String label, String message) {\r
1388             super(parent, title, false);\r
1389             me = this;\r
1390             this.setLayout(new BorderLayout());\r
1391             if (label.length() != 0) {\r
1392                 this.add("North", new Label(label));\r
1393             }\r
1394             \r
1395             area = new TextArea(message, 8, 80, TextArea.SCROLLBARS_VERTICAL_ONLY);\r
1396             this.add("Center", area);\r
1397             \r
1398             button = new Button("Hide");\r
1399             button.addActionListener(new ActionListener() {\r
1400                 public void actionPerformed(ActionEvent e) {\r
1401                     me.hide();\r
1402                 }\r
1403             });\r
1404             bottom = new Panel();\r
1405             bottom.setLayout(new FlowLayout(FlowLayout.CENTER, 0, 0));\r
1406             bottom.add(button);\r
1407             this.add("South", bottom);\r
1408             this.pack();\r
1409             addWindowListener(new WindowAdapter() {\r
1410                 public void windowClosing(WindowEvent e) {\r
1411                     me.hide();\r
1412                 }\r
1413             });\r
1414         }\r
1415     }\r
1416     */\r
1417 }\r