1 7 package javax.swing.text.rtf; 8 9 import java.lang.*; 10 import java.util.*; 11 import java.awt.Color ; 12 import java.awt.Font ; 13 import java.io.OutputStream ; 14 import java.io.IOException ; 15 16 import javax.swing.text.*; 17 18 32 33 class RTFGenerator extends Object  34 { 35 37 Dictionary colorTable; 38 int colorCount; 39 Dictionary fontTable; 40 int fontCount; 41 Dictionary styleTable; 42 int styleCount; 43 44 45 OutputStream outputStream; 46 47 boolean afterKeyword; 48 49 MutableAttributeSet outputAttributes; 50 51 52 int unicodeCount; 53 54 55 private Segment workingSegment; 56 57 int[] outputConversion; 58 59 61 static public final Color defaultRTFColor = Color.black; 62 63 static public final float defaultFontSize = 12f; 64 65 static public final String defaultFontFamily = "Helvetica"; 66 67 68 69 static protected Integer One, Zero; 70 static protected Boolean False; 71 static protected Float ZeroPointZero; 72 static private Object MagicToken; 73 74 78 static class CharacterKeywordPair 79 { public char character; public String keyword; }; 80 static protected CharacterKeywordPair[] textKeywords; 81 82 static { 83 One = new Integer (1); 84 Zero = new Integer (0); 85 False = Boolean.valueOf(false); 86 MagicToken = new Object (); 87 ZeroPointZero = new Float (0); 88 89 Dictionary textKeywordDictionary = RTFReader.textKeywords; 90 Enumeration keys = textKeywordDictionary.keys(); 91 Vector tempPairs = new Vector(); 92 while(keys.hasMoreElements()) { 93 CharacterKeywordPair pair = new CharacterKeywordPair(); 94 pair.keyword = (String )keys.nextElement(); 95 pair.character = ((String )textKeywordDictionary.get(pair.keyword)).charAt(0); 96 tempPairs.addElement(pair); 97 } 98 textKeywords = new CharacterKeywordPair[tempPairs.size()]; 99 tempPairs.copyInto(textKeywords); 100 } 101 102 static final char[] hexdigits = { '0', '1', '2', '3', '4', '5', '6', '7', 103 '8', '9', 'a', 'b', 'c', 'd', 'e', 'f' }; 104 105 static public void writeDocument(Document d, OutputStream to) 106 throws IOException  107 { 108 RTFGenerator gen = new RTFGenerator (to); 109 Element root = d.getDefaultRootElement(); 110 111 gen.examineElement(root); 112 gen.writeRTFHeader(); 113 gen.writeDocumentProperties(d); 114 115 117 int max = root.getElementCount(); 118 for(int idx = 0; idx < max; idx++) 119 gen.writeParagraphElement(root.getElement(idx)); 120 121 gen.writeRTFTrailer(); 122 } 123 124 public RTFGenerator(OutputStream to) 125 { 126 colorTable = new Hashtable(); 127 colorTable.put(defaultRTFColor, new Integer (0)); 128 colorCount = 1; 129 130 fontTable = new Hashtable(); 131 fontCount = 0; 132 133 styleTable = new Hashtable(); 134 135 styleCount = 0; 136 137 workingSegment = new Segment(); 138 139 outputStream = to; 140 141 unicodeCount = 1; 142 } 143 144 public void examineElement(Element el) 145 { 146 AttributeSet a = el.getAttributes(); 147 String fontName; 148 Object foregroundColor, backgroundColor; 149 150 tallyStyles(a); 151 152 if (a != null) { 153 154 155 foregroundColor = StyleConstants.getForeground(a); 156 if (foregroundColor != null && 157 colorTable.get(foregroundColor) == null) { 158 colorTable.put(foregroundColor, new Integer (colorCount)); 159 colorCount ++; 160 } 161 162 backgroundColor = a.getAttribute(StyleConstants.Background); 163 if (backgroundColor != null && 164 colorTable.get(backgroundColor) == null) { 165 colorTable.put(backgroundColor, new Integer (colorCount)); 166 colorCount ++; 167 } 168 169 fontName = StyleConstants.getFontFamily(a); 170 171 if (fontName == null) 172 fontName = defaultFontFamily; 173 174 if (fontName != null && 175 fontTable.get(fontName) == null) { 176 fontTable.put(fontName, new Integer (fontCount)); 177 fontCount ++; 178 } 179 } 180 181 int el_count = el.getElementCount(); 182 for(int el_idx = 0; el_idx < el_count; el_idx ++) { 183 examineElement(el.getElement(el_idx)); 184 } 185 } 186 187 private void tallyStyles(AttributeSet a) { 188 while (a != null) { 189 if (a instanceof Style) { 190 Integer aNum = (Integer )styleTable.get(a); 191 if (aNum == null) { 192 styleCount = styleCount + 1; 193 aNum = new Integer (styleCount); 194 styleTable.put(a, aNum); 195 } 196 } 197 a = a.getResolveParent(); 198 } 199 } 200 201 private Style findStyle(AttributeSet a) 202 { 203 while(a != null) { 204 if (a instanceof Style) { 205 Object aNum = styleTable.get(a); 206 if (aNum != null) 207 return (Style)a; 208 } 209 a = a.getResolveParent(); 210 } 211 return null; 212 } 213 214 private Integer findStyleNumber(AttributeSet a, String domain) 215 { 216 while(a != null) { 217 if (a instanceof Style) { 218 Integer aNum = (Integer )styleTable.get(a); 219 if (aNum != null) { 220 if (domain == null || 221 domain.equals(a.getAttribute(Constants.StyleType))) 222 return aNum; 223 } 224 225 } 226 a = a.getResolveParent(); 227 } 228 return null; 229 } 230 231 static private Object attrDiff(MutableAttributeSet oldAttrs, 232 AttributeSet newAttrs, 233 Object key, 234 Object dfl) 235 { 236 Object oldValue, newValue; 237 238 oldValue = oldAttrs.getAttribute(key); 239 newValue = newAttrs.getAttribute(key); 240 241 if (newValue == oldValue) 242 return null; 243 if (newValue == null) { 244 oldAttrs.removeAttribute(key); 245 if (dfl != null && !dfl.equals(oldValue)) 246 return dfl; 247 else 248 return null; 249 } 250 if (oldValue == null || 251 !equalArraysOK(oldValue, newValue)) { 252 oldAttrs.addAttribute(key, newValue); 253 return newValue; 254 } 255 return null; 256 } 257 258 static private boolean equalArraysOK(Object a, Object b) 259 { 260 Object [] aa, bb; 261 if (a == b) 262 return true; 263 if (a == null || b == null) 264 return false; 265 if (a.equals(b)) 266 return true; 267 if (!(a.getClass().isArray() && b.getClass().isArray())) 268 return false; 269 aa = (Object [])a; 270 bb = (Object [])b; 271 if (aa.length != bb.length) 272 return false; 273 274 int i; 275 int l = aa.length; 276 for(i = 0; i < l; i++) { 277 if (!equalArraysOK(aa[i], bb[i])) 278 return false; 279 } 280 281 return true; 282 } 283 284 285 public void writeLineBreak() 286 throws IOException  287 { 288 writeRawString("\n"); 289 afterKeyword = false; 290 } 291 292 293 public void writeRTFHeader() 294 throws IOException  295 { 296 int index; 297 298 304 writeBegingroup(); 305 writeControlWord("rtf", 1); 306 writeControlWord("ansi"); 307 outputConversion = outputConversionForName("ansi"); 308 writeLineBreak(); 309 310 311 String [] sortedFontTable = new String [fontCount]; 312 Enumeration fonts = fontTable.keys(); 313 String font; 314 while(fonts.hasMoreElements()) { 315 font = (String )fonts.nextElement(); 316 Integer num = (Integer )(fontTable.get(font)); 317 sortedFontTable[num.intValue()] = font; 318 } 319 writeBegingroup(); 320 writeControlWord("fonttbl"); 321 for(index = 0; index < fontCount; index ++) { 322 writeControlWord("f", index); 323 writeControlWord("fnil"); 324 writeText(sortedFontTable[index]); 325 writeText(";"); 326 } 327 writeEndgroup(); 328 writeLineBreak(); 329 330 331 if (colorCount > 1) { 332 Color [] sortedColorTable = new Color [colorCount]; 333 Enumeration colors = colorTable.keys(); 334 Color color; 335 while(colors.hasMoreElements()) { 336 color = (Color )colors.nextElement(); 337 Integer num = (Integer )(colorTable.get(color)); 338 sortedColorTable[num.intValue()] = color; 339 } 340 writeBegingroup(); 341 writeControlWord("colortbl"); 342 for(index = 0; index < colorCount; index ++) { 343 color = sortedColorTable[index]; 344 if (color != null) { 345 writeControlWord("red", color.getRed()); 346 writeControlWord("green", color.getGreen()); 347 writeControlWord("blue", color.getBlue()); 348 } 349 writeRawString(";"); 350 } 351 writeEndgroup(); 352 writeLineBreak(); 353 } 354 355 356 if (styleCount > 1) { 357 writeBegingroup(); 358 writeControlWord("stylesheet"); 359 Enumeration styles = styleTable.keys(); 360 while(styles.hasMoreElements()) { 361 Style style = (Style)styles.nextElement(); 362 int styleNumber = ((Integer )styleTable.get(style)).intValue(); 363 writeBegingroup(); 364 String styleType = (String )style.getAttribute(Constants.StyleType); 365 if (styleType == null) 366 styleType = Constants.STParagraph; 367 if (styleType.equals(Constants.STCharacter)) { 368 writeControlWord("*"); 369 writeControlWord("cs", styleNumber); 370 } else if(styleType.equals(Constants.STSection)) { 371 writeControlWord("*"); 372 writeControlWord("ds", styleNumber); 373 } else { 374 writeControlWord("s", styleNumber); 375 } 376 377 AttributeSet basis = style.getResolveParent(); 378 MutableAttributeSet goat; 379 if (basis == null) { 380 goat = new SimpleAttributeSet(); 381 } else { 382 goat = new SimpleAttributeSet(basis); 383 } 384 385 updateSectionAttributes(goat, style, false); 386 updateParagraphAttributes(goat, style, false); 387 updateCharacterAttributes(goat, style, false); 388 389 basis = style.getResolveParent(); 390 if (basis != null && basis instanceof Style) { 391 Integer basedOn = (Integer )styleTable.get(basis); 392 if (basedOn != null) { 393 writeControlWord("sbasedon", basedOn.intValue()); 394 } 395 } 396 397 Style nextStyle = (Style)style.getAttribute(Constants.StyleNext); 398 if (nextStyle != null) { 399 Integer nextNum = (Integer )styleTable.get(nextStyle); 400 if (nextNum != null) { 401 writeControlWord("snext", nextNum.intValue()); 402 } 403 } 404 405 Boolean hidden = (Boolean )style.getAttribute(Constants.StyleHidden); 406 if (hidden != null && hidden.booleanValue()) 407 writeControlWord("shidden"); 408 409 Boolean additive = (Boolean )style.getAttribute(Constants.StyleAdditive); 410 if (additive != null && additive.booleanValue()) 411 writeControlWord("additive"); 412 413 414 writeText(style.getName()); 415 writeText(";"); 416 writeEndgroup(); 417 } 418 writeEndgroup(); 419 writeLineBreak(); 420 } 421 422 outputAttributes = new SimpleAttributeSet(); 423 } 424 425 void writeDocumentProperties(Document doc) 426 throws IOException  427 { 428 429 int i; 430 boolean wroteSomething = false; 431 432 for(i = 0; i < RTFAttributes.attributes.length; i++) { 433 RTFAttribute attr = RTFAttributes.attributes[i]; 434 if (attr.domain() != RTFAttribute.D_DOCUMENT) 435 continue; 436 Object prop = doc.getProperty(attr.swingName()); 437 boolean ok = attr.writeValue(prop, this, false); 438 if (ok) 439 wroteSomething = true; 440 } 441 442 if (wroteSomething) 443 writeLineBreak(); 444 } 445 446 public void writeRTFTrailer() 447 throws IOException  448 { 449 writeEndgroup(); 450 writeLineBreak(); 451 } 452 453 protected void checkNumericControlWord(MutableAttributeSet currentAttributes, 454 AttributeSet newAttributes, 455 Object attrName, 456 String controlWord, 457 float dflt, float scale) 458 throws IOException  459 { 460 Object parm; 461 462 if ((parm = attrDiff(currentAttributes, newAttributes, 463 attrName, MagicToken)) != null) { 464 float targ; 465 if (parm == MagicToken) 466 targ = dflt; 467 else 468 targ = ((Number )parm).floatValue(); 469 writeControlWord(controlWord, Math.round(targ * scale)); 470 } 471 } 472 473 protected void checkControlWord(MutableAttributeSet currentAttributes, 474 AttributeSet newAttributes, 475 RTFAttribute word) 476 throws IOException  477 { 478 Object parm; 479 480 if ((parm = attrDiff(currentAttributes, newAttributes, 481 word.swingName(), MagicToken)) != null) { 482 if (parm == MagicToken) 483 parm = null; 484 word.writeValue(parm, this, true); 485 } 486 } 487 488 protected void checkControlWords(MutableAttributeSet currentAttributes, 489 AttributeSet newAttributes, 490 RTFAttribute words[], 491 int domain) 492 throws IOException  493 { 494 int wordIndex; 495 int wordCount = words.length; 496 for(wordIndex = 0; wordIndex < wordCount; wordIndex++) { 497 RTFAttribute attr = words[wordIndex]; 498 if (attr.domain() == domain) 499 checkControlWord(currentAttributes, newAttributes, attr); 500 } 501 } 502 503 void updateSectionAttributes(MutableAttributeSet current, 504 AttributeSet newAttributes, 505 boolean emitStyleChanges) 506 throws IOException  507 { 508 if (emitStyleChanges) { 509 Object oldStyle = current.getAttribute("sectionStyle"); 510 Object newStyle = findStyleNumber(newAttributes, Constants.STSection); 511 if (oldStyle != newStyle) { 512 if (oldStyle != null) { 513 resetSectionAttributes(current); 514 } 515 if (newStyle != null) { 516 writeControlWord("ds", ((Integer )newStyle).intValue()); 517 current.addAttribute("sectionStyle", newStyle); 518 } else { 519 current.removeAttribute("sectionStyle"); 520 } 521 } 522 } 523 524 checkControlWords(current, newAttributes, 525 RTFAttributes.attributes, RTFAttribute.D_SECTION); 526 } 527 528 protected void resetSectionAttributes(MutableAttributeSet currentAttributes) 529 throws IOException  530 { 531 writeControlWord("sectd"); 532 533 int wordIndex; 534 int wordCount = RTFAttributes.attributes.length; 535 for(wordIndex = 0; wordIndex < wordCount; wordIndex++) { 536 RTFAttribute attr = RTFAttributes.attributes[wordIndex]; 537 if (attr.domain() == RTFAttribute.D_SECTION) 538 attr.setDefault(currentAttributes); 539 } 540 541 currentAttributes.removeAttribute("sectionStyle"); 542 } 543 544 void updateParagraphAttributes(MutableAttributeSet current, 545 AttributeSet newAttributes, 546 boolean emitStyleChanges) 547 throws IOException  548 { 549 Object parm; 550 Object oldStyle, newStyle; 551 552 556 557 if (emitStyleChanges) { 558 oldStyle = current.getAttribute("paragraphStyle"); 559 newStyle = findStyleNumber(newAttributes, Constants.STParagraph); 560 if (oldStyle != newStyle) { 561 if (oldStyle != null) { 562 resetParagraphAttributes(current); 563 oldStyle = null; 564 } 565 } 566 } else { 567 oldStyle = null; 568 newStyle = null; 569 } 570 571 Object oldTabs = current.getAttribute(Constants.Tabs); 572 Object newTabs = newAttributes.getAttribute(Constants.Tabs); 573 if (oldTabs != newTabs) { 574 if (oldTabs != null) { 575 resetParagraphAttributes(current); 576 oldTabs = null; 577 oldStyle = null; 578 } 579 } 580 581 if (oldStyle != newStyle && newStyle != null) { 582 writeControlWord("s", ((Integer )newStyle).intValue()); 583 current.addAttribute("paragraphStyle", newStyle); 584 } 585 586 checkControlWords(current, newAttributes, 587 RTFAttributes.attributes, RTFAttribute.D_PARAGRAPH); 588 589 if (oldTabs != newTabs && newTabs != null) { 590 TabStop tabs[] = (TabStop[])newTabs; 591 int index; 592 for(index = 0; index < tabs.length; index ++) { 593 TabStop tab = tabs[index]; 594 switch (tab.getAlignment()) { 595 case TabStop.ALIGN_LEFT: 596 case TabStop.ALIGN_BAR: 597 break; 598 case TabStop.ALIGN_RIGHT: 599 writeControlWord("tqr"); 600 break; 601 case TabStop.ALIGN_CENTER: 602 writeControlWord("tqc"); 603 break; 604 case TabStop.ALIGN_DECIMAL: 605 writeControlWord("tqdec"); 606 break; 607 } 608 switch (tab.getLeader()) { 609 case TabStop.LEAD_NONE: 610 break; 611 case TabStop.LEAD_DOTS: 612 writeControlWord("tldot"); 613 break; 614 case TabStop.LEAD_HYPHENS: 615 writeControlWord("tlhyph"); 616 break; 617 case TabStop.LEAD_UNDERLINE: 618 writeControlWord("tlul"); 619 break; 620 case TabStop.LEAD_THICKLINE: 621 writeControlWord("tlth"); 622 break; 623 case TabStop.LEAD_EQUALS: 624 writeControlWord("tleq"); 625 break; 626 } 627 int twips = Math.round(20f * tab.getPosition()); 628 if (tab.getAlignment() == TabStop.ALIGN_BAR) { 629 writeControlWord("tb", twips); 630 } else { 631 writeControlWord("tx", twips); 632 } 633 } 634 current.addAttribute(Constants.Tabs, tabs); 635 } 636 } 637 638 public void writeParagraphElement(Element el) 639 throws IOException  640 { 641 updateParagraphAttributes(outputAttributes, el.getAttributes(), true); 642 643 int sub_count = el.getElementCount(); 644 for(int idx = 0; idx < sub_count; idx ++) { 645 writeTextElement(el.getElement(idx)); 646 } 647 648 writeControlWord("par"); 649 writeLineBreak(); 650 } 651 652 672 673 protected void resetParagraphAttributes(MutableAttributeSet currentAttributes) 674 throws IOException  675 { 676 writeControlWord("pard"); 677 678 currentAttributes.addAttribute(StyleConstants.Alignment, Zero); 679 680 int wordIndex; 681 int wordCount = RTFAttributes.attributes.length; 682 for(wordIndex = 0; wordIndex < wordCount; wordIndex++) { 683 RTFAttribute attr = RTFAttributes.attributes[wordIndex]; 684 if (attr.domain() == RTFAttribute.D_PARAGRAPH) 685 attr.setDefault(currentAttributes); 686 } 687 688 currentAttributes.removeAttribute("paragraphStyle"); 689 currentAttributes.removeAttribute(Constants.Tabs); 690 } 691 692 void updateCharacterAttributes(MutableAttributeSet current, 693 AttributeSet newAttributes, 694 boolean updateStyleChanges) 695 throws IOException  696 { 697 Object parm; 698 699 if (updateStyleChanges) { 700 Object oldStyle = current.getAttribute("characterStyle"); 701 Object newStyle = findStyleNumber(newAttributes, 702 Constants.STCharacter); 703 if (oldStyle != newStyle) { 704 if (oldStyle != null) { 705 resetCharacterAttributes(current); 706 } 707 if (newStyle != null) { 708 writeControlWord("cs", ((Integer )newStyle).intValue()); 709 current.addAttribute("characterStyle", newStyle); 710 } else { 711 current.removeAttribute("characterStyle"); 712 } 713 } 714 } 715 716 if ((parm = attrDiff(current, newAttributes, 717 StyleConstants.FontFamily, null)) != null) { 718 Number fontNum = (Number )fontTable.get(parm); 719 writeControlWord("f", fontNum.intValue()); 720 } 721 722 checkNumericControlWord(current, newAttributes, 723 StyleConstants.FontSize, "fs", 724 defaultFontSize, 2f); 725 726 checkControlWords(current, newAttributes, 727 RTFAttributes.attributes, RTFAttribute.D_CHARACTER); 728 729 checkNumericControlWord(current, newAttributes, 730 StyleConstants.LineSpacing, "sl", 731 0, 20f); 732 733 if ((parm = attrDiff(current, newAttributes, 734 StyleConstants.Background, MagicToken)) != null) { 735 int colorNum; 736 if (parm == MagicToken) 737 colorNum = 0; 738 else 739 colorNum = ((Number )colorTable.get(parm)).intValue(); 740 writeControlWord("cb", colorNum); 741 } 742 743 if ((parm = attrDiff(current, newAttributes, 744 StyleConstants.Foreground, null)) != null) { 745 int colorNum; 746 if (parm == MagicToken) 747 colorNum = 0; 748 else 749 colorNum = ((Number )colorTable.get(parm)).intValue(); 750 writeControlWord("cf", colorNum); 751 } 752 } 753 754 protected void resetCharacterAttributes(MutableAttributeSet currentAttributes) 755 throws IOException  756 { 757 writeControlWord("plain"); 758 759 int wordIndex; 760 int wordCount = RTFAttributes.attributes.length; 761 for(wordIndex = 0; wordIndex < wordCount; wordIndex++) { 762 RTFAttribute attr = RTFAttributes.attributes[wordIndex]; 763 if (attr.domain() == RTFAttribute.D_CHARACTER) 764 attr.setDefault(currentAttributes); 765 } 766 767 StyleConstants.setFontFamily(currentAttributes, defaultFontFamily); 768 currentAttributes.removeAttribute(StyleConstants.FontSize); 769 currentAttributes.removeAttribute(StyleConstants.Background); 770 currentAttributes.removeAttribute(StyleConstants.Foreground); 771 currentAttributes.removeAttribute(StyleConstants.LineSpacing); 772 currentAttributes.removeAttribute("characterStyle"); 773 } 774 775 public void writeTextElement(Element el) 776 throws IOException  777 { 778 updateCharacterAttributes(outputAttributes, el.getAttributes(), true); 779 780 if (el.isLeaf()) { 781 try { 782 el.getDocument().getText(el.getStartOffset(), 783 el.getEndOffset() - el.getStartOffset(), 784 this.workingSegment); 785 } catch (BadLocationException ble) { 786 787 ble.printStackTrace(); 788 throw new InternalError (ble.getMessage()); 789 } 790 writeText(this.workingSegment); 791 } else { 792 int sub_count = el.getElementCount(); 793 for(int idx = 0; idx < sub_count; idx ++) 794 writeTextElement(el.getElement(idx)); 795 } 796 } 797 798 public void writeText(Segment s) 799 throws IOException  800 { 801 int pos, end; 802 char[] array; 803 804 pos = s.offset; 805 end = pos + s.count; 806 array = s.array; 807 for( ; pos < end; pos ++) 808 writeCharacter(array[pos]); 809 } 810 811 public void writeText(String s) 812 throws IOException  813 { 814 int pos, end; 815 816 pos = 0; 817 end = s.length(); 818 for( ; pos < end; pos ++) 819 writeCharacter(s.charAt(pos)); 820 } 821 822 public void writeRawString(String str) 823 throws IOException  824 { 825 int strlen = str.length(); 826 for (int offset = 0; offset < strlen; offset ++) 827 outputStream.write((int)str.charAt(offset)); 828 } 829 830 public void writeControlWord(String keyword) 831 throws IOException  832 { 833 outputStream.write('\\'); 834 writeRawString(keyword); 835 afterKeyword = true; 836 } 837 838 public void writeControlWord(String keyword, int arg) 839 throws IOException  840 { 841 outputStream.write('\\'); 842 writeRawString(keyword); 843 writeRawString(String.valueOf(arg)); 844 afterKeyword = true; 845 } 846 847 public void writeBegingroup() 848 throws IOException  849 { 850 outputStream.write('{'); 851 afterKeyword = false; 852 } 853 854 public void writeEndgroup() 855 throws IOException  856 { 857 outputStream.write('}'); 858 afterKeyword = false; 859 } 860 861 public void writeCharacter(char ch) 862 throws IOException  863 { 864 866 if (ch == 0xA0) { 867 outputStream.write(0x5C); 868 outputStream.write(0x7E); 869 afterKeyword = false; 870 return; 871 } 872 873 if (ch == 0x09) { 874 writeControlWord("tab"); 875 return; 876 } 877 878 if (ch == 10 || ch == 13) { 879 880 return; 881 } 882 883 int b = convertCharacter(outputConversion, ch); 884 if (b == 0) { 885 886 int i; 887 for(i = 0; i < textKeywords.length; i++) { 888 if (textKeywords[i].character == ch) { 889 writeControlWord(textKeywords[i].keyword); 890 return; 891 } 892 } 893 896 898 String approximation = approximationForUnicode(ch); 899 if (approximation.length() != unicodeCount) { 900 unicodeCount = approximation.length(); 901 writeControlWord("uc", unicodeCount); 902 } 903 writeControlWord("u", (int)ch); 904 writeRawString(" "); 905 writeRawString(approximation); 906 afterKeyword = false; 907 return; 908 } 909 910 if (b > 127) { 911 int nybble; 912 outputStream.write('\\'); 913 outputStream.write('\''); 914 nybble = ( b & 0xF0 ) >>> 4; 915 outputStream.write(hexdigits[nybble]); 916 nybble = ( b & 0x0F ); 917 outputStream.write(hexdigits[nybble]); 918 afterKeyword = false; 919 return; 920 } 921 922 switch (b) { 923 case '}': 924 case '{': 925 case '\\': 926 outputStream.write(0x5C); 927 afterKeyword = false; 928 929 default: 930 if (afterKeyword) { 931 outputStream.write(0x20); 932 afterKeyword = false; 933 } 934 outputStream.write(b); 935 break; 936 } 937 } 938 939 String approximationForUnicode(char ch) 940 { 941 943 return "?"; 944 } 945 946 949 952 static int[] outputConversionFromTranslationTable(char[] table) 953 { 954 int[] conversion = new int[2 * table.length]; 955 956 int index; 957 958 for(index = 0; index < table.length; index ++) { 959 conversion[index * 2] = table[index]; 960 conversion[(index * 2) + 1] = index; 961 } 962 963 return conversion; 964 } 965 966 static int[] outputConversionForName(String name) 967 throws IOException  968 { 969 char[] table = (char[])RTFReader.getCharacterSet(name); 970 return outputConversionFromTranslationTable(table); 971 } 972 973 978 979 static protected int convertCharacter(int[] conversion, char ch) 980 { 981 int index; 982 983 for(index = 0; index < conversion.length; index += 2) { 984 if(conversion[index] == ch) 985 return conversion[index + 1]; 986 } 987 988 return 0; 989 } 990 991 } 992 | Popular Tags |