?? rtfgenerator.java
字號:
RTFAttribute attr = words[wordIndex]; if (attr.domain() == domain) checkControlWord(currentAttributes, newAttributes, attr); }}void updateSectionAttributes(MutableAttributeSet current, AttributeSet newAttributes, boolean emitStyleChanges) throws IOException{ if (emitStyleChanges) { Object oldStyle = current.getAttribute("sectionStyle"); Object newStyle = findStyleNumber(newAttributes, Constants.STSection); if (oldStyle != newStyle) { if (oldStyle != null) { resetSectionAttributes(current); } if (newStyle != null) { writeControlWord("ds", ((Integer)newStyle).intValue()); current.addAttribute("sectionStyle", newStyle); } else { current.removeAttribute("sectionStyle"); } } } checkControlWords(current, newAttributes, RTFAttributes.attributes, RTFAttribute.D_SECTION);}protected void resetSectionAttributes(MutableAttributeSet currentAttributes) throws IOException{ writeControlWord("sectd"); int wordIndex; int wordCount = RTFAttributes.attributes.length; for(wordIndex = 0; wordIndex < wordCount; wordIndex++) { RTFAttribute attr = RTFAttributes.attributes[wordIndex]; if (attr.domain() == RTFAttribute.D_SECTION) attr.setDefault(currentAttributes); } currentAttributes.removeAttribute("sectionStyle");} void updateParagraphAttributes(MutableAttributeSet current, AttributeSet newAttributes, boolean emitStyleChanges) throws IOException{ Object parm; Object oldStyle, newStyle; /* The only way to get rid of tabs or styles is with the \pard keyword, emitted by resetParagraphAttributes(). Ideally we should avoid emitting \pard if the new paragraph's tabs are a superset of the old paragraph's tabs. */ if (emitStyleChanges) { oldStyle = current.getAttribute("paragraphStyle"); newStyle = findStyleNumber(newAttributes, Constants.STParagraph); if (oldStyle != newStyle) { if (oldStyle != null) { resetParagraphAttributes(current); oldStyle = null; } } } else { oldStyle = null; newStyle = null; } Object oldTabs = current.getAttribute(Constants.Tabs); Object newTabs = newAttributes.getAttribute(Constants.Tabs); if (oldTabs != newTabs) { if (oldTabs != null) { resetParagraphAttributes(current); oldTabs = null; oldStyle = null; } } if (oldStyle != newStyle && newStyle != null) { writeControlWord("s", ((Integer)newStyle).intValue()); current.addAttribute("paragraphStyle", newStyle); } checkControlWords(current, newAttributes, RTFAttributes.attributes, RTFAttribute.D_PARAGRAPH); if (oldTabs != newTabs && newTabs != null) { TabStop tabs[] = (TabStop[])newTabs; int index; for(index = 0; index < tabs.length; index ++) { TabStop tab = tabs[index]; switch (tab.getAlignment()) { case TabStop.ALIGN_LEFT: case TabStop.ALIGN_BAR: break; case TabStop.ALIGN_RIGHT: writeControlWord("tqr"); break; case TabStop.ALIGN_CENTER: writeControlWord("tqc"); break; case TabStop.ALIGN_DECIMAL: writeControlWord("tqdec"); break; } switch (tab.getLeader()) { case TabStop.LEAD_NONE: break; case TabStop.LEAD_DOTS: writeControlWord("tldot"); break; case TabStop.LEAD_HYPHENS: writeControlWord("tlhyph"); break; case TabStop.LEAD_UNDERLINE: writeControlWord("tlul"); break; case TabStop.LEAD_THICKLINE: writeControlWord("tlth"); break; case TabStop.LEAD_EQUALS: writeControlWord("tleq"); break; } int twips = Math.round(20f * tab.getPosition()); if (tab.getAlignment() == TabStop.ALIGN_BAR) { writeControlWord("tb", twips); } else { writeControlWord("tx", twips); } } current.addAttribute(Constants.Tabs, tabs); }}public void writeParagraphElement(Element el) throws IOException{ updateParagraphAttributes(outputAttributes, el.getAttributes(), true); int sub_count = el.getElementCount(); for(int idx = 0; idx < sub_count; idx ++) { writeTextElement(el.getElement(idx)); } writeControlWord("par"); writeLineBreak(); /* makes the raw file more readable */}/* debugging. TODO: remove.private static String tabdump(Object tso){ String buf; int i; if (tso == null) return "[none]"; TabStop[] ts = (TabStop[])tso; buf = "["; for(i = 0; i < ts.length; i++) { buf = buf + ts[i].toString(); if ((i+1) < ts.length) buf = buf + ","; } return buf + "]";}*/protected void resetParagraphAttributes(MutableAttributeSet currentAttributes) throws IOException{ writeControlWord("pard"); currentAttributes.addAttribute(StyleConstants.Alignment, Zero); int wordIndex; int wordCount = RTFAttributes.attributes.length; for(wordIndex = 0; wordIndex < wordCount; wordIndex++) { RTFAttribute attr = RTFAttributes.attributes[wordIndex]; if (attr.domain() == RTFAttribute.D_PARAGRAPH) attr.setDefault(currentAttributes); } currentAttributes.removeAttribute("paragraphStyle"); currentAttributes.removeAttribute(Constants.Tabs);} void updateCharacterAttributes(MutableAttributeSet current, AttributeSet newAttributes, boolean updateStyleChanges) throws IOException{ Object parm; if (updateStyleChanges) { Object oldStyle = current.getAttribute("characterStyle"); Object newStyle = findStyleNumber(newAttributes, Constants.STCharacter); if (oldStyle != newStyle) { if (oldStyle != null) { resetCharacterAttributes(current); } if (newStyle != null) { writeControlWord("cs", ((Integer)newStyle).intValue()); current.addAttribute("characterStyle", newStyle); } else { current.removeAttribute("characterStyle"); } } } if ((parm = attrDiff(current, newAttributes, StyleConstants.FontFamily, null)) != null) { Number fontNum = (Number)fontTable.get(parm); writeControlWord("f", fontNum.intValue()); } checkNumericControlWord(current, newAttributes, StyleConstants.FontSize, "fs", defaultFontSize, 2f); checkControlWords(current, newAttributes, RTFAttributes.attributes, RTFAttribute.D_CHARACTER); checkNumericControlWord(current, newAttributes, StyleConstants.LineSpacing, "sl", 0, 20f); /* TODO: sl wackiness */ if ((parm = attrDiff(current, newAttributes, StyleConstants.Background, MagicToken)) != null) { int colorNum; if (parm == MagicToken) colorNum = 0; else colorNum = ((Number)colorTable.get(parm)).intValue(); writeControlWord("cb", colorNum); } if ((parm = attrDiff(current, newAttributes, StyleConstants.Foreground, null)) != null) { int colorNum; if (parm == MagicToken) colorNum = 0; else colorNum = ((Number)colorTable.get(parm)).intValue(); writeControlWord("cf", colorNum); }}protected void resetCharacterAttributes(MutableAttributeSet currentAttributes) throws IOException{ writeControlWord("plain"); int wordIndex; int wordCount = RTFAttributes.attributes.length; for(wordIndex = 0; wordIndex < wordCount; wordIndex++) { RTFAttribute attr = RTFAttributes.attributes[wordIndex]; if (attr.domain() == RTFAttribute.D_CHARACTER) attr.setDefault(currentAttributes); } StyleConstants.setFontFamily(currentAttributes, defaultFontFamily); currentAttributes.removeAttribute(StyleConstants.FontSize); /* =default */ currentAttributes.removeAttribute(StyleConstants.Background); currentAttributes.removeAttribute(StyleConstants.Foreground); currentAttributes.removeAttribute(StyleConstants.LineSpacing); currentAttributes.removeAttribute("characterStyle");} public void writeTextElement(Element el) throws IOException{ updateCharacterAttributes(outputAttributes, el.getAttributes(), true); if (el.isLeaf()) { try { el.getDocument().getText(el.getStartOffset(), el.getEndOffset() - el.getStartOffset(), this.workingSegment); } catch (BadLocationException ble) { /* TODO is this the correct error to raise? */ ble.printStackTrace(); throw new InternalError(ble.getMessage()); } writeText(this.workingSegment); } else { int sub_count = el.getElementCount(); for(int idx = 0; idx < sub_count; idx ++) writeTextElement(el.getElement(idx)); }}public void writeText(Segment s) throws IOException{ int pos, end; char[] array; pos = s.offset; end = pos + s.count; array = s.array; for( ; pos < end; pos ++) writeCharacter(array[pos]);}public void writeText(String s) throws IOException{ int pos, end; pos = 0; end = s.length(); for( ; pos < end; pos ++) writeCharacter(s.charAt(pos));}public void writeRawString(String str) throws IOException{ int strlen = str.length(); for (int offset = 0; offset < strlen; offset ++) outputStream.write((int)str.charAt(offset));}public void writeControlWord(String keyword) throws IOException{ outputStream.write('\\'); writeRawString(keyword); afterKeyword = true;}public void writeControlWord(String keyword, int arg) throws IOException{ outputStream.write('\\'); writeRawString(keyword); writeRawString(String.valueOf(arg)); /* TODO: correct in all cases? */ afterKeyword = true;} public void writeBegingroup() throws IOException{ outputStream.write('{'); afterKeyword = false;}public void writeEndgroup() throws IOException{ outputStream.write('}'); afterKeyword = false;}public void writeCharacter(char ch) throws IOException{ /* Nonbreaking space is in most RTF encodings, but the keyword is preferable; same goes for tabs */ if (ch == 0xA0) { /* nonbreaking space */ outputStream.write(0x5C); /* backslash */ outputStream.write(0x7E); /* tilde */ afterKeyword = false; /* non-alpha keywords are self-terminating */ return; } if (ch == 0x09) { /* horizontal tab */ writeControlWord("tab"); return; } if (ch == 10 || ch == 13) { /* newline / paragraph */ /* ignore CRs, we'll write a paragraph element soon enough */ return; } int b = convertCharacter(outputConversion, ch); if (b == 0) { /* Unicode characters which have corresponding RTF keywords */ int i; for(i = 0; i < textKeywords.length; i++) { if (textKeywords[i].character == ch) { writeControlWord(textKeywords[i].keyword); return; } } /* In some cases it would be reasonable to check to see if the glyph being written out is in the Symbol encoding, and if so, to switch to the Symbol font for this character. TODO. */ /* Currently all unrepresentable characters are written as Unicode escapes. */ String approximation = approximationForUnicode(ch); if (approximation.length() != unicodeCount) { unicodeCount = approximation.length(); writeControlWord("uc", unicodeCount); } writeControlWord("u", (int)ch); writeRawString(" "); writeRawString(approximation); afterKeyword = false; return; } if (b > 127) { int nybble; outputStream.write('\\'); outputStream.write('\''); nybble = ( b & 0xF0 ) >>> 4; outputStream.write(hexdigits[nybble]); nybble = ( b & 0x0F ); outputStream.write(hexdigits[nybble]); afterKeyword = false; return; } switch (b) { case '}': case '{': case '\\': outputStream.write(0x5C); /* backslash */ afterKeyword = false; /* in a keyword, actually ... */ /* fall through */ default: if (afterKeyword) { outputStream.write(0x20); /* space */ afterKeyword = false; } outputStream.write(b); break; }}String approximationForUnicode(char ch){ /* TODO: Find reasonable approximations for all Unicode characters in all RTF code pages... heh, heh... */ return "?";} /** Takes a translation table (a 256-element array of characters) * and creates an output conversion table for use by * convertCharacter(). */ /* Not very efficient at all. Could be changed to sort the table for binary search. TODO. (Even though this is inefficient however, writing RTF is still much faster than reading it.) */static int[] outputConversionFromTranslationTable(char[] table){ int[] conversion = new int[2 * table.length]; int index; for(index = 0; index < table.length; index ++) { conversion[index * 2] = table[index]; conversion[(index * 2) + 1] = index; } return conversion;} static int[] outputConversionForName(String name) throws IOException{ char[] table = (char[])RTFReader.getCharacterSet(name); return outputConversionFromTranslationTable(table);}/** Takes a char and a conversion table (an int[] in the current * implementation, but conversion tables should be treated as an opaque * type) and returns the * corresponding byte value (as an int, since bytes are signed). */ /* Not very efficient. TODO. */static protected int convertCharacter(int[] conversion, char ch){ int index; for(index = 0; index < conversion.length; index += 2) { if(conversion[index] == ch) return conversion[index + 1]; } return 0; /* 0 indicates an unrepresentable character */}}
?? 快捷鍵說明
復制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -