/*
* (c) Copyright 2010-2011 AgileBirds
*
* This file is part of OpenFlexo.
*
* OpenFlexo is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* OpenFlexo is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with OpenFlexo. If not, see <http://www.gnu.org/licenses/>.
*
*/
package org.openflexo.toolbox;
import java.io.BufferedReader;
import java.io.File;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.Iterator;
import java.util.Vector;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import java.util.regex.PatternSyntaxException;
/**
* @author gpolet
*
*/
public class LatexUtils {
public static final String TEXIFY = "texify";
public static final String PDFLATEX = "pdflatex";
public static final Vector<String> stringsToIgnore = new Vector<String>();
protected static final String LATEX_BACKSLASH = HTMLUtils.LATEX_BACKSLASH;
protected static final String JAVA_BACKSLASH = "\\";
protected static final String LATEX_TAG_REGEXP = "^\\\\[^ {]+(\\{[^}]*\\}\\s*)*";
protected static final Pattern LATEX_TAG_PATTERN = Pattern.compile(LATEX_TAG_REGEXP);
protected static final String CHARS_TO_ESCAPE_REGEXP = "[\\\\{}_&%#~]";
protected static final Pattern CHARS_TO_ESCAPE_PATTERN = Pattern.compile(CHARS_TO_ESCAPE_REGEXP);
static {
stringsToIgnore.add("<BR>");
stringsToIgnore.add("<LI>");
stringsToIgnore.add("<UL>");
stringsToIgnore.add("</UL>");
}
public static String getDefaultLatex2PDFCommand() {
return getDefaultLatex2PDFCommand(true);
}
public static String getDefaultLatex2PDFCommand(boolean testDefaultCommands) {
// First we test the default commands (if they are defined in the path, it should work)
if (testDefaultCommands) {
if (testLatexCommand(TEXIFY)) {
return TEXIFY;
} else if (testLatexCommand(PDFLATEX)) {
return PDFLATEX;
}
}
// Then we scan the paths stored in the PATH variable
String string = System.getenv("PATH");
if (string != null) {
String[] s = string.split(System.getProperty("path.separator"));
for (int i = 0; i < s.length; i++) {
String string2 = s[i];
if (string2.toLowerCase().indexOf("tex") > 0) {
File file = new File(string2, "texify");
if (file.exists()) {
return file.getAbsolutePath();
} else {
file = new File(string2, "pdflatex");
if (file.exists()) {
return file.getAbsolutePath();
}
}
}
}
}
// Finally we perform a scan in the typical installation directory
if (ToolBox.getPLATFORM() == ToolBox.WINDOWS) {
File pgFiles = new File(System.getenv("ProgramFiles"));
File[] f = pgFiles.listFiles();
for (int i = 0; i < f.length; i++) {
File file = f[i];
if (file.getName().toLowerCase().startsWith("miktex")) {
File cmd = new File(file, "miktex/bin/textify");
if (cmd.exists()) {
return cmd.getAbsolutePath();
}
cmd = new File(file, "miktex/bin/pdflatex");
if (cmd.exists()) {
return cmd.getAbsolutePath();
}
}
}
} else if (ToolBox.getPLATFORM() == ToolBox.MACOS) {
StringBuilder sb = new StringBuilder("/usr/local/teTeX/bin/");
sb.append(System.getProperty("os.arch").equals("ppc") ? "powerpc" : "i386");
sb.append("-apple-darwin-current");
String path = testCommandsWithPath(sb.toString());
if (path != null) {
return path;
}
} else if (ToolBox.getPLATFORM() == ToolBox.LINUX) {
String path = testCommandsWithPath("/usr/bin");
if (path != null) {
return path;
}
path = testCommandsWithPath("/bin");
if (path != null) {
return path;
}
path = testCommandsWithPath("/usr/local/bin");
if (path != null) {
return path;
}
}
return null;
}
/**
* @param path
*/
private static String testCommandsWithPath(String path) {
File file = new File(path.toString());
if (file.exists() && file.isDirectory()) {
File cmd = new File(file, "texify");
if (cmd.exists()) {
return cmd.getAbsolutePath();
}
cmd = new File(file, "pdflatex");
if (cmd.exists()) {
return cmd.getAbsolutePath();
}
}
return null;
}
public static boolean testLatexCommand(String command) {
final Process p;
try {
p = Runtime.getRuntime().exec(command + " --help");
Thread readThread = new Thread(new Runnable() {
/**
* Overrides run
*
* @see java.lang.Runnable#run()
*/
@Override
public void run() {
InputStreamReader is = new InputStreamReader(p.getInputStream());
BufferedReader reader = new BufferedReader(is);
String line;
try {
while ((line = reader.readLine()) != null) {
}
} catch (IOException e) {
e.printStackTrace();
}
}
});
readThread.start();
p.waitFor();
return p.exitValue() == 0;
} catch (IOException e) {
e.printStackTrace();
} catch (InterruptedException e) {
e.printStackTrace();
}
return false;
}
/**
* @param javaString
* @return
*/
private static String removeStringsToIgnore(String javaString) {
StringBuffer sb = new StringBuffer();
Iterator i = stringsToIgnore.iterator();
while (i.hasNext()) {
String s = (String) i.next();
sb.append(s);
if (i.hasNext()) {
sb.append('|');
}
}
Pattern p = Pattern.compile(sb.toString(), Pattern.CASE_INSENSITIVE);
Matcher m = p.matcher(javaString);
sb = new StringBuffer();
while (m.find()) {
m.appendReplacement(sb, " ");
}
m.appendTail(sb);
return sb.toString();
}
/**
* This method escapes the characters that LaTeX requires to escape. Such chars are:<br>
* {, }, $, \, &, %, # and ~
*
* @param javaString
* @return
*/
public static String prepareJavaStringForLatex(String javaString) {
if (javaString == null) {
return ""; // This will avoid any NPE
}
javaString = removeStringsToIgnore(javaString);
try {
StringBuffer sb = new StringBuffer();
Matcher m = CHARS_TO_ESCAPE_PATTERN.matcher(javaString);
while (m.find()) {
String tmp = javaString.substring(m.start());
Matcher latex = LATEX_TAG_PATTERN.matcher(tmp);
if (latex.find()) {// This means it has found a Latex_tag
// pattern
if (latex.group(1) == null) {// just a tag \blabla
m.appendReplacement(sb, "$0");
} else {// a tag \blabla{bloblo} {}
String str = latex.group();
int n = -1;
Matcher tmpMatcher = CHARS_TO_ESCAPE_PATTERN.matcher(str);
while (tmpMatcher.find()) {
n++;
}
while (n > 0 && m.find()) {
n--;
m.appendReplacement(sb, "$0");
}
}
} else {
if (m.group().equals(JAVA_BACKSLASH)) {
m.appendReplacement(sb, "\\" + LATEX_BACKSLASH);
// The double \ added in front of the replacement are
// there to escape the begining of a Latex backslash
// which starts with a backslash too and are interpreted
// in the replacement method.
} else {
m.appendReplacement(sb, "\\\\" + m.group());
}
}
}
m.appendTail(sb);
return fixQuotesAndLineReturns(sb.toString().replaceAll("\\$", "\\\\$0"));
} catch (PatternSyntaxException e) {
e.printStackTrace();
return javaString;
}
}
public static String fixQuotesAndLineReturns(String string) {
String s = string.replaceAll("\"(.*?)\"", "``$1''");// This
// does
// something:
// the
// first expression is a
// regular expression in
// which you have to escape
// the dollar sign. Since
// the escape character has
// to be escaped in Java
// too, it is escaped twice.
// In the second expression,
// it is a litteral string
// where the escape
// character is escaped with
// himself (see Javadoc)
// s = s.replaceAll("[\n\r]{2,}", "\n"); // aja remove to test paragraph in wysiwyg
return s;
}
}