package net.sf.jabref.export.layout.format; import net.sf.jabref.Globals; import net.sf.jabref.export.layout.LayoutFormatter; /** * Transform a LaTeX-String to RTF. * * This method will: * * 1.) Remove LaTeX-Command sequences. * * 2.) Replace LaTeX-Special chars with RTF aquivalents. * * 3.) Replace emph and textit and textbf with their RTF replacements. * * 4.) Take special care to save all unicode characters correctly. * * 5.) Replace --- by \emdash and -- by \endash. * * @author $Author: mortenalver $ * @version $Revision: 3655 $ ($Date: 2011-09-12 19:43:56 +0200 (Mo, 12 Sep 2011) $) * */ public class RTFChars implements LayoutFormatter { public String format(String field) { StringBuffer sb = new StringBuffer(""); StringBuffer currentCommand = null; boolean escaped = false, incommand = false; for (int i = 0; i < field.length(); i++) { /*System.out.println("incommand="+incommand+". escaped="+escaped +". currentCommand='"+(currentCommand!=null?currentCommand.toString():"")+"'"); System.out.println("sb: '"+sb.toString()+"'");*/ char c = field.charAt(i); //System.out.println("Char: '"+((char)c)+"'"); if (escaped && (c == '\\')) { sb.append('\\'); escaped = false; } else if (c == '\\') { escaped = true; incommand = true; currentCommand = new StringBuffer(); } else if (!incommand && (c == '{' || c == '}')) { // Swallow the brace. } else if (Character.isLetter(c) || (Globals.SPECIAL_COMMAND_CHARS.indexOf("" + c) >= 0)) { escaped = false; if (!incommand){ sb.append(c); } else { // Else we are in a command, and should not keep the letter. currentCommand.append(c); testCharCom: if ((currentCommand.length() == 1) && (Globals.SPECIAL_COMMAND_CHARS.indexOf(currentCommand.toString()) >= 0)) { // This indicates that we are in a command of the type // \^o or \~{n} if (i >= field.length() - 1) break testCharCom; String command = currentCommand.toString(); i++; c = field.charAt(i); String combody; if (c == '{') { IntAndString part = getPart(field, i); i += part.i; combody = part.s; } else { combody = field.substring(i, i + 1); } String result = Globals.RTFCHARS.get(command + combody); if (result != null) sb.append(result); incommand = false; escaped = false; } } } else { // if (!incommand || ((c!='{') && !Character.isWhitespace(c))) testContent: if (!incommand || (!Character.isWhitespace(c) && (c != '{') && (c != '}'))) sb.append(c); else { // First test for braces that may be part of a LaTeX command: if ((c == '{') && (currentCommand.length() == 0)) { // We have seen something like \{, which is probably the start // of a command like \{aa}. Swallow the brace. continue; } else if ((c == '}') && (currentCommand.length() > 0)) { // Seems to be the end of a command like \{aa}. Look it up: String command = currentCommand.toString(); String result = Globals.RTFCHARS.get(command); if (result != null) { sb.append(result); } incommand = false; escaped = false; continue; } // Then look for italics etc., // but first check if we are already at the end of the string. if (i >= field.length() - 1) break testContent; if ((c == '{') && (currentCommand.length() > 0)) { String command = currentCommand.toString(); // Then test if we are dealing with a italics or bold // command. If so, handle. if (command.equals("em") || command.equals("emph") || command.equals("textit")) { IntAndString part = getPart(field, i); i += part.i; sb.append("}{\\i ").append(part.s).append("}{"); } else if (command.equals("textbf")) { IntAndString part = getPart(field, i); i += part.i; sb.append("}{\\b ").append(part.s).append("}{"); } } else sb.append(c); } incommand = false; escaped = false; } } char[] chars = sb.toString().toCharArray(); sb = new StringBuffer(); for (int i = 0; i < chars.length; i++) { char c = chars[i]; if (c < 128) sb.append(c); else sb.append("\\u").append((long) c).append('?'); } return sb.toString().replaceAll("---", "{\\\\emdash}").replaceAll("--", "{\\\\endash}").replaceAll("``", "{\\\\ldblquote}").replaceAll("''","{\\\\rdblquote}"); } private IntAndString getPart(String text, int i) { char c; int count = 0; StringBuffer part = new StringBuffer(); while ((count >= 0) && (i < text.length())) { i++; c = text.charAt(i); if (c == '}') count--; else if (c == '{') count++; part.append(c); } return new IntAndString(part.length(), format(part.toString())); } private class IntAndString { public int i; String s; public IntAndString(int i, String s) { this.i = i; this.s = s; } } }