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