| /* |
| * Copyright 2000-2014 JetBrains s.r.o. |
| * |
| * Licensed under the Apache License, Version 2.0 (the "License"); |
| * you may not use this file except in compliance with the License. |
| * You may obtain a copy of the License at |
| * |
| * http://www.apache.org/licenses/LICENSE-2.0 |
| * |
| * Unless required by applicable law or agreed to in writing, software |
| * distributed under the License is distributed on an "AS IS" BASIS, |
| * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| * See the License for the specific language governing permissions and |
| * limitations under the License. |
| */ |
| package com.intellij.openapi.editor.richcopy.view; |
| |
| import com.intellij.openapi.editor.richcopy.model.ColorRegistry; |
| import com.intellij.openapi.editor.richcopy.model.FontNameRegistry; |
| import com.intellij.openapi.editor.richcopy.model.MarkupHandler; |
| import com.intellij.openapi.editor.richcopy.model.SyntaxInfo; |
| import org.jetbrains.annotations.NotNull; |
| |
| import java.awt.*; |
| import java.awt.datatransfer.DataFlavor; |
| |
| public class RtfTransferableData extends AbstractSyntaxAwareInputStreamTransferableData { |
| |
| @NotNull public static final DataFlavor FLAVOR = new DataFlavor("text/rtf;class=java.io.InputStream", "RTF text"); |
| |
| @NotNull private static final String HEADER_PREFIX = "{\\rtf1\\ansi\\deff0"; |
| @NotNull private static final String HEADER_SUFFIX = "}"; |
| @NotNull private static final String TAB = "\\tab\n"; |
| @NotNull private static final String NEW_LINE = "\\line\n"; |
| @NotNull private static final String BOLD = "\\b"; |
| @NotNull private static final String ITALIC = "\\i"; |
| |
| public RtfTransferableData(@NotNull SyntaxInfo syntaxInfo) { |
| super(syntaxInfo, FLAVOR); |
| } |
| |
| @Override |
| protected void build(@NotNull final StringBuilder holder, final int maxLength) { |
| holder.append(HEADER_PREFIX); |
| |
| holder.append("{\\colortbl;"); |
| ColorRegistry colorRegistry = mySyntaxInfo.getColorRegistry(); |
| for (int id : colorRegistry.getAllIds()) { |
| Color color = colorRegistry.dataById(id); |
| holder.append(String.format("\\red%d\\green%d\\blue%d;", color.getRed(), color.getGreen(), color.getBlue())); |
| } |
| holder.append("}\n"); |
| |
| holder.append("{\\fonttbl"); |
| FontNameRegistry fontNameRegistry = mySyntaxInfo.getFontNameRegistry(); |
| for (int id : fontNameRegistry.getAllIds()) { |
| String fontName = fontNameRegistry.dataById(id); |
| holder.append(String.format("{\\f%d %s;}", id, fontName)); |
| } |
| holder.append("}\n"); |
| |
| holder.append("\n\\s0\\box") |
| .append("\\cbpat").append(mySyntaxInfo.getDefaultBackground()) |
| .append("\\cb").append(mySyntaxInfo.getDefaultBackground()); |
| addFontSize(holder, mySyntaxInfo.getFontSize()); |
| holder.append('\n'); |
| |
| mySyntaxInfo.processOutputInfo(new MyVisitor(holder, myRawText, mySyntaxInfo, maxLength)); |
| |
| holder.append("\\par"); |
| holder.append(HEADER_SUFFIX); |
| } |
| |
| @NotNull |
| @Override |
| protected String getCharset() { |
| return "US-ASCII"; |
| } |
| |
| private static void addFontSize(StringBuilder buffer, int fontSize) { |
| buffer.append("\\fs").append(fontSize * 2); |
| } |
| |
| private static class MyVisitor implements MarkupHandler { |
| |
| @NotNull private final StringBuilder myBuffer; |
| @NotNull private final String myRawText; |
| private final int myMaxLength; |
| |
| private final int myDefaultBackgroundId; |
| private final int myFontSize; |
| private int myForegroundId = -1; |
| private int myFontNameId = -1; |
| private int myFontStyle = -1; |
| |
| MyVisitor(@NotNull StringBuilder buffer, @NotNull String rawText, @NotNull SyntaxInfo syntaxInfo, int maxLength) { |
| myBuffer = buffer; |
| myRawText = rawText; |
| myMaxLength = maxLength; |
| |
| myDefaultBackgroundId = syntaxInfo.getDefaultBackground(); |
| myFontSize = syntaxInfo.getFontSize(); |
| } |
| |
| @Override |
| public void handleText(int startOffset, int endOffset) throws Exception { |
| myBuffer.append("\n"); |
| for (int i = startOffset; i < endOffset; i++) { |
| char c = myRawText.charAt(i); |
| if (c > 127) { |
| // Escape non-ascii symbols. |
| myBuffer.append(String.format("\\u%04d?", (int)c)); |
| continue; |
| } |
| |
| switch (c) { |
| case '\t': |
| myBuffer.append(TAB); |
| continue; |
| case '\n': |
| myBuffer.append(NEW_LINE); |
| continue; |
| case '\\': |
| case '{': |
| case '}': |
| myBuffer.append('\\'); |
| } |
| myBuffer.append(c); |
| } |
| } |
| |
| @Override |
| public void handleBackground(int backgroundId) throws Exception { |
| if (backgroundId == myDefaultBackgroundId) { |
| myBuffer.append("\\plain"); // we cannot use \chcbpat with default background id, as it doesn't work in MS Word, |
| // and we cannot use \chcbpat0 as it doesn't work in OpenOffice |
| |
| addFontSize(myBuffer, myFontSize); |
| if (myFontNameId >= 0) { |
| handleFont(myFontNameId); |
| } |
| if (myForegroundId >= 0) { |
| handleForeground(myForegroundId); |
| } |
| if (myFontStyle >= 0) { |
| handleStyle(myFontStyle); |
| } |
| } |
| else { |
| myBuffer.append("\\chcbpat").append(backgroundId); |
| } |
| myBuffer.append("\\cb").append(backgroundId); |
| myBuffer.append('\n'); |
| } |
| |
| @Override |
| public void handleForeground(int foregroundId) throws Exception { |
| myBuffer.append("\\cf").append(foregroundId).append('\n'); |
| myForegroundId = foregroundId; |
| } |
| |
| @Override |
| public void handleFont(int fontNameId) throws Exception { |
| myBuffer.append("\\f").append(fontNameId).append('\n'); |
| myFontNameId = fontNameId; |
| } |
| |
| @Override |
| public void handleStyle(int style) throws Exception { |
| myBuffer.append(ITALIC); |
| if ((style & Font.ITALIC) == 0) { |
| myBuffer.append('0'); |
| } |
| myBuffer.append(BOLD); |
| if ((style & Font.BOLD) == 0) { |
| myBuffer.append('0'); |
| } |
| myBuffer.append('\n'); |
| myFontStyle = style; |
| } |
| |
| @Override |
| public boolean canHandleMore() { |
| if (myBuffer.length() > myMaxLength) { |
| myBuffer.append("... truncated ..."); |
| return false; |
| } |
| return true; |
| } |
| } |
| } |