1 7 package javax.swing.text.rtf; 8 9 import java.lang.*; 10 import java.util.*; 11 import java.io.*; 12 import java.awt.Font ; 13 import java.awt.Color ; 14 15 import javax.swing.text.*; 16 17 31 class RTFReader extends RTFParser 32 { 33 34 StyledDocument target; 35 36 39 Dictionary parserState; 40 43 Destination rtfDestination; 44 45 MutableAttributeSet documentAttributes; 46 47 48 Dictionary fontTable; 49 50 Color [] colorTable; 51 52 Style[] characterStyles; 53 54 Style[] paragraphStyles; 55 56 Style[] sectionStyles; 57 58 60 int rtfversion; 61 62 64 boolean ignoreGroupIfUnknownKeyword; 65 66 69 int skippingCharacters; 70 71 static private Dictionary straightforwardAttributes; 72 static { 73 straightforwardAttributes = RTFAttributes.attributesByKeyword(); 74 } 75 76 private MockAttributeSet mockery; 77 78 79 81 static Dictionary textKeywords = null; 82 static { 83 textKeywords = new Hashtable(); 84 textKeywords.put("\\", "\\"); 85 textKeywords.put("{", "{"); 86 textKeywords.put("}", "}"); 87 textKeywords.put(" ", "\u00A0"); 88 textKeywords.put("~", "\u00A0"); 89 textKeywords.put("_", "\u2011"); 90 textKeywords.put("bullet", "\u2022"); 91 textKeywords.put("emdash", "\u2014"); 92 textKeywords.put("emspace", "\u2003"); 93 textKeywords.put("endash", "\u2013"); 94 textKeywords.put("enspace", "\u2002"); 95 textKeywords.put("ldblquote", "\u201C"); 96 textKeywords.put("lquote", "\u2018"); 97 textKeywords.put("ltrmark", "\u200E"); 98 textKeywords.put("rdblquote", "\u201D"); 99 textKeywords.put("rquote", "\u2019"); 100 textKeywords.put("rtlmark", "\u200F"); 101 textKeywords.put("tab", "\u0009"); 102 textKeywords.put("zwj", "\u200D"); 103 textKeywords.put("zwnj", "\u200C"); 104 105 107 textKeywords.put("-", "\u2027"); 108 } 109 110 111 static final String TabAlignmentKey = "tab_alignment"; 112 static final String TabLeaderKey = "tab_leader"; 113 114 static Dictionary characterSets; 115 static boolean useNeXTForAnsi = false; 116 static { 117 characterSets = new Hashtable(); 118 } 119 120 121 122 128 public RTFReader(StyledDocument destination) 129 { 130 int i; 131 132 target = destination; 133 parserState = new Hashtable(); 134 fontTable = new Hashtable(); 135 136 rtfversion = -1; 137 138 mockery = new MockAttributeSet (); 139 documentAttributes = new SimpleAttributeSet(); 140 } 141 142 147 public void handleBinaryBlob(byte[] data) 148 { 149 if (skippingCharacters > 0) { 150 151 skippingCharacters --; 152 return; 153 } 154 155 156 } 157 158 159 162 public void handleText(String text) 163 { 164 if (skippingCharacters > 0) { 165 if (skippingCharacters >= text.length()) { 166 skippingCharacters -= text.length(); 167 return; 168 } else { 169 text = text.substring(skippingCharacters); 170 skippingCharacters = 0; 171 } 172 } 173 174 if (rtfDestination != null) { 175 rtfDestination.handleText(text); 176 return; 177 } 178 179 warning("Text with no destination. oops."); 180 } 181 182 183 Color defaultColor() 184 { 185 return Color.black; 186 } 187 188 193 public void begingroup() 194 { 195 if (skippingCharacters > 0) { 196 197 skippingCharacters = 0; 198 } 199 200 202 Object oldSaveState = parserState.get("_savedState"); 203 if (oldSaveState != null) 204 parserState.remove("_savedState"); 205 Dictionary saveState = (Dictionary)((Hashtable)parserState).clone(); 206 if (oldSaveState != null) 207 saveState.put("_savedState", oldSaveState); 208 parserState.put("_savedState", saveState); 209 210 if (rtfDestination != null) 211 rtfDestination.begingroup(); 212 } 213 214 220 public void endgroup() 221 { 222 if (skippingCharacters > 0) { 223 224 skippingCharacters = 0; 225 } 226 227 Dictionary restoredState = (Dictionary)parserState.get("_savedState"); 228 Destination restoredDestination = (Destination)restoredState.get("dst"); 229 if (restoredDestination != rtfDestination) { 230 rtfDestination.close(); 231 rtfDestination = restoredDestination; 232 } 233 Dictionary oldParserState = parserState; 234 parserState = restoredState; 235 if (rtfDestination != null) 236 rtfDestination.endgroup(oldParserState); 237 } 238 239 protected void setRTFDestination(Destination newDestination) 240 { 241 243 Dictionary previousState = (Dictionary)parserState.get("_savedState"); 244 if (previousState != null) { 245 if (rtfDestination != previousState.get("dst")) { 246 warning("Warning, RTF destination overridden, invalid RTF."); 247 rtfDestination.close(); 248 } 249 } 250 rtfDestination = newDestination; 251 parserState.put("dst", rtfDestination); 252 } 253 254 259 public void close() 260 throws IOException 261 { 262 Enumeration docProps = documentAttributes.getAttributeNames(); 263 while(docProps.hasMoreElements()) { 264 Object propName = docProps.nextElement(); 265 target.putProperty(propName, 266 documentAttributes.getAttribute((String )propName)); 267 } 268 269 270 271 warning("RTF filter done."); 272 273 super.close(); 274 } 275 276 284 public boolean handleKeyword(String keyword) 285 { 286 Object item; 287 boolean ignoreGroupIfUnknownKeywordSave = ignoreGroupIfUnknownKeyword; 288 289 if (skippingCharacters > 0) { 290 skippingCharacters --; 291 return true; 292 } 293 294 ignoreGroupIfUnknownKeyword = false; 295 296 if ((item = textKeywords.get(keyword)) != null) { 297 handleText((String )item); 298 return true; 299 } 300 301 if (keyword.equals("fonttbl")) { 302 setRTFDestination(new FonttblDestination()); 303 return true; 304 } 305 306 if (keyword.equals("colortbl")) { 307 setRTFDestination(new ColortblDestination()); 308 return true; 309 } 310 311 if (keyword.equals("stylesheet")) { 312 setRTFDestination(new StylesheetDestination()); 313 return true; 314 } 315 316 if (keyword.equals("info")) { 317 setRTFDestination(new InfoDestination()); 318 return false; 319 } 320 321 if (keyword.equals("mac")) { 322 setCharacterSet("mac"); 323 return true; 324 } 325 326 if (keyword.equals("ansi")) { 327 if (useNeXTForAnsi) 328 setCharacterSet("NeXT"); 329 else 330 setCharacterSet("ansi"); 331 return true; 332 } 333 334 if (keyword.equals("next")) { 335 setCharacterSet("NeXT"); 336 return true; 337 } 338 339 if (keyword.equals("pc")) { 340 setCharacterSet("cpg437"); 341 return true; 342 } 343 344 if (keyword.equals("pca")) { 345 setCharacterSet("cpg850"); 346 return true; 347 } 348 349 if (keyword.equals("*")) { 350 ignoreGroupIfUnknownKeyword = true; 351 return true; 352 } 353 354 if (rtfDestination != null) { 355 if(rtfDestination.handleKeyword(keyword)) 356 return true; 357 } 358 359 360 361 362 if (keyword.equals("aftncn") || 363 keyword.equals("aftnsep") || 364 keyword.equals("aftnsepc") || 365 keyword.equals("annotation") || 366 keyword.equals("atnauthor") || 367 keyword.equals("atnicn") || 368 keyword.equals("atnid") || 369 keyword.equals("atnref") || 370 keyword.equals("atntime") || 371 keyword.equals("atrfend") || 372 keyword.equals("atrfstart") || 373 keyword.equals("bkmkend") || 374 keyword.equals("bkmkstart") || 375 keyword.equals("datafield") || 376 keyword.equals("do") || 377 keyword.equals("dptxbxtext") || 378 keyword.equals("falt") || 379 keyword.equals("field") || 380 keyword.equals("file") || 381 keyword.equals("filetbl") || 382 keyword.equals("fname") || 383 keyword.equals("fontemb") || 384 keyword.equals("fontfile") || 385 keyword.equals("footer") || 386 keyword.equals("footerf") || 387 keyword.equals("footerl") || 388 keyword.equals("footerr") || 389 keyword.equals("footnote") || 390 keyword.equals("ftncn") || 391 keyword.equals("ftnsep") || 392 keyword.equals("ftnsepc") || 393 keyword.equals("header") || 394 keyword.equals("headerf") || 395 keyword.equals("headerl") || 396 keyword.equals("headerr") || 397 keyword.equals("keycode") || 398 keyword.equals("nextfile") || 399 keyword.equals("object") || 400 keyword.equals("pict") || 401 keyword.equals("pn") || 402 keyword.equals("pnseclvl") || 403 keyword.equals("pntxtb") || 404 keyword.equals("pntxta") || 405 keyword.equals("revtbl") || 406 keyword.equals("rxe") || 407 keyword.equals("tc") || 408 keyword.equals("template") || 409 keyword.equals("txe") || 410 keyword.equals("xe")) { 411 ignoreGroupIfUnknownKeywordSave = true; 412 } 413 414 if (ignoreGroupIfUnknownKeywordSave) { 415 setRTFDestination(new DiscardingDestination()); 416 } 417 418 return false; 419 } 420 421 430 public boolean handleKeyword(String keyword, int parameter) 431 { 432 boolean ignoreGroupIfUnknownKeywordSave = ignoreGroupIfUnknownKeyword; 433 434 if (skippingCharacters > 0) { 435 skippingCharacters --; 436 return true; 437 } 438 439 ignoreGroupIfUnknownKeyword = false; 440 441 if (keyword.equals("uc")) { 442 443 parserState.put("UnicodeSkip", Integer.valueOf(parameter)); 444 return true; 445 } 446 if (keyword.equals("u")) { 447 if (parameter < 0) 448 parameter = parameter + 65536; 449 handleText((char)parameter); 450 Number skip = (Number )(parserState.get("UnicodeSkip")); 451 if (skip != null) { 452 skippingCharacters = skip.intValue(); 453 } else { 454 skippingCharacters = 1; 455 } 456 return true; 457 } 458 459 if (keyword.equals("rtf")) { 460 rtfversion = parameter; 461 setRTFDestination(new DocumentDestination()); 462 return true; 463 } 464 465 if (keyword.startsWith("NeXT") || 466 keyword.equals("private")) 467 ignoreGroupIfUnknownKeywordSave = true; 468 469 if (rtfDestination != null) { 470 if(rtfDestination.handleKeyword(keyword, parameter)) 471 return true; 472 } 473 474 475 476 if (ignoreGroupIfUnknownKeywordSave) { 477 setRTFDestination(new DiscardingDestination()); 478 } 479 480 return false; 481 } 482 483 private void setTargetAttribute(String name, Object value) 484 { 485 } 487 488 494 public void setCharacterSet(String name) 495 { 496 Object set; 497 498 try { 499 set = getCharacterSet(name); 500 } catch (Exception e) { 501 warning("Exception loading RTF character set \"" + name + "\": " + e); 502 set = null; 503 } 504 505 if (set != null) { 506 translationTable = (char[])set; 507 } else { 508 warning("Unknown RTF character set \"" + name + "\""); 509 if (!name.equals("ansi")) { 510 try { 511 translationTable = (char[])getCharacterSet("ansi"); 512 } catch (IOException e) { 513 throw new InternalError ("RTFReader: Unable to find character set resources (" + e + ")"); 514 } 515 } 516 } 517 518 setTargetAttribute(Constants.RTFCharacterSet, name); 519 } 520 521 523 public static void 524 defineCharacterSet(String name, char[] table) 525 { 526 if (table.length < 256) 527 throw new IllegalArgumentException ("Translation table must have 256 entries."); 528 characterSets.put(name, table); 529 } 530 531 537 public static Object 538 getCharacterSet(final String name) 539 throws IOException 540 { 541 char[] set; 542 543 set = (char [])characterSets.get(name); 544 if (set == null) { 545 InputStream charsetStream; 546 charsetStream = (InputStream)java.security.AccessController. 547 doPrivileged(new java.security.PrivilegedAction () { 548 public Object run() { 549 return RTFReader .class.getResourceAsStream 550 ("charsets/" + name + ".txt"); 551 } 552 }); 553 set = readCharset(charsetStream); 554 defineCharacterSet(name, set); 555 } 556 return set; 557 } 558 559 565 static char[] readCharset(InputStream strm) 566 throws IOException 567 { 568 char[] values = new char[256]; 569 int i; 570 StreamTokenizer in = new StreamTokenizer(new BufferedReader( 571 new InputStreamReader(strm, "ISO-8859-1"))); 572 573 in.eolIsSignificant(false); 574 in.commentChar('#'); 575 in.slashSlashComments(true); 576 in.slashStarComments(true); 577 578 i = 0; 579 while (i < 256) { 580 int ttype; 581 try { 582 ttype = in.nextToken(); 583 } catch (Exception e) { 584 throw new IOException("Unable to read from character set file (" + e + ")"); 585 } 586 if (ttype != in.TT_NUMBER) { 587 throw new IOException("Unexpected token in character set file"); 589 } 591 values[i] = (char)(in.nval); 592 i++; 593 } 594 595 return values; 596 } 597 598 static char[] readCharset(java.net.URL href) 599 throws IOException 600 { 601 return readCharset(href.openStream()); 602 } 603 604 610 interface Destination { 611 void handleBinaryBlob(byte[] data); 612 void handleText(String text); 613 boolean handleKeyword(String keyword); 614 boolean handleKeyword(String keyword, int parameter); 615 616 void begingroup(); 617 void endgroup(Dictionary oldState); 618 619 void close(); 620 } 621 622 625 class DiscardingDestination implements Destination 626 { 627 public void handleBinaryBlob(byte[] data) 628 { 629 630 } 631 632 public void handleText(String text) 633 { 634 635 } 636 637 public boolean handleKeyword(String text) 638 { 639 640 return true; 641 } 642 643 public boolean handleKeyword(String text, int parameter) 644 { 645 646 return true; 647 } 648 649 public void begingroup() 650 { 651 653 } 654 655 public void endgroup(Dictionary oldState) 656 { 657 658 } 659 660 public void close() 661 { 662 663 } 664 } 665 666 668 class FonttblDestination implements Destination 669 { 670 int nextFontNumber; 671 Object fontNumberKey = null; 672 String nextFontFamily; 673 674 public void handleBinaryBlob(byte[] data) 675 { } 676 677 public void handleText(String text) 678 { 679 int semicolon = text.indexOf(';'); 680 String fontName; 681 682 if (semicolon > -1) 683 fontName = text.substring(0, semicolon); 684 else 685 fontName = text; 686 687 688 689 690 if (nextFontNumber == -1 691 && fontNumberKey != null) { 692 fontName = fontTable.get(fontNumberKey) + fontName; 694 } else { 695 fontNumberKey = Integer.valueOf(nextFontNumber); 696 } 697 fontTable.put(fontNumberKey, fontName); 698 699 nextFontNumber = -1; 700 nextFontFamily = null; 701 return; 702 } 703 704 public boolean handleKeyword(String keyword) 705 { 706 if (keyword.charAt(0) == 'f') { 707 nextFontFamily = keyword.substring(1); 708 return true; 709 } 710 711 return false; 712 } 713 714 public boolean handleKeyword(String keyword, int parameter) 715 { 716 if (keyword.equals("f")) { 717 nextFontNumber = parameter; 718 return true; 719 } 720 721 return false; 722 } 723 724 725 public void begingroup() {} 726 public void endgroup(Dictionary oldState) {} 727 728 730 public void close() 731 { 732 Enumeration nums = fontTable.keys(); 733 warning("Done reading font table."); 734 while(nums.hasMoreElements()) { 735 Integer num = (Integer )nums.nextElement(); 736 warning("Number " + num + ": " + fontTable.get(num)); 737 } 738 } 739 } 740 741 743 class ColortblDestination implements Destination 744 { 745 int red, green, blue; 746 Vector proTemTable; 747 748 public ColortblDestination() 749 { 750 red = 0; 751 green = 0; 752 blue = 0; 753 proTemTable = new Vector(); 754 } 755 756 public void handleText(String text) 757 { 758 int index = 0; 759 760 for (index = 0; index < text.length(); index ++) { 761 if (text.charAt(index) == ';') { 762 Color newColor; 763 newColor = new Color (red, green, blue); 764 proTemTable.addElement(newColor); 765 } 766 } 767 } 768 769 public void close() 770 { 771 int count = proTemTable.size(); 772 warning("Done reading color table, " + count + " entries."); 773 colorTable = new Color [count]; 774 proTemTable.copyInto(colorTable); 775 } 776 777 public boolean handleKeyword(String keyword, int parameter) 778 { 779 if (keyword.equals("red")) 780 red = parameter; 781 else if (keyword.equals("green")) 782 green = parameter; 783 else if (keyword.equals("blue")) 784 blue = parameter; 785 else 786 return false; 787 788 return true; 789 } 790 791 792 public boolean handleKeyword(String keyword) { return false; } 793 794 795 public void begingroup() {} 796 public void endgroup(Dictionary oldState) {} 797 798 799 public void handleBinaryBlob(byte[] data) {} 800 } 801 802 804 class StylesheetDestination 805 extends DiscardingDestination 806 implements Destination 807 { 808 Dictionary definedStyles; 809 810 public StylesheetDestination() 811 { 812 definedStyles = new Hashtable(); 813 } 814 815 public void begingroup() 816 { 817 setRTFDestination(new StyleDefiningDestination()); 818 } 819 820 public void close() 821 { 822 Vector chrStyles, pgfStyles, secStyles; 823 chrStyles = new Vector(); 824 pgfStyles = new Vector(); 825 secStyles = new Vector(); 826 Enumeration styles = definedStyles.elements(); 827 while(styles.hasMoreElements()) { 828 StyleDefiningDestination style; 829 Style defined; 830 style = (StyleDefiningDestination)styles.nextElement(); 831 defined = style.realize(); 832 warning("Style "+style.number+" ("+style.styleName+"): "+defined); 833 String stype = (String )defined.getAttribute(Constants.StyleType); 834 Vector toSet; 835 if (stype.equals(Constants.STSection)) { 836 toSet = secStyles; 837 } else if (stype.equals(Constants.STCharacter)) { 838 toSet = chrStyles; 839 } else { 840 toSet = pgfStyles; 841 } 842 if (toSet.size() <= style.number) 843 toSet.setSize(style.number + 1); 844 toSet.setElementAt(defined, style.number); 845 } 846 if (!(chrStyles.isEmpty())) { 847 Style[] styleArray = new Style[chrStyles.size()]; 848 chrStyles.copyInto(styleArray); 849 characterStyles = styleArray; 850 } 851 if (!(pgfStyles.isEmpty())) { 852 Style[] styleArray = new Style[pgfStyles.size()]; 853 pgfStyles.copyInto(styleArray); 854 paragraphStyles = styleArray; 855 } 856 if (!(secStyles.isEmpty())) { 857 Style[] styleArray = new Style[secStyles.size()]; 858 secStyles.copyInto(styleArray); 859 sectionStyles = styleArray; 860 } 861 862 880 } 881 882 883 class StyleDefiningDestination 884 extends AttributeTrackingDestination 885 implements Destination 886 { 887 final int STYLENUMBER_NONE = 222; 888 boolean additive; 889 boolean characterStyle; 890 boolean sectionStyle; 891 public String styleName; 892 public int number; 893 int basedOn; 894 int nextStyle; 895 boolean hidden; 896 897 Style realizedStyle; 898 899 public StyleDefiningDestination() 900 { 901 additive = false; 902 characterStyle = false; 903 sectionStyle = false; 904 styleName = null; 905 number = 0; 906 basedOn = STYLENUMBER_NONE; 907 nextStyle = STYLENUMBER_NONE; 908 hidden = false; 909 } 910 911 public void handleText(String text) 912 { 913 if (styleName != null) 914 styleName = styleName + text; 915 else 916 styleName = text; 917 } 918 919 public void close() { 920 int semicolon = (styleName == null) ? 0 : styleName.indexOf(';'); 921 if (semicolon > 0) 922 styleName = styleName.substring(0, semicolon); 923 definedStyles.put(Integer.valueOf(number), this); 924 super.close(); 925 } 926 927 public boolean handleKeyword(String keyword) 928 { 929 if (keyword.equals("additive")) { 930 additive = true; 931 return true; 932 } 933 if (keyword.equals("shidden")) { 934 hidden = true; 935 return true; 936 } 937 return super.handleKeyword(keyword); 938 } 939 940 public boolean handleKeyword(String keyword, int parameter) 941 { 942 if (keyword.equals("s")) { 943 characterStyle = false; 944 sectionStyle = false; 945 number = parameter; 946 } else if (keyword.equals("cs")) { 947 characterStyle = true; 948 sectionStyle = false; 949 number = parameter; 950 } else if (keyword.equals("ds")) { 951 characterStyle = false; 952 sectionStyle = true; 953 number = parameter; 954 } else if (keyword.equals("sbasedon")) { 955 basedOn = parameter; 956 } else if (keyword.equals("snext")) { 957 nextStyle = parameter; 958 } else { 959 return super.handleKeyword(keyword, parameter); 960 } 961 return true; 962 } 963 964 public Style realize() 965 { 966 Style basis = null; 967 Style next = null; 968 969 if (realizedStyle != null) 970 return realizedStyle; 971 972 if (basedOn != STYLENUMBER_NONE) { 973 StyleDefiningDestination styleDest; 974 styleDest = (StyleDefiningDestination)definedStyles.get(Integer.valueOf(basedOn)); 975 if (styleDest != null && styleDest != this) { 976 basis = styleDest.realize(); 977 } 978 } 979 980 983 realizedStyle = target.addStyle(styleName, basis); 984 985 if (characterStyle) { 986 realizedStyle.addAttributes(currentTextAttributes()); 987 realizedStyle.addAttribute(Constants.StyleType, 988 Constants.STCharacter); 989 } else if (sectionStyle) { 990 realizedStyle.addAttributes(currentSectionAttributes()); 991 realizedStyle.addAttribute(Constants.StyleType, 992 Constants.STSection); 993 } else { 994 realizedStyle.addAttributes(currentParagraphAttributes()); 995 realizedStyle.addAttribute(Constants.StyleType, 996 Constants.STParagraph); 997 } 998 999 if (nextStyle != STYLENUMBER_NONE) { 1000 StyleDefiningDestination styleDest; 1001 styleDest = (StyleDefiningDestination)definedStyles.get(Integer.valueOf(nextStyle)); 1002 if (styleDest != null) { 1003 next = styleDest.realize(); 1004 } 1005 } 1006 1007 if (next != null) 1008 realizedStyle.addAttribute(Constants.StyleNext, next); 1009 realizedStyle.addAttribute(Constants.StyleAdditive, 1010 Boolean.valueOf(additive)); 1011 realizedStyle.addAttribute(Constants.StyleHidden, 1012 Boolean.valueOf(hidden)); 1013 1014 return realizedStyle; 1015 } 1016 } 1017} 1018 1019 1021class InfoDestination 1022 extends DiscardingDestination 1023 implements Destination 1024{ 1025} 1026 1027 1032abstract class AttributeTrackingDestination implements Destination 1033{ 1034 1036 MutableAttributeSet characterAttributes; 1037 1039 MutableAttributeSet paragraphAttributes; 1040 1042 MutableAttributeSet sectionAttributes; 1043 1044 public AttributeTrackingDestination() 1045 { 1046 characterAttributes = rootCharacterAttributes(); 1047 parserState.put("chr", characterAttributes); 1048 paragraphAttributes = rootParagraphAttributes(); 1049 parserState.put("pgf", paragraphAttributes); 1050 sectionAttributes = rootSectionAttributes(); 1051 parserState.put("sec", sectionAttributes); 1052 } 1053 1054 abstract public void handleText(String text); 1055 1056 public void handleBinaryBlob(byte[] data) 1057 { 1058 1061 warning("Unexpected binary data in RTF file."); 1062 } 1063 1064 public void begingroup() 1065 { 1066 AttributeSet characterParent = currentTextAttributes(); 1067 AttributeSet paragraphParent = currentParagraphAttributes(); 1068 AttributeSet sectionParent = currentSectionAttributes(); 1069 1070 1074 1075 1076 characterAttributes = new SimpleAttributeSet(); 1077 characterAttributes.addAttributes(characterParent); 1078 parserState.put("chr", characterAttributes); 1079 1080 paragraphAttributes = new SimpleAttributeSet(); 1081 paragraphAttributes.addAttributes(paragraphParent); 1082 parserState.put("pgf", paragraphAttributes); 1083 1084 sectionAttributes = new SimpleAttributeSet(); 1085 sectionAttributes.addAttributes(sectionParent); 1086 parserState.put("sec", sectionAttributes); 1087 } 1088 1089 public void endgroup(Dictionary oldState) 1090 { 1091 characterAttributes = (MutableAttributeSet)parserState.get("chr"); 1092 paragraphAttributes = (MutableAttributeSet)parserState.get("pgf"); 1093 sectionAttributes = (MutableAttributeSet)parserState.get("sec"); 1094 } 1095 1096 public void close() 1097 { 1098 } 1099 1100 public boolean handleKeyword(String keyword) 1101 { 1102 if (keyword.equals("ulnone")) { 1103 return handleKeyword("ul", 0); 1104 } 1105 1106 { 1107 Object item = straightforwardAttributes.get(keyword); 1108 if (item != null) { 1109 RTFAttribute attr = (RTFAttribute )item; 1110 boolean ok; 1111 1112 switch(attr.domain()) { 1113 case RTFAttribute.D_CHARACTER: 1114 ok = attr.set(characterAttributes); 1115 break; 1116 case RTFAttribute.D_PARAGRAPH: 1117 ok = attr.set(paragraphAttributes); 1118 break; 1119 case RTFAttribute.D_SECTION: 1120 ok = attr.set(sectionAttributes); 1121 break; 1122 case RTFAttribute.D_META: 1123 mockery.backing = parserState; 1124 ok = attr.set(mockery); 1125 mockery.backing = null; 1126 break; 1127 case RTFAttribute.D_DOCUMENT: 1128 ok = attr.set(documentAttributes); 1129 break; 1130 default: 1131 1132 ok = false; 1133 break; 1134 } 1135 if (ok) 1136 return true; 1137 } 1138 } 1139 1140 1141 if (keyword.equals("plain")) { 1142 resetCharacterAttributes(); 1143 return true; 1144 } 1145 1146 if (keyword.equals("pard")) { 1147 resetParagraphAttributes(); 1148 return true; 1149 } 1150 1151 if (keyword.equals("sectd")) { 1152 resetSectionAttributes(); 1153 return true; 1154 } 1155 1156 return false; 1157 } 1158 1159 public boolean handleKeyword(String keyword, int parameter) 1160 { 1161 boolean booleanParameter = (parameter != 0); 1162 1163 if (keyword.equals("fc")) 1164 keyword = "cf"; 1165 1166 if (keyword.equals("f")) { 1167 parserState.put(keyword, Integer.valueOf(parameter)); 1168 return true; 1169 } 1170 if (keyword.equals("cf")) { 1171 parserState.put(keyword, Integer.valueOf(parameter)); 1172 return true; 1173 } 1174 1175 { 1176 Object item = straightforwardAttributes.get(keyword); 1177 if (item != null) { 1178 RTFAttribute attr = (RTFAttribute )item; 1179 boolean ok; 1180 1181 switch(attr.domain()) { 1182 case RTFAttribute.D_CHARACTER: 1183 ok = attr.set(characterAttributes, parameter); 1184 break; 1185 case RTFAttribute.D_PARAGRAPH: 1186 ok = attr.set(paragraphAttributes, parameter); 1187 break; 1188 case RTFAttribute.D_SECTION: 1189 ok = attr.set(sectionAttributes, parameter); 1190 break; 1191 case RTFAttribute.D_META: 1192 mockery.backing = parserState; 1193 ok = attr.set(mockery, parameter); 1194 mockery.backing = null; 1195 break; 1196 case RTFAttribute.D_DOCUMENT: 1197 ok = attr.set(documentAttributes, parameter); 1198 break; 1199 default: 1200 1201 ok = false; 1202 break; 1203 } 1204 if (ok) 1205 return true; 1206 } 1207 } 1208 1209 if (keyword.equals("fs")) { 1210 StyleConstants.setFontSize(characterAttributes, (parameter / 2)); 1211 return true; 1212 } 1213 1214 1215 1216 if (keyword.equals("sl")) { 1217 if (parameter == 1000) { 1218 characterAttributes.removeAttribute(StyleConstants.LineSpacing); 1219 } else { 1220 1224 StyleConstants.setLineSpacing(characterAttributes, 1225 parameter / 20f); 1226 } 1227 return true; 1228 } 1229 1230 1231 1232 if (keyword.equals("tx") || keyword.equals("tb")) { 1233 float tabPosition = parameter / 20f; 1234 int tabAlignment, tabLeader; 1235 Number item; 1236 1237 tabAlignment = TabStop.ALIGN_LEFT; 1238 item = (Number )(parserState.get("tab_alignment")); 1239 if (item != null) 1240 tabAlignment = item.intValue(); 1241 tabLeader = TabStop.LEAD_NONE; 1242 item = (Number )(parserState.get("tab_leader")); 1243 if (item != null) 1244 tabLeader = item.intValue(); 1245 if (keyword.equals("tb")) 1246 tabAlignment = TabStop.ALIGN_BAR; 1247 1248 parserState.remove("tab_alignment"); 1249 parserState.remove("tab_leader"); 1250 1251 TabStop newStop = new TabStop(tabPosition, tabAlignment, tabLeader); 1252 Dictionary tabs; 1253 Integer stopCount; 1254 1255 tabs = (Dictionary)parserState.get("_tabs"); 1256 if (tabs == null) { 1257 tabs = new Hashtable(); 1258 parserState.put("_tabs", tabs); 1259 stopCount = Integer.valueOf(1); 1260 } else { 1261 stopCount = (Integer )tabs.get("stop count"); 1262 stopCount = Integer.valueOf(1 + stopCount.intValue()); 1263 } 1264 tabs.put(stopCount, newStop); 1265 tabs.put("stop count", stopCount); 1266 parserState.remove("_tabs_immutable"); 1267 1268 return true; 1269 } 1270 1271 if (keyword.equals("s") && 1272 paragraphStyles != null) { 1273 parserState.put("paragraphStyle", paragraphStyles[parameter]); 1274 return true; 1275 } 1276 1277 if (keyword.equals("cs") && 1278 characterStyles != null) { 1279 parserState.put("characterStyle", characterStyles[parameter]); 1280 return true; 1281 } 1282 1283 if (keyword.equals("ds") && 1284 sectionStyles != null) { 1285 parserState.put("sectionStyle", sectionStyles[parameter]); 1286 return true; 1287 } 1288 1289 return false; 1290 } 1291 1292 1294 protected MutableAttributeSet rootCharacterAttributes() 1295 { 1296 MutableAttributeSet set = new SimpleAttributeSet(); 1297 1298 1299 1300 StyleConstants.setItalic(set, false); 1301 StyleConstants.setBold(set, false); 1302 StyleConstants.setUnderline(set, false); 1303 StyleConstants.setForeground(set, defaultColor()); 1304 1305 return set; 1306 } 1307 1308 1310 protected MutableAttributeSet rootParagraphAttributes() 1311 { 1312 MutableAttributeSet set = new SimpleAttributeSet(); 1313 1314 StyleConstants.setLeftIndent(set, 0f); 1315 StyleConstants.setRightIndent(set, 0f); 1316 StyleConstants.setFirstLineIndent(set, 0f); 1317 1318 1319 set.setResolveParent(target.getStyle(StyleContext.DEFAULT_STYLE)); 1320 1321 return set; 1322 } 1323 1324 1326 protected MutableAttributeSet rootSectionAttributes() 1327 { 1328 MutableAttributeSet set = new SimpleAttributeSet(); 1329 1330 return set; 1331 } 1332 1333 1339 MutableAttributeSet currentTextAttributes() 1340 { 1341 MutableAttributeSet attributes = 1342 new SimpleAttributeSet(characterAttributes); 1343 Integer fontnum; 1344 Integer stateItem; 1345 1346 1347 1350 fontnum = (Integer )parserState.get("f"); 1351 1352 String fontFamily; 1353 if (fontnum != null) 1354 fontFamily = (String )fontTable.get(fontnum); 1355 else 1356 fontFamily = null; 1357 if (fontFamily != null) 1358 StyleConstants.setFontFamily(attributes, fontFamily); 1359 else 1360 attributes.removeAttribute(StyleConstants.FontFamily); 1361 1362 if (colorTable != null) { 1363 stateItem = (Integer )parserState.get("cf"); 1364 if (stateItem != null) { 1365 Color fg = colorTable[stateItem.intValue()]; 1366 StyleConstants.setForeground(attributes, fg); 1367 } else { 1368 1369 attributes.removeAttribute(StyleConstants.Foreground); 1370 } 1371 } 1372 1373 if (colorTable != null) { 1374 stateItem = (Integer )parserState.get("cb"); 1375 if (stateItem != null) { 1376 Color bg = colorTable[stateItem.intValue()]; 1377 attributes.addAttribute(StyleConstants.Background, 1378 bg); 1379 } else { 1380 1381 attributes.removeAttribute(StyleConstants.Background); 1382 } 1383 } 1384 1385 Style characterStyle = (Style)parserState.get("characterStyle"); 1386 if (characterStyle != null) 1387 attributes.setResolveParent(characterStyle); 1388 1389 1390 1391 return attributes; 1392 } 1393 1394 1401 MutableAttributeSet currentParagraphAttributes() 1402 { 1403 1404 MutableAttributeSet bld = new SimpleAttributeSet(paragraphAttributes); 1405 1406 Integer stateItem; 1407 1408 1409 TabStop tabs[]; 1410 1411 tabs = (TabStop[])parserState.get("_tabs_immutable"); 1412 if (tabs == null) { 1413 Dictionary workingTabs = (Dictionary)parserState.get("_tabs"); 1414 if (workingTabs != null) { 1415 int count = ((Integer )workingTabs.get("stop count")).intValue(); 1416 tabs = new TabStop[count]; 1417 for (int ix = 1; ix <= count; ix ++) 1418 tabs[ix-1] = (TabStop)workingTabs.get(Integer.valueOf(ix)); 1419 parserState.put("_tabs_immutable", tabs); 1420 } 1421 } 1422 if (tabs != null) 1423 bld.addAttribute(Constants.Tabs, tabs); 1424 1425 Style paragraphStyle = (Style)parserState.get("paragraphStyle"); 1426 if (paragraphStyle != null) 1427 bld.setResolveParent(paragraphStyle); 1428 1429 return bld; 1430 } 1431 1432 1438 public AttributeSet currentSectionAttributes() 1439 { 1440 MutableAttributeSet attributes = new SimpleAttributeSet(sectionAttributes); 1441 1442 Style sectionStyle = (Style)parserState.get("sectionStyle"); 1443 if (sectionStyle != null) 1444 attributes.setResolveParent(sectionStyle); 1445 1446 return attributes; 1447 } 1448 1449 1452 protected void resetCharacterAttributes() 1453 { 1454 handleKeyword("f", 0); 1455 handleKeyword("cf", 0); 1456 1457 handleKeyword("fs", 24); 1458 1459 Enumeration attributes = straightforwardAttributes.elements(); 1460 while(attributes.hasMoreElements()) { 1461 RTFAttribute attr = (RTFAttribute )attributes.nextElement(); 1462 if (attr.domain() == RTFAttribute.D_CHARACTER) 1463 attr.setDefault(characterAttributes); 1464 } 1465 1466 handleKeyword("sl", 1000); 1467 1468 parserState.remove("characterStyle"); 1469 } 1470 1471 1474 protected void resetParagraphAttributes() 1475 { 1476 parserState.remove("_tabs"); 1477 parserState.remove("_tabs_immutable"); 1478 parserState.remove("paragraphStyle"); 1479 1480 StyleConstants.setAlignment(paragraphAttributes, 1481 StyleConstants.ALIGN_LEFT); 1482 1483 Enumeration attributes = straightforwardAttributes.elements(); 1484 while(attributes.hasMoreElements()) { 1485 RTFAttribute attr = (RTFAttribute )attributes.nextElement(); 1486 if (attr.domain() == RTFAttribute.D_PARAGRAPH) 1487 attr.setDefault(characterAttributes); 1488 } 1489 } 1490 1491 1494 protected void resetSectionAttributes() 1495 { 1496 Enumeration attributes = straightforwardAttributes.elements(); 1497 while(attributes.hasMoreElements()) { 1498 RTFAttribute attr = (RTFAttribute )attributes.nextElement(); 1499 if (attr.domain() == RTFAttribute.D_SECTION) 1500 attr.setDefault(characterAttributes); 1501 } 1502 1503 parserState.remove("sectionStyle"); 1504 } 1505} 1506 1507 1516abstract class TextHandlingDestination 1517 extends AttributeTrackingDestination 1518 implements Destination 1519{ 1520 1522 boolean inParagraph; 1523 1524 public TextHandlingDestination() 1525 { 1526 super(); 1527 inParagraph = false; 1528 } 1529 1530 public void handleText(String text) 1531 { 1532 if (! inParagraph) 1533 beginParagraph(); 1534 1535 deliverText(text, currentTextAttributes()); 1536 } 1537 1538 abstract void deliverText(String text, AttributeSet characterAttributes); 1539 1540 public void close() 1541 { 1542 if (inParagraph) 1543 endParagraph(); 1544 1545 super.close(); 1546 } 1547 1548 public boolean handleKeyword(String keyword) 1549 { 1550 if (keyword.equals("\r") || keyword.equals("\n")) { 1551 keyword = "par"; 1552 } 1553 1554 if (keyword.equals("par")) { 1555 endParagraph(); 1557 return true; 1558 } 1559 1560 if (keyword.equals("sect")) { 1561 endSection(); 1563 return true; 1564 } 1565 1566 return super.handleKeyword(keyword); 1567 } 1568 1569 protected void beginParagraph() 1570 { 1571 inParagraph = true; 1572 } 1573 1574 protected void endParagraph() 1575 { 1576 AttributeSet pgfAttributes = currentParagraphAttributes(); 1577 AttributeSet chrAttributes = currentTextAttributes(); 1578 finishParagraph(pgfAttributes, chrAttributes); 1579 inParagraph = false; 1580 } 1581 1582 abstract void finishParagraph(AttributeSet pgfA, AttributeSet chrA); 1583 1584 abstract void endSection(); 1585} 1586 1587 1592class DocumentDestination 1593 extends TextHandlingDestination 1594 implements Destination 1595{ 1596 public void deliverText(String text, AttributeSet characterAttributes) 1597 { 1598 try { 1599 target.insertString(target.getLength(), 1600 text, 1601 currentTextAttributes()); 1602 } catch (BadLocationException ble) { 1603 1604 1605 throw new InternalError (ble.getMessage()); 1606 } 1607 } 1608 1609 public void finishParagraph(AttributeSet pgfAttributes, 1610 AttributeSet chrAttributes) 1611 { 1612 int pgfEndPosition = target.getLength(); 1613 try { 1614 target.insertString(pgfEndPosition, "\n", chrAttributes); 1615 target.setParagraphAttributes(pgfEndPosition, 1, pgfAttributes, true); 1616 } catch (BadLocationException ble) { 1617 1618 1619 throw new InternalError (ble.getMessage()); 1620 } 1621 } 1622 1623 public void endSection() 1624 { 1625 1626 } 1627} 1628 1629} 1630 1631 1632 | Popular Tags |