Initial import
git-svn-id: svn://svn.code.sf.net/p/writer2latex/code/trunk@5 f0f2a975-2e09-46c8-9428-3b39399b9f3c
This commit is contained in:
parent
75e32b1e8f
commit
b0b66fcae9
252 changed files with 49000 additions and 0 deletions
|
@ -0,0 +1,188 @@
|
|||
/************************************************************************
|
||||
*
|
||||
* ByteArrayXStream.java
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License version 2.1, as published by the Free Software Foundation.
|
||||
*
|
||||
* This library 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
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston,
|
||||
* MA 02111-1307 USA
|
||||
*
|
||||
* Copyright: 2002-2008 by Henrik Just
|
||||
*
|
||||
* All Rights Reserved.
|
||||
*
|
||||
* Version 1.0 (2008-07-22)
|
||||
*
|
||||
*/
|
||||
|
||||
package org.openoffice.da.comp.w2lcommon.filter;
|
||||
|
||||
// This class is based on these java uno adapter classes:
|
||||
// com.sun.star.lib.uno.adapter.ByteArrayToXInputStreamAdapter;
|
||||
// com.sun.star.lib.uno.adapter.XOutputStreamToByteArrayAdapter;
|
||||
// See http://go-oo.org/lxr/source/udk/javaunohelper/com/sun/star/lib/uno/adapter/XOutputStreamToByteArrayAdapter.java
|
||||
// and http://go-oo.org/lxr/source/udk/javaunohelper/com/sun/star/lib/uno/adapter/ByteArrayToXInputStreamAdapter.java
|
||||
// for original source
|
||||
|
||||
import com.sun.star.io.XInputStream;
|
||||
import com.sun.star.io.XOutputStream;
|
||||
import com.sun.star.io.XSeekable;
|
||||
import com.sun.star.io.XStream;
|
||||
|
||||
/** <p>This is a java-uno adapter class which implements XStream using a
|
||||
* byte array. (We need this because XGraphicProvider demans read/write access
|
||||
* when storing a graphic to a stream.)</p>
|
||||
*/
|
||||
public class ByteArrayXStream implements XInputStream, XOutputStream, XSeekable, XStream {
|
||||
|
||||
// Keep data about our byte array (we read and write to the same byte array)
|
||||
|
||||
private int initialSize = 100240; // 10 kb
|
||||
private int size = 0; // The current buffer size
|
||||
private int position = 0; // The current write position, always<=size
|
||||
private int readPosition = 0; // The current read position, always<=position
|
||||
private boolean closed = false; // The XStream is closed
|
||||
private byte[] buffer; // The buffer
|
||||
|
||||
// Constructor: Initialize the byte array
|
||||
|
||||
public ByteArrayXStream() {
|
||||
size = initialSize;
|
||||
buffer = new byte[size];
|
||||
}
|
||||
|
||||
// Implementation of XOutputStream
|
||||
|
||||
public void closeOutput()
|
||||
throws com.sun.star.io.NotConnectedException,
|
||||
com.sun.star.io.BufferSizeExceededException,
|
||||
com.sun.star.io.IOException {
|
||||
|
||||
// trim buffer
|
||||
if ( buffer.length > position) {
|
||||
byte[] newBuffer = new byte[position];
|
||||
System.arraycopy(buffer, 0, newBuffer, 0, position);
|
||||
buffer = newBuffer;
|
||||
}
|
||||
closed = true;
|
||||
}
|
||||
|
||||
public void flush()
|
||||
throws com.sun.star.io.NotConnectedException,
|
||||
com.sun.star.io.BufferSizeExceededException,
|
||||
com.sun.star.io.IOException {
|
||||
}
|
||||
|
||||
public void writeBytes(byte[] values)
|
||||
throws com.sun.star.io.NotConnectedException,
|
||||
com.sun.star.io.BufferSizeExceededException,
|
||||
com.sun.star.io.IOException {
|
||||
if ( values.length > size-position ) {
|
||||
byte[] newBuffer = null;
|
||||
while ( values.length > size-position )
|
||||
size *= 2;
|
||||
newBuffer = new byte[size];
|
||||
System.arraycopy(buffer, 0, newBuffer, 0, position);
|
||||
buffer = newBuffer;
|
||||
}
|
||||
System.arraycopy(values, 0, buffer, position, values.length);
|
||||
position += values.length;
|
||||
}
|
||||
|
||||
// Implementation of XInputStream
|
||||
|
||||
private void _check() throws com.sun.star.io.NotConnectedException, com.sun.star.io.IOException {
|
||||
if(closed) {
|
||||
throw new com.sun.star.io.IOException("input closed");
|
||||
}
|
||||
}
|
||||
|
||||
public int available() throws com.sun.star.io.NotConnectedException, com.sun.star.io.IOException {
|
||||
_check();
|
||||
return position - readPosition;
|
||||
}
|
||||
|
||||
public void closeInput() throws com.sun.star.io.NotConnectedException, com.sun.star.io.IOException {
|
||||
closed = true;
|
||||
}
|
||||
|
||||
public int readBytes(byte[][] values, int param) throws com.sun.star.io.NotConnectedException, com.sun.star.io.BufferSizeExceededException, com.sun.star.io.IOException {
|
||||
_check();
|
||||
try {
|
||||
int remain = (int)(position - readPosition);
|
||||
if (param > remain) param = remain;
|
||||
/* ARGH!!! */
|
||||
if (values[0] == null){
|
||||
values[0] = new byte[param];
|
||||
// System.err.println("allocated new buffer of "+param+" bytes");
|
||||
}
|
||||
System.arraycopy(buffer, readPosition, values[0], 0, param);
|
||||
// System.err.println("readbytes() -> "+param);
|
||||
readPosition += param;
|
||||
return param;
|
||||
} catch (ArrayIndexOutOfBoundsException ae) {
|
||||
// System.err.println("readbytes() -> ArrayIndexOutOfBounds");
|
||||
ae.printStackTrace();
|
||||
throw new com.sun.star.io.BufferSizeExceededException("buffer overflow");
|
||||
} catch (Exception e) {
|
||||
// System.err.println("readbytes() -> Exception: "+e.getMessage());
|
||||
e.printStackTrace();
|
||||
throw new com.sun.star.io.IOException("error accessing buffer");
|
||||
}
|
||||
}
|
||||
|
||||
public int readSomeBytes(byte[][] values, int param) throws com.sun.star.io.NotConnectedException, com.sun.star.io.BufferSizeExceededException, com.sun.star.io.IOException {
|
||||
// System.err.println("readSomebytes()");
|
||||
return readBytes(values, param);
|
||||
}
|
||||
|
||||
public void skipBytes(int param) throws com.sun.star.io.NotConnectedException, com.sun.star.io.BufferSizeExceededException, com.sun.star.io.IOException {
|
||||
// System.err.println("skipBytes("+param+")");
|
||||
_check();
|
||||
if (param > (position - readPosition))
|
||||
throw new com.sun.star.io.BufferSizeExceededException("buffer overflow");
|
||||
readPosition += param;
|
||||
}
|
||||
|
||||
|
||||
// Implementation of XSeekable
|
||||
|
||||
public long getLength() throws com.sun.star.io.IOException {
|
||||
// System.err.println("getLength() -> "+m_length);
|
||||
if (buffer != null) return position;
|
||||
else throw new com.sun.star.io.IOException("no bytes");
|
||||
}
|
||||
|
||||
public long getPosition() throws com.sun.star.io.IOException {
|
||||
// System.err.println("getPosition() -> "+m_pos);
|
||||
if (buffer != null) return readPosition;
|
||||
else throw new com.sun.star.io.IOException("no bytes");
|
||||
}
|
||||
|
||||
public void seek(long param) throws com.sun.star.lang.IllegalArgumentException, com.sun.star.io.IOException {
|
||||
// System.err.println("seek("+param+")");
|
||||
if (buffer != null) {
|
||||
if (param < 0 || param > position) throw new com.sun.star.lang.IllegalArgumentException("invalid seek position");
|
||||
else readPosition = (int)param;
|
||||
} else throw new com.sun.star.io.IOException("no bytes");
|
||||
}
|
||||
|
||||
// Implementation of XStream
|
||||
public XInputStream getInputStream() { return this; }
|
||||
|
||||
public XOutputStream getOutputStream() { return this; }
|
||||
|
||||
// Get the buffer
|
||||
public byte[] getBuffer() { return buffer; }
|
||||
|
||||
}
|
||||
|
|
@ -0,0 +1,504 @@
|
|||
/************************************************************************
|
||||
*
|
||||
* ExportFilterBase.java
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License version 2.1, as published by the Free Software Foundation.
|
||||
*
|
||||
* This library 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
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston,
|
||||
* MA 02111-1307 USA
|
||||
*
|
||||
* Copyright: 2002-2008 by Henrik Just
|
||||
*
|
||||
* All Rights Reserved.
|
||||
*
|
||||
* Version 1.0 (2008-11-24)
|
||||
*
|
||||
*/
|
||||
|
||||
// This file was originally based on OOo's XMergeBridge, which is (c) by Sun Microsystems
|
||||
|
||||
package org.openoffice.da.comp.w2lcommon.filter;
|
||||
|
||||
import com.sun.star.lib.uno.adapter.XInputStreamToInputStreamAdapter;
|
||||
import com.sun.star.lib.uno.adapter.XOutputStreamToOutputStreamAdapter;
|
||||
|
||||
//import com.sun.star.beans.PropertyValue;
|
||||
import com.sun.star.io.XInputStream;
|
||||
import com.sun.star.io.XOutputStream;
|
||||
import com.sun.star.lang.XMultiServiceFactory;
|
||||
import com.sun.star.lang.XServiceInfo;
|
||||
import com.sun.star.lang.XServiceName;
|
||||
import com.sun.star.lang.XTypeProvider;
|
||||
import com.sun.star.uno.AnyConverter;
|
||||
import com.sun.star.ucb.XSimpleFileAccess2;
|
||||
import com.sun.star.uno.Type;
|
||||
import com.sun.star.uno.UnoRuntime;
|
||||
import com.sun.star.uno.XComponentContext;
|
||||
//import com.sun.star.xml.sax.InputSource;
|
||||
//import com.sun.star.xml.sax.XParser;
|
||||
import com.sun.star.xml.sax.XDocumentHandler;
|
||||
import com.sun.star.xml.XExportFilter;
|
||||
|
||||
import org.openoffice.da.comp.w2lcommon.helper.MessageBox;
|
||||
//import org.openoffice.da.comp.w2lcommon.helper.PropertyHelper;
|
||||
import writer2latex.api.Converter;
|
||||
import writer2latex.api.ConverterFactory;
|
||||
import writer2latex.api.ConverterResult;
|
||||
import writer2latex.api.OutputFile;
|
||||
|
||||
import java.util.Iterator;
|
||||
//import java.util.Enumeration;
|
||||
//import java.util.Vector;
|
||||
import java.io.*;
|
||||
//import javax.xml.parsers.*;
|
||||
//import org.xml.sax.SAXException;
|
||||
//import java.net.URI;
|
||||
|
||||
|
||||
/** This class provides an abstract uno component which implements an XExportFilter.
|
||||
* The filter is actually generic and only then constructor and 3 strings needs
|
||||
* to changed by the subclass.
|
||||
*/
|
||||
public abstract class ExportFilterBase implements
|
||||
XExportFilter,
|
||||
XServiceName,
|
||||
XServiceInfo,
|
||||
XDocumentHandler,
|
||||
XTypeProvider {
|
||||
|
||||
/** Service name for the component */
|
||||
public static final String __serviceName = "";
|
||||
|
||||
/** Implementation name for the component */
|
||||
public static final String __implementationName = "";
|
||||
|
||||
/** Filter name to include in error messages */
|
||||
public static final String __displayName = "";
|
||||
|
||||
private static XComponentContext xComponentContext = null;
|
||||
protected static XMultiServiceFactory xMSF;
|
||||
private static XInputStream xInStream =null;
|
||||
private static XOutputStream xOutStream=null;
|
||||
private static XOutputStream xos = null;
|
||||
private static String sdMime=null;
|
||||
private static String sURL="";
|
||||
|
||||
private Object filterData;
|
||||
private XSimpleFileAccess2 sfa2;
|
||||
|
||||
|
||||
/** We need to get the Service Manager from the Component context to
|
||||
* instantiate certain services, hence this constructor.
|
||||
* The subclass must override this to set xMSF properly from the reigstration class
|
||||
*/
|
||||
public ExportFilterBase(XComponentContext xComponentContext1) {
|
||||
xComponentContext = xComponentContext1;
|
||||
xMSF = null;
|
||||
}
|
||||
|
||||
|
||||
// Some utility methods:
|
||||
|
||||
String getFileName(String origName) {
|
||||
String name=null;
|
||||
if (origName !=null) {
|
||||
if(origName.equalsIgnoreCase(""))
|
||||
name = "OutFile";
|
||||
else {
|
||||
if (origName.lastIndexOf("/")>=0) {
|
||||
origName=origName.substring(origName.lastIndexOf("/")+1,origName.length());
|
||||
}
|
||||
if (origName.lastIndexOf(".")>=0) {
|
||||
name = origName.substring(0,(origName.lastIndexOf(".")));
|
||||
}
|
||||
else {
|
||||
name=origName;
|
||||
}
|
||||
}
|
||||
}
|
||||
else{
|
||||
name = "OutFile";
|
||||
}
|
||||
|
||||
return name;
|
||||
}
|
||||
|
||||
public String replace(String origString, String origChar, String replaceChar){
|
||||
String tmp="";
|
||||
int index=origString.indexOf(origChar);
|
||||
if(index !=-1){
|
||||
while (index !=-1){
|
||||
String first =origString.substring(0,index);
|
||||
first=first.concat(replaceChar);
|
||||
tmp=tmp.concat(first);
|
||||
origString=origString.substring(index+1,origString.length());
|
||||
index=origString.indexOf(origChar);
|
||||
if(index==-1) {
|
||||
tmp=tmp.concat(origString);
|
||||
}
|
||||
}
|
||||
}
|
||||
return tmp;
|
||||
}
|
||||
|
||||
public String needsMask(String origString) {
|
||||
if (origString.indexOf("&")!=-1){
|
||||
origString=replace(origString,"&","&");
|
||||
}
|
||||
if (origString.indexOf("\"")!=-1){
|
||||
origString=replace(origString,"\"",""");
|
||||
}
|
||||
if (origString.indexOf("<")!=-1){
|
||||
origString=replace(origString,"<","<");
|
||||
}
|
||||
if (origString.indexOf(">")!=-1){
|
||||
origString=replace(origString,">",">");
|
||||
}
|
||||
return origString;
|
||||
|
||||
}
|
||||
|
||||
|
||||
// Implementation of XExportFilter:
|
||||
|
||||
public boolean exporter(com.sun.star.beans.PropertyValue[] aSourceData,
|
||||
java.lang.String[] msUserData) throws com.sun.star.uno.RuntimeException{
|
||||
|
||||
sURL=null;
|
||||
filterData = null;
|
||||
|
||||
// Get user data from configuration (type detection)
|
||||
//String udConvertClass=msUserData[0];
|
||||
//String udImport =msUserData[2];
|
||||
//String udExport =msUserData[3];
|
||||
sdMime = msUserData[5];
|
||||
|
||||
// Get source data (only the OutputStream and the URL are actually used)
|
||||
com.sun.star.beans.PropertyValue[] pValue = aSourceData;
|
||||
for (int i = 0 ; i < pValue.length; i++) {
|
||||
try{
|
||||
if (pValue[i].Name.compareTo("OutputStream")==0){
|
||||
xos=(com.sun.star.io.XOutputStream)AnyConverter.toObject(new Type(com.sun.star.io.XOutputStream.class), pValue[i].Value);
|
||||
}
|
||||
//if (pValue[i].Name.compareTo("FileName")==0){
|
||||
// sFileName=(String)AnyConverter.toObject(new Type(java.lang.String.class), pValue[i].Value);
|
||||
//}
|
||||
if (pValue[i].Name.compareTo("URL")==0){
|
||||
sURL=(String)AnyConverter.toObject(new Type(java.lang.String.class), pValue[i].Value);
|
||||
}
|
||||
//if (pValue[i].Name.compareTo("Title")==0){
|
||||
// title=(String)AnyConverter.toObject(new Type(java.lang.String.class), pValue[i].Value);
|
||||
//}
|
||||
if (pValue[i].Name.compareTo("FilterData")==0) {
|
||||
filterData = pValue[i].Value;
|
||||
}
|
||||
}
|
||||
catch(com.sun.star.lang.IllegalArgumentException AnyExec){
|
||||
System.err.println("\nIllegalArgumentException "+AnyExec);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
if (sURL==null){
|
||||
sURL="";
|
||||
}
|
||||
|
||||
// Create a pipe to be used by the XDocumentHandler implementation:
|
||||
try {
|
||||
Object xPipeObj=xMSF.createInstance("com.sun.star.io.Pipe");
|
||||
xInStream = (XInputStream) UnoRuntime.queryInterface(
|
||||
XInputStream.class , xPipeObj );
|
||||
xOutStream = (XOutputStream) UnoRuntime.queryInterface(
|
||||
XOutputStream.class , xPipeObj );
|
||||
}
|
||||
catch (Exception e){
|
||||
System.err.println("Exception "+e);
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
|
||||
// Implementation of XDocumentHandler:
|
||||
// Flat xml is created by the sax events and passed through the pipe
|
||||
// created by exporter()
|
||||
|
||||
public void startDocument () {
|
||||
//Do nothing
|
||||
}
|
||||
|
||||
public void endDocument()throws com.sun.star.uno.RuntimeException {
|
||||
try{
|
||||
xOutStream.closeOutput();
|
||||
convert(xInStream,xos);
|
||||
}
|
||||
catch (IOException e){
|
||||
MessageBox msgBox = new MessageBox(xComponentContext);
|
||||
msgBox.showMessage(__displayName+": IO error in conversion",
|
||||
e.toString()+" at "+e.getStackTrace()[0].toString());
|
||||
throw new com.sun.star.uno.RuntimeException(e.getMessage());
|
||||
}
|
||||
catch (Exception e){
|
||||
MessageBox msgBox = new MessageBox(xComponentContext);
|
||||
msgBox.showMessage(__displayName+": Internal error in conversion",
|
||||
e.toString()+" at "+e.getStackTrace()[0].toString());
|
||||
throw new com.sun.star.uno.RuntimeException(__displayName+" Exception");
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
public void startElement (String str, com.sun.star.xml.sax.XAttributeList xattribs)
|
||||
{
|
||||
|
||||
str="<".concat(str);
|
||||
if (xattribs !=null)
|
||||
{
|
||||
str= str.concat(" ");
|
||||
int len=xattribs.getLength();
|
||||
for (short i=0;i<len;i++)
|
||||
{
|
||||
str=str.concat(xattribs.getNameByIndex(i));
|
||||
str=str.concat("=\"");
|
||||
str=str.concat(needsMask(xattribs.getValueByIndex(i)));
|
||||
str=str.concat("\" ");
|
||||
}
|
||||
}
|
||||
str=str.concat(">");
|
||||
try{
|
||||
xOutStream.writeBytes(str.getBytes("UTF-8"));
|
||||
}
|
||||
catch (Exception e){
|
||||
System.err.println("\n"+e);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
public void endElement(String str){
|
||||
|
||||
str="</".concat(str);
|
||||
str=str.concat(">");
|
||||
try{
|
||||
xOutStream.writeBytes(str.getBytes("UTF-8"));
|
||||
|
||||
}
|
||||
catch (Exception e){
|
||||
System.err.println("\n"+e);
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
public void characters(String str){
|
||||
str=needsMask(str);
|
||||
try{
|
||||
xOutStream.writeBytes(str.getBytes("UTF-8"));
|
||||
}
|
||||
catch (Exception e){
|
||||
System.err.println("\n"+e);
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
public void ignorableWhitespace(String str){
|
||||
|
||||
|
||||
}
|
||||
public void processingInstruction(String aTarget, String aData){
|
||||
|
||||
}
|
||||
|
||||
public void setDocumentLocator(com.sun.star.xml.sax.XLocator xLocator){
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
// This is the actual conversion method, using Writer2LaTeX to convert
|
||||
// the flat xml recieved from the XInputStream, and writing the result
|
||||
// to the XOutputStream. The XMLExporter does not support export to
|
||||
// compound documents with multiple output files; so the main file
|
||||
// is written to the XOutStream and other files are written using ucb.
|
||||
|
||||
public void convert (com.sun.star.io.XInputStream xml,com.sun.star.io.XOutputStream exportStream)
|
||||
throws com.sun.star.uno.RuntimeException, IOException {
|
||||
|
||||
// Initialise the file access
|
||||
sfa2 = null;
|
||||
try {
|
||||
Object sfaObject = xComponentContext.getServiceManager().createInstanceWithContext(
|
||||
"com.sun.star.ucb.SimpleFileAccess", xComponentContext);
|
||||
sfa2 = (XSimpleFileAccess2) UnoRuntime.queryInterface(XSimpleFileAccess2.class, sfaObject);
|
||||
}
|
||||
catch (com.sun.star.uno.Exception e) {
|
||||
// failed to get SimpleFileAccess service (should not happen)
|
||||
}
|
||||
|
||||
// Get base name from the url provided by OOo
|
||||
String sName= getFileName(sURL);
|
||||
|
||||
// Adapter for input stream (OpenDocument flat xml)
|
||||
XInputStreamToInputStreamAdapter xis =new XInputStreamToInputStreamAdapter(xml);
|
||||
|
||||
// Adapter for output stream (Main output file)
|
||||
XOutputStreamToOutputStreamAdapter newxos =new XOutputStreamToOutputStreamAdapter(exportStream);
|
||||
|
||||
// Create converter
|
||||
Converter converter = ConverterFactory.createConverter(sdMime);
|
||||
if (converter==null) {
|
||||
throw new com.sun.star.uno.RuntimeException("Failed to create converter to "+sdMime);
|
||||
}
|
||||
|
||||
// Apply the FilterData to the converter
|
||||
if (filterData!=null) {
|
||||
FilterDataParser fdp = new FilterDataParser(xComponentContext);
|
||||
fdp.applyFilterData(filterData,converter);
|
||||
}
|
||||
|
||||
// Do conversion
|
||||
converter.setGraphicConverter(new GraphicConverterImpl(xComponentContext));
|
||||
|
||||
ConverterResult dataOut = null;
|
||||
try {
|
||||
dataOut = converter.convert(xis,sName);
|
||||
}
|
||||
catch (IOException e) {
|
||||
// Fail silently
|
||||
}
|
||||
|
||||
// Write out files
|
||||
Iterator docEnum = dataOut.iterator();
|
||||
|
||||
// Remove the file name part of the url
|
||||
String sNewURL = null;
|
||||
if (sURL.lastIndexOf("/")>-1) {
|
||||
// Take the url up to and including the last slash
|
||||
sNewURL = sURL.substring(0,sURL.lastIndexOf("/")+1);
|
||||
}
|
||||
else {
|
||||
// The url does not include a path; this should not really happen,
|
||||
// but in this case we will write to the current default directory
|
||||
sNewURL = "";
|
||||
}
|
||||
|
||||
while (docEnum.hasNext() && sURL.startsWith("file:")) {
|
||||
OutputFile docOut = (OutputFile)docEnum.next();
|
||||
|
||||
if (dataOut.getMasterDocument()==docOut) {
|
||||
// The master document is written to the XOutStream supplied
|
||||
// by the XMLFilterAdaptor
|
||||
docOut.write(newxos);
|
||||
newxos.flush();
|
||||
newxos.close();
|
||||
}
|
||||
else {
|
||||
// Additional documents are written directly using ucb
|
||||
|
||||
// Get the file name and the (optional) directory name
|
||||
String sFullFileName = docOut.getFileName();
|
||||
String sDirName = "";
|
||||
String sFileName = sFullFileName;
|
||||
int nSlash = sFileName.indexOf("/");
|
||||
if (nSlash>-1) {
|
||||
sDirName = sFileName.substring(0,nSlash);
|
||||
sFileName = sFileName.substring(nSlash+1);
|
||||
}
|
||||
|
||||
try{
|
||||
// Create subdirectory if required
|
||||
if (sDirName.length()>0 && !sfa2.exists(sNewURL+sDirName)) {
|
||||
sfa2.createFolder(sNewURL+sDirName);
|
||||
}
|
||||
|
||||
// writeFile demands an InputStream, so we need a pipe
|
||||
Object xPipeObj=xMSF.createInstance("com.sun.star.io.Pipe");
|
||||
XInputStream xInStream
|
||||
= (XInputStream) UnoRuntime.queryInterface(XInputStream.class, xPipeObj );
|
||||
XOutputStream xOutStream
|
||||
= (XOutputStream) UnoRuntime.queryInterface(XOutputStream.class, xPipeObj );
|
||||
OutputStream outStream = new XOutputStreamToOutputStreamAdapter(xOutStream);
|
||||
// Feed the pipe with content...
|
||||
docOut.write(outStream);
|
||||
outStream.flush();
|
||||
outStream.close();
|
||||
xOutStream.closeOutput();
|
||||
// ...and then write the content to the url
|
||||
sfa2.writeFile(sNewURL+sFullFileName,xInStream);
|
||||
}
|
||||
catch (Throwable e){
|
||||
MessageBox msgBox = new MessageBox(xComponentContext);
|
||||
msgBox.showMessage(__displayName+": Error writing files",
|
||||
e.toString()+" at "+e.getStackTrace()[0].toString());
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
// Implement methods from interface XTypeProvider
|
||||
// Implementation of XTypeProvider
|
||||
|
||||
public com.sun.star.uno.Type[] getTypes() {
|
||||
Type[] typeReturn = {};
|
||||
|
||||
try {
|
||||
typeReturn = new Type[] {
|
||||
new Type( XTypeProvider.class ),
|
||||
new Type( XExportFilter.class ),
|
||||
new Type( XServiceName.class ),
|
||||
new Type( XServiceInfo.class ) };
|
||||
}
|
||||
catch( Exception exception ) {
|
||||
|
||||
}
|
||||
|
||||
return( typeReturn );
|
||||
}
|
||||
|
||||
|
||||
public byte[] getImplementationId() {
|
||||
byte[] byteReturn = {};
|
||||
|
||||
byteReturn = new String( "" + this.hashCode() ).getBytes();
|
||||
|
||||
return( byteReturn );
|
||||
}
|
||||
|
||||
// Implement method from interface XServiceName
|
||||
public String getServiceName() {
|
||||
return( __serviceName );
|
||||
}
|
||||
|
||||
// Implement methods from interface XServiceInfo
|
||||
public boolean supportsService(String stringServiceName) {
|
||||
return( stringServiceName.equals( __serviceName ) );
|
||||
}
|
||||
|
||||
public String getImplementationName() {
|
||||
return __implementationName;
|
||||
//return( W2LExportFilter.class.getName() );
|
||||
}
|
||||
|
||||
public String[] getSupportedServiceNames() {
|
||||
String[] stringSupportedServiceNames = { __serviceName };
|
||||
return( stringSupportedServiceNames );
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
|
@ -0,0 +1,271 @@
|
|||
/************************************************************************
|
||||
*
|
||||
* FilterDataParser.java
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License version 2.1, as published by the Free Software Foundation.
|
||||
*
|
||||
* This library 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
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston,
|
||||
* MA 02111-1307 USA
|
||||
*
|
||||
* Copyright: 2002-2008 by Henrik Just
|
||||
*
|
||||
* All Rights Reserved.
|
||||
*
|
||||
* Version 1.0 (2008-11-22)
|
||||
*
|
||||
*/
|
||||
|
||||
package org.openoffice.da.comp.w2lcommon.filter;
|
||||
|
||||
import java.io.InputStream;
|
||||
import java.io.IOException;
|
||||
import java.io.OutputStream;
|
||||
import java.util.Enumeration;
|
||||
|
||||
import com.sun.star.beans.PropertyValue;
|
||||
import com.sun.star.io.NotConnectedException;
|
||||
import com.sun.star.io.XInputStream;
|
||||
import com.sun.star.io.XOutputStream;
|
||||
import com.sun.star.ucb.CommandAbortedException;
|
||||
import com.sun.star.ucb.XSimpleFileAccess2;
|
||||
import com.sun.star.uno.AnyConverter;
|
||||
import com.sun.star.uno.UnoRuntime;
|
||||
import com.sun.star.uno.XComponentContext;
|
||||
import com.sun.star.util.XStringSubstitution;
|
||||
|
||||
import com.sun.star.lib.uno.adapter.XInputStreamToInputStreamAdapter;
|
||||
import com.sun.star.lib.uno.adapter.XOutputStreamToOutputStreamAdapter;
|
||||
|
||||
import org.openoffice.da.comp.w2lcommon.helper.PropertyHelper;
|
||||
import writer2latex.api.Converter;
|
||||
|
||||
|
||||
/** This class parses the FilterData property passed to the filter and
|
||||
* applies it to a <code>Converter</code>
|
||||
* All errors are silently ignored
|
||||
*/
|
||||
public class FilterDataParser {
|
||||
|
||||
//private static XComponentContext xComponentContext = null;
|
||||
|
||||
private XSimpleFileAccess2 sfa2;
|
||||
private XStringSubstitution xPathSub;
|
||||
|
||||
public FilterDataParser(XComponentContext xComponentContext) {
|
||||
//this.xComponentContext = xComponentContext;
|
||||
|
||||
// Get the SimpleFileAccess service
|
||||
sfa2 = null;
|
||||
try {
|
||||
Object sfaObject = xComponentContext.getServiceManager().createInstanceWithContext(
|
||||
"com.sun.star.ucb.SimpleFileAccess", xComponentContext);
|
||||
sfa2 = (XSimpleFileAccess2) UnoRuntime.queryInterface(XSimpleFileAccess2.class, sfaObject);
|
||||
}
|
||||
catch (com.sun.star.uno.Exception e) {
|
||||
// failed to get SimpleFileAccess service (should not happen)
|
||||
}
|
||||
|
||||
// Get the PathSubstitution service
|
||||
xPathSub = null;
|
||||
try {
|
||||
Object psObject = xComponentContext.getServiceManager().createInstanceWithContext(
|
||||
"com.sun.star.util.PathSubstitution", xComponentContext);
|
||||
xPathSub = (XStringSubstitution) UnoRuntime.queryInterface(XStringSubstitution.class, psObject);
|
||||
}
|
||||
catch (com.sun.star.uno.Exception e) {
|
||||
// failed to get PathSubstitution service (should not happen)
|
||||
}
|
||||
}
|
||||
|
||||
/** Apply the given FilterData property to the given converter
|
||||
* @param data an Any containing the FilterData property
|
||||
* @param converter a <code>writer2latex.api.Converter</code> implementation
|
||||
*/
|
||||
public void applyFilterData(Object data, Converter converter) {
|
||||
// Get the array from the data, if possible
|
||||
PropertyValue[] filterData = null;
|
||||
if (AnyConverter.isArray(data)) {
|
||||
try {
|
||||
Object[] arrayData = (Object[]) AnyConverter.toArray(data);
|
||||
if (arrayData instanceof PropertyValue[]) {
|
||||
filterData = (PropertyValue[]) arrayData;
|
||||
}
|
||||
}
|
||||
catch (com.sun.star.lang.IllegalArgumentException e) {
|
||||
// Failed to convert to array; should not happen - ignore
|
||||
}
|
||||
}
|
||||
if (filterData==null) { return; }
|
||||
|
||||
PropertyHelper props = new PropertyHelper(filterData);
|
||||
|
||||
// Get the special properties TemplateURL, ConfigURL and AutoCreate
|
||||
Object tpl = props.get("TemplateURL");
|
||||
String sTemplate = null;
|
||||
if (tpl!=null && AnyConverter.isString(tpl)) {
|
||||
try {
|
||||
sTemplate = substituteVariables(AnyConverter.toString(tpl));
|
||||
}
|
||||
catch (com.sun.star.lang.IllegalArgumentException e) {
|
||||
// Failed to convert to String; should not happen - ignore
|
||||
}
|
||||
}
|
||||
|
||||
Object auto = props.get("AutoCreate");
|
||||
boolean bAutoCreate = false;
|
||||
if (auto!=null && AnyConverter.isString(auto)) {
|
||||
try {
|
||||
if ("true".equals(AnyConverter.toString(auto))) {
|
||||
bAutoCreate = true;
|
||||
}
|
||||
}
|
||||
catch (com.sun.star.lang.IllegalArgumentException e) {
|
||||
// Failed to convert to String; should not happen - ignore
|
||||
}
|
||||
}
|
||||
|
||||
Object cfg = props.get("ConfigURL");
|
||||
String sConfig = null;
|
||||
if (cfg!=null && AnyConverter.isString(cfg)) {
|
||||
try {
|
||||
sConfig = substituteVariables(AnyConverter.toString(cfg));
|
||||
}
|
||||
catch (com.sun.star.lang.IllegalArgumentException e) {
|
||||
// Failed to convert to String; should not happen - ignore
|
||||
}
|
||||
}
|
||||
|
||||
// Load the template from the specified URL, if any
|
||||
if (sfa2!=null && sTemplate!=null && sTemplate.length()>0) {
|
||||
try {
|
||||
XInputStream xIs = sfa2.openFileRead(sTemplate);
|
||||
if (xIs!=null) {
|
||||
InputStream is = new XInputStreamToInputStreamAdapter(xIs);
|
||||
converter.readTemplate(is);
|
||||
is.close();
|
||||
xIs.closeInput();
|
||||
}
|
||||
}
|
||||
catch (IOException e) {
|
||||
// ignore
|
||||
}
|
||||
catch (NotConnectedException e) {
|
||||
// ignore
|
||||
}
|
||||
catch (CommandAbortedException e) {
|
||||
// ignore
|
||||
}
|
||||
catch (com.sun.star.uno.Exception e) {
|
||||
// ignore
|
||||
}
|
||||
}
|
||||
|
||||
// Create config if required
|
||||
try {
|
||||
if (bAutoCreate && sfa2!=null && sConfig!=null && !sConfig.startsWith("*") && !sfa2.exists(sConfig)) {
|
||||
// Note: Requires random access, ie. must be a file URL:
|
||||
XOutputStream xOs = sfa2.openFileWrite(sConfig);
|
||||
if (xOs!=null) {
|
||||
OutputStream os = new XOutputStreamToOutputStreamAdapter(xOs);
|
||||
converter.getConfig().write(os);
|
||||
os.flush();
|
||||
os.close();
|
||||
xOs.closeOutput();
|
||||
}
|
||||
}
|
||||
}
|
||||
catch (IOException e) {
|
||||
// ignore
|
||||
}
|
||||
catch (NotConnectedException e) {
|
||||
// ignore
|
||||
}
|
||||
catch (CommandAbortedException e) {
|
||||
// Ignore
|
||||
}
|
||||
catch (com.sun.star.uno.Exception e) {
|
||||
// Ignore
|
||||
}
|
||||
|
||||
// Load the configuration from the specified URL, if any
|
||||
if (sConfig!=null) {
|
||||
if (sConfig.startsWith("*")) { // internal configuration
|
||||
try {
|
||||
converter.getConfig().readDefaultConfig(sConfig.substring(1));
|
||||
}
|
||||
catch (IllegalArgumentException e) {
|
||||
// ignore
|
||||
}
|
||||
}
|
||||
else if (sfa2!=null) { // real URL
|
||||
try {
|
||||
XInputStream xIs = sfa2.openFileRead(sConfig);;
|
||||
if (xIs!=null) {
|
||||
InputStream is = new XInputStreamToInputStreamAdapter(xIs);
|
||||
converter.getConfig().read(is);
|
||||
is.close();
|
||||
xIs.closeInput();
|
||||
}
|
||||
}
|
||||
catch (IOException e) {
|
||||
// Ignore
|
||||
}
|
||||
catch (NotConnectedException e) {
|
||||
// Ignore
|
||||
}
|
||||
catch (CommandAbortedException e) {
|
||||
// Ignore
|
||||
}
|
||||
catch (com.sun.star.uno.Exception e) {
|
||||
// Ignore
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Read further configuration properties
|
||||
Enumeration keys = props.keys();
|
||||
while (keys.hasMoreElements()) {
|
||||
String sKey = (String) keys.nextElement();
|
||||
if (!"ConfigURL".equals(sKey) && !"TemplateURL".equals(sKey) && !"AutoCreate".equals(sKey)) {
|
||||
Object value = props.get(sKey);
|
||||
if (AnyConverter.isString(value)) {
|
||||
try {
|
||||
converter.getConfig().setOption(sKey,AnyConverter.toString(value));
|
||||
}
|
||||
catch (com.sun.star.lang.IllegalArgumentException e) {
|
||||
// Failed to convert to String; should not happen - ignore
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private String substituteVariables(String sUrl) {
|
||||
if (xPathSub!=null) {
|
||||
try {
|
||||
return xPathSub.substituteVariables(sUrl, false);
|
||||
}
|
||||
catch (com.sun.star.container.NoSuchElementException e) {
|
||||
// Found an unknown variable, no substitution
|
||||
// (This will only happen if false is replaced by true above)
|
||||
return sUrl;
|
||||
}
|
||||
}
|
||||
else { // Not path substitution available
|
||||
return sUrl;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
|
@ -0,0 +1,67 @@
|
|||
/************************************************************************
|
||||
*
|
||||
* GraphicConverterImpl.java
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License version 2.1, as published by the Free Software Foundation.
|
||||
*
|
||||
* This library 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
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston,
|
||||
* MA 02111-1307 USA
|
||||
*
|
||||
* Copyright: 2002-2008 by Henrik Just
|
||||
*
|
||||
* All Rights Reserved.
|
||||
*
|
||||
* Version 1.0 (2008-07-21)
|
||||
*
|
||||
*/
|
||||
|
||||
package org.openoffice.da.comp.w2lcommon.filter;
|
||||
|
||||
import com.sun.star.uno.XComponentContext;
|
||||
|
||||
import writer2latex.api.GraphicConverter;
|
||||
|
||||
public class GraphicConverterImpl implements GraphicConverter {
|
||||
|
||||
private GraphicConverter graphicConverter1;
|
||||
private GraphicConverter graphicConverter2;
|
||||
|
||||
public GraphicConverterImpl(XComponentContext xComponentContext) {
|
||||
graphicConverter1 = new GraphicConverterImpl1(xComponentContext);
|
||||
graphicConverter2 = new GraphicConverterImpl2(xComponentContext);
|
||||
}
|
||||
|
||||
public boolean supportsConversion(String sSourceMime, String sTargetMime, boolean bCrop, boolean bResize) {
|
||||
return graphicConverter1.supportsConversion(sSourceMime, sTargetMime, bCrop, bResize) ||
|
||||
graphicConverter2.supportsConversion(sSourceMime, sTargetMime, bCrop, bResize);
|
||||
}
|
||||
|
||||
public byte[] convert(byte[] source, String sSourceMime, String sTargetMime) {
|
||||
byte[] result = null;
|
||||
|
||||
// Prefer the simple implementation (GraphicProvider)
|
||||
if (graphicConverter1.supportsConversion(sSourceMime, sTargetMime, false, false)) {
|
||||
result = graphicConverter1.convert(source, sSourceMime, sTargetMime);
|
||||
}
|
||||
|
||||
// If this is not possible or fails, try the complex implementation
|
||||
if (result==null) {
|
||||
result = graphicConverter2.convert(source, sSourceMime, sTargetMime);
|
||||
}
|
||||
|
||||
return result;
|
||||
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
|
@ -0,0 +1,194 @@
|
|||
/************************************************************************
|
||||
*
|
||||
* GraphicConverterImpl1.java
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License version 2.1, as published by the Free Software Foundation.
|
||||
*
|
||||
* This library 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
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston,
|
||||
* MA 02111-1307 USA
|
||||
*
|
||||
* Copyright: 2002-2008 by Henrik Just
|
||||
*
|
||||
* All Rights Reserved.
|
||||
*/
|
||||
|
||||
// Version 1.0 (2008-11-22)
|
||||
|
||||
package org.openoffice.da.comp.w2lcommon.filter;
|
||||
|
||||
// Java uno helper class
|
||||
import com.sun.star.lib.uno.adapter.ByteArrayToXInputStreamAdapter;
|
||||
|
||||
// UNO classes
|
||||
import com.sun.star.beans.PropertyValue;
|
||||
import com.sun.star.graphic.XGraphic;
|
||||
import com.sun.star.graphic.XGraphicProvider;
|
||||
//import com.sun.star.io.XInputStream;
|
||||
//import com.sun.star.io.XOutputStream;
|
||||
import com.sun.star.lang.XMultiComponentFactory;
|
||||
import com.sun.star.uno.XComponentContext;
|
||||
import com.sun.star.uno.UnoRuntime;
|
||||
|
||||
//import java.io.InputStream;
|
||||
//import java.io.OutputStream;
|
||||
|
||||
import writer2latex.api.GraphicConverter;
|
||||
import writer2latex.api.MIMETypes;
|
||||
|
||||
/** A GraphicConverter implementation which uses the GraphicProvider service
|
||||
* to convert the graphic. This service does only support simple format
|
||||
* conversion using the "internal" graphics filters in Draw. Advanced features
|
||||
* like pdf, crop and resize thus cannot be handled.
|
||||
*/
|
||||
public class GraphicConverterImpl1 implements GraphicConverter {
|
||||
|
||||
// Signatures for start and end in exp
|
||||
private byte[] psStart;
|
||||
private byte[] psEnd;
|
||||
|
||||
|
||||
private XGraphicProvider xGraphicProvider;
|
||||
|
||||
public GraphicConverterImpl1(XComponentContext xComponentContext) {
|
||||
try {
|
||||
// Get the XGraphicProvider interface of the GraphicProvider service
|
||||
XMultiComponentFactory xMCF = xComponentContext.getServiceManager();
|
||||
Object graphicProviderObject = xMCF.createInstanceWithContext("com.sun.star.graphic.GraphicProvider", xComponentContext);
|
||||
xGraphicProvider = (XGraphicProvider) UnoRuntime.queryInterface(XGraphicProvider.class, graphicProviderObject);
|
||||
}
|
||||
catch (com.sun.star.uno.Exception ex) {
|
||||
System.err.println("Failed to get XGraphicProvider object");
|
||||
xGraphicProvider = null;
|
||||
}
|
||||
try {
|
||||
psStart = "%!PS-Adobe".getBytes("US-ASCII");
|
||||
psEnd = "%%EOF".getBytes("US-ASCII");
|
||||
}
|
||||
catch (java.io.UnsupportedEncodingException ex) {
|
||||
// US-ASCII *is* supported :-)
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
public boolean supportsConversion(String sSourceMime, String sTargetMime, boolean bCrop, boolean bResize) {
|
||||
// We don't support cropping and resizing
|
||||
if (bCrop || bResize) { return false; }
|
||||
|
||||
// We can convert vector formats to eps:
|
||||
if (MIMETypes.EPS.equals(sTargetMime) && (MIMETypes.WMF.equals(sSourceMime) && MIMETypes.SVM.equals(sSourceMime))) {
|
||||
return true;
|
||||
}
|
||||
|
||||
// And we can convert all formats to bitmaps
|
||||
boolean bSupportsSource =
|
||||
MIMETypes.PNG.equals(sSourceMime) || MIMETypes.JPEG.equals(sSourceMime) ||
|
||||
MIMETypes.GIF.equals(sSourceMime) || MIMETypes.TIFF.equals(sSourceMime) ||
|
||||
MIMETypes.BMP.equals(sSourceMime) || MIMETypes.WMF.equals(sSourceMime) ||
|
||||
MIMETypes.SVM.equals(sSourceMime);
|
||||
boolean bSupportsTarget =
|
||||
MIMETypes.PNG.equals(sTargetMime) || MIMETypes.JPEG.equals(sTargetMime) ||
|
||||
MIMETypes.GIF.equals(sTargetMime) || MIMETypes.TIFF.equals(sTargetMime) ||
|
||||
MIMETypes.BMP.equals(sTargetMime);
|
||||
return bSupportsSource && bSupportsTarget;
|
||||
}
|
||||
|
||||
public byte[] convert(byte[] source, String sSourceMime, String sTargetMime) {
|
||||
|
||||
// It seems that the GraphicProvider can only create proper eps if
|
||||
// the source is a vector format, hence
|
||||
if (MIMETypes.EPS.equals(sTargetMime)) {
|
||||
if (!MIMETypes.WMF.equals(sSourceMime) && !MIMETypes.SVM.equals(sSourceMime)) {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
ByteArrayToXInputStreamAdapter xSource = new ByteArrayToXInputStreamAdapter(source);
|
||||
ByteArrayXStream xTarget = new ByteArrayXStream();
|
||||
try {
|
||||
// Read the source
|
||||
PropertyValue[] sourceProps = new PropertyValue[1];
|
||||
sourceProps[0] = new PropertyValue();
|
||||
sourceProps[0].Name = "InputStream";
|
||||
sourceProps[0].Value = xSource;
|
||||
XGraphic result = xGraphicProvider.queryGraphic(sourceProps);
|
||||
|
||||
// Store as new type
|
||||
PropertyValue[] targetProps = new PropertyValue[2];
|
||||
targetProps[0] = new PropertyValue();
|
||||
targetProps[0].Name = "MimeType";
|
||||
targetProps[0].Value = sTargetMime;
|
||||
targetProps[1] = new PropertyValue();
|
||||
targetProps[1].Name = "OutputStream";
|
||||
targetProps[1].Value = xTarget;
|
||||
xGraphicProvider.storeGraphic(result,targetProps);
|
||||
|
||||
|
||||
// Close the output and return the result
|
||||
xTarget.closeOutput();
|
||||
xTarget.flush();
|
||||
if (MIMETypes.EPS.equals(sTargetMime)) {
|
||||
return cleanEps(xTarget.getBuffer());
|
||||
}
|
||||
else {
|
||||
return xTarget.getBuffer();
|
||||
}
|
||||
}
|
||||
catch (com.sun.star.io.IOException e) {
|
||||
return null;
|
||||
}
|
||||
catch (com.sun.star.lang.IllegalArgumentException e) {
|
||||
return null;
|
||||
}
|
||||
catch (com.sun.star.lang.WrappedTargetException e) {
|
||||
return null;
|
||||
}
|
||||
catch (Throwable e) {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
private byte[] cleanEps(byte[] blob) {
|
||||
int n = blob.length;
|
||||
|
||||
int nStart = 0;
|
||||
for (int i=0; i<n; i++) {
|
||||
if (match(blob,psStart,i)) {
|
||||
nStart=i;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
int nEnd = n;
|
||||
for (int i=nStart; i<n; i++) {
|
||||
if (match(blob,psEnd,i)) {
|
||||
nEnd=i+psEnd.length;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
byte[] newBlob = new byte[nEnd-nStart];
|
||||
System.arraycopy(blob,nStart,newBlob,0,nEnd-nStart);
|
||||
return newBlob;
|
||||
}
|
||||
|
||||
private boolean match(byte[] blob, byte[] sig, int nStart) {
|
||||
int n = sig.length;
|
||||
if (nStart+n>=blob.length) { return false; }
|
||||
for (int i=0; i<n; i++) {
|
||||
if (blob[nStart+i]!=sig[i]) { return false; }
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
|
@ -0,0 +1,267 @@
|
|||
/************************************************************************
|
||||
*
|
||||
* GraphicConverterImpl2.java
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License version 2.1, as published by the Free Software Foundation.
|
||||
*
|
||||
* This library 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
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston,
|
||||
* MA 02111-1307 USA
|
||||
*
|
||||
* Copyright: 2002-2008 by Henrik Just
|
||||
*
|
||||
* All Rights Reserved.
|
||||
*
|
||||
* Version 1.0 (2008-10-07)
|
||||
*
|
||||
*/
|
||||
|
||||
|
||||
package org.openoffice.da.comp.w2lcommon.filter;
|
||||
|
||||
import java.util.Hashtable;
|
||||
|
||||
import com.sun.star.awt.Point;
|
||||
import com.sun.star.awt.Size;
|
||||
import com.sun.star.beans.PropertyValue;
|
||||
import com.sun.star.beans.XPropertySet;
|
||||
import com.sun.star.drawing.XDrawPage;
|
||||
import com.sun.star.drawing.XDrawPages;
|
||||
import com.sun.star.drawing.XDrawPagesSupplier;
|
||||
import com.sun.star.drawing.XShape;
|
||||
import com.sun.star.frame.XComponentLoader;
|
||||
import com.sun.star.frame.XStorable;
|
||||
import com.sun.star.lang.XComponent;
|
||||
import com.sun.star.lang.XMultiComponentFactory;
|
||||
import com.sun.star.uno.XComponentContext;
|
||||
import com.sun.star.uno.UnoRuntime;
|
||||
import com.sun.star.util.XRefreshable;
|
||||
|
||||
import com.sun.star.lib.uno.adapter.ByteArrayToXInputStreamAdapter;
|
||||
import com.sun.star.lib.uno.adapter.XOutputStreamToByteArrayAdapter;
|
||||
|
||||
import writer2latex.api.GraphicConverter;
|
||||
import writer2latex.api.MIMETypes;
|
||||
|
||||
/** A GraphicConverter implementation which uses a hidden Draw document to
|
||||
* store the graphic, providing more control over the image than the
|
||||
* simple GraphicProvider implementation.
|
||||
*/
|
||||
public class GraphicConverterImpl2 implements GraphicConverter {
|
||||
|
||||
private XComponentContext xComponentContext;
|
||||
private Hashtable importFilter;
|
||||
private Hashtable exportFilter;
|
||||
|
||||
public GraphicConverterImpl2(XComponentContext xComponentContext) {
|
||||
this.xComponentContext = xComponentContext;
|
||||
|
||||
importFilter = new Hashtable();
|
||||
importFilter.put(MIMETypes.BMP, "BMP - MS Windows");
|
||||
//importFilter.put(MIMETypes.EMF, "EMF - MS Windows Metafile");
|
||||
importFilter.put(MIMETypes.EPS, "EPS - Encapsulated PostScript");
|
||||
importFilter.put(MIMETypes.GIF, "GIF - Graphics Interchange Format");
|
||||
importFilter.put(MIMETypes.JPEG, "JPG - JPEG");
|
||||
importFilter.put(MIMETypes.PNG, "PNG - Portable Network Graphic");
|
||||
importFilter.put(MIMETypes.SVM, "SVM - StarView Metafile");
|
||||
importFilter.put(MIMETypes.TIFF, "TIF - Tag Image File");
|
||||
importFilter.put(MIMETypes.WMF, "WMF - MS Windows Metafile");
|
||||
|
||||
exportFilter = new Hashtable();
|
||||
exportFilter.put(MIMETypes.BMP,"draw_bmp_Export");
|
||||
//exportFilter.put(MIMETypes.EMF,"draw_emf_Export");
|
||||
exportFilter.put(MIMETypes.EPS,"draw_eps_Export");
|
||||
exportFilter.put(MIMETypes.GIF,"draw_gif_Export");
|
||||
exportFilter.put(MIMETypes.JPEG,"draw_jpg_Export");
|
||||
exportFilter.put(MIMETypes.PNG,"draw_png_Export");
|
||||
//exportFilter.put(MIMETypes.SVG,"draw_svg_Export");
|
||||
exportFilter.put(MIMETypes.SVM,"draw_svm_Export");
|
||||
exportFilter.put(MIMETypes.TIFF,"draw_tif_Export");
|
||||
exportFilter.put(MIMETypes.WMF,"draw_wmf_Export");
|
||||
exportFilter.put(MIMETypes.PDF,"draw_pdf_Export");
|
||||
}
|
||||
|
||||
public boolean supportsConversion(String sSourceMime, String sTargetMime, boolean bCrop, boolean bResize) {
|
||||
// We don't support cropping and resizing
|
||||
if (bCrop || bResize) { return false; }
|
||||
|
||||
// We currently only support conversion of svm into pdf
|
||||
// Trying wmf causes an IllegalArgumentException "URL seems to be an unsupported one"
|
||||
// Seems to be an OOo bug; workaround: Use temporary files..??
|
||||
boolean bSupportsSource = MIMETypes.SVM.equals(sSourceMime);
|
||||
/*MIMETypes.PNG.equals(sSourceMime) || MIMETypes.JPEG.equals(sSourceMime) ||
|
||||
MIMETypes.GIF.equals(sSourceMime) || MIMETypes.TIFF.equals(sSourceMime) ||
|
||||
MIMETypes.BMP.equals(sSourceMime) || MIMETypes.WMF.equals(sSourceMime) ||
|
||||
MIMETypes.SVM.equals(sSourceMime);*/
|
||||
return bSupportsSource && MIMETypes.PDF.equals(sTargetMime);
|
||||
}
|
||||
|
||||
public byte[] convert(byte[] source, String sSourceMime, String sTargetMime) {
|
||||
// Open a hidden sdraw document
|
||||
XMultiComponentFactory xMCF = xComponentContext.getServiceManager();
|
||||
|
||||
org.openoffice.da.comp.w2lcommon.helper.MessageBox msgBox = new org.openoffice.da.comp.w2lcommon.helper.MessageBox(xComponentContext);
|
||||
|
||||
try {
|
||||
// Load the graphic into a new draw document as xDocument
|
||||
// using a named filter
|
||||
Object desktop = xMCF.createInstanceWithContext(
|
||||
"com.sun.star.frame.Desktop", xComponentContext);
|
||||
|
||||
XComponentLoader xComponentLoader = (XComponentLoader)
|
||||
UnoRuntime.queryInterface(XComponentLoader.class, desktop);
|
||||
//msgBox.showMessage("Graphics","Trying to load using filter name "+importFilter.get(sSourceMime));
|
||||
|
||||
PropertyValue[] fileProps = new PropertyValue[3];
|
||||
fileProps[0] = new PropertyValue();
|
||||
fileProps[0].Name = "FilterName";
|
||||
fileProps[0].Value = (String) importFilter.get(sSourceMime);
|
||||
fileProps[1] = new PropertyValue();
|
||||
fileProps[1].Name = "InputStream";
|
||||
fileProps[1].Value = new ByteArrayToXInputStreamAdapter(source);
|
||||
fileProps[2] = new PropertyValue();
|
||||
fileProps[2].Name = "Hidden";
|
||||
fileProps[2].Value = new Boolean(true);
|
||||
|
||||
XComponent xDocument = xComponentLoader.loadComponentFromURL(
|
||||
"private:stream", "_blank", 0, fileProps);
|
||||
|
||||
// Get the first draw page as xDrawPage
|
||||
XDrawPagesSupplier xDrawPagesSupplier = (XDrawPagesSupplier)
|
||||
UnoRuntime.queryInterface(XDrawPagesSupplier.class, xDocument);
|
||||
XDrawPages xDrawPages = xDrawPagesSupplier.getDrawPages();
|
||||
Object drawPage = xDrawPages.getByIndex(0);
|
||||
XDrawPage xDrawPage = (XDrawPage) UnoRuntime.queryInterface(
|
||||
XDrawPage.class, drawPage);
|
||||
|
||||
// Get the shape as xShape
|
||||
Object shape = xDrawPage.getByIndex(0);
|
||||
XShape xShape = (XShape) UnoRuntime.queryInterface(XShape.class, shape);
|
||||
|
||||
// Move the shape to upper left corner of the page
|
||||
Point position = new Point();
|
||||
position.X = 0;
|
||||
position.Y = 0;
|
||||
xShape.setPosition(position);
|
||||
|
||||
// Adjust the page size and margin to the size of the graphic
|
||||
XPropertySet xPageProps = (XPropertySet) UnoRuntime.queryInterface(
|
||||
XPropertySet.class, xDrawPage);
|
||||
Size size = xShape.getSize();
|
||||
xPageProps.setPropertyValue("Width", new Integer(size.Width));
|
||||
xPageProps.setPropertyValue("Height", new Integer(size.Height));
|
||||
xPageProps.setPropertyValue("BorderTop", new Integer(0));
|
||||
xPageProps.setPropertyValue("BorderBottom", new Integer(0));
|
||||
xPageProps.setPropertyValue("BorderLeft", new Integer(0));
|
||||
xPageProps.setPropertyValue("BorderRight", new Integer(0));
|
||||
|
||||
// Export the draw document (xDocument)
|
||||
refreshDocument(xDocument);
|
||||
|
||||
XOutputStreamToByteArrayAdapter outputStream = new XOutputStreamToByteArrayAdapter();
|
||||
|
||||
PropertyValue[] exportProps = new PropertyValue[3];
|
||||
exportProps[0] = new PropertyValue();
|
||||
exportProps[0].Name = "FilterName";
|
||||
exportProps[0].Value = (String) exportFilter.get(sTargetMime);
|
||||
exportProps[1] = new PropertyValue();
|
||||
exportProps[1].Name = "OutputStream";
|
||||
exportProps[1].Value = outputStream;
|
||||
exportProps[2] = new PropertyValue();
|
||||
exportProps[2].Name = "Overwrite";
|
||||
exportProps[2].Value = new Boolean(true);
|
||||
|
||||
XStorable xStore = (XStorable) UnoRuntime.queryInterface (
|
||||
XStorable.class, xDocument);
|
||||
xStore.storeToURL ("private:stream", exportProps);
|
||||
outputStream.closeOutput();
|
||||
|
||||
byte[] result = outputStream.getBuffer();
|
||||
xDocument.dispose();
|
||||
|
||||
return result;
|
||||
|
||||
}
|
||||
catch (com.sun.star.beans.PropertyVetoException e) {
|
||||
msgBox.showMessage("Exception",e.toString());
|
||||
}
|
||||
catch (com.sun.star.beans.UnknownPropertyException e) {
|
||||
msgBox.showMessage("Exception",e.toString());
|
||||
}
|
||||
catch (com.sun.star.io.IOException e) {
|
||||
msgBox.showMessage("Exception",e.toString());
|
||||
}
|
||||
catch (com.sun.star.lang.IllegalArgumentException e) {
|
||||
msgBox.showMessage("Exception",e.toString());
|
||||
}
|
||||
catch (com.sun.star.lang.IndexOutOfBoundsException e) {
|
||||
msgBox.showMessage("Exception",e.toString());
|
||||
}
|
||||
catch (com.sun.star.lang.WrappedTargetException e) {
|
||||
msgBox.showMessage("Exception",e.toString());
|
||||
}
|
||||
catch (com.sun.star.uno.Exception e) {
|
||||
msgBox.showMessage("Exception",e.toString());
|
||||
}
|
||||
|
||||
// Conversion failed, for whatever reason
|
||||
return null;
|
||||
|
||||
}
|
||||
|
||||
protected void refreshDocument(XComponent document) {
|
||||
XRefreshable refreshable = (XRefreshable) UnoRuntime.queryInterface(XRefreshable.class, document);
|
||||
if (refreshable != null) {
|
||||
refreshable.refresh();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
/* Dim SelSize As New com.sun.star.awt.Size
|
||||
SelSize = oGraphic.Size
|
||||
oDrawGraphic.GraphicURL = oGraphic.GraphicURL
|
||||
oDrawGraphic.Size = SelSize
|
||||
oDrawPage.add(oDrawGraphic)
|
||||
oDrawGraphic.GraphicCrop = oGraphic.GraphicCrop
|
||||
oDrawPage.Width = oGraphic.Size.Width
|
||||
oDrawPage.Height = oGraphic.Size.Height
|
||||
Dim aFilterData (1) As new com.sun.star.beans.PropertyValue
|
||||
aFilterData(0).Name = "PixelWidth" '
|
||||
aFilterData(0).Value = oDrawPage.Width/100 * iPixels / 25.40
|
||||
aFilterData(1).Name = "PixelHeight"
|
||||
aFilterData(1).Value = oDrawPage.Height/100 * iPixels / 25.40
|
||||
Export( oDrawPage, sURLImageResized , aFilterData() )
|
||||
On error resume Next
|
||||
oDrawDoc.Close(True)
|
||||
On error goto 0
|
||||
|
||||
SUB Export( xObject, sFileUrl As String, aFilterData )
|
||||
Dim xExporter As Object
|
||||
xExporter = createUnoService( "com.sun.star.drawing.GraphicExportFilter" )
|
||||
xExporter.SetSourceDocument( xObject )
|
||||
Dim aArgs (2) As new com.sun.star.beans.PropertyValue
|
||||
'sFileURL = ConvertToURL(sFileURL)
|
||||
aArgs(0).Name = "FilterName"
|
||||
aArgs(0).Value = "jpg"
|
||||
aArgs(1).Name = "URL"
|
||||
aArgs(1).Value = sFileURL
|
||||
'print sFileURL
|
||||
aArgs(2).Name = "FilterData"
|
||||
aArgs(2).Value = aFilterData
|
||||
xExporter.filter( aArgs() )
|
||||
END SUB*/
|
||||
|
||||
|
||||
|
||||
}
|
||||
|
|
@ -0,0 +1,547 @@
|
|||
/************************************************************************
|
||||
*
|
||||
* OptionsDialogBase.java
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License version 2.1, as published by the Free Software Foundation.
|
||||
*
|
||||
* This library 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
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston,
|
||||
* MA 02111-1307 USA
|
||||
*
|
||||
* Copyright: 2002-2008 by Henrik Just
|
||||
*
|
||||
* All Rights Reserved.
|
||||
*
|
||||
* Version 1.0 (2008-10-14)
|
||||
*
|
||||
*/
|
||||
|
||||
package org.openoffice.da.comp.w2lcommon.filter;
|
||||
|
||||
import java.util.HashSet;
|
||||
|
||||
import com.sun.star.awt.XDialogEventHandler;
|
||||
import com.sun.star.beans.PropertyValue;
|
||||
import com.sun.star.beans.XPropertyAccess;
|
||||
import com.sun.star.beans.XPropertySet;
|
||||
import com.sun.star.container.XNameAccess;
|
||||
import com.sun.star.document.XDocumentInfoSupplier;
|
||||
import com.sun.star.frame.XDesktop;
|
||||
import com.sun.star.lang.XComponent;
|
||||
import com.sun.star.lang.IllegalArgumentException;
|
||||
import com.sun.star.lang.XMultiServiceFactory;
|
||||
import com.sun.star.lang.XServiceInfo;
|
||||
import com.sun.star.lang.XServiceName;
|
||||
import com.sun.star.lang.XTypeProvider;
|
||||
import com.sun.star.ui.dialogs.XExecutableDialog;
|
||||
import com.sun.star.uno.Type;
|
||||
import com.sun.star.uno.UnoRuntime;
|
||||
import com.sun.star.uno.XComponentContext;
|
||||
import com.sun.star.util.XChangesBatch;
|
||||
import com.sun.star.util.XMacroExpander;
|
||||
|
||||
import org.openoffice.da.comp.w2lcommon.helper.DialogBase;
|
||||
import org.openoffice.da.comp.w2lcommon.helper.PropertyHelper;
|
||||
|
||||
/** This class provides an abstract uno component which implements a filter ui
|
||||
*/
|
||||
public abstract class OptionsDialogBase extends DialogBase implements
|
||||
XPropertyAccess { // Filter ui requires XExecutableDialog + XPropertyAccess
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
// The subclass must override the following; and override the
|
||||
// implementation of XDialogEventHandler if needed
|
||||
|
||||
/** Load settings from the registry to the dialog
|
||||
* The subclass must implement this
|
||||
*/
|
||||
protected abstract void loadSettings(XPropertySet xRegistryProps);
|
||||
|
||||
/** Save settings from the dialog to the registry and create FilterData
|
||||
* The subclass must implement this
|
||||
*/
|
||||
protected abstract void saveSettings(XPropertySet xRegistryProps, PropertyHelper filterData);
|
||||
|
||||
/** Return the name of the library containing the dialog
|
||||
*/
|
||||
public abstract String getDialogLibraryName();
|
||||
|
||||
/** Return the name of the dialog within the library
|
||||
*/
|
||||
public abstract String getDialogName();
|
||||
|
||||
/** Return the path to the options in the registry */
|
||||
public abstract String getRegistryPath();
|
||||
|
||||
/** Create a new OptionsDialogBase */
|
||||
public OptionsDialogBase(XComponentContext xContext) {
|
||||
super(xContext);
|
||||
this.xMSF = null; // must be set properly by subclass
|
||||
mediaProps = null;
|
||||
sConfigNames = null;
|
||||
lockedOptions = new HashSet();
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
// Implement some methods required by DialogBase
|
||||
|
||||
/** Initialize the dialog (eg. with settings from the registry)
|
||||
*/
|
||||
public void initialize() {
|
||||
try {
|
||||
// Prepare registry view
|
||||
Object view = getRegistryView(false);
|
||||
XPropertySet xProps = (XPropertySet)
|
||||
UnoRuntime.queryInterface(XPropertySet.class,view);
|
||||
|
||||
// Load settings using method from subclass
|
||||
loadSettings(xProps);
|
||||
|
||||
// Dispose the registry view
|
||||
disposeRegistryView(view);
|
||||
}
|
||||
catch (com.sun.star.uno.Exception e) {
|
||||
// Failed to get registry view
|
||||
}
|
||||
}
|
||||
|
||||
/** Finalize the dialog after execution (eg. save settings to the registry)
|
||||
*/
|
||||
public void finalize() {
|
||||
try {
|
||||
// Prepare registry view
|
||||
Object rwview = getRegistryView(true);
|
||||
XPropertySet xProps = (XPropertySet)
|
||||
UnoRuntime.queryInterface(XPropertySet.class,rwview);
|
||||
|
||||
// Save settings and create FilterData using method from subclass
|
||||
PropertyHelper filterData = new PropertyHelper();
|
||||
saveSettings(xProps, filterData);
|
||||
|
||||
// Commit registry changes
|
||||
XChangesBatch xUpdateContext = (XChangesBatch)
|
||||
UnoRuntime.queryInterface(XChangesBatch.class,rwview);
|
||||
try {
|
||||
xUpdateContext.commitChanges();
|
||||
}
|
||||
catch (Exception e) {
|
||||
// ignore
|
||||
}
|
||||
|
||||
// Dispose the registry view
|
||||
disposeRegistryView(rwview);
|
||||
|
||||
// Update the media properties with the FilterData
|
||||
PropertyHelper helper = new PropertyHelper(mediaProps);
|
||||
helper.put("FilterData",filterData.toArray());
|
||||
mediaProps = helper.toArray();
|
||||
}
|
||||
catch (com.sun.star.uno.Exception e) {
|
||||
// Failed to get registry view
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
// Some private global variables
|
||||
|
||||
// The service factory
|
||||
protected XMultiServiceFactory xMSF;
|
||||
|
||||
// The media properties (set/get via XPropertyAccess implementation)
|
||||
private PropertyValue[] mediaProps;
|
||||
|
||||
// Configuration names (stored during execution of dialog)
|
||||
private String[] sConfigNames;
|
||||
|
||||
// Set of locked controls
|
||||
private HashSet lockedOptions;
|
||||
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
// Some private utility methods
|
||||
|
||||
// Perform macro extansion
|
||||
private String expandMacros(String s) {
|
||||
if (s.startsWith("vnd.sun.star.expand:")) {
|
||||
// The string contains a macro, usually as a result of using %origin% in the registry
|
||||
s = s.substring(20);
|
||||
Object expander = xContext.getValueByName("/singletons/com.sun.star.util.theMacroExpander");
|
||||
XMacroExpander xExpander = (XMacroExpander) UnoRuntime.queryInterface (XMacroExpander.class, expander);
|
||||
try {
|
||||
return xExpander.expandMacros(s);
|
||||
}
|
||||
catch (IllegalArgumentException e) {
|
||||
// Unknown macro name found, proceed and hope for the best
|
||||
return s;
|
||||
}
|
||||
}
|
||||
else {
|
||||
return s;
|
||||
}
|
||||
}
|
||||
|
||||
// Get the template name from the document with ui focus
|
||||
private String getTemplateName() {
|
||||
try {
|
||||
// Get current component
|
||||
Object desktop = xContext.getServiceManager()
|
||||
.createInstanceWithContext("com.sun.star.frame.Desktop",xContext);
|
||||
XDesktop xDesktop = (XDesktop) UnoRuntime.queryInterface(XDesktop.class,desktop);
|
||||
XComponent xComponent = xDesktop.getCurrentComponent();
|
||||
|
||||
// Get the document info property set
|
||||
XDocumentInfoSupplier xDocInfoSuppl = (XDocumentInfoSupplier)
|
||||
UnoRuntime.queryInterface(XDocumentInfoSupplier.class, xComponent);
|
||||
Object docInfo = xDocInfoSuppl.getDocumentInfo();
|
||||
XPropertySet xDocInfo = (XPropertySet)
|
||||
UnoRuntime.queryInterface(XPropertySet.class, docInfo);
|
||||
|
||||
return getPropertyValueAsString(xDocInfo,"Template");
|
||||
}
|
||||
catch (Exception e) {
|
||||
return "";
|
||||
}
|
||||
}
|
||||
|
||||
// Get a view of the options root in the registry
|
||||
private Object getRegistryView(boolean bUpdate)
|
||||
throws com.sun.star.uno.Exception {
|
||||
Object provider = xMSF.createInstance(
|
||||
"com.sun.star.configuration.ConfigurationProvider");
|
||||
XMultiServiceFactory xProvider = (XMultiServiceFactory)
|
||||
UnoRuntime.queryInterface(XMultiServiceFactory.class,provider);
|
||||
PropertyValue[] args = new PropertyValue[1];
|
||||
args[0] = new PropertyValue();
|
||||
args[0].Name = "nodepath";
|
||||
args[0].Value = getRegistryPath();
|
||||
String sServiceName = bUpdate ?
|
||||
"com.sun.star.configuration.ConfigurationUpdateAccess" :
|
||||
"com.sun.star.configuration.ConfigurationAccess";
|
||||
Object view = xProvider.createInstanceWithArguments(sServiceName,args);
|
||||
return view;
|
||||
}
|
||||
|
||||
// Dispose a previously obtained registry view
|
||||
private void disposeRegistryView(Object view) {
|
||||
XComponent xComponent = (XComponent)
|
||||
UnoRuntime.queryInterface(XComponent.class,view);
|
||||
xComponent.dispose();
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
// Implement uno interfaces
|
||||
|
||||
// Override getTypes() from the interface XTypeProvider
|
||||
public Type[] getTypes() {
|
||||
Type[] typeReturn = {};
|
||||
try {
|
||||
typeReturn = new Type[] {
|
||||
new Type( XServiceName.class ),
|
||||
new Type( XServiceInfo.class ),
|
||||
new Type( XTypeProvider.class ),
|
||||
new Type( XExecutableDialog.class ),
|
||||
new Type( XPropertyAccess.class ),
|
||||
new Type( XDialogEventHandler.class ) };
|
||||
} catch(Exception exception) {
|
||||
}
|
||||
return typeReturn;
|
||||
}
|
||||
|
||||
|
||||
// Implement the interface XPropertyAccess
|
||||
public PropertyValue[] getPropertyValues() {
|
||||
return mediaProps;
|
||||
}
|
||||
|
||||
public void setPropertyValues(PropertyValue[] props) {
|
||||
mediaProps = props;
|
||||
}
|
||||
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
// Various utility methods to be used by the sublasses
|
||||
|
||||
// Helpers to load and save settings
|
||||
|
||||
protected void updateLockedOptions() {
|
||||
lockedOptions.clear();
|
||||
short nItem = getListBoxSelectedItem("Config");
|
||||
int nStdConfigs = getListBoxStringItemList("Config").length - sConfigNames.length;
|
||||
if (nItem>=nStdConfigs) {
|
||||
// Get current configuration name
|
||||
String sName = sConfigNames[nItem-nStdConfigs];
|
||||
|
||||
try {
|
||||
// Prepare registry view
|
||||
Object view = getRegistryView(false);
|
||||
XPropertySet xProps = (XPropertySet)
|
||||
UnoRuntime.queryInterface(XPropertySet.class,view);
|
||||
|
||||
// Get the available configurations
|
||||
Object configurations = getPropertyValue(xProps,"Configurations");
|
||||
XNameAccess xConfigurations = (XNameAccess)
|
||||
UnoRuntime.queryInterface(XNameAccess.class,configurations);
|
||||
|
||||
// Get the LockedOptions node from the desired configuration
|
||||
String sLockedOptions = "";
|
||||
Object config = xConfigurations.getByName(sName);
|
||||
XPropertySet xCfgProps = (XPropertySet)
|
||||
UnoRuntime.queryInterface(XPropertySet.class,config);
|
||||
sLockedOptions = getPropertyValueAsString(xCfgProps,"LockedOptions");
|
||||
|
||||
// Dispose the registry view
|
||||
disposeRegistryView(view);
|
||||
|
||||
// Feed lockedOptions with the comma separated list of options
|
||||
int nStart = 0;
|
||||
for (int i=0; i<sLockedOptions.length(); i++) {
|
||||
if (sLockedOptions.charAt(i)==',') {
|
||||
lockedOptions.add(sLockedOptions.substring(nStart,i).trim());
|
||||
nStart = i+1;
|
||||
}
|
||||
}
|
||||
if (nStart<sLockedOptions.length()) {
|
||||
lockedOptions.add(sLockedOptions.substring(nStart).trim());
|
||||
}
|
||||
}
|
||||
catch (Exception e) {
|
||||
// no options will be locked...
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
protected boolean isLocked(String sOptionName) {
|
||||
return lockedOptions.contains(sOptionName);
|
||||
}
|
||||
|
||||
// Configuration
|
||||
protected void loadConfig(XPropertySet xProps) {
|
||||
// The list box is extended with configurations from the registry
|
||||
String[] sStdConfigs = getListBoxStringItemList("Config");
|
||||
int nStdConfigs = sStdConfigs.length;
|
||||
|
||||
Object configurations = getPropertyValue(xProps,"Configurations");
|
||||
XNameAccess xConfigurations = (XNameAccess)
|
||||
UnoRuntime.queryInterface(XNameAccess.class,configurations);
|
||||
sConfigNames = xConfigurations.getElementNames();
|
||||
int nRegConfigs = sConfigNames.length;
|
||||
|
||||
String[] sAllConfigs = new String[nStdConfigs+nRegConfigs];
|
||||
for (short i=0; i<nStdConfigs; i++) {
|
||||
sAllConfigs[i] = sStdConfigs[i];
|
||||
}
|
||||
|
||||
for (short i=0; i<nRegConfigs; i++) {
|
||||
try {
|
||||
Object config = xConfigurations.getByName(sConfigNames[i]);
|
||||
XPropertySet xCfgProps = (XPropertySet)
|
||||
UnoRuntime.queryInterface(XPropertySet.class,config);
|
||||
sAllConfigs[nStdConfigs+i] = getPropertyValueAsString(xCfgProps,"DisplayName");
|
||||
}
|
||||
catch (Exception e) {
|
||||
sAllConfigs[nStdConfigs+i] = "";
|
||||
}
|
||||
}
|
||||
|
||||
setListBoxStringItemList("Config",sAllConfigs);
|
||||
if (nStdConfigs+nRegConfigs<=12) {
|
||||
setListBoxLineCount("Config",(short) (nStdConfigs+nRegConfigs));
|
||||
}
|
||||
else {
|
||||
setListBoxLineCount("Config",(short) 12);
|
||||
}
|
||||
|
||||
// Select item based on template name
|
||||
String sTheTemplateName = getTemplateName();
|
||||
Object templates = getPropertyValue(xProps,"Templates");
|
||||
XNameAccess xTemplates = (XNameAccess)
|
||||
UnoRuntime.queryInterface(XNameAccess.class,templates);
|
||||
String[] sTemplateNames = xTemplates.getElementNames();
|
||||
for (int i=0; i<sTemplateNames.length; i++) {
|
||||
try {
|
||||
Object template = xTemplates.getByName(sTemplateNames[i]);
|
||||
XPropertySet xTplProps = (XPropertySet)
|
||||
UnoRuntime.queryInterface(XPropertySet.class,template);
|
||||
String sTemplateName = getPropertyValueAsString(xTplProps,"TemplateName");
|
||||
if (sTemplateName.equals(sTheTemplateName)) {
|
||||
String sConfigName = getPropertyValueAsString(xTplProps,"ConfigName");
|
||||
for (short j=0; j<nRegConfigs; j++) {
|
||||
if (sConfigNames[j].equals(sConfigName)) {
|
||||
setListBoxSelectedItem("Config",(short) (nStdConfigs+j));
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
catch (Exception e) {
|
||||
// ignore
|
||||
}
|
||||
}
|
||||
|
||||
// Select item based on value stored in registry
|
||||
short nConfig = getPropertyValueAsShort(xProps,"Config");
|
||||
if (nConfig<nStdConfigs) {
|
||||
setListBoxSelectedItem("Config",nConfig);
|
||||
}
|
||||
else { // Registry configurations are stored by name
|
||||
String sConfigName = getPropertyValueAsString(xProps,"ConfigName");
|
||||
for (short i=0; i<nRegConfigs; i++) {
|
||||
if (sConfigNames[i].equals(sConfigName)) {
|
||||
setListBoxSelectedItem("Config",(short) (nStdConfigs+i));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
protected short saveConfig(XPropertySet xProps, PropertyHelper filterData) {
|
||||
// The Config list box is common for all dialogs
|
||||
Object configurations = getPropertyValue(xProps,"Configurations");
|
||||
XNameAccess xNameAccess = (XNameAccess)
|
||||
UnoRuntime.queryInterface(XNameAccess.class,configurations);
|
||||
|
||||
boolean bFound = false;
|
||||
short nConfig = getListBoxSelectedItem("Config");
|
||||
int nStdConfigs = getListBoxStringItemList("Config").length - sConfigNames.length;
|
||||
if (nConfig>=nStdConfigs) { // only handle registry configurations
|
||||
int i = nConfig-nStdConfigs;
|
||||
try {
|
||||
Object config = xNameAccess.getByName(sConfigNames[i]);
|
||||
XPropertySet xCfgProps = (XPropertySet)
|
||||
UnoRuntime.queryInterface(XPropertySet.class,config);
|
||||
filterData.put("ConfigURL",expandMacros(getPropertyValueAsString(xCfgProps,"ConfigURL")));
|
||||
filterData.put("TemplateURL",expandMacros(getPropertyValueAsString(xCfgProps,"TargetTemplateURL")));
|
||||
setPropertyValue(xProps,"ConfigName",sConfigNames[i]);
|
||||
bFound = true;
|
||||
}
|
||||
catch (Exception e) {
|
||||
}
|
||||
}
|
||||
setPropertyValue(xProps,"Config",nConfig);
|
||||
if (!bFound) { setPropertyValue(xProps,"ConfigName",""); }
|
||||
return nConfig;
|
||||
}
|
||||
|
||||
// Check box option (boolean)
|
||||
protected boolean loadCheckBoxOption(XPropertySet xProps, String sName) {
|
||||
boolean bValue = getPropertyValueAsBoolean(xProps,sName);
|
||||
setCheckBoxStateAsBoolean(sName, bValue);
|
||||
return bValue;
|
||||
}
|
||||
|
||||
protected boolean saveCheckBoxOption(XPropertySet xProps, String sName) {
|
||||
boolean bValue = getCheckBoxStateAsBoolean(sName);
|
||||
setPropertyValue(xProps, sName, bValue);
|
||||
return bValue;
|
||||
}
|
||||
|
||||
protected boolean saveCheckBoxOption(XPropertySet xProps, PropertyHelper filterData,
|
||||
String sName, String sOptionName) {
|
||||
boolean bValue = saveCheckBoxOption(xProps, sName);
|
||||
if (!isLocked(sOptionName)) {
|
||||
filterData.put(sOptionName, Boolean.toString(bValue));
|
||||
}
|
||||
return bValue;
|
||||
}
|
||||
|
||||
// List box option
|
||||
protected short loadListBoxOption(XPropertySet xProps, String sName) {
|
||||
short nValue = getPropertyValueAsShort(xProps, sName);
|
||||
setListBoxSelectedItem(sName ,nValue);
|
||||
return nValue;
|
||||
}
|
||||
|
||||
protected short saveListBoxOption(XPropertySet xProps, String sName) {
|
||||
short nValue = getListBoxSelectedItem(sName);
|
||||
setPropertyValue(xProps, sName, nValue);
|
||||
return nValue;
|
||||
}
|
||||
|
||||
protected short saveListBoxOption(XPropertySet xProps, PropertyHelper filterData,
|
||||
String sName, String sOptionName, String[] sValues) {
|
||||
short nValue = saveListBoxOption(xProps, sName);
|
||||
if (!isLocked(sOptionName) && (nValue>=0) && (nValue<sValues.length)) {
|
||||
filterData.put(sOptionName, sValues[nValue]);
|
||||
}
|
||||
return nValue;
|
||||
}
|
||||
|
||||
// Combo box option
|
||||
protected String loadComboBoxOption(XPropertySet xProps, String sName) {
|
||||
String sValue = getPropertyValueAsString(xProps, sName);
|
||||
setComboBoxText(sName ,sValue);
|
||||
return sValue;
|
||||
}
|
||||
|
||||
protected String saveComboBoxOption(XPropertySet xProps, String sName) {
|
||||
String sValue = getComboBoxText(sName);
|
||||
setPropertyValue(xProps, sName, sValue);
|
||||
return sValue;
|
||||
}
|
||||
|
||||
protected String saveComboBoxOption(XPropertySet xProps, PropertyHelper filterData,
|
||||
String sName, String sOptionName) {
|
||||
String sValue = saveComboBoxOption(xProps, sName);
|
||||
if (!isLocked(sOptionName)) {
|
||||
filterData.put(sOptionName, sValue);
|
||||
}
|
||||
return sValue;
|
||||
}
|
||||
|
||||
// Text Field option
|
||||
protected String loadTextFieldOption(XPropertySet xProps, String sName) {
|
||||
String sValue = getPropertyValueAsString(xProps, sName);
|
||||
setTextFieldText(sName ,sValue);
|
||||
return sValue;
|
||||
}
|
||||
|
||||
protected String saveTextFieldOption(XPropertySet xProps, String sName) {
|
||||
String sValue = getTextFieldText(sName);
|
||||
setPropertyValue(xProps, sName, sValue);
|
||||
return sValue;
|
||||
}
|
||||
|
||||
protected String saveTextFieldOption(XPropertySet xProps, PropertyHelper filterData,
|
||||
String sName, String sOptionName) {
|
||||
String sValue = saveTextFieldOption(xProps, sName);
|
||||
if (!isLocked(sOptionName)) {
|
||||
filterData.put(sOptionName, sValue);
|
||||
}
|
||||
return sValue;
|
||||
}
|
||||
|
||||
// Numeric option
|
||||
protected int loadNumericOption(XPropertySet xProps, String sName) {
|
||||
int nValue = getPropertyValueAsInteger(xProps, sName);
|
||||
setNumericFieldValue(sName, nValue);
|
||||
return nValue;
|
||||
}
|
||||
|
||||
protected int saveNumericOption(XPropertySet xProps, String sName) {
|
||||
int nValue = getNumericFieldValue(sName);
|
||||
setPropertyValue(xProps, sName, nValue);
|
||||
return nValue;
|
||||
}
|
||||
|
||||
protected int saveNumericOptionAsPercentage(XPropertySet xProps,
|
||||
PropertyHelper filterData, String sName, String sOptionName) {
|
||||
int nValue = saveNumericOption(xProps, sName);
|
||||
if (!isLocked(sOptionName)) {
|
||||
filterData.put(sOptionName,Integer.toString(nValue)+"%");
|
||||
}
|
||||
return nValue;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
|
@ -0,0 +1,503 @@
|
|||
/************************************************************************
|
||||
*
|
||||
* DialogBase.java
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License version 2.1, as published by the Free Software Foundation.
|
||||
*
|
||||
* This library 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
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston,
|
||||
* MA 02111-1307 USA
|
||||
*
|
||||
* Copyright: 2002-2008 by Henrik Just
|
||||
*
|
||||
* All Rights Reserved.
|
||||
*
|
||||
* Version 1.0 (2008-09-11)
|
||||
*
|
||||
*/
|
||||
|
||||
package org.openoffice.da.comp.w2lcommon.helper;
|
||||
|
||||
import com.sun.star.awt.XControl;
|
||||
import com.sun.star.awt.XControlContainer;
|
||||
import com.sun.star.awt.XControlModel;
|
||||
import com.sun.star.awt.XDialog;
|
||||
import com.sun.star.awt.XDialogEventHandler;
|
||||
import com.sun.star.awt.XDialogProvider2;
|
||||
import com.sun.star.beans.PropertyVetoException;
|
||||
import com.sun.star.beans.UnknownPropertyException;
|
||||
import com.sun.star.beans.XPropertySet;
|
||||
import com.sun.star.lang.IllegalArgumentException;
|
||||
import com.sun.star.lang.WrappedTargetException;
|
||||
import com.sun.star.lang.XMultiComponentFactory;
|
||||
import com.sun.star.lang.XServiceInfo;
|
||||
import com.sun.star.lang.XServiceName;
|
||||
import com.sun.star.lang.XTypeProvider;
|
||||
import com.sun.star.ui.dialogs.ExecutableDialogResults;
|
||||
import com.sun.star.ui.dialogs.XExecutableDialog;
|
||||
import com.sun.star.uno.Type;
|
||||
import com.sun.star.uno.UnoRuntime;
|
||||
import com.sun.star.uno.XComponentContext;
|
||||
|
||||
|
||||
/** This class provides an abstract uno component which implements a dialog
|
||||
* from an xml description (using the DialogProvider2 service)
|
||||
*/
|
||||
public abstract class DialogBase implements
|
||||
XTypeProvider, XServiceInfo, XServiceName, // Uno component
|
||||
XExecutableDialog, // Execute the dialog
|
||||
XDialogEventHandler { // Event handling for dialog
|
||||
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
// The subclass must override the following; and override the
|
||||
// implementation of XDialogEventHandler if needed
|
||||
|
||||
/** The component will be registered under this name.
|
||||
* The subclass must override this with a suitable name
|
||||
*/
|
||||
public static String __serviceName = "";
|
||||
|
||||
/** The component should also have an implementation name.
|
||||
* The subclass must override this with a suitable name
|
||||
*/
|
||||
public static String __implementationName = "";
|
||||
|
||||
/** Return the name of the library containing the dialog
|
||||
* The subclass must override this to provide the name of the library
|
||||
*/
|
||||
public abstract String getDialogLibraryName();
|
||||
|
||||
/** Return the name of the dialog within the library
|
||||
* The subclass must override this to provide the name of the dialog
|
||||
*/
|
||||
public abstract String getDialogName();
|
||||
|
||||
/** Initialize the dialog (eg. with settings from the registry)
|
||||
* The subclass must implement this
|
||||
*/
|
||||
protected abstract void initialize();
|
||||
|
||||
/** Finalize the dialog after execution (eg. save settings to the registry)
|
||||
* The subclass must implement this
|
||||
*/
|
||||
protected abstract void finalize();
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
// Some constants
|
||||
|
||||
// State of a checkbox
|
||||
protected static final short CHECKBOX_NOT_CHECKED = 0;
|
||||
protected static final short CHECKBOX_CHECKED = 1;
|
||||
protected static final short CHECKBOX_DONT_KNOW = 2;
|
||||
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
// Some private global variables
|
||||
|
||||
// The component context (from constructor)
|
||||
protected XComponentContext xContext;
|
||||
|
||||
// The dialog (created by XExecutableDialog implementation)
|
||||
private XDialog xDialog;
|
||||
private String sTitle;
|
||||
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
// The constructor
|
||||
|
||||
/** Create a new OptionsDialogBase */
|
||||
public DialogBase(XComponentContext xContext) {
|
||||
this.xContext = xContext;
|
||||
xDialog = null;
|
||||
sTitle = null;
|
||||
}
|
||||
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
// Implement uno interfaces
|
||||
|
||||
// Implement the interface XTypeProvider
|
||||
public Type[] getTypes() {
|
||||
Type[] typeReturn = {};
|
||||
try {
|
||||
typeReturn = new Type[] {
|
||||
new Type( XServiceName.class ),
|
||||
new Type( XServiceInfo.class ),
|
||||
new Type( XTypeProvider.class ),
|
||||
new Type( XExecutableDialog.class ),
|
||||
new Type( XDialogEventHandler.class ) };
|
||||
} catch(Exception exception) {
|
||||
}
|
||||
return typeReturn;
|
||||
}
|
||||
|
||||
public byte[] getImplementationId() {
|
||||
byte[] byteReturn = {};
|
||||
byteReturn = new String( "" + this.hashCode() ).getBytes();
|
||||
return( byteReturn );
|
||||
}
|
||||
|
||||
|
||||
// Implement the interface XServiceName
|
||||
public String getServiceName() {
|
||||
return __serviceName;
|
||||
}
|
||||
|
||||
|
||||
// Implement the interface XServiceInfo
|
||||
public boolean supportsService(String sServiceName) {
|
||||
return sServiceName.equals(__serviceName);
|
||||
}
|
||||
|
||||
public String getImplementationName() {
|
||||
return __implementationName;
|
||||
}
|
||||
|
||||
public String[] getSupportedServiceNames() {
|
||||
String[] sSupportedServiceNames = { __serviceName };
|
||||
return sSupportedServiceNames;
|
||||
}
|
||||
|
||||
|
||||
// Implement the interface XExecutableDialog
|
||||
public void setTitle(String sTitle) {
|
||||
this.sTitle = sTitle;
|
||||
}
|
||||
|
||||
public short execute() {
|
||||
try {
|
||||
// Create the dialog
|
||||
XMultiComponentFactory xMCF = xContext.getServiceManager();
|
||||
Object provider = xMCF.createInstanceWithContext(
|
||||
"com.sun.star.awt.DialogProvider2", xContext);
|
||||
XDialogProvider2 xDialogProvider = (XDialogProvider2)
|
||||
UnoRuntime.queryInterface(XDialogProvider2.class, provider);
|
||||
String sDialogUrl = "vnd.sun.star.script:"+getDialogLibraryName()+"."
|
||||
+getDialogName()+"?location=application";
|
||||
xDialog = xDialogProvider.createDialogWithHandler(sDialogUrl, this);
|
||||
if (sTitle!=null) { xDialog.setTitle(sTitle); }
|
||||
|
||||
// Do initialization using method from subclass
|
||||
initialize();
|
||||
|
||||
// Execute the dialog
|
||||
short nResult = xDialog.execute();
|
||||
|
||||
if (nResult == ExecutableDialogResults.OK) {
|
||||
// Finalize after execution of dialog using method from subclass
|
||||
finalize();
|
||||
}
|
||||
xDialog.endExecute();
|
||||
return nResult;
|
||||
}
|
||||
catch (Exception e) {
|
||||
MessageBox msgBox = new MessageBox(xContext);
|
||||
msgBox.showMessage("Error",e.toString()+" "+e.getStackTrace()[0].toString());
|
||||
|
||||
// continue as if the dialog was executed OK
|
||||
return ExecutableDialogResults.OK;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// Implement the interface XDialogEventHandler
|
||||
public boolean callHandlerMethod(XDialog xDialog, Object event, String sMethod) {
|
||||
// Do nothing, leaving the responsibility to the subclass
|
||||
return true;
|
||||
}
|
||||
|
||||
public String[] getSupportedMethodNames() {
|
||||
// We do not support any method names, subclass should take care of this
|
||||
return new String[0];
|
||||
}
|
||||
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
// Helpers to access controls in the dialog (to be used by the subclass)
|
||||
// Note: The helpers fail silently if an exception occurs. Could query the
|
||||
// the ClassId property for the control type and check that the property
|
||||
// exists to ensure a correct behaviour in all cases, but as long as the
|
||||
// helpers are used correctly, this doesn't really matter.
|
||||
|
||||
// Get the properties of a named control in the dialog
|
||||
private XPropertySet getControlProperties(String sControlName) {
|
||||
XControlContainer xContainer = (XControlContainer)
|
||||
UnoRuntime.queryInterface(XControlContainer.class, xDialog);
|
||||
XControl xControl = xContainer.getControl(sControlName);
|
||||
XControlModel xModel = xControl.getModel();
|
||||
XPropertySet xPropertySet = (XPropertySet)
|
||||
UnoRuntime.queryInterface(XPropertySet.class, xModel);
|
||||
return xPropertySet;
|
||||
}
|
||||
|
||||
|
||||
protected void setControlEnabled(String sControlName, boolean bEnabled) {
|
||||
XPropertySet xPropertySet = getControlProperties(sControlName);
|
||||
try {
|
||||
xPropertySet.setPropertyValue("Enabled", new Boolean(bEnabled));
|
||||
}
|
||||
catch (Exception e) {
|
||||
// Will fail if the control does not exist
|
||||
}
|
||||
}
|
||||
|
||||
protected short getCheckBoxState(String sControlName) {
|
||||
XPropertySet xPropertySet = getControlProperties(sControlName);
|
||||
try {
|
||||
return ((Short) xPropertySet.getPropertyValue("State")).shortValue();
|
||||
}
|
||||
catch (Exception e) {
|
||||
// Will fail if the control does not exist or is not a checkbox
|
||||
return CHECKBOX_DONT_KNOW;
|
||||
}
|
||||
}
|
||||
|
||||
protected boolean getCheckBoxStateAsBoolean(String sControlName) {
|
||||
return getCheckBoxState(sControlName)==CHECKBOX_CHECKED;
|
||||
}
|
||||
|
||||
protected void setCheckBoxState(String sControlName, short nState) {
|
||||
XPropertySet xPropertySet = getControlProperties(sControlName);
|
||||
try {
|
||||
xPropertySet.setPropertyValue("State",new Short(nState));
|
||||
}
|
||||
catch (Exception e) {
|
||||
// will fail if the control does not exist or is not a checkbox or
|
||||
// nState has an illegal value
|
||||
}
|
||||
}
|
||||
|
||||
protected void setCheckBoxStateAsBoolean(String sControlName, boolean bChecked) {
|
||||
setCheckBoxState(sControlName,bChecked ? CHECKBOX_CHECKED : CHECKBOX_NOT_CHECKED);
|
||||
}
|
||||
|
||||
protected String[] getListBoxStringItemList(String sControlName) {
|
||||
XPropertySet xPropertySet = getControlProperties(sControlName);
|
||||
try {
|
||||
return (String[]) xPropertySet.getPropertyValue("StringItemList");
|
||||
}
|
||||
catch (Exception e) {
|
||||
// Will fail if the control does not exist or is not a list box
|
||||
return new String[0];
|
||||
}
|
||||
}
|
||||
|
||||
protected void setListBoxStringItemList(String sControlName, String[] items) {
|
||||
XPropertySet xPropertySet = getControlProperties(sControlName);
|
||||
try {
|
||||
xPropertySet.setPropertyValue("StringItemList",items);
|
||||
}
|
||||
catch (Exception e) {
|
||||
// Will fail if the control does not exist or is not a list box
|
||||
}
|
||||
}
|
||||
|
||||
protected short getListBoxSelectedItem(String sControlName) {
|
||||
// Returns the first selected element in case of a multiselection
|
||||
XPropertySet xPropertySet = getControlProperties(sControlName);
|
||||
try {
|
||||
short[] selection = (short[]) xPropertySet.getPropertyValue("SelectedItems");
|
||||
return selection[0];
|
||||
}
|
||||
catch (Exception e) {
|
||||
// Will fail if the control does not exist or is not a list box
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
protected void setListBoxSelectedItem(String sControlName, short nIndex) {
|
||||
XPropertySet xPropertySet = getControlProperties(sControlName);
|
||||
try {
|
||||
short[] selection = new short[1];
|
||||
selection[0] = nIndex;
|
||||
xPropertySet.setPropertyValue("SelectedItems",selection);
|
||||
}
|
||||
catch (Exception e) {
|
||||
// Will fail if the control does not exist or is not a list box or
|
||||
// nIndex is an illegal value
|
||||
}
|
||||
}
|
||||
|
||||
protected short getListBoxLineCount(String sControlName) {
|
||||
// Returns the first selected element in case of a multiselection
|
||||
XPropertySet xPropertySet = getControlProperties(sControlName);
|
||||
try {
|
||||
return ((Short) xPropertySet.getPropertyValue("LineCount")).shortValue();
|
||||
}
|
||||
catch (Exception e) {
|
||||
// Will fail if the control does not exist or is not a list box
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
protected void setListBoxLineCount(String sControlName, short nLineCount) {
|
||||
XPropertySet xPropertySet = getControlProperties(sControlName);
|
||||
try {
|
||||
xPropertySet.setPropertyValue("LineCount",new Short(nLineCount));
|
||||
}
|
||||
catch (Exception e) {
|
||||
// Will fail if the control does not exist or is not a list box or
|
||||
// nLineCount is an illegal value
|
||||
}
|
||||
}
|
||||
|
||||
protected String getComboBoxText(String sControlName) {
|
||||
// Returns the text of a combobox
|
||||
XPropertySet xPropertySet = getControlProperties(sControlName);
|
||||
try {
|
||||
return (String) xPropertySet.getPropertyValue("Text");
|
||||
}
|
||||
catch (Exception e) {
|
||||
// Will fail if the control does not exist or is not a combo
|
||||
return "";
|
||||
}
|
||||
}
|
||||
|
||||
protected void setComboBoxText(String sControlName, String sText) {
|
||||
XPropertySet xPropertySet = getControlProperties(sControlName);
|
||||
try {
|
||||
xPropertySet.setPropertyValue("Text", sText);
|
||||
}
|
||||
catch (Exception e) {
|
||||
// Will fail if the control does not exist or is not a combo box or
|
||||
// nText is an illegal value
|
||||
}
|
||||
}
|
||||
|
||||
protected String getTextFieldText(String sControlName) {
|
||||
XPropertySet xPropertySet = getControlProperties(sControlName);
|
||||
try {
|
||||
return (String) xPropertySet.getPropertyValue("Text");
|
||||
}
|
||||
catch (Exception e) {
|
||||
// Will fail if the control does not exist or is not a text field
|
||||
return "";
|
||||
}
|
||||
}
|
||||
|
||||
protected void setTextFieldText(String sControlName, String sText) {
|
||||
XPropertySet xPropertySet = getControlProperties(sControlName);
|
||||
try {
|
||||
xPropertySet.setPropertyValue("Text",sText);
|
||||
}
|
||||
catch (Exception e) {
|
||||
// Will fail if the control does not exist or is not a text field
|
||||
}
|
||||
}
|
||||
|
||||
protected String getFormattedFieldText(String sControlName) {
|
||||
XPropertySet xPropertySet = getControlProperties(sControlName);
|
||||
try {
|
||||
return (String) xPropertySet.getPropertyValue("Text");
|
||||
}
|
||||
catch (Exception e) {
|
||||
// Will fail if the control does not exist or is not a formatted field
|
||||
return "";
|
||||
}
|
||||
}
|
||||
|
||||
protected void setFormattedFieldText(String sControlName, String sText) {
|
||||
XPropertySet xPropertySet = getControlProperties(sControlName);
|
||||
try {
|
||||
xPropertySet.setPropertyValue("Text",sText);
|
||||
}
|
||||
catch (Exception e) {
|
||||
// Will fail if the control does not exist or is not a formatted field
|
||||
}
|
||||
}
|
||||
|
||||
protected int getNumericFieldValue(String sControlName) {
|
||||
XPropertySet xPropertySet = getControlProperties(sControlName);
|
||||
try {
|
||||
return ((Double) xPropertySet.getPropertyValue("Value")).intValue();
|
||||
}
|
||||
catch (Exception e) {
|
||||
// Will fail if the control does not exist or is not a numeric field
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
protected void setNumericFieldValue(String sControlName, int nValue) {
|
||||
XPropertySet xPropertySet = getControlProperties(sControlName);
|
||||
try {
|
||||
xPropertySet.setPropertyValue("Value",new Double(nValue));
|
||||
}
|
||||
catch (Exception e) {
|
||||
// Will fail if the control does not exist or is not a numeric field
|
||||
}
|
||||
}
|
||||
|
||||
// Helpers for access to an XPropertySet. The helpers will fail silently if
|
||||
// names or data is provided, but the subclass is expected to use them with
|
||||
// correct data only...
|
||||
protected Object getPropertyValue(XPropertySet xProps, String sName) {
|
||||
try {
|
||||
return xProps.getPropertyValue(sName);
|
||||
}
|
||||
catch (UnknownPropertyException e) {
|
||||
return null;
|
||||
}
|
||||
catch (WrappedTargetException e) {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
protected void setPropertyValue(XPropertySet xProps, String sName, Object value) {
|
||||
try {
|
||||
xProps.setPropertyValue(sName,value);
|
||||
}
|
||||
catch (UnknownPropertyException e) {
|
||||
}
|
||||
catch (PropertyVetoException e) { // unacceptable value
|
||||
}
|
||||
catch (IllegalArgumentException e) {
|
||||
}
|
||||
catch (WrappedTargetException e) {
|
||||
}
|
||||
}
|
||||
|
||||
protected String getPropertyValueAsString(XPropertySet xProps, String sName) {
|
||||
Object value = getPropertyValue(xProps,sName);
|
||||
return value instanceof String ? (String) value : "";
|
||||
}
|
||||
|
||||
protected int getPropertyValueAsInteger(XPropertySet xProps, String sName) {
|
||||
Object value = getPropertyValue(xProps,sName);
|
||||
return value instanceof Integer ? ((Integer) value).intValue() : 0;
|
||||
}
|
||||
|
||||
protected void setPropertyValue(XPropertySet xProps, String sName, int nValue) {
|
||||
setPropertyValue(xProps,sName,new Integer(nValue));
|
||||
}
|
||||
|
||||
protected short getPropertyValueAsShort(XPropertySet xProps, String sName) {
|
||||
Object value = getPropertyValue(xProps,sName);
|
||||
return value instanceof Short ? ((Short) value).shortValue() : 0;
|
||||
}
|
||||
|
||||
protected void setPropertyValue(XPropertySet xProps, String sName, short nValue) {
|
||||
setPropertyValue(xProps,sName,new Short(nValue));
|
||||
}
|
||||
|
||||
protected boolean getPropertyValueAsBoolean(XPropertySet xProps, String sName) {
|
||||
Object value = getPropertyValue(xProps,sName);
|
||||
return value instanceof Boolean ? ((Boolean) value).booleanValue() : false;
|
||||
}
|
||||
|
||||
protected void setPropertyValue(XPropertySet xProps, String sName, boolean bValue) {
|
||||
setPropertyValue(xProps,sName,new Boolean(bValue));
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
|
@ -0,0 +1,105 @@
|
|||
/************************************************************************
|
||||
*
|
||||
* MessageBox.java
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License version 2.1, as published by the Free Software Foundation.
|
||||
*
|
||||
* This library 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
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston,
|
||||
* MA 02111-1307 USA
|
||||
*
|
||||
* Copyright: 2002-2008 by Henrik Just
|
||||
*
|
||||
* All Rights Reserved.
|
||||
*
|
||||
* Version 1.0 (2008-07-21)
|
||||
*
|
||||
*/
|
||||
|
||||
package org.openoffice.da.comp.w2lcommon.helper;
|
||||
|
||||
import com.sun.star.awt.Rectangle;
|
||||
import com.sun.star.awt.WindowAttribute;
|
||||
import com.sun.star.awt.WindowClass;
|
||||
import com.sun.star.awt.WindowDescriptor;
|
||||
import com.sun.star.awt.XMessageBox;
|
||||
import com.sun.star.awt.XToolkit;
|
||||
import com.sun.star.awt.XWindowPeer;
|
||||
import com.sun.star.frame.XDesktop;
|
||||
import com.sun.star.frame.XFrame;
|
||||
import com.sun.star.uno.UnoRuntime;
|
||||
import com.sun.star.uno.XComponentContext;
|
||||
|
||||
/** This class provides simple access to a uno awt message box
|
||||
*/
|
||||
public class MessageBox {
|
||||
|
||||
private XFrame xFrame;
|
||||
private XToolkit xToolkit;
|
||||
|
||||
/** Create a new MessageBox belonging to the current frame
|
||||
*/
|
||||
public MessageBox(XComponentContext xContext) {
|
||||
this(xContext,null);
|
||||
}
|
||||
|
||||
/** Create a new MessageBox belonging to a specific frame
|
||||
*/
|
||||
public MessageBox(XComponentContext xContext, XFrame xFrame) {
|
||||
try {
|
||||
Object toolkit = xContext.getServiceManager()
|
||||
.createInstanceWithContext("com.sun.star.awt.Toolkit",xContext);
|
||||
xToolkit = (XToolkit) UnoRuntime.queryInterface(XToolkit.class,toolkit);
|
||||
if (xFrame==null) {
|
||||
Object desktop = xContext.getServiceManager()
|
||||
.createInstanceWithContext("com.sun.star.frame.Desktop",xContext);
|
||||
XDesktop xDesktop = (XDesktop) UnoRuntime.queryInterface(XDesktop.class,desktop);
|
||||
xFrame = xDesktop.getCurrentFrame();
|
||||
}
|
||||
this.xFrame = xFrame;
|
||||
}
|
||||
catch (Exception e) {
|
||||
// Failed to get toolkit or frame
|
||||
xToolkit = null;
|
||||
xFrame = null;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public void showMessage(String sTitle, String sMessage) {
|
||||
if (xToolkit==null || xFrame==null) { return; }
|
||||
try {
|
||||
WindowDescriptor descriptor = new WindowDescriptor();
|
||||
descriptor.Type = WindowClass.MODALTOP;
|
||||
descriptor.WindowServiceName = "infobox";
|
||||
descriptor.ParentIndex = -1;
|
||||
descriptor.Parent = (XWindowPeer) UnoRuntime.queryInterface(
|
||||
XWindowPeer.class,xFrame.getContainerWindow());
|
||||
descriptor.Bounds = new Rectangle(0,0,300,200);
|
||||
descriptor.WindowAttributes = WindowAttribute.BORDER |
|
||||
WindowAttribute.MOVEABLE | WindowAttribute.CLOSEABLE;
|
||||
XWindowPeer xPeer = xToolkit.createWindow(descriptor);
|
||||
if (xPeer!=null) {
|
||||
XMessageBox xMessageBox = (XMessageBox)
|
||||
UnoRuntime.queryInterface(XMessageBox.class,xPeer);
|
||||
if (xMessageBox!=null) {
|
||||
xMessageBox.setCaptionText(sTitle);
|
||||
xMessageBox.setMessageText(sMessage);
|
||||
xMessageBox.execute();
|
||||
}
|
||||
}
|
||||
}
|
||||
catch (Exception e) {
|
||||
// ignore, give up...
|
||||
}
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,78 @@
|
|||
/************************************************************************
|
||||
*
|
||||
* PropertyHelper.java
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License version 2.1, as published by the Free Software Foundation.
|
||||
*
|
||||
* This library 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
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston,
|
||||
* MA 02111-1307 USA
|
||||
*
|
||||
* Copyright: 2002-2008 by Henrik Just
|
||||
*
|
||||
* All Rights Reserved.
|
||||
*
|
||||
* Version 1.0 (2008-07-21)
|
||||
*
|
||||
*/
|
||||
|
||||
package org.openoffice.da.comp.w2lcommon.helper;
|
||||
|
||||
import java.util.Enumeration;
|
||||
import java.util.Hashtable;
|
||||
|
||||
import com.sun.star.beans.PropertyValue;
|
||||
|
||||
/** This class provides access by name to a <code>PropertyValue</code> array
|
||||
*/
|
||||
public class PropertyHelper {
|
||||
|
||||
private Hashtable data;
|
||||
|
||||
public PropertyHelper() {
|
||||
data = new Hashtable();
|
||||
}
|
||||
|
||||
public PropertyHelper(PropertyValue[] props) {
|
||||
data = new Hashtable();
|
||||
int nLen = props.length;
|
||||
for (int i=0; i<nLen; i++) {
|
||||
data.put(props[i].Name,props[i].Value);
|
||||
}
|
||||
}
|
||||
|
||||
public void put(String sName, Object value) {
|
||||
data.put(sName,value);
|
||||
}
|
||||
|
||||
public Object get(String sName) {
|
||||
return data.get(sName);
|
||||
}
|
||||
|
||||
public Enumeration keys() {
|
||||
return data.keys();
|
||||
}
|
||||
|
||||
public PropertyValue[] toArray() {
|
||||
int nSize = data.size();
|
||||
PropertyValue[] props = new PropertyValue[nSize];
|
||||
int i=0;
|
||||
Enumeration keys = keys();
|
||||
while (keys.hasMoreElements()) {
|
||||
String sKey = (String) keys.nextElement();
|
||||
props[i] = new PropertyValue();
|
||||
props[i].Name = sKey;
|
||||
props[i++].Value = get(sKey);
|
||||
}
|
||||
return props;
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,351 @@
|
|||
/************************************************************************
|
||||
*
|
||||
* LaTeXOptionsDialog.java
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License version 2.1, as published by the Free Software Foundation.
|
||||
*
|
||||
* This library 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
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston,
|
||||
* MA 02111-1307 USA
|
||||
*
|
||||
* Copyright: 2002-2009 by Henrik Just
|
||||
*
|
||||
* All Rights Reserved.
|
||||
*
|
||||
* Version 1.0 (2009-02-18)
|
||||
*
|
||||
*/
|
||||
|
||||
package org.openoffice.da.comp.writer2latex;
|
||||
|
||||
import com.sun.star.awt.XDialog;
|
||||
import com.sun.star.beans.XPropertySet;
|
||||
//import com.sun.star.frame.XDesktop;
|
||||
//import com.sun.star.lang.XComponent;
|
||||
//import com.sun.star.text.XTextFieldsSupplier;
|
||||
//import com.sun.star.uno.UnoRuntime;
|
||||
import com.sun.star.uno.XComponentContext;
|
||||
|
||||
import org.openoffice.da.comp.w2lcommon.helper.PropertyHelper;
|
||||
import org.openoffice.da.comp.w2lcommon.filter.OptionsDialogBase;
|
||||
|
||||
/** This class provides a uno component which implements a filter ui for the
|
||||
* LaTeX export
|
||||
*/
|
||||
public class LaTeXOptionsDialog extends OptionsDialogBase {
|
||||
|
||||
// Translate list box items to configuration option values
|
||||
private static final String[] BACKEND_VALUES =
|
||||
{ "generic", "pdftex", "dvips", "unspecified" };
|
||||
private static final String[] INPUTENCODING_VALUES =
|
||||
{ "ascii", "latin1", "latin2", "iso-8859-7", "cp1250", "cp1251", "koi8-r", "utf8" };
|
||||
private static final String[] NOTES_VALUES =
|
||||
{ "ignore", "comment", "marginpar", "pdfannotation" };
|
||||
private static final String[] FLOATOPTIONS_VALUES =
|
||||
{ "", "tp", "bp", "htp", "hbp" };
|
||||
|
||||
/** The component will be registered under this name.
|
||||
*/
|
||||
public static String __serviceName = "org.openoffice.da.writer2latex.LaTeXOptionsDialog";
|
||||
|
||||
/** The component should also have an implementation name.
|
||||
* The subclass should override this with a suitable name
|
||||
*/
|
||||
public static String __implementationName = "org.openoffice.da.comp.writer2latex.LaTeXOptionsDialog";
|
||||
|
||||
public String getDialogLibraryName() { return "W2LDialogs"; }
|
||||
|
||||
|
||||
/** Create a new LaTeXOptionsDialog */
|
||||
public LaTeXOptionsDialog(XComponentContext xContext) {
|
||||
super(xContext);
|
||||
xMSF = W2LRegistration.xMultiServiceFactory;
|
||||
}
|
||||
|
||||
/** Return the name of the dialog within the library
|
||||
*/
|
||||
public String getDialogName() { return "LaTeXOptions"; }
|
||||
|
||||
/** Return the name of the registry path
|
||||
*/
|
||||
public String getRegistryPath() {
|
||||
return "/org.openoffice.da.Writer2LaTeX.Options/LaTeXOptions";
|
||||
}
|
||||
|
||||
/** Load settings from the registry to the dialog */
|
||||
protected void loadSettings(XPropertySet xProps) {
|
||||
// General
|
||||
loadConfig(xProps);
|
||||
loadListBoxOption(xProps,"Backend");
|
||||
loadListBoxOption(xProps,"Inputencoding");
|
||||
loadCheckBoxOption(xProps,"Multilingual");
|
||||
loadCheckBoxOption(xProps,"GreekMath");
|
||||
loadCheckBoxOption(xProps,"AdditionalSymbols");
|
||||
|
||||
// Bibliography
|
||||
loadCheckBoxOption(xProps,"UseBibtex");
|
||||
loadComboBoxOption(xProps,"BibtexStyle");
|
||||
|
||||
// Files
|
||||
loadCheckBoxOption(xProps,"WrapLines");
|
||||
loadNumericOption(xProps,"WrapLinesAfter");
|
||||
loadCheckBoxOption(xProps,"SplitLinkedSections");
|
||||
loadCheckBoxOption(xProps,"SplitToplevelSections");
|
||||
loadCheckBoxOption(xProps,"SaveImagesInSubdir");
|
||||
|
||||
// Special content
|
||||
loadListBoxOption(xProps,"Notes");
|
||||
loadCheckBoxOption(xProps,"Metadata");
|
||||
|
||||
// Figures and tables
|
||||
loadCheckBoxOption(xProps,"OriginalImageSize");
|
||||
loadCheckBoxOption(xProps,"OptimizeSimpleTables");
|
||||
loadNumericOption(xProps,"SimpleTableLimit");
|
||||
loadCheckBoxOption(xProps,"FloatTables");
|
||||
loadCheckBoxOption(xProps,"FloatFigures");
|
||||
loadListBoxOption(xProps,"FloatOptions");
|
||||
|
||||
// AutoCorrect
|
||||
loadCheckBoxOption(xProps,"IgnoreHardPageBreaks");
|
||||
loadCheckBoxOption(xProps,"IgnoreHardLineBreaks");
|
||||
loadCheckBoxOption(xProps,"IgnoreEmptyParagraphs");
|
||||
loadCheckBoxOption(xProps,"IgnoreDoubleSpaces");
|
||||
|
||||
updateLockedOptions();
|
||||
enableControls();
|
||||
}
|
||||
|
||||
/** Save settings from the dialog to the registry and create FilterData */
|
||||
protected void saveSettings(XPropertySet xProps, PropertyHelper filterData) {
|
||||
// General
|
||||
short nConfig = saveConfig(xProps, filterData);
|
||||
switch (nConfig) {
|
||||
case 0: filterData.put("ConfigURL","*ultraclean.xml"); break;
|
||||
case 1: filterData.put("ConfigURL","*clean.xml"); break;
|
||||
case 2: filterData.put("ConfigURL","*default.xml"); break;
|
||||
case 3: filterData.put("ConfigURL","*pdfprint.xml"); break;
|
||||
case 4: filterData.put("ConfigURL","*pdfscreen.xml"); break;
|
||||
case 5: filterData.put("ConfigURL","$(user)/writer2latex.xml");
|
||||
filterData.put("AutoCreate","true");
|
||||
}
|
||||
|
||||
saveListBoxOption(xProps, filterData, "Backend", "backend", BACKEND_VALUES );
|
||||
if (getListBoxSelectedItem("Config")==4) {
|
||||
// pdfscreen locks the backend to pdftex
|
||||
filterData.put("backend","pdftex");
|
||||
}
|
||||
saveListBoxOption(xProps, filterData, "Inputencoding", "inputencoding", INPUTENCODING_VALUES);
|
||||
saveCheckBoxOption(xProps, filterData, "Multilingual", "multilingual");
|
||||
saveCheckBoxOption(xProps, filterData, "GreekMath", "greek_math");
|
||||
// AdditionalSymbols sets 5 different w2l options...
|
||||
saveCheckBoxOption(xProps, filterData, "AdditionalSymbols", "use_pifont");
|
||||
saveCheckBoxOption(xProps, filterData, "AdditionalSymbols", "use_ifsym");
|
||||
saveCheckBoxOption(xProps, filterData, "AdditionalSymbols", "use_wasysym");
|
||||
saveCheckBoxOption(xProps, filterData, "AdditionalSymbols", "use_eurosym");
|
||||
saveCheckBoxOption(xProps, filterData, "AdditionalSymbols", "use_tipa");
|
||||
|
||||
// Bibliography
|
||||
saveCheckBoxOption(xProps, filterData, "UseBibtex", "use_bibtex");
|
||||
saveComboBoxOption(xProps, filterData, "BibtexStyle", "bibtex_style");
|
||||
|
||||
// Files
|
||||
boolean bWrapLines = saveCheckBoxOption(xProps, "WrapLines");
|
||||
int nWrapLinesAfter = saveNumericOption(xProps, "WrapLinesAfter");
|
||||
if (!isLocked("wrap_lines_after")) {
|
||||
if (bWrapLines) {
|
||||
filterData.put("wrap_lines_after",Integer.toString(nWrapLinesAfter));
|
||||
}
|
||||
else {
|
||||
filterData.put("wrap_lines_after","0");
|
||||
}
|
||||
}
|
||||
|
||||
saveCheckBoxOption(xProps, filterData, "SplitLinkedSections", "split_linked_sections");
|
||||
saveCheckBoxOption(xProps, filterData, "SplitToplevelSections", "split_toplevel_sections");
|
||||
saveCheckBoxOption(xProps, filterData, "SaveImagesInSubdir", "save_images_in_subdir");
|
||||
|
||||
// Special content
|
||||
saveListBoxOption(xProps, filterData, "Notes", "notes", NOTES_VALUES);
|
||||
saveCheckBoxOption(xProps, filterData, "Metadata", "metadata");
|
||||
|
||||
// Figures and tables
|
||||
saveCheckBoxOption(xProps, filterData, "OriginalImageSize", "original_image_size");
|
||||
|
||||
boolean bOptimizeSimpleTables = saveCheckBoxOption(xProps,"OptimizeSimpleTables");
|
||||
int nSimpleTableLimit = saveNumericOption(xProps,"SimpleTableLimit");
|
||||
if (!isLocked("simple_table_limit")) {
|
||||
if (bOptimizeSimpleTables) {
|
||||
filterData.put("simple_table_limit",Integer.toString(nSimpleTableLimit));
|
||||
}
|
||||
else {
|
||||
filterData.put("simple_table_limit","0");
|
||||
}
|
||||
}
|
||||
|
||||
saveCheckBoxOption(xProps, filterData, "FloatTables", "float_tables");
|
||||
saveCheckBoxOption(xProps, filterData, "FloatFigures", "float_figures");
|
||||
saveListBoxOption(xProps, filterData, "FloatOptions", "float_options", FLOATOPTIONS_VALUES);
|
||||
|
||||
// AutoCorrect
|
||||
saveCheckBoxOption(xProps, filterData, "IgnoreHardPageBreaks", "ignore_hard_page_breaks");
|
||||
saveCheckBoxOption(xProps, filterData, "IgnoreHardLineBreaks", "ignore_hard_line_breaks");
|
||||
saveCheckBoxOption(xProps, filterData, "IgnoreEmptyParagraphs", "ignore_empty_paragraphs");
|
||||
saveCheckBoxOption(xProps, filterData, "IgnoreDoubleSpaces", "ignore_double_spaces");
|
||||
}
|
||||
|
||||
|
||||
// Implement XDialogEventHandler
|
||||
public boolean callHandlerMethod(XDialog xDialog, Object event, String sMethod) {
|
||||
if (sMethod.equals("ConfigChange")) {
|
||||
updateLockedOptions();
|
||||
enableControls();
|
||||
}
|
||||
else if (sMethod.equals("UseBibtexChange")) {
|
||||
enableBibtexStyle();
|
||||
}
|
||||
else if (sMethod.equals("WrapLinesChange")) {
|
||||
enableWrapLinesAfter();
|
||||
}
|
||||
else if (sMethod.equals("OptimizeSimpleTablesChange")) {
|
||||
enableSimpleTableLimit();
|
||||
}
|
||||
else if (sMethod.equals("FloatTablesChange")) {
|
||||
enableFloatOptions();
|
||||
}
|
||||
else if (sMethod.equals("FloatFiguresChange")) {
|
||||
enableFloatOptions();
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
public String[] getSupportedMethodNames() {
|
||||
String[] sNames = { "ConfigChange", "UseBibtexChange", "WrapLinesChange",
|
||||
"OptimizeSimpleTablesChange", "FloatTablesChange", "FloatFiguresChange" };
|
||||
return sNames;
|
||||
}
|
||||
|
||||
protected boolean isLocked(String sOptionName) {
|
||||
if ("backend".equals(sOptionName)) {
|
||||
// backend must be pdf for pdfscreen
|
||||
return getListBoxSelectedItem("Config")==4 || super.isLocked(sOptionName);
|
||||
}
|
||||
else if ("additional_symbols".equals(sOptionName)) {
|
||||
// additional_symbols is disabled for custom config (where the 5
|
||||
// individual options can be set independently)
|
||||
return getListBoxSelectedItem("Config")==5 || super.isLocked(sOptionName);
|
||||
}
|
||||
else if ("use_pifont".equals(sOptionName)) {
|
||||
return isLocked("additional_symbols");
|
||||
}
|
||||
else if ("use_ifsym".equals(sOptionName)) {
|
||||
return isLocked("additional_symbols");
|
||||
}
|
||||
else if ("use_wasysym".equals(sOptionName)) {
|
||||
return isLocked("additional_symbols");
|
||||
}
|
||||
else if ("use_eurosym".equals(sOptionName)) {
|
||||
return isLocked("additional_symbols");
|
||||
}
|
||||
else if ("use_tipa".equals(sOptionName)) {
|
||||
return isLocked("additional_symbols");
|
||||
}
|
||||
else {
|
||||
return super.isLocked(sOptionName);
|
||||
}
|
||||
}
|
||||
|
||||
private void enableControls() {
|
||||
// General
|
||||
setControlEnabled("BackendLabel",!isLocked("backend"));
|
||||
setControlEnabled("Backend",!isLocked("backend"));
|
||||
setControlEnabled("InputencodingLabel",!isLocked("inputencoding"));
|
||||
setControlEnabled("Inputencoding",!isLocked("inputencoding"));
|
||||
setControlEnabled("Multilingual",!isLocked("multilingual"));
|
||||
setControlEnabled("GreekMath",!isLocked("greek_math"));
|
||||
setControlEnabled("AdditionalSymbols",!isLocked("additional_symbols"));
|
||||
|
||||
// Bibliography
|
||||
setControlEnabled("UseBibtex",!isLocked("use_bibtex"));
|
||||
boolean bUseBibtex = getCheckBoxStateAsBoolean("UseBibtex");
|
||||
setControlEnabled("BibtexStyleLabel",!isLocked("bibtex_style") && bUseBibtex);
|
||||
setControlEnabled("BibtexStyle",!isLocked("bibtex_style") && bUseBibtex);
|
||||
|
||||
// Files
|
||||
setControlEnabled("WrapLines",!isLocked("wrap_lines_after"));
|
||||
boolean bWrapLines = getCheckBoxStateAsBoolean("WrapLines");
|
||||
setControlEnabled("WrapLinesAfterLabel",!isLocked("wrap_lines_after") && bWrapLines);
|
||||
setControlEnabled("WrapLinesAfter",!isLocked("wrap_lines_after") && bWrapLines);
|
||||
setControlEnabled("SplitLinkedSections",!isLocked("split_linked_sections"));
|
||||
setControlEnabled("SplitToplevelSections",!isLocked("split_toplevel_sections"));
|
||||
setControlEnabled("SaveImagesInSubdir",!isLocked("save_images_in_subdir"));
|
||||
|
||||
// Special content
|
||||
setControlEnabled("NotesLabel",!isLocked("notes"));
|
||||
setControlEnabled("Notes",!isLocked("notes"));
|
||||
setControlEnabled("Metadata",!isLocked("metadata"));
|
||||
|
||||
// Figures and tables
|
||||
setControlEnabled("OriginalImageSize",!isLocked("original_image_size"));
|
||||
setControlEnabled("OptimizeSimpleTables",!isLocked("simple_table_limit"));
|
||||
boolean bOptimizeSimpleTables = getCheckBoxStateAsBoolean("OptimizeSimpleTables");
|
||||
setControlEnabled("SimpleTableLimitLabel",!isLocked("simple_table_limit") && bOptimizeSimpleTables);
|
||||
setControlEnabled("SimpleTableLimit",!isLocked("simple_table_limit") && bOptimizeSimpleTables);
|
||||
setControlEnabled("FloatTables",!isLocked("float_tables"));
|
||||
setControlEnabled("FloatFigures",!isLocked("float_figures"));
|
||||
boolean bFloat = getCheckBoxStateAsBoolean("FloatFigures") ||
|
||||
getCheckBoxStateAsBoolean("FloatTables");
|
||||
setControlEnabled("FloatOptionsLabel",!isLocked("float_options") && bFloat);
|
||||
setControlEnabled("FloatOptions",!isLocked("float_options") && bFloat);
|
||||
|
||||
// AutoCorrect
|
||||
setControlEnabled("IgnoreHardPageBreaks",!isLocked("ignore_hard_page_breaks"));
|
||||
setControlEnabled("IgnoreHardLineBreaks",!isLocked("ignore_hard_line_breaks"));
|
||||
setControlEnabled("IgnoreEmptyParagraphs",!isLocked("ignore_empty_paragraphs"));
|
||||
setControlEnabled("IgnoreDoubleSpaces",!isLocked("ignore_double_spaces"));
|
||||
}
|
||||
|
||||
private void enableBibtexStyle() {
|
||||
if (!isLocked("bibtex_style")) {
|
||||
boolean bState = getCheckBoxStateAsBoolean("UseBibtex");
|
||||
setControlEnabled("BibtexStyleLabel",bState);
|
||||
setControlEnabled("BibtexStyle",bState);
|
||||
}
|
||||
}
|
||||
|
||||
private void enableWrapLinesAfter() {
|
||||
if (!isLocked("wrap_lines_after")) {
|
||||
boolean bState = getCheckBoxStateAsBoolean("WrapLines");
|
||||
setControlEnabled("WrapLinesAfterLabel",bState);
|
||||
setControlEnabled("WrapLinesAfter",bState);
|
||||
}
|
||||
}
|
||||
|
||||
private void enableSimpleTableLimit() {
|
||||
if (!isLocked("simple_table_limit")) {
|
||||
boolean bState = getCheckBoxStateAsBoolean("OptimizeSimpleTables");
|
||||
setControlEnabled("SimpleTableLimitLabel",bState);
|
||||
setControlEnabled("SimpleTableLimit",bState);
|
||||
}
|
||||
}
|
||||
|
||||
private void enableFloatOptions() {
|
||||
if (!isLocked("float_options")) {
|
||||
boolean bState = getCheckBoxStateAsBoolean("FloatFigures") ||
|
||||
getCheckBoxStateAsBoolean("FloatTables");
|
||||
setControlEnabled("FloatOptionsLabel",bState);
|
||||
setControlEnabled("FloatOptions",bState);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
|
@ -0,0 +1,56 @@
|
|||
/************************************************************************
|
||||
*
|
||||
* W2LExportFilter.java
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License version 2.1, as published by the Free Software Foundation.
|
||||
*
|
||||
* This library 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
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston,
|
||||
* MA 02111-1307 USA
|
||||
*
|
||||
* Copyright: 2002-2008 by Henrik Just
|
||||
*
|
||||
* All Rights Reserved.
|
||||
*
|
||||
* Version 1.0 (2008-07-21)
|
||||
*
|
||||
*/
|
||||
|
||||
package org.openoffice.da.comp.writer2latex;
|
||||
|
||||
import com.sun.star.uno.XComponentContext;
|
||||
|
||||
import org.openoffice.da.comp.w2lcommon.filter.ExportFilterBase;
|
||||
|
||||
|
||||
/** This class implements the LaTeX and BibTeX export filter component
|
||||
*/
|
||||
public class W2LExportFilter extends ExportFilterBase {
|
||||
|
||||
/** Service name for the component */
|
||||
public static final String __serviceName = "org.openoffice.da.comp.writer2latex.W2LExportFilter";
|
||||
|
||||
/** Implementation name for the component */
|
||||
public static final String __implementationName = "org.openoffice.da.comp.writer2latex.W2LExportFilter";
|
||||
|
||||
/** Filter name to include in error messages */
|
||||
public static final String __displayName = "Writer2LaTeX";
|
||||
|
||||
public W2LExportFilter(XComponentContext xComponentContext1) {
|
||||
super(xComponentContext1);
|
||||
xMSF = W2LRegistration.xMultiServiceFactory;
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
|
@ -0,0 +1,103 @@
|
|||
/************************************************************************
|
||||
*
|
||||
* W2LRegistration.java
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License version 2.1, as published by the Free Software Foundation.
|
||||
*
|
||||
* This library 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
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston,
|
||||
* MA 02111-1307 USA
|
||||
*
|
||||
* Copyright: 2002-2008 by Henrik Just
|
||||
*
|
||||
* All Rights Reserved.
|
||||
*
|
||||
* Version 1.0 (2008-07-21)
|
||||
*
|
||||
*/
|
||||
|
||||
package org.openoffice.da.comp.writer2latex;
|
||||
|
||||
import com.sun.star.lang.XMultiServiceFactory;
|
||||
import com.sun.star.lang.XSingleServiceFactory;
|
||||
import com.sun.star.registry.XRegistryKey;
|
||||
|
||||
import com.sun.star.comp.loader.FactoryHelper;
|
||||
|
||||
/** This class provides a static method to instantiate our uno components
|
||||
* on demand (__getServiceFactory()), and a static method to give
|
||||
* information about the components (__writeRegistryServiceInfo()).
|
||||
* Furthermore, it saves the XMultiServiceFactory provided to the
|
||||
* __getServiceFactory method for future reference by the componentes.
|
||||
*/
|
||||
public class W2LRegistration {
|
||||
|
||||
public static XMultiServiceFactory xMultiServiceFactory;
|
||||
|
||||
/**
|
||||
* Returns a factory for creating the service.
|
||||
* This method is called by the <code>JavaLoader</code>
|
||||
*
|
||||
* @return returns a <code>XSingleServiceFactory</code> for creating the
|
||||
* component
|
||||
*
|
||||
* @param implName the name of the implementation for which a
|
||||
* service is desired
|
||||
* @param multiFactory the service manager to be used if needed
|
||||
* @param regKey the registryKey
|
||||
*
|
||||
* @see com.sun.star.comp.loader.JavaLoader
|
||||
*/
|
||||
public static XSingleServiceFactory __getServiceFactory(String implName,
|
||||
XMultiServiceFactory multiFactory, XRegistryKey regKey) {
|
||||
xMultiServiceFactory = multiFactory;
|
||||
XSingleServiceFactory xSingleServiceFactory = null;
|
||||
if (implName.equals(W2LExportFilter.class.getName()) ) {
|
||||
xSingleServiceFactory = FactoryHelper.getServiceFactory(W2LExportFilter.class,
|
||||
W2LExportFilter.__serviceName,
|
||||
multiFactory,
|
||||
regKey);
|
||||
}
|
||||
else if (implName.equals(LaTeXOptionsDialog.__implementationName)) {
|
||||
xSingleServiceFactory = FactoryHelper.getServiceFactory(LaTeXOptionsDialog.class,
|
||||
LaTeXOptionsDialog.__serviceName,
|
||||
multiFactory,
|
||||
regKey);
|
||||
}
|
||||
else if (implName.equals(W2LStarMathConverter.__implementationName)) {
|
||||
xSingleServiceFactory = FactoryHelper.getServiceFactory(W2LStarMathConverter.class,
|
||||
W2LStarMathConverter.__serviceName,
|
||||
multiFactory,
|
||||
regKey);
|
||||
}
|
||||
|
||||
return xSingleServiceFactory;
|
||||
}
|
||||
|
||||
/**
|
||||
* Writes the service information into the given registry key.
|
||||
* This method is called by the <code>JavaLoader</code>
|
||||
* <p>
|
||||
* @return returns true if the operation succeeded
|
||||
* @param regKey the registryKey
|
||||
* @see com.sun.star.comp.loader.JavaLoader
|
||||
*/
|
||||
public static boolean __writeRegistryServiceInfo(XRegistryKey regKey) {
|
||||
return
|
||||
FactoryHelper.writeRegistryServiceInfo(W2LExportFilter.__implementationName,
|
||||
W2LExportFilter.__serviceName, regKey) &
|
||||
FactoryHelper.writeRegistryServiceInfo(LaTeXOptionsDialog.__implementationName,
|
||||
LaTeXOptionsDialog.__serviceName, regKey) &
|
||||
FactoryHelper.writeRegistryServiceInfo(W2LStarMathConverter.__implementationName,
|
||||
W2LStarMathConverter.__serviceName, regKey);
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,125 @@
|
|||
/************************************************************************
|
||||
*
|
||||
* W2LStarMathConverter.java
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License version 2.1, as published by the Free Software Foundation.
|
||||
*
|
||||
* This library 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
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston,
|
||||
* MA 02111-1307 USA
|
||||
*
|
||||
* Copyright: 2002-2008 by Henrik Just
|
||||
*
|
||||
* All Rights Reserved.
|
||||
*/
|
||||
|
||||
// Version 1.0 (2008-11-22)
|
||||
|
||||
package org.openoffice.da.comp.writer2latex;
|
||||
|
||||
import com.sun.star.lang.XServiceInfo;
|
||||
import com.sun.star.lang.XTypeProvider;
|
||||
import com.sun.star.uno.Type;
|
||||
//import com.sun.star.uno.UnoRuntime;
|
||||
import com.sun.star.uno.XComponentContext;
|
||||
import com.sun.star.lang.XServiceName;
|
||||
|
||||
import writer2latex.api.ConverterFactory;
|
||||
import writer2latex.api.StarMathConverter;
|
||||
|
||||
// Import interface as defined in uno idl
|
||||
import org.openoffice.da.writer2latex.XW2LStarMathConverter;
|
||||
|
||||
/** This class provides a uno component which implements the interface
|
||||
* org.openoffice.da.writer2latex.XW2LConverter
|
||||
*/
|
||||
public class W2LStarMathConverter implements
|
||||
XW2LStarMathConverter,
|
||||
XServiceName,
|
||||
XServiceInfo,
|
||||
XTypeProvider {
|
||||
|
||||
/** The component will be registered under this name.
|
||||
*/
|
||||
public static final String __serviceName = "org.openoffice.da.writer2latex.W2LStarMathConverter";
|
||||
|
||||
public static final String __implementationName = "org.openoffice.da.comp.writer2latex.W2LStarMathConverter";
|
||||
|
||||
//private static XComponentContext xComponentContext = null;
|
||||
private static StarMathConverter starMathConverter;
|
||||
|
||||
public W2LStarMathConverter(XComponentContext xComponentContext1) {
|
||||
starMathConverter = ConverterFactory.createStarMathConverter();
|
||||
}
|
||||
|
||||
// Implementation of XW2LConverter:
|
||||
public String convertFormula(String sStarMathFormula) {
|
||||
return starMathConverter.convert(sStarMathFormula);
|
||||
}
|
||||
|
||||
public String getPreamble() {
|
||||
return starMathConverter.getPreamble();
|
||||
}
|
||||
|
||||
|
||||
// Implement methods from interface XTypeProvider
|
||||
// Implementation of XTypeProvider
|
||||
|
||||
public com.sun.star.uno.Type[] getTypes() {
|
||||
Type[] typeReturn = {};
|
||||
|
||||
try {
|
||||
typeReturn = new Type[] {
|
||||
new Type( XW2LStarMathConverter.class ),
|
||||
new Type( XTypeProvider.class ),
|
||||
new Type( XServiceName.class ),
|
||||
new Type( XServiceInfo.class ) };
|
||||
}
|
||||
catch( Exception exception ) {
|
||||
|
||||
}
|
||||
|
||||
return( typeReturn );
|
||||
}
|
||||
|
||||
|
||||
public byte[] getImplementationId() {
|
||||
byte[] byteReturn = {};
|
||||
|
||||
byteReturn = new String( "" + this.hashCode() ).getBytes();
|
||||
|
||||
return( byteReturn );
|
||||
}
|
||||
|
||||
// Implement method from interface XServiceName
|
||||
public String getServiceName() {
|
||||
return( __serviceName );
|
||||
}
|
||||
|
||||
// Implement methods from interface XServiceInfo
|
||||
public boolean supportsService(String stringServiceName) {
|
||||
return( stringServiceName.equals( __serviceName ) );
|
||||
}
|
||||
|
||||
public String getImplementationName() {
|
||||
return( __implementationName );
|
||||
}
|
||||
|
||||
public String[] getSupportedServiceNames() {
|
||||
String[] stringSupportedServiceNames = { __serviceName };
|
||||
return( stringSupportedServiceNames );
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
|
@ -0,0 +1,541 @@
|
|||
/************************************************************************
|
||||
*
|
||||
* BatchConverter.java
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License version 2.1, as published by the Free Software Foundation.
|
||||
*
|
||||
* This library 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
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston,
|
||||
* MA 02111-1307 USA
|
||||
*
|
||||
* Copyright: 2002-2009 by Henrik Just
|
||||
*
|
||||
* All Rights Reserved.
|
||||
*
|
||||
* Version 1.0 (2009-02-16)
|
||||
*
|
||||
*/
|
||||
|
||||
package org.openoffice.da.comp.writer2xhtml;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.OutputStream;
|
||||
import java.net.URI;
|
||||
import java.net.URISyntaxException;
|
||||
|
||||
import com.sun.star.lib.uno.adapter.XInputStreamToInputStreamAdapter;
|
||||
import com.sun.star.lib.uno.adapter.XOutputStreamToOutputStreamAdapter;
|
||||
import com.sun.star.beans.PropertyValue;
|
||||
import com.sun.star.beans.UnknownPropertyException;
|
||||
import com.sun.star.beans.XPropertySet;
|
||||
import com.sun.star.document.XDocumentInfoSupplier;
|
||||
import com.sun.star.frame.XComponentLoader;
|
||||
import com.sun.star.frame.XStorable;
|
||||
import com.sun.star.io.NotConnectedException;
|
||||
import com.sun.star.io.XInputStream;
|
||||
import com.sun.star.io.XOutputStream;
|
||||
import com.sun.star.lang.WrappedTargetException;
|
||||
import com.sun.star.lang.XComponent;
|
||||
import com.sun.star.lang.XServiceInfo;
|
||||
import com.sun.star.lang.XServiceName;
|
||||
import com.sun.star.lang.XTypeProvider;
|
||||
import com.sun.star.sheet.XSpreadsheetDocument;
|
||||
import com.sun.star.text.XTextDocument;
|
||||
import com.sun.star.ucb.CommandAbortedException;
|
||||
import com.sun.star.ucb.XSimpleFileAccess2;
|
||||
import com.sun.star.uno.AnyConverter;
|
||||
import com.sun.star.uno.Type;
|
||||
import com.sun.star.uno.UnoRuntime;
|
||||
import com.sun.star.uno.XComponentContext;
|
||||
|
||||
//import writer2latex.api.BatchConverter;
|
||||
//import writer2latex.api.BatchHandler;
|
||||
//import writer2latex.api.Converter;
|
||||
import writer2latex.api.ConverterFactory;
|
||||
import writer2latex.api.IndexPageEntry;
|
||||
import writer2latex.api.MIMETypes;
|
||||
import writer2latex.api.OutputFile;
|
||||
|
||||
// Import interfaces as defined in uno idl
|
||||
import org.openoffice.da.writer2xhtml.XBatchConverter;
|
||||
import org.openoffice.da.writer2xhtml.XBatchHandler;
|
||||
import org.openoffice.da.comp.w2lcommon.helper.PropertyHelper;
|
||||
|
||||
/** This class provides a uno component which implements the interface
|
||||
* org.openoffice.da.writer2xhtml.XBatchConverter
|
||||
*/
|
||||
public class BatchConverter implements
|
||||
XBatchConverter,
|
||||
XServiceName,
|
||||
XServiceInfo,
|
||||
XTypeProvider {
|
||||
|
||||
/** The component will be registered under this name.
|
||||
*/
|
||||
public static final String __serviceName = "org.openoffice.da.writer2xhtml.BatchConverter";
|
||||
|
||||
public static final String __implementationName = "org.openoffice.da.comp.writer2xhtml.BatchConverter";
|
||||
|
||||
private XComponentContext xComponentContext = null;
|
||||
|
||||
private XSimpleFileAccess2 sfa2 = null;
|
||||
private writer2latex.api.BatchConverter batchConverter = null;
|
||||
|
||||
private XBatchHandler handler;
|
||||
|
||||
// Based on convert arguments
|
||||
private boolean bRecurse = true;
|
||||
private String sWriterFilterName = "org.openoffice.da.writer2xhtml";
|
||||
private Object writerFilterData = null;
|
||||
private String sCalcFilterName = "org.openoffice.da.calc2xhtml";
|
||||
private Object calcFilterData = null;
|
||||
private boolean bIncludePdf = true;
|
||||
private boolean bIncludeOriginal = false;
|
||||
private boolean bUseTitle = true;
|
||||
private boolean bUseDescription = true;
|
||||
private String sUplink = "";
|
||||
private String sDirectoryIcon = "";
|
||||
private String sDocumentIcon = "";
|
||||
private String sTemplateURL = null;
|
||||
|
||||
public BatchConverter(XComponentContext xComponentContext) {
|
||||
this.xComponentContext = xComponentContext;
|
||||
// Get the SimpleFileAccess service
|
||||
try {
|
||||
Object sfaObject = xComponentContext.getServiceManager().createInstanceWithContext(
|
||||
"com.sun.star.ucb.SimpleFileAccess", xComponentContext);
|
||||
sfa2 = (XSimpleFileAccess2) UnoRuntime.queryInterface(XSimpleFileAccess2.class, sfaObject);
|
||||
}
|
||||
catch (com.sun.star.uno.Exception e) {
|
||||
// failed to get SimpleFileAccess service (should not happen)
|
||||
}
|
||||
}
|
||||
|
||||
// Helper: Get a string from an any
|
||||
private String getValue(Object any) {
|
||||
if (AnyConverter.isString(any)) {
|
||||
try {
|
||||
return AnyConverter.toString(any);
|
||||
}
|
||||
catch (com.sun.star.lang.IllegalArgumentException e) {
|
||||
return "";
|
||||
}
|
||||
}
|
||||
else {
|
||||
return "";
|
||||
}
|
||||
}
|
||||
|
||||
// Implementation of XBatchConverter:
|
||||
public void convert(String sSourceURL, String sTargetURL, PropertyValue[] lArguments, XBatchHandler handler) {
|
||||
// Create batch converter (currently we don't need to set a converter)
|
||||
batchConverter = ConverterFactory.createBatchConverter(MIMETypes.XHTML);
|
||||
|
||||
this.handler = handler;
|
||||
|
||||
// Read the arguments
|
||||
int nSize = lArguments.length;
|
||||
for (int i=0; i<nSize; i++) {
|
||||
String sName = lArguments[i].Name;
|
||||
Object value = lArguments[i].Value;
|
||||
if ("Recurse".equals(sName)) {
|
||||
bRecurse = !"false".equals(getValue(value));
|
||||
}
|
||||
else if ("IncludePdf".equals(sName)) {
|
||||
bIncludePdf = !"false".equals(getValue(value));
|
||||
}
|
||||
else if ("IncludeOriginal".equals(sName)) {
|
||||
bIncludeOriginal = "true".equals(getValue(value));
|
||||
|
||||
}
|
||||
else if ("UseTitle".equals(sName)) {
|
||||
bUseTitle = !"false".equals(getValue(value));
|
||||
}
|
||||
else if ("UseDescription".equals(sName)) {
|
||||
bUseDescription = !"false".equals(getValue(value));
|
||||
}
|
||||
else if ("Uplink".equals(sName)) {
|
||||
sUplink = getValue(value);
|
||||
}
|
||||
else if ("DirectoryIcon".equals(sName)) {
|
||||
sDirectoryIcon = getValue(value);
|
||||
}
|
||||
else if ("DocumentIcon".equals(sName)) {
|
||||
sDocumentIcon = getValue(value);
|
||||
}
|
||||
else if ("TemplateURL".equals(sName)) {
|
||||
sTemplateURL = getValue(value);
|
||||
}
|
||||
else if ("WriterFilterName".equals(sName)) {
|
||||
sWriterFilterName = getValue(value);
|
||||
}
|
||||
else if ("WriterFilterData".equals(sName)) {
|
||||
writerFilterData = lArguments[i].Value;
|
||||
}
|
||||
else if ("CalcFilterName".equals(sName)) {
|
||||
sCalcFilterName = getValue(value);
|
||||
}
|
||||
else if ("CalcFilterData".equals(sName)) {
|
||||
calcFilterData = lArguments[i].Value;
|
||||
}
|
||||
}
|
||||
|
||||
// Set arguments on batch converter
|
||||
batchConverter.getConfig().setOption("uplink", sUplink);
|
||||
batchConverter.getConfig().setOption("directory_icon", sDirectoryIcon);
|
||||
batchConverter.getConfig().setOption("document_icon", sDocumentIcon);
|
||||
if (sTemplateURL!=null) {
|
||||
try {
|
||||
XInputStream xis = sfa2.openFileRead(sTemplateURL);
|
||||
XInputStreamToInputStreamAdapter isa = new XInputStreamToInputStreamAdapter(xis);
|
||||
batchConverter.readTemplate(isa);
|
||||
}
|
||||
catch (IOException e) {
|
||||
// The batchconverter failed to read the template
|
||||
}
|
||||
catch (CommandAbortedException e) {
|
||||
// The sfa could not execute the command
|
||||
}
|
||||
catch (com.sun.star.uno.Exception e) {
|
||||
// Unspecified uno exception
|
||||
}
|
||||
}
|
||||
|
||||
// Convert the directory
|
||||
handler.startConversion();
|
||||
convertDirectory(sSourceURL, sTargetURL, getName(sSourceURL));
|
||||
handler.endConversion();
|
||||
}
|
||||
|
||||
// Convert a directory - return true if not cancelled
|
||||
private boolean convertDirectory(String sSourceURL, String sTargetURL, String sHeading) {
|
||||
handler.startDirectory(sSourceURL);
|
||||
|
||||
// Step 1: Get the directory
|
||||
String[] contents;
|
||||
try {
|
||||
contents = sfa2.getFolderContents(sSourceURL, true);
|
||||
}
|
||||
catch (CommandAbortedException e) {
|
||||
handler.endDirectory(sSourceURL,false);
|
||||
return true;
|
||||
}
|
||||
catch (com.sun.star.uno.Exception e) {
|
||||
handler.endDirectory(sSourceURL,false);
|
||||
return true;
|
||||
}
|
||||
int nLen = contents.length;
|
||||
IndexPageEntry[] entries = new IndexPageEntry[nLen];
|
||||
|
||||
// Step 2: Traverse subdirectories, if allowed
|
||||
if (bRecurse) {
|
||||
String sUplink = batchConverter.getConfig().getOption("uplink");
|
||||
for (int i=0; i<nLen; i++) {
|
||||
boolean bIsDirectory = false;
|
||||
try {
|
||||
bIsDirectory = sfa2.isFolder(contents[i]);
|
||||
}
|
||||
catch (CommandAbortedException e) {
|
||||
// Considered non critical, ignore
|
||||
}
|
||||
catch (com.sun.star.uno.Exception e) {
|
||||
// Considered non critical, ignore
|
||||
}
|
||||
if (bIsDirectory) {
|
||||
batchConverter.getConfig().setOption("uplink","../index.html");
|
||||
String sNewTargetURL = ensureSlash(sTargetURL) + getName(contents[i]);
|
||||
String sNewHeading = sHeading + " - " + decodeURL(getName(contents[i]));
|
||||
boolean bResult = convertDirectory(contents[i],sNewTargetURL,sNewHeading);
|
||||
batchConverter.getConfig().setOption("uplink", sUplink);
|
||||
if (!bResult) { return false; }
|
||||
// Create entry for this subdirectory
|
||||
IndexPageEntry entry = new IndexPageEntry(ensureSlash(sNewTargetURL)+"index.html",true);
|
||||
entry.setDisplayName(decodeURL(getName(contents[i])));
|
||||
entries[i]=entry;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Step 3: Traverse documents
|
||||
for (int i=0; i<nLen; i++) {
|
||||
boolean bIsFile = false;
|
||||
try {
|
||||
bIsFile = sfa2.exists(contents[i]) && !sfa2.isFolder(contents[i]);
|
||||
}
|
||||
catch (CommandAbortedException e) {
|
||||
// Considered non critical, ignore
|
||||
}
|
||||
catch (com.sun.star.uno.Exception e) {
|
||||
// Considered non critical, ignore
|
||||
}
|
||||
if (bIsFile) {
|
||||
IndexPageEntry entry = convertFile(contents[i],sTargetURL);
|
||||
if (entry!=null) { entries[i]=entry; }
|
||||
if (handler.cancel()) { return false; }
|
||||
}
|
||||
}
|
||||
|
||||
// Step 4: Create and write out the index file
|
||||
OutputFile indexFile = batchConverter.createIndexFile(sHeading, entries);
|
||||
|
||||
try {
|
||||
if (!sfa2.exists(sTargetURL)) { sfa2.createFolder(sTargetURL); }
|
||||
}
|
||||
catch (CommandAbortedException e) {
|
||||
handler.endDirectory(sSourceURL,false);
|
||||
return true;
|
||||
}
|
||||
catch (com.sun.star.uno.Exception e) {
|
||||
handler.endDirectory(sSourceURL,false);
|
||||
return true;
|
||||
}
|
||||
|
||||
try {
|
||||
// writeFile demands an InputStream, so we need a pipe
|
||||
Object xPipeObj=xComponentContext.getServiceManager().createInstanceWithContext(
|
||||
"com.sun.star.io.Pipe",xComponentContext);
|
||||
XInputStream xInStream
|
||||
= (XInputStream) UnoRuntime.queryInterface(XInputStream.class, xPipeObj );
|
||||
XOutputStream xOutStream
|
||||
= (XOutputStream) UnoRuntime.queryInterface(XOutputStream.class, xPipeObj );
|
||||
OutputStream outStream = new XOutputStreamToOutputStreamAdapter(xOutStream);
|
||||
// Feed the pipe with content...
|
||||
indexFile.write(outStream);
|
||||
outStream.flush();
|
||||
outStream.close();
|
||||
xOutStream.closeOutput();
|
||||
// ...and then write the content to the url
|
||||
sfa2.writeFile(ensureSlash(sTargetURL)+"index.html",xInStream);
|
||||
}
|
||||
catch (IOException e) {
|
||||
handler.endDirectory(sSourceURL,false);
|
||||
return true;
|
||||
}
|
||||
catch (NotConnectedException e) {
|
||||
handler.endDirectory(sSourceURL,false);
|
||||
return true;
|
||||
}
|
||||
catch (com.sun.star.uno.Exception e) {
|
||||
handler.endDirectory(sSourceURL,false);
|
||||
return true;
|
||||
}
|
||||
|
||||
handler.endDirectory(sSourceURL, true);
|
||||
|
||||
return !handler.cancel();
|
||||
}
|
||||
|
||||
private IndexPageEntry convertFile(String sSourceFileURL, String sTargetURL) {
|
||||
handler.startFile(sSourceFileURL);
|
||||
|
||||
String sTargetFileURL = ensureSlash(sTargetURL) + getBaseName(sSourceFileURL) + ".html";
|
||||
|
||||
IndexPageEntry entry = new IndexPageEntry(getName(sTargetFileURL),false);
|
||||
entry.setDisplayName(decodeURL(getBaseName(sTargetFileURL)));
|
||||
|
||||
// Load component
|
||||
XComponent xDocument;
|
||||
try {
|
||||
Object desktop = xComponentContext.getServiceManager().createInstanceWithContext(
|
||||
"com.sun.star.frame.Desktop", xComponentContext);
|
||||
|
||||
XComponentLoader xComponentLoader = (XComponentLoader)
|
||||
UnoRuntime.queryInterface(XComponentLoader.class, desktop);
|
||||
|
||||
PropertyValue[] fileProps = new PropertyValue[1];
|
||||
fileProps[0] = new PropertyValue();
|
||||
fileProps[0].Name = "Hidden";
|
||||
fileProps[0].Value = new Boolean(true);
|
||||
|
||||
xDocument = xComponentLoader.loadComponentFromURL(sSourceFileURL, "_blank", 0, fileProps);
|
||||
}
|
||||
catch (com.sun.star.io.IOException e) {
|
||||
handler.endFile(sSourceFileURL,false);
|
||||
return null;
|
||||
}
|
||||
catch (com.sun.star.uno.Exception e) {
|
||||
handler.endFile(sSourceFileURL,false);
|
||||
return null;
|
||||
}
|
||||
|
||||
// Get the title and the description of the document
|
||||
XDocumentInfoSupplier docInfo = (XDocumentInfoSupplier) UnoRuntime.queryInterface(XDocumentInfoSupplier.class, xDocument);
|
||||
XPropertySet infoProps = (XPropertySet) UnoRuntime.queryInterface(XPropertySet.class, docInfo.getDocumentInfo());
|
||||
if (infoProps!=null) {
|
||||
try {
|
||||
Object loadedTitle = infoProps.getPropertyValue("Title");
|
||||
if (AnyConverter.isString(loadedTitle)) {
|
||||
String sLoadedTitle = AnyConverter.toString(loadedTitle);
|
||||
if (bUseTitle && sLoadedTitle.length()>0) {
|
||||
entry.setDisplayName(sLoadedTitle);
|
||||
}
|
||||
}
|
||||
|
||||
Object loadedDescription = infoProps.getPropertyValue("Description");
|
||||
if (AnyConverter.isString(loadedDescription)) {
|
||||
String sLoadedDescription = AnyConverter.toString(loadedDescription);
|
||||
if (bUseDescription && sLoadedDescription.length()>0) {
|
||||
entry.setDescription(sLoadedDescription);
|
||||
}
|
||||
}
|
||||
}
|
||||
catch (UnknownPropertyException e) {
|
||||
}
|
||||
catch (WrappedTargetException e) {
|
||||
}
|
||||
catch (com.sun.star.lang.IllegalArgumentException e) {
|
||||
}
|
||||
}
|
||||
|
||||
// Determine the type of the component
|
||||
boolean bText = false;
|
||||
boolean bSpreadsheet = false;
|
||||
if (UnoRuntime.queryInterface(XTextDocument.class, xDocument)!=null) { bText=true; }
|
||||
else if (UnoRuntime.queryInterface(XSpreadsheetDocument.class, xDocument)!=null) { bSpreadsheet=true; }
|
||||
if (!bText && !bSpreadsheet) {
|
||||
handler.endFile(sSourceFileURL,false);
|
||||
xDocument.dispose();
|
||||
return null;
|
||||
}
|
||||
|
||||
// Convert using requested filter
|
||||
boolean bHtmlSuccess = true;
|
||||
|
||||
PropertyHelper exportProps = new PropertyHelper();
|
||||
exportProps.put("FilterName", bText ? sWriterFilterName : sCalcFilterName);
|
||||
exportProps.put("Overwrite", new Boolean(true));
|
||||
if (bText && writerFilterData!=null) { exportProps.put("FilterData", writerFilterData); }
|
||||
if (bSpreadsheet && calcFilterData!=null) { exportProps.put("FilterData", calcFilterData); }
|
||||
|
||||
try {
|
||||
XStorable xStore = (XStorable) UnoRuntime.queryInterface (XStorable.class, xDocument);
|
||||
xStore.storeToURL (sTargetFileURL, exportProps.toArray());
|
||||
}
|
||||
catch (com.sun.star.io.IOException e) {
|
||||
// Failed to convert; continue anyway, but don't link to the file name
|
||||
entry.setFile(null);
|
||||
bHtmlSuccess = false;
|
||||
}
|
||||
|
||||
// Convet to pdf if requested
|
||||
boolean bPdfSuccess = true;
|
||||
|
||||
if (bIncludePdf) {
|
||||
PropertyValue[] pdfProps = new PropertyValue[2];
|
||||
pdfProps[0] = new PropertyValue();
|
||||
pdfProps[0].Name = "FilterName";
|
||||
pdfProps[0].Value = bText ? "writer_pdf_Export" : "calc_pdf_Export";
|
||||
pdfProps[1] = new PropertyValue();
|
||||
pdfProps[1].Name = "Overwrite";
|
||||
pdfProps[1].Value = new Boolean(true);
|
||||
|
||||
String sPdfFileURL = ensureSlash(sTargetURL) + getBaseName(sSourceFileURL) + ".pdf";
|
||||
|
||||
try {
|
||||
XStorable xStore = (XStorable) UnoRuntime.queryInterface (XStorable.class, xDocument);
|
||||
xStore.storeToURL (sPdfFileURL, pdfProps);
|
||||
entry.setPdfFile(sPdfFileURL);
|
||||
}
|
||||
catch (com.sun.star.io.IOException e) {
|
||||
// Not critical, continue without pdf
|
||||
bPdfSuccess = false;
|
||||
}
|
||||
}
|
||||
|
||||
xDocument.dispose();
|
||||
|
||||
// Include original document if required
|
||||
if (bIncludeOriginal) {
|
||||
// TODO
|
||||
}
|
||||
|
||||
// Report a failure to the user if either of the exports failed
|
||||
handler.endFile(sSourceFileURL,bHtmlSuccess && bPdfSuccess);
|
||||
// But return the index entry even if only one succeded
|
||||
if (bHtmlSuccess || bPdfSuccess) { return entry; }
|
||||
else { return null; }
|
||||
}
|
||||
|
||||
private String getName(String sURL) {
|
||||
int n = sURL.lastIndexOf("/");
|
||||
return n>-1 ? sURL.substring(n+1) : sURL;
|
||||
}
|
||||
|
||||
private String getBaseName(String sURL) {
|
||||
String sName = getName(sURL);
|
||||
int n = sName.lastIndexOf(".");
|
||||
return n>-1 ? sName.substring(0,n) : sName;
|
||||
}
|
||||
|
||||
private String ensureSlash(String sURL) {
|
||||
return sURL.endsWith("/") ? sURL : sURL+"/";
|
||||
}
|
||||
|
||||
private String decodeURL(String sURL) {
|
||||
try {
|
||||
return new URI(sURL).getPath();
|
||||
}
|
||||
catch (URISyntaxException e) {
|
||||
return sURL;
|
||||
}
|
||||
}
|
||||
|
||||
// Implement methods from interface XTypeProvider
|
||||
|
||||
public com.sun.star.uno.Type[] getTypes() {
|
||||
Type[] typeReturn = {};
|
||||
try {
|
||||
typeReturn = new Type[] {
|
||||
new Type( XBatchConverter.class ),
|
||||
new Type( XTypeProvider.class ),
|
||||
new Type( XServiceName.class ),
|
||||
new Type( XServiceInfo.class ) };
|
||||
}
|
||||
catch( Exception exception ) {
|
||||
|
||||
}
|
||||
|
||||
return( typeReturn );
|
||||
}
|
||||
|
||||
|
||||
public byte[] getImplementationId() {
|
||||
byte[] byteReturn = {};
|
||||
|
||||
byteReturn = new String( "" + this.hashCode() ).getBytes();
|
||||
|
||||
return( byteReturn );
|
||||
}
|
||||
|
||||
// Implement method from interface XServiceName
|
||||
public String getServiceName() {
|
||||
return( __serviceName );
|
||||
}
|
||||
|
||||
// Implement methods from interface XServiceInfo
|
||||
public boolean supportsService(String stringServiceName) {
|
||||
return( stringServiceName.equals( __serviceName ) );
|
||||
}
|
||||
|
||||
public String getImplementationName() {
|
||||
return( __implementationName );
|
||||
}
|
||||
|
||||
public String[] getSupportedServiceNames() {
|
||||
String[] stringSupportedServiceNames = { __serviceName };
|
||||
return( stringSupportedServiceNames );
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
|
@ -0,0 +1,72 @@
|
|||
/************************************************************************
|
||||
*
|
||||
* BatchHandlerAdapter.java
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License version 2.1, as published by the Free Software Foundation.
|
||||
*
|
||||
* This library 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
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston,
|
||||
* MA 02111-1307 USA
|
||||
*
|
||||
* Copyright: 2002-2008 by Henrik Just
|
||||
*
|
||||
* All Rights Reserved.
|
||||
*
|
||||
* Version 1.0 (2008-10-05)
|
||||
*
|
||||
*/
|
||||
|
||||
package org.openoffice.da.comp.writer2xhtml;
|
||||
|
||||
import writer2latex.api.BatchHandler;
|
||||
import org.openoffice.da.writer2xhtml.XBatchHandler;
|
||||
|
||||
/** The uno interface provides an XBatchHandler implementation, the java
|
||||
* interface requires a BatchHandler implementation. This simple class
|
||||
* implements the latter using an instance of the former.
|
||||
*/
|
||||
public class BatchHandlerAdapter implements BatchHandler {
|
||||
|
||||
private XBatchHandler unoHandler;
|
||||
|
||||
public BatchHandlerAdapter(XBatchHandler unoHandler) {
|
||||
this.unoHandler = unoHandler;
|
||||
}
|
||||
|
||||
public void startConversion() {
|
||||
unoHandler.startConversion();
|
||||
}
|
||||
|
||||
public void endConversion() {
|
||||
unoHandler.endConversion();
|
||||
}
|
||||
|
||||
public void startDirectory(String sName) {
|
||||
unoHandler.startDirectory(sName);
|
||||
}
|
||||
|
||||
public void endDirectory(String sName, boolean bSuccess) {
|
||||
unoHandler.endDirectory(sName, bSuccess);
|
||||
}
|
||||
|
||||
public void startFile(String sName) {
|
||||
unoHandler.startFile(sName);
|
||||
}
|
||||
|
||||
public void endFile(String sName, boolean bSuccess) {
|
||||
unoHandler.endFile(sName, bSuccess);
|
||||
}
|
||||
|
||||
public boolean cancel() {
|
||||
return unoHandler.cancel();
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,56 @@
|
|||
/************************************************************************
|
||||
*
|
||||
* W2XExportFilter.java
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License version 2.1, as published by the Free Software Foundation.
|
||||
*
|
||||
* This library 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
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston,
|
||||
* MA 02111-1307 USA
|
||||
*
|
||||
* Copyright: 2002-2008 by Henrik Just
|
||||
*
|
||||
* All Rights Reserved.
|
||||
*
|
||||
* Version 1.0 (2008-07-21)
|
||||
*
|
||||
*/
|
||||
|
||||
package org.openoffice.da.comp.writer2xhtml;
|
||||
|
||||
import com.sun.star.uno.XComponentContext;
|
||||
|
||||
import org.openoffice.da.comp.w2lcommon.filter.ExportFilterBase;
|
||||
|
||||
|
||||
/** This class implements the xhtml export filter component
|
||||
*/
|
||||
public class W2XExportFilter extends ExportFilterBase {
|
||||
|
||||
/** Service name for the component */
|
||||
public static final String __serviceName = "org.openoffice.da.comp.writer2xhtml.W2XExportFilter";
|
||||
|
||||
/** Implementation name for the component */
|
||||
public static final String __implementationName = "org.openoffice.da.comp.writer2xhtml.W2XExportFilter";
|
||||
|
||||
/** Filter name to include in error messages */
|
||||
public static final String __displayName = "Writer2xhtml";
|
||||
|
||||
public W2XExportFilter(XComponentContext xComponentContext1) {
|
||||
super(xComponentContext1);
|
||||
xMSF = W2XRegistration.xMultiServiceFactory;
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
|
@ -0,0 +1,119 @@
|
|||
/************************************************************************
|
||||
*
|
||||
* W2XRegistration.java
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License version 2.1, as published by the Free Software Foundation.
|
||||
*
|
||||
* This library 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
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston,
|
||||
* MA 02111-1307 USA
|
||||
*
|
||||
* Copyright: 2002-2008 by Henrik Just
|
||||
*
|
||||
* All Rights Reserved.
|
||||
*
|
||||
* Version 1.0 (2008-10-04)
|
||||
*
|
||||
*/
|
||||
|
||||
package org.openoffice.da.comp.writer2xhtml;
|
||||
|
||||
import com.sun.star.lang.XMultiServiceFactory;
|
||||
import com.sun.star.lang.XSingleServiceFactory;
|
||||
import com.sun.star.registry.XRegistryKey;
|
||||
|
||||
import com.sun.star.comp.loader.FactoryHelper;
|
||||
|
||||
/** This class provides a static method to instantiate our uno components
|
||||
* on demand (__getServiceFactory()), and a static method to give
|
||||
* information about the components (__writeRegistryServiceInfo()).
|
||||
* Furthermore, it saves the XMultiServiceFactory provided to the
|
||||
* __getServiceFactory method for future reference by the componentes.
|
||||
*/
|
||||
public class W2XRegistration {
|
||||
|
||||
public static XMultiServiceFactory xMultiServiceFactory;
|
||||
|
||||
/**
|
||||
* Returns a factory for creating the service.
|
||||
* This method is called by the <code>JavaLoader</code>
|
||||
*
|
||||
* @return returns a <code>XSingleServiceFactory</code> for creating the
|
||||
* component
|
||||
*
|
||||
* @param implName the name of the implementation for which a
|
||||
* service is desired
|
||||
* @param multiFactory the service manager to be used if needed
|
||||
* @param regKey the registryKey
|
||||
*
|
||||
* @see com.sun.star.comp.loader.JavaLoader
|
||||
*/
|
||||
public static XSingleServiceFactory __getServiceFactory(String implName,
|
||||
XMultiServiceFactory multiFactory, XRegistryKey regKey) {
|
||||
xMultiServiceFactory = multiFactory;
|
||||
XSingleServiceFactory xSingleServiceFactory = null;
|
||||
if (implName.equals(W2XExportFilter.class.getName()) ) {
|
||||
xSingleServiceFactory = FactoryHelper.getServiceFactory(W2XExportFilter.class,
|
||||
W2XExportFilter.__serviceName,
|
||||
multiFactory,
|
||||
regKey);
|
||||
}
|
||||
else if (implName.equals(BatchConverter.__implementationName) ) {
|
||||
xSingleServiceFactory = FactoryHelper.getServiceFactory(BatchConverter.class,
|
||||
BatchConverter.__serviceName,
|
||||
multiFactory,
|
||||
regKey);
|
||||
}
|
||||
else if (implName.equals(XhtmlOptionsDialog.__implementationName)) {
|
||||
xSingleServiceFactory = FactoryHelper.getServiceFactory(XhtmlOptionsDialog.class,
|
||||
XhtmlOptionsDialog.__serviceName,
|
||||
multiFactory,
|
||||
regKey);
|
||||
}
|
||||
else if (implName.equals(XhtmlOptionsDialogXsl.__implementationName)) {
|
||||
xSingleServiceFactory = FactoryHelper.getServiceFactory(XhtmlOptionsDialogXsl.class,
|
||||
XhtmlOptionsDialogXsl.__serviceName,
|
||||
multiFactory,
|
||||
regKey);
|
||||
}
|
||||
else if (implName.equals(XhtmlOptionsDialogCalc.__implementationName)) {
|
||||
xSingleServiceFactory = FactoryHelper.getServiceFactory(XhtmlOptionsDialogCalc.class,
|
||||
XhtmlOptionsDialogCalc.__serviceName,
|
||||
multiFactory,
|
||||
regKey);
|
||||
}
|
||||
|
||||
return xSingleServiceFactory;
|
||||
}
|
||||
|
||||
/**
|
||||
* Writes the service information into the given registry key.
|
||||
* This method is called by the <code>JavaLoader</code>
|
||||
* <p>
|
||||
* @return returns true if the operation succeeded
|
||||
* @param regKey the registryKey
|
||||
* @see com.sun.star.comp.loader.JavaLoader
|
||||
*/
|
||||
public static boolean __writeRegistryServiceInfo(XRegistryKey regKey) {
|
||||
return
|
||||
FactoryHelper.writeRegistryServiceInfo(BatchConverter.__implementationName,
|
||||
BatchConverter.__serviceName, regKey) &
|
||||
FactoryHelper.writeRegistryServiceInfo(W2XExportFilter.__implementationName,
|
||||
W2XExportFilter.__serviceName, regKey) &
|
||||
FactoryHelper.writeRegistryServiceInfo(XhtmlOptionsDialog.__implementationName,
|
||||
XhtmlOptionsDialog.__serviceName, regKey) &
|
||||
FactoryHelper.writeRegistryServiceInfo(XhtmlOptionsDialogXsl.__implementationName,
|
||||
XhtmlOptionsDialogXsl.__serviceName, regKey) &
|
||||
FactoryHelper.writeRegistryServiceInfo(XhtmlOptionsDialogCalc.__implementationName,
|
||||
XhtmlOptionsDialogCalc.__serviceName, regKey);
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,216 @@
|
|||
/************************************************************************
|
||||
*
|
||||
* XhtmlOptionsDialog.java
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License version 2.1, as published by the Free Software Foundation.
|
||||
*
|
||||
* This library 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
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston,
|
||||
* MA 02111-1307 USA
|
||||
*
|
||||
* Copyright: 2002-2008 by Henrik Just
|
||||
*
|
||||
* All Rights Reserved.
|
||||
*
|
||||
* Version 1.0 (2008-11-16)
|
||||
*
|
||||
*/
|
||||
|
||||
package org.openoffice.da.comp.writer2xhtml;
|
||||
|
||||
import com.sun.star.awt.XDialog;
|
||||
import com.sun.star.beans.XPropertySet;
|
||||
import com.sun.star.uno.XComponentContext;
|
||||
|
||||
import org.openoffice.da.comp.w2lcommon.helper.PropertyHelper;
|
||||
import org.openoffice.da.comp.w2lcommon.filter.OptionsDialogBase;
|
||||
|
||||
/** This class provides a uno component which implements a filter ui for the
|
||||
* Xhtml export
|
||||
*/
|
||||
public class XhtmlOptionsDialog extends OptionsDialogBase {
|
||||
|
||||
/** The component will be registered under this name.
|
||||
*/
|
||||
public static String __serviceName = "org.openoffice.da.writer2xhtml.XhtmlOptionsDialog";
|
||||
|
||||
/** The component should also have an implementation name.
|
||||
*/
|
||||
public static String __implementationName = "org.openoffice.da.comp.writer2xhtml.XhtmlOptionsDialog";
|
||||
|
||||
public String getDialogLibraryName() { return "W2XDialogs"; }
|
||||
|
||||
/** Return the name of the dialog within the library
|
||||
*/
|
||||
public String getDialogName() { return "XhtmlOptions"; }
|
||||
|
||||
/** Return the name of the registry path
|
||||
*/
|
||||
public String getRegistryPath() {
|
||||
return "/org.openoffice.da.Writer2xhtml.Options/XhtmlOptions";
|
||||
}
|
||||
|
||||
/** Create a new XhtmlOptionsDialog */
|
||||
public XhtmlOptionsDialog(XComponentContext xContext) {
|
||||
super(xContext);
|
||||
xMSF = W2XRegistration.xMultiServiceFactory;
|
||||
}
|
||||
|
||||
/** Load settings from the registry to the dialog */
|
||||
protected void loadSettings(XPropertySet xProps) {
|
||||
// Style
|
||||
loadConfig(xProps);
|
||||
loadCheckBoxOption(xProps, "ConvertToPx");
|
||||
loadNumericOption(xProps, "Scaling");
|
||||
loadNumericOption(xProps, "ColumnScaling");
|
||||
loadCheckBoxOption(xProps, "OriginalImageSize");
|
||||
|
||||
// Special content
|
||||
loadCheckBoxOption(xProps, "Notes");
|
||||
loadCheckBoxOption(xProps, "UseDublinCore");
|
||||
|
||||
// AutoCorrect
|
||||
loadCheckBoxOption(xProps, "IgnoreHardLineBreaks");
|
||||
loadCheckBoxOption(xProps, "IgnoreEmptyParagraphs");
|
||||
loadCheckBoxOption(xProps, "IgnoreDoubleSpaces");
|
||||
|
||||
// Files
|
||||
loadCheckBoxOption(xProps, "Split");
|
||||
loadListBoxOption(xProps, "SplitLevel");
|
||||
loadListBoxOption(xProps, "RepeatLevels");
|
||||
loadCheckBoxOption(xProps, "SaveImagesInSubdir");
|
||||
loadTextFieldOption(xProps, "XsltPath");
|
||||
|
||||
updateLockedOptions();
|
||||
enableControls();
|
||||
}
|
||||
|
||||
/** Save settings from the dialog to the registry and create FilterData */
|
||||
protected void saveSettings(XPropertySet xProps, PropertyHelper helper) {
|
||||
// Style
|
||||
short nConfig = saveConfig(xProps, helper);
|
||||
String[] sCoreStyles = { "Chocolate", "Midnight", "Modernist",
|
||||
"Oldstyle", "Steely", "Swiss", "Traditional", "Ultramarine" };
|
||||
switch (nConfig) {
|
||||
case 0: helper.put("ConfigURL","*default.xml"); break;
|
||||
case 1:
|
||||
case 2:
|
||||
case 3:
|
||||
case 4:
|
||||
case 5:
|
||||
case 6:
|
||||
case 7:
|
||||
case 8: helper.put("ConfigURL","*cleanxhtml.xml");
|
||||
helper.put("custom_stylesheet",
|
||||
"http://www.w3.org/StyleSheets/Core/"+sCoreStyles[nConfig-1]);
|
||||
break;
|
||||
case 9: helper.put("ConfigURL","$(user)/writer2xhtml.xml");
|
||||
helper.put("AutoCreate","true");
|
||||
}
|
||||
|
||||
saveCheckBoxOption(xProps, helper, "ConvertToPx", "convert_to_px");
|
||||
saveNumericOptionAsPercentage(xProps, helper, "Scaling", "scaling");
|
||||
saveNumericOptionAsPercentage(xProps, helper, "ColumnScaling", "column_scaling");
|
||||
saveCheckBoxOption(xProps, helper, "OriginalImageSize", "original_image_size");
|
||||
|
||||
// Special content
|
||||
saveCheckBoxOption(xProps, helper, "Notes", "notes");
|
||||
saveCheckBoxOption(xProps, helper, "UseDublinCore", "use_dublin_core");
|
||||
|
||||
// AutoCorrect
|
||||
saveCheckBoxOption(xProps, helper, "IgnoreHardLineBreaks", "ignore_hard_line_breaks");
|
||||
saveCheckBoxOption(xProps, helper, "IgnoreEmptyParagraphs", "ignore_empty_paragraphs");
|
||||
saveCheckBoxOption(xProps, helper, "IgnoreDoubleSpaces", "ignore_double_spaces");
|
||||
|
||||
// Files
|
||||
boolean bSplit = saveCheckBoxOption(xProps, "Split");
|
||||
short nSplitLevel = saveListBoxOption(xProps, "SplitLevel");
|
||||
short nRepeatLevels = saveListBoxOption(xProps, "RepeatLevels");
|
||||
if (!isLocked("split_level")) {
|
||||
if (bSplit) {
|
||||
helper.put("split_level",Integer.toString(nSplitLevel+1));
|
||||
helper.put("repeat_levels",Integer.toString(nRepeatLevels));
|
||||
}
|
||||
else {
|
||||
helper.put("split_level","0");
|
||||
}
|
||||
}
|
||||
|
||||
saveCheckBoxOption(xProps, helper, "SaveImagesInSubdir", "save_images_in_subdir");
|
||||
saveTextFieldOption(xProps, helper, "XsltPath", "xslt_path");
|
||||
|
||||
}
|
||||
|
||||
|
||||
// Implement XDialogEventHandler
|
||||
public boolean callHandlerMethod(XDialog xDialog, Object event, String sMethod) {
|
||||
if (sMethod.equals("ConfigChange")) {
|
||||
updateLockedOptions();
|
||||
enableControls();
|
||||
}
|
||||
else if (sMethod.equals("SplitChange")) {
|
||||
enableSplitLevel();
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
public String[] getSupportedMethodNames() {
|
||||
String[] sNames = { "ConfigChange", "SplitChange" };
|
||||
return sNames;
|
||||
}
|
||||
|
||||
private void enableControls() {
|
||||
// Style
|
||||
setControlEnabled("ScalingLabel",!isLocked("scaling"));
|
||||
setControlEnabled("Scaling",!isLocked("scaling"));
|
||||
setControlEnabled("ColumnScalingLabel",!isLocked("column_scaling"));
|
||||
setControlEnabled("ColumnScaling",!isLocked("column_scaling"));
|
||||
setControlEnabled("ConvertToPx",!isLocked("convert_to_px"));
|
||||
setControlEnabled("OriginalImageSize",!isLocked("original_image_size"));
|
||||
|
||||
// Special content
|
||||
setControlEnabled("Notes",!isLocked("notes"));
|
||||
setControlEnabled("UseDublinCore",!isLocked("use_dublin_core"));
|
||||
|
||||
// AutoCorrect
|
||||
setControlEnabled("IgnoreHardLineBreaks",!isLocked("ignore_hard_line_breaks"));
|
||||
setControlEnabled("IgnoreEmptyParagraphs",!isLocked("ignore_empty_paragraphs"));
|
||||
setControlEnabled("IgnoreDoubleSpaces",!isLocked("ignore_double_spaces"));
|
||||
|
||||
// Files
|
||||
boolean bSplit = getCheckBoxStateAsBoolean("Split");
|
||||
setControlEnabled("Split",!isLocked("split_level"));
|
||||
setControlEnabled("SplitLevelLabel",!isLocked("split_level") && bSplit);
|
||||
setControlEnabled("SplitLevel",!isLocked("split_level") && bSplit);
|
||||
setControlEnabled("RepeatLevelsLabel",!isLocked("repeat_levels") && !isLocked("split_level") && bSplit);
|
||||
setControlEnabled("RepeatLevels",!isLocked("repeat_levels") && !isLocked("split_level") && bSplit);
|
||||
setControlEnabled("SaveImagesInSubdir",!isLocked("save_images_in_subdir"));
|
||||
setControlEnabled("XsltPathLabel",(this instanceof XhtmlOptionsDialogXsl) && !isLocked("xslt_path"));
|
||||
setControlEnabled("XsltPath",(this instanceof XhtmlOptionsDialogXsl) && !isLocked("xslt_path"));
|
||||
}
|
||||
|
||||
private void enableSplitLevel() {
|
||||
if (!isLocked("split_level")) {
|
||||
boolean bState = getCheckBoxStateAsBoolean("Split");
|
||||
setControlEnabled("SplitLevelLabel",bState);
|
||||
setControlEnabled("SplitLevel",bState);
|
||||
if (!isLocked("repeat_levels")) {
|
||||
setControlEnabled("RepeatLevelsLabel",bState);
|
||||
setControlEnabled("RepeatLevels",bState);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
|
@ -0,0 +1,174 @@
|
|||
/************************************************************************
|
||||
*
|
||||
* XhtmlOptionsDialogCalc.java
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License version 2.1, as published by the Free Software Foundation.
|
||||
*
|
||||
* This library 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
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston,
|
||||
* MA 02111-1307 USA
|
||||
*
|
||||
* Copyright: 2002-2009 by Henrik Just
|
||||
*
|
||||
* All Rights Reserved.
|
||||
*
|
||||
* Version 1.0 (2009-02-18)
|
||||
*
|
||||
*/
|
||||
|
||||
package org.openoffice.da.comp.writer2xhtml;
|
||||
|
||||
import com.sun.star.awt.XDialog;
|
||||
import com.sun.star.beans.XPropertySet;
|
||||
import com.sun.star.uno.XComponentContext;
|
||||
|
||||
import org.openoffice.da.comp.w2lcommon.helper.PropertyHelper;
|
||||
import org.openoffice.da.comp.w2lcommon.filter.OptionsDialogBase;
|
||||
|
||||
/** This class provides a uno component which implements a filter ui for the
|
||||
* Xhtml export in Calc
|
||||
*/
|
||||
public class XhtmlOptionsDialogCalc extends OptionsDialogBase {
|
||||
|
||||
/** The component will be registered under this name.
|
||||
*/
|
||||
public static String __serviceName = "org.openoffice.da.writerxhtml.XhtmlOptionsDialogCalc";
|
||||
|
||||
/** The component should also have an implementation name.
|
||||
*/
|
||||
public static String __implementationName = "org.openoffice.da.comp.writer2xhtml.XhtmlOptionsDialogCalc";
|
||||
|
||||
public String getDialogLibraryName() { return "W2XDialogs"; }
|
||||
|
||||
/** Return the name of the dialog within the library
|
||||
*/
|
||||
public String getDialogName() { return "XhtmlOptionsCalc"; }
|
||||
|
||||
/** Return the name of the registry path
|
||||
*/
|
||||
public String getRegistryPath() {
|
||||
return "/org.openoffice.da.Writer2xhtml.Options/XhtmlOptionsCalc";
|
||||
}
|
||||
|
||||
/** Create a new XhtmlOptionsDialogCalc */
|
||||
public XhtmlOptionsDialogCalc(XComponentContext xContext) {
|
||||
super(xContext);
|
||||
xMSF = W2XRegistration.xMultiServiceFactory;
|
||||
}
|
||||
|
||||
/** Load settings from the registry to the dialog */
|
||||
protected void loadSettings(XPropertySet xProps) {
|
||||
// Style
|
||||
loadConfig(xProps);
|
||||
loadCheckBoxOption(xProps, "ConvertToPx");
|
||||
loadNumericOption(xProps, "Scaling");
|
||||
loadNumericOption(xProps, "ColumnScaling");
|
||||
loadCheckBoxOption(xProps, "OriginalImageSize");
|
||||
|
||||
// Special content
|
||||
loadCheckBoxOption(xProps, "Notes");
|
||||
loadCheckBoxOption(xProps, "UseDublinCore");
|
||||
|
||||
// Sheets
|
||||
loadCheckBoxOption(xProps, "DisplayHiddenSheets");
|
||||
loadCheckBoxOption(xProps, "DisplayHiddenRowsCols");
|
||||
loadCheckBoxOption(xProps, "DisplayFilteredRowsCols");
|
||||
loadCheckBoxOption(xProps, "ApplyPrintRanges");
|
||||
loadCheckBoxOption(xProps, "UseTitleAsHeading");
|
||||
loadCheckBoxOption(xProps, "UseSheetNamesAsHeadings");
|
||||
|
||||
// Files
|
||||
loadCheckBoxOption(xProps, "CalcSplit");
|
||||
loadCheckBoxOption(xProps, "SaveImagesInSubdir");
|
||||
|
||||
updateLockedOptions();
|
||||
enableControls();
|
||||
}
|
||||
|
||||
/** Save settings from the dialog to the registry and create FilterData */
|
||||
protected void saveSettings(XPropertySet xProps, PropertyHelper helper) {
|
||||
// Style
|
||||
short nConfig = saveConfig(xProps, helper);
|
||||
if (nConfig==0) {
|
||||
helper.put("ConfigURL","*default.xml");
|
||||
}
|
||||
else if (nConfig==1) {
|
||||
helper.put("ConfigURL","$(user)/writer2xhtml.xml");
|
||||
helper.put("AutoCreate","true");
|
||||
}
|
||||
|
||||
saveCheckBoxOption(xProps, helper, "ConvertToPx", "convert_to_px");
|
||||
saveNumericOptionAsPercentage(xProps, helper, "Scaling", "scaling");
|
||||
saveNumericOptionAsPercentage(xProps, helper, "ColumnScaling", "column_scaling");
|
||||
saveCheckBoxOption(xProps, helper, "OriginalImageSize", "original_image_size");
|
||||
|
||||
// Special content
|
||||
saveCheckBoxOption(xProps, helper, "Notes", "notes");
|
||||
saveCheckBoxOption(xProps, helper, "UseDublinCore", "use_dublin_core");
|
||||
|
||||
// Sheets
|
||||
saveCheckBoxOption(xProps, helper, "DisplayHiddenSheets", "display_hidden_sheets");
|
||||
saveCheckBoxOption(xProps, helper, "DisplayHiddenRowsCols", "display_hidden_rows_cols");
|
||||
saveCheckBoxOption(xProps, helper, "DisplayFilteredRowsCols", "display_filtered_rows_cols");
|
||||
saveCheckBoxOption(xProps, helper, "ApplyPrintRanges", "apply_print_ranges");
|
||||
saveCheckBoxOption(xProps, helper, "UseTitleAsHeading", "use_title_as_heading");
|
||||
saveCheckBoxOption(xProps, helper, "UseSheetNamesAsHeadings", "use_sheet_names_as_headings");
|
||||
|
||||
// Files
|
||||
saveCheckBoxOption(xProps, helper, "CalcSplit", "calc_split");
|
||||
saveCheckBoxOption(xProps, helper, "SaveImagesInSubdir", "save_images_in_subdir");
|
||||
|
||||
}
|
||||
|
||||
// Implement XDialogEventHandler
|
||||
public boolean callHandlerMethod(XDialog xDialog, Object event, String sMethod) {
|
||||
if (sMethod.equals("ConfigChange")) {
|
||||
updateLockedOptions();
|
||||
enableControls();
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
public String[] getSupportedMethodNames() {
|
||||
String[] sNames = { "ConfigChange" };
|
||||
return sNames;
|
||||
}
|
||||
|
||||
private void enableControls() {
|
||||
// Style
|
||||
setControlEnabled("ConvertToPx",!isLocked("convert_to_px"));
|
||||
setControlEnabled("ScalingLabel",!isLocked("scaling"));
|
||||
setControlEnabled("Scaling",!isLocked("scaling"));
|
||||
setControlEnabled("ColumnScalingLabel",!isLocked("column_scaling"));
|
||||
setControlEnabled("ColumnScaling",!isLocked("column_scaling"));
|
||||
setControlEnabled("OriginalImageSize",!isLocked("original_image_size"));
|
||||
|
||||
// Special content
|
||||
setControlEnabled("Notes",!isLocked("notes"));
|
||||
setControlEnabled("UseDublinCore",!isLocked("use_dublin_core"));
|
||||
|
||||
// Sheets
|
||||
setControlEnabled("DisplayHiddenSheets", !isLocked("display_hidden_sheets"));
|
||||
setControlEnabled("DisplayHiddenRowsCols", !isLocked("display_hidden_rows_cols"));
|
||||
setControlEnabled("DisplayFilteredRowsCols", !isLocked("display_filtered_rows_cols"));
|
||||
setControlEnabled("ApplyPrintRanges", !isLocked("apply_print_ranges"));
|
||||
setControlEnabled("UseTitleAsHeading", !isLocked("use_title_as_heading"));
|
||||
setControlEnabled("UseSheetNamesAsHeadings", !isLocked("use_sheet_names_as_headings"));
|
||||
|
||||
// Files
|
||||
setControlEnabled("CalcSplit",!isLocked("calc_split"));
|
||||
setControlEnabled("SaveImagesInSubdir",!isLocked("save_images_in_subdir"));
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
|
@ -0,0 +1,52 @@
|
|||
/************************************************************************
|
||||
*
|
||||
* XhtmlOptionsDialogXsl.java
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License version 2.1, as published by the Free Software Foundation.
|
||||
*
|
||||
* This library 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
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston,
|
||||
* MA 02111-1307 USA
|
||||
*
|
||||
* Copyright: 2002-2008 by Henrik Just
|
||||
*
|
||||
* All Rights Reserved.
|
||||
*
|
||||
* Version 1.0 (2008-09-11)
|
||||
*
|
||||
*/
|
||||
|
||||
package org.openoffice.da.comp.writer2xhtml;
|
||||
|
||||
import com.sun.star.uno.XComponentContext;
|
||||
|
||||
/** This class provides a uno component which implements a filter ui for the
|
||||
* Xhtml export (xsl variant)
|
||||
* This variant of the dialog has the XsltPath setting enabled
|
||||
*/
|
||||
public class XhtmlOptionsDialogXsl extends XhtmlOptionsDialog {
|
||||
/** The component will be registered under this name.
|
||||
*/
|
||||
public static String __serviceName = "org.openoffice.da.writer2xhtml.XhtmlOptionsDialogXsl";
|
||||
|
||||
/** The component should also have an implementation name.
|
||||
*/
|
||||
public static String __implementationName = "org.openoffice.da.comp.writer2xhtml.XhtmlOptionsDialogXsl";
|
||||
|
||||
/** Create a new XhtmlOptionsDialogXsl */
|
||||
public XhtmlOptionsDialogXsl(XComponentContext xContext) {
|
||||
super(xContext);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
382
source/java/writer2latex/Application.java
Normal file
382
source/java/writer2latex/Application.java
Normal file
|
@ -0,0 +1,382 @@
|
|||
/************************************************************************
|
||||
*
|
||||
* Application.java
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License version 2.1, as published by the Free Software Foundation.
|
||||
*
|
||||
* This library 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
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston,
|
||||
* MA 02111-1307 USA
|
||||
*
|
||||
* Copyright: 2002-2008 by Henrik Just
|
||||
*
|
||||
* All Rights Reserved.
|
||||
*
|
||||
* Version 1.0 (2008-11-22)
|
||||
*
|
||||
*/
|
||||
|
||||
package writer2latex;
|
||||
|
||||
import java.io.ByteArrayInputStream;
|
||||
import java.io.File;
|
||||
import java.io.FileNotFoundException;
|
||||
//import java.io.FileOutputStream;
|
||||
import java.io.FileInputStream;
|
||||
import java.io.IOException;
|
||||
import java.util.Enumeration;
|
||||
import java.util.Hashtable;
|
||||
import java.util.Vector;
|
||||
|
||||
import writer2latex.api.BatchConverter;
|
||||
import writer2latex.api.Converter;
|
||||
import writer2latex.api.ConverterFactory;
|
||||
import writer2latex.api.ConverterResult;
|
||||
import writer2latex.api.MIMETypes;
|
||||
//import writer2latex.api.OutputFile;
|
||||
|
||||
import writer2latex.util.Misc;
|
||||
|
||||
/**
|
||||
* <p>Commandline utility to convert an OpenOffice.org Writer XML file into XHTML/LaTeX/BibTeX</p>
|
||||
* <p>The utility is invoked with the following command line:</p>
|
||||
* <pre>java -jar writer2latex.jar [options] source [target]</pre>
|
||||
* <p>Where the available options are
|
||||
* <ul>
|
||||
* <li><code>-latex</code>, <code>-bibtex</code>, <code>-xhtml</code>,
|
||||
<code>-xhtml+mathml</code>, <code>-xhtml+mathml+xsl</code>
|
||||
* <li><code>-recurse</code>
|
||||
* <li><code>-ultraclean</code>, <code>-clean</code>, <code>-pdfscreen</code>,
|
||||
* <code>-pdfprint</code>, <code>-cleanxhtml</code>
|
||||
* <li><code>-config[=]filename</code>
|
||||
* <li><code>-template[=]filename</code>
|
||||
* <li><code>-option[=]value</code>
|
||||
* </ul>
|
||||
* <p>where <code>option</code> can be any simple option known to Writer2LaTeX
|
||||
* (see documentation for the configuration file).</p>
|
||||
*/
|
||||
public final class Application {
|
||||
|
||||
/* Based on command-line parameters. */
|
||||
private String sTargetMIME = MIMETypes.LATEX;
|
||||
private boolean bRecurse = false;
|
||||
private Vector configFileNames = new Vector();
|
||||
private String sTemplateFileName = null;
|
||||
private Hashtable options = new Hashtable();
|
||||
private String sSource = null;
|
||||
private String sTarget = null;
|
||||
|
||||
/**
|
||||
* Main method
|
||||
*
|
||||
* @param args The argument passed on the command line.
|
||||
*/
|
||||
public static final void main (String[] args){
|
||||
try {
|
||||
Application app = new Application();
|
||||
app.parseCommandLine(args);
|
||||
app.doConversion();
|
||||
} catch (IllegalArgumentException ex) {
|
||||
String msg = ex.getMessage();
|
||||
showUsage(msg);
|
||||
}
|
||||
}
|
||||
|
||||
// Convert the directory or file
|
||||
private void doConversion() {
|
||||
// Step 1: Say hello...
|
||||
String sOutputFormat;
|
||||
if (MIMETypes.LATEX.equals(sTargetMIME)) { sOutputFormat = "LaTeX"; }
|
||||
else if (MIMETypes.BIBTEX.equals(sTargetMIME)) { sOutputFormat = "BibTeX"; }
|
||||
else { sOutputFormat = "xhtml"; }
|
||||
System.out.println();
|
||||
System.out.println("This is Writer2" + sOutputFormat +
|
||||
", Version " + ConverterFactory.getVersion() +
|
||||
" (" + ConverterFactory.getDate() + ")");
|
||||
System.out.println();
|
||||
System.out.println("Starting conversion...");
|
||||
|
||||
// Step 2: Examine source
|
||||
File source = new File(sSource);
|
||||
if (!source.exists()) {
|
||||
System.out.println("I'm sorry, I can't find "+sSource);
|
||||
System.exit(1);
|
||||
}
|
||||
if (!source.canRead()) {
|
||||
System.out.println("I'm sorry, I can't read "+sSource);
|
||||
System.exit(1);
|
||||
}
|
||||
boolean bBatch = source.isDirectory();
|
||||
|
||||
// Step 3: Examine target
|
||||
File target;
|
||||
if (bBatch) {
|
||||
if (sTarget==null) {
|
||||
target=source;
|
||||
}
|
||||
else {
|
||||
target = new File(sTarget);
|
||||
}
|
||||
}
|
||||
else {
|
||||
if (sTarget==null) {
|
||||
target = new File(source.getParent(),Misc.removeExtension(source.getName()));
|
||||
}
|
||||
else {
|
||||
target = new File(sTarget);
|
||||
if (sTarget.endsWith(File.separator)) {
|
||||
target = new File(target,Misc.removeExtension(source.getName()));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Step 4: Create converters
|
||||
Converter converter = ConverterFactory.createConverter(sTargetMIME);
|
||||
if (converter==null) {
|
||||
System.out.println("Failed to create converter for "+sTargetMIME);
|
||||
System.exit(1);
|
||||
}
|
||||
|
||||
BatchConverter batchCv = null;
|
||||
if (bBatch) {
|
||||
batchCv = ConverterFactory.createBatchConverter(MIMETypes.XHTML);
|
||||
if (batchCv==null) {
|
||||
System.out.println("Failed to create batch converter");
|
||||
System.exit(1);
|
||||
}
|
||||
batchCv.setConverter(converter);
|
||||
}
|
||||
|
||||
// Step 5: Read template
|
||||
if (sTemplateFileName!=null) {
|
||||
try {
|
||||
System.out.println("Reading template "+sTemplateFileName);
|
||||
byte [] templateBytes = Misc.inputStreamToByteArray(new FileInputStream(sTemplateFileName));
|
||||
converter.readTemplate(new ByteArrayInputStream(templateBytes));
|
||||
if (batchCv!=null) {
|
||||
// Currently we use the same template for the directory and the files
|
||||
batchCv.readTemplate(new ByteArrayInputStream(templateBytes));
|
||||
}
|
||||
}
|
||||
catch (FileNotFoundException e) {
|
||||
System.out.println("--> This file does not exist!");
|
||||
System.out.println(" "+e.getMessage());
|
||||
}
|
||||
catch (IOException e) {
|
||||
System.out.println("--> Failed to read the template file!");
|
||||
System.out.println(" "+e.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
// Step 6: Read config
|
||||
for (int i=0; i<configFileNames.size(); i++) {
|
||||
String sConfigFileName = (String) configFileNames.get(i);
|
||||
if (sConfigFileName.startsWith("*")) {
|
||||
sConfigFileName = sConfigFileName.substring(1);
|
||||
System.out.println("Reading default configuration "+sConfigFileName);
|
||||
try {
|
||||
converter.getConfig().readDefaultConfig(sConfigFileName);
|
||||
}
|
||||
catch (IllegalArgumentException e) {
|
||||
System.err.println("--> This configuration is unknown!");
|
||||
System.out.println(" "+e.getMessage());
|
||||
}
|
||||
}
|
||||
else {
|
||||
System.out.println("Reading configuration file "+sConfigFileName);
|
||||
try {
|
||||
byte[] configBytes = Misc.inputStreamToByteArray(new FileInputStream(sConfigFileName));
|
||||
converter.getConfig().read(new ByteArrayInputStream(configBytes));
|
||||
if (bBatch) {
|
||||
// Currently we use the same configuration for the directory and the files
|
||||
batchCv.getConfig().read(new ByteArrayInputStream(configBytes));
|
||||
}
|
||||
}
|
||||
catch (IOException e) {
|
||||
System.err.println("--> Failed to read the configuration!");
|
||||
System.out.println(" "+e.getMessage());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Step 7: Set options from command line
|
||||
Enumeration keys = options.keys();
|
||||
while (keys.hasMoreElements()) {
|
||||
String sKey = (String) keys.nextElement();
|
||||
String sValue = (String) options.get(sKey);
|
||||
converter.getConfig().setOption(sKey,sValue);
|
||||
if (batchCv!=null) {
|
||||
batchCv.getConfig().setOption(sKey,sValue);
|
||||
}
|
||||
}
|
||||
|
||||
// Step 8: Perform conversion
|
||||
if (bBatch) {
|
||||
batchCv.convert(source,target,bRecurse, new BatchHandlerImpl());
|
||||
}
|
||||
else {
|
||||
System.out.println("Converting "+source.getPath());
|
||||
ConverterResult dataOut = null;
|
||||
|
||||
try {
|
||||
dataOut = converter.convert(source,target.getName());
|
||||
}
|
||||
catch (FileNotFoundException e) {
|
||||
System.out.println("--> The file "+source.getPath()+" does not exist!");
|
||||
System.out.println(" "+e.getMessage());
|
||||
System.exit(1);
|
||||
}
|
||||
catch (IOException e) {
|
||||
System.out.println("--> Failed to convert the file "+source.getPath()+"!");
|
||||
System.out.println(" "+e.getMessage());
|
||||
System.exit(1);
|
||||
}
|
||||
|
||||
// TODO: Should do some further checking on the feasability of writing
|
||||
// the directory and the files.
|
||||
File targetDir = target.getParentFile();
|
||||
if (targetDir!=null && !targetDir.exists()) { targetDir.mkdirs(); }
|
||||
try {
|
||||
dataOut.write(targetDir);
|
||||
}
|
||||
catch (IOException e) {
|
||||
System.out.println("--> Error writing out file!");
|
||||
System.out.println(" "+e.getMessage());
|
||||
System.exit(1);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
// Step 9: Say goodbye!
|
||||
System.out.println("Done!");
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Display usage.
|
||||
*/
|
||||
private static void showUsage(String msg) {
|
||||
System.out.println();
|
||||
System.out.println("This is Writer2LaTeX, Version " + ConverterFactory.getVersion()
|
||||
+ " (" + ConverterFactory.getDate() + ")");
|
||||
System.out.println();
|
||||
if (msg != null) System.out.println(msg);
|
||||
System.out.println();
|
||||
System.out.println("Usage:");
|
||||
System.out.println(" java -jar <path>/writer2latex.jar <options> <source file/directory> [<target file/directory>]");
|
||||
System.out.println("where the available options are:");
|
||||
System.out.println(" -latex");
|
||||
System.out.println(" -bibtex");
|
||||
System.out.println(" -xhtml");
|
||||
System.out.println(" -xhtml+mathml");
|
||||
System.out.println(" -xhtml+mathml+xsl");
|
||||
System.out.println(" -recurse");
|
||||
System.out.println(" -template[=]<template file>");
|
||||
System.out.println(" -ultraclean");
|
||||
System.out.println(" -clean");
|
||||
System.out.println(" -pdfprint");
|
||||
System.out.println(" -pdfscreen");
|
||||
System.out.println(" -cleanxhtml");
|
||||
System.out.println(" -config[=]<configuration file>");
|
||||
System.out.println(" -<configuration option>[=]<value>");
|
||||
System.out.println("See the documentation for the available configuration options");
|
||||
}
|
||||
|
||||
/**
|
||||
* Parse command-line arguments.
|
||||
*
|
||||
* @param args Array of command line arguments.
|
||||
*
|
||||
* @throws IllegalArgumentException If an argument is invalid.
|
||||
*/
|
||||
private void parseCommandLine(String sArgs[])
|
||||
throws IllegalArgumentException {
|
||||
|
||||
int i = 0;
|
||||
|
||||
while (i<sArgs.length) {
|
||||
String sArg = getArg(i++,sArgs);
|
||||
if (sArg.startsWith("-")) { // found an option
|
||||
if ("-latex".equals(sArg)) { sTargetMIME = MIMETypes.LATEX; }
|
||||
else if ("-bibtex".equals(sArg)) { sTargetMIME = MIMETypes.BIBTEX; }
|
||||
else if ("-xhtml".equals(sArg)) { sTargetMIME = MIMETypes.XHTML; }
|
||||
else if ("-xhtml+mathml".equals(sArg)) { sTargetMIME = MIMETypes.XHTML_MATHML; }
|
||||
else if ("-xhtml+mathml+xsl".equals(sArg)) { sTargetMIME = MIMETypes.XHTML_MATHML_XSL; }
|
||||
else if ("-recurse".equals(sArg)) { bRecurse = true; }
|
||||
else if ("-ultraclean".equals(sArg)) { configFileNames.add("*ultraclean.xml"); }
|
||||
else if ("-clean".equals(sArg)) { configFileNames.add("*clean.xml"); }
|
||||
else if ("-pdfprint".equals(sArg)) { configFileNames.add("*pdfprint.xml"); }
|
||||
else if ("-pdfscreen".equals(sArg)) { configFileNames.add("*pdfscreen.xml"); }
|
||||
else if ("-cleanxhtml".equals(sArg)) { configFileNames.add("*cleanxhtml.xml"); }
|
||||
else { // option with argument
|
||||
int j=sArg.indexOf("=");
|
||||
String sArg2;
|
||||
if (j>-1) { // argument is separated by =
|
||||
sArg2 = sArg.substring(j+1);
|
||||
sArg = sArg.substring(0,j);
|
||||
}
|
||||
else { // argument is separated by space
|
||||
sArg2 = getArg(i++,sArgs);
|
||||
}
|
||||
if ("-config".equals(sArg)) { configFileNames.add(sArg2); }
|
||||
else if ("-template".equals(sArg)) { sTemplateFileName = sArg2; }
|
||||
else { // configuration option
|
||||
options.put(sArg.substring(1),sArg2);
|
||||
}
|
||||
}
|
||||
}
|
||||
else { // not an option, so this must be the source
|
||||
sSource = sArg;
|
||||
// Possibly followed by the target
|
||||
if (i<sArgs.length) {
|
||||
String sArgument = getArg(i++,sArgs);
|
||||
if (sArgument.length()>0) { sTarget = sArgument; }
|
||||
}
|
||||
// Skip any trailing empty arguments and signal an error if there's more
|
||||
while (i<sArgs.length) {
|
||||
String sArgument = getArg(i++,sArgs);
|
||||
if (sArgument.length()>0) {
|
||||
throw new IllegalArgumentException("I didn't expect "+sArgument+"?");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if (sSource==null) {
|
||||
throw new IllegalArgumentException("Please specify a source document/directory!");
|
||||
}
|
||||
// Parsing of command line ended successfully!
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Extract the next argument from the array, while checking to see
|
||||
* that the array size is not exceeded. Throw a friendly error
|
||||
* message in case the arg is missing.
|
||||
*
|
||||
* @param i Argument index.
|
||||
* @param args Array of command line arguments.
|
||||
*
|
||||
* @return The argument with the specified index.
|
||||
*
|
||||
* @throws IllegalArgumentException If an argument is invalid.
|
||||
*/
|
||||
private String getArg(int i, String args[])
|
||||
throws IllegalArgumentException {
|
||||
|
||||
if (i < args.length) {
|
||||
return args[i];
|
||||
}
|
||||
else throw new
|
||||
IllegalArgumentException("I'm sorry, the commandline ended abnormally");
|
||||
}
|
||||
|
||||
|
||||
}
|
94
source/java/writer2latex/BatchHandlerImpl.java
Normal file
94
source/java/writer2latex/BatchHandlerImpl.java
Normal file
|
@ -0,0 +1,94 @@
|
|||
/************************************************************************
|
||||
*
|
||||
* BatchHandlerImpl.java
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License version 2.1, as published by the Free Software Foundation.
|
||||
*
|
||||
* This library 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
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston,
|
||||
* MA 02111-1307 USA
|
||||
*
|
||||
* Copyright: 2002-2008 by Henrik Just
|
||||
*
|
||||
* All Rights Reserved.
|
||||
*
|
||||
* Version 1.0 (2008-10-03)
|
||||
*
|
||||
*/
|
||||
|
||||
package writer2latex;
|
||||
|
||||
import java.io.BufferedReader;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStreamReader;
|
||||
|
||||
import writer2latex.api.BatchHandler;
|
||||
|
||||
/** This class implements a <code>BatchHandler</code> for command line usage
|
||||
*/
|
||||
public class BatchHandlerImpl implements BatchHandler {
|
||||
private int nIndent = 0;
|
||||
|
||||
private void writeMessage(String sMsg) {
|
||||
for (int i=0; i<nIndent; i++) {
|
||||
System.out.print(" ");
|
||||
}
|
||||
System.out.println(sMsg);
|
||||
}
|
||||
|
||||
public void startConversion() {
|
||||
System.out.println("Press Enter to cancel the conversion");
|
||||
}
|
||||
|
||||
public void endConversion() {
|
||||
// No message
|
||||
}
|
||||
|
||||
public void startDirectory(String sName) {
|
||||
writeMessage("Converting directory "+sName);
|
||||
nIndent++;
|
||||
}
|
||||
|
||||
public void endDirectory(String sName, boolean bSuccess) {
|
||||
nIndent--;
|
||||
if (!bSuccess) {
|
||||
writeMessage("--> Conversion of the directory "+sName+" failed!");
|
||||
}
|
||||
}
|
||||
|
||||
public void startFile(String sName) {
|
||||
writeMessage("Converting file "+sName);
|
||||
nIndent++;
|
||||
}
|
||||
|
||||
public void endFile(String sName, boolean bSuccess) {
|
||||
nIndent--;
|
||||
if (!bSuccess) {
|
||||
writeMessage("--> Conversion of the file "+sName+" failed!");
|
||||
}
|
||||
}
|
||||
|
||||
public boolean cancel() {
|
||||
try {
|
||||
if (System.in.available()>0) {
|
||||
BufferedReader in = new BufferedReader(new InputStreamReader(System.in));
|
||||
in.readLine();
|
||||
System.out.print("Do you want to cancel the conversion (y/n)? ");
|
||||
String s = in.readLine();
|
||||
if (s!= null && s.toLowerCase().startsWith("y")) { return true; }
|
||||
}
|
||||
}
|
||||
catch (IOException e) {
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
}
|
96
source/java/writer2latex/api/BatchConverter.java
Normal file
96
source/java/writer2latex/api/BatchConverter.java
Normal file
|
@ -0,0 +1,96 @@
|
|||
/************************************************************************
|
||||
*
|
||||
* BatchConverter.java
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License version 2.1, as published by the Free Software Foundation.
|
||||
*
|
||||
* This library 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
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston,
|
||||
* MA 02111-1307 USA
|
||||
*
|
||||
* Copyright: 2002-2008 by Henrik Just
|
||||
*
|
||||
* All Rights Reserved.
|
||||
*
|
||||
* Version 1.0 (2008-11-23)
|
||||
*
|
||||
*/
|
||||
|
||||
package writer2latex.api;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.InputStream;
|
||||
import java.io.IOException;
|
||||
|
||||
/** This is an interface for a converter, which offers conversion of
|
||||
* all OpenDocument (or OpenOffice.org 1.x) documents in a directory
|
||||
* (and optionally subdirectories), creating index pages in a specific format.
|
||||
* Instances of this interface are created using the
|
||||
* {@link ConverterFactory}
|
||||
*/
|
||||
public interface BatchConverter {
|
||||
|
||||
/** Get the configuration interface for this batch converter
|
||||
*
|
||||
* @return the configuration
|
||||
*/
|
||||
public Config getConfig();
|
||||
|
||||
/** Define a <code>Converter</code> implementation to use for
|
||||
* conversion of the individual documents.
|
||||
* If no converter is given, the <code>convert</code> method cannot
|
||||
* convert documents (but can still create index pages).
|
||||
*
|
||||
* @param converter the <code>Converter</code> to use
|
||||
*/
|
||||
public void setConverter(Converter converter);
|
||||
|
||||
/** Read a template to use as a base for the index pages.
|
||||
* The format of the template depends on the <code>BatchConverter</code>
|
||||
* implementation.
|
||||
*
|
||||
* @param is an <code>InputStream</code> from which to read the template
|
||||
* @throws IOException if some exception occurs while reading the template
|
||||
*/
|
||||
public void readTemplate(InputStream is) throws IOException;
|
||||
|
||||
/** Read a template to use as a base for the index pages.
|
||||
* The format of the template depends on the <code>BatchConverter</code>
|
||||
* implementation.
|
||||
*
|
||||
* @param file the file from which to read the template
|
||||
* @throws IOException if the file does not exist or some exception occurs
|
||||
* while reading the template
|
||||
*/
|
||||
public void readTemplate(File file) throws IOException;
|
||||
|
||||
/** Create an index page with specific entries
|
||||
*
|
||||
* @param sHeading a heading describing the index page
|
||||
* @param entries an array of <code>IndexPageEntry</code> objects (null entries
|
||||
* are allowed, and will be ignored) describing the individual directories
|
||||
* and documents
|
||||
*/
|
||||
public OutputFile createIndexFile(String sHeading, IndexPageEntry[] entries);
|
||||
|
||||
/** Convert a directory using the given <code>Converter</code> (if none is given,
|
||||
* all files will be ignored).
|
||||
* This method fails silently if you haven't set a converter.
|
||||
*
|
||||
* @param source a <code>File</code> representing the directory to convert
|
||||
* @param target a <code>File</code> representing the directory to contain
|
||||
* the converted documents
|
||||
* @param bRecurse determines wether or not to recurse into subdirectories
|
||||
* @param handler a </code>BatchHandler</code>
|
||||
*/
|
||||
public void convert(File source, File target, boolean bRecurse, BatchHandler handler);
|
||||
|
||||
}
|
77
source/java/writer2latex/api/BatchHandler.java
Normal file
77
source/java/writer2latex/api/BatchHandler.java
Normal file
|
@ -0,0 +1,77 @@
|
|||
/************************************************************************
|
||||
*
|
||||
* BatchHandler.java
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License version 2.1, as published by the Free Software Foundation.
|
||||
*
|
||||
* This library 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
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston,
|
||||
* MA 02111-1307 USA
|
||||
*
|
||||
* Copyright: 2002-2008 by Henrik Just
|
||||
*
|
||||
* All Rights Reserved.
|
||||
*
|
||||
* Version 1.0 (2008-11-23)
|
||||
*
|
||||
*/
|
||||
|
||||
package writer2latex.api;
|
||||
|
||||
/** This is a call back interface to handle user interaction during a
|
||||
* batch conversion with a {@link BatchConverter}
|
||||
*/
|
||||
public interface BatchHandler {
|
||||
|
||||
/** Notification that the conversion is started */
|
||||
public void startConversion();
|
||||
|
||||
/** Notification that the conversion has finished */
|
||||
public void endConversion();
|
||||
|
||||
/** Notification that a directory conversion starts
|
||||
*
|
||||
* @param sName the name of the directory to convert
|
||||
*/
|
||||
public void startDirectory(String sName);
|
||||
|
||||
/** Notification that a directory conversion has finished
|
||||
*
|
||||
* @param sName the name of the directory
|
||||
* @param bSuccess true if the conversion was successful (this only means
|
||||
* that the index page was created with success, not that the conversion
|
||||
* of files and subdirectories was successful)
|
||||
*/
|
||||
public void endDirectory(String sName, boolean bSuccess);
|
||||
|
||||
/** Notification that a file conversion starts
|
||||
*
|
||||
* @param sName the name of the file to convert
|
||||
*/
|
||||
public void startFile(String sName);
|
||||
|
||||
/** Notification that a file conversion has finished
|
||||
*
|
||||
* @param sName the name of the file
|
||||
* @param bSuccess true if the conversion of this file was successful
|
||||
*/
|
||||
public void endFile(String sName, boolean bSuccess);
|
||||
|
||||
/** Notification that the conversion may be cancelled. The
|
||||
* {@link BatchConverter} fires this event once per document.
|
||||
* Cancelling the conversion does not delete files that was already
|
||||
* converted
|
||||
*
|
||||
* @return true if the handler wants to cancel the conversion
|
||||
*/
|
||||
public boolean cancel();
|
||||
|
||||
}
|
99
source/java/writer2latex/api/Config.java
Normal file
99
source/java/writer2latex/api/Config.java
Normal file
|
@ -0,0 +1,99 @@
|
|||
/************************************************************************
|
||||
*
|
||||
* Config.java
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License version 2.1, as published by the Free Software Foundation.
|
||||
*
|
||||
* This library 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
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston,
|
||||
* MA 02111-1307 USA
|
||||
*
|
||||
* Copyright: 2002-2008 by Henrik Just
|
||||
*
|
||||
* All Rights Reserved.
|
||||
*
|
||||
* Version 1.0 (2008-11-23)
|
||||
*
|
||||
*/
|
||||
|
||||
package writer2latex.api;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.InputStream;
|
||||
import java.io.IOException;
|
||||
import java.io.OutputStream;
|
||||
import java.lang.IllegalArgumentException;
|
||||
|
||||
/** This is an interface for configuration of a {@link Converter}.
|
||||
* A configuration always supports simple name/value options.
|
||||
* In addition, you can read and write configurations using streams
|
||||
* or abstract file names. The format depends on the {@link Converter}
|
||||
* implementation, cf. the user's manual.
|
||||
*/
|
||||
public interface Config {
|
||||
|
||||
/** Read a default configuration: The available configurations depend on the
|
||||
* {@link Converter} implementation
|
||||
*
|
||||
* @param sName the name of the configuration
|
||||
* @throws IllegalArgumentException if the configuration does not exist
|
||||
*/
|
||||
public void readDefaultConfig(String sName) throws IllegalArgumentException;
|
||||
|
||||
/** Read a configuration (stream based version)
|
||||
*
|
||||
* @param is the <code>InputStream</code> to read from
|
||||
* @throws IOException if an error occurs reading the stream, or the data
|
||||
* is not in the right format
|
||||
*/
|
||||
public void read(InputStream is) throws IOException;
|
||||
|
||||
/** Read a configuration (file based version)
|
||||
*
|
||||
* @param file the <code>File</code> to read from
|
||||
* @throws IOException if the file does not exist, an error occurs reading
|
||||
* the file, or the data is not in the right format
|
||||
*/
|
||||
public void read(File file) throws IOException;
|
||||
|
||||
/** Write the configuration (stream based version)
|
||||
*
|
||||
* @param os the <code>OutputStream</code> to write to
|
||||
* @throws IOException if an error occurs writing to the stream
|
||||
*/
|
||||
public void write(OutputStream os) throws IOException;
|
||||
|
||||
/** Write the configuration (file based version)
|
||||
*
|
||||
* @param file the <code>File</code> to write to
|
||||
* @throws IOException if an error occurs writing to the file
|
||||
*/
|
||||
public void write(File file) throws IOException;
|
||||
|
||||
/** Set a name/value option. Options that are not defined by the
|
||||
* {@link Converter} implementation as well as null values are
|
||||
* silently ignored
|
||||
*
|
||||
* @param sName the name of the option
|
||||
* @param sValue the value of the option
|
||||
*/
|
||||
public void setOption(String sName, String sValue);
|
||||
|
||||
/** Get a named option
|
||||
*
|
||||
* @param sName the name of the option
|
||||
* @return the value of the option, or <code>null</code> if the option does
|
||||
* not exist or the given name is null
|
||||
*/
|
||||
public String getOption(String sName);
|
||||
|
||||
}
|
||||
|
99
source/java/writer2latex/api/Converter.java
Normal file
99
source/java/writer2latex/api/Converter.java
Normal file
|
@ -0,0 +1,99 @@
|
|||
/************************************************************************
|
||||
*
|
||||
* Converter.java
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License version 2.1, as published by the Free Software Foundation.
|
||||
*
|
||||
* This library 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
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston,
|
||||
* MA 02111-1307 USA
|
||||
*
|
||||
* Copyright: 2002-2008 by Henrik Just
|
||||
*
|
||||
* All Rights Reserved.
|
||||
*
|
||||
* Version 1.0 (2008-11-23)
|
||||
*
|
||||
*/
|
||||
|
||||
package writer2latex.api;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.FileNotFoundException;
|
||||
import java.io.InputStream;
|
||||
import java.io.IOException;
|
||||
|
||||
/** This is an interface for a converter, which offers conversion of
|
||||
* OpenDocument (or OpenOffice.org 1.x) documents into a specific format.
|
||||
* Instances of this interface are created using the
|
||||
* <code>ConverterFactory</code>
|
||||
*/
|
||||
public interface Converter {
|
||||
|
||||
/** Get the interface for the configuration of this converter
|
||||
*
|
||||
* @return the configuration
|
||||
*/
|
||||
public Config getConfig();
|
||||
|
||||
/** Define a <code>GraphicConverter</code> implementation to use for
|
||||
* conversion of graphic files. If no converter is specified, graphic
|
||||
* files will not be converted into other formats.
|
||||
*
|
||||
* @param gc the <code>GraphicConverter</code> to use
|
||||
*/
|
||||
public void setGraphicConverter(GraphicConverter gc);
|
||||
|
||||
/** Read a template to use as a base for the converted document.
|
||||
* The format of the template depends on the <code>Converter</code>
|
||||
* implementation.
|
||||
*
|
||||
* @param is an <code>InputStream</code> from which to read the template
|
||||
* @throws IOException if some exception occurs while reading the template
|
||||
*/
|
||||
public void readTemplate(InputStream is) throws IOException;
|
||||
|
||||
/** Read a template to use as a base for the converted document.
|
||||
* The format of the template depends on the <code>Converter</code>
|
||||
* implementation.
|
||||
*
|
||||
* @param file a file from which to read the template
|
||||
* @throws IOException if the file does not exist or some exception occurs
|
||||
* while reading the template
|
||||
*/
|
||||
public void readTemplate(File file) throws IOException;
|
||||
|
||||
/** Convert a document
|
||||
*
|
||||
* @param is an <code>InputStream</code> from which to read the source document.
|
||||
* @param sTargetFileName the file name to use for the converted document
|
||||
* (if the converted document is a compound document consisting consisting
|
||||
* of several files, this name will be used for the master document)
|
||||
* @return a <code>ConverterResult</code> containing the converted document
|
||||
* @throws IOException if some exception occurs while reading the document
|
||||
*/
|
||||
public ConverterResult convert(InputStream is, String sTargetFileName)
|
||||
throws IOException;
|
||||
|
||||
/** Convert a document
|
||||
*
|
||||
* @param source a <code>File</code> from which to read the source document.
|
||||
* @param sTargetFileName the file name to use for the converted document
|
||||
* (if the converted document is a compound document consisting consisting
|
||||
* of several files, this name will be used for the master document)
|
||||
* @return a <code>ConverterResult</code> containing the converted document
|
||||
* @throws FileNotFoundException if the file does not exist
|
||||
* @throws IOException if some exception occurs while reading the document
|
||||
*/
|
||||
public ConverterResult convert(File source, String sTargetFileName)
|
||||
throws FileNotFoundException, IOException;
|
||||
|
||||
}
|
126
source/java/writer2latex/api/ConverterFactory.java
Normal file
126
source/java/writer2latex/api/ConverterFactory.java
Normal file
|
@ -0,0 +1,126 @@
|
|||
/************************************************************************
|
||||
*
|
||||
* ConverterFactory.java
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License version 2.1, as published by the Free Software Foundation.
|
||||
*
|
||||
* This library 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
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston,
|
||||
* MA 02111-1307 USA
|
||||
*
|
||||
* Copyright: 2002-2009 by Henrik Just
|
||||
*
|
||||
* All Rights Reserved.
|
||||
*
|
||||
* Version 1.0 (2009-02-18)
|
||||
*
|
||||
*/
|
||||
|
||||
package writer2latex.api;
|
||||
|
||||
/** This is a factory class which provides static methods to create converters
|
||||
* for documents in OpenDocument (or OpenOffice.org 1.x) format into a specific MIME type
|
||||
*/
|
||||
public class ConverterFactory {
|
||||
|
||||
// Version information
|
||||
private static final String VERSION = "0.9.4";
|
||||
private static final String DATE = "2008-02-19";
|
||||
|
||||
/** Return version information
|
||||
* @return the Writer2LaTeX version in the form
|
||||
* (major version).(minor version).(development version).(patch level)
|
||||
*/
|
||||
public static String getVersion() { return VERSION; }
|
||||
|
||||
/** Return date information
|
||||
* @return the release date for this Writer2LaTeX version
|
||||
*/
|
||||
public static String getDate() { return DATE; }
|
||||
|
||||
/** <p>Create a <code>Converter</code> implementation which supports
|
||||
* conversion into the specified MIME type.</p>
|
||||
* <p>Currently supported MIME types are:</p>
|
||||
* <ul>
|
||||
* <li><code>application/x-latex</code> for LaTeX format</li>
|
||||
* <li><code>application/x-bibtex</code> for BibTeX format</li>
|
||||
* <li><code>text/html</code> for XHTML 1.0 strict format</li>
|
||||
* <li><code>application/xhtml+xml</code> for XHTML+MathML</li>
|
||||
* <li><code>application/xml</code> for XHTML+MathML using stylesheets from w3c's
|
||||
* math working group</li>
|
||||
* </ul>
|
||||
*
|
||||
* @param sMIME the MIME type of the target format
|
||||
* @return the required <code>Converter</code> or null if a converter for
|
||||
* the requested MIME type could not be created
|
||||
*/
|
||||
public static Converter createConverter(String sMIME) {
|
||||
Object converter = null;
|
||||
if (MIMETypes.LATEX.equals(sMIME)) {
|
||||
converter = createInstance("writer2latex.latex.ConverterPalette");
|
||||
}
|
||||
else if (MIMETypes.BIBTEX.equals(sMIME)) {
|
||||
converter = createInstance("writer2latex.bibtex.Converter");
|
||||
}
|
||||
else if (MIMETypes.XHTML.equals(sMIME)) {
|
||||
converter = createInstance("writer2latex.xhtml.Xhtml10Converter");
|
||||
}
|
||||
else if (MIMETypes.XHTML_MATHML.equals(sMIME)) {
|
||||
converter = createInstance("writer2latex.xhtml.XhtmlMathMLConverter");
|
||||
}
|
||||
else if (MIMETypes.XHTML_MATHML_XSL.equals(sMIME)) {
|
||||
converter = createInstance("writer2latex.xhtml.XhtmlMathMLXSLConverter");
|
||||
}
|
||||
return converter instanceof Converter ? (Converter) converter : null;
|
||||
}
|
||||
|
||||
/** <p>Create a <code>BatchConverter</code> implementation which supports
|
||||
* conversion into the specified MIME type</p>
|
||||
* <p>The only currently supported MIME type is <code>text/html</code>
|
||||
* (XHTML 1.0 strict)</p>
|
||||
*
|
||||
* @param sMIME the MIME type of the target format
|
||||
* @return the required <code>BatchConverter</code> or null if a converter
|
||||
* for the requested MIME type could not be created
|
||||
*/
|
||||
public static BatchConverter createBatchConverter(String sMIME) {
|
||||
Object converter = null;
|
||||
if (MIMETypes.XHTML.equals(sMIME)) {
|
||||
converter = createInstance("writer2latex.xhtml.BatchConverterImpl");
|
||||
}
|
||||
return converter instanceof BatchConverter ? (BatchConverter) converter : null;
|
||||
}
|
||||
|
||||
/** Create a <code>StarMathConverter</code> implementation
|
||||
*
|
||||
* @return the converter
|
||||
*/
|
||||
public static StarMathConverter createStarMathConverter() {
|
||||
Object converter = createInstance("writer2latex.latex.StarMathConverter");
|
||||
return converter instanceof StarMathConverter ? (StarMathConverter) converter : null;
|
||||
}
|
||||
|
||||
private static Object createInstance(String sClassName) {
|
||||
try {
|
||||
return Class.forName(sClassName).newInstance();
|
||||
}
|
||||
catch (java.lang.ClassNotFoundException e) {
|
||||
return null;
|
||||
}
|
||||
catch (java.lang.InstantiationException e) {
|
||||
return null;
|
||||
}
|
||||
catch (java.lang.IllegalAccessException e) {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
59
source/java/writer2latex/api/ConverterResult.java
Normal file
59
source/java/writer2latex/api/ConverterResult.java
Normal file
|
@ -0,0 +1,59 @@
|
|||
/************************************************************************
|
||||
*
|
||||
* ConverterResult.java
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License version 2.1, as published by the Free Software Foundation.
|
||||
*
|
||||
* This library 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
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston,
|
||||
* MA 02111-1307 USA
|
||||
*
|
||||
* Copyright: 2002-2008 by Henrik Just
|
||||
*
|
||||
* All Rights Reserved.
|
||||
*
|
||||
* Version 1.0 (2008-11-24)
|
||||
*
|
||||
*/
|
||||
|
||||
package writer2latex.api;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.util.Iterator;
|
||||
|
||||
/** A <code>ConverterResult</code> represent a document, which is the result
|
||||
* of a conversion performed by a <code>Converter</code>implementation.
|
||||
*/
|
||||
public interface ConverterResult {
|
||||
|
||||
/** Get the master document
|
||||
* @return <code>OutputFile</code> the master document
|
||||
*/
|
||||
public OutputFile getMasterDocument();
|
||||
|
||||
/** Gets an <code>Iterator</code> to access all files in the
|
||||
* <code>ConverterResult</code>. This <em>includes</em> the master document.
|
||||
* @return an <code>Iterator</code> of all files
|
||||
*/
|
||||
public Iterator iterator();
|
||||
|
||||
/** Write all files of the <code>ConverterResult</code> to a directory.
|
||||
* Subdirectories are created as required by the individual
|
||||
* <code>OutputFile</code>s.
|
||||
* @param dir the directory to write to (this directory must exist).
|
||||
If the parameter is null, the default directory is used
|
||||
* @throws IOException if the directory does not exist or one or more files
|
||||
* could not be written
|
||||
*/
|
||||
public void write(File dir) throws IOException;
|
||||
|
||||
}
|
58
source/java/writer2latex/api/GraphicConverter.java
Normal file
58
source/java/writer2latex/api/GraphicConverter.java
Normal file
|
@ -0,0 +1,58 @@
|
|||
/************************************************************************
|
||||
*
|
||||
* GraphicConverter.java
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License version 2.1, as published by the Free Software Foundation.
|
||||
*
|
||||
* This library 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
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston,
|
||||
* MA 02111-1307 USA
|
||||
*
|
||||
* Copyright: 2002-2008 by Henrik Just
|
||||
*
|
||||
* All Rights Reserved.
|
||||
*
|
||||
* Version 1.0 (2008-11-23)
|
||||
*
|
||||
*/
|
||||
|
||||
package writer2latex.api;
|
||||
|
||||
/** A simple interface for a graphic converter which converts between various
|
||||
* graphics formats
|
||||
*/
|
||||
public interface GraphicConverter {
|
||||
|
||||
/** Check whether a certain conversion is supported by the converter
|
||||
*
|
||||
* @param sSourceMime a string containing the source Mime type
|
||||
* @param sTargetMime a string containing the target Mime type
|
||||
* @param bCrop true if the target graphic should be cropped
|
||||
* @param bResize true if the target graphic should be resized
|
||||
* (the last two parameters are for future use)
|
||||
* @return true if the conversion is supported
|
||||
*/
|
||||
public boolean supportsConversion(String sSourceMime, String sTargetMime, boolean bCrop, boolean bResize);
|
||||
|
||||
/** Convert a graphics file from one format to another
|
||||
*
|
||||
* @param source a byte array containing the source graphic
|
||||
* @param sSourceMime a string containing the Mime type of the source
|
||||
* @param sTargetMime a string containing the desired Mime type of the target
|
||||
* @return a byte array containing the converted graphic. Returns null
|
||||
* if the conversion failed.
|
||||
*/
|
||||
public byte[] convert(byte[] source, String sSourceMime, String sTargetMime);
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
141
source/java/writer2latex/api/IndexPageEntry.java
Normal file
141
source/java/writer2latex/api/IndexPageEntry.java
Normal file
|
@ -0,0 +1,141 @@
|
|||
/************************************************************************
|
||||
*
|
||||
* IndexPageEntry.java
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License version 2.1, as published by the Free Software Foundation.
|
||||
*
|
||||
* This library 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
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston,
|
||||
* MA 02111-1307 USA
|
||||
*
|
||||
* Copyright: 2002-2009 by Henrik Just
|
||||
*
|
||||
* All Rights Reserved.
|
||||
*
|
||||
* Version 1.0 (2009-02-08)
|
||||
*
|
||||
*/
|
||||
|
||||
package writer2latex.api;
|
||||
|
||||
/** This class represents a single entry on an index page created by a batch converter
|
||||
*/
|
||||
public class IndexPageEntry {
|
||||
|
||||
private String sFile;
|
||||
private String sDisplayName;
|
||||
private String sDescription = null;
|
||||
private String sPdfFile = null;
|
||||
private String sOriginalFile = null;
|
||||
private boolean bIsDirectory;
|
||||
|
||||
/** Construct a new <code>IndexPageEntry</code> based on a file name.
|
||||
* The file name is also used as display name.
|
||||
*
|
||||
* @param sFile the file name for this entry
|
||||
* @param bIsDirectory true if this is a directory, false if it is a file
|
||||
*/
|
||||
public IndexPageEntry(String sFile, boolean bIsDirectory) {
|
||||
this.sFile = sFile;
|
||||
this.sDisplayName = sFile;
|
||||
this.bIsDirectory = bIsDirectory;
|
||||
}
|
||||
|
||||
/** Set the file name
|
||||
*
|
||||
* @param sFile the file name
|
||||
*/
|
||||
public void setFile(String sFile) {
|
||||
this.sFile = sFile;
|
||||
}
|
||||
|
||||
/** Set the display name for this entry. The display name is the
|
||||
* name presented on the index page.
|
||||
*
|
||||
* @param sDisplayName the display name
|
||||
*/
|
||||
public void setDisplayName(String sDisplayName) {
|
||||
this.sDisplayName = sDisplayName;
|
||||
}
|
||||
|
||||
/** Set the description of this file (additional information about the file)
|
||||
*
|
||||
* @param sDescription the description
|
||||
*/
|
||||
public void setDescription(String sDescription) {
|
||||
this.sDescription = sDescription;
|
||||
}
|
||||
|
||||
/** Set the file name for a pdf file associated with this file
|
||||
*
|
||||
* @param sPdfFile the file name
|
||||
*/
|
||||
public void setPdfFile(String sPdfFile) {
|
||||
this.sPdfFile = sPdfFile;
|
||||
}
|
||||
|
||||
/** Set the file name for the original file
|
||||
*
|
||||
* @param sOriginalFile the origianl file name
|
||||
*/
|
||||
public void setOriginalFile(String sOriginalFile) {
|
||||
this.sOriginalFile = sOriginalFile;
|
||||
}
|
||||
|
||||
/** Get the file name
|
||||
*
|
||||
* @return the file name
|
||||
*/
|
||||
public String getFile() {
|
||||
return sFile;
|
||||
}
|
||||
|
||||
/** Get the display name
|
||||
*
|
||||
* @return the display name
|
||||
*/
|
||||
public String getDisplayName() {
|
||||
return sDisplayName;
|
||||
}
|
||||
|
||||
/** Get the description
|
||||
*
|
||||
* @return the description, or null if there is no description
|
||||
*/
|
||||
public String getDescription() {
|
||||
return sDescription;
|
||||
}
|
||||
|
||||
/** Get the pdf file name
|
||||
*
|
||||
* @return the file name or null if there is none
|
||||
*/
|
||||
public String getPdfFile() {
|
||||
return sPdfFile;
|
||||
}
|
||||
|
||||
/** Get the original file name
|
||||
*
|
||||
* @return the file name or null if there is none
|
||||
*/
|
||||
public String getOriginalFile() {
|
||||
return sOriginalFile;
|
||||
}
|
||||
|
||||
/** Check whether this is a file or a directory
|
||||
*
|
||||
* @return true for a directory, false for a file
|
||||
*/
|
||||
public boolean isDirectory() {
|
||||
return bIsDirectory;
|
||||
}
|
||||
|
||||
}
|
55
source/java/writer2latex/api/MIMETypes.java
Normal file
55
source/java/writer2latex/api/MIMETypes.java
Normal file
|
@ -0,0 +1,55 @@
|
|||
/************************************************************************
|
||||
*
|
||||
* MIMETypes.java
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License version 2.1, as published by the Free Software Foundation.
|
||||
*
|
||||
* This library 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
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston,
|
||||
* MA 02111-1307 USA
|
||||
*
|
||||
* Copyright: 2002-2008 by Henrik Just
|
||||
*
|
||||
* All Rights Reserved.
|
||||
*
|
||||
* Version 1.0 (2008-11-23)
|
||||
*
|
||||
*/
|
||||
|
||||
package writer2latex.api;
|
||||
|
||||
/* Some helpers to handle the MIME types used by OOo
|
||||
*/
|
||||
|
||||
public class MIMETypes {
|
||||
// Various graphics formats, see
|
||||
// http://api.openoffice.org/docs/common/ref/com/sun/star/graphic/MediaProperties.html#MimeType
|
||||
public static final String PNG="image/png";
|
||||
public static final String JPEG="image/jpeg";
|
||||
public static final String GIF="image/gif";
|
||||
public static final String TIFF="image/tiff";
|
||||
public static final String BMP="image/bmp";
|
||||
public static final String WMF="image/x-wmf";
|
||||
public static final String EPS="image/x-eps";
|
||||
// MIME type for SVM has changed
|
||||
//public static final String SVM="image/x-svm";
|
||||
public static final String SVM="application/x-openoffice-gdimetafile;windows_formatname=\"GDIMetaFile\"";
|
||||
public static final String PDF="application/pdf";
|
||||
|
||||
// Desitination formats
|
||||
public static final String XHTML="text/html";
|
||||
public static final String XHTML_MATHML="application/xhtml+xml";
|
||||
public static final String XHTML_MATHML_XSL="application/xml";
|
||||
public static final String LATEX="application/x-latex";
|
||||
public static final String BIBTEX="application/x-bibtex";
|
||||
public static final String TEXT="text";
|
||||
|
||||
}
|
53
source/java/writer2latex/api/OutputFile.java
Normal file
53
source/java/writer2latex/api/OutputFile.java
Normal file
|
@ -0,0 +1,53 @@
|
|||
/************************************************************************
|
||||
*
|
||||
* OutputFile.java
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License version 2.1, as published by the Free Software Foundation.
|
||||
*
|
||||
* This library 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
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston,
|
||||
* MA 02111-1307 USA
|
||||
*
|
||||
* Copyright: 2002-2008 by Henrik Just
|
||||
*
|
||||
* All Rights Reserved.
|
||||
*
|
||||
* Version 1.0 (2008-11-23)
|
||||
*
|
||||
*/
|
||||
|
||||
package writer2latex.api;
|
||||
|
||||
import java.io.OutputStream;
|
||||
import java.io.IOException;
|
||||
|
||||
/** An <code>OutputFile</code> represent a single file in a
|
||||
* {@link ConverterResult}, which is output from a {@link Converter}
|
||||
* implementation.
|
||||
*/
|
||||
public interface OutputFile {
|
||||
|
||||
/** Writes the <code>OutputFile</code> to an <code>OutputStream</code>.
|
||||
*
|
||||
* @param os <code>OutputStream</code> to which the content should be written
|
||||
* @throws IOException if any I/O error occurs
|
||||
*/
|
||||
public void write(OutputStream os) throws IOException;
|
||||
|
||||
/** Returns the file name of the <code>OutputFile</code>. This includes
|
||||
* the file extension and may also include a relative path, always using
|
||||
* / as separator.
|
||||
*
|
||||
* @return the file name of this <code>OutputFile</code>
|
||||
*/
|
||||
public String getFileName();
|
||||
|
||||
}
|
13
source/java/writer2latex/api/Package.html
Normal file
13
source/java/writer2latex/api/Package.html
Normal file
|
@ -0,0 +1,13 @@
|
|||
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
|
||||
|
||||
<html>
|
||||
<head>
|
||||
<title>The package writer2latex.api</title>
|
||||
</head>
|
||||
|
||||
<body>
|
||||
<p>This package contains the api for using Writer2LaTeX.</p>
|
||||
<p>The api consitst of a factory class and a number of interfaces, and is
|
||||
used by the command line application as well as by the filters.
|
||||
</body>
|
||||
</html>
|
61
source/java/writer2latex/api/StarMathConverter.java
Normal file
61
source/java/writer2latex/api/StarMathConverter.java
Normal file
|
@ -0,0 +1,61 @@
|
|||
/************************************************************************
|
||||
*
|
||||
* StarMathConverter.java
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License version 2.1, as published by the Free Software Foundation.
|
||||
*
|
||||
* This library 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
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston,
|
||||
* MA 02111-1307 USA
|
||||
*
|
||||
* Copyright: 2002-2008 by Henrik Just
|
||||
*
|
||||
* All Rights Reserved.
|
||||
*
|
||||
* Version 1.0 (2008-11-23)
|
||||
*
|
||||
*/
|
||||
|
||||
package writer2latex.api;
|
||||
|
||||
//import java.io.InputStream;
|
||||
//import java.io.IOException;
|
||||
|
||||
/** This is an interface for a converter, which offers conversion of
|
||||
* a StarMath formula into LaTeX
|
||||
* Instances of this interface are created using the
|
||||
* {@link ConverterFactory}
|
||||
*/
|
||||
public interface StarMathConverter {
|
||||
|
||||
/** Get the configuration used when converting.
|
||||
*
|
||||
* @return the configuration used by this converter
|
||||
*/
|
||||
public Config getConfig();
|
||||
|
||||
/** Convert a StarMath formula
|
||||
*
|
||||
* @param sStarMathFormula is a string containing the StarMath formula
|
||||
* @return a string containing the converted LaTeX formula
|
||||
*/
|
||||
public String convert(String sStarMathFormula);
|
||||
|
||||
/** Create a suitable LaTeX preamble to process the formulas converted so far
|
||||
*
|
||||
* @return a string containg the entire LaTeX preamble
|
||||
*/
|
||||
public String getPreamble();
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
182
source/java/writer2latex/base/BatchConverterBase.java
Normal file
182
source/java/writer2latex/base/BatchConverterBase.java
Normal file
|
@ -0,0 +1,182 @@
|
|||
/************************************************************************
|
||||
*
|
||||
* BatchConverterBase.java
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License version 2.1, as published by the Free Software Foundation.
|
||||
*
|
||||
* This library 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
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston,
|
||||
* MA 02111-1307 USA
|
||||
*
|
||||
* Copyright: 2002-2008 by Henrik Just
|
||||
*
|
||||
* All Rights Reserved.
|
||||
*
|
||||
* Version 1.0 (2008-10-15)
|
||||
*
|
||||
*/
|
||||
|
||||
package writer2latex.base;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.FileOutputStream;
|
||||
import java.io.FileNotFoundException;
|
||||
import java.io.IOException;
|
||||
|
||||
import writer2latex.api.BatchConverter;
|
||||
import writer2latex.api.BatchHandler;
|
||||
import writer2latex.api.Converter;
|
||||
import writer2latex.api.ConverterResult;
|
||||
import writer2latex.api.IndexPageEntry;
|
||||
import writer2latex.api.OutputFile;
|
||||
|
||||
import writer2latex.util.Misc;
|
||||
|
||||
/**
|
||||
* Abstract base implementation of <code>writer2latex.api.BatchConverter</code>.
|
||||
* The base implementation handles the traversal of directories and files, and
|
||||
* leaves the handling of indexpages to the subclass.
|
||||
*/
|
||||
public abstract class BatchConverterBase implements BatchConverter {
|
||||
|
||||
private Converter converter;
|
||||
|
||||
public BatchConverterBase() {
|
||||
converter = null;
|
||||
}
|
||||
|
||||
// Partial implementation of the interface
|
||||
|
||||
public void setConverter(Converter converter) {
|
||||
this.converter = converter;
|
||||
}
|
||||
|
||||
public void convert(File source, File target, boolean bRecurse, BatchHandler handler) {
|
||||
handler.startConversion();
|
||||
convertDirectory(source, target, bRecurse, source.getName(), handler);
|
||||
handler.endConversion();
|
||||
}
|
||||
|
||||
protected abstract String getIndexFileName();
|
||||
|
||||
// Convert files and directories in the directory indir
|
||||
// (return false if conversion has been cancelled by the BatchHandler)
|
||||
private boolean convertDirectory(File indir, File outdir, boolean bRecurse, String sHeading, BatchHandler handler) {
|
||||
handler.startDirectory(indir.getPath());
|
||||
|
||||
// Step 1: Get the directory
|
||||
File[] contents = indir.listFiles();
|
||||
int nLen = contents.length;
|
||||
IndexPageEntry[] entries = new IndexPageEntry[nLen];
|
||||
|
||||
// Step 2: Traverse subdirectories, if allowed
|
||||
if (bRecurse) {
|
||||
String sUplink = getConfig().getOption("uplink");
|
||||
for (int i=0; i<nLen; i++) {
|
||||
if (contents[i].isDirectory()) {
|
||||
getConfig().setOption("uplink","../"+getIndexFileName());
|
||||
File newOutdir = new File(outdir,contents[i].getName());
|
||||
String sNewHeading = sHeading + " - " + contents[i].getName();
|
||||
boolean bResult = convertDirectory(contents[i],newOutdir,bRecurse,sNewHeading,handler);
|
||||
getConfig().setOption("uplink", sUplink);
|
||||
if (!bResult) { return false; }
|
||||
// Create entry for this subdirectory
|
||||
IndexPageEntry entry = new IndexPageEntry(Misc.makeHref(contents[i].getName()+"/"+getIndexFileName()),true);
|
||||
entry.setDisplayName(contents[i].getName());
|
||||
entries[i]=entry;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Step 3: Traverse documents, if we have a converter
|
||||
if (converter!=null) {
|
||||
String sUplink = getConfig().getOption("uplink");
|
||||
for (int i=0; i<nLen; i++) {
|
||||
if (contents[i].isFile()) {
|
||||
getConfig().setOption("uplink",getIndexFileName());
|
||||
String sLinkFile = convertFile(contents[i],outdir,handler);
|
||||
getConfig().setOption("uplink", sUplink);
|
||||
if (sLinkFile!=null) {
|
||||
// Create entry for this file
|
||||
IndexPageEntry entry = new IndexPageEntry(Misc.makeHref(sLinkFile),false);
|
||||
entry.setDisplayName(Misc.removeExtension(sLinkFile));
|
||||
entries[i]=entry;
|
||||
if (handler.cancel()) { return false; }
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Step 4: Create and write out the index file
|
||||
OutputFile indexFile = createIndexFile(sHeading, entries);
|
||||
|
||||
if (!outdir.exists()) { outdir.mkdirs(); }
|
||||
|
||||
boolean bSuccess = true;
|
||||
File outfile = new File(outdir,indexFile.getFileName());
|
||||
try {
|
||||
FileOutputStream fos = new FileOutputStream(outfile);
|
||||
indexFile.write(fos);
|
||||
fos.flush();
|
||||
fos.close();
|
||||
} catch (Exception writeExcept) {
|
||||
bSuccess = false;
|
||||
}
|
||||
|
||||
handler.endDirectory(indir.getPath(), bSuccess);
|
||||
|
||||
return !handler.cancel();
|
||||
}
|
||||
|
||||
// Convert a single file, returning the name of the master file
|
||||
// Returns null if conversion fails
|
||||
private String convertFile(File infile, File outdir, BatchHandler handler) {
|
||||
handler.startFile(infile.getPath());
|
||||
|
||||
// Currently we discriminate based on file extension
|
||||
if (!(infile.getName().endsWith(".odt") || infile.getName().endsWith(".ods") || infile.getName().endsWith(".odp"))) {
|
||||
handler.endFile(infile.getPath(),false);
|
||||
return null;
|
||||
}
|
||||
|
||||
// Do conversion
|
||||
ConverterResult dataOut = null;
|
||||
try {
|
||||
// The target file name is always the same as the source
|
||||
dataOut = converter.convert(infile,Misc.removeExtension(infile.getName()));
|
||||
}
|
||||
catch (FileNotFoundException e) {
|
||||
handler.endFile(infile.getPath(),false);
|
||||
return null;
|
||||
}
|
||||
catch (IOException e) {
|
||||
handler.endFile(infile.getPath(),false);
|
||||
return null;
|
||||
}
|
||||
|
||||
// Write out files
|
||||
if (!outdir.exists()) { outdir.mkdirs(); }
|
||||
|
||||
try {
|
||||
dataOut.write(outdir);
|
||||
}
|
||||
catch (IOException e) {
|
||||
handler.endFile(infile.getPath(),false);
|
||||
return null;
|
||||
}
|
||||
|
||||
handler.endFile(infile.getPath(),true);
|
||||
|
||||
return dataOut.getMasterDocument().getFileName();
|
||||
}
|
||||
|
||||
|
||||
}
|
44
source/java/writer2latex/base/BooleanOption.java
Normal file
44
source/java/writer2latex/base/BooleanOption.java
Normal file
|
@ -0,0 +1,44 @@
|
|||
/************************************************************************
|
||||
*
|
||||
* BooleanOption.java
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License version 2.1, as published by the Free Software Foundation.
|
||||
*
|
||||
* This library 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
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston,
|
||||
* MA 02111-1307 USA
|
||||
*
|
||||
* Copyright: 2002-2008 by Henrik Just
|
||||
*
|
||||
* All Rights Reserved.
|
||||
*
|
||||
* Version 1.0 (2008-09-08)
|
||||
*
|
||||
*/
|
||||
|
||||
package writer2latex.base;
|
||||
|
||||
// A BooleanOption interprets the values as booleans
|
||||
public class BooleanOption extends Option {
|
||||
private boolean bValue;
|
||||
|
||||
public boolean getValue() { return bValue; }
|
||||
|
||||
public void setString(String sValue) {
|
||||
super.setString(sValue);
|
||||
bValue = "true".equals(sValue);
|
||||
}
|
||||
|
||||
public BooleanOption(String sName, String sDefaultValue) {
|
||||
super(sName,sDefaultValue);
|
||||
}
|
||||
}
|
||||
|
170
source/java/writer2latex/base/ConfigBase.java
Normal file
170
source/java/writer2latex/base/ConfigBase.java
Normal file
|
@ -0,0 +1,170 @@
|
|||
/************************************************************************
|
||||
*
|
||||
* ConfigBase.java
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License version 2.1, as published by the Free Software Foundation.
|
||||
*
|
||||
* This library 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
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston,
|
||||
* MA 02111-1307 USA
|
||||
*
|
||||
* Copyright: 2002-2008 by Henrik Just
|
||||
*
|
||||
* All Rights Reserved.
|
||||
*
|
||||
* Version 1.0 (2008-11-22)
|
||||
*
|
||||
*/
|
||||
|
||||
package writer2latex.base;
|
||||
|
||||
/** Base implementation of writer2latex.api.Config
|
||||
*/
|
||||
|
||||
import java.io.File;
|
||||
import java.io.FileInputStream;
|
||||
import java.io.FileOutputStream;
|
||||
import java.io.InputStream;
|
||||
import java.io.IOException;
|
||||
import java.io.OutputStream;
|
||||
import javax.xml.parsers.DocumentBuilder;
|
||||
import javax.xml.parsers.DocumentBuilderFactory;
|
||||
import org.w3c.dom.Document;
|
||||
import org.w3c.dom.Node;
|
||||
import org.w3c.dom.Element;
|
||||
import org.w3c.dom.DOMImplementation;
|
||||
|
||||
import writer2latex.xmerge.NewDOMDocument;
|
||||
|
||||
public abstract class ConfigBase implements writer2latex.api.Config {
|
||||
|
||||
protected abstract int getOptionCount();
|
||||
protected abstract String getDefaultConfigPath();
|
||||
|
||||
protected Option[] options;
|
||||
|
||||
public ConfigBase() {
|
||||
options = new Option[getOptionCount()];
|
||||
}
|
||||
|
||||
public void setOption(String sName,String sValue) {
|
||||
if (sName!=null && sValue!=null) {
|
||||
for (int j=0; j<getOptionCount(); j++) {
|
||||
if (sName.equals(options[j].getName())) {
|
||||
options[j].setString(sValue);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public String getOption(String sName) {
|
||||
if (sName!=null) {
|
||||
for (int j=0; j<getOptionCount(); j++) {
|
||||
if (sName.equals(options[j].getName())) {
|
||||
return options[j].getString();
|
||||
}
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
public void readDefaultConfig(String sName) throws IllegalArgumentException {
|
||||
InputStream is = this.getClass().getResourceAsStream(getDefaultConfigPath()+sName);
|
||||
if (is==null) {
|
||||
throw new IllegalArgumentException("The internal configuration '"+sName+ "' does not exist");
|
||||
}
|
||||
try {
|
||||
read(is);
|
||||
}
|
||||
catch (IOException e) {
|
||||
// This would imply a bug in the configuration file!
|
||||
throw new IllegalArgumentException("The internal configuration '"+sName+ "' is invalid");
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/** <p>Read configuration from a specified input stream</p>
|
||||
* @param is the input stream to read the configuration from
|
||||
*/
|
||||
public void read(InputStream is) throws IOException {
|
||||
NewDOMDocument doc = new NewDOMDocument("config",".xml");
|
||||
doc.read(is); // may throw an IOException
|
||||
Document dom = doc.getContentDOM();
|
||||
if (dom==null) {
|
||||
throw new IOException("Failed to parse configuration");
|
||||
}
|
||||
|
||||
Node root = dom.getDocumentElement();
|
||||
Node child = root.getFirstChild();
|
||||
while (child!=null) {
|
||||
if (child.getNodeType()==Node.ELEMENT_NODE) {
|
||||
Element elm = (Element)child;
|
||||
if (elm.getTagName().equals("option")) {
|
||||
String sName = elm.getAttribute("name");
|
||||
String sValue = elm.getAttribute("value");
|
||||
if (sName!="") { setOption(sName,sValue); }
|
||||
}
|
||||
else {
|
||||
readInner(elm);
|
||||
}
|
||||
}
|
||||
child = child.getNextSibling();
|
||||
}
|
||||
}
|
||||
|
||||
public void read(File file) throws IOException {
|
||||
read(new FileInputStream(file));
|
||||
}
|
||||
|
||||
/** Read configuration information from an xml element.
|
||||
* The subclass must define this to read richer configuration data
|
||||
*/
|
||||
protected abstract void readInner(Element elm);
|
||||
|
||||
public void write(OutputStream os) throws IOException {
|
||||
NewDOMDocument doc = new NewDOMDocument("config",".xml");
|
||||
Document dom = null;
|
||||
try {
|
||||
DocumentBuilderFactory builderFactory = DocumentBuilderFactory.newInstance();
|
||||
DocumentBuilder builder = builderFactory.newDocumentBuilder();
|
||||
DOMImplementation domImpl = builder.getDOMImplementation();
|
||||
dom = domImpl.createDocument("","config",null);
|
||||
}
|
||||
catch (Throwable t) {
|
||||
t.printStackTrace();
|
||||
}
|
||||
Element rootElement = dom.getDocumentElement();
|
||||
|
||||
for (int i=0; i<getOptionCount(); i++) {
|
||||
Element optionNode = dom.createElement("option");
|
||||
optionNode.setAttribute("name",options[i].getName());
|
||||
optionNode.setAttribute("value",options[i].getString());
|
||||
rootElement.appendChild(optionNode);
|
||||
}
|
||||
|
||||
writeInner(dom);
|
||||
|
||||
doc.setContentDOM(dom);
|
||||
doc.write(os); // may throw an IOException
|
||||
}
|
||||
|
||||
public void write(File file) throws IOException {
|
||||
write(new FileOutputStream(file));
|
||||
}
|
||||
|
||||
/** Write configuration information to an xml document.
|
||||
* The subclass must define this to write richer configuration data
|
||||
*/
|
||||
protected abstract void writeInner(Document dom);
|
||||
|
||||
}
|
||||
|
117
source/java/writer2latex/base/ConverterBase.java
Normal file
117
source/java/writer2latex/base/ConverterBase.java
Normal file
|
@ -0,0 +1,117 @@
|
|||
/************************************************************************
|
||||
*
|
||||
* ConverterBase.java
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License version 2.1, as published by the Free Software Foundation.
|
||||
*
|
||||
* This library 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
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston,
|
||||
* MA 02111-1307 USA
|
||||
*
|
||||
* Copyright: 2002-2008 by Henrik Just
|
||||
*
|
||||
* All Rights Reserved.
|
||||
*
|
||||
* Version 1.0 (2008-11-23)
|
||||
*
|
||||
*/
|
||||
|
||||
package writer2latex.base;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.FileInputStream;
|
||||
import java.io.FileNotFoundException;
|
||||
import java.io.InputStream;
|
||||
import java.io.IOException;
|
||||
|
||||
import writer2latex.api.GraphicConverter;
|
||||
import writer2latex.api.Converter;
|
||||
import writer2latex.api.ConverterResult;
|
||||
import writer2latex.api.OutputFile;
|
||||
import writer2latex.office.ImageLoader;
|
||||
import writer2latex.office.MetaData;
|
||||
import writer2latex.office.OfficeReader;
|
||||
import writer2latex.xmerge.EmbeddedObject;
|
||||
import writer2latex.xmerge.ConvertData;
|
||||
import writer2latex.xmerge.OfficeDocument;
|
||||
|
||||
/**<p>Abstract base implementation of <code>writer2latex.api.Converter</code></p>
|
||||
*/
|
||||
public abstract class ConverterBase implements Converter {
|
||||
|
||||
// Helper
|
||||
protected GraphicConverter graphicConverter;
|
||||
|
||||
// The source document
|
||||
protected OfficeDocument odDoc;
|
||||
protected OfficeReader ofr;
|
||||
protected MetaData metaData;
|
||||
protected ImageLoader imageLoader;
|
||||
|
||||
// The output file(s)
|
||||
protected String sTargetFileName;
|
||||
protected ConvertData convertData;
|
||||
|
||||
// Constructor
|
||||
public ConverterBase() {
|
||||
graphicConverter = null;
|
||||
convertData = new ConvertData();
|
||||
}
|
||||
|
||||
// Implement the interface
|
||||
public void setGraphicConverter(GraphicConverter graphicConverter) {
|
||||
this.graphicConverter = graphicConverter;
|
||||
}
|
||||
|
||||
// Provide a do noting fallback method
|
||||
public void readTemplate(InputStream is) throws IOException { }
|
||||
|
||||
// Provide a do noting fallback method
|
||||
public void readTemplate(File file) throws IOException { }
|
||||
|
||||
public ConverterResult convert(File source, String sTargetFileName) throws FileNotFoundException,IOException {
|
||||
return convert(new FileInputStream(source), sTargetFileName);
|
||||
}
|
||||
|
||||
public ConverterResult convert(InputStream is, String sTargetFileName) throws IOException {
|
||||
// Read document
|
||||
odDoc = new OfficeDocument("InFile");
|
||||
odDoc.read(is);
|
||||
ofr = new OfficeReader(odDoc,false);
|
||||
metaData = new MetaData(odDoc);
|
||||
imageLoader = new ImageLoader(odDoc,sTargetFileName,true);
|
||||
imageLoader.setGraphicConverter(graphicConverter);
|
||||
|
||||
// Prepare output
|
||||
this.sTargetFileName = sTargetFileName;
|
||||
convertData.reset();
|
||||
|
||||
convertInner();
|
||||
|
||||
return convertData;
|
||||
}
|
||||
|
||||
// The subclass must provide the implementation
|
||||
public abstract void convertInner() throws IOException;
|
||||
|
||||
public MetaData getMetaData() { return metaData; }
|
||||
|
||||
public ImageLoader getImageLoader() { return imageLoader; }
|
||||
|
||||
public void addDocument(OutputFile doc) { convertData.addDocument(doc); }
|
||||
|
||||
public EmbeddedObject getEmbeddedObject(String sHref) {
|
||||
return odDoc.getEmbeddedObject(sHref);
|
||||
}
|
||||
|
||||
|
||||
|
||||
}
|
40
source/java/writer2latex/base/IntegerOption.java
Normal file
40
source/java/writer2latex/base/IntegerOption.java
Normal file
|
@ -0,0 +1,40 @@
|
|||
/************************************************************************
|
||||
*
|
||||
* IntegerOption.java
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License version 2.1, as published by the Free Software Foundation.
|
||||
*
|
||||
* This library 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
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston,
|
||||
* MA 02111-1307 USA
|
||||
*
|
||||
* Copyright: 2002-2008 by Henrik Just
|
||||
*
|
||||
* All Rights Reserved.
|
||||
*
|
||||
* Version 1.0 (2008-09-08)
|
||||
*
|
||||
*/
|
||||
|
||||
package writer2latex.base;
|
||||
|
||||
|
||||
// An IntegerOption must always be subclassed (must override setString)
|
||||
public abstract class IntegerOption extends Option {
|
||||
protected int nValue;
|
||||
|
||||
public int getValue() { return nValue; }
|
||||
|
||||
public IntegerOption(String sName, String sDefaultValue) {
|
||||
super(sName,sDefaultValue);
|
||||
}
|
||||
}
|
||||
|
45
source/java/writer2latex/base/Option.java
Normal file
45
source/java/writer2latex/base/Option.java
Normal file
|
@ -0,0 +1,45 @@
|
|||
/************************************************************************
|
||||
*
|
||||
* Option.java
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License version 2.1, as published by the Free Software Foundation.
|
||||
*
|
||||
* This library 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
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston,
|
||||
* MA 02111-1307 USA
|
||||
*
|
||||
* Copyright: 2002-2008 by Henrik Just
|
||||
*
|
||||
* All Rights Reserved.
|
||||
*
|
||||
* Version 1.0 (2008-09-08)
|
||||
*
|
||||
*/
|
||||
|
||||
package writer2latex.base;
|
||||
|
||||
// The mother of all options; reads and writes string values
|
||||
public class Option {
|
||||
protected String sValue;
|
||||
private String sName;
|
||||
|
||||
public void setString(String sValue) { this.sValue = sValue; }
|
||||
|
||||
public String getString() { return sValue; }
|
||||
|
||||
public String getName() { return sName; }
|
||||
|
||||
public Option(String sName, String sDefaultValue) {
|
||||
this.sName = sName;
|
||||
setString(sDefaultValue);
|
||||
}
|
||||
}
|
||||
|
17
source/java/writer2latex/base/Package.html
Normal file
17
source/java/writer2latex/base/Package.html
Normal file
|
@ -0,0 +1,17 @@
|
|||
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
|
||||
|
||||
<html>
|
||||
<head>
|
||||
<title>The package writer2latex.base</title>
|
||||
</head>
|
||||
|
||||
<body>
|
||||
<p>This package contains (abstract) base implementations of some of the
|
||||
interfaces in writer2latex.api</p>
|
||||
|
||||
<p>They are intended to be subclassed by converters into specific formats
|
||||
e.g. LaTeX, xhtml</p>
|
||||
|
||||
|
||||
</body>
|
||||
</html>
|
238
source/java/writer2latex/bibtex/BibTeXDocument.java
Normal file
238
source/java/writer2latex/bibtex/BibTeXDocument.java
Normal file
|
@ -0,0 +1,238 @@
|
|||
/************************************************************************
|
||||
*
|
||||
* BibTeXDocument.java
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License version 2.1, as published by the Free Software Foundation.
|
||||
*
|
||||
* This library 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
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston,
|
||||
* MA 02111-1307 USA
|
||||
*
|
||||
* Copyright: 2002-2009 by Henrik Just
|
||||
*
|
||||
* All Rights Reserved.
|
||||
*
|
||||
* Version 1.0 (2009-02-17)
|
||||
*
|
||||
*/
|
||||
|
||||
package writer2latex.bibtex;
|
||||
|
||||
import writer2latex.xmerge.Document;
|
||||
|
||||
import java.util.Hashtable;
|
||||
import java.util.Enumeration;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.io.OutputStream;
|
||||
import java.io.OutputStreamWriter;
|
||||
|
||||
import writer2latex.api.ConverterFactory;
|
||||
import writer2latex.latex.LaTeXConfig;
|
||||
import writer2latex.latex.i18n.ClassicI18n;
|
||||
import writer2latex.latex.i18n.I18n;
|
||||
import writer2latex.util.ExportNameCollection;
|
||||
//import writer2latex.util.Misc;
|
||||
import writer2latex.office.BibMark;
|
||||
|
||||
/**
|
||||
* <p>Class representing a BibTeX document.</p>
|
||||
*
|
||||
*/
|
||||
public class BibTeXDocument implements Document {
|
||||
private static final String FILE_EXTENSION = ".bib";
|
||||
|
||||
private String sName;
|
||||
private Hashtable entries = new Hashtable();
|
||||
private ExportNameCollection exportNames = new ExportNameCollection(true);
|
||||
private I18n i18n;
|
||||
|
||||
/**
|
||||
* <p>Constructs a new BibTeX Document.</p>
|
||||
*
|
||||
* <p>This new document is empty. Bibliographic data must added
|
||||
* using the <code>put</code> method.</p>
|
||||
*
|
||||
* @param sName The name of the <code>BibTeXDocument</code>.
|
||||
*/
|
||||
public BibTeXDocument(String sName) {
|
||||
this.sName = trimDocumentName(sName);
|
||||
// Use default config (only ascii, no extra font packages)
|
||||
i18n = new ClassicI18n(new LaTeXConfig());
|
||||
}
|
||||
|
||||
/**
|
||||
* <p>This method is supposed to read <code>byte</code> data from the InputStream.
|
||||
* Currently it does nothing, since we don't need it.</p>
|
||||
*
|
||||
* @param is InputStream containing a BibTeX data file.
|
||||
*
|
||||
* @throws IOException In case of any I/O errors.
|
||||
*/
|
||||
public void read(InputStream is) throws IOException {
|
||||
// Do nothing.
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* <p>Returns the <code>Document</code> name with no file extension.</p>
|
||||
*
|
||||
* @return The <code>Document</code> name with no file extension.
|
||||
*/
|
||||
public String getName() {
|
||||
return sName;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* <p>Returns the <code>Document</code> name with file extension.</p>
|
||||
*
|
||||
* @return The <code>Document</code> name with file extension.
|
||||
*/
|
||||
public String getFileName() {
|
||||
return new String(sName + FILE_EXTENSION);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* <p>Writes out the <code>Document</code> content to the specified
|
||||
* <code>OutputStream</code>.</p>
|
||||
*
|
||||
* <p>This method may not be thread-safe.
|
||||
* Implementations may or may not synchronize this
|
||||
* method. User code (i.e. caller) must make sure that
|
||||
* calls to this method are thread-safe.</p>
|
||||
*
|
||||
* @param os <code>OutputStream</code> to write out the
|
||||
* <code>Document</code> content.
|
||||
*
|
||||
* @throws IOException If any I/O error occurs.
|
||||
*/
|
||||
public void write(OutputStream os) throws IOException {
|
||||
// BibTeX files are plain ascii
|
||||
OutputStreamWriter osw = new OutputStreamWriter(os,"ASCII");
|
||||
osw.write("%% This file was converted to BibTeX by Writer2BibTeX ver. "+ConverterFactory.getVersion()+".\n");
|
||||
osw.write("%% See http://www.hj-gym.dk/~hj/writer2latex for more info.\n");
|
||||
osw.write("\n");
|
||||
Enumeration enumeration = entries.elements();
|
||||
while (enumeration.hasMoreElements()) {
|
||||
BibMark entry = (BibMark) enumeration.nextElement();
|
||||
osw.write("@");
|
||||
osw.write(entry.getEntryType().toUpperCase());
|
||||
osw.write("{");
|
||||
osw.write(exportNames.getExportName(entry.getIdentifier()));
|
||||
osw.write(",\n");
|
||||
for (int i=0; i<BibMark.FIELD_COUNT; i++) {
|
||||
String sValue = entry.getField(i);
|
||||
if (sValue!=null) {
|
||||
if (i==BibMark.AUTHOR || i==BibMark.EDITOR) {
|
||||
// OOo uses ; to separate authors and editors - BibTeX uses and
|
||||
sValue = sValue.replaceAll(";" , " and ");
|
||||
}
|
||||
osw.write(" ");
|
||||
osw.write(getFieldName(i).toUpperCase());
|
||||
osw.write(" = {");
|
||||
for (int j=0; j<sValue.length(); j++) {
|
||||
String s = i18n.convert(Character.toString(sValue.charAt(j)),false,"en");
|
||||
if (s.charAt(0)=='\\') { osw.write("{"); }
|
||||
osw.write(s);
|
||||
if (s.charAt(0)=='\\') { osw.write("}"); }
|
||||
}
|
||||
osw.write("},\n");
|
||||
}
|
||||
}
|
||||
osw.write("}\n\n");
|
||||
}
|
||||
osw.flush();
|
||||
osw.close();
|
||||
}
|
||||
|
||||
/**
|
||||
* <p> Return BibTeX name of field </p>
|
||||
*/
|
||||
public static final String getFieldName(int nField) {
|
||||
switch (nField) {
|
||||
case BibMark.ADDRESS: return "address";
|
||||
case BibMark.ANNOTE: return "annote";
|
||||
case BibMark.AUTHOR: return "author";
|
||||
case BibMark.BOOKTITLE: return "booktitle";
|
||||
case BibMark.CHAPTER: return "chapter";
|
||||
// case BibMark.CROSSREF: return "croosref"; // not in OOo
|
||||
case BibMark.EDITION: return "edition";
|
||||
case BibMark.EDITOR: return "editor";
|
||||
case BibMark.HOWPUBLISHED: return "howpublished";
|
||||
case BibMark.INSTITUTION: return "institution";
|
||||
case BibMark.JOURNAL: return "journal";
|
||||
// case BibMark.KEY: return "key"; // not in OOo
|
||||
case BibMark.MONTH: return "month";
|
||||
case BibMark.NOTE: return "note";
|
||||
case BibMark.NUMBER: return "number";
|
||||
case BibMark.ORGANIZATIONS: return "organization";
|
||||
case BibMark.PAGES: return "pages";
|
||||
case BibMark.PUBLISHER: return "publisher";
|
||||
case BibMark.SCHOOL: return "school";
|
||||
case BibMark.SERIES: return "series";
|
||||
case BibMark.TITLE: return "title";
|
||||
case BibMark.REPORT_TYPE: return "type";
|
||||
case BibMark.VOLUME: return "volume";
|
||||
case BibMark.YEAR: return "year";
|
||||
case BibMark.URL: return "url";
|
||||
case BibMark.CUSTOM1: return "custom1";
|
||||
case BibMark.CUSTOM2: return "custom2";
|
||||
case BibMark.CUSTOM3: return "custom3";
|
||||
case BibMark.CUSTOM4: return "custom4";
|
||||
case BibMark.CUSTOM5: return "custom5";
|
||||
case BibMark.ISBN: return "isbn";
|
||||
default: return null;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* <p>Check if this entry exists</p>
|
||||
*/
|
||||
public boolean containsKey(String sIdentifier) {
|
||||
return entries.containsKey(sIdentifier);
|
||||
}
|
||||
|
||||
/*
|
||||
* <p>Add an entry</p>
|
||||
*/
|
||||
public void put(BibMark entry) {
|
||||
entries.put(entry.getIdentifier(),entry);
|
||||
exportNames.addName(entry.getIdentifier());
|
||||
}
|
||||
|
||||
/*
|
||||
* <p>Get export name for an identifier</p>
|
||||
*/
|
||||
public String getExportName(String sIdentifier) {
|
||||
return exportNames.getExportName(sIdentifier);
|
||||
}
|
||||
|
||||
/*
|
||||
* Utility method to make sure the document name is stripped of any file
|
||||
* extensions before use.
|
||||
*/
|
||||
private String trimDocumentName(String name) {
|
||||
String temp = name.toLowerCase();
|
||||
|
||||
if (temp.endsWith(FILE_EXTENSION)) {
|
||||
// strip the extension
|
||||
int nlen = name.length();
|
||||
int endIndex = nlen - FILE_EXTENSION.length();
|
||||
name = name.substring(0,endIndex);
|
||||
}
|
||||
|
||||
return name;
|
||||
}
|
||||
}
|
||||
|
91
source/java/writer2latex/bibtex/Converter.java
Normal file
91
source/java/writer2latex/bibtex/Converter.java
Normal file
|
@ -0,0 +1,91 @@
|
|||
/************************************************************************
|
||||
*
|
||||
* Converter.java
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License version 2.1, as published by the Free Software Foundation.
|
||||
*
|
||||
* This library 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
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston,
|
||||
* MA 02111-1307 USA
|
||||
*
|
||||
* Copyright: 2001-2008 by Henrik Just
|
||||
*
|
||||
* All Rights Reserved.
|
||||
*
|
||||
* version 1.0 (2008-11-22)
|
||||
*
|
||||
*/
|
||||
|
||||
package writer2latex.bibtex;
|
||||
|
||||
import writer2latex.api.Config;
|
||||
//import writer2latex.api.ConverterResult;
|
||||
import writer2latex.base.ConverterBase;
|
||||
import writer2latex.latex.LaTeXConfig;
|
||||
import writer2latex.office.BibMark;
|
||||
import writer2latex.office.XMLString;
|
||||
import writer2latex.util.Misc;
|
||||
|
||||
//import writer2latex.xmerge.ConvertData;
|
||||
//import writer2latex.xmerge.OfficeDocument;
|
||||
|
||||
import java.io.IOException;
|
||||
|
||||
import org.w3c.dom.Element;
|
||||
import org.w3c.dom.NodeList;
|
||||
|
||||
/**
|
||||
* <p>BibTeX export</p>
|
||||
*
|
||||
* <p>This class extracts bibliographic information from an OpenDocument text file to a BibTeX data file.</p>
|
||||
*
|
||||
*/
|
||||
public final class Converter extends ConverterBase {
|
||||
|
||||
// Configuration - TODO: Doesn't really use it - should use some fake config
|
||||
private LaTeXConfig config;
|
||||
|
||||
public Config getConfig() { return config; }
|
||||
|
||||
// Constructor
|
||||
public Converter() {
|
||||
super();
|
||||
config = new LaTeXConfig();
|
||||
}
|
||||
|
||||
/**
|
||||
* <p>Convert the data passed into the <code>InputStream</code>
|
||||
* into BibTeX format.</p>
|
||||
*
|
||||
* @throws IOException If any I/O error occurs.
|
||||
*/
|
||||
public void convertInner() throws IOException {
|
||||
sTargetFileName = Misc.trimDocumentName(sTargetFileName,".bib");
|
||||
|
||||
BibTeXDocument bibDoc = new BibTeXDocument(sTargetFileName);
|
||||
|
||||
// Collect all text:bibliography-mark elements from the content
|
||||
Element doc = ofr.getContent();
|
||||
NodeList list;
|
||||
list = doc.getElementsByTagName(XMLString.TEXT_BIBLIOGRAPHY_MARK);
|
||||
int nLen = list.getLength();
|
||||
for (int i=0; i<nLen; i++) {
|
||||
String sIdentifier = Misc.getAttribute(list.item(i),XMLString.TEXT_IDENTIFIER);
|
||||
if (sIdentifier!=null && !bibDoc.containsKey(sIdentifier)) {
|
||||
bibDoc.put(new BibMark(list.item(i)));
|
||||
}
|
||||
}
|
||||
|
||||
// Add result
|
||||
convertData.addDocument(bibDoc);
|
||||
}
|
||||
|
||||
}
|
14
source/java/writer2latex/bibtex/Package.html
Normal file
14
source/java/writer2latex/bibtex/Package.html
Normal file
|
@ -0,0 +1,14 @@
|
|||
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
|
||||
|
||||
<html>
|
||||
<head>
|
||||
<title>The package writer2latex.bibtex</title>
|
||||
</head>
|
||||
|
||||
<body>
|
||||
<p>This package contains BibTeX specific code.</p>
|
||||
<p>It contains a <code>writerlatex.api.Converter</code> implementation for
|
||||
conversion into BibTeX, as well as code to convert to BibTeX as part of a
|
||||
conversion into LaTeX.</p>
|
||||
</body>
|
||||
</html>
|
157
source/java/writer2latex/latex/BibConverter.java
Normal file
157
source/java/writer2latex/latex/BibConverter.java
Normal file
|
@ -0,0 +1,157 @@
|
|||
/************************************************************************
|
||||
*
|
||||
* BibConverter.java
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License version 2.1, as published by the Free Software Foundation.
|
||||
*
|
||||
* This library 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
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston,
|
||||
* MA 02111-1307 USA
|
||||
*
|
||||
* Copyright: 2002-2008 by Henrik Just
|
||||
*
|
||||
* All Rights Reserved.
|
||||
*
|
||||
* Version 1.0 (2008-09-08)
|
||||
*
|
||||
*/
|
||||
|
||||
package writer2latex.latex;
|
||||
|
||||
import org.w3c.dom.Element;
|
||||
|
||||
import writer2latex.bibtex.BibTeXDocument;
|
||||
|
||||
import writer2latex.latex.util.Context;
|
||||
|
||||
import writer2latex.office.BibMark;
|
||||
import writer2latex.office.OfficeReader;
|
||||
import writer2latex.office.XMLString;
|
||||
|
||||
import writer2latex.util.Misc;
|
||||
|
||||
/**
|
||||
* This class handles the bibliography. The result depends on these
|
||||
* configuration options. The citations will be treated like this:
|
||||
* <ul>
|
||||
* <li><code>use_bibtex</code>: If true, citations will be exported as \cite
|
||||
* commands. If false, citations will be exported as static text</li>
|
||||
* </ul>
|
||||
* The bibliography will be treated like this:
|
||||
* <ul>
|
||||
* <li><code>use_index</code>: If false, the bibliography will be omitted</li>
|
||||
* <li><code>use_bibtex</code> true and <code>external_bibtex_files</code>
|
||||
* empty: The citations will be exported to a BibTeX file, which will be used
|
||||
* for the bibliography</li>
|
||||
* <li><code>use_bibtex</code> true and <code>external_bibtex_files</code>
|
||||
* non-empty: The citations will be not be exported to a BibTeX file, the
|
||||
* files referred to by the option will be used instead</li>
|
||||
* <li><code>use_bibtex</code> false: The bibliography will be exported as
|
||||
* static text.
|
||||
* <li><code>bibtex_style</code> If BibTeX is used, this style will be applied
|
||||
* </ul>
|
||||
*/
|
||||
public class BibConverter extends ConverterHelper {
|
||||
|
||||
private BibTeXDocument bibDoc;
|
||||
|
||||
/** Construct a new BibConverter.
|
||||
* @param config the configuration to use
|
||||
* @param palette the ConverterPalette to use
|
||||
*/
|
||||
public BibConverter(OfficeReader ofr,LaTeXConfig config, ConverterPalette palette) {
|
||||
super(ofr,config,palette);
|
||||
}
|
||||
|
||||
/** Append declarations needed by the <code>BibConverter</code> to
|
||||
* the preamble.
|
||||
* @param pack the LaTeXDocumentPortion to which
|
||||
* declarations of packages should be added (\\usepackage).
|
||||
* @param decl the LaTeXDocumentPortion to which
|
||||
* other declarations should be added.
|
||||
*/
|
||||
public void appendDeclarations(LaTeXDocumentPortion pack, LaTeXDocumentPortion decl) {
|
||||
// Currently nothing; may add support for eg. natbib later
|
||||
}
|
||||
|
||||
/** Process a bibliography (text:bibliography tag)
|
||||
* @param node The element containing the Bibliography
|
||||
* @param ldp the LaTeXDocumentPortion to which LaTeX code should be added
|
||||
* @param oc the current context
|
||||
*/
|
||||
public void handleBibliography (Element node, LaTeXDocumentPortion ldp, Context oc) {
|
||||
if (config.noIndex()) { return; }
|
||||
if (config.useBibtex()) {
|
||||
// Use the style given in the configuration
|
||||
// TODO: Create a bst file from the settings of the text:bibliography
|
||||
ldp.append("\\bibliographystyle{")
|
||||
.append(config.bibtexStyle())
|
||||
.append("}").nl();
|
||||
|
||||
// Use BibTeX file from configuration, or exported BibTeX file
|
||||
if (config.externalBibtexFiles().length()>0) {
|
||||
ldp.append("\\bibliography{")
|
||||
.append(config.externalBibtexFiles())
|
||||
.append("}").nl();
|
||||
}
|
||||
else {
|
||||
if (bibDoc==null) { bibDoc = new BibTeXDocument(palette.getOutFileName()); }
|
||||
ldp.append("\\bibliography{")
|
||||
.append(bibDoc.getName())
|
||||
.append("}").nl();
|
||||
}
|
||||
}
|
||||
else { // typeset current content
|
||||
Element body = Misc.getChildByTagName(node,XMLString.TEXT_INDEX_BODY);
|
||||
if (body!=null) {
|
||||
Element title = Misc.getChildByTagName(body,XMLString.TEXT_INDEX_TITLE);
|
||||
if (title!=null) { palette.getBlockCv().traverseBlockText(title,ldp,oc); }
|
||||
palette.getBlockCv().traverseBlockText(body,ldp,oc);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/** Process a Bibliography Mark (text:bibliography-mark tag)
|
||||
* @param node The element containing the Mark
|
||||
* @param ldp the LaTeXDocumentPortion to which LaTeX code should be added
|
||||
* @param oc the current context
|
||||
*/
|
||||
public void handleBibliographyMark(Element node, LaTeXDocumentPortion ldp, Context oc) {
|
||||
if (config.useBibtex()) {
|
||||
String sIdentifier = node.getAttribute(XMLString.TEXT_IDENTIFIER);
|
||||
if (sIdentifier!=null) {
|
||||
if (config.externalBibtexFiles().length()==0) {
|
||||
if (bibDoc==null) { bibDoc = new BibTeXDocument(palette.getOutFileName()); }
|
||||
if (!bibDoc.containsKey(sIdentifier)) {
|
||||
bibDoc.put(new BibMark(node));
|
||||
}
|
||||
}
|
||||
ldp.append("\\cite{")
|
||||
.append(bibDoc.getExportName(sIdentifier))
|
||||
.append("}");
|
||||
}
|
||||
}
|
||||
else { // use current value
|
||||
palette.getInlineCv().traverseInlineText(node,ldp,oc);
|
||||
}
|
||||
}
|
||||
|
||||
/** Get the BibTeX document, if any (the document is only created if it's
|
||||
* specified in the configuration *and* the document contains bibliographic
|
||||
* data *and* the configuration does not specify external BibTeX files
|
||||
* @return the BiBTeXDocument, or null if it does not exist).
|
||||
*/
|
||||
public BibTeXDocument getBibTeXDocument () {
|
||||
return bibDoc;
|
||||
}
|
||||
|
||||
|
||||
}
|
378
source/java/writer2latex/latex/BlockConverter.java
Normal file
378
source/java/writer2latex/latex/BlockConverter.java
Normal file
|
@ -0,0 +1,378 @@
|
|||
/************************************************************************
|
||||
*
|
||||
* BlockConverter.java
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License version 2.1, as published by the Free Software Foundation.
|
||||
*
|
||||
* This library 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
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston,
|
||||
* MA 02111-1307 USA
|
||||
*
|
||||
* Copyright: 2002-2008 by Henrik Just
|
||||
*
|
||||
* All Rights Reserved.
|
||||
*
|
||||
* Version 1.0 (2008-11-23)
|
||||
*
|
||||
*/
|
||||
|
||||
package writer2latex.latex;
|
||||
|
||||
import org.w3c.dom.Element;
|
||||
import org.w3c.dom.Node;
|
||||
import org.w3c.dom.NodeList;
|
||||
|
||||
import writer2latex.latex.util.BeforeAfter;
|
||||
import writer2latex.latex.util.Context;
|
||||
//import writer2latex.latex.util.HeadingMap;
|
||||
import writer2latex.latex.util.StyleMap;
|
||||
import writer2latex.office.ListStyle;
|
||||
import writer2latex.office.OfficeReader;
|
||||
//import writer2latex.office.TableReader;
|
||||
import writer2latex.office.XMLString;
|
||||
import writer2latex.util.Misc;
|
||||
|
||||
/**
|
||||
* <p>This class handles basic block content, including the main text body,
|
||||
* sections, tables, lists, headings and paragraphs.</p>
|
||||
*/
|
||||
public class BlockConverter extends ConverterHelper {
|
||||
|
||||
public BlockConverter(OfficeReader ofr, LaTeXConfig config, ConverterPalette palette) {
|
||||
super(ofr,config,palette);
|
||||
}
|
||||
|
||||
public void appendDeclarations(LaTeXDocumentPortion pack, LaTeXDocumentPortion decl) {
|
||||
// currently do nothing..
|
||||
}
|
||||
|
||||
|
||||
/** <p> Traverse block text (eg. content of body, section, list item).
|
||||
* This is traversed in logical order and dedicated handlers take care of
|
||||
* each block element.</p>
|
||||
* <p> (Note: As a rule, all handling of block level elements should add a
|
||||
* newline to the LaTeX document at the end of the block)</p>
|
||||
* @param node The element containing the block text
|
||||
* @param ldp the <code>LaTeXDocumentPortion</code> to which
|
||||
* LaTeX code should be added
|
||||
* @param oc the current context
|
||||
*/
|
||||
public void traverseBlockText(Element node, LaTeXDocumentPortion ldp, Context oc) {
|
||||
Context ic = (Context) oc.clone();
|
||||
|
||||
// The current paragraph block:
|
||||
StyleMap blockMap = config.getParBlockStyleMap();
|
||||
String sBlockName = null;
|
||||
|
||||
if (node.hasChildNodes()) {
|
||||
NodeList list = node.getChildNodes();
|
||||
int nLen = list.getLength();
|
||||
|
||||
for (int i = 0; i < nLen; i++) {
|
||||
Node childNode = list.item(i);
|
||||
|
||||
if (childNode.getNodeType() == Node.ELEMENT_NODE) {
|
||||
Element child = (Element)childNode;
|
||||
String sTagName = child.getTagName();
|
||||
|
||||
// Start/End a paragraph block (not in tables)
|
||||
if (!ic.isInTable()) {
|
||||
if (sTagName.equals(XMLString.TEXT_P)) {
|
||||
String sStyleName = ofr.getParStyles().getDisplayName(child.getAttribute(XMLString.TEXT_STYLE_NAME));
|
||||
if (sBlockName!=null && !blockMap.isNext(sBlockName,sStyleName)) {
|
||||
// end current block
|
||||
String sAfter = blockMap.getAfter(sBlockName);
|
||||
if (sAfter.length()>0) ldp.append(sAfter).nl();
|
||||
sBlockName = null;
|
||||
ic.setVerbatim(false);
|
||||
}
|
||||
if (sBlockName==null && blockMap.contains(sStyleName)) {
|
||||
// start a new block
|
||||
sBlockName = sStyleName;
|
||||
String sBefore = blockMap.getBefore(sBlockName);
|
||||
if (sBefore.length()>0) ldp.append(sBefore).nl();
|
||||
ic.setVerbatim(blockMap.getVerbatim(sStyleName));
|
||||
}
|
||||
}
|
||||
else if (sBlockName!=null) {
|
||||
// non-paragraph: end current block
|
||||
String sAfter = blockMap.getAfter(sBlockName);
|
||||
if (sAfter.length()>0) ldp.append(sAfter).nl();
|
||||
sBlockName = null;
|
||||
ic.setVerbatim(false);
|
||||
}
|
||||
}
|
||||
|
||||
palette.getFieldCv().flushReferenceMarks(ldp,ic);
|
||||
palette.getIndexCv().flushIndexMarks(ldp,ic);
|
||||
|
||||
palette.getInfo().addDebugInfo(child,ldp);
|
||||
|
||||
// Basic block content; handle by this class
|
||||
if (sTagName.equals(XMLString.TEXT_P)) {
|
||||
// is this a caption?
|
||||
String sSequence = ofr.getSequenceName(child);
|
||||
if (ofr.isFigureSequenceName(sSequence)) {
|
||||
palette.getDrawCv().handleCaption(child,ldp,ic);
|
||||
}
|
||||
else if (ofr.isTableSequenceName(sSequence)) {
|
||||
// Next node *should* be a table
|
||||
if (i+1<nLen && Misc.isElement(list.item(i+1),XMLString.TABLE_TABLE)) {
|
||||
// Found table with caption above
|
||||
palette.getTableCv().handleTable((Element)list.item(++i),child,true,ldp,ic);
|
||||
}
|
||||
else {
|
||||
// Found lonely caption
|
||||
palette.getTableCv().handleCaption(child,ldp,ic);
|
||||
}
|
||||
}
|
||||
else {
|
||||
palette.getParCv().handleParagraph(child,ldp,ic,i==nLen-1);
|
||||
}
|
||||
}
|
||||
|
||||
else if(sTagName.equals(XMLString.TEXT_H)) {
|
||||
palette.getHeadingCv().handleHeading(child,ldp,ic);
|
||||
}
|
||||
|
||||
else if (sTagName.equals(XMLString.TEXT_LIST)) { // oasis
|
||||
handleList(child,ldp,ic);
|
||||
}
|
||||
|
||||
else if (sTagName.equals(XMLString.TEXT_UNORDERED_LIST)) {
|
||||
handleList(child,ldp,ic);
|
||||
}
|
||||
|
||||
else if (sTagName.equals(XMLString.TEXT_ORDERED_LIST)) {
|
||||
handleList(child,ldp,ic);
|
||||
}
|
||||
else if (sTagName.equals(XMLString.TABLE_TABLE)) {
|
||||
// Next node *could* be a caption
|
||||
if (i+1<nLen && Misc.isElement(list.item(i+1),XMLString.TEXT_P) &&
|
||||
ofr.isTableSequenceName(ofr.getSequenceName((Element)list.item(i+1)))) {
|
||||
// Found table with caption below
|
||||
palette.getTableCv().handleTable(child,(Element)list.item(++i),false,ldp,oc);
|
||||
}
|
||||
else {
|
||||
// Found table without caption
|
||||
palette.getTableCv().handleTable(child,null,false,ldp,oc);
|
||||
}
|
||||
}
|
||||
|
||||
else if (sTagName.equals(XMLString.TABLE_SUB_TABLE)) {
|
||||
palette.getTableCv().handleTable(child,null,true,ldp,ic);
|
||||
}
|
||||
|
||||
else if (sTagName.equals(XMLString.TEXT_SECTION)) {
|
||||
palette.getSectionCv().handleSection(child,ldp,ic);
|
||||
}
|
||||
|
||||
// Draw elements may appear in block context if they are
|
||||
// anchored to page
|
||||
else if (sTagName.startsWith("draw:")) {
|
||||
palette.getDrawCv().handleDrawElement(child,ldp,ic);
|
||||
}
|
||||
|
||||
// Indexes
|
||||
else if (sTagName.equals(XMLString.TEXT_TABLE_OF_CONTENT)) {
|
||||
palette.getIndexCv().handleTOC(child,ldp,ic);
|
||||
}
|
||||
|
||||
else if (sTagName.equals(XMLString.TEXT_ILLUSTRATION_INDEX)) {
|
||||
palette.getIndexCv().handleLOF(child,ldp,ic);
|
||||
}
|
||||
|
||||
else if (sTagName.equals(XMLString.TEXT_TABLE_INDEX)) {
|
||||
palette.getIndexCv().handleLOT(child,ldp,ic);
|
||||
}
|
||||
|
||||
else if (sTagName.equals(XMLString.TEXT_OBJECT_INDEX)) {
|
||||
palette.getIndexCv().handleObjectIndex(child,ldp,ic);
|
||||
}
|
||||
|
||||
else if (sTagName.equals(XMLString.TEXT_USER_INDEX)) {
|
||||
palette.getIndexCv().handleUserIndex(child,ldp,ic);
|
||||
}
|
||||
|
||||
else if (sTagName.equals(XMLString.TEXT_ALPHABETICAL_INDEX)) {
|
||||
palette.getIndexCv().handleAlphabeticalIndex(child,ldp,ic);
|
||||
}
|
||||
|
||||
else if (sTagName.equals(XMLString.TEXT_BIBLIOGRAPHY)) {
|
||||
palette.getBibCv().handleBibliography(child,ldp,ic);
|
||||
}
|
||||
|
||||
// Sequence declarations appear in the main text body (before the actual content)
|
||||
else if (sTagName.equals(XMLString.TEXT_SEQUENCE_DECLS)) {
|
||||
palette.getFieldCv().handleSequenceDecls(child);
|
||||
}
|
||||
// other tags are ignored
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (!oc.isInTable() && sBlockName!=null) {
|
||||
// end current block
|
||||
String sAfter = blockMap.getAfter(sBlockName);
|
||||
if (sAfter.length()>0) ldp.append(sAfter).nl();
|
||||
sBlockName = null;
|
||||
}
|
||||
palette.getFieldCv().flushReferenceMarks(ldp,ic);
|
||||
palette.getIndexCv().flushIndexMarks(ldp,ic);
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
/** <p> Process a list (text:ordered-lst or text:unordered-list tag)</p>
|
||||
* @param node The element containing the list
|
||||
* @param ldp the <code>LaTeXDocumentPortion</code> to which
|
||||
* LaTeX code should be added
|
||||
* @param oc the current context
|
||||
*/
|
||||
public void handleList(Element node, LaTeXDocumentPortion ldp, Context oc) {
|
||||
// Set up new context
|
||||
Context ic = (Context) oc.clone();
|
||||
ic.incListLevel();
|
||||
|
||||
// Get the style name, if we don't know it already
|
||||
if (ic.getListStyleName()==null) {
|
||||
ic.setListStyleName(node.getAttribute(XMLString.TEXT_STYLE_NAME));
|
||||
}
|
||||
|
||||
// Use the style to determine the type of list
|
||||
ListStyle style = ofr.getListStyle(ic.getListStyleName());
|
||||
boolean bOrdered = style!=null && style.isNumber(ic.getListLevel());
|
||||
|
||||
// If the list contains headings, ignore it!
|
||||
if (ic.isIgnoreLists() || listContainsHeadings(node)) {
|
||||
ic.setIgnoreLists(true);
|
||||
traverseList(node,ldp,ic);
|
||||
return;
|
||||
}
|
||||
|
||||
// Apply the style
|
||||
BeforeAfter ba = new BeforeAfter();
|
||||
palette.getListSc().applyListStyle(ic.getListStyleName(),ic.getListLevel(),
|
||||
bOrdered,"true".equals(node.getAttribute(XMLString.TEXT_CONTINUE_NUMBERING)),
|
||||
ba);
|
||||
|
||||
// Export the list
|
||||
if (ba.getBefore().length()>0) { ldp.append(ba.getBefore()).nl(); }
|
||||
traverseList(node,ldp,ic);
|
||||
if (ba.getAfter().length()>0) { ldp.append(ba.getAfter()).nl(); }
|
||||
}
|
||||
|
||||
/*
|
||||
* Process the contents of a list
|
||||
*/
|
||||
private void traverseList (Element node, LaTeXDocumentPortion ldp, Context oc) {
|
||||
if (node.hasChildNodes()) {
|
||||
NodeList list = node.getChildNodes();
|
||||
int nLen = list.getLength();
|
||||
|
||||
for (int i = 0; i < nLen; i++) {
|
||||
Node child = list.item(i);
|
||||
|
||||
if (child.getNodeType() == Node.ELEMENT_NODE) {
|
||||
String nodeName = child.getNodeName();
|
||||
|
||||
palette.getInfo().addDebugInfo((Element)child,ldp);
|
||||
|
||||
if (nodeName.equals(XMLString.TEXT_LIST_ITEM)) {
|
||||
handleListItem((Element)child,ldp,oc);
|
||||
}
|
||||
if (nodeName.equals(XMLString.TEXT_LIST_HEADER)) {
|
||||
handleListItem((Element)child,ldp,oc);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void handleListItem(Element node, LaTeXDocumentPortion ldp, Context oc) {
|
||||
// Are we ignoring this list?
|
||||
if (oc.isIgnoreLists()) {
|
||||
traverseBlockText(node,ldp,oc);
|
||||
return;
|
||||
}
|
||||
|
||||
// Apply the style
|
||||
BeforeAfter ba = new BeforeAfter();
|
||||
palette.getListSc().applyListItemStyle(
|
||||
oc.getListStyleName(), oc.getListLevel(),
|
||||
node.getNodeName().equals(XMLString.TEXT_LIST_HEADER),
|
||||
"true".equals(node.getAttribute(XMLString.TEXT_RESTART_NUMBERING)),
|
||||
Misc.getPosInteger(node.getAttribute(XMLString.TEXT_START_VALUE),1)-1,
|
||||
ba);
|
||||
|
||||
// export the list item
|
||||
if (ba.getBefore().length()>0) {
|
||||
ldp.append(ba.getBefore());
|
||||
if (config.formatting()>=LaTeXConfig.CONVERT_MOST) { ldp.nl(); }
|
||||
}
|
||||
traverseBlockText(node,ldp,oc);
|
||||
if (ba.getAfter().length()>0) { ldp.append(ba.getAfter()).nl(); }
|
||||
}
|
||||
|
||||
/*
|
||||
* Helper: Check to see, if this list contains headings
|
||||
* (in that case we will ignore the list!)
|
||||
*/
|
||||
private boolean listContainsHeadings (Node node) {
|
||||
if (node.hasChildNodes()) {
|
||||
NodeList nList = node.getChildNodes();
|
||||
int len = nList.getLength();
|
||||
for (int i = 0; i < len; i++) {
|
||||
Node child = nList.item(i);
|
||||
if (child.getNodeType() == Node.ELEMENT_NODE) {
|
||||
String nodeName = child.getNodeName();
|
||||
if (nodeName.equals(XMLString.TEXT_LIST_ITEM)) {
|
||||
if (listItemContainsHeadings(child)) return true;
|
||||
}
|
||||
if (nodeName.equals(XMLString.TEXT_LIST_HEADER)) {
|
||||
if (listItemContainsHeadings(child)) return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
private boolean listItemContainsHeadings(Node node) {
|
||||
if (node.hasChildNodes()) {
|
||||
NodeList nList = node.getChildNodes();
|
||||
int len = nList.getLength();
|
||||
for (int i = 0; i < len; i++) {
|
||||
Node child = nList.item(i);
|
||||
if (child.getNodeType() == Node.ELEMENT_NODE) {
|
||||
String nodeName = child.getNodeName();
|
||||
if(nodeName.equals(XMLString.TEXT_H)) {
|
||||
return true;
|
||||
}
|
||||
if (nodeName.equals(XMLString.TEXT_LIST)) {
|
||||
if (listContainsHeadings(child)) return true;
|
||||
}
|
||||
if (nodeName.equals(XMLString.TEXT_ORDERED_LIST)) {
|
||||
if (listContainsHeadings(child)) return true;
|
||||
}
|
||||
if (nodeName.equals(XMLString.TEXT_UNORDERED_LIST)) {
|
||||
if (listContainsHeadings(child)) return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
|
||||
}
|
163
source/java/writer2latex/latex/CaptionConverter.java
Normal file
163
source/java/writer2latex/latex/CaptionConverter.java
Normal file
|
@ -0,0 +1,163 @@
|
|||
/************************************************************************
|
||||
*
|
||||
* CaptionConverter.java
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License version 2.1, as published by the Free Software Foundation.
|
||||
*
|
||||
* This library 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
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston,
|
||||
* MA 02111-1307 USA
|
||||
*
|
||||
* Copyright: 2002-2008 by Henrik Just
|
||||
*
|
||||
* All Rights Reserved.
|
||||
*
|
||||
* Version 1.0 (2008-11-23)
|
||||
*
|
||||
*/
|
||||
|
||||
package writer2latex.latex;
|
||||
|
||||
import org.w3c.dom.Element;
|
||||
import org.w3c.dom.Node;
|
||||
|
||||
import writer2latex.latex.util.Context;
|
||||
import writer2latex.office.OfficeReader;
|
||||
import writer2latex.office.XMLString;
|
||||
|
||||
/**
|
||||
* <p>This class converts captions (for figures and tables) to LaTeX.</p>
|
||||
* <p>Packages:
|
||||
* <ul><li>caption.sty is used implement non-floating captions</li></ul>
|
||||
* <p>Options:
|
||||
* <ul><li>use_caption is a boolean option to determine whether or not
|
||||
* to use caption.sty. If this option is set to false, a simple definition of
|
||||
* \captionof (borrowed from capt-of.sty) is inserted in the preamble</li></ul>
|
||||
* <p>TODO: Implement formatting of captions using the features of caption.sty
|
||||
* (only if formatting>=CONVERT_BASIC)
|
||||
*/
|
||||
public class CaptionConverter extends ConverterHelper {
|
||||
|
||||
private boolean bNeedCaptionOf = false;
|
||||
|
||||
private Element seqField = null; // the sequence field within the current caption
|
||||
|
||||
public CaptionConverter(OfficeReader ofr, LaTeXConfig config, ConverterPalette palette) {
|
||||
super(ofr,config,palette);
|
||||
}
|
||||
|
||||
public void appendDeclarations(LaTeXDocumentPortion pack, LaTeXDocumentPortion decl) {
|
||||
if (bNeedCaptionOf) {
|
||||
if (config.useCaption()) {
|
||||
pack.append("\\usepackage{caption}").nl();
|
||||
}
|
||||
else { // use definition borrowed from capt-of.sty
|
||||
decl.append("% Non-floating captions").nl()
|
||||
.append("\\makeatletter").nl()
|
||||
.append("\\newcommand\\captionof[1]{\\def\\@captype{#1}\\caption}").nl()
|
||||
.append("\\makeatother").nl();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* <p> Process content of a text:p tag as a caption body (inluding label)</p>
|
||||
* @param node The text:p element node containing the caption
|
||||
* @param ldp The <code>LaTeXDocumentPortion</code> to add LaTeX code to
|
||||
* @param oc The current context
|
||||
* @param bIsCaptionOf true if this is caption uses captionof
|
||||
*/
|
||||
public void handleCaptionBody(Element node,LaTeXDocumentPortion ldp, Context oc, boolean bIsCaptionOf) {
|
||||
bNeedCaptionOf|=bIsCaptionOf;
|
||||
|
||||
// Get rid of the caption label before converting
|
||||
removeCaptionLabel(node,0);
|
||||
Element label = seqField;
|
||||
seqField = null;
|
||||
|
||||
// Get the stylename of the paragraph and push the font used
|
||||
String sStyleName = node.getAttribute(XMLString.TEXT_STYLE_NAME);
|
||||
palette.getI18n().pushSpecialTable(palette.getCharSc().getFontName(ofr.getParStyle(sStyleName)));
|
||||
|
||||
if (palette.getHeadingCv().containsElements(node)) {
|
||||
ldp.append("[");
|
||||
palette.getInlineCv().traversePlainInlineText(node,ldp,oc);
|
||||
ldp.append("]");
|
||||
}
|
||||
// Update context before traversing text
|
||||
Context ic = (Context) oc.clone();
|
||||
ldp.append("{");
|
||||
palette.getInlineCv().traverseInlineText(node,ldp,ic);
|
||||
ldp.append("}").nl();
|
||||
|
||||
// Insert label
|
||||
palette.getFieldCv().handleSequence(label,ldp,oc);
|
||||
|
||||
// Flush any index marks
|
||||
palette.getIndexCv().flushIndexMarks(ldp,oc);
|
||||
|
||||
// pop the font name
|
||||
palette.getI18n().popSpecialTable();
|
||||
|
||||
}
|
||||
|
||||
// In OpenDocument a caption is an ordinary paragraph with a text:seqence
|
||||
// element. For example
|
||||
// Table <text:sequence>3</text:sequence>: Caption text
|
||||
// The first part is the caption label which is autogenerated by LaTeX.
|
||||
// Before converting, we remove this in 3 steps:
|
||||
// nStep = 0: Remove all text before the text:sequence
|
||||
// nStep = 1: Remove all text up to the first alphanumeric character
|
||||
// after the text:sequence
|
||||
// nStep = 2: Finished!
|
||||
private int removeCaptionLabel(Element node, int nStep) {
|
||||
if (nStep==2) { return 2; }
|
||||
|
||||
Node removeMe = null;
|
||||
|
||||
Node child = node.getFirstChild();
|
||||
while (child!=null) {
|
||||
if (child.getNodeType()==Node.ELEMENT_NODE) {
|
||||
if (nStep==0 && child.getNodeName().equals(XMLString.TEXT_SEQUENCE)) {
|
||||
removeMe = child;
|
||||
seqField = (Element) child; // remember me...
|
||||
nStep = 1;
|
||||
}
|
||||
else if (nStep<2 && !OfficeReader.isDrawElement(child)) {
|
||||
// draw elements (frames) should not be touched..
|
||||
nStep = removeCaptionLabel((Element)child,nStep);
|
||||
}
|
||||
}
|
||||
else if (child.getNodeType()==Node.TEXT_NODE) {
|
||||
if (nStep==0) {
|
||||
child.setNodeValue("");
|
||||
}
|
||||
else if (nStep==1) {
|
||||
String s = child.getNodeValue();
|
||||
int n = s.length();
|
||||
for (int j=0; j<n; j++) {
|
||||
if (Character.isLetterOrDigit(s.charAt(j))) {
|
||||
child.setNodeValue(s.substring(j));
|
||||
nStep = 2;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
child = child.getNextSibling();
|
||||
}
|
||||
|
||||
if (removeMe!=null) { node.removeChild(removeMe); }
|
||||
return nStep;
|
||||
}
|
||||
|
||||
|
||||
}
|
507
source/java/writer2latex/latex/CharStyleConverter.java
Normal file
507
source/java/writer2latex/latex/CharStyleConverter.java
Normal file
|
@ -0,0 +1,507 @@
|
|||
/************************************************************************
|
||||
*
|
||||
* CharStyleConverter.java
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License version 2.1, as published by the Free Software Foundation.
|
||||
*
|
||||
* This library 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
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston,
|
||||
* MA 02111-1307 USA
|
||||
*
|
||||
* Copyright: 2002-2008 by Henrik Just
|
||||
*
|
||||
* All Rights Reserved.
|
||||
*
|
||||
* Version 1.0 (2008-12-03)
|
||||
*
|
||||
*/
|
||||
|
||||
package writer2latex.latex;
|
||||
|
||||
import java.util.Hashtable;
|
||||
|
||||
import writer2latex.util.*;
|
||||
import writer2latex.office.*;
|
||||
import writer2latex.latex.util.BeforeAfter;
|
||||
import writer2latex.latex.util.Context;
|
||||
import writer2latex.latex.util.StyleMap;
|
||||
|
||||
/** This class creates LaTeX code from OOo character formatting
|
||||
Character formatting in OOo includes font, font effects/decorations and color.
|
||||
In addition it includes color and language/country information, this is however handled
|
||||
by the classes <code>writer2latex.latex.ColorConverter</code> and
|
||||
<code>writer2latex.latex.style.I18n</code>
|
||||
*/
|
||||
public class CharStyleConverter extends StyleConverter {
|
||||
|
||||
// Cache of converted font declarations
|
||||
private Hashtable fontDecls = new Hashtable();
|
||||
|
||||
// Which formatting should we export?
|
||||
private boolean bIgnoreHardFontsize;
|
||||
private boolean bIgnoreFontsize;
|
||||
private boolean bIgnoreFont;
|
||||
private boolean bIgnoreAll;
|
||||
private boolean bUseUlem;
|
||||
// Do we need actually use ulem.sty or \textsubscript?
|
||||
private boolean bNeedUlem = false;
|
||||
private boolean bNeedSubscript = false;
|
||||
|
||||
/** <p>Constructs a new <code>CharStyleConverter</code>.</p>
|
||||
*/
|
||||
public CharStyleConverter(OfficeReader ofr, LaTeXConfig config, ConverterPalette palette) {
|
||||
super(ofr,config,palette);
|
||||
|
||||
bUseUlem = config.useUlem();
|
||||
|
||||
// No character formatting at all:
|
||||
bIgnoreAll = config.formatting()==LaTeXConfig.IGNORE_ALL;
|
||||
// No font family or size:
|
||||
bIgnoreFont = config.formatting()<=LaTeXConfig.IGNORE_MOST;
|
||||
// No fontsize:
|
||||
bIgnoreFontsize = config.formatting()<=LaTeXConfig.CONVERT_BASIC;
|
||||
// No hard fontsize
|
||||
bIgnoreHardFontsize = config.formatting()<=LaTeXConfig.CONVERT_MOST;
|
||||
}
|
||||
|
||||
public void appendDeclarations(LaTeXDocumentPortion pack, LaTeXDocumentPortion decl) {
|
||||
if (bNeedUlem) {
|
||||
pack.append("\\usepackage[normalem]{ulem}").nl();
|
||||
}
|
||||
if (bNeedSubscript && !config.getTextAttributeStyleMap().contains("subscript")) {
|
||||
decl.append("\\newcommand\\textsubscript[1]{\\ensuremath{{}_{\\text{#1}}}}").nl();
|
||||
}
|
||||
if (!styleNames.isEmpty()) {
|
||||
decl.append("% Text styles").nl().append(declarations);
|
||||
}
|
||||
}
|
||||
|
||||
/** <p>Use a text style in LaTeX.</p>
|
||||
* @param sName the name of the text style
|
||||
* @param ba a <code>BeforeAfter</code> to put code into
|
||||
*/
|
||||
public void applyTextStyle(String sName, BeforeAfter ba, Context context) {
|
||||
if (sName==null) { return; }
|
||||
String sDisplayName = ofr.getTextStyles().getDisplayName(sName);
|
||||
|
||||
if (bIgnoreAll) {
|
||||
// Even if all is ignored, we still apply style maps from config..
|
||||
StyleMap sm = config.getTextStyleMap();
|
||||
if (sm.contains(sDisplayName)) {
|
||||
ba.add(sm.getBefore(sDisplayName),sm.getAfter(sDisplayName));
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
// Style already converted?
|
||||
if (styleMap.contains(sName)) {
|
||||
ba.add(styleMap.getBefore(sName),styleMap.getAfter(sName));
|
||||
context.updateFormattingFromStyle(ofr.getTextStyle(sName));
|
||||
// it's verbatim if specified as such in the configuration
|
||||
StyleMap sm = config.getTextStyleMap();
|
||||
boolean bIsVerbatim = sm.contains(sDisplayName) && sm.getVerbatim(sDisplayName);
|
||||
context.setVerbatim(bIsVerbatim);
|
||||
context.setNoLineBreaks(bIsVerbatim);
|
||||
return;
|
||||
}
|
||||
|
||||
// The style may already be declared in the configuration:
|
||||
StyleMap sm = config.getTextStyleMap();
|
||||
if (sm.contains(sDisplayName)) {
|
||||
styleMap.put(sName,sm.getBefore(sDisplayName),sm.getAfter(sDisplayName));
|
||||
applyTextStyle(sName,ba,context);
|
||||
return;
|
||||
}
|
||||
|
||||
// Get the style, if it exists:
|
||||
StyleWithProperties style = ofr.getTextStyle(sName);
|
||||
if (style==null) {
|
||||
styleMap.put(sName,"","");
|
||||
applyTextStyle(sName,ba,context);
|
||||
return;
|
||||
}
|
||||
|
||||
// Convert automatic style
|
||||
if (style.isAutomatic()) {
|
||||
palette.getI18n().applyLanguage(style,false,true,ba);
|
||||
applyFont(style,false,true,ba,context);
|
||||
applyFontEffects(style,true,ba);
|
||||
context.updateFormattingFromStyle(ofr.getTextStyle(sName));
|
||||
return;
|
||||
}
|
||||
|
||||
// Convert soft style:
|
||||
// This must be converted relative to a blank context!
|
||||
BeforeAfter baText = new BeforeAfter();
|
||||
palette.getI18n().applyLanguage(style,false,true,baText);
|
||||
applyFont(style,false,true,baText,new Context());
|
||||
applyFontEffects(style,true,baText);
|
||||
// declare the text style (\newcommand)
|
||||
String sTeXName = styleNames.getExportName(ofr.getTextStyles().getDisplayName(sName));
|
||||
styleMap.put(sName,"\\textstyle"+sTeXName+"{","}");
|
||||
declarations.append("\\newcommand\\textstyle")
|
||||
.append(sTeXName).append("[1]{")
|
||||
.append(baText.getBefore()).append("#1").append(baText.getAfter())
|
||||
.append("}").nl();
|
||||
applyTextStyle(sName,ba,context);
|
||||
}
|
||||
|
||||
public String getFontName(StyleWithProperties style) {
|
||||
if (style!=null) {
|
||||
String sName = style.getProperty(XMLString.STYLE_FONT_NAME);
|
||||
if (sName!=null) {
|
||||
FontDeclaration fd = ofr.getFontDeclaration(sName);
|
||||
if (fd!=null) {
|
||||
return fd.getFontFamily();
|
||||
}
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
// Get the font name from a char style
|
||||
public String getFontName(String sStyleName) {
|
||||
return getFontName(ofr.getTextStyle(sStyleName));
|
||||
}
|
||||
|
||||
/** <p>Apply hard character formatting (no inheritance).</p>
|
||||
* <p>This is used in sections and {foot|end}notes</p>
|
||||
* @param style the style to use
|
||||
* @param ba the <code>BeforeAfter</code> to add LaTeX code to
|
||||
*/
|
||||
public void applyHardCharFormatting(StyleWithProperties style, BeforeAfter ba) {
|
||||
palette.getI18n().applyLanguage(style,true,false,ba);
|
||||
applyFont(style,true,false,ba,new Context());
|
||||
if (!ba.isEmpty()) { ba.add(" ",""); }
|
||||
}
|
||||
|
||||
/** <p>Apply all font attributes (family, series, shape, size and color).</p>
|
||||
* @param style the OOo style to read attributesfrom
|
||||
* @param bDecl true if declaration form is required
|
||||
* @param bInherit true if inherited properties should be used
|
||||
* @param ba the <code>BeforeAfter</code> to add LaTeX code to.
|
||||
*/
|
||||
public void applyFont(StyleWithProperties style, boolean bDecl, boolean bInherit, BeforeAfter ba, Context context) {
|
||||
// Note: if bDecl is true, nothing will be put in the "after" part of ba.
|
||||
if (style==null) { return; }
|
||||
applyNfssSize(style,bDecl,bInherit,ba,context);
|
||||
applyNfssFamily(style,bDecl,bInherit,ba,context);
|
||||
applyNfssSeries(style,bDecl,bInherit,ba,context);
|
||||
applyNfssShape(style,bDecl,bInherit,ba,context);
|
||||
palette.getColorCv().applyColor(style,bDecl,bInherit,ba,context);
|
||||
}
|
||||
|
||||
/** <p>Reset to normal font, size and color.</p>
|
||||
* @param ba the <code>BeforeAfter</code> to add LaTeX code to.
|
||||
*/
|
||||
public void applyNormalFont(BeforeAfter ba) {
|
||||
ba.add("\\normalfont\\normalsize","");
|
||||
palette.getColorCv().applyNormalColor(ba);
|
||||
}
|
||||
|
||||
/** <p>Apply default font attributes (family, series, shape, size and color).</p>
|
||||
* @param style the OOo style to read attributesfrom
|
||||
* @param ldp the <code>LaTeXDocumentPortion</code> to add LaTeX code to.
|
||||
*/
|
||||
public void applyDefaultFont(StyleWithProperties style, LaTeXDocumentPortion ldp) {
|
||||
if (style==null) { return; }
|
||||
|
||||
String s = convertFontDeclaration(style.getProperty(XMLString.STYLE_FONT_NAME));
|
||||
if (s!=null){
|
||||
ldp.append("\\renewcommand\\familydefault{\\")
|
||||
.append(s).append("default}").nl();
|
||||
} // TODO: Else read props directly from the style
|
||||
|
||||
s = nfssSeries(style.getProperty(XMLString.FO_FONT_WEIGHT));
|
||||
if (s!=null) {
|
||||
ldp.append("\\renewcommand\\seriesdefault{\\")
|
||||
.append(s).append("default}").nl();
|
||||
}
|
||||
|
||||
s = nfssShape(style.getProperty(XMLString.FO_FONT_VARIANT),
|
||||
style.getProperty(XMLString.FO_FONT_STYLE));
|
||||
if (s!=null) {
|
||||
ldp.append("\\renewcommand\\shapedefault{\\")
|
||||
.append(s).append("default}").nl();
|
||||
}
|
||||
|
||||
palette.getColorCv().setNormalColor(style.getProperty(XMLString.FO_COLOR),ldp);
|
||||
}
|
||||
|
||||
/** <p>Apply font effects (position, underline, crossout, change case.</p>
|
||||
* @param style the OOo style to read attributesfrom
|
||||
* @param bInherit true if inherited properties should be used
|
||||
* @param ba the <code>BeforeAfter</code> to add LaTeX code to.
|
||||
*/
|
||||
public void applyFontEffects(StyleWithProperties style, boolean bInherit, BeforeAfter ba) {
|
||||
if (style==null) { return; }
|
||||
applyTextPosition(style, bInherit, ba);
|
||||
applyUnderline(style, bInherit, ba);
|
||||
applyCrossout(style, bInherit, ba);
|
||||
applyChangeCase(style, bInherit, ba);
|
||||
}
|
||||
|
||||
// Remaining methods are private
|
||||
|
||||
/** <p>Apply font family.</p>
|
||||
* @param style the OOo style to read attributesfrom
|
||||
* @param bDecl true if declaration form is required
|
||||
* @param bInherit true if inherited properties should be used
|
||||
* @param ba the <code>BeforeAfter</code> to add LaTeX code to.
|
||||
*/
|
||||
private void applyNfssFamily(StyleWithProperties style, boolean bDecl, boolean bInherit, BeforeAfter ba, Context context) {
|
||||
// Note: if bDecl is true, nothing will be put in the "after" part of ba.
|
||||
if (style==null || bIgnoreFont) { return; }
|
||||
String sFontName=style.getProperty(XMLString.STYLE_FONT_NAME,bInherit);
|
||||
if (sFontName!=null){
|
||||
String sFamily = convertFontDeclaration(sFontName);
|
||||
if (sFamily==null) { return; }
|
||||
if (sFamily.equals(convertFontDeclaration(context.getFontName()))) { return; }
|
||||
if (bDecl) { ba.add("\\"+sFamily+"family",""); }
|
||||
else { ba.add("\\text"+sFamily+"{","}"); }
|
||||
} // TODO: Else read props directly from the style
|
||||
}
|
||||
|
||||
/** <p>Apply font series.</p>
|
||||
* @param style the OOo style to read attributesfrom
|
||||
* @param bDecl true if declaration form is required
|
||||
* @param bInherit true if inherited properties should be used
|
||||
* @param ba the <code>BeforeAfter</code> to add LaTeX code to.
|
||||
*/
|
||||
private void applyNfssSeries(StyleWithProperties style, boolean bDecl, boolean bInherit, BeforeAfter ba, Context context) {
|
||||
// Note: if bDecl is true, nothing will be put in the "after" part of ba.
|
||||
if (style!=null && !bIgnoreAll) {
|
||||
String sSeries = nfssSeries(style.getProperty(XMLString.FO_FONT_WEIGHT,bInherit));
|
||||
if (sSeries!=null) {
|
||||
// Temporary: Support text-attribute style maps for this particular case
|
||||
// TODO: Reimplement the CharStyleConverter to properly support this...
|
||||
if (!bDecl && "bf".equals(sSeries) && config.getTextAttributeStyleMap().contains("bold")) {
|
||||
ba.add(config.getTextAttributeStyleMap().getBefore("bold"),
|
||||
config.getTextAttributeStyleMap().getAfter("bold"));
|
||||
}
|
||||
else {
|
||||
if (style.isAutomatic()) { // optimize hard formatting
|
||||
if (sSeries.equals(nfssSeries(context.getFontWeight()))) { return; }
|
||||
if (context.getFontWeight()==null && sSeries.equals("md")) { return; }
|
||||
}
|
||||
if (bDecl) { ba.add("\\"+sSeries+"series",""); }
|
||||
else { ba.add("\\text"+sSeries+"{","}"); }
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/** <p>Apply font shape.</p>
|
||||
* @param style the OOo style to read attributesfrom
|
||||
* @param bDecl true if declaration form is required
|
||||
* @param bInherit true if inherited properties should be used
|
||||
* @param ba the <code>BeforeAfter</code> to add LaTeX code to.
|
||||
*/
|
||||
private void applyNfssShape(StyleWithProperties style, boolean bDecl, boolean bInherit, BeforeAfter ba, Context context) {
|
||||
// Note: if bDecl is true, nothing will be put in the "after" part of ba.
|
||||
if (style!=null && !bIgnoreAll) {
|
||||
String sVariant = style.getProperty(XMLString.FO_FONT_VARIANT, bInherit);
|
||||
String sStyle = style.getProperty(XMLString.FO_FONT_STYLE, bInherit);
|
||||
String sShape = nfssShape(sVariant,sStyle);
|
||||
if (sShape!=null) {
|
||||
// Temporary: Support text-attribute style maps for this particular case
|
||||
// TODO: Reimplement the CharStyleConverter to properly support this...
|
||||
if (!bDecl && "sc".equals(sShape) && config.getTextAttributeStyleMap().contains("small-caps")) {
|
||||
ba.add(config.getTextAttributeStyleMap().getBefore("small-caps"),
|
||||
config.getTextAttributeStyleMap().getAfter("small-caps"));
|
||||
}
|
||||
else if (!bDecl && "it".equals(sShape) && config.getTextAttributeStyleMap().contains("italic")) {
|
||||
ba.add(config.getTextAttributeStyleMap().getBefore("italic"),
|
||||
config.getTextAttributeStyleMap().getAfter("italic"));
|
||||
}
|
||||
else {
|
||||
if (style.isAutomatic()) { // optimize hard formatting
|
||||
if (sShape.equals(nfssShape(context.getFontVariant(),context.getFontStyle()))) return;
|
||||
if (context.getFontVariant()==null && context.getFontStyle()==null && sShape.equals("up")) return;
|
||||
}
|
||||
if (bDecl) ba.add("\\"+sShape+"shape","");
|
||||
else ba.add("\\text"+sShape+"{","}");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/** <p>Apply font size.</p>
|
||||
* @param style the OOo style to read attributesfrom
|
||||
* @param bDecl true if declaration form is required
|
||||
* @param bInherit true if inherited properties should be used
|
||||
* @param ba the <code>BeforeAfter</code> to add LaTeX code to.
|
||||
*/
|
||||
private void applyNfssSize(StyleWithProperties style, boolean bDecl, boolean bInherit, BeforeAfter ba, Context context) {
|
||||
// Note: if bDecl is true, nothing will be put in the "after" part of ba.
|
||||
if (style==null|| bIgnoreFontsize || (bIgnoreHardFontsize && style.isAutomatic())) { return; }
|
||||
if (style.getProperty(XMLString.FO_FONT_SIZE, bInherit)==null) { return; }
|
||||
String sSize = nfssSize(style.getAbsoluteProperty(XMLString.FO_FONT_SIZE));
|
||||
if (sSize==null) { return; }
|
||||
if (sSize.equals(nfssSize(context.getFontSize()))) { return; }
|
||||
if (bDecl) { ba.add(sSize,""); }
|
||||
else { ba.add("{"+sSize+" ","}"); }
|
||||
}
|
||||
|
||||
// Remaining methods are not context-sensitive
|
||||
|
||||
/** <p>Apply text position.</p>
|
||||
* @param style the OOo style to read attributesfrom
|
||||
* @param bInherit true if inherited properties should be used
|
||||
* @param ba the <code>BeforeAfter</code> to add LaTeX code to.
|
||||
*/
|
||||
private void applyTextPosition(StyleWithProperties style, boolean bInherit, BeforeAfter ba) {
|
||||
if (style!=null && !bIgnoreAll) {
|
||||
String s = textPosition(style.getProperty(XMLString.STYLE_TEXT_POSITION, bInherit));
|
||||
// Temporary: Support text-attribute style maps for this particular case
|
||||
// TODO: Reimplement the CharStyleConverter to properly support this...
|
||||
if (config.getTextAttributeStyleMap().contains("superscript") && "\\textsuperscript".equals(s)) {
|
||||
ba.add(config.getTextAttributeStyleMap().getBefore("superscript"),
|
||||
config.getTextAttributeStyleMap().getAfter("superscript"));
|
||||
}
|
||||
else if (config.getTextAttributeStyleMap().contains("subscript") && "\\textsubscript".equals(s)) {
|
||||
ba.add(config.getTextAttributeStyleMap().getBefore("subscript"),
|
||||
config.getTextAttributeStyleMap().getAfter("subscript"));
|
||||
}
|
||||
else if (s!=null) {
|
||||
ba.add(s+"{","}");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/** <p>Apply text underline.</p>
|
||||
* @param style the OOo style to read attributesfrom
|
||||
* @param bInherit true if inherited properties should be used
|
||||
* @param ba the <code>BeforeAfter</code> to add LaTeX code to.
|
||||
*/
|
||||
private void applyUnderline(StyleWithProperties style, boolean bInherit, BeforeAfter ba) {
|
||||
if (style==null || !bUseUlem) { return; }
|
||||
if (bIgnoreAll) { return; }
|
||||
String sTag = ofr.isOpenDocument() ?
|
||||
XMLString.STYLE_TEXT_UNDERLINE_STYLE :
|
||||
XMLString.STYLE_TEXT_UNDERLINE;
|
||||
String s = underline(style.getProperty(sTag, bInherit));
|
||||
if (s!=null) { bNeedUlem = true; ba.add(s+"{","}"); }
|
||||
}
|
||||
|
||||
/** <p>Apply text crossout.</p>
|
||||
* @param style the OOo style to read attributesfrom
|
||||
* @param bInherit true if inherited properties should be used
|
||||
* @param ba the <code>BeforeAfter</code> to add LaTeX code to.
|
||||
*/
|
||||
private void applyCrossout(StyleWithProperties style, boolean bInherit, BeforeAfter ba) {
|
||||
if (style==null || !bUseUlem) { return; }
|
||||
if (bIgnoreAll) { return; }
|
||||
String sTag = ofr.isOpenDocument() ?
|
||||
XMLString.STYLE_TEXT_LINE_THROUGH_STYLE :
|
||||
XMLString.STYLE_TEXT_CROSSING_OUT;
|
||||
String s = crossout(style.getProperty(sTag, bInherit));
|
||||
if (s!=null) { bNeedUlem = true; ba.add(s+"{","}"); }
|
||||
}
|
||||
|
||||
/** <p>Apply change case.</p>
|
||||
* @param style the OOo style to read attributesfrom
|
||||
* @param bInherit true if inherited properties should be used
|
||||
* @param ba the <code>BeforeAfter</code> to add LaTeX code to.
|
||||
*/
|
||||
private void applyChangeCase(StyleWithProperties style, boolean bInherit, BeforeAfter ba) {
|
||||
if (style==null) { return; }
|
||||
if (bIgnoreAll) { return; }
|
||||
String s = changeCase(style.getProperty(XMLString.FO_TEXT_TRANSFORM));
|
||||
if (s!=null) { ba.add(s+"{","}"); }
|
||||
}
|
||||
|
||||
/** <p>Convert font declarations to LaTeX.</p>
|
||||
* <p>It returns a generic LaTeX font family (rm, tt, sf).</p>
|
||||
* <p>It returns null if the font declaration doesn't exist.</p>
|
||||
* @param sName the name of the font declaration
|
||||
* @return <code>String</code> with a LaTeX generic fontfamily
|
||||
*/
|
||||
private String convertFontDeclaration(String sName) {
|
||||
FontDeclaration fd = ofr.getFontDeclaration(sName);
|
||||
if (fd==null) { return null; }
|
||||
if (!fontDecls.containsKey(sName)) {
|
||||
String sFontFamily = fd.getFontFamily();
|
||||
String sFontPitch = fd.getFontPitch();
|
||||
String sFontFamilyGeneric = fd.getFontFamilyGeneric();
|
||||
fontDecls.put(sName,nfssFamily(sFontFamily,sFontFamilyGeneric,sFontPitch));
|
||||
}
|
||||
return (String) fontDecls.get(sName);
|
||||
}
|
||||
|
||||
// The remaining methods are static helpers to convert single style properties
|
||||
|
||||
// Font change. These methods return the declaration form if the paramater
|
||||
// bDecl is true, and otherwise the command form
|
||||
|
||||
private static final String nfssFamily(String sFontFamily, String sFontFamilyGeneric,
|
||||
String sFontPitch){
|
||||
// Note: Defaults to rm
|
||||
// TODO: What about decorative, script, system?
|
||||
if ("fixed".equals(sFontPitch)) return "tt";
|
||||
else if ("modern".equals(sFontFamilyGeneric)) return "tt";
|
||||
else if ("swiss".equals(sFontFamilyGeneric)) return "sf";
|
||||
else return "rm";
|
||||
}
|
||||
|
||||
private static final String nfssSeries(String sFontWeight){
|
||||
if (sFontWeight==null) return null;
|
||||
if ("bold".equals(sFontWeight)) return "bf";
|
||||
else return "md";
|
||||
}
|
||||
|
||||
private static final String nfssShape(String sFontVariant, String sFontStyle){
|
||||
if (sFontVariant==null && sFontStyle==null) return null;
|
||||
if ("small-caps".equals(sFontVariant)) return "sc";
|
||||
else if ("italic".equals(sFontStyle)) return "it";
|
||||
else if ("oblique".equals(sFontStyle)) return "sl";
|
||||
else return "up";
|
||||
}
|
||||
|
||||
private static final String nfssSize(String sFontSize){
|
||||
if (sFontSize==null) return null;
|
||||
return "\\fontsize{"+sFontSize+"}{"+Misc.multiply("120%",sFontSize)+"}\\selectfont";
|
||||
}
|
||||
|
||||
// other character formatting
|
||||
|
||||
private final String textPosition(String sTextPosition){
|
||||
if (sTextPosition==null) return null;
|
||||
if (sTextPosition.startsWith("super")) return "\\textsuperscript";
|
||||
if (sTextPosition.startsWith("sub") || sTextPosition.startsWith("-")) {
|
||||
bNeedSubscript = true;
|
||||
return "\\textsubscript";
|
||||
}
|
||||
if (sTextPosition.startsWith("0%")) return null;
|
||||
return "\\textsuperscript";
|
||||
}
|
||||
|
||||
private static final String underline(String sUnderline) {
|
||||
if (sUnderline==null) { return null; }
|
||||
if (sUnderline.equals("none")) { return null; }
|
||||
if (sUnderline.indexOf("wave")>=0) { return "\\uwave"; }
|
||||
return "\\uline";
|
||||
}
|
||||
|
||||
private static final String crossout(String sCrossout) {
|
||||
if (sCrossout==null) { return null; }
|
||||
if (sCrossout.equals("X")) { return "\\xout"; }
|
||||
if (sCrossout.equals("slash")) { return "\\xout"; }
|
||||
return "\\sout";
|
||||
}
|
||||
|
||||
private static final String changeCase(String sTextTransform){
|
||||
if ("lowercase".equals(sTextTransform)) return "\\MakeLowercase";
|
||||
if ("uppercase".equals(sTextTransform)) return "\\MakeUppercase";
|
||||
return null;
|
||||
}
|
||||
|
||||
}
|
202
source/java/writer2latex/latex/ColorConverter.java
Normal file
202
source/java/writer2latex/latex/ColorConverter.java
Normal file
|
@ -0,0 +1,202 @@
|
|||
/************************************************************************
|
||||
*
|
||||
* ColorConverter.java
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License version 2.1, as published by the Free Software Foundation.
|
||||
*
|
||||
* This library 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
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston,
|
||||
* MA 02111-1307 USA
|
||||
*
|
||||
* Copyright: 2002-2008 by Henrik Just
|
||||
*
|
||||
* All Rights Reserved.
|
||||
*
|
||||
* Version 1.0 (2008-11-23)
|
||||
*
|
||||
*/
|
||||
|
||||
package writer2latex.latex;
|
||||
|
||||
import writer2latex.latex.util.BeforeAfter;
|
||||
import writer2latex.latex.util.Context;
|
||||
import writer2latex.office.OfficeReader;
|
||||
import writer2latex.office.StyleWithProperties;
|
||||
import writer2latex.office.XMLString;
|
||||
import writer2latex.util.Misc;
|
||||
|
||||
|
||||
/** This class converts color
|
||||
*/
|
||||
public class ColorConverter extends ConverterHelper {
|
||||
|
||||
private static final int RED = 0;
|
||||
private static final int GREEN = 1;
|
||||
private static final int BLUE = 2;
|
||||
|
||||
private boolean bUseColor;
|
||||
|
||||
/** <p>Constructs a new <code>CharStyleConverter</code>.</p>
|
||||
*/
|
||||
public ColorConverter(OfficeReader ofr, LaTeXConfig config, ConverterPalette palette) {
|
||||
super(ofr,config,palette);
|
||||
|
||||
// We use color if requested in the configuration, however ignoring
|
||||
// all formatting overrides this
|
||||
bUseColor = config.useColor() && config.formatting()>LaTeXConfig.IGNORE_ALL;
|
||||
}
|
||||
|
||||
public void appendDeclarations(LaTeXDocumentPortion pack, LaTeXDocumentPortion decl) {
|
||||
if (bUseColor) {
|
||||
pack.append("\\usepackage{color}").nl();
|
||||
}
|
||||
}
|
||||
|
||||
public void setNormalColor(String sColor, LaTeXDocumentPortion ldp) {
|
||||
if (bUseColor && sColor!=null) {
|
||||
ldp.append("\\renewcommand\\normalcolor{\\color")
|
||||
.append(color(sColor)).append("}").nl();
|
||||
}
|
||||
}
|
||||
|
||||
public void applyNormalColor(BeforeAfter ba) {
|
||||
if (bUseColor) { ba.add("\\normalcolor",""); }
|
||||
}
|
||||
|
||||
/** <p>Apply foreground color.</p>
|
||||
* @param style the OOo style to read attributesfrom
|
||||
* @param bDecl true if declaration form is required
|
||||
* @param bInherit true if inherited properties should be used
|
||||
* @param ba the <code>BeforeAfter</code> to add LaTeX code to.
|
||||
* @param context the current context
|
||||
*/
|
||||
public void applyColor(StyleWithProperties style, boolean bDecl, boolean bInherit, BeforeAfter ba, Context context) {
|
||||
// Note: if bDecl is true, nothing will be put in the "after" part of ba.
|
||||
if (bUseColor && style!=null) {
|
||||
String sColor = style.getProperty(XMLString.FO_COLOR,bInherit);
|
||||
if (sColor!=null) {
|
||||
if (!sColor.equals(context.getFontColor())) {
|
||||
// Convert color if it differs from the current font color
|
||||
context.setFontColor(sColor);
|
||||
applyColor(sColor, bDecl, ba, context);
|
||||
}
|
||||
}
|
||||
else {
|
||||
// No color; maybe automatic color?
|
||||
String sAutomatic = style.getProperty(XMLString.STYLE_USE_WINDOW_FONT_COLOR,bInherit);
|
||||
if (sAutomatic==null && bInherit) {
|
||||
// We may need to inherit this property from the default style
|
||||
StyleWithProperties defaultStyle = ofr.getDefaultParStyle();
|
||||
if (defaultStyle!=null) {
|
||||
sAutomatic = defaultStyle.getProperty(XMLString.STYLE_USE_WINDOW_FONT_COLOR,bInherit);
|
||||
}
|
||||
}
|
||||
if ("true".equals(sAutomatic)) {
|
||||
// Automatic color based on background
|
||||
if (context.getBgColor()!=null) { applyAutomaticColor(ba,bDecl,context); }
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/** <p>Apply a specific foreground color.</p>
|
||||
* @param sColor the rgb color to use
|
||||
* @param bDecl true if declaration form is required
|
||||
* @param ba the <code>BeforeAfter</code> to add LaTeX code to.
|
||||
*/
|
||||
public void applyColor(String sColor, boolean bDecl, BeforeAfter ba, Context context) {
|
||||
// Note: if bDecl is true, nothing will be put in the "after" part of ba.
|
||||
if (bUseColor && sColor!=null) {
|
||||
// If there's a background color, allow all colors
|
||||
String s = context.getBgColor()!=null ? fullcolor(sColor) : color(sColor);
|
||||
if (s!=null) {
|
||||
if (bDecl) { ba.add("\\color"+s,""); }
|
||||
else { ba.add("\\textcolor"+s+"{","}"); }
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void applyBgColor(String sCommand, String sColor, BeforeAfter ba, Context context) {
|
||||
// Note: Will only fill "before" part of ba
|
||||
if (sColor!=null && !"transparent".equals(sColor)) {
|
||||
String s = fullcolor(sColor);
|
||||
if (bUseColor && s!=null) {
|
||||
context.setBgColor(sColor);
|
||||
ba.add(sCommand+s,"");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void applyAutomaticColor(BeforeAfter ba, boolean bDecl, Context context) {
|
||||
String s = automaticcolor(context.getBgColor());
|
||||
if (s!=null) {
|
||||
if (bDecl) { ba.add("\\color"+s,""); }
|
||||
else { ba.add("\\textcolor"+s+"{","}"); }
|
||||
}
|
||||
}
|
||||
|
||||
private static final String automaticcolor(String sBgColor) {
|
||||
if (sBgColor!=null && sBgColor.length()==7) {
|
||||
float[] rgb = getRgb(sBgColor);
|
||||
if (rgb[RED]+rgb[GREEN]+rgb[BLUE]<0.6) {
|
||||
// Dark background
|
||||
return "{white}";
|
||||
}
|
||||
}
|
||||
return "{black}";
|
||||
}
|
||||
|
||||
private static final String color(String sColor){
|
||||
if ("#000000".equalsIgnoreCase(sColor)) { return "{black}"; }
|
||||
else if ("#ff0000".equalsIgnoreCase(sColor)) { return "{red}"; }
|
||||
else if ("#00ff00".equalsIgnoreCase(sColor)) { return "{green}"; }
|
||||
else if ("#0000ff".equalsIgnoreCase(sColor)) { return "{blue}"; }
|
||||
else if ("#ffff00".equalsIgnoreCase(sColor)) { return "{yellow}"; }
|
||||
else if ("#ff00ff".equalsIgnoreCase(sColor)) { return "{magenta}"; }
|
||||
else if ("#00ffff".equalsIgnoreCase(sColor)) { return "{cyan}"; }
|
||||
//no white, since we don't have background colors:
|
||||
//else if ("#ffffff".equalsIgnoreCase(sColor)) { return "{white}"; }
|
||||
else {
|
||||
if (sColor==null || sColor.length()!=7) return null;
|
||||
float[] rgb = getRgb(sColor);
|
||||
// avoid very bright colors (since we don't have background colors):
|
||||
if (rgb[RED]+rgb[GREEN]+rgb[BLUE]>2.7) { return "{black}"; }
|
||||
else { return "[rgb]{"+rgb[RED]+","+rgb[GREEN]+","+rgb[BLUE]+"}"; }
|
||||
}
|
||||
}
|
||||
|
||||
private static final String fullcolor(String sColor){
|
||||
if ("#000000".equalsIgnoreCase(sColor)) { return "{black}"; }
|
||||
else if ("#ff0000".equalsIgnoreCase(sColor)) { return "{red}"; }
|
||||
else if ("#00ff00".equalsIgnoreCase(sColor)) { return "{green}"; }
|
||||
else if ("#0000ff".equalsIgnoreCase(sColor)) { return "{blue}"; }
|
||||
else if ("#ffff00".equalsIgnoreCase(sColor)) { return "{yellow}"; }
|
||||
else if ("#ff00ff".equalsIgnoreCase(sColor)) { return "{magenta}"; }
|
||||
else if ("#00ffff".equalsIgnoreCase(sColor)) { return "{cyan}"; }
|
||||
else if ("#ffffff".equalsIgnoreCase(sColor)) { return "{white}"; }
|
||||
else {
|
||||
// This could mean transparent:
|
||||
if (sColor==null || sColor.length()!=7) return null;
|
||||
float[] rgb = getRgb(sColor);
|
||||
return "[rgb]{"+rgb[RED]+","+rgb[GREEN]+","+rgb[BLUE]+"}";
|
||||
}
|
||||
}
|
||||
|
||||
private static final float[] getRgb(String sColor) {
|
||||
float[] rgb = new float[3];
|
||||
rgb[RED] = (float)Misc.getIntegerFromHex(sColor.substring(1,3),0)/255;
|
||||
rgb[GREEN] = (float)Misc.getIntegerFromHex(sColor.substring(3,5),0)/255;
|
||||
rgb[BLUE] = (float)Misc.getIntegerFromHex(sColor.substring(5,7),0)/255;
|
||||
return rgb;
|
||||
}
|
||||
|
||||
|
||||
}
|
43
source/java/writer2latex/latex/ContentHandlingOption.java
Normal file
43
source/java/writer2latex/latex/ContentHandlingOption.java
Normal file
|
@ -0,0 +1,43 @@
|
|||
/************************************************************************
|
||||
*
|
||||
* ContentHandlingOption.java
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License version 2.1, as published by the Free Software Foundation.
|
||||
*
|
||||
* This library 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
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston,
|
||||
* MA 02111-1307 USA
|
||||
*
|
||||
* Copyright: 2002-2008 by Henrik Just
|
||||
*
|
||||
* All Rights Reserved.
|
||||
*
|
||||
* Version 1.0 (2008-09-08)
|
||||
*
|
||||
*/
|
||||
|
||||
package writer2latex.latex;
|
||||
|
||||
import writer2latex.base.IntegerOption;
|
||||
|
||||
public class ContentHandlingOption extends IntegerOption {
|
||||
public ContentHandlingOption(String sName, String sDefaultValue) {
|
||||
super(sName,sDefaultValue);
|
||||
}
|
||||
|
||||
public void setString(String sValue) {
|
||||
super.setString(sValue);
|
||||
if ("accept".equals(sValue)) nValue = LaTeXConfig.ACCEPT;
|
||||
else if ("ignore".equals(sValue)) nValue = LaTeXConfig.IGNORE;
|
||||
else if ("warning".equals(sValue)) nValue = LaTeXConfig.WARNING;
|
||||
else if ("error".equals(sValue)) nValue = LaTeXConfig.ERROR;
|
||||
}
|
||||
}
|
49
source/java/writer2latex/latex/ConverterHelper.java
Normal file
49
source/java/writer2latex/latex/ConverterHelper.java
Normal file
|
@ -0,0 +1,49 @@
|
|||
/************************************************************************
|
||||
*
|
||||
* ConverterHelper.java
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License version 2.1, as published by the Free Software Foundation.
|
||||
*
|
||||
* This library 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
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston,
|
||||
* MA 02111-1307 USA
|
||||
*
|
||||
* Copyright: 2002-2008 by Henrik Just
|
||||
*
|
||||
* All Rights Reserved.
|
||||
*
|
||||
* Version 1.0 (2008-09-08)
|
||||
*
|
||||
*/
|
||||
|
||||
package writer2latex.latex;
|
||||
|
||||
import writer2latex.office.OfficeReader;
|
||||
|
||||
/**
|
||||
* <p>This is an abstract superclass for converter helpers.</p>
|
||||
*/
|
||||
public abstract class ConverterHelper {
|
||||
|
||||
protected OfficeReader ofr;
|
||||
protected LaTeXConfig config;
|
||||
protected ConverterPalette palette;
|
||||
|
||||
protected ConverterHelper(OfficeReader ofr, LaTeXConfig config, ConverterPalette palette) {
|
||||
this.ofr = ofr;
|
||||
this.config = config;
|
||||
this.palette = palette;
|
||||
}
|
||||
|
||||
public void appendDeclarations(LaTeXDocumentPortion pack, LaTeXDocumentPortion decl) {
|
||||
}
|
||||
|
||||
}
|
303
source/java/writer2latex/latex/ConverterPalette.java
Normal file
303
source/java/writer2latex/latex/ConverterPalette.java
Normal file
|
@ -0,0 +1,303 @@
|
|||
/************************************************************************
|
||||
*
|
||||
* ConverterPalette.java
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License version 2.1, as published by the Free Software Foundation.
|
||||
*
|
||||
* This library 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
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston,
|
||||
* MA 02111-1307 USA
|
||||
*
|
||||
* Copyright: 2002-2009 by Henrik Just
|
||||
*
|
||||
* All Rights Reserved.
|
||||
*
|
||||
* Version 1.0 (2009-02-17)
|
||||
*
|
||||
*/
|
||||
|
||||
package writer2latex.latex;
|
||||
|
||||
import org.w3c.dom.Element;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.LinkedList;
|
||||
|
||||
import writer2latex.api.Config;
|
||||
import writer2latex.api.ConverterFactory;
|
||||
//import writer2latex.api.ConverterResult;
|
||||
import writer2latex.base.ConverterBase;
|
||||
import writer2latex.latex.i18n.ClassicI18n;
|
||||
import writer2latex.latex.i18n.I18n;
|
||||
import writer2latex.latex.i18n.XeTeXI18n;
|
||||
import writer2latex.latex.util.Context;
|
||||
import writer2latex.latex.util.Info;
|
||||
import writer2latex.util.CSVList;
|
||||
import writer2latex.util.ExportNameCollection;
|
||||
import writer2latex.util.Misc;
|
||||
import writer2latex.office.MIMETypes;
|
||||
import writer2latex.office.StyleWithProperties;
|
||||
import writer2latex.office.XMLString;
|
||||
|
||||
/**
|
||||
* <p>This class converts a Writer XML file to a LaTeX file<.</p>
|
||||
*/
|
||||
public final class ConverterPalette extends ConverterBase {
|
||||
|
||||
// Configuration
|
||||
private LaTeXConfig config;
|
||||
|
||||
public Config getConfig() { return config; }
|
||||
|
||||
// The main outfile
|
||||
private LaTeXDocument texDoc;
|
||||
|
||||
// Various data used in conversion
|
||||
private Context mainContext; // main context
|
||||
private CSVList globalOptions; // global options
|
||||
|
||||
// The helpers (the "colors" of the palette)
|
||||
private I18n i18n;
|
||||
private ColorConverter colorCv;
|
||||
private CharStyleConverter charSc;
|
||||
private ListStyleConverter listSc;
|
||||
private PageStyleConverter pageSc;
|
||||
private BlockConverter blockCv;
|
||||
private ParConverter parCv;
|
||||
private HeadingConverter headingCv;
|
||||
private IndexConverter indexCv;
|
||||
private BibConverter bibCv;
|
||||
private SectionConverter sectionCv;
|
||||
private TableConverter tableCv;
|
||||
private NoteConverter noteCv;
|
||||
private CaptionConverter captionCv;
|
||||
private InlineConverter inlineCv;
|
||||
private FieldConverter fieldCv;
|
||||
private DrawConverter drawCv;
|
||||
private MathmlConverter mathmlCv;
|
||||
private Info info;
|
||||
|
||||
// Constructor
|
||||
public ConverterPalette() {
|
||||
super();
|
||||
config = new LaTeXConfig();
|
||||
}
|
||||
|
||||
// Accessor methods for data
|
||||
|
||||
public String getOutFileName() { return sTargetFileName; }
|
||||
|
||||
public Context getMainContext() { return mainContext; }
|
||||
|
||||
public void addGlobalOption(String sOption) {
|
||||
globalOptions.addValue(sOption);
|
||||
}
|
||||
|
||||
// Accessor methods for helpers
|
||||
public I18n getI18n() { return i18n; }
|
||||
public ColorConverter getColorCv() { return colorCv; }
|
||||
public CharStyleConverter getCharSc() { return charSc; }
|
||||
public ListStyleConverter getListSc() { return listSc; }
|
||||
public PageStyleConverter getPageSc() { return pageSc; }
|
||||
public BlockConverter getBlockCv() { return blockCv; }
|
||||
public ParConverter getParCv() { return parCv; }
|
||||
public HeadingConverter getHeadingCv() { return headingCv; }
|
||||
public IndexConverter getIndexCv() { return indexCv; }
|
||||
public BibConverter getBibCv() { return bibCv; }
|
||||
public SectionConverter getSectionCv() { return sectionCv; }
|
||||
public TableConverter getTableCv() { return tableCv; }
|
||||
public NoteConverter getNoteCv() { return noteCv; }
|
||||
public CaptionConverter getCaptionCv() { return captionCv; }
|
||||
public InlineConverter getInlineCv() { return inlineCv; }
|
||||
public FieldConverter getFieldCv() { return fieldCv; }
|
||||
public DrawConverter getDrawCv() { return drawCv; }
|
||||
public MathmlConverter getMathmlCv() { return mathmlCv; }
|
||||
public Info getInfo() { return info; }
|
||||
|
||||
|
||||
// fill out inner converter method
|
||||
public void convertInner() throws IOException {
|
||||
sTargetFileName = Misc.trimDocumentName(sTargetFileName,".tex");
|
||||
imageLoader.setOutFileName(new ExportNameCollection(true).getExportName(sTargetFileName));
|
||||
|
||||
imageLoader.setUseSubdir(config.saveImagesInSubdir());
|
||||
|
||||
// Set graphics formats depending on backend
|
||||
if (config.getBackend()==LaTeXConfig.PDFTEX || config.getBackend()==LaTeXConfig.XETEX) {
|
||||
imageLoader.setDefaultFormat(MIMETypes.PNG);
|
||||
imageLoader.setDefaultVectorFormat(MIMETypes.PDF);
|
||||
imageLoader.addAcceptedFormat(MIMETypes.JPEG);
|
||||
}
|
||||
else if (config.getBackend()==LaTeXConfig.DVIPS) {
|
||||
imageLoader.setDefaultFormat(MIMETypes.EPS);
|
||||
}
|
||||
// Other values: keep original format
|
||||
|
||||
// Inject user sequence names for tables and figures into OfficeReader
|
||||
if (config.getTableSequenceName().length()>0) {
|
||||
ofr.addTableSequenceName(config.getTableSequenceName());
|
||||
}
|
||||
if (config.getFigureSequenceName().length()>0) {
|
||||
ofr.addFigureSequenceName(config.getFigureSequenceName());
|
||||
}
|
||||
|
||||
// Create helpers
|
||||
if (config.getBackend()!=LaTeXConfig.XETEX) {
|
||||
i18n = new ClassicI18n(ofr,config,this);
|
||||
}
|
||||
else {
|
||||
i18n = new XeTeXI18n(ofr,config,this);
|
||||
}
|
||||
colorCv = new ColorConverter(ofr,config,this);
|
||||
charSc = new CharStyleConverter(ofr,config,this);
|
||||
listSc = new ListStyleConverter(ofr,config,this);
|
||||
pageSc = new PageStyleConverter(ofr,config,this);
|
||||
blockCv = new BlockConverter(ofr,config,this);
|
||||
parCv = new ParConverter(ofr,config,this);
|
||||
headingCv = new HeadingConverter(ofr,config,this);
|
||||
indexCv = new IndexConverter(ofr,config,this);
|
||||
bibCv = new BibConverter(ofr,config,this);
|
||||
sectionCv = new SectionConverter(ofr,config,this);
|
||||
tableCv = new TableConverter(ofr,config,this);
|
||||
noteCv = new NoteConverter(ofr,config,this);
|
||||
captionCv = new CaptionConverter(ofr,config,this);
|
||||
inlineCv = new InlineConverter(ofr,config,this);
|
||||
fieldCv = new FieldConverter(ofr,config,this);
|
||||
drawCv = new DrawConverter(ofr,config,this);
|
||||
mathmlCv = new MathmlConverter(ofr,config,this);
|
||||
info = new Info(ofr,config,this);
|
||||
|
||||
// Create master document and add this
|
||||
this.texDoc = new LaTeXDocument(sTargetFileName,config.getWrapLinesAfter());
|
||||
if (config.getBackend()!=LaTeXConfig.XETEX) {
|
||||
texDoc.setEncoding(ClassicI18n.writeJavaEncoding(config.getInputencoding()));
|
||||
}
|
||||
else {
|
||||
texDoc.setEncoding("UTF-8");
|
||||
|
||||
}
|
||||
convertData.addDocument(texDoc);
|
||||
|
||||
// Create other data
|
||||
globalOptions = new CSVList(',');
|
||||
|
||||
// Setup context.
|
||||
// The default language is specified in the default paragraph style:
|
||||
mainContext = new Context();
|
||||
mainContext.resetFormattingFromStyle(ofr.getDefaultParStyle());
|
||||
mainContext.setInMulticols(pageSc.isTwocolumn());
|
||||
|
||||
// Create main LaTeXDocumentPortions
|
||||
LaTeXDocumentPortion packages = new LaTeXDocumentPortion(false);
|
||||
LaTeXDocumentPortion declarations = new LaTeXDocumentPortion(false);
|
||||
LaTeXDocumentPortion body = new LaTeXDocumentPortion(true);
|
||||
|
||||
// Traverse the content
|
||||
Element content = ofr.getContent();
|
||||
blockCv.traverseBlockText(content,body,mainContext);
|
||||
noteCv.insertEndnotes(body);
|
||||
|
||||
// Add declarations from our helpers
|
||||
i18n.appendDeclarations(packages,declarations);
|
||||
colorCv.appendDeclarations(packages,declarations);
|
||||
charSc.appendDeclarations(packages,declarations);
|
||||
headingCv.appendDeclarations(packages,declarations);
|
||||
parCv.appendDeclarations(packages,declarations);
|
||||
listSc.appendDeclarations(packages,declarations);
|
||||
pageSc.appendDeclarations(packages,declarations);
|
||||
blockCv.appendDeclarations(packages,declarations);
|
||||
indexCv.appendDeclarations(packages,declarations);
|
||||
bibCv.appendDeclarations(packages,declarations);
|
||||
sectionCv.appendDeclarations(packages,declarations);
|
||||
tableCv.appendDeclarations(packages,declarations);
|
||||
noteCv.appendDeclarations(packages,declarations);
|
||||
captionCv.appendDeclarations(packages,declarations);
|
||||
inlineCv.appendDeclarations(packages,declarations);
|
||||
fieldCv.appendDeclarations(packages,declarations);
|
||||
drawCv.appendDeclarations(packages,declarations);
|
||||
mathmlCv.appendDeclarations(packages,declarations);
|
||||
|
||||
// Add custom preamble
|
||||
LinkedList customPreamble = config.getCustomPreamble();
|
||||
int nCPLen = customPreamble.size();
|
||||
for (int i=0; i<nCPLen; i++) {
|
||||
declarations.append( (String) customPreamble.get(i) ).nl();
|
||||
}
|
||||
|
||||
// Set \title, \author and \date (for \maketitle)
|
||||
createMeta("title",metaData.getTitle(),declarations);
|
||||
if (config.metadata()) {
|
||||
createMeta("author",metaData.getCreator(),declarations);
|
||||
// According to the spec, the date has the format YYYY-MM-DDThh:mm:ss
|
||||
String sDate = metaData.getDate();
|
||||
if (sDate.length()==19 && sDate.charAt(10)=='T') {
|
||||
sDate = sDate.substring(0,10);
|
||||
}
|
||||
createMeta("date",sDate,declarations);
|
||||
}
|
||||
|
||||
// Create options for documentclass
|
||||
if (config.formatting()>=LaTeXConfig.CONVERT_MOST) {
|
||||
StyleWithProperties dpStyle = ofr.getDefaultParStyle();
|
||||
if (dpStyle!=null) {
|
||||
String s = dpStyle.getProperty(XMLString.FO_FONT_SIZE);
|
||||
if ("10pt".equals(s)) { globalOptions.addValue("10pt"); }
|
||||
if ("11pt".equals(s)) { globalOptions.addValue("11pt"); }
|
||||
if ("12pt".equals(s)) { globalOptions.addValue("12pt"); }
|
||||
}
|
||||
}
|
||||
|
||||
// Temp solution. TODO: Fix when new CSVList is implemented
|
||||
if (config.getGlobalOptions().length()>0) {
|
||||
globalOptions.addValue(config.getGlobalOptions());
|
||||
}
|
||||
|
||||
// Assemble the document
|
||||
LaTeXDocumentPortion result = texDoc.getContents();
|
||||
|
||||
if (!config.noPreamble()) {
|
||||
// Create document class declaration
|
||||
result.append("% This file was converted to LaTeX by Writer2LaTeX ver. "+ConverterFactory.getVersion()).nl()
|
||||
.append("% see http://www.hj-gym.dk/~hj/writer2latex for more info").nl();
|
||||
result.append("\\documentclass");
|
||||
if (!globalOptions.isEmpty()) {
|
||||
result.append("[").append(globalOptions.toString()).append("]");
|
||||
}
|
||||
result.append("{").append(config.getDocumentclass()).append("}").nl();
|
||||
|
||||
result.append(packages)
|
||||
.append(declarations)
|
||||
.append("\\begin{document}").nl();
|
||||
}
|
||||
|
||||
result.append(body);
|
||||
|
||||
if (!config.noPreamble()) {
|
||||
result.append("\\end{document}").nl();
|
||||
}
|
||||
else {
|
||||
result.append("\\endinput").nl();
|
||||
}
|
||||
|
||||
// Add BibTeX document if there's any bibliographic data
|
||||
if (bibCv.getBibTeXDocument()!=null) {
|
||||
convertData.addDocument(bibCv.getBibTeXDocument());
|
||||
}
|
||||
}
|
||||
|
||||
private void createMeta(String sName, String sValue,LaTeXDocumentPortion ldp) {
|
||||
if (sValue==null) { return; }
|
||||
// Meta data is assumed to be in the default language:
|
||||
ldp.append("\\"+sName+"{"+i18n.convert(sValue,false,mainContext.getLang())+"}").nl();
|
||||
}
|
||||
|
||||
|
||||
}
|
496
source/java/writer2latex/latex/DrawConverter.java
Normal file
496
source/java/writer2latex/latex/DrawConverter.java
Normal file
|
@ -0,0 +1,496 @@
|
|||
/************************************************************************
|
||||
*
|
||||
* DrawConverter.java
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License version 2.1, as published by the Free Software Foundation.
|
||||
*
|
||||
* This library 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
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston,
|
||||
* MA 02111-1307 USA
|
||||
*
|
||||
* Copyright: 2002-2009 by Henrik Just
|
||||
*
|
||||
* All Rights Reserved.
|
||||
*
|
||||
* Version 1.0 (2009-02-17)
|
||||
*
|
||||
*/
|
||||
|
||||
package writer2latex.latex;
|
||||
|
||||
import java.util.LinkedList;
|
||||
import java.util.Stack;
|
||||
|
||||
import org.w3c.dom.Document;
|
||||
import org.w3c.dom.Element;
|
||||
//import org.w3c.dom.Node;
|
||||
|
||||
import writer2latex.xmerge.EmbeddedObject;
|
||||
import writer2latex.xmerge.EmbeddedXMLObject;
|
||||
|
||||
import writer2latex.latex.util.BeforeAfter;
|
||||
import writer2latex.latex.util.Context;
|
||||
//import writer2latex.office.ImageLoader;
|
||||
import writer2latex.office.MIMETypes;
|
||||
import writer2latex.office.OfficeReader;
|
||||
import writer2latex.office.StyleWithProperties;
|
||||
import writer2latex.office.XMLString;
|
||||
import writer2latex.util.CSVList;
|
||||
import writer2latex.util.Misc;
|
||||
import writer2latex.xmerge.BinaryGraphicsDocument;
|
||||
|
||||
/**
|
||||
* <p>This class handles draw elements.</p>
|
||||
*/
|
||||
public class DrawConverter extends ConverterHelper {
|
||||
|
||||
private boolean bNeedGraphicx = false;
|
||||
private boolean bNeedOOoLaTeXPreamble = false;
|
||||
|
||||
// Keep track of floating frames (images, textboxes...)
|
||||
private Stack floatingFramesStack = new Stack();
|
||||
|
||||
private Element getFrame(Element onode) {
|
||||
if (ofr.isOpenDocument()) return (Element) onode.getParentNode();
|
||||
else return onode;
|
||||
}
|
||||
|
||||
public DrawConverter(OfficeReader ofr, LaTeXConfig config, ConverterPalette palette) {
|
||||
super(ofr,config,palette);
|
||||
floatingFramesStack.push(new LinkedList());
|
||||
}
|
||||
|
||||
public void appendDeclarations(LaTeXDocumentPortion pack, LaTeXDocumentPortion decl) {
|
||||
if (bNeedGraphicx) {
|
||||
pack.append("\\usepackage");
|
||||
if (config.getBackend()==LaTeXConfig.PDFTEX) pack.append("[pdftex]");
|
||||
//else if (config.getBackend()==LaTeXConfig.XETEX) pack.append("[xetex]");
|
||||
else if (config.getBackend()==LaTeXConfig.DVIPS) pack.append("[dvips]");
|
||||
pack.append("{graphicx}").nl();
|
||||
}
|
||||
if (bNeedOOoLaTeXPreamble) {
|
||||
// The preamble may be stored in the description
|
||||
String sDescription = palette.getMetaData().getDescription();
|
||||
int nStart = sDescription.indexOf("%%% OOoLatex Preamble %%%%%%%%%%%%%%");
|
||||
int nEnd = sDescription.indexOf("%%% End OOoLatex Preamble %%%%%%%%%%%%");
|
||||
if (nStart>-1 && nEnd>nStart) {
|
||||
decl.append("% OOoLaTeX preamble").nl()
|
||||
.append(sDescription.substring(nStart+37,nEnd));
|
||||
}
|
||||
// TODO: Otherwise try the user settings...
|
||||
}
|
||||
}
|
||||
|
||||
public void handleCaption(Element node, LaTeXDocumentPortion ldp, Context oc) {
|
||||
// Floating frames should be positioned *above* the label, hence
|
||||
// we use a separate ldp for the paragraphs and add this later
|
||||
LaTeXDocumentPortion capLdp = new LaTeXDocumentPortion(true);
|
||||
|
||||
// Convert the caption
|
||||
if (oc.isInFigureFloat()) { // float
|
||||
capLdp.append("\\caption");
|
||||
palette.getCaptionCv().handleCaptionBody(node,capLdp,oc,false);
|
||||
}
|
||||
else { // nonfloat
|
||||
capLdp.append("\\captionof{figure}");
|
||||
palette.getCaptionCv().handleCaptionBody(node,capLdp,oc,true);
|
||||
}
|
||||
|
||||
flushFloatingFrames(ldp,oc);
|
||||
ldp.append(capLdp);
|
||||
}
|
||||
|
||||
public void handleDrawElement(Element node, LaTeXDocumentPortion ldp, Context oc) {
|
||||
// node must be an elment in the draw namespace
|
||||
String sName = node.getTagName();
|
||||
if (sName.equals(XMLString.DRAW_OBJECT)) {
|
||||
handleDrawObject(node,ldp,oc);
|
||||
}
|
||||
else if (sName.equals(XMLString.DRAW_OBJECT_OLE)) {
|
||||
handleDrawObject(node,ldp,oc);
|
||||
}
|
||||
else if ((!oc.isInHeaderFooter()) && sName.equals(XMLString.DRAW_IMAGE)) {
|
||||
handleDrawImage(node,ldp,oc);
|
||||
}
|
||||
else if ((!oc.isInHeaderFooter()) && sName.equals(XMLString.DRAW_TEXT_BOX)) {
|
||||
handleDrawTextBox(node,ldp,oc);
|
||||
}
|
||||
else if (sName.equals(XMLString.DRAW_A)) {
|
||||
// we handle this like text:a
|
||||
palette.getFieldCv().handleAnchor(node,ldp,oc);
|
||||
}
|
||||
else if (sName.equals(XMLString.DRAW_FRAME)) {
|
||||
// OpenDocument: Get the actual draw element in the frame
|
||||
handleDrawElement(Misc.getFirstChildElement(node),ldp,oc);
|
||||
}
|
||||
else {
|
||||
// Other drawing objects (eg. shapes) are currently not supported
|
||||
ldp.append("[Warning: Draw object ignored]");
|
||||
}
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------
|
||||
// handle draw:object elements (OOo objects such as Chart, Math,...)
|
||||
|
||||
private void handleDrawObject(Element node, LaTeXDocumentPortion ldp, Context oc) {
|
||||
String sHref = Misc.getAttribute(node,XMLString.XLINK_HREF);
|
||||
|
||||
if (sHref!=null) { // Embedded object in package or linked object
|
||||
if (ofr.isInPackage(sHref)) { // Embedded object in package
|
||||
if (sHref.startsWith("#")) { sHref=sHref.substring(1); }
|
||||
if (sHref.startsWith("./")) { sHref=sHref.substring(2); }
|
||||
EmbeddedObject object = palette.getEmbeddedObject(sHref);
|
||||
if (object!=null) {
|
||||
if (MIMETypes.MATH.equals(object.getType()) || MIMETypes.ODF.equals(object.getType())) { // Formula!
|
||||
try {
|
||||
Document settings = ((EmbeddedXMLObject) object).getSettingsDOM();
|
||||
Document formuladoc = ((EmbeddedXMLObject) object).getContentDOM();
|
||||
Element formula = Misc.getChildByTagName(formuladoc,XMLString.MATH_MATH);
|
||||
ldp.append(" $")
|
||||
.append(palette.getMathmlCv().convert(settings,formula))
|
||||
.append("$");
|
||||
if (Character.isLetterOrDigit(OfficeReader.getNextChar(node))) { ldp.append(" "); }
|
||||
}
|
||||
catch (org.xml.sax.SAXException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
catch (java.io.IOException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
else { // unsupported object
|
||||
boolean bIgnore = true;
|
||||
if (ofr.isOpenDocument()) { // look for replacement image
|
||||
Element replacementImage = Misc.getChildByTagName(getFrame(node),XMLString.DRAW_IMAGE);
|
||||
if (replacementImage!=null) {
|
||||
handleDrawImage(replacementImage,ldp,oc);
|
||||
bIgnore = false;
|
||||
}
|
||||
}
|
||||
if (bIgnore) {
|
||||
ldp.append("[Warning: object ignored]");
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
else { // flat xml, object is contained in node
|
||||
Element formula = Misc.getChildByTagName(node,XMLString.MATH_MATH);
|
||||
if (formula!=null) {
|
||||
ldp.append(" $")
|
||||
.append(palette.getMathmlCv().convert(null,formula))
|
||||
.append("$");
|
||||
if (Character.isLetterOrDigit(OfficeReader.getNextChar(node))) { ldp.append(" "); }
|
||||
}
|
||||
else { // unsupported object
|
||||
boolean bIgnore = true;
|
||||
if (ofr.isOpenDocument()) { // look for replacement image
|
||||
Element replacementImage = Misc.getChildByTagName(getFrame(node),XMLString.DRAW_IMAGE);
|
||||
if (replacementImage!=null) {
|
||||
handleDrawImage(replacementImage,ldp,oc);
|
||||
bIgnore = false;
|
||||
}
|
||||
}
|
||||
if (bIgnore) {
|
||||
ldp.append("[Warning: object ignored]");
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------
|
||||
// Create float environment
|
||||
private void applyFigureFloat(BeforeAfter ba, Context oc) {
|
||||
// todo: check context...
|
||||
if (config.floatFigures() && !oc.isInFrame() && !oc.isInTable()) {
|
||||
if (oc.isInMulticols()) {
|
||||
ba.add("\\begin{figure*}","\\end{figure*}\n");
|
||||
}
|
||||
else {
|
||||
ba.add("\\begin{figure}","\\end{figure}\n");
|
||||
}
|
||||
if (config.getFloatOptions().length()>0) {
|
||||
ba.add("["+config.getFloatOptions()+"]","");
|
||||
}
|
||||
ba.add("\n","");
|
||||
oc.setInFigureFloat(true);
|
||||
}
|
||||
if (!oc.isInFrame() && config.alignFrames()) {
|
||||
// Avoid nesting center environment
|
||||
ba.add("\\begin{center}\n","\n\\end{center}\n");
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------
|
||||
// Handle draw:image elements
|
||||
|
||||
private void handleDrawImage(Element node, LaTeXDocumentPortion ldp, Context oc) {
|
||||
// Include graphics if allowed by the configuration
|
||||
switch (config.imageContent()) {
|
||||
case LaTeXConfig.IGNORE:
|
||||
// Ignore graphics silently
|
||||
return;
|
||||
case LaTeXConfig.WARNING:
|
||||
System.err.println("Warning: Images are not allowed");
|
||||
return;
|
||||
case LaTeXConfig.ERROR:
|
||||
ldp.append("% Error in document: An image was ignored");
|
||||
return;
|
||||
}
|
||||
|
||||
Element frame = getFrame(node);
|
||||
//String sName = frame.getAttribute(XMLString.DRAW_NAME);
|
||||
palette.getFieldCv().addTarget(frame,"|graphics",ldp);
|
||||
String sAnchor = frame.getAttribute(XMLString.TEXT_ANCHOR_TYPE);
|
||||
|
||||
// TODO: Recognize Jex equations (needs further testing of Jex)
|
||||
/*Element desc = Misc.getChildByTagName(frame,XMLString.SVG_DESC);
|
||||
if (desc!=null) {
|
||||
String sDesc = Misc.getPCDATA(desc);
|
||||
if (sDesc.startsWith("jex149$tex={") && sDesc.endsWith("}")) {
|
||||
String sTeX = sDesc.substring(12,sDesc.length()-1);
|
||||
if (sTeX.length()>0) {
|
||||
// Succesfully extracted Jex equation!
|
||||
ldp.append("$"+sTeX+"$");
|
||||
return;
|
||||
}
|
||||
}
|
||||
}*/
|
||||
|
||||
// Recognize OOoLaTeX equation
|
||||
// The LaTeX code is embedded in a custom style attribute:
|
||||
StyleWithProperties style = ofr.getFrameStyle(
|
||||
Misc.getAttribute(frame, XMLString.DRAW_STYLE_NAME));
|
||||
if (style!=null) {
|
||||
String sOOoLaTeX = style.getProperty("OOoLatexArgs");
|
||||
// The content of the attribute is <point size><paragraph sign><mode><paragraph sign><TeX code>
|
||||
int n=0;
|
||||
if (sOOoLaTeX!=null) {
|
||||
if ((n=sOOoLaTeX.indexOf("\u00A7display\u00A7"))>-1) {
|
||||
ldp.append("\\[").append(sOOoLaTeX.substring(n+9)).append("\\]");
|
||||
bNeedOOoLaTeXPreamble = true;
|
||||
return;
|
||||
}
|
||||
else if ((n=sOOoLaTeX.indexOf("\u00A7inline\u00A7"))>-1) {
|
||||
ldp.append("$").append(sOOoLaTeX.substring(n+8)).append("$");
|
||||
bNeedOOoLaTeXPreamble = true;
|
||||
return;
|
||||
}
|
||||
else if ((n=sOOoLaTeX.indexOf("\u00A7text\u00A7"))>-1) {
|
||||
ldp.append(sOOoLaTeX.substring(n+6));
|
||||
bNeedOOoLaTeXPreamble = true;
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//if (oc.isInFrame() || "as-char".equals(sAnchor)) {
|
||||
if ("as-char".equals(sAnchor)) {
|
||||
handleDrawImageAsChar(node,ldp,oc);
|
||||
}
|
||||
else {
|
||||
((LinkedList) floatingFramesStack.peek()).add(node);
|
||||
}
|
||||
}
|
||||
|
||||
private void handleDrawImageAsChar(Element node, LaTeXDocumentPortion ldp, Context oc) {
|
||||
ldp.append(" ");
|
||||
includeGraphics(node,ldp,oc);
|
||||
ldp.append(" ");
|
||||
}
|
||||
|
||||
private void handleDrawImageFloat(Element node, LaTeXDocumentPortion ldp, Context oc) {
|
||||
Context ic = (Context) oc.clone();
|
||||
BeforeAfter ba = new BeforeAfter();
|
||||
|
||||
applyFigureFloat(ba,ic);
|
||||
|
||||
ldp.append(ba.getBefore());
|
||||
includeGraphics(node,ldp,ic);
|
||||
ldp.append(ba.getAfter());
|
||||
}
|
||||
|
||||
private void includeGraphics(Element node, LaTeXDocumentPortion ldp, Context oc) {
|
||||
String sFileName = null;
|
||||
boolean bCommentOut = true;
|
||||
String sHref = node.getAttribute(XMLString.XLINK_HREF);
|
||||
|
||||
if (node.hasAttribute(XMLString.XLINK_HREF) && !ofr.isInPackage(sHref)) {
|
||||
// Linked image is not yet handled by ImageLoader. This is a temp.
|
||||
// solution (will go away when ImageLoader is finished)
|
||||
sFileName = sHref;
|
||||
// In OpenDocument package format ../ means "leave the package"
|
||||
if (ofr.isOpenDocument() && ofr.isPackageFormat() && sFileName.startsWith("../")) {
|
||||
sFileName=sFileName.substring(3);
|
||||
}
|
||||
int nExtStart = sHref.lastIndexOf(".");
|
||||
String sExt = nExtStart>=0 ? sHref.substring(nExtStart).toLowerCase() : "";
|
||||
// Accept only relative filenames and supported filetypes:
|
||||
bCommentOut = sFileName.indexOf(":")>-1 || !(
|
||||
config.getBackend()==LaTeXConfig.UNSPECIFIED ||
|
||||
(config.getBackend()==LaTeXConfig.PDFTEX && MIMETypes.JPEG_EXT.equals(sExt)) ||
|
||||
(config.getBackend()==LaTeXConfig.PDFTEX && MIMETypes.PNG_EXT.equals(sExt)) ||
|
||||
(config.getBackend()==LaTeXConfig.PDFTEX && MIMETypes.PDF_EXT.equals(sExt)) ||
|
||||
(config.getBackend()==LaTeXConfig.XETEX && MIMETypes.JPEG_EXT.equals(sExt)) ||
|
||||
(config.getBackend()==LaTeXConfig.XETEX && MIMETypes.PNG_EXT.equals(sExt)) ||
|
||||
(config.getBackend()==LaTeXConfig.XETEX && MIMETypes.PDF_EXT.equals(sExt)) ||
|
||||
(config.getBackend()==LaTeXConfig.DVIPS && MIMETypes.EPS_EXT.equals(sExt)));
|
||||
}
|
||||
else { // embedded or base64 encoded image
|
||||
BinaryGraphicsDocument bgd = palette.getImageLoader().getImage(node);
|
||||
if (bgd!=null) {
|
||||
palette.addDocument(bgd);
|
||||
sFileName = bgd.getFileName();
|
||||
String sMIME = bgd.getDocumentMIMEType();
|
||||
bCommentOut = !(
|
||||
config.getBackend()==LaTeXConfig.UNSPECIFIED ||
|
||||
(config.getBackend()==LaTeXConfig.PDFTEX && MIMETypes.JPEG.equals(sMIME)) ||
|
||||
(config.getBackend()==LaTeXConfig.PDFTEX && MIMETypes.PNG.equals(sMIME)) ||
|
||||
(config.getBackend()==LaTeXConfig.PDFTEX && MIMETypes.PDF.equals(sMIME)) ||
|
||||
(config.getBackend()==LaTeXConfig.XETEX && MIMETypes.JPEG.equals(sMIME)) ||
|
||||
(config.getBackend()==LaTeXConfig.XETEX && MIMETypes.PNG.equals(sMIME)) ||
|
||||
(config.getBackend()==LaTeXConfig.XETEX && MIMETypes.PDF.equals(sMIME)) ||
|
||||
(config.getBackend()==LaTeXConfig.DVIPS && MIMETypes.EPS.equals(sMIME)));
|
||||
}
|
||||
}
|
||||
|
||||
if (sFileName==null) {
|
||||
ldp.append("[Warning: Image not found]");
|
||||
return;
|
||||
}
|
||||
|
||||
// Now for the actual inclusion:
|
||||
bNeedGraphicx = true;
|
||||
/* TODO: handle cropping and mirror:
|
||||
style:mirror can be none, vertical (lodret), horizontal (vandret),
|
||||
horizontal-on-odd, or
|
||||
horizontal-on-even (horizontal on odd or even pages).
|
||||
mirror is handled with scalebox, eg:
|
||||
%\\scalebox{-1}[1]{...}
|
||||
can check for even/odd page first!!
|
||||
|
||||
fo:clip="rect(t,r,b,l) svarer til trim
|
||||
value can be auto - no clip!
|
||||
cropping is handled with clip and trim:
|
||||
\\includegraphics[clip,trim=l b r t]{...}
|
||||
note the different order from xsl-fo!
|
||||
*/
|
||||
|
||||
if (bCommentOut) {
|
||||
ldp.append(" [Warning: Image ignored] ");
|
||||
ldp.append("% Unhandled or unsupported graphics:").nl().append("%");
|
||||
}
|
||||
ldp.append("\\includegraphics");
|
||||
|
||||
CSVList options = new CSVList(',');
|
||||
if (!config.originalImageSize()) {
|
||||
Element frame = getFrame(node);
|
||||
String sWidth = Misc.truncateLength(frame.getAttribute(XMLString.SVG_WIDTH));
|
||||
String sHeight = Misc.truncateLength(frame.getAttribute(XMLString.SVG_HEIGHT));
|
||||
if (sWidth!=null) { options.addValue("width="+sWidth); }
|
||||
if (sHeight!=null) { options.addValue("height="+sHeight); }
|
||||
}
|
||||
if (config.getImageOptions().length()>0) {
|
||||
options.addValue(config.getImageOptions()); // TODO: New CSVList...
|
||||
}
|
||||
if (!options.isEmpty()) {
|
||||
ldp.append("[").append(options.toString()).append("]");
|
||||
}
|
||||
|
||||
if (config.removeGraphicsExtension()) {
|
||||
sFileName = Misc.removeExtension(sFileName);
|
||||
}
|
||||
ldp.append("{").append(sFileName).append("}");
|
||||
if (bCommentOut) { ldp.nl(); }
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------
|
||||
// handle draw:text-box element
|
||||
|
||||
private void handleDrawTextBox(Element node, LaTeXDocumentPortion ldp, Context oc) {
|
||||
Element frame = getFrame(node);
|
||||
//String sName = frame.getAttribute(XMLString.DRAW_NAME);
|
||||
palette.getFieldCv().addTarget(frame,"|frame",ldp);
|
||||
String sAnchor = frame.getAttribute(XMLString.TEXT_ANCHOR_TYPE);
|
||||
//if (oc.isInFrame() || "as-char".equals(sAnchor)) {
|
||||
if ("as-char".equals(sAnchor)) {
|
||||
makeDrawTextBox(node, ldp, oc);
|
||||
}
|
||||
else {
|
||||
((LinkedList) floatingFramesStack.peek()).add(node);
|
||||
}
|
||||
}
|
||||
|
||||
private void handleDrawTextBoxFloat(Element node, LaTeXDocumentPortion ldp, Context oc) {
|
||||
BeforeAfter ba = new BeforeAfter();
|
||||
Context ic = (Context) oc.clone();
|
||||
|
||||
applyFigureFloat(ba,ic);
|
||||
|
||||
ldp.append(ba.getBefore());
|
||||
makeDrawTextBox(node, ldp, ic);
|
||||
ldp.append(ba.getAfter());
|
||||
}
|
||||
|
||||
private void makeDrawTextBox(Element node, LaTeXDocumentPortion ldp, Context oc) {
|
||||
Context ic = (Context) oc.clone();
|
||||
ic.setInFrame(true);
|
||||
ic.setNoFootnotes(true);
|
||||
|
||||
// Check to see, if this is really a container for a figure caption
|
||||
boolean bIsCaption = false;
|
||||
if (OfficeReader.isSingleParagraph(node)) {
|
||||
Element par = Misc.getFirstChildElement(node);
|
||||
String sSeqName = ofr.getSequenceName(par);
|
||||
if (ofr.isFigureSequenceName(sSeqName)) { bIsCaption = true; }
|
||||
}
|
||||
|
||||
String sWidth = Misc.truncateLength(getFrame(node).getAttribute(XMLString.SVG_WIDTH));
|
||||
if (!bIsCaption) {
|
||||
ldp.append("\\begin{minipage}{").append(sWidth).append("}").nl();
|
||||
}
|
||||
floatingFramesStack.push(new LinkedList());
|
||||
palette.getBlockCv().traverseBlockText(node,ldp,ic);
|
||||
flushFloatingFrames(ldp,ic);
|
||||
floatingFramesStack.pop();
|
||||
if (!bIsCaption) {
|
||||
ldp.append("\\end{minipage}");
|
||||
}
|
||||
if (!oc.isNoFootnotes()) { palette.getNoteCv().flushFootnotes(ldp,oc); }
|
||||
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------------------
|
||||
//handle any pending floating frames
|
||||
|
||||
public void flushFloatingFrames(LaTeXDocumentPortion ldp, Context oc) {
|
||||
// todo: fix language
|
||||
LinkedList floatingFrames = (LinkedList) floatingFramesStack.peek();
|
||||
int n = floatingFrames.size();
|
||||
if (n==0) { return; }
|
||||
for (int i=0; i<n; i++) {
|
||||
Element node = (Element) floatingFrames.get(i);
|
||||
String sName = node.getNodeName();
|
||||
if (sName.equals(XMLString.DRAW_IMAGE)) {
|
||||
handleDrawImageFloat(node,ldp,oc);
|
||||
}
|
||||
else if (sName.equals(XMLString.DRAW_TEXT_BOX)) {
|
||||
handleDrawTextBoxFloat(node,ldp,oc);
|
||||
}
|
||||
}
|
||||
floatingFrames.clear();
|
||||
}
|
||||
|
||||
}
|
672
source/java/writer2latex/latex/FieldConverter.java
Normal file
672
source/java/writer2latex/latex/FieldConverter.java
Normal file
|
@ -0,0 +1,672 @@
|
|||
/************************************************************************
|
||||
*
|
||||
* FieldConverter.java
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License version 2.1, as published by the Free Software Foundation.
|
||||
*
|
||||
* This library 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
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston,
|
||||
* MA 02111-1307 USA
|
||||
*
|
||||
* Copyright: 2002-2008 by Henrik Just
|
||||
*
|
||||
* All Rights Reserved.
|
||||
*
|
||||
* Version 1.0 (2008-11-23)
|
||||
*
|
||||
*/
|
||||
|
||||
package writer2latex.latex;
|
||||
|
||||
//import java.io.UnsupportedEncodingException;
|
||||
import java.util.Enumeration;
|
||||
import java.util.Hashtable;
|
||||
import java.util.Vector;
|
||||
|
||||
import org.w3c.dom.Element;
|
||||
import org.w3c.dom.Node;
|
||||
|
||||
import writer2latex.latex.util.Context;
|
||||
import writer2latex.latex.util.HeadingMap;
|
||||
import writer2latex.office.OfficeReader;
|
||||
import writer2latex.office.XMLString;
|
||||
import writer2latex.util.CSVList;
|
||||
import writer2latex.util.ExportNameCollection;
|
||||
import writer2latex.util.Misc;
|
||||
import writer2latex.util.SimpleInputBuffer;
|
||||
|
||||
/**
|
||||
* This class handles text fields and links in the document.
|
||||
* Packages: lastpage, hyperref, titleref, oooref (all optional)
|
||||
* TODO: Need proper treatment of "caption" and "text" for sequence
|
||||
* references not to figures and tables (should be fairly rare, though)
|
||||
|
||||
*/
|
||||
public class FieldConverter extends ConverterHelper {
|
||||
|
||||
// Links & references
|
||||
private ExportNameCollection targets = new ExportNameCollection(true);
|
||||
private ExportNameCollection refnames = new ExportNameCollection(true);
|
||||
private ExportNameCollection bookmarknames = new ExportNameCollection(true);
|
||||
private ExportNameCollection seqnames = new ExportNameCollection(true);
|
||||
private ExportNameCollection seqrefnames = new ExportNameCollection(true);
|
||||
|
||||
// sequence declarations (maps name->text:sequence-decl element)
|
||||
private Hashtable seqDecl = new Hashtable();
|
||||
// first usage of sequence (maps name->text:sequence element)
|
||||
private Hashtable seqFirst = new Hashtable();
|
||||
|
||||
private Vector postponedReferenceMarks = new Vector();
|
||||
private Vector postponedBookmarks = new Vector();
|
||||
|
||||
private boolean bUseHyperref = false;
|
||||
private boolean bUsesPageCount = false;
|
||||
private boolean bUsesTitleref = false;
|
||||
private boolean bUsesOooref = false;
|
||||
|
||||
public FieldConverter(OfficeReader ofr, LaTeXConfig config, ConverterPalette palette) {
|
||||
super(ofr,config,palette);
|
||||
// hyperref.sty is not compatible with titleref.sty and oooref.sty:
|
||||
bUseHyperref = config.useHyperref() && !config.useTitleref() && !config.useOooref();
|
||||
}
|
||||
|
||||
/** <p>Append declarations needed by the <code>FieldConverter</code> to
|
||||
* the preamble.</p>
|
||||
* @param pack the <code>LaTeXDocumentPortion</code> to which
|
||||
* declarations of packages should be added (<code>\\usepackage</code>).
|
||||
* @param decl the <code>LaTeXDocumentPortion</code> to which
|
||||
* other declarations should be added.
|
||||
*/
|
||||
public void appendDeclarations(LaTeXDocumentPortion pack, LaTeXDocumentPortion decl) {
|
||||
// use lastpage.sty
|
||||
if (bUsesPageCount) {
|
||||
pack.append("\\usepackage{lastpage}").nl();
|
||||
}
|
||||
|
||||
// use titleref.sty
|
||||
if (bUsesTitleref) {
|
||||
pack.append("\\usepackage{titleref}").nl();
|
||||
}
|
||||
|
||||
// use oooref.sty
|
||||
if (bUsesOooref) {
|
||||
pack.append("\\usepackage[");
|
||||
HeadingMap hm = config.getHeadingMap();
|
||||
CSVList opt = new CSVList(",");
|
||||
for (int i=0; i<=hm.getMaxLevel(); i++) { opt.addValue(hm.getName(i)); }
|
||||
pack.append(opt.toString()).append("]{oooref}").nl();
|
||||
}
|
||||
|
||||
// use hyperref.sty
|
||||
if (bUseHyperref){
|
||||
pack.append("\\usepackage{hyperref}").nl();
|
||||
pack.append("\\hypersetup{");
|
||||
if (config.getBackend()==LaTeXConfig.PDFTEX) pack.append("pdftex, ");
|
||||
else if (config.getBackend()==LaTeXConfig.DVIPS) pack.append("dvips, ");
|
||||
//else pack.append("hypertex");
|
||||
pack.append("colorlinks=true, linkcolor=blue, citecolor=blue, filecolor=blue, urlcolor=blue");
|
||||
if (config.getBackend()==LaTeXConfig.PDFTEX) {
|
||||
pack.append(createPdfMeta("pdftitle",palette.getMetaData().getTitle()));
|
||||
if (config.metadata()) {
|
||||
pack.append(createPdfMeta("pdfauthor",palette.getMetaData().getCreator()))
|
||||
.append(createPdfMeta("pdfsubject",palette.getMetaData().getSubject()))
|
||||
.append(createPdfMeta("pdfkeywords",palette.getMetaData().getKeywords()));
|
||||
}
|
||||
}
|
||||
pack.append("}").nl();
|
||||
}
|
||||
|
||||
// Export sequence declarations
|
||||
// The number format is fetched from the first occurence of the
|
||||
// sequence in the text, while the outline level and the separation
|
||||
// character are fetched from the declaration
|
||||
Enumeration names = seqFirst.keys();
|
||||
while (names.hasMoreElements()) {
|
||||
// Get first text:sequence element
|
||||
String sName = (String) names.nextElement();
|
||||
Element first = (Element) seqFirst.get(sName);
|
||||
// Collect data
|
||||
String sNumFormat = Misc.getAttribute(first,XMLString.STYLE_NUM_FORMAT);
|
||||
if (sNumFormat==null) { sNumFormat="1"; }
|
||||
int nLevel = 0;
|
||||
String sSepChar = ".";
|
||||
if (seqDecl.containsKey(sName)) {
|
||||
Element sdecl = (Element) seqDecl.get(sName);
|
||||
nLevel = Misc.getPosInteger(sdecl.getAttribute(XMLString.TEXT_DISPLAY_OUTLINE_LEVEL),0);
|
||||
if (sdecl.hasAttribute(XMLString.TEXT_SEPARATION_CHARACTER)) {
|
||||
sSepChar = palette.getI18n().convert(
|
||||
sdecl.getAttribute(XMLString.TEXT_SEPARATION_CHARACTER),
|
||||
false,palette.getMainContext().getLang());
|
||||
}
|
||||
}
|
||||
// Create counter
|
||||
decl.append("\\newcounter{")
|
||||
.append(seqnames.getExportName(sName))
|
||||
.append("}");
|
||||
String sPrefix = "";
|
||||
if (nLevel>0) {
|
||||
HeadingMap hm = config.getHeadingMap();
|
||||
int nUsedLevel = nLevel<=hm.getMaxLevel() ? nLevel : hm.getMaxLevel();
|
||||
if (nUsedLevel>0) {
|
||||
decl.append("[").append(hm.getName(nUsedLevel)).append("]");
|
||||
sPrefix = "\\the"+hm.getName(nUsedLevel)+sSepChar;
|
||||
}
|
||||
}
|
||||
decl.nl()
|
||||
.append("\\renewcommand\\the")
|
||||
.append(seqnames.getExportName(sName))
|
||||
.append("{").append(sPrefix)
|
||||
.append(ListStyleConverter.numFormat(sNumFormat))
|
||||
.append("{").append(seqnames.getExportName(sName))
|
||||
.append("}}").nl();
|
||||
}
|
||||
}
|
||||
|
||||
/** <p>Process sequence declarations</p>
|
||||
* @param node the text:sequence-decls node
|
||||
*/
|
||||
public void handleSequenceDecls(Element node) {
|
||||
Node child = node.getFirstChild();
|
||||
while (child!=null) {
|
||||
if (Misc.isElement(child,XMLString.TEXT_SEQUENCE_DECL)) {
|
||||
// Don't process the declaration, but store a reference
|
||||
seqDecl.put(((Element)child).getAttribute(XMLString.TEXT_NAME),child);
|
||||
}
|
||||
child = child.getNextSibling();
|
||||
}
|
||||
}
|
||||
|
||||
/** <p>Process a sequence field (text:sequence tag)</p>
|
||||
* @param node The element containing the sequence field
|
||||
* @param ldp the <code>LaTeXDocumentPortion</code> to which
|
||||
* LaTeX code should be added
|
||||
* @param oc the current context
|
||||
*/
|
||||
public void handleSequence(Element node, LaTeXDocumentPortion ldp, Context oc) {
|
||||
String sName = Misc.getAttribute(node,XMLString.TEXT_NAME);
|
||||
String sRefName = Misc.getAttribute(node,XMLString.TEXT_REF_NAME);
|
||||
String sFormula = Misc.getAttribute(node,XMLString.TEXT_FORMULA);
|
||||
if (sFormula==null) {
|
||||
// If there's no formula, we must use the content as formula
|
||||
// The parser below requires a namespace, so we add that..
|
||||
sFormula = "ooow:"+Misc.getPCDATA(node);
|
||||
}
|
||||
if (sName!=null) {
|
||||
if (ofr.isFigureSequenceName(sName) || ofr.isTableSequenceName(sName)) {
|
||||
// Export \label only, assuming the number is generated by \caption
|
||||
if (sRefName!=null && ofr.hasSequenceRefTo(sRefName)) {
|
||||
ldp.append("\\label{seq:")
|
||||
.append(seqrefnames.getExportName(sRefName))
|
||||
.append("}");
|
||||
}
|
||||
}
|
||||
else {
|
||||
// General purpose sequence -> export as counter
|
||||
if (!seqFirst.containsKey(sName)) {
|
||||
// Save first occurence -> used to determine number format
|
||||
seqFirst.put(sName,node);
|
||||
}
|
||||
if (sRefName!=null && ofr.hasSequenceRefTo(sRefName)) {
|
||||
// Export as {\refstepcounter{name}\thename\label{refname}}
|
||||
ldp.append("{").append(changeCounter(sName,sFormula,true))
|
||||
.append("\\the").append(seqnames.getExportName(sName))
|
||||
.append("\\label{seq:")
|
||||
.append(seqrefnames.getExportName(sRefName))
|
||||
.append("}}");
|
||||
}
|
||||
else {
|
||||
// Export as \stepcounter{name}{\thename}
|
||||
ldp.append(changeCounter(sName,sFormula,false))
|
||||
.append("{\\the")
|
||||
.append(seqnames.getExportName(sName))
|
||||
.append("}");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/** <p>Create label for a sequence field (text:sequence tag)</p>
|
||||
* @param node The element containing the sequence field
|
||||
* @param ldp the <code>LaTeXDocumentPortion</code> to which
|
||||
* LaTeX code should be added
|
||||
*/
|
||||
public void handleSequenceLabel(Element node, LaTeXDocumentPortion ldp) {
|
||||
String sRefName = Misc.getAttribute(node,XMLString.TEXT_REF_NAME);
|
||||
if (sRefName!=null && ofr.hasSequenceRefTo(sRefName)) {
|
||||
ldp.append("\\label{seq:")
|
||||
.append(seqrefnames.getExportName(sRefName))
|
||||
.append("}");
|
||||
}
|
||||
}
|
||||
|
||||
// According to the spec for OpenDocument, the formula is application
|
||||
// specific, prefixed with a namespace. OOo uses the namespace ooow, and
|
||||
// we accept the formulas ooow:<number>, ooow:<name>, ooow:<name>+<number>
|
||||
// and ooow:<name>-<number>
|
||||
// Note: In OOo a counter is a 16 bit unsigned integer, whereas a (La)TeX
|
||||
// counter can be negative - thus there will be a slight deviation in the
|
||||
// (rare) case of a negative number
|
||||
private String changeCounter(String sName, String sFormula, boolean bRef) {
|
||||
if (sFormula!=null) {
|
||||
sFormula = sFormula.trim();
|
||||
if (sFormula.startsWith("ooow:")) {
|
||||
SimpleInputBuffer input = new SimpleInputBuffer(sFormula.substring(5));
|
||||
if (input.peekChar()>='0' && input.peekChar()<='9') {
|
||||
// Value is <number>
|
||||
String sNumber = input.getInteger();
|
||||
if (input.atEnd()) {
|
||||
return setCounter(sName, Misc.getPosInteger(sNumber,0), bRef);
|
||||
}
|
||||
}
|
||||
else if (input.peekChar()=='-') {
|
||||
// Value is a negative <number>
|
||||
input.getChar();
|
||||
if (input.peekChar()>='0' && input.peekChar()<='9') {
|
||||
String sNumber = input.getInteger();
|
||||
if (input.atEnd()) {
|
||||
return setCounter(sName, -Misc.getPosInteger(sNumber,0), bRef);
|
||||
}
|
||||
}
|
||||
}
|
||||
else {
|
||||
// Value starts with <name>
|
||||
String sToken = input.getIdentifier();
|
||||
if (sToken.equals(sName)) {
|
||||
input.skipSpaces();
|
||||
if (input.peekChar()=='+') {
|
||||
// Value is <name>+<number>
|
||||
input.getChar();
|
||||
input.skipSpaces();
|
||||
String sNumber = input.getInteger();
|
||||
if (input.atEnd()) {
|
||||
return addtoCounter(sName, Misc.getPosInteger(sNumber,0), bRef);
|
||||
}
|
||||
}
|
||||
else if (input.peekChar()=='-') {
|
||||
// Value is <name>-<number>
|
||||
input.getChar();
|
||||
input.skipSpaces();
|
||||
String sNumber = input.getInteger();
|
||||
if (input.atEnd()) {
|
||||
return addtoCounter(sName, -Misc.getPosInteger(sNumber,0), bRef);
|
||||
}
|
||||
}
|
||||
else if (input.atEnd()) {
|
||||
// Value is <name>
|
||||
return addtoCounter(sName, 0, bRef);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
// No formula, or a formula we don't understand -> use default behavior
|
||||
return stepCounter(sName, bRef);
|
||||
}
|
||||
|
||||
private String stepCounter(String sName, boolean bRef) {
|
||||
if (bRef) {
|
||||
return "\\refstepcounter{" + seqnames.getExportName(sName) + "}";
|
||||
}
|
||||
else {
|
||||
return "\\stepcounter{" + seqnames.getExportName(sName) + "}";
|
||||
}
|
||||
}
|
||||
|
||||
private String addtoCounter(String sName, int nValue, boolean bRef) {
|
||||
if (nValue==1) {
|
||||
return stepCounter(sName, bRef);
|
||||
}
|
||||
else if (bRef) {
|
||||
return "\\addtocounter{" + seqnames.getExportName(sName) + "}"
|
||||
+ "{" + Integer.toString(nValue-1) + "}"
|
||||
+ "\\refstepcounter{" + seqnames.getExportName(sName) + "}";
|
||||
}
|
||||
else if (nValue!=0) {
|
||||
return "\\addtocounter{" + seqnames.getExportName(sName) + "}"
|
||||
+ "{" + Integer.toString(nValue) + "}";
|
||||
}
|
||||
else {
|
||||
return "";
|
||||
}
|
||||
}
|
||||
|
||||
private String setCounter(String sName, int nValue, boolean bRef) {
|
||||
if (bRef) {
|
||||
return "\\setcounter{" + seqnames.getExportName(sName) + "}"
|
||||
+ "{" + Integer.toString(nValue-1) + "}"
|
||||
+ "\\refstepcounter{" + seqnames.getExportName(sName) + "}";
|
||||
}
|
||||
else {
|
||||
return "\\setcounter{" + seqnames.getExportName(sName) + "}"
|
||||
+ "{" + Integer.toString(nValue) + "}";
|
||||
}
|
||||
}
|
||||
|
||||
/** <p>Process a sequence reference (text:sequence-ref tag)</p>
|
||||
* @param node The element containing the sequence reference
|
||||
* @param ldp the <code>LaTeXDocumentPortion</code> to which
|
||||
* LaTeX code should be added
|
||||
* @param oc the current context
|
||||
*/
|
||||
public void handleSequenceRef(Element node, LaTeXDocumentPortion ldp, Context oc) {
|
||||
String sRefName = Misc.getAttribute(node,XMLString.TEXT_REF_NAME);
|
||||
String sFormat = Misc.getAttribute(node,XMLString.TEXT_REFERENCE_FORMAT);
|
||||
String sName = ofr.getSequenceFromRef(sRefName);
|
||||
if (sRefName!=null) {
|
||||
if (sFormat==null || "page".equals(sFormat)) {
|
||||
ldp.append("\\pageref{seq:")
|
||||
.append(seqrefnames.getExportName(sRefName))
|
||||
.append("}");
|
||||
}
|
||||
else if ("value".equals(sFormat)) {
|
||||
ldp.append("\\ref{seq:")
|
||||
.append(seqrefnames.getExportName(sRefName))
|
||||
.append("}");
|
||||
}
|
||||
else if ("category-and-value".equals(sFormat)) {
|
||||
// Export as Name~\\ref{refname}
|
||||
if (sName!=null) {
|
||||
if (ofr.isFigureSequenceName(sName)) {
|
||||
ldp.append("\\figurename~");
|
||||
}
|
||||
else if (ofr.isTableSequenceName(sName)) {
|
||||
ldp.append("\\tablename~");
|
||||
}
|
||||
else {
|
||||
ldp.append(sName).append("~");
|
||||
}
|
||||
}
|
||||
ldp.append("\\ref{seq:")
|
||||
.append(seqrefnames.getExportName(sRefName))
|
||||
.append("}");
|
||||
}
|
||||
else if ("chapter".equals(sFormat) && config.useOooref()) {
|
||||
ldp.append("\\chapterref{seq:")
|
||||
.append(seqrefnames.getExportName(sRefName))
|
||||
.append("}");
|
||||
bUsesOooref = true;
|
||||
}
|
||||
else if ("caption".equals(sFormat) && config.useTitleref() &&
|
||||
(ofr.isFigureSequenceName(sName) || ofr.isTableSequenceName(sName))) {
|
||||
ldp.append("\\titleref{seq:")
|
||||
.append(seqrefnames.getExportName(sRefName))
|
||||
.append("}");
|
||||
bUsesTitleref = true;
|
||||
}
|
||||
else if ("text".equals(sFormat) && config.useTitleref() &&
|
||||
(ofr.isFigureSequenceName(sName) || ofr.isTableSequenceName(sName))) {
|
||||
// This is a combination of "category-and-value" and "caption"
|
||||
// Export as \\figurename~\ref{refname}:~\titleref{refname}
|
||||
if (ofr.isFigureSequenceName(sName)) {
|
||||
ldp.append("\\figurename");
|
||||
}
|
||||
else if (ofr.isTableSequenceName(sName)) {
|
||||
ldp.append("\\tablename");
|
||||
}
|
||||
ldp.append("~\\ref{seq:")
|
||||
.append(seqrefnames.getExportName(sRefName))
|
||||
.append("}:~\\titleref{")
|
||||
.append(seqrefnames.getExportName(sRefName))
|
||||
.append("}");
|
||||
bUsesTitleref = true;
|
||||
}
|
||||
else { // use current value
|
||||
palette.getInlineCv().traversePCDATA(node,ldp,oc);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/** <p>Process a reference mark (text:reference-mark tag)</p>
|
||||
* @param node The element containing the reference mark
|
||||
* @param ldp the <code>LaTeXDocumentPortion</code> to which
|
||||
* LaTeX code should be added
|
||||
* @param oc the current context
|
||||
*/
|
||||
public void handleReferenceMark(Element node, LaTeXDocumentPortion ldp, Context oc) {
|
||||
if (!oc.isInSection() && !oc.isInCaption() && !oc.isVerbatim()) {
|
||||
// Note: Always include \label here, even when it's not used
|
||||
String sName = node.getAttribute(XMLString.TEXT_NAME);
|
||||
if (sName!=null) {
|
||||
ldp.append("\\label{ref:"+refnames.getExportName(sName)+"}");
|
||||
}
|
||||
}
|
||||
else {
|
||||
// Reference marks should not appear within \section or \caption
|
||||
postponedReferenceMarks.add(node);
|
||||
}
|
||||
}
|
||||
|
||||
/** <p>Process a reference (text:reference-ref tag)</p>
|
||||
* @param node The element containing the reference
|
||||
* @param ldp the <code>LaTeXDocumentPortion</code> to which
|
||||
* LaTeX code should be added
|
||||
* @param oc the current context
|
||||
*/
|
||||
public void handleReferenceRef(Element node, LaTeXDocumentPortion ldp, Context oc) {
|
||||
String sFormat = node.getAttribute(XMLString.TEXT_REFERENCE_FORMAT);
|
||||
String sName = node.getAttribute(XMLString.TEXT_REF_NAME);
|
||||
if (("page".equals(sFormat) || "".equals(sFormat)) && sName!=null) {
|
||||
ldp.append("\\pageref{ref:"+refnames.getExportName(sName)+"}");
|
||||
}
|
||||
else if ("chapter".equals(sFormat) && ofr.referenceMarkInHeading(sName)) {
|
||||
// This is safe if the reference mark is contained in a heading
|
||||
ldp.append("\\ref{ref:"+refnames.getExportName(sName)+"}");
|
||||
}
|
||||
else { // use current value
|
||||
palette.getInlineCv().traversePCDATA(node,ldp,oc);
|
||||
}
|
||||
}
|
||||
|
||||
/** <p>Process a bookmark (text:bookmark tag)</p>
|
||||
* <p>A bookmark may be the target for either a hyperlink or a reference,
|
||||
* so this will generate a <code>\\hyperref</code> and/or a <code>\\label</code></p>
|
||||
* @param node The element containing the bookmark
|
||||
* @param ldp the <code>LaTeXDocumentPortion</code> to which
|
||||
* LaTeX code should be added
|
||||
* @param oc the current context
|
||||
*/
|
||||
public void handleBookmark(Element node, LaTeXDocumentPortion ldp, Context oc) {
|
||||
if (!oc.isInSection() && !oc.isInCaption() && !oc.isVerbatim()) {
|
||||
String sName = node.getAttribute(XMLString.TEXT_NAME);
|
||||
if (sName!=null) {
|
||||
// A bookmark may be used as a target for a hyperlink as well as
|
||||
// for a reference. We export whatever is actually used:
|
||||
addTarget(node,"",ldp);
|
||||
if (ofr.hasBookmarkRefTo(sName)) {
|
||||
ldp.append("\\label{bkm:"+bookmarknames.getExportName(sName)+"}");
|
||||
}
|
||||
}
|
||||
}
|
||||
else {
|
||||
// Bookmarks should not appear within \section or \caption
|
||||
postponedBookmarks.add(node);
|
||||
}
|
||||
}
|
||||
|
||||
/** <p>Process a bookmark reference (text:bookmark-ref tag).</p>
|
||||
* @param node The element containing the bookmark reference
|
||||
* @param ldp the <code>LaTeXDocumentPortion</code> to which
|
||||
* LaTeX code should be added
|
||||
* @param oc the current context
|
||||
*/
|
||||
public void handleBookmarkRef(Element node, LaTeXDocumentPortion ldp, Context oc) {
|
||||
String sFormat = node.getAttribute(XMLString.TEXT_REFERENCE_FORMAT);
|
||||
String sName = node.getAttribute(XMLString.TEXT_REF_NAME);
|
||||
if (("page".equals(sFormat) || "".equals(sFormat)) && sName!=null) {
|
||||
ldp.append("\\pageref{bkm:"+bookmarknames.getExportName(sName)+"}");
|
||||
}
|
||||
else if ("chapter".equals(sFormat) && ofr.bookmarkInHeading(sName)) {
|
||||
// This is safe if the bookmark is contained in a heading
|
||||
ldp.append("\\ref{bkm:"+bookmarknames.getExportName(sName)+"}");
|
||||
}
|
||||
else { // use current value
|
||||
palette.getInlineCv().traversePCDATA(node,ldp,oc);
|
||||
}
|
||||
}
|
||||
|
||||
/** <p>Process pending reference marks and bookmarks (which may have been
|
||||
* postponed within sections, captions or verbatim text.</p>
|
||||
* @param ldp the <code>LaTeXDocumentPortion</code> to which
|
||||
* LaTeX code should be added
|
||||
* @param oc the current context
|
||||
*/
|
||||
public void flushReferenceMarks(LaTeXDocumentPortion ldp, Context oc) {
|
||||
// We may still be in a context with no reference marks
|
||||
if (!oc.isInSection() && !oc.isInCaption() && !oc.isVerbatim()) {
|
||||
// Type out all postponed reference marks
|
||||
int n = postponedReferenceMarks.size();
|
||||
for (int i=0; i<n; i++) {
|
||||
handleReferenceMark((Element) postponedReferenceMarks.get(i),ldp,oc);
|
||||
}
|
||||
postponedReferenceMarks.clear();
|
||||
// Type out all postponed bookmarks
|
||||
n = postponedBookmarks.size();
|
||||
for (int i=0; i<n; i++) {
|
||||
handleBookmark((Element) postponedBookmarks.get(i),ldp,oc);
|
||||
}
|
||||
postponedBookmarks.clear();
|
||||
}
|
||||
}
|
||||
|
||||
/** <p>Process a hyperlink (text:a tag)</p>
|
||||
* @param node The element containing the hyperlink
|
||||
* @param ldp the <code>LaTeXDocumentPortion</code> to which
|
||||
* LaTeX code should be added
|
||||
* @param oc the current context
|
||||
*/
|
||||
public void handleAnchor(Element node, LaTeXDocumentPortion ldp, Context oc) {
|
||||
String sHref = node.getAttribute(XMLString.XLINK_HREF);
|
||||
if (sHref!=null) {
|
||||
if (sHref.startsWith("#")) {
|
||||
// TODO: hyperlinks to headings (?) and objects
|
||||
if (bUseHyperref) {
|
||||
ldp.append("\\hyperlink{")
|
||||
.append(targets.getExportName(Misc.urlDecode(sHref.substring(1))))
|
||||
.append("}{");
|
||||
// ignore text style (let hyperref.sty handle the decoration):
|
||||
palette.getInlineCv().traverseInlineText(node,ldp,oc);
|
||||
ldp.append("}");
|
||||
}
|
||||
else { // user don't want to include hyperlinks
|
||||
palette.getInlineCv().handleTextSpan(node,ldp,oc);
|
||||
}
|
||||
}
|
||||
else {
|
||||
if (bUseHyperref) {
|
||||
if (ofr.getTextContent(node).trim().equals(sHref)) {
|
||||
// The link text equals the url
|
||||
ldp.append("\\url{")
|
||||
.append(oc.isInFootnote() ? escapeHref(Misc.urlDecode(sHref)) : Misc.urlDecode(sHref))
|
||||
.append("}");
|
||||
}
|
||||
else {
|
||||
ldp.append("\\href{")
|
||||
.append(oc.isInFootnote() ? escapeHref(Misc.urlDecode(sHref)) : Misc.urlDecode(sHref))
|
||||
.append("}{");
|
||||
// ignore text style (let hyperref.sty handle the decoration):
|
||||
palette.getInlineCv().traverseInlineText(node,ldp,oc);
|
||||
ldp.append("}");
|
||||
}
|
||||
}
|
||||
else { // user don't want to include hyperlinks
|
||||
palette.getInlineCv().handleTextSpan(node,ldp,oc);
|
||||
}
|
||||
}
|
||||
}
|
||||
else {
|
||||
palette.getInlineCv().handleTextSpan(node,ldp,oc);
|
||||
}
|
||||
}
|
||||
|
||||
/** <p>Add a <code>\\hypertarget</code></p>
|
||||
* @param node The element containing the name of the target
|
||||
* @param sSuffix A suffix to be added to the target,
|
||||
* e.g. "|table" for a reference to a table.
|
||||
* @param ldp the <code>LaTeXDocumentPortion</code> to which
|
||||
* LaTeX code should be added
|
||||
*/
|
||||
public void addTarget(Element node, String sSuffix, LaTeXDocumentPortion ldp) {
|
||||
// TODO: Remove this and use addTarget by name only
|
||||
String sName = node.getAttribute(XMLString.TEXT_NAME);
|
||||
if (sName == null) { sName = node.getAttribute(XMLString.TABLE_NAME); }
|
||||
if (sName == null || !bUseHyperref) { return; }
|
||||
if (!ofr.hasLinkTo(sName+sSuffix)) { return; }
|
||||
ldp.append("\\hypertarget{")
|
||||
.append(targets.getExportName(sName+sSuffix))
|
||||
.append("}{}");
|
||||
}
|
||||
|
||||
/** <p>Add a <code>\\hypertarget</code></p>
|
||||
* @param sName The name of the target
|
||||
* @param sSuffix A suffix to be added to the target,
|
||||
* e.g. "|table" for a reference to a table.
|
||||
* @param ldp the <code>LaTeXDocumentPortion</code> to which
|
||||
* LaTeX code should be added
|
||||
*/
|
||||
public void addTarget(String sName, String sSuffix, LaTeXDocumentPortion ldp) {
|
||||
if (sName!=null && bUseHyperref && ofr.hasLinkTo(sName+sSuffix)) {
|
||||
ldp.append("\\hypertarget{")
|
||||
.append(targets.getExportName(sName+sSuffix))
|
||||
.append("}{}");
|
||||
}
|
||||
}
|
||||
|
||||
/** <p>Process a page number field (text:page-number tag)</p>
|
||||
* @param node The element containing the page number field
|
||||
* @param ldp the <code>LaTeXDocumentPortion</code> to which
|
||||
* LaTeX code should be added
|
||||
* @param oc the current context
|
||||
*/
|
||||
public void handlePageNumber(Element node, LaTeXDocumentPortion ldp, Context oc) {
|
||||
// TODO: Obey attributes!
|
||||
ldp.append("\\thepage{}");
|
||||
}
|
||||
|
||||
/** <p>Process a page count field (text:page-count tag)</p>
|
||||
* @param node The element containing the page count field
|
||||
* @param ldp the <code>LaTeXDocumentPortion</code> to which
|
||||
* LaTeX code should be added
|
||||
* @param oc the current context
|
||||
*/
|
||||
public void handlePageCount(Element node, LaTeXDocumentPortion ldp, Context oc) {
|
||||
// TODO: Obey attributes!
|
||||
// Note: Actually LastPage refers to the page number of the last page, not the number of pages
|
||||
if (config.useLastpage()) {
|
||||
bUsesPageCount = true;
|
||||
ldp.append("\\pageref{LastPage}");
|
||||
}
|
||||
else {
|
||||
ldp.append("?");
|
||||
}
|
||||
}
|
||||
|
||||
// Helpers:
|
||||
|
||||
private String createPdfMeta(String sName, String sValue) {
|
||||
if (sValue==null) { return ""; }
|
||||
// Replace commas with semicolons (the keyval package doesn't like commas):
|
||||
sValue = sValue.replace(',', ';');
|
||||
// Meta data is assumed to be in the default language:
|
||||
return ", "+sName+"="+palette.getI18n().convert(sValue,false,palette.getMainContext().getLang());
|
||||
}
|
||||
|
||||
// For href within footnote, we have to escape the #
|
||||
private String escapeHref(String s) {
|
||||
StringBuffer buf = new StringBuffer();
|
||||
for (int i=0; i<s.length(); i++) {
|
||||
if (s.charAt(i)=='#') { buf.append("\\#"); }
|
||||
else { buf.append(s.charAt(i)); }
|
||||
}
|
||||
return buf.toString();
|
||||
}
|
||||
|
||||
}
|
357
source/java/writer2latex/latex/HeadingConverter.java
Normal file
357
source/java/writer2latex/latex/HeadingConverter.java
Normal file
|
@ -0,0 +1,357 @@
|
|||
/************************************************************************
|
||||
*
|
||||
* HeadingConverter.java
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License version 2.1, as published by the Free Software Foundation.
|
||||
*
|
||||
* This library 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
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston,
|
||||
* MA 02111-1307 USA
|
||||
*
|
||||
* Copyright: 2002-2008 by Henrik Just
|
||||
*
|
||||
* All Rights Reserved.
|
||||
*
|
||||
* Version 1.0 (2008-11-22)
|
||||
*
|
||||
*/
|
||||
|
||||
package writer2latex.latex;
|
||||
|
||||
//import java.util.Hashtable;
|
||||
|
||||
import org.w3c.dom.Element;
|
||||
import org.w3c.dom.Node;
|
||||
import org.w3c.dom.NodeList;
|
||||
|
||||
import writer2latex.util.*;
|
||||
import writer2latex.office.*;
|
||||
import writer2latex.latex.util.BeforeAfter;
|
||||
import writer2latex.latex.util.Context;
|
||||
import writer2latex.latex.util.HeadingMap;
|
||||
//import writer2latex.latex.util.StyleMap;
|
||||
|
||||
/* This class converts OpenDocument headings (<code>text:h</code>) and
|
||||
* paragraph styles/formatting into LaTeX
|
||||
* Export of formatting depends on the option "formatting":
|
||||
* <ul>
|
||||
* <li><code>ignore_all</code>
|
||||
* <li><code>ignore_most</code>
|
||||
* <li><code>convert_basic</code>
|
||||
* <li><code>convert_most</code>
|
||||
* <li><code>convert_all</code>
|
||||
* </ul>
|
||||
*/
|
||||
public class HeadingConverter extends ConverterHelper {
|
||||
private String[] sHeadingStyles = new String[11];
|
||||
|
||||
/** Constructs a new <code>HeadingConverter</code>.
|
||||
*/
|
||||
public HeadingConverter(OfficeReader ofr, LaTeXConfig config,
|
||||
ConverterPalette palette) {
|
||||
super(ofr,config,palette);
|
||||
}
|
||||
|
||||
public void appendDeclarations(LaTeXDocumentPortion pack, LaTeXDocumentPortion decl) {
|
||||
appendHeadingStyles(decl);
|
||||
}
|
||||
|
||||
/** Process a heading
|
||||
* @param node The text:h element node containing the heading
|
||||
* @param ldp The LaTeXDocumentPortion to add LaTeX code to
|
||||
* @param oc The current context
|
||||
*/
|
||||
public void handleHeading(Element node, LaTeXDocumentPortion ldp, Context oc) {
|
||||
// Get the level, the heading map and the style name
|
||||
int nLevel = ofr.isOpenDocument() ?
|
||||
Misc.getPosInteger(Misc.getAttribute(node, XMLString.TEXT_OUTLINE_LEVEL),1) :
|
||||
Misc.getPosInteger(Misc.getAttribute(node, XMLString.TEXT_LEVEL),1);
|
||||
HeadingMap hm = config.getHeadingMap();
|
||||
String sStyleName = node.getAttribute(XMLString.TEXT_STYLE_NAME);
|
||||
|
||||
if (nLevel<=hm.getMaxLevel()) {
|
||||
// Always push the font used
|
||||
palette.getI18n().pushSpecialTable(palette.getCharSc().getFontName(ofr.getParStyle(sStyleName)));
|
||||
|
||||
Context ic = (Context) oc.clone();
|
||||
ic.setInSection(true);
|
||||
// Footnotes with more than one paragraph are not allowed within
|
||||
// sections. To be safe, we disallow all footnotes
|
||||
ic.setNoFootnotes(true);
|
||||
|
||||
// Apply style
|
||||
BeforeAfter baHardPage = new BeforeAfter();
|
||||
BeforeAfter baHardChar = new BeforeAfter();
|
||||
applyHardHeadingStyle(nLevel, sStyleName,
|
||||
baHardPage, baHardChar, ic);
|
||||
|
||||
// Export the heading
|
||||
ldp.append(baHardPage.getBefore());
|
||||
ldp.append("\\"+hm.getName(nLevel));
|
||||
// If this heading contains formatting, add optional argument:
|
||||
if (baHardChar.getBefore().length()>0 || containsElements(node)) {
|
||||
ldp.append("[");
|
||||
palette.getInlineCv().traversePlainInlineText(node,ldp,ic);
|
||||
ldp.append("]");
|
||||
}
|
||||
ldp.append("{").append(baHardChar.getBefore());
|
||||
palette.getInlineCv().traverseInlineText(node,ldp,ic);
|
||||
ldp.append(baHardChar.getAfter()).append("}").nl();
|
||||
ldp.append(baHardPage.getAfter());
|
||||
|
||||
// Include pending index marks, labels, footnotes & floating frames
|
||||
palette.getFieldCv().flushReferenceMarks(ldp,oc);
|
||||
palette.getIndexCv().flushIndexMarks(ldp,oc);
|
||||
palette.getNoteCv().flushFootnotes(ldp,oc);
|
||||
palette.getDrawCv().flushFloatingFrames(ldp,ic);
|
||||
|
||||
// Pop the font name
|
||||
palette.getI18n().popSpecialTable();
|
||||
}
|
||||
else { // beyond supported headings - export as ordinary paragraph
|
||||
palette.getParCv().handleParagraph(node,ldp,oc,false);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/** Use a paragraph style on a heading. If hard paragraph formatting
|
||||
* is applied to a heading, page break and font is converted - other
|
||||
* hard formatting is ignored.
|
||||
* This method also collects name of heading style
|
||||
* @param <code>nLevel</code> The level of this heading
|
||||
* @param <code>sStyleName</code> the name of the paragraph style to use
|
||||
* @param <code>baPage</code> a <code>BeforeAfter</code> to put page break code into
|
||||
* @param <code>baText</code> a <code>BeforeAfter</code> to put character formatting code into
|
||||
* @param <code>context</code> the current context. This method will use and update the formatting context
|
||||
*/
|
||||
private void applyHardHeadingStyle(int nLevel, String sStyleName,
|
||||
BeforeAfter baPage, BeforeAfter baText, Context context) {
|
||||
|
||||
// Get the style
|
||||
StyleWithProperties style = ofr.getParStyle(sStyleName);
|
||||
if (style==null) { return; }
|
||||
|
||||
// Register heading style
|
||||
if (sHeadingStyles[nLevel]==null) {
|
||||
sHeadingStyles[nLevel] = style.isAutomatic() ? style.getParentName() : sStyleName;
|
||||
}
|
||||
|
||||
// Do conversion
|
||||
if (style.isAutomatic()) {
|
||||
palette.getPageSc().applyPageBreak(style,false,baPage);
|
||||
palette.getCharSc().applyHardCharFormatting(style,baText);
|
||||
}
|
||||
|
||||
// Update context
|
||||
context.updateFormattingFromStyle(style);
|
||||
}
|
||||
|
||||
|
||||
/** Convert heading styles and outline numbering to LaTeX.
|
||||
* An array of stylenames to use is required: The OOo writer file format
|
||||
* allows different paragraph styles to be applied to individual headings,
|
||||
* so this is not included in the styles.
|
||||
* LaTeX (and OOo Writer!) usually uses the same format for all headings.
|
||||
* @param ldp the LaTeXDocumentPortion to add definitions to.
|
||||
*/
|
||||
// TODO: use method from ListStyleConverter to create labels
|
||||
private void appendHeadingStyles(LaTeXDocumentPortion ldp) {
|
||||
// The user may not want to convert the formatting of headings
|
||||
if (config.formatting()<=LaTeXConfig.IGNORE_MOST) { return; }
|
||||
|
||||
HeadingMap hm = config.getHeadingMap();
|
||||
|
||||
// OK, we are going to convert. First find the max level for headings
|
||||
int nMaxLevel = 0;
|
||||
for (int i=1; i<=5; i++) { if (sHeadingStyles[i]!=null) { nMaxLevel=i; } }
|
||||
if (nMaxLevel==0) { return; } // no headings, nothing to do!
|
||||
if (nMaxLevel>hm.getMaxLevel()) { nMaxLevel = hm.getMaxLevel(); }
|
||||
|
||||
boolean bOnlyNum = config.formatting()==LaTeXConfig.CONVERT_BASIC;
|
||||
if (bOnlyNum) {
|
||||
ldp.append("% Outline numbering").nl();
|
||||
}
|
||||
else {
|
||||
ldp.append("% Headings and outline numbering").nl()
|
||||
.append("\\makeatletter").nl();
|
||||
}
|
||||
|
||||
// Paragraph style for headings:
|
||||
if (!bOnlyNum) {
|
||||
for (int i=1; i<=nMaxLevel; i++) {
|
||||
if (sHeadingStyles[i]!=null) {
|
||||
StyleWithProperties style = ofr.getParStyle(sHeadingStyles[i]);
|
||||
if (style!=null) {
|
||||
BeforeAfter decl = new BeforeAfter();
|
||||
BeforeAfter comm = new BeforeAfter();
|
||||
|
||||
palette.getPageSc().applyPageBreak(style,true,decl);
|
||||
|
||||
palette.getCharSc().applyNormalFont(decl);
|
||||
palette.getCharSc().applyFont(style,true,true,decl,new Context());
|
||||
palette.getParCv().applyAlignment(style,false,true,decl);
|
||||
|
||||
palette.getI18n().applyLanguage(style,false,true,comm);
|
||||
palette.getCharSc().applyFontEffects(style,true,comm);
|
||||
|
||||
String sMarginTop = style.getAbsoluteLength(XMLString.FO_MARGIN_TOP);
|
||||
String sMarginBottom = style.getAbsoluteLength(XMLString.FO_MARGIN_BOTTOM);
|
||||
String sMarginLeft = style.getAbsoluteLength(XMLString.FO_MARGIN_LEFT);
|
||||
|
||||
String sSecName = hm.getName(i);
|
||||
if (!comm.isEmpty()) { // have to create a cs for this heading
|
||||
ldp.append("\\newcommand\\cs").append(sSecName).append("[1]{")
|
||||
.append(comm.getBefore()).append("#1").append(comm.getAfter())
|
||||
.append("}").nl();
|
||||
}
|
||||
ldp.append("\\renewcommand\\").append(sSecName)
|
||||
.append("{\\@startsection{").append(sSecName).append("}{"+hm.getLevel(i))
|
||||
.append("}{"+sMarginLeft+"}{");
|
||||
// Suppress indentation after heading? currently not..
|
||||
// ldp.append("-");
|
||||
ldp.append(sMarginTop)
|
||||
.append("}{").append(sMarginBottom).append("}{");
|
||||
// Note: decl.getAfter() may include a page break after, which we ignore
|
||||
ldp.append(decl.getBefore());
|
||||
if (!comm.isEmpty()) {
|
||||
ldp.append("\\cs").append(sSecName);
|
||||
}
|
||||
ldp.append("}}").nl();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// redefine formatting of section counters
|
||||
// simplified if the user wants to ignore formatting
|
||||
if (!bOnlyNum) {
|
||||
ldp.append("\\renewcommand\\@seccntformat[1]{")
|
||||
.append("\\csname @textstyle#1\\endcsname{\\csname the#1\\endcsname}")
|
||||
.append("\\csname @distance#1\\endcsname}").nl();
|
||||
}
|
||||
|
||||
// Collect numbering styles and set secnumdepth
|
||||
int nSecnumdepth = nMaxLevel;
|
||||
ListStyle outline = ofr.getOutlineStyle();
|
||||
String[] sNumFormat = new String[6];
|
||||
for (int i=nMaxLevel; i>=1; i--) {
|
||||
sNumFormat[i] = ListStyleConverter.numFormat(outline.getLevelProperty(i,
|
||||
XMLString.STYLE_NUM_FORMAT));
|
||||
if (sNumFormat[i]==null || "".equals(sNumFormat[i])) {
|
||||
nSecnumdepth = i-1;
|
||||
}
|
||||
}
|
||||
ldp.append("\\setcounter{secnumdepth}{"+nSecnumdepth+"}").nl();
|
||||
|
||||
for (int i=1; i<=nMaxLevel; i++) {
|
||||
if (sNumFormat[i]==null || "".equals(sNumFormat[i])) {
|
||||
// no numbering at this level
|
||||
if (!bOnlyNum) {
|
||||
ldp.append("\\newcommand\\@distance")
|
||||
.append(hm.getName(i)).append("{}").nl()
|
||||
.append("\\newcommand\\@textstyle")
|
||||
.append(hm.getName(i)).append("[1]{#1}").nl();
|
||||
}
|
||||
}
|
||||
else {
|
||||
if (!bOnlyNum) {
|
||||
// Distance between label and text:
|
||||
String sDistance = outline.getLevelStyleProperty(i,XMLString.TEXT_MIN_LABEL_DISTANCE);
|
||||
ldp.append("\\newcommand\\@distance")
|
||||
.append(hm.getName(i)).append("{");
|
||||
if (sDistance!=null) {
|
||||
ldp.append("\\hspace{").append(sDistance).append("}");
|
||||
}
|
||||
ldp.append("}").nl();
|
||||
// Label width and alignment
|
||||
String sLabelWidth = outline.getLevelStyleProperty(i,XMLString.TEXT_MIN_LABEL_WIDTH);
|
||||
String sTextAlign = outline.getLevelStyleProperty(i,XMLString.FO_TEXT_ALIGN);
|
||||
String sAlignmentChar = "l"; // start (or left) is default
|
||||
if (sTextAlign!=null) {
|
||||
if ("end".equals(sTextAlign)) { sAlignmentChar="r"; }
|
||||
else if ("right".equals(sTextAlign)) { sAlignmentChar="r"; }
|
||||
else if ("center".equals(sTextAlign)) { sAlignmentChar="c"; }
|
||||
}
|
||||
// Textstyle to use for label:
|
||||
String sStyleName = outline.getLevelProperty(i,XMLString.TEXT_STYLE_NAME);
|
||||
// Prefix and suffix text to decorate the label
|
||||
String sPrefix = outline.getLevelProperty(i,XMLString.STYLE_NUM_PREFIX);
|
||||
String sSuffix = outline.getLevelProperty(i,XMLString.STYLE_NUM_SUFFIX);
|
||||
// TODO is this correct?? todo: space-before??? start value???
|
||||
BeforeAfter baText = new BeforeAfter();
|
||||
if (!bOnlyNum) {palette.getCharSc().applyTextStyle(sStyleName,baText,new Context()); }
|
||||
ldp.append("\\newcommand\\@textstyle")
|
||||
.append(hm.getName(i)).append("[1]{");
|
||||
if (!bOnlyNum && sLabelWidth!=null) {
|
||||
ldp.append("\\makebox[").append(sLabelWidth).append("][").append(sAlignmentChar).append("]{");
|
||||
}
|
||||
ldp.append(baText.getBefore())
|
||||
.append(sPrefix!=null ? sPrefix : "")
|
||||
.append("#1")
|
||||
.append(sSuffix!=null ? sSuffix : "")
|
||||
.append(baText.getAfter());
|
||||
if (!bOnlyNum && sLabelWidth!=null) {
|
||||
ldp.append("}");
|
||||
}
|
||||
ldp.append("}").nl();
|
||||
}
|
||||
|
||||
// The label:
|
||||
int nLevels = Misc.getPosInteger(outline.getLevelProperty(i,
|
||||
XMLString.TEXT_DISPLAY_LEVELS),1);
|
||||
ldp.append("\\renewcommand\\the")
|
||||
.append(hm.getName(i))
|
||||
.append("{");
|
||||
for (int j=i-nLevels+1; j<i; j++) {
|
||||
ldp.append(sNumFormat[j])
|
||||
.append("{").append(sectionName(j)).append("}")
|
||||
.append(".");
|
||||
}
|
||||
ldp.append(sNumFormat[i])
|
||||
.append("{").append(hm.getName(i)).append("}")
|
||||
.append("}").nl();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
if (!bOnlyNum) {
|
||||
ldp.append("\\makeatother").nl();
|
||||
}
|
||||
}
|
||||
|
||||
/* Check to see if this node contains any element nodes, except reference marks */
|
||||
public boolean containsElements(Node node) {
|
||||
if (!node.hasChildNodes()) { return false; }
|
||||
NodeList list = node.getChildNodes();
|
||||
int nLen = list.getLength();
|
||||
for (int i = 0; i < nLen; i++) {
|
||||
Node child = list.item(i);
|
||||
if (child.getNodeType()==Node.ELEMENT_NODE &&
|
||||
!child.getNodeName().startsWith(XMLString.TEXT_REFERENCE_MARK)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
static final String sectionName(int nLevel){
|
||||
switch (nLevel) {
|
||||
case 1: return "section";
|
||||
case 2: return "subsection";
|
||||
case 3: return "subsubsection";
|
||||
case 4: return "paragraph";
|
||||
case 5: return "subparagraph";
|
||||
default: return null;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
}
|
242
source/java/writer2latex/latex/IndexConverter.java
Normal file
242
source/java/writer2latex/latex/IndexConverter.java
Normal file
|
@ -0,0 +1,242 @@
|
|||
/************************************************************************
|
||||
*
|
||||
* IndexConverter.java
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License version 2.1, as published by the Free Software Foundation.
|
||||
*
|
||||
* This library 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
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston,
|
||||
* MA 02111-1307 USA
|
||||
*
|
||||
* Copyright: 2002-2008 by Henrik Just
|
||||
*
|
||||
* All Rights Reserved.
|
||||
*
|
||||
* Version 1.0 (2008-11-23)
|
||||
*
|
||||
*/
|
||||
|
||||
package writer2latex.latex;
|
||||
|
||||
import java.util.Vector;
|
||||
|
||||
import org.w3c.dom.Element;
|
||||
//import org.w3c.dom.Node;
|
||||
|
||||
import writer2latex.util.Misc;
|
||||
|
||||
import writer2latex.office.IndexMark;
|
||||
import writer2latex.office.OfficeReader;
|
||||
import writer2latex.office.XMLString;
|
||||
|
||||
import writer2latex.latex.util.Context;
|
||||
|
||||
/**
|
||||
* <p>This class handles indexes (table of contents, list of tables, list of
|
||||
* illustrations, object index, user index, alphabetical index)
|
||||
* as well as their associated index marks.</p>
|
||||
*/
|
||||
public class IndexConverter extends ConverterHelper {
|
||||
|
||||
private boolean bContainsAlphabeticalIndex = false;
|
||||
|
||||
private Vector postponedIndexMarks = new Vector();
|
||||
|
||||
/** <p>Construct a new <code>IndexConverter</code>.
|
||||
* @param config the configuration to use
|
||||
* @param palette the <code>ConverterPalette</code> to link to
|
||||
* if such a document is created by the <code>IndexConverter</code>
|
||||
*/
|
||||
public IndexConverter(OfficeReader ofr,LaTeXConfig config, ConverterPalette palette) {
|
||||
super(ofr,config,palette);
|
||||
}
|
||||
|
||||
/** <p>Append declarations needed by the <code>IndexConverter</code> to
|
||||
* the preamble.
|
||||
* @param pack the <code>LaTeXDocumentPortion</code> to which
|
||||
* declarations of packages should be added (<code>\\usepackage</code>).
|
||||
* @param decl the <code>LaTeXDocumentPortion</code> to which
|
||||
* other declarations should be added.
|
||||
*/
|
||||
public void appendDeclarations(LaTeXDocumentPortion pack, LaTeXDocumentPortion decl) {
|
||||
if (bContainsAlphabeticalIndex) {
|
||||
pack.append("\\usepackage{makeidx}").nl();
|
||||
decl.append("\\makeindex").nl();
|
||||
}
|
||||
}
|
||||
|
||||
/** Process Table of Contents (text:table-of-content tag)
|
||||
* @param node The element containing the Table of Contents
|
||||
* @param ldp the <code>LaTeXDocumentPortion</code> to which
|
||||
* LaTeX code should be added
|
||||
* @param oc the current context
|
||||
*/
|
||||
public void handleTOC (Element node, LaTeXDocumentPortion ldp, Context oc) {
|
||||
if (config.noIndex()) { return; }
|
||||
/* TODO: Apply more formatting by modfification of \l@section etc.
|
||||
Something like this:
|
||||
\newcommand\l@section[2]{\@dottedtocline{1}{1.5em}{2.3em}{\textbf{#1}}{\textit{#2}}
|
||||
Textformatting is trivial; see article.cls for examples of more complicated
|
||||
formatting. Note: The section number can't be formatted indivdually.*/
|
||||
|
||||
Element source = Misc.getChildByTagName(node,XMLString.TEXT_TABLE_OF_CONTENT_SOURCE);
|
||||
if (source!=null) {
|
||||
if ("chapter".equals(source.getAttribute(XMLString.TEXT_INDEX_SOURCE))) {
|
||||
ldp.append("[Warning: Table of content (for this chapter) ignored!]").nl().nl();
|
||||
}
|
||||
else {
|
||||
int nLevel = Misc.getPosInteger(source.getAttribute(XMLString.TEXT_OUTLINE_LEVEL),1);
|
||||
ldp.append("\\setcounter{tocdepth}{"+nLevel+"}").nl();
|
||||
Element title = Misc.getChildByTagName(source,XMLString.TEXT_INDEX_TITLE_TEMPLATE);
|
||||
if (title!=null) {
|
||||
ldp.append("\\renewcommand\\contentsname{");
|
||||
palette.getInlineCv().traversePCDATA(title,ldp,oc);
|
||||
ldp.append("}").nl();
|
||||
}
|
||||
}
|
||||
}
|
||||
ldp.append("\\tableofcontents").nl();
|
||||
}
|
||||
|
||||
/** Process List of Illustrations (text:list-of-illustrations tag)
|
||||
* @param node The element containing the List of Illustrations
|
||||
* @param ldp the <code>LaTeXDocumentPortion</code> to which
|
||||
* LaTeX code should be added
|
||||
* @param oc the current context
|
||||
*/
|
||||
public void handleLOF (Element node, LaTeXDocumentPortion ldp, Context oc) {
|
||||
if (config.noIndex()) { return; }
|
||||
ldp.append("\\listoffigures").nl();
|
||||
}
|
||||
|
||||
/** Process List of Tables (text:list-of-tables tag)
|
||||
* @param node The element containing the List of Tables
|
||||
* @param ldp the <code>LaTeXDocumentPortion</code> to which
|
||||
* LaTeX code should be added
|
||||
* @param oc the current context
|
||||
*/
|
||||
public void handleLOT (Element node, LaTeXDocumentPortion ldp, Context oc) {
|
||||
if (config.noIndex()) { return; }
|
||||
ldp.append("\\listoftables").nl();
|
||||
}
|
||||
|
||||
/** Process Object Index (text:object index tag)
|
||||
* @param node The element containing the Object Index
|
||||
* @param ldp the <code>LaTeXDocumentPortion</code> to which
|
||||
* LaTeX code should be added
|
||||
* @param oc the current context
|
||||
*/
|
||||
public void handleObjectIndex (Element node, LaTeXDocumentPortion ldp, Context oc) {
|
||||
if (config.noIndex()) { return; }
|
||||
ldp.append("[Warning: Object index ignored]").nl().nl();
|
||||
}
|
||||
|
||||
/** Process User Index (text:user-index tag)
|
||||
* @param node The element containing the User Index
|
||||
* @param ldp the <code>LaTeXDocumentPortion</code> to which
|
||||
* LaTeX code should be added
|
||||
* @param oc the current context
|
||||
*/
|
||||
public void handleUserIndex (Element node, LaTeXDocumentPortion ldp, Context oc) {
|
||||
if (config.noIndex()) { return; }
|
||||
ldp.append("[Warning: User index ignored]").nl().nl();
|
||||
}
|
||||
|
||||
|
||||
/** Process Alphabetical Index (text:alphabetical-index tag)
|
||||
* @param node The element containing the Alphabetical Index
|
||||
* @param ldp the <code>LaTeXDocumentPortion</code> to which
|
||||
* LaTeX code should be added
|
||||
* @param oc the current context
|
||||
*/
|
||||
public void handleAlphabeticalIndex (Element node, LaTeXDocumentPortion ldp, Context oc) {
|
||||
if (config.noIndex()) { return; }
|
||||
ldp.append("\\printindex").nl();
|
||||
bContainsAlphabeticalIndex = true;
|
||||
}
|
||||
|
||||
|
||||
/** Process an Alphabetical Index Mark (text:alphabetical-index-mark{-start} tag)
|
||||
* @param node The element containing the Mark
|
||||
* @param ldp the <code>LaTeXDocumentPortion</code> to which
|
||||
* LaTeX code should be added
|
||||
* @param oc the current context
|
||||
*/
|
||||
public void handleAlphabeticalIndexMark(Element node, LaTeXDocumentPortion ldp, Context oc) {
|
||||
if (!oc.isInSection() && !oc.isInCaption() && !oc.isVerbatim()) {
|
||||
String sValue = IndexMark.getIndexValue(node);
|
||||
if (sValue!=null) {
|
||||
ldp.append("\\index{");
|
||||
String sKey1 = IndexMark.getKey1(node);
|
||||
if (sKey1!=null) {
|
||||
writeIndexText(sKey1.trim(),ldp,oc);
|
||||
ldp.append("!");
|
||||
}
|
||||
String sKey2 = IndexMark.getKey2(node);
|
||||
if (sKey2!=null) {
|
||||
writeIndexText(sKey2.trim(),ldp,oc);
|
||||
ldp.append("!");
|
||||
}
|
||||
writeIndexText(sValue.trim(),ldp,oc);
|
||||
ldp.append("}");
|
||||
}
|
||||
}
|
||||
else {
|
||||
// Index marks should not appear within \section or \caption
|
||||
postponedIndexMarks.add(node);
|
||||
}
|
||||
}
|
||||
|
||||
public void flushIndexMarks(LaTeXDocumentPortion ldp, Context oc) {
|
||||
// We may still be in a context with no index marks
|
||||
if (!oc.isInSection() && !oc.isInCaption() && !oc.isVerbatim()) {
|
||||
// Type out all postponed index marks
|
||||
int n = postponedIndexMarks.size();
|
||||
for (int i=0; i<n; i++) {
|
||||
handleAlphabeticalIndexMark((Element) postponedIndexMarks.get(i),ldp,oc);
|
||||
}
|
||||
postponedIndexMarks.clear();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// Helper: Write the text of an index mark, escaping special characters
|
||||
private void writeIndexText(String sText, LaTeXDocumentPortion ldp, Context oc) {
|
||||
String sTextOut = palette.getI18n().convert(sText,false,oc.getLang());
|
||||
// need to escape !, @, | and ":
|
||||
int nLen = sTextOut.length();
|
||||
boolean bBackslash = false;
|
||||
for (int i=0; i<nLen; i++) {
|
||||
if (bBackslash) {
|
||||
ldp.append(sTextOut.substring(i,i+1));
|
||||
bBackslash = false;
|
||||
}
|
||||
else {
|
||||
switch (sTextOut.charAt(i)) {
|
||||
case '\\' : bBackslash = true;
|
||||
ldp.append("\\");
|
||||
break;
|
||||
case '~' :
|
||||
case '\u00A0' :
|
||||
// Non-breaking space causes trouble in index:
|
||||
ldp.append(" ");
|
||||
break;
|
||||
case '!' :
|
||||
case '@' :
|
||||
case '|' :
|
||||
case '"' : ldp.append("\"");
|
||||
default : ldp.append(sTextOut.substring(i,i+1));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
636
source/java/writer2latex/latex/InlineConverter.java
Normal file
636
source/java/writer2latex/latex/InlineConverter.java
Normal file
|
@ -0,0 +1,636 @@
|
|||
/************************************************************************
|
||||
*
|
||||
* InlineConverter.java
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License version 2.1, as published by the Free Software Foundation.
|
||||
*
|
||||
* This library 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
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston,
|
||||
* MA 02111-1307 USA
|
||||
*
|
||||
* Copyright: 2002-2008 by Henrik Just
|
||||
*
|
||||
* All Rights Reserved.
|
||||
*
|
||||
* Version 1.0 (2008-11-22)
|
||||
*
|
||||
*/
|
||||
|
||||
package writer2latex.latex;
|
||||
|
||||
import org.w3c.dom.Element;
|
||||
import org.w3c.dom.Node;
|
||||
import org.w3c.dom.NodeList;
|
||||
|
||||
import writer2latex.util.Misc;
|
||||
import writer2latex.office.OfficeReader;
|
||||
import writer2latex.office.StyleWithProperties;
|
||||
import writer2latex.office.XMLString;
|
||||
import writer2latex.latex.util.BeforeAfter;
|
||||
import writer2latex.latex.util.Context;
|
||||
import writer2latex.latex.util.HeadingMap;
|
||||
|
||||
/**
|
||||
* <p>This class handles basic inline text.</p>
|
||||
*/
|
||||
public class InlineConverter extends ConverterHelper {
|
||||
|
||||
private String sTabstop = "\\ \\ ";
|
||||
private boolean bHasPdfannotation = false;
|
||||
|
||||
public InlineConverter(OfficeReader ofr, LaTeXConfig config, ConverterPalette palette) {
|
||||
super(ofr,config,palette);
|
||||
// Get custom code for tab stops
|
||||
if (config.getTabstop().length()>0) {
|
||||
sTabstop = config.getTabstop();
|
||||
}
|
||||
}
|
||||
|
||||
public void appendDeclarations(LaTeXDocumentPortion pack, LaTeXDocumentPortion decl) {
|
||||
if (bHasPdfannotation) {
|
||||
decl.append("\\newcommand\\pdfannotation[1]")
|
||||
.append("{\\ifx\\pdfoutput\\undefined\\marginpar{#1}\\else")
|
||||
.append("\\pdfstringdef\\tempstring{#1}\\marginpar{")
|
||||
.append("\\pdfannot width 5cm height 12pt depth 4cm ")
|
||||
.append("{ /Subtype /Text /Open false /Contents(\\tempstring) /Color [1 0 0]}")
|
||||
.append("}\\fi}").nl();
|
||||
}
|
||||
}
|
||||
|
||||
/** Handle a text:span element
|
||||
*/
|
||||
public void handleTextSpan(Element node, LaTeXDocumentPortion ldp, Context oc) {
|
||||
if (oc.isMathMode()) { handleTextSpanMath(node, ldp, oc); }
|
||||
else { handleTextSpanText(node, ldp, oc); }
|
||||
}
|
||||
|
||||
private void handleTextSpanMath(Element node, LaTeXDocumentPortion ldp, Context oc) {
|
||||
// TODO: Handle a selection of formatting attributes: color, supscript...
|
||||
String sStyleName = node.getAttribute(XMLString.TEXT_STYLE_NAME);
|
||||
StyleWithProperties style = ofr.getTextStyle(sStyleName);
|
||||
|
||||
// Always push the font used
|
||||
palette.getI18n().pushSpecialTable(palette.getCharSc().getFontName(style));
|
||||
|
||||
// Convert formatting
|
||||
BeforeAfter ba = new BeforeAfter();
|
||||
if (style!=null) {
|
||||
String sPos = style.getProperty(XMLString.STYLE_TEXT_POSITION, true);
|
||||
if (sPos!=null) {
|
||||
if (sPos.startsWith("sub") || sPos.startsWith("-")) {
|
||||
ba.add("_{", "}");
|
||||
}
|
||||
else if (sPos.startsWith("super") || !sPos.startsWith("0%")) {
|
||||
ba.add("^{", "}");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
ldp.append(ba.getBefore());
|
||||
traverseInlineMath(node, ldp, oc);
|
||||
ldp.append(ba.getAfter());
|
||||
|
||||
// finally pop the font table
|
||||
palette.getI18n().popSpecialTable();
|
||||
}
|
||||
|
||||
private void handleTextSpanText(Element node, LaTeXDocumentPortion ldp, Context oc) {
|
||||
String styleName = node.getAttribute(XMLString.TEXT_STYLE_NAME);
|
||||
|
||||
// Check for strict handling of styles
|
||||
String sDisplayName = ofr.getTextStyles().getDisplayName(styleName);
|
||||
if (config.otherStyles()!=LaTeXConfig.ACCEPT && !config.getTextStyleMap().contains(sDisplayName)) {
|
||||
if (config.otherStyles()==LaTeXConfig.WARNING) {
|
||||
System.err.println("Warning: Text with style "+sDisplayName+" was ignored");
|
||||
}
|
||||
else if (config.otherStyles()==LaTeXConfig.ERROR) {
|
||||
ldp.append("% Error in source document: Text with style ")
|
||||
.append(palette.getI18n().convert(sDisplayName,false,oc.getLang()))
|
||||
.append(" was ignored").nl();
|
||||
}
|
||||
// Ignore this text:
|
||||
return;
|
||||
}
|
||||
|
||||
boolean styled = true;
|
||||
|
||||
// don't style it if a {foot|end}note is the only content
|
||||
if (onlyNote(node) || OfficeReader.getCharacterCount(node)==0) { styled = false; }
|
||||
|
||||
// Also don't style it if we're already within a verbatim environment
|
||||
if (oc.isVerbatim()) { styled = false; }
|
||||
|
||||
boolean bNoFootnotes = false;
|
||||
|
||||
// Always push the font used
|
||||
palette.getI18n().pushSpecialTable(palette.getCharSc().getFontName(ofr.getTextStyle(styleName)));
|
||||
|
||||
// Apply the style
|
||||
BeforeAfter ba = new BeforeAfter();
|
||||
Context ic = (Context) oc.clone();
|
||||
if (styled) { palette.getCharSc().applyTextStyle(styleName,ba,ic); }
|
||||
|
||||
// Footnote problems:
|
||||
// No footnotes in sub/superscript (will disappear)
|
||||
// No multiparagraph footnotes embedded in text command (eg. \textbf{..})
|
||||
// Simple solution: styled text element is forbidden footnote area
|
||||
if (styled && !ic.isInFootnote()) { bNoFootnotes = true; }
|
||||
|
||||
// Temp solution: Ignore hard formatting in header/footer (name clash problem)
|
||||
// only in package format.
|
||||
StyleWithProperties style = ofr.getTextStyle(styleName);
|
||||
if (ofr.isPackageFormat() && (style!=null && style.isAutomatic()) && ic.isInHeaderFooter()) {
|
||||
styled = false;
|
||||
}
|
||||
|
||||
if (styled) {
|
||||
if (bNoFootnotes) { ic.setNoFootnotes(true); }
|
||||
ldp.append(ba.getBefore());
|
||||
}
|
||||
|
||||
traverseInlineText(node,ldp,ic);
|
||||
|
||||
if (styled) {
|
||||
ldp.append(ba.getAfter());
|
||||
ic.setNoFootnotes(false);
|
||||
if (!ic.isInFootnote()) { palette.getNoteCv().flushFootnotes(ldp,oc); }
|
||||
}
|
||||
|
||||
// Flush any pending index marks and reference marks
|
||||
palette.getFieldCv().flushReferenceMarks(ldp,oc);
|
||||
palette.getIndexCv().flushIndexMarks(ldp,oc);
|
||||
|
||||
// finally pop the special table
|
||||
palette.getI18n().popSpecialTable();
|
||||
}
|
||||
|
||||
public void traverseInlineText(Element node, LaTeXDocumentPortion ldp, Context oc) {
|
||||
if (oc.isVerbatim()) {
|
||||
traverseVerbatimInlineText(node,ldp,oc);
|
||||
}
|
||||
else if (oc.isMathMode()) {
|
||||
traverseInlineMath(node,ldp,oc);
|
||||
}
|
||||
else {
|
||||
traverseOrdinaryInlineText(node,ldp,oc);
|
||||
}
|
||||
}
|
||||
|
||||
// Traverse ordinary inline text in text mode (temporarily changing to math
|
||||
// mode for a sequence of text:span with style "OOoLaTeX")
|
||||
private void traverseOrdinaryInlineText(Element node,LaTeXDocumentPortion ldp, Context oc) {
|
||||
Node childNode = node.getFirstChild();
|
||||
while (childNode!=null) {
|
||||
short nodeType = childNode.getNodeType();
|
||||
|
||||
switch (nodeType) {
|
||||
case Node.TEXT_NODE:
|
||||
String s = childNode.getNodeValue();
|
||||
if (s.length() > 0) {
|
||||
ldp.append(palette.getI18n().convert(s, false, oc.getLang()));
|
||||
}
|
||||
break;
|
||||
|
||||
case Node.ELEMENT_NODE:
|
||||
Element child = (Element)childNode;
|
||||
String sName = child.getTagName();
|
||||
if (sName.equals(XMLString.TEXT_SPAN)) {
|
||||
String sStyleName = child.getAttribute(XMLString.TEXT_STYLE_NAME);
|
||||
boolean bIsMathSpan = "OOoLaTeX".equals(ofr.getTextStyles().getDisplayName(sStyleName));
|
||||
if (bIsMathSpan) {
|
||||
// Temporarily change to math mode
|
||||
Context ic = (Context) oc.clone();
|
||||
ic.setMathMode(true);
|
||||
|
||||
ldp.append("$");
|
||||
|
||||
Node remember;
|
||||
boolean bContinue = false;
|
||||
|
||||
do {
|
||||
handleTextSpanMath((Element)childNode, ldp, ic);
|
||||
remember = childNode;
|
||||
childNode = childNode.getNextSibling();
|
||||
bContinue = false;
|
||||
if (childNode!=null && childNode.getNodeType()==Node.ELEMENT_NODE &&
|
||||
childNode.getNodeName().equals(XMLString.TEXT_SPAN)) {
|
||||
sStyleName = Misc.getAttribute(childNode,XMLString.TEXT_STYLE_NAME);
|
||||
if ("OOoLaTeX".equals(ofr.getTextStyles().getDisplayName(sStyleName)))
|
||||
//child = (Element) childNode;
|
||||
bContinue = true;
|
||||
}
|
||||
} while(bContinue);
|
||||
childNode = remember;
|
||||
|
||||
ldp.append("$");
|
||||
}
|
||||
else {
|
||||
handleTextSpan(child,ldp,oc);
|
||||
}
|
||||
}
|
||||
else if (child.getNodeName().startsWith("draw:")) {
|
||||
palette.getDrawCv().handleDrawElement(child,ldp,oc);
|
||||
}
|
||||
else if (sName.equals(XMLString.TEXT_S)) {
|
||||
if (config.ignoreDoubleSpaces()) {
|
||||
ldp.append(" ");
|
||||
}
|
||||
else {
|
||||
int count= Misc.getPosInteger(child.getAttribute(XMLString.TEXT_C),1);
|
||||
//String sSpace = config.ignoreDoubleSpaces() ? " " : "\\ ";
|
||||
for ( ; count > 0; count--) { ldp.append("\\ "); }
|
||||
}
|
||||
}
|
||||
else if (sName.equals(XMLString.TEXT_TAB_STOP) || sName.equals(XMLString.TEXT_TAB)) { // text:tab in oasis
|
||||
// tab stops are not supported by the converter, but the special usage
|
||||
// of tab stops in header and footer can be emulated with \hfill
|
||||
// TODO: Sometimes extra \hfill should be added at end of line
|
||||
if (oc.isInHeaderFooter()) { ldp.append("\\hfill "); }
|
||||
else { ldp.append(sTabstop); }
|
||||
}
|
||||
else if (sName.equals(XMLString.TEXT_LINE_BREAK)) {
|
||||
if (!oc.isInHeaderFooter() && !config.ignoreHardLineBreaks()) {
|
||||
ldp.append("\\newline").nl();
|
||||
}
|
||||
else { ldp.append(" "); }
|
||||
}
|
||||
else if (sName.equals(XMLString.TEXT_A)) {
|
||||
palette.getFieldCv().handleAnchor(child,ldp,oc);
|
||||
}
|
||||
else if (sName.equals(XMLString.OFFICE_ANNOTATION)) {
|
||||
handleOfficeAnnotation(child,ldp,oc);
|
||||
}
|
||||
else if (sName.equals(XMLString.TEXT_PAGE_NUMBER)) {
|
||||
palette.getFieldCv().handlePageNumber(child,ldp,oc);
|
||||
}
|
||||
else if (sName.equals(XMLString.TEXT_PAGE_COUNT)) {
|
||||
palette.getFieldCv().handlePageCount(child,ldp,oc);
|
||||
}
|
||||
else if (oc.isInHeaderFooter()) {
|
||||
if (sName.equals(XMLString.TEXT_CHAPTER)) {
|
||||
handleChapterField(child,ldp,oc);
|
||||
}
|
||||
else if (sName.startsWith("text:")) {
|
||||
traverseInlineText(child,ldp,oc);
|
||||
}
|
||||
}
|
||||
else {
|
||||
// These tags are ignored in header and footer
|
||||
if (sName.equals(XMLString.TEXT_FOOTNOTE)) {
|
||||
palette.getNoteCv().handleFootnote(child,ldp,oc);
|
||||
}
|
||||
else if (sName.equals(XMLString.TEXT_ENDNOTE)) {
|
||||
palette.getNoteCv().handleEndnote(child,ldp,oc);
|
||||
}
|
||||
else if (sName.equals(XMLString.TEXT_NOTE)) {
|
||||
if ("endnote".equals(child.getAttribute(XMLString.TEXT_NOTE_CLASS))) {
|
||||
palette.getNoteCv().handleEndnote(child,ldp,oc);
|
||||
}
|
||||
else {
|
||||
palette.getNoteCv().handleFootnote(child,ldp,oc);
|
||||
}
|
||||
}
|
||||
else if (sName.equals(XMLString.TEXT_SEQUENCE)) {
|
||||
palette.getFieldCv().handleSequence(child,ldp,oc);
|
||||
}
|
||||
else if (sName.equals(XMLString.TEXT_SEQUENCE_REF)) {
|
||||
palette.getFieldCv().handleSequenceRef(child,ldp,oc);
|
||||
}
|
||||
else if (sName.equals(XMLString.TEXT_FOOTNOTE_REF)) {
|
||||
palette.getNoteCv().handleFootnoteRef(child,ldp,oc);
|
||||
}
|
||||
else if (sName.equals(XMLString.TEXT_ENDNOTE_REF)) {
|
||||
palette.getNoteCv().handleEndnoteRef(child,ldp,oc);
|
||||
}
|
||||
else if (sName.equals(XMLString.TEXT_NOTE_REF)) { // oasis
|
||||
palette.getNoteCv().handleNoteRef(child,ldp,oc);
|
||||
}
|
||||
else if (sName.equals(XMLString.TEXT_REFERENCE_MARK)) {
|
||||
palette.getFieldCv().handleReferenceMark(child,ldp,oc);
|
||||
}
|
||||
else if (sName.equals(XMLString.TEXT_REFERENCE_MARK_START)) {
|
||||
palette.getFieldCv().handleReferenceMark(child,ldp,oc);
|
||||
}
|
||||
else if (sName.equals(XMLString.TEXT_REFERENCE_REF)) {
|
||||
palette.getFieldCv().handleReferenceRef(child,ldp,oc);
|
||||
}
|
||||
else if (sName.equals(XMLString.TEXT_BOOKMARK)) {
|
||||
palette.getFieldCv().handleBookmark(child,ldp,oc);
|
||||
}
|
||||
else if (sName.equals(XMLString.TEXT_BOOKMARK_START)) {
|
||||
palette.getFieldCv().handleBookmark(child,ldp,oc);
|
||||
}
|
||||
else if (sName.equals(XMLString.TEXT_BOOKMARK_REF)) {
|
||||
palette.getFieldCv().handleBookmarkRef(child,ldp,oc);
|
||||
}
|
||||
else if (sName.equals(XMLString.TEXT_BIBLIOGRAPHY_MARK)) {
|
||||
palette.getBibCv().handleBibliographyMark(child,ldp,oc);
|
||||
}
|
||||
else if (sName.equals(XMLString.TEXT_ALPHABETICAL_INDEX_MARK)) {
|
||||
palette.getIndexCv().handleAlphabeticalIndexMark(child,ldp,oc);
|
||||
}
|
||||
else if (sName.equals(XMLString.TEXT_ALPHABETICAL_INDEX_MARK_START)) {
|
||||
palette.getIndexCv().handleAlphabeticalIndexMark(child,ldp,oc);
|
||||
}
|
||||
else if (sName.startsWith("text:")) {
|
||||
traverseInlineText(child,ldp,oc);
|
||||
}
|
||||
}
|
||||
break;
|
||||
default:
|
||||
// Do nothing
|
||||
}
|
||||
|
||||
childNode = childNode.getNextSibling();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/* traverse inline text, ignoring any draw objects, footnotes, formatting and hyperlinks */
|
||||
public void traversePlainInlineText(Element node,LaTeXDocumentPortion ldp, Context oc) {
|
||||
String styleName = node.getAttribute(XMLString.TEXT_STYLE_NAME);
|
||||
|
||||
// Always push the font used
|
||||
palette.getI18n().pushSpecialTable(palette.getCharSc().getFontName(ofr.getTextStyle(styleName)));
|
||||
|
||||
Node childNode = node.getFirstChild();
|
||||
while (childNode!=null) {
|
||||
short nodeType = childNode.getNodeType();
|
||||
|
||||
switch (nodeType) {
|
||||
case Node.TEXT_NODE:
|
||||
String s = childNode.getNodeValue();
|
||||
if (s.length() > 0) {
|
||||
// Need to protect ]
|
||||
for (int j=0; j<s.length(); j++) {
|
||||
if (s.charAt(j)!=']') {
|
||||
ldp.append(palette.getI18n().convert(Character.toString(s.charAt(j)),false,oc.getLang()));
|
||||
}
|
||||
else {
|
||||
ldp.append("{]}");
|
||||
}
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case Node.ELEMENT_NODE:
|
||||
Element child = (Element)childNode;
|
||||
String sName = child.getTagName();
|
||||
if (sName.equals(XMLString.TEXT_SPAN)) {
|
||||
traversePlainInlineText(child,ldp,oc);
|
||||
}
|
||||
else if (sName.equals(XMLString.TEXT_S)) {
|
||||
int count= Misc.getPosInteger(child.getAttribute(XMLString.TEXT_C),1);
|
||||
for ( ; count > 0; count--) {
|
||||
ldp.append("\\ ");
|
||||
}
|
||||
}
|
||||
else if (sName.equals(XMLString.TEXT_TAB_STOP) || sName.equals(XMLString.TEXT_TAB)) { // text:tab in oasis
|
||||
// tab stops are not supported by the converter
|
||||
ldp.append(sTabstop);
|
||||
}
|
||||
else if (OfficeReader.isNoteElement(child)) {
|
||||
// ignore
|
||||
}
|
||||
else if (OfficeReader.isTextElement(child)) {
|
||||
traversePlainInlineText(child,ldp,oc);
|
||||
}
|
||||
break;
|
||||
default:
|
||||
// Do nothing
|
||||
}
|
||||
childNode = childNode.getNextSibling();
|
||||
}
|
||||
// finally pop the special table
|
||||
palette.getI18n().popSpecialTable();
|
||||
}
|
||||
|
||||
/* traverse inline math, ignoring any draw objects, footnotes, formatting and hyperlinks */
|
||||
public void traverseInlineMath(Element node,LaTeXDocumentPortion ldp, Context oc) {
|
||||
String styleName = node.getAttribute(XMLString.TEXT_STYLE_NAME);
|
||||
|
||||
// Always push the font used
|
||||
palette.getI18n().pushSpecialTable(palette.getCharSc().getFontName(ofr.getTextStyle(styleName)));
|
||||
|
||||
Node childNode = node.getFirstChild();
|
||||
while (childNode!=null) {
|
||||
short nodeType = childNode.getNodeType();
|
||||
|
||||
switch (nodeType) {
|
||||
case Node.TEXT_NODE:
|
||||
String s = childNode.getNodeValue();
|
||||
ldp.append(palette.getI18n().convert(s,true,oc.getLang()));
|
||||
break;
|
||||
|
||||
case Node.ELEMENT_NODE:
|
||||
Element child = (Element)childNode;
|
||||
String sName = child.getTagName();
|
||||
if (sName.equals(XMLString.TEXT_S)) {
|
||||
int count= Misc.getPosInteger(child.getAttribute(XMLString.TEXT_C),1);
|
||||
for ( ; count > 0; count--) {
|
||||
ldp.append("\\ ");
|
||||
}
|
||||
}
|
||||
else if (sName.equals(XMLString.TEXT_TAB_STOP) || sName.equals(XMLString.TEXT_TAB)) { // text:tab in oasis
|
||||
// tab stops are not supported by the converter
|
||||
ldp.append(" ");
|
||||
}
|
||||
else if (OfficeReader.isNoteElement(child)) {
|
||||
// ignore
|
||||
}
|
||||
else if (OfficeReader.isTextElement(child)) {
|
||||
traversePlainInlineText(child,ldp,oc);
|
||||
}
|
||||
break;
|
||||
default:
|
||||
// Do nothing
|
||||
}
|
||||
childNode = childNode.getNextSibling();
|
||||
}
|
||||
// finally pop the special table
|
||||
palette.getI18n().popSpecialTable();
|
||||
}
|
||||
|
||||
/* traverse verbatim inline text, ignoring any draw objects, footnotes, formatting and hyperlinks */
|
||||
private void traverseVerbatimInlineText(Element node,LaTeXDocumentPortion ldp, Context oc) {
|
||||
if (node.hasChildNodes()) {
|
||||
|
||||
NodeList nList = node.getChildNodes();
|
||||
int len = nList.getLength();
|
||||
|
||||
for (int i = 0; i < len; i++) {
|
||||
|
||||
Node childNode = nList.item(i);
|
||||
short nodeType = childNode.getNodeType();
|
||||
|
||||
switch (nodeType) {
|
||||
case Node.TEXT_NODE:
|
||||
String s = childNode.getNodeValue();
|
||||
if (s.length() > 0) {
|
||||
// text is copied verbatim! (Will be replaced by
|
||||
// question marks if outside inputenc)
|
||||
ldp.append(s);
|
||||
}
|
||||
break;
|
||||
|
||||
case Node.ELEMENT_NODE:
|
||||
Element child = (Element)childNode;
|
||||
String sName = child.getTagName();
|
||||
if (sName.equals(XMLString.TEXT_S)) {
|
||||
int count= Misc.getPosInteger(child.getAttribute(XMLString.TEXT_C),1);
|
||||
for ( ; count > 0; count--) {
|
||||
ldp.append(" ");
|
||||
}
|
||||
}
|
||||
else if (sName.equals(XMLString.TEXT_TAB_STOP) || sName.equals(XMLString.TEXT_TAB)) { // text:tab in oasis
|
||||
// tab stops are not supported by the onverter
|
||||
ldp.append(sTabstop);
|
||||
}
|
||||
else if (sName.equals(XMLString.TEXT_LINE_BREAK)) {
|
||||
if (!oc.isNoLineBreaks()) { ldp.nl(); }
|
||||
}
|
||||
else if (sName.equals(XMLString.TEXT_NOTE)) {
|
||||
// oasis; ignore
|
||||
}
|
||||
else if (sName.equals(XMLString.TEXT_FOOTNOTE)) {
|
||||
// ignore
|
||||
}
|
||||
else if (sName.equals(XMLString.TEXT_ENDNOTE)) {
|
||||
// ignore
|
||||
}
|
||||
// The respective handlers know how to postpone these marks in verbatim context:
|
||||
else if (sName.equals(XMLString.TEXT_ALPHABETICAL_INDEX_MARK)) {
|
||||
palette.getIndexCv().handleAlphabeticalIndexMark(child,ldp,oc);
|
||||
}
|
||||
else if (sName.equals(XMLString.TEXT_ALPHABETICAL_INDEX_MARK_START)) {
|
||||
palette.getIndexCv().handleAlphabeticalIndexMark(child,ldp,oc);
|
||||
}
|
||||
else if (sName.equals(XMLString.TEXT_REFERENCE_MARK)) {
|
||||
palette.getFieldCv().handleReferenceMark(child,ldp,oc);
|
||||
}
|
||||
else if (sName.equals(XMLString.TEXT_REFERENCE_MARK_START)) {
|
||||
palette.getFieldCv().handleReferenceMark(child,ldp,oc);
|
||||
}
|
||||
else if (sName.equals(XMLString.TEXT_BOOKMARK)) {
|
||||
palette.getFieldCv().handleBookmark(child,ldp,oc);
|
||||
}
|
||||
else if (sName.equals(XMLString.TEXT_BOOKMARK_START)) {
|
||||
palette.getFieldCv().handleBookmark(child,ldp,oc);
|
||||
}
|
||||
|
||||
else if (sName.startsWith("text:")) {
|
||||
traverseVerbatimInlineText(child,ldp,oc);
|
||||
}
|
||||
break;
|
||||
default:
|
||||
// Do nothing
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void traversePCDATA(Element node, LaTeXDocumentPortion ldp, Context oc) {
|
||||
if (node.hasChildNodes()) {
|
||||
NodeList nl = node.getChildNodes();
|
||||
int nLen = nl.getLength();
|
||||
for (int i=0; i<nLen; i++) {
|
||||
if (nl.item(i).getNodeType()==Node.TEXT_NODE) {
|
||||
ldp.append(palette.getI18n().convert(nl.item(i).getNodeValue(),false,oc.getLang()));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void handleChapterField(Element node, LaTeXDocumentPortion ldp, Context oc) {
|
||||
HeadingMap hm = config.getHeadingMap();
|
||||
int nLevel = Misc.getPosInteger(node.getAttribute(XMLString.TEXT_OUTLINE_LEVEL),1);
|
||||
if (nLevel<=hm.getMaxLevel()) {
|
||||
int nLaTeXLevel = hm.getLevel(nLevel);
|
||||
if (nLaTeXLevel==1) {
|
||||
palette.getPageSc().setChapterField1(node.getAttribute(XMLString.TEXT_DISPLAY));
|
||||
ldp.append("{\\leftmark}");
|
||||
}
|
||||
else if (nLaTeXLevel==2) {
|
||||
palette.getPageSc().setChapterField2(node.getAttribute(XMLString.TEXT_DISPLAY));
|
||||
ldp.append("{\\rightmark}");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Annotations
|
||||
|
||||
private void handleOfficeAnnotation(Element node, LaTeXDocumentPortion ldp, Context oc) {
|
||||
String sCommand = null;
|
||||
switch (config.notes()) {
|
||||
case LaTeXConfig.IGNORE: return;
|
||||
case LaTeXConfig.COMMENT:
|
||||
// Get the unformatted text of all paragraphs and insert each paragraph as a single comment
|
||||
ldp.append("%").nl();
|
||||
Node child = node.getFirstChild();
|
||||
while (child!=null) {
|
||||
if (Misc.isElement(child, XMLString.TEXT_P)) {
|
||||
ldp.append("%");
|
||||
traversePlainInlineText((Element)child, ldp, oc);
|
||||
ldp.nl();
|
||||
}
|
||||
child = child.getNextSibling();
|
||||
}
|
||||
return;
|
||||
case LaTeXConfig.PDFANNOTATION:
|
||||
bHasPdfannotation = true;
|
||||
sCommand = "\\pdfannotation";
|
||||
break;
|
||||
case LaTeXConfig.MARGINPAR:
|
||||
sCommand = "\\marginpar";
|
||||
break;
|
||||
case LaTeXConfig.CUSTOM:
|
||||
sCommand = config.getNotesCommand();
|
||||
break;
|
||||
}
|
||||
|
||||
// Get the unformatted text of all paragraphs, separated by spaces
|
||||
ldp.append(sCommand).append("{");
|
||||
boolean bFirst = true;
|
||||
Node child = node.getFirstChild();
|
||||
while (child!=null) {
|
||||
if (Misc.isElement(child, XMLString.TEXT_P)) {
|
||||
if (!bFirst) ldp.append(" ");
|
||||
traversePlainInlineText((Element)child, ldp, oc);
|
||||
bFirst = false;
|
||||
}
|
||||
child = child.getNextSibling();
|
||||
|
||||
}
|
||||
ldp.append("}");
|
||||
}
|
||||
|
||||
/* Check to see if this node has a footnote or endnote as the only subnode */
|
||||
private boolean onlyNote(Node node) {
|
||||
if (!node.hasChildNodes()) { return false; }
|
||||
NodeList nList = node.getChildNodes();
|
||||
int nLen = nList.getLength();
|
||||
|
||||
for (int i = 0; i < nLen; i++) {
|
||||
|
||||
Node child = nList.item(i);
|
||||
short nType = child.getNodeType();
|
||||
|
||||
switch (nType) {
|
||||
case Node.TEXT_NODE: return false;
|
||||
case Node.ELEMENT_NODE:
|
||||
if (!OfficeReader.isNoteElement(child)) { return false; }
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
}
|
543
source/java/writer2latex/latex/LaTeXConfig.java
Normal file
543
source/java/writer2latex/latex/LaTeXConfig.java
Normal file
|
@ -0,0 +1,543 @@
|
|||
/************************************************************************
|
||||
*
|
||||
* LaTeXConfig.java
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License version 2.1, as published by the Free Software Foundation.
|
||||
*
|
||||
* This library 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
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston,
|
||||
* MA 02111-1307 USA
|
||||
*
|
||||
* Copyright: 2002-2009 by Henrik Just
|
||||
*
|
||||
* All Rights Reserved.
|
||||
*
|
||||
* Version 1.0 (2009-02-17)
|
||||
*
|
||||
*/
|
||||
|
||||
package writer2latex.latex;
|
||||
|
||||
import java.util.LinkedList;
|
||||
import java.util.Hashtable;
|
||||
import java.util.Enumeration;
|
||||
|
||||
import org.w3c.dom.Document;
|
||||
import org.w3c.dom.Node;
|
||||
import org.w3c.dom.Element;
|
||||
|
||||
import writer2latex.base.BooleanOption;
|
||||
import writer2latex.base.IntegerOption;
|
||||
import writer2latex.base.Option;
|
||||
import writer2latex.latex.util.HeadingMap;
|
||||
import writer2latex.latex.i18n.ClassicI18n;
|
||||
import writer2latex.latex.i18n.ReplacementTrie;
|
||||
import writer2latex.latex.util.StyleMap;
|
||||
import writer2latex.util.Misc;
|
||||
|
||||
public class LaTeXConfig extends writer2latex.base.ConfigBase {
|
||||
protected int getOptionCount() { return 59; }
|
||||
protected String getDefaultConfigPath() { return "/writer2latex/latex/config/"; }
|
||||
|
||||
// Override setOption to be backwards compatible
|
||||
public void setOption(String sName,String sValue) {
|
||||
// this option has been renamed:
|
||||
if (sName.equals("keep_image_size")) { sName = "original_image_size"; }
|
||||
super.setOption(sName, sValue);
|
||||
}
|
||||
|
||||
// Backend
|
||||
public static final int GENERIC = 0;
|
||||
public static final int DVIPS = 1;
|
||||
public static final int PDFTEX = 2;
|
||||
public static final int UNSPECIFIED = 3;
|
||||
public static final int XETEX = 4;
|
||||
|
||||
// Formatting (must be ordered)
|
||||
public static final int IGNORE_ALL = 0;
|
||||
public static final int IGNORE_MOST = 1;
|
||||
public static final int CONVERT_BASIC = 2;
|
||||
public static final int CONVERT_MOST = 3;
|
||||
public static final int CONVERT_ALL = 4;
|
||||
// Page formatting
|
||||
public static final int CONVERT_HEADER_FOOTER = 5;
|
||||
// Handling of other formatting
|
||||
public static final int IGNORE = 0;
|
||||
public static final int ACCEPT = 1;
|
||||
public static final int WARNING = 2;
|
||||
public static final int ERROR = 3;
|
||||
|
||||
// Notes
|
||||
//public static final int IGNORE = 0;
|
||||
public static final int COMMENT = 1;
|
||||
public static final int PDFANNOTATION = 2;
|
||||
public static final int MARGINPAR = 3;
|
||||
public static final int CUSTOM = 4;
|
||||
|
||||
// Options
|
||||
protected int OPTION_COUNT = 59;
|
||||
|
||||
private static final int BACKEND = 0;
|
||||
private static final int NO_PREAMBLE = 1;
|
||||
private static final int NO_INDEX = 2;
|
||||
private static final int DOCUMENTCLASS = 3;
|
||||
private static final int GLOBAL_OPTIONS = 4;
|
||||
private static final int INPUTENCODING = 5;
|
||||
private static final int MULTILINGUAL = 6;
|
||||
private static final int GREEK_MATH = 7;
|
||||
private static final int USE_OOOMATH = 8;
|
||||
private static final int USE_PIFONT = 9;
|
||||
private static final int USE_IFSYM = 10;
|
||||
private static final int USE_WASYSYM = 11;
|
||||
private static final int USE_BBDING = 12;
|
||||
private static final int USE_EUROSYM = 13;
|
||||
private static final int USE_TIPA = 14;
|
||||
private static final int USE_COLOR = 15;
|
||||
private static final int USE_COLORTBL = 16;
|
||||
private static final int USE_GEOMETRY = 17;
|
||||
private static final int USE_FANCYHDR = 18;
|
||||
private static final int USE_HYPERREF = 19;
|
||||
private static final int USE_CAPTION = 20;
|
||||
private static final int USE_LONGTABLE = 21;
|
||||
private static final int USE_SUPERTABULAR = 22;
|
||||
private static final int USE_TABULARY = 23;
|
||||
private static final int USE_ENDNOTES = 24;
|
||||
private static final int USE_ULEM = 25;
|
||||
private static final int USE_LASTPAGE = 26;
|
||||
private static final int USE_TITLEREF = 27;
|
||||
private static final int USE_OOOREF = 28;
|
||||
private static final int USE_BIBTEX = 29;
|
||||
private static final int BIBTEX_STYLE = 30;
|
||||
private static final int EXTERNAL_BIBTEX_FILES = 31;
|
||||
private static final int FORMATTING = 32;
|
||||
private static final int PAGE_FORMATTING = 33;
|
||||
private static final int OTHER_STYLES = 34;
|
||||
private static final int IMAGE_CONTENT = 35;
|
||||
private static final int TABLE_CONTENT = 36;
|
||||
private static final int IGNORE_HARD_PAGE_BREAKS = 37;
|
||||
private static final int IGNORE_HARD_LINE_BREAKS = 38;
|
||||
private static final int IGNORE_EMPTY_PARAGRAPHS = 39;
|
||||
private static final int IGNORE_DOUBLE_SPACES = 40;
|
||||
private static final int ALIGN_FRAMES = 41;
|
||||
private static final int FLOAT_FIGURES = 42;
|
||||
private static final int FLOAT_TABLES = 43;
|
||||
private static final int FLOAT_OPTIONS = 44;
|
||||
private static final int FIGURE_SEQUENCE_NAME = 45;
|
||||
private static final int TABLE_SEQUENCE_NAME = 46;
|
||||
private static final int IMAGE_OPTIONS = 47;
|
||||
private static final int REMOVE_GRAPHICS_EXTENSION = 48;
|
||||
private static final int ORIGINAL_IMAGE_SIZE = 49;
|
||||
private static final int SIMPLE_TABLE_LIMIT = 50;
|
||||
private static final int NOTES = 51;
|
||||
private static final int METADATA = 52;
|
||||
private static final int TABSTOP = 53;
|
||||
private static final int WRAP_LINES_AFTER = 54;
|
||||
private static final int SPLIT_LINKED_SECTIONS = 55;
|
||||
private static final int SPLIT_TOPLEVEL_SECTIONS = 56;
|
||||
private static final int SAVE_IMAGES_IN_SUBDIR = 57;
|
||||
private static final int DEBUG = 58;
|
||||
|
||||
protected LinkedList customPreamble = new LinkedList();
|
||||
protected StyleMap par = new StyleMap();
|
||||
protected StyleMap parBlock = new StyleMap();
|
||||
protected StyleMap text = new StyleMap();
|
||||
protected StyleMap list = new StyleMap();
|
||||
protected StyleMap listItem = new StyleMap();
|
||||
protected StyleMap textAttr = new StyleMap();
|
||||
protected HeadingMap headingMap = new HeadingMap(5);
|
||||
protected Hashtable mathSymbols = new Hashtable();
|
||||
protected ReplacementTrie stringReplace = new ReplacementTrie();
|
||||
|
||||
public LaTeXConfig() {
|
||||
super();
|
||||
// create options with default values
|
||||
options[NO_PREAMBLE] = new BooleanOption("no_preamble","false");
|
||||
options[NO_INDEX] = new BooleanOption("no_index","false");
|
||||
options[DOCUMENTCLASS] = new Option("documentclass","article");
|
||||
options[GLOBAL_OPTIONS] = new Option("global_options","");
|
||||
options[BACKEND] = new IntegerOption("backend","pdftex") {
|
||||
public void setString(String sValue) {
|
||||
super.setString(sValue);
|
||||
if ("generic".equals(sValue)) nValue = GENERIC;
|
||||
else if ("dvips".equals(sValue)) nValue = DVIPS;
|
||||
else if ("pdftex".equals(sValue)) nValue = PDFTEX;
|
||||
else if ("unspecified".equals(sValue)) nValue = UNSPECIFIED;
|
||||
else if ("xetex".equals(sValue)) nValue = XETEX;
|
||||
}
|
||||
};
|
||||
options[INPUTENCODING] = new IntegerOption("inputencoding",ClassicI18n.writeInputenc(ClassicI18n.ASCII)) {
|
||||
public void setString(String sValue) {
|
||||
super.setString(sValue);
|
||||
nValue = ClassicI18n.readInputenc(sValue);
|
||||
}
|
||||
};
|
||||
options[MULTILINGUAL] = new BooleanOption("multilingual","true");
|
||||
options[GREEK_MATH] = new BooleanOption("greek_math","true");
|
||||
options[USE_OOOMATH] = new BooleanOption("use_ooomath","false");
|
||||
options[USE_PIFONT] = new BooleanOption("use_pifont","false");
|
||||
options[USE_IFSYM] = new BooleanOption("use_ifsym","false");
|
||||
options[USE_WASYSYM] = new BooleanOption("use_wasysym","false");
|
||||
options[USE_BBDING] = new BooleanOption("use_bbding","false");
|
||||
options[USE_EUROSYM] = new BooleanOption("use_eurosym","false");
|
||||
options[USE_TIPA] = new BooleanOption("use_tipa","false");
|
||||
options[USE_COLOR] = new BooleanOption("use_color","true");
|
||||
options[USE_COLORTBL] = new BooleanOption("use_colortbl","false");
|
||||
options[USE_GEOMETRY] = new BooleanOption("use_geometry","false");
|
||||
options[USE_FANCYHDR] = new BooleanOption("use_fancyhdr","false");
|
||||
options[USE_HYPERREF] = new BooleanOption("use_hyperref","true");
|
||||
options[USE_CAPTION] = new BooleanOption("use_caption","false");
|
||||
options[USE_LONGTABLE] = new BooleanOption("use_longtable","false");
|
||||
options[USE_SUPERTABULAR] = new BooleanOption("use_supertabular","true");
|
||||
options[USE_TABULARY] = new BooleanOption("use_tabulary","false");
|
||||
options[USE_ENDNOTES] = new BooleanOption("use_endnotes","false");
|
||||
options[USE_ULEM] = new BooleanOption("use_ulem","false");
|
||||
options[USE_LASTPAGE] = new BooleanOption("use_lastpage","false");
|
||||
options[USE_TITLEREF] = new BooleanOption("use_titleref","false");
|
||||
options[USE_OOOREF] = new BooleanOption("use_oooref","false");
|
||||
options[USE_BIBTEX] = new BooleanOption("use_bibtex","false");
|
||||
options[BIBTEX_STYLE] = new Option("bibtex_style","plain");
|
||||
options[EXTERNAL_BIBTEX_FILES] = new Option("external_bibtex_files","");
|
||||
options[FORMATTING] = new IntegerOption("formatting","convert_basic") {
|
||||
public void setString(String sValue) {
|
||||
super.setString(sValue);
|
||||
if ("convert_all".equals(sValue)) nValue = CONVERT_ALL;
|
||||
else if ("convert_most".equals(sValue)) nValue = CONVERT_MOST;
|
||||
else if ("convert_basic".equals(sValue)) nValue = CONVERT_BASIC;
|
||||
else if ("ignore_most".equals(sValue)) nValue = IGNORE_MOST;
|
||||
else if ("ignore_all".equals(sValue)) nValue = IGNORE_ALL;
|
||||
}
|
||||
};
|
||||
options[PAGE_FORMATTING] = new IntegerOption("page_formatting","convert_all") {
|
||||
public void setString(String sValue) {
|
||||
super.setString(sValue);
|
||||
if ("convert_all".equals(sValue)) nValue = CONVERT_ALL;
|
||||
else if ("convert_header_footer".equals(sValue)) nValue = CONVERT_HEADER_FOOTER;
|
||||
else if ("ignore_all".equals(sValue)) nValue = IGNORE_ALL;
|
||||
}
|
||||
};
|
||||
options[OTHER_STYLES] = new ContentHandlingOption("other_styles","accept");
|
||||
options[IMAGE_CONTENT] = new ContentHandlingOption("image_content","accept");
|
||||
options[TABLE_CONTENT] = new ContentHandlingOption("table_content","accept");
|
||||
options[IGNORE_HARD_PAGE_BREAKS] = new BooleanOption("ignore_hard_page_breaks","false");
|
||||
options[IGNORE_HARD_LINE_BREAKS] = new BooleanOption("ignore_hard_line_breaks","false");
|
||||
options[IGNORE_EMPTY_PARAGRAPHS] = new BooleanOption("ignore_empty_paragraphs","false");
|
||||
options[IGNORE_DOUBLE_SPACES] = new BooleanOption("ignore_double_spaces","false");
|
||||
options[ALIGN_FRAMES] = new BooleanOption("align_frames","true");
|
||||
options[FLOAT_FIGURES] = new BooleanOption("float_figures","false");
|
||||
options[FLOAT_TABLES] = new BooleanOption("float_tables","false");
|
||||
options[FLOAT_OPTIONS] = new Option("float_options","h");
|
||||
options[FIGURE_SEQUENCE_NAME] = new BooleanOption("figure_sequence_name","");
|
||||
options[TABLE_SEQUENCE_NAME] = new BooleanOption("table_sequence_name","");
|
||||
options[IMAGE_OPTIONS] = new Option("image_options","");
|
||||
options[REMOVE_GRAPHICS_EXTENSION] = new BooleanOption("remove_graphics_extension","false");
|
||||
options[ORIGINAL_IMAGE_SIZE] = new BooleanOption("original_image_size","false");
|
||||
options[SIMPLE_TABLE_LIMIT] = new IntegerOption("simple_table_limit","0") {
|
||||
public void setString(String sValue) {
|
||||
super.setString(sValue);
|
||||
nValue = Misc.getPosInteger(sValue,0);
|
||||
}
|
||||
};
|
||||
options[NOTES] = new IntegerOption("notes","comment") {
|
||||
public void setString(String sValue) {
|
||||
super.setString(sValue);
|
||||
if ("ignore".equals(sValue)) nValue = IGNORE;
|
||||
else if ("comment".equals(sValue)) nValue = COMMENT;
|
||||
else if ("pdfannotation".equals(sValue)) nValue = PDFANNOTATION;
|
||||
else if ("marginpar".equals(sValue)) nValue = MARGINPAR;
|
||||
else nValue = CUSTOM;
|
||||
}
|
||||
};
|
||||
options[METADATA] = new BooleanOption("metadata","true");
|
||||
options[TABSTOP] = new Option("tabstop","");
|
||||
options[WRAP_LINES_AFTER] = new IntegerOption("wrap_lines_after","72") {
|
||||
public void setString(String sValue) {
|
||||
super.setString(sValue);
|
||||
nValue = Misc.getPosInteger(sValue,0);
|
||||
}
|
||||
};
|
||||
options[SPLIT_LINKED_SECTIONS] = new BooleanOption("split_linked_sections","false");
|
||||
options[SPLIT_TOPLEVEL_SECTIONS] = new BooleanOption("split_toplevel_sections","false");
|
||||
options[SAVE_IMAGES_IN_SUBDIR] = new BooleanOption("save_images_in_subdir","false");
|
||||
options[DEBUG] = new BooleanOption("debug","false");
|
||||
// Headings for article class:
|
||||
headingMap.setLevelData(1,"section",1);
|
||||
headingMap.setLevelData(2,"subsection",2);
|
||||
headingMap.setLevelData(3,"subsubsection",3);
|
||||
headingMap.setLevelData(4,"paragraph",4);
|
||||
headingMap.setLevelData(5,"subparagraph",5);
|
||||
// Standard string replace:
|
||||
// Fix french spacing; replace nonbreaking space
|
||||
// right before em-dash, !, ?, : and ; (babel handles this)
|
||||
stringReplace.put("\u00A0\u2014"," \u2014",ClassicI18n.readFontencs("any"));
|
||||
stringReplace.put("\u00A0!"," !",ClassicI18n.readFontencs("any"));
|
||||
stringReplace.put("\u00A0?"," ?",ClassicI18n.readFontencs("any"));
|
||||
stringReplace.put("\u00A0:"," :",ClassicI18n.readFontencs("any"));
|
||||
stringReplace.put("\u00A0;"," ;",ClassicI18n.readFontencs("any"));
|
||||
// Right after opening guillemet and right before closing guillemet:
|
||||
// Here we must *keep* the non-breaking space
|
||||
// TODO: Use \og and \fg if the document contains french...
|
||||
//stringReplace.put("\u00AB\u00A0","\u00AB ",I18n.readFontencs("any"));
|
||||
//stringReplace.put("\u00A0\u00BB"," \u00BB",I18n.readFontencs("any"));
|
||||
}
|
||||
|
||||
protected void readInner(Element elm) {
|
||||
if (elm.getTagName().equals("style-map")) {
|
||||
String sName = elm.getAttribute("name");
|
||||
String sFamily = elm.getAttribute("family");
|
||||
if (sFamily.length()==0) { // try old name
|
||||
sFamily = elm.getAttribute("class");
|
||||
}
|
||||
String sBefore = elm.getAttribute("before");
|
||||
String sAfter = elm.getAttribute("after");
|
||||
boolean bLineBreak = !"false".equals(elm.getAttribute("line-break"));
|
||||
boolean bVerbatim = "true".equals(elm.getAttribute("verbatim"));
|
||||
if ("paragraph".equals(sFamily)) {
|
||||
par.put(sName,sBefore,sAfter,bLineBreak,bVerbatim);
|
||||
}
|
||||
if ("paragraph-block".equals(sFamily)) {
|
||||
String sNext = elm.getAttribute("next");
|
||||
parBlock.put(sName,sBefore,sAfter,sNext,bVerbatim);
|
||||
}
|
||||
else if ("text".equals(sFamily)) {
|
||||
text.put(sName,sBefore,sAfter,false,bVerbatim);
|
||||
}
|
||||
else if ("list".equals(sFamily)) {
|
||||
list.put(sName,sBefore,sAfter);
|
||||
}
|
||||
else if ("listitem".equals(sFamily)) {
|
||||
listItem.put(sName,sBefore,sAfter);
|
||||
}
|
||||
else if ("text-attribute".equals(sFamily)) {
|
||||
textAttr.put(sName, sBefore, sAfter);
|
||||
}
|
||||
}
|
||||
else if (elm.getTagName().equals("heading-map")) {
|
||||
readHeadingMap(elm);
|
||||
}
|
||||
else if (elm.getTagName().equals("string-replace")) {
|
||||
String sInput = elm.getAttribute("input");
|
||||
String sLaTeXCode = elm.getAttribute("latex-code");
|
||||
String sFontencs = elm.getAttribute("fontencs");
|
||||
int nFontencs = ClassicI18n.readFontencs(sFontencs.length()>0 ? sFontencs : "any");
|
||||
stringReplace.put(sInput,sLaTeXCode,nFontencs);
|
||||
}
|
||||
else if (elm.getTagName().equals("custom-preamble")) {
|
||||
Node child = elm.getFirstChild();
|
||||
while (child!=null) {
|
||||
if (child.getNodeType()==Node.TEXT_NODE) {
|
||||
customPreamble.add(child.getNodeValue());
|
||||
}
|
||||
child = child.getNextSibling();
|
||||
}
|
||||
}
|
||||
else if (elm.getTagName().equals("math-symbol-map")) {
|
||||
String sName = elm.getAttribute("name");
|
||||
String sLatex = elm.getAttribute("latex");
|
||||
mathSymbols.put(sName,sLatex);
|
||||
}
|
||||
}
|
||||
|
||||
public void readHeadingMap(Element node) {
|
||||
int nMaxLevel = Misc.getPosInteger(node.getAttribute("max-level"),0);
|
||||
headingMap.reset(nMaxLevel);
|
||||
Node child = node.getFirstChild();
|
||||
while (child!=null) {
|
||||
if (child.getNodeType()==Node.ELEMENT_NODE) {
|
||||
Element elm = (Element) child;
|
||||
if (elm.getTagName().equals("heading-level-map")) {
|
||||
int nWriterLevel = Misc.getPosInteger(elm.getAttribute("writer-level"),1);
|
||||
String sName = elm.getAttribute("name");
|
||||
int nLevel = Misc.getPosInteger(elm.getAttribute("level"),0);
|
||||
headingMap.setLevelData(nWriterLevel,sName,nLevel);
|
||||
}
|
||||
}
|
||||
child = child.getNextSibling();
|
||||
}
|
||||
}
|
||||
|
||||
protected void writeInner(Document dom) {
|
||||
// Write math symbol map
|
||||
Enumeration msEnum = mathSymbols.keys();
|
||||
while (msEnum.hasMoreElements()) {
|
||||
String sName = (String) msEnum.nextElement();
|
||||
String sLatex = (String) mathSymbols.get(sName);
|
||||
Element msNode = dom.createElement("math-symbol-map");
|
||||
msNode.setAttribute("name",sName);
|
||||
msNode.setAttribute("latex",sLatex);
|
||||
dom.getDocumentElement().appendChild(msNode);
|
||||
}
|
||||
|
||||
writeStyleMap(dom,par,"paragraph");
|
||||
writeStyleMap(dom,parBlock,"paragraph-block");
|
||||
writeStyleMap(dom,text,"text");
|
||||
writeStyleMap(dom,list,"list");
|
||||
writeStyleMap(dom,listItem,"listitem");
|
||||
writeStyleMap(dom,textAttr,"text-attribute");
|
||||
|
||||
Element hmNode = dom.createElement("heading-map");
|
||||
hmNode.setAttribute("max-level",Integer.toString(headingMap.getMaxLevel()));
|
||||
dom.getDocumentElement().appendChild(hmNode);
|
||||
for (int i=1; i<=headingMap.getMaxLevel(); i++) {
|
||||
Element hlmNode = dom.createElement("heading-level-map");
|
||||
hlmNode.setAttribute("writer-level",Integer.toString(i));
|
||||
hlmNode.setAttribute("name",headingMap.getName(i));
|
||||
hlmNode.setAttribute("level",Integer.toString(headingMap.getLevel(i)));
|
||||
hmNode.appendChild(hlmNode);
|
||||
}
|
||||
|
||||
// TODO: Export string replacements
|
||||
//String[] sInputStrings = stringReplace.getInputStrings();
|
||||
/*
|
||||
int nSize = sInputStrings.size();
|
||||
for (int i=0; i<nSize; i++) {
|
||||
String sInput = sInputStrings[i];
|
||||
ReplacementTrieNode node = stringReplace.get(sInput);
|
||||
Element srNode = dom.createElement("string-replace");
|
||||
srNode.setAttribute("input",sInput);
|
||||
srNode.setAttribute("latex-code",node.getLaTeXCode());
|
||||
srNode.setAttribute("fontenc",I18n.writeFontencs(node.getFontencs()));
|
||||
hmNode.appendChild(srNode);
|
||||
}
|
||||
*/
|
||||
|
||||
writeContent(dom,customPreamble,"custom-preamble");
|
||||
|
||||
}
|
||||
|
||||
private void writeStyleMap(Document dom, StyleMap sm, String sFamily) {
|
||||
Enumeration smEnum = sm.getNames();
|
||||
while (smEnum.hasMoreElements()) {
|
||||
String sName = (String) smEnum.nextElement();
|
||||
Element smNode = dom.createElement("style-map");
|
||||
smNode.setAttribute("name",sName);
|
||||
smNode.setAttribute("family",sFamily);
|
||||
smNode.setAttribute("before",sm.getBefore(sName));
|
||||
smNode.setAttribute("after",sm.getAfter(sName));
|
||||
if (sm.getNext(sName)!=null) {
|
||||
smNode.setAttribute("next",sm.getNext(sName));
|
||||
}
|
||||
if (!sm.getLineBreak(sName)) {
|
||||
smNode.setAttribute("line-break","false");
|
||||
}
|
||||
if (sm.getVerbatim(sName)) {
|
||||
smNode.setAttribute("verbatim","true");
|
||||
}
|
||||
dom.getDocumentElement().appendChild(smNode);
|
||||
}
|
||||
}
|
||||
|
||||
private void writeContent(Document dom, LinkedList list, String sElement) {
|
||||
Element node = dom.createElement(sElement);
|
||||
int nLen = list.size();
|
||||
for (int i=0; i<nLen; i++) {
|
||||
node.appendChild( dom.createTextNode( (String) list.get(i) ) );
|
||||
}
|
||||
dom.getDocumentElement().appendChild(node);
|
||||
}
|
||||
|
||||
// Convenience accessor methods
|
||||
|
||||
// String replace
|
||||
public ReplacementTrie getStringReplace() { return stringReplace; }
|
||||
|
||||
// Common options
|
||||
public boolean debug() { return ((BooleanOption) options[DEBUG]).getValue(); }
|
||||
|
||||
// General options
|
||||
public String getDocumentclass() { return options[DOCUMENTCLASS].getString(); }
|
||||
public String getGlobalOptions() { return options[GLOBAL_OPTIONS].getString(); }
|
||||
public int getBackend() { return ((IntegerOption) options[BACKEND]).getValue(); }
|
||||
public int getInputencoding() { return ((IntegerOption) options[INPUTENCODING]).getValue(); }
|
||||
public boolean multilingual() { return ((BooleanOption) options[MULTILINGUAL]).getValue(); }
|
||||
public boolean greekMath() { return ((BooleanOption) options[GREEK_MATH]).getValue(); }
|
||||
public boolean noPreamble() { return ((BooleanOption) options[NO_PREAMBLE]).getValue(); }
|
||||
public boolean noIndex() { return ((BooleanOption) options[NO_INDEX]).getValue(); }
|
||||
|
||||
// Package options
|
||||
public boolean useOoomath() { return ((BooleanOption) options[USE_OOOMATH]).getValue(); }
|
||||
public boolean usePifont() { return ((BooleanOption) options[USE_PIFONT]).getValue(); }
|
||||
public boolean useIfsym() { return ((BooleanOption) options[USE_IFSYM]).getValue(); }
|
||||
public boolean useWasysym() { return ((BooleanOption) options[USE_WASYSYM]).getValue(); }
|
||||
public boolean useBbding() { return ((BooleanOption) options[USE_BBDING]).getValue(); }
|
||||
public boolean useEurosym() { return ((BooleanOption) options[USE_EUROSYM]).getValue(); }
|
||||
public boolean useTipa() { return ((BooleanOption) options[USE_TIPA]).getValue(); }
|
||||
public boolean useColor() { return ((BooleanOption) options[USE_COLOR]).getValue(); }
|
||||
public boolean useColortbl() { return ((BooleanOption) options[USE_COLORTBL]).getValue(); }
|
||||
public boolean useGeometry() { return ((BooleanOption) options[USE_GEOMETRY]).getValue(); }
|
||||
public boolean useFancyhdr() { return ((BooleanOption) options[USE_FANCYHDR]).getValue(); }
|
||||
public boolean useHyperref() { return ((BooleanOption) options[USE_HYPERREF]).getValue(); }
|
||||
public boolean useCaption() { return ((BooleanOption) options[USE_CAPTION]).getValue(); }
|
||||
public boolean useLongtable() { return ((BooleanOption) options[USE_LONGTABLE]).getValue(); }
|
||||
public boolean useSupertabular() { return ((BooleanOption) options[USE_SUPERTABULAR]).getValue(); }
|
||||
public boolean useTabulary() { return ((BooleanOption) options[USE_TABULARY]).getValue(); }
|
||||
public boolean useEndnotes() { return ((BooleanOption) options[USE_ENDNOTES]).getValue(); }
|
||||
public boolean useUlem() { return ((BooleanOption) options[USE_ULEM]).getValue(); }
|
||||
public boolean useLastpage() { return ((BooleanOption) options[USE_LASTPAGE]).getValue(); }
|
||||
public boolean useTitleref() { return ((BooleanOption) options[USE_TITLEREF]).getValue(); }
|
||||
public boolean useOooref() { return ((BooleanOption) options[USE_OOOREF]).getValue(); }
|
||||
public boolean useBibtex() { return ((BooleanOption) options[USE_BIBTEX]).getValue(); }
|
||||
public String bibtexStyle() { return options[BIBTEX_STYLE].getString(); }
|
||||
public String externalBibtexFiles() { return options[EXTERNAL_BIBTEX_FILES].getString(); }
|
||||
|
||||
// Formatting options
|
||||
public int formatting() { return ((IntegerOption) options[FORMATTING]).getValue(); }
|
||||
public int pageFormatting() { return ((IntegerOption) options[PAGE_FORMATTING]).getValue(); }
|
||||
public int otherStyles() { return ((IntegerOption) options[OTHER_STYLES]).getValue(); }
|
||||
public int imageContent() { return ((IntegerOption) options[IMAGE_CONTENT]).getValue(); }
|
||||
public int tableContent() { return ((IntegerOption) options[TABLE_CONTENT]).getValue(); }
|
||||
public boolean ignoreHardPageBreaks() { return ((BooleanOption) options[IGNORE_HARD_PAGE_BREAKS]).getValue(); }
|
||||
public boolean ignoreHardLineBreaks() { return ((BooleanOption) options[IGNORE_HARD_LINE_BREAKS]).getValue(); }
|
||||
public boolean ignoreEmptyParagraphs() { return ((BooleanOption) options[IGNORE_EMPTY_PARAGRAPHS]).getValue(); }
|
||||
public boolean ignoreDoubleSpaces() { return ((BooleanOption) options[IGNORE_DOUBLE_SPACES]).getValue(); }
|
||||
|
||||
// Graphics options
|
||||
public boolean alignFrames() { return ((BooleanOption) options[ALIGN_FRAMES]).getValue(); }
|
||||
public boolean floatFigures() { return ((BooleanOption) options[FLOAT_FIGURES]).getValue(); }
|
||||
public boolean floatTables() { return ((BooleanOption) options[FLOAT_TABLES]).getValue(); }
|
||||
public String getFloatOptions() { return options[FLOAT_OPTIONS].getString(); }
|
||||
public String getFigureSequenceName() { return options[FIGURE_SEQUENCE_NAME].getString(); }
|
||||
public String getTableSequenceName() { return options[TABLE_SEQUENCE_NAME].getString(); }
|
||||
public String getImageOptions() { return options[IMAGE_OPTIONS].getString(); }
|
||||
public boolean removeGraphicsExtension() { return ((BooleanOption) options[REMOVE_GRAPHICS_EXTENSION]).getValue(); }
|
||||
public boolean originalImageSize() { return ((BooleanOption) options[ORIGINAL_IMAGE_SIZE]).getValue(); }
|
||||
|
||||
// Tables
|
||||
public int getSimpleTableLimit() { return ((IntegerOption) options[SIMPLE_TABLE_LIMIT]).getValue(); }
|
||||
|
||||
// Notes
|
||||
public int notes() { return ((IntegerOption) options[NOTES]).getValue(); }
|
||||
public String getNotesCommand() { return options[NOTES].getString(); }
|
||||
|
||||
// Metadata
|
||||
public boolean metadata() { return ((BooleanOption) options[METADATA]).getValue(); }
|
||||
|
||||
// Tab stops
|
||||
public String getTabstop() { return options[TABSTOP].getString(); }
|
||||
|
||||
// Files
|
||||
public int getWrapLinesAfter() { return ((IntegerOption) options[WRAP_LINES_AFTER]).getValue(); }
|
||||
public boolean splitLinkedSections() { return ((BooleanOption) options[SPLIT_LINKED_SECTIONS]).getValue(); }
|
||||
public boolean splitToplevelSections() { return ((BooleanOption) options[SPLIT_TOPLEVEL_SECTIONS]).getValue(); }
|
||||
public boolean saveImagesInSubdir() { return ((BooleanOption) options[SAVE_IMAGES_IN_SUBDIR]).getValue(); }
|
||||
|
||||
public Hashtable getMathSymbols() { return mathSymbols; }
|
||||
|
||||
public StyleMap getParStyleMap() { return par; }
|
||||
public StyleMap getParBlockStyleMap() { return parBlock; }
|
||||
public StyleMap getTextStyleMap() { return text; }
|
||||
public StyleMap getListStyleMap() { return list; }
|
||||
public StyleMap getListItemStyleMap() { return listItem; }
|
||||
public StyleMap getTextAttributeStyleMap() { return textAttr; }
|
||||
public HeadingMap getHeadingMap() { return headingMap; }
|
||||
public LinkedList getCustomPreamble() { return customPreamble; }
|
||||
|
||||
}
|
||||
|
152
source/java/writer2latex/latex/LaTeXDocument.java
Normal file
152
source/java/writer2latex/latex/LaTeXDocument.java
Normal file
|
@ -0,0 +1,152 @@
|
|||
/************************************************************************
|
||||
*
|
||||
* LaTeXDocument.java
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License version 2.1, as published by the Free Software Foundation.
|
||||
*
|
||||
* This library 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
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston,
|
||||
* MA 02111-1307 USA
|
||||
*
|
||||
* Copyright: 2002-2008 by Henrik Just
|
||||
*
|
||||
* All Rights Reserved.
|
||||
*
|
||||
* Version 1.0 (2008-11-23)
|
||||
*
|
||||
*/
|
||||
|
||||
package writer2latex.latex;
|
||||
|
||||
import writer2latex.xmerge.Document;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.io.OutputStream;
|
||||
import java.io.OutputStreamWriter;
|
||||
|
||||
/**
|
||||
* <p>Class representing a LaTeX document.</p>
|
||||
*
|
||||
*/
|
||||
public class LaTeXDocument implements Document {
|
||||
private static final String FILE_EXTENSION = ".tex";
|
||||
|
||||
private String sName;
|
||||
|
||||
private String sEncoding = "ASCII";
|
||||
|
||||
private int nWrap;
|
||||
|
||||
private LaTeXDocumentPortion contents;
|
||||
|
||||
/**
|
||||
* <p>Constructs a new LaTeX Document.</p>
|
||||
*
|
||||
* <p>This new document is empty. Document data must added to the preamble and
|
||||
* the body using appropriate methods.</p>
|
||||
*
|
||||
* @param sName The name of the <code>LaTeXDocument</code>.
|
||||
* @param nWrap Lines should be wrapped after this position
|
||||
*/
|
||||
public LaTeXDocument(String sName,int nWrap) {
|
||||
this.nWrap = nWrap;
|
||||
this.sName = trimDocumentName(sName);
|
||||
contents = new LaTeXDocumentPortion(true);
|
||||
}
|
||||
|
||||
/**
|
||||
* <p>This method is supposed to read <code>byte</code> data from the InputStream.
|
||||
* Currently it does nothing, since we don't need it.</p>
|
||||
*
|
||||
* @param is InputStream containing a LaTeX data file.
|
||||
*
|
||||
* @throws IOException In case of any I/O errors.
|
||||
*/
|
||||
public void read(InputStream is) throws IOException {
|
||||
// Do nothing.
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* <p>Returns the <code>Document</code> name with no file extension.</p>
|
||||
*
|
||||
* @return The <code>Document</code> name with no file extension.
|
||||
*/
|
||||
public String getName() {
|
||||
return sName;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* <p>Returns the <code>Document</code> name with file extension.</p>
|
||||
*
|
||||
* @return The <code>Document</code> name with file extension.
|
||||
*/
|
||||
public String getFileName() {
|
||||
return new String(sName + FILE_EXTENSION);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* <p>Writes out the <code>Document</code> content to the specified
|
||||
* <code>OutputStream</code>.</p>
|
||||
*
|
||||
* <p>This method may not be thread-safe.
|
||||
* Implementations may or may not synchronize this
|
||||
* method. User code (i.e. caller) must make sure that
|
||||
* calls to this method are thread-safe.</p>
|
||||
*
|
||||
* @param os <code>OutputStream</code> to write out the
|
||||
* <code>Document</code> content.
|
||||
*
|
||||
* @throws IOException If any I/O error occurs.
|
||||
*/
|
||||
public void write(OutputStream os) throws IOException {
|
||||
OutputStreamWriter osw = new OutputStreamWriter(os,sEncoding);
|
||||
contents.write(osw,nWrap,"\n");
|
||||
osw.flush();
|
||||
osw.close();
|
||||
}
|
||||
|
||||
/**
|
||||
* <p> Set the output encoding to use when writing the document.</p>
|
||||
*/
|
||||
public void setEncoding(String sEncoding) { this.sEncoding = sEncoding; }
|
||||
|
||||
/**
|
||||
* <p>Returns the <code>LaTeXDocumentPortion</code>, that contains the
|
||||
* contents of the document.</p>
|
||||
*
|
||||
* @return The content <code>LaTeXDocumentPortion</code>.
|
||||
*/
|
||||
public LaTeXDocumentPortion getContents(){
|
||||
return contents;
|
||||
}
|
||||
|
||||
/*
|
||||
* Utility method to make sure the document name is stripped of any file
|
||||
* extensions before use.
|
||||
*/
|
||||
private String trimDocumentName(String name) {
|
||||
String temp = name.toLowerCase();
|
||||
|
||||
if (temp.endsWith(FILE_EXTENSION)) {
|
||||
// strip the extension
|
||||
int nlen = name.length();
|
||||
int endIndex = nlen - FILE_EXTENSION.length();
|
||||
name = name.substring(0,endIndex);
|
||||
}
|
||||
|
||||
return name;
|
||||
}
|
||||
}
|
||||
|
214
source/java/writer2latex/latex/LaTeXDocumentPortion.java
Normal file
214
source/java/writer2latex/latex/LaTeXDocumentPortion.java
Normal file
|
@ -0,0 +1,214 @@
|
|||
/************************************************************************
|
||||
*
|
||||
* LaTeXDocumentPortion.java
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License version 2.1, as published by the Free Software Foundation.
|
||||
*
|
||||
* This library 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
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston,
|
||||
* MA 02111-1307 USA
|
||||
*
|
||||
* Copyright: 2002-2006 by Henrik Just
|
||||
*
|
||||
* All Rights Reserved.
|
||||
*
|
||||
* Version 1.0 (2007-10-02)
|
||||
*
|
||||
*/
|
||||
|
||||
package writer2latex.latex;
|
||||
|
||||
import java.io.OutputStreamWriter;
|
||||
import java.io.IOException;
|
||||
import java.util.Vector;
|
||||
|
||||
import writer2latex.util.Misc;
|
||||
|
||||
/** This class represents a portion of a LaTeX document. A portion is any
|
||||
number of lines, and may include subportions. */
|
||||
public class LaTeXDocumentPortion {
|
||||
|
||||
private Vector nodes; // The collection of all nodes in this portion
|
||||
|
||||
private StringBuffer curText; // The currently active node (always the last node)
|
||||
private boolean bEmpty; // Is the active node empty?
|
||||
|
||||
private boolean bWrap; // Do we allow line wrap in this portion?
|
||||
|
||||
public LaTeXDocumentPortion(boolean bWrap){
|
||||
this.bWrap = bWrap;
|
||||
nodes = new Vector();
|
||||
curText = new StringBuffer();
|
||||
bEmpty = true;
|
||||
}
|
||||
|
||||
/** Add another portion to the end of this portion */
|
||||
public LaTeXDocumentPortion append(LaTeXDocumentPortion ldp) {
|
||||
if (!bEmpty) {
|
||||
// add the current node to the node list and create new current node
|
||||
nodes.add(curText);
|
||||
curText = new StringBuffer();
|
||||
bEmpty = true;
|
||||
}
|
||||
nodes.add(ldp);
|
||||
return this;
|
||||
}
|
||||
|
||||
/** Add a string to the end of this portion */
|
||||
public LaTeXDocumentPortion append(String s){
|
||||
curText.append(s);
|
||||
bEmpty = false; // even if this is the empty string!
|
||||
return this;
|
||||
}
|
||||
|
||||
/** Add a newline to the end of this portion */
|
||||
public LaTeXDocumentPortion nl(){
|
||||
curText.append("\n");
|
||||
bEmpty = false;
|
||||
return this;
|
||||
}
|
||||
|
||||
/** write a segment of text (eg. a word) to the output */
|
||||
private void writeSegment(String s, int nStart, int nEnd, OutputStreamWriter osw) throws IOException {
|
||||
for (int i=nStart; i<nEnd; i++) { osw.write(s.charAt(i)); }
|
||||
}
|
||||
|
||||
/** write the contents of a StringBuffer to the output */
|
||||
private void writeBuffer(StringBuffer text, OutputStreamWriter osw, int nLineLen, String sNewline) throws IOException {
|
||||
String s = text.toString();
|
||||
int nLen = s.length();
|
||||
|
||||
int[] nBreakPoints = new int[100];
|
||||
int nLastBPIndex = 99;
|
||||
|
||||
int nStart = 0;
|
||||
|
||||
while (nStart<nLen) {
|
||||
// identify line and breakpoints
|
||||
int nBPIndex = 0;
|
||||
boolean bEscape = false;
|
||||
boolean bComment = false;
|
||||
int nNewline = nStart;
|
||||
char c;
|
||||
while (nNewline<nLen) {
|
||||
if (nBPIndex==nLastBPIndex) {
|
||||
nBreakPoints = Misc.doubleIntArray(nBreakPoints);
|
||||
nLastBPIndex = nBreakPoints.length-1;
|
||||
}
|
||||
c = s.charAt(nNewline);
|
||||
if (c=='\n') {
|
||||
nBreakPoints[nBPIndex++] = nNewline;
|
||||
break;
|
||||
}
|
||||
if (bEscape) { bEscape = false; }
|
||||
else if (c=='\\') { bEscape = true; }
|
||||
else if (c=='%') { bComment = true; }
|
||||
else if (!bComment && c==' ') { nBreakPoints[nBPIndex++] = nNewline; }
|
||||
nNewline++;
|
||||
}
|
||||
if (nBPIndex==nLastBPIndex) {
|
||||
nBreakPoints = Misc.doubleIntArray(nBreakPoints);
|
||||
nLastBPIndex = nBreakPoints.length-1;
|
||||
}
|
||||
if (nNewline==nLen) { nBreakPoints[nBPIndex++] = nNewline; }
|
||||
|
||||
// write out line
|
||||
int nCurLineLen = nBreakPoints[0]-nStart;
|
||||
writeSegment(s,nStart,nBreakPoints[0],osw);
|
||||
for (int i=0; i<nBPIndex-1; i++) {
|
||||
int nSegmentLen = nBreakPoints[i+1]-nBreakPoints[i];
|
||||
if (nSegmentLen+nCurLineLen>nLineLen) {
|
||||
// break line before this segment
|
||||
osw.write(sNewline);
|
||||
nCurLineLen = nSegmentLen;
|
||||
}
|
||||
else {
|
||||
// segment fits in current line
|
||||
osw.write(" ");
|
||||
nCurLineLen += nSegmentLen;
|
||||
}
|
||||
writeSegment(s,nBreakPoints[i]+1,nBreakPoints[i+1],osw);
|
||||
}
|
||||
osw.write(sNewline);
|
||||
nStart = nNewline+1;
|
||||
}
|
||||
}
|
||||
|
||||
/** write the contents of a StringBuffer to the output without wrap */
|
||||
private void writeBuffer(StringBuffer text, OutputStreamWriter osw, String sNewline) throws IOException {
|
||||
String s = text.toString();
|
||||
int nLen = s.length();
|
||||
|
||||
int nStart = 0;
|
||||
|
||||
while (nStart<nLen) {
|
||||
// identify line
|
||||
int nNewline = nStart;
|
||||
while (nNewline<nLen) {
|
||||
if (s.charAt(nNewline)=='\n') { break; }
|
||||
nNewline++;
|
||||
}
|
||||
|
||||
// write out line
|
||||
writeSegment(s,nStart,nNewline,osw);
|
||||
osw.write(sNewline);
|
||||
nStart = nNewline+1;
|
||||
}
|
||||
}
|
||||
|
||||
/** Write this portion to the output (note: nLineLen=0 means no wrap) */
|
||||
public void write(OutputStreamWriter osw, int nLineLen, String sNewline) throws IOException {
|
||||
int n = nodes.size();
|
||||
for (int i=0; i<n; i++) {
|
||||
if (nodes.get(i) instanceof LaTeXDocumentPortion) {
|
||||
((LaTeXDocumentPortion) nodes.get(i)).write(osw,nLineLen,sNewline);
|
||||
}
|
||||
else if (bWrap && nLineLen>0) {
|
||||
writeBuffer((StringBuffer) nodes.get(i),osw,nLineLen,sNewline);
|
||||
}
|
||||
else {
|
||||
writeBuffer((StringBuffer) nodes.get(i),osw,sNewline);
|
||||
}
|
||||
}
|
||||
if (!bEmpty) { // write current node as well
|
||||
if (bWrap && nLineLen>0) {
|
||||
writeBuffer(curText,osw,nLineLen,sNewline);
|
||||
}
|
||||
else {
|
||||
writeBuffer(curText,osw,sNewline);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/** Return the content of this LaTeXDocumentStream as a string */
|
||||
public String toString() {
|
||||
StringBuffer buf = new StringBuffer();
|
||||
int n = nodes.size();
|
||||
for (int i=0; i<n; i++) {
|
||||
if (nodes.get(i) instanceof LaTeXDocumentPortion) {
|
||||
buf.append(((LaTeXDocumentPortion) nodes.get(i)).toString());
|
||||
}
|
||||
else {
|
||||
buf.append(((StringBuffer) nodes.get(i)).toString());
|
||||
}
|
||||
}
|
||||
if (!bEmpty) { // write current node as well
|
||||
buf.append(curText.toString());
|
||||
}
|
||||
return buf.toString();
|
||||
}
|
||||
|
||||
|
||||
|
||||
} // end class LaTeXDocumentPortion
|
||||
|
||||
// TO DO: consider StringBuffer->ByteArrayOutputStream (performance??)
|
||||
|
384
source/java/writer2latex/latex/ListStyleConverter.java
Normal file
384
source/java/writer2latex/latex/ListStyleConverter.java
Normal file
|
@ -0,0 +1,384 @@
|
|||
/************************************************************************
|
||||
*
|
||||
* ListStyleConverter.java
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License version 2.1, as published by the Free Software Foundation.
|
||||
*
|
||||
* This library 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
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston,
|
||||
* MA 02111-1307 USA
|
||||
*
|
||||
* Copyright: 2002-2008 by Henrik Just
|
||||
*
|
||||
* All Rights Reserved.
|
||||
*
|
||||
* Version 1.0 (2008-09-08)
|
||||
*
|
||||
*/
|
||||
|
||||
package writer2latex.latex;
|
||||
|
||||
import java.util.Hashtable;
|
||||
|
||||
import writer2latex.util.*;
|
||||
import writer2latex.office.*;
|
||||
import writer2latex.latex.util.BeforeAfter;
|
||||
import writer2latex.latex.util.Context;
|
||||
|
||||
/* This class creates LaTeX code from OOo list styles
|
||||
*/
|
||||
public class ListStyleConverter extends StyleConverter {
|
||||
boolean bNeedSaveEnumCounter = false;
|
||||
private Hashtable listStyleLevelNames = new Hashtable();
|
||||
|
||||
/** <p>Constructs a new <code>ListStyleConverter</code>.</p>
|
||||
*/
|
||||
public ListStyleConverter(OfficeReader ofr, LaTeXConfig config,
|
||||
ConverterPalette palette) {
|
||||
super(ofr,config,palette);
|
||||
}
|
||||
|
||||
public void appendDeclarations(LaTeXDocumentPortion pack, LaTeXDocumentPortion decl) {
|
||||
if (config.formatting()>=LaTeXConfig.CONVERT_MOST || !styleNames.isEmpty()) {
|
||||
decl.append("% List styles").nl();
|
||||
// May need an extra counter to handle continued numbering in lists
|
||||
if (bNeedSaveEnumCounter) {
|
||||
decl.append("\\newcounter{saveenum}").nl();
|
||||
}
|
||||
// If we export formatting, we need some hooks from lists to paragraphs:
|
||||
if (config.formatting()>=LaTeXConfig.CONVERT_MOST) {
|
||||
decl.append("\\newcommand\\writerlistleftskip{}").nl()
|
||||
.append("\\newcommand\\writerlistparindent{}").nl()
|
||||
.append("\\newcommand\\writerlistlabel{}").nl()
|
||||
.append("\\newcommand\\writerlistremovelabel{")
|
||||
.append("\\aftergroup\\let\\aftergroup\\writerlistparindent\\aftergroup\\relax")
|
||||
.append("\\aftergroup\\let\\aftergroup\\writerlistlabel\\aftergroup\\relax}").nl();
|
||||
}
|
||||
super.appendDeclarations(pack,decl);
|
||||
}
|
||||
}
|
||||
|
||||
/** <p>Apply a list style to an ordered or unordered list.</p> */
|
||||
public void applyListStyle(String sStyleName, int nLevel, boolean bOrdered,
|
||||
boolean bContinue, BeforeAfter ba) {
|
||||
// Step 1. We may have a style map, this always takes precedence
|
||||
String sDisplayName = ofr.getListStyles().getDisplayName(sStyleName);
|
||||
if (config.getListStyleMap().contains(sDisplayName)) {
|
||||
ba.add(config.getListStyleMap().getBefore(sDisplayName),
|
||||
config.getListStyleMap().getAfter(sDisplayName));
|
||||
return;
|
||||
}
|
||||
// Step 2: The list style may not exist, or the user wants to ignore it.
|
||||
// In this case we create default lists
|
||||
ListStyle style = ofr.getListStyle(sStyleName);
|
||||
if (style==null || config.formatting()<=LaTeXConfig.IGNORE_MOST) {
|
||||
if (nLevel<=4) {
|
||||
if (bOrdered) {
|
||||
ba.add("\\begin{enumerate}","\\end{enumerate}");
|
||||
}
|
||||
else {
|
||||
ba.add("\\begin{itemize}","\\end{itemize}");
|
||||
}
|
||||
}
|
||||
return;
|
||||
}
|
||||
// Step 3: Export as default lists, but redefine labels
|
||||
if (config.formatting()==LaTeXConfig.CONVERT_BASIC) {
|
||||
if (nLevel==1) {
|
||||
if (!styleNames.containsName(getDisplayName(sStyleName))) {
|
||||
createListStyleLabels(sStyleName);
|
||||
}
|
||||
ba.add("\\liststyle"+styleNames.getExportName(getDisplayName(sStyleName))+"\n","");
|
||||
}
|
||||
if (nLevel<=4) {
|
||||
String sCounterName = ((String[]) listStyleLevelNames.get(sStyleName))[nLevel];
|
||||
if (bContinue && style.isNumber(nLevel)) {
|
||||
bNeedSaveEnumCounter = true;
|
||||
ba.add("\\setcounter{saveenum}{\\value{"+sCounterName+"}}\n","");
|
||||
}
|
||||
if (bOrdered) {
|
||||
ba.add("\\begin{enumerate}","\\end{enumerate}");
|
||||
}
|
||||
else {
|
||||
ba.add("\\begin{itemize}","\\end{itemize}");
|
||||
}
|
||||
if (bContinue && style.isNumber(nLevel)) {
|
||||
ba.add("\n\\setcounter{"+sCounterName+"}{\\value{saveenum}}","");
|
||||
}
|
||||
}
|
||||
return;
|
||||
}
|
||||
// Step 4: Export with formatting, as "Writer style" custom lists
|
||||
if (nLevel<=4) { // TODO: Max level should not be fixed
|
||||
if (!styleNames.containsName(getDisplayName(sStyleName))) {
|
||||
createListStyle(sStyleName);
|
||||
}
|
||||
String sTeXName="list"+styleNames.getExportName(getDisplayName(sStyleName))
|
||||
+"level"+Misc.int2roman(nLevel);
|
||||
if (!bContinue && style.isNumber(nLevel)) {
|
||||
int nStartValue = Misc.getPosInteger(style.getLevelProperty(nLevel,XMLString.TEXT_START_VALUE),1)-1;
|
||||
ba.add("\\setcounter{"+sTeXName+"}{"+Integer.toString(nStartValue)+"}\n","");
|
||||
}
|
||||
ba.add("\\begin{"+sTeXName+"}","\\end{"+sTeXName+"}");
|
||||
}
|
||||
}
|
||||
|
||||
/** <p>Apply a list style to a list item.</p> */
|
||||
public void applyListItemStyle(String sStyleName, int nLevel, boolean bHeader,
|
||||
boolean bRestart, int nStartValue, BeforeAfter ba) {
|
||||
// Step 1. We may have a style map, this always takes precedence
|
||||
String sDisplayName = ofr.getListStyles().getDisplayName(sStyleName);
|
||||
if (config.getListItemStyleMap().contains(sDisplayName)) {
|
||||
ba.add(config.getListItemStyleMap().getBefore(sDisplayName),
|
||||
config.getListItemStyleMap().getAfter(sDisplayName));
|
||||
return;
|
||||
}
|
||||
// Step 2: The list style may not exist, or the user wants to ignore it.
|
||||
// In this case we create default lists
|
||||
ListStyle style = ofr.getListStyle(sStyleName);
|
||||
if (style==null || config.formatting()<=LaTeXConfig.IGNORE_MOST) {
|
||||
if (nLevel<=4) {
|
||||
if (bHeader) { ba.add("\\item[] ",""); }
|
||||
else { ba.add("\\item ",""); }
|
||||
}
|
||||
return;
|
||||
}
|
||||
// Step 3: Export as default lists (with redefined labels)
|
||||
if (config.formatting()==LaTeXConfig.CONVERT_BASIC) {
|
||||
if (nLevel<=4) {
|
||||
if (bHeader) {
|
||||
ba.add("\\item[] ","");
|
||||
}
|
||||
else if (bRestart && style.isNumber(nLevel)) {
|
||||
ba.add("\n\\setcounter{enum"+Misc.int2roman(nLevel)
|
||||
+"}{"+(nStartValue-1)+"}\n\\item ","");
|
||||
}
|
||||
else {
|
||||
ba.add("\\item ","");
|
||||
}
|
||||
}
|
||||
return;
|
||||
}
|
||||
// Step 4: Export with formatting, as "Writer style" custom lists
|
||||
if (nLevel<=4 && !bHeader) { // TODO: Max level should not be fixed
|
||||
String sTeXName="list"+styleNames.getExportName(getDisplayName(sStyleName))
|
||||
+"level"+Misc.int2roman(nLevel);
|
||||
if (bRestart && style.isNumber(nLevel)) {
|
||||
ba.add("\\setcounter{"+sTeXName+"}{"+(nStartValue-1)+"}\n","");
|
||||
}
|
||||
ba.add("\\item ","");
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/** <p>Create labels for default lists (enumerate/itemize) based on
|
||||
* a List Style
|
||||
*/
|
||||
private void createListStyleLabels(String sStyleName) {
|
||||
String sTeXName = styleNames.getExportName(getDisplayName(sStyleName));
|
||||
declarations.append("\\newcommand\\liststyle")
|
||||
.append(sTeXName).append("{%").nl();
|
||||
ListStyle style = ofr.getListStyle(sStyleName);
|
||||
int nEnum = 0;
|
||||
int nItem = 0;
|
||||
String sName[] = new String[5];
|
||||
for (int i=1; i<=4; i++) {
|
||||
if (style.isNumber(i)) { sName[i]="enum"+Misc.int2roman(++nEnum); }
|
||||
else { sName[i]="item"+Misc.int2roman(++nItem); }
|
||||
}
|
||||
listStyleLevelNames.put(sStyleName, sName);
|
||||
createLabels(style, sName, 4, false, true, false, declarations);
|
||||
declarations.append("}").nl();
|
||||
}
|
||||
|
||||
/** <p>Create "Writer style" lists based on a List Style.
|
||||
<p>A list in writer is really a sequence of numbered paragraphs, so
|
||||
this is also how we implement it in LaTeX.
|
||||
The enivronment + redefined \item defines three hooks:
|
||||
\writerlistleftskip, \writerlistparindent, \writerlistlabel
|
||||
which are used by exported paragraph styles to apply numbering.
|
||||
*/
|
||||
private void createListStyle(String sStyleName) {
|
||||
ListStyle style = ofr.getListStyle(sStyleName);
|
||||
|
||||
// Create labels
|
||||
String sTeXName = styleNames.getExportName(getDisplayName(sStyleName));
|
||||
String[] sLevelName = new String[5];
|
||||
for (int i=1; i<=4; i++) {
|
||||
sLevelName[i]="list"+sTeXName+"level"+Misc.int2roman(i);
|
||||
}
|
||||
createLabels(style,sLevelName,4,true,false,true,declarations);
|
||||
|
||||
// Create environments
|
||||
for (int i=1; i<=4; i++) {
|
||||
String sSpaceBefore = getLength(style,i,XMLString.TEXT_SPACE_BEFORE);
|
||||
String sLabelWidth = getLength(style,i,XMLString.TEXT_MIN_LABEL_WIDTH);
|
||||
String sLabelDistance = getLength(style,i,XMLString.TEXT_MIN_LABEL_DISTANCE);
|
||||
String sTextAlign = style.getLevelStyleProperty(i,XMLString.FO_TEXT_ALIGN);
|
||||
String sAlignmentChar = "l"; // start (or left) is default
|
||||
if (sTextAlign!=null) {
|
||||
if ("end".equals(sTextAlign)) { sAlignmentChar="r"; }
|
||||
else if ("right".equals(sTextAlign)) { sAlignmentChar="r"; }
|
||||
else if ("center".equals(sTextAlign)) { sAlignmentChar="c"; }
|
||||
}
|
||||
declarations
|
||||
.append("\\newenvironment{")
|
||||
.append(sLevelName[i]).append("}{")
|
||||
.append("\\def\\writerlistleftskip{\\addtolength\\leftskip{")
|
||||
.append(Misc.add(sSpaceBefore,sLabelWidth)).append("}}")
|
||||
.append("\\def\\writerlistparindent{}")
|
||||
.append("\\def\\writerlistlabel{}");
|
||||
// Redefine \item
|
||||
declarations
|
||||
.append("\\def\\item{")
|
||||
.append("\\def\\writerlistparindent{\\setlength\\parindent{")
|
||||
.append("-").append(sLabelWidth).append("}}")
|
||||
.append("\\def\\writerlistlabel{");
|
||||
if (style.isNumber(i)) {
|
||||
declarations.append("\\stepcounter{")
|
||||
.append(sLevelName[i]).append("}");
|
||||
}
|
||||
declarations
|
||||
.append("\\makebox[").append(sLabelWidth).append("][")
|
||||
.append(sAlignmentChar).append("]{")
|
||||
.append("\\label").append(sLevelName[i]).append("}")
|
||||
.append("\\hspace{").append(sLabelDistance).append("}")
|
||||
.append("\\writerlistremovelabel}}}{}").nl();
|
||||
}
|
||||
}
|
||||
|
||||
/** <p>Create LaTeX list labels from an OOo list style. Examples:</p>
|
||||
* <p>Bullets:</p>
|
||||
* <pre>\newcommand\labelliststylei{\textbullet}
|
||||
* \newcommand\labelliststyleii{*}
|
||||
* \newcommand\labelliststyleiii{\textstylebullet{>}}</pre>
|
||||
* <p>Numbering:</p>
|
||||
* <pre>\newcounter{liststylei}
|
||||
* \newcounter{liststyleii}[liststylei]
|
||||
* \newcounter{liststyleiii}[liststyleii]
|
||||
* \renewcommand\theliststylei{\Roman{liststylei}}
|
||||
* \renewcommand\theliststyleii{\Roman{liststylei}.\arabic{liststyleii}}
|
||||
* \renewcommand\theliststyleiii{\alph{liststyleiii}}
|
||||
* \newcommand\labelliststylei{\textstylelabel{\theliststylei .}}
|
||||
* \newcommand\labelliststyleii{\textstylelabel{\theliststyleii .}}
|
||||
* \newcommand\labelliststyleiii{\textstylelabel{\theliststyleiii )}}</pre>
|
||||
*
|
||||
* @param <code>style</code> the OOo list style to use
|
||||
* @param <code>sName</code> an array of label basenames to use
|
||||
* @param <code>nMaxLevel</code> the highest level in this numbering
|
||||
* @param <code>bDeclareCounters</code> true if counters should be declared (they may
|
||||
* exist already, eg. "section", "subsection"... or "enumi", "enumii"...
|
||||
* @param <code>bRenewLabels</code> true if labels should be defined with \renewcommand
|
||||
* @param <code>bUseTextStyle</code> true if labels should be formatted with the associated text style
|
||||
* (rather than \newcommand).
|
||||
* @param <code>ldp</code> the <code>LaTeXDocumentPortion</code> to add LaTeX code to.
|
||||
*/
|
||||
private void createLabels(ListStyle style, String[] sName, int nMaxLevel,
|
||||
boolean bDeclareCounters, boolean bRenewLabels,
|
||||
boolean bUseTextStyle, LaTeXDocumentPortion ldp) {
|
||||
// Declare counters if required (eg. "\newcounter{countername1}[countername2]")
|
||||
if (bDeclareCounters) {
|
||||
int j = 0;
|
||||
for (int i=1; i<=nMaxLevel; i++) {
|
||||
if (style.isNumber(i)) {
|
||||
ldp.append("\\newcounter{").append(sName[i]).append("}");
|
||||
if (j>0) { ldp.append("[").append(sName[j]).append("]"); }
|
||||
ldp.nl();
|
||||
j = i;
|
||||
}
|
||||
}
|
||||
}
|
||||
// Create numbering for each level (eg. "\arabic{countername}")
|
||||
String[] sNumFormat = new String[nMaxLevel+1];
|
||||
for (int i=1; i<=nMaxLevel; i++) {
|
||||
String s = numFormat(style.getLevelProperty(i,XMLString.STYLE_NUM_FORMAT));
|
||||
if (s==null) { sNumFormat[i]=""; }
|
||||
else { sNumFormat[i] = s + "{" + sName[i] + "}"; }
|
||||
}
|
||||
// Create numberings (ie. define "\thecountername"):
|
||||
for (int i=1; i<=nMaxLevel; i++) {
|
||||
if (style.isNumber(i)) {
|
||||
ldp.append("\\renewcommand\\the").append(sName[i]).append("{");
|
||||
int nLevels = Misc.getPosInteger(style.getLevelProperty(i,XMLString.TEXT_DISPLAY_LEVELS),1);
|
||||
for (int j=i-nLevels+1; j<i; j++) {
|
||||
if (style.isNumber(j)) {
|
||||
ldp.append(sNumFormat[j]).append(".");
|
||||
}
|
||||
}
|
||||
ldp.append(sNumFormat[i]);
|
||||
ldp.append("}").nl();
|
||||
}
|
||||
}
|
||||
// Create labels (ie. define "\labelcountername"):
|
||||
for (int i=1; i<=nMaxLevel; i++) {
|
||||
ldp.append(bRenewLabels ? "\\renewcommand" : "\\newcommand")
|
||||
.append("\\label").append(sName[i]).append("{");
|
||||
// Apply text style if required
|
||||
BeforeAfter baText = new BeforeAfter();
|
||||
if (bUseTextStyle) {
|
||||
String sStyleName = style.getLevelProperty(i,XMLString.TEXT_STYLE_NAME);
|
||||
palette.getCharSc().applyTextStyle(sStyleName,baText,new Context());
|
||||
}
|
||||
|
||||
// Create label content
|
||||
if (style.isNumber(i)) {
|
||||
String sPrefix = style.getLevelProperty(i,XMLString.STYLE_NUM_PREFIX);
|
||||
String sSuffix = style.getLevelProperty(i,XMLString.STYLE_NUM_SUFFIX);
|
||||
// Apply style
|
||||
ldp.append(baText.getBefore());
|
||||
if (sPrefix!=null) { ldp.append(sPrefix); }
|
||||
ldp.append("\\the").append(sName[i]);
|
||||
if (sSuffix!=null) { ldp.append(sSuffix); }
|
||||
ldp.append(baText.getAfter());
|
||||
}
|
||||
else if (style.isBullet(i)) {
|
||||
String sBullet = style.getLevelProperty(i,XMLString.TEXT_BULLET_CHAR);
|
||||
// Apply style
|
||||
ldp.append(baText.getBefore());
|
||||
if (sBullet!=null) {
|
||||
// Bullets are usually symbols, so this should be OK:
|
||||
ldp.append(palette.getI18n().convert(sBullet,false,"en"));
|
||||
}
|
||||
ldp.append(baText.getAfter());
|
||||
}
|
||||
else {
|
||||
// TODO: Support images!
|
||||
ldp.append("\\textbullet");
|
||||
}
|
||||
|
||||
ldp.append("}").nl();
|
||||
}
|
||||
}
|
||||
|
||||
/* Helper: Get a length property that defaults to 0cm. */
|
||||
private String getLength(ListStyle style,int nLevel,String sProperty) {
|
||||
String s = style.getLevelStyleProperty(nLevel,sProperty);
|
||||
if (s==null) { return "0cm"; }
|
||||
else { return s; }
|
||||
}
|
||||
|
||||
/* Helper: Get display name, or original name if it doesn't exist */
|
||||
private String getDisplayName(String sName) {
|
||||
String sDisplayName = ofr.getListStyles().getDisplayName(sName);
|
||||
return sDisplayName!=null ? sDisplayName : sName;
|
||||
}
|
||||
|
||||
/* Helper: Convert OOo number format to LaTeX number format */
|
||||
public static final String numFormat(String sFormat){
|
||||
if ("1".equals(sFormat)) { return "\\arabic"; }
|
||||
else if ("i".equals(sFormat)) { return "\\roman"; }
|
||||
else if ("I".equals(sFormat)) { return "\\Roman"; }
|
||||
else if ("a".equals(sFormat)) { return "\\alph"; }
|
||||
else if ("A".equals(sFormat)) { return "\\Alph"; }
|
||||
else { return null; }
|
||||
}
|
||||
|
||||
}
|
232
source/java/writer2latex/latex/MathmlConverter.java
Normal file
232
source/java/writer2latex/latex/MathmlConverter.java
Normal file
|
@ -0,0 +1,232 @@
|
|||
/************************************************************************
|
||||
*
|
||||
* MathmlConverter.java
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License version 2.1, as published by the Free Software Foundation.
|
||||
*
|
||||
* This library 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
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston,
|
||||
* MA 02111-1307 USA
|
||||
*
|
||||
* Copyright: 2002-2008 by Henrik Just
|
||||
*
|
||||
* All Rights Reserved.
|
||||
*
|
||||
* Version 1.0 (2008-11-22)
|
||||
*
|
||||
*/
|
||||
|
||||
package writer2latex.latex;
|
||||
|
||||
//import java.util.Hashtable;
|
||||
|
||||
import org.w3c.dom.Document;
|
||||
import org.w3c.dom.Element;
|
||||
import org.w3c.dom.Node;
|
||||
import org.w3c.dom.NodeList;
|
||||
|
||||
//import writer2latex.latex.i18n.I18n;
|
||||
import writer2latex.office.MIMETypes;
|
||||
import writer2latex.office.OfficeReader;
|
||||
import writer2latex.office.XMLString;
|
||||
import writer2latex.util.Misc;
|
||||
import writer2latex.xmerge.EmbeddedObject;
|
||||
import writer2latex.xmerge.EmbeddedXMLObject;
|
||||
|
||||
/**
|
||||
* This class converts mathml nodes to LaTeX.
|
||||
* (Actually it only converts the starmath annotation currently, if available).
|
||||
*/
|
||||
public final class MathmlConverter extends ConverterHelper {
|
||||
|
||||
private StarMathConverter smc;
|
||||
|
||||
private boolean bContainsFormulas = false;
|
||||
|
||||
public MathmlConverter(OfficeReader ofr,LaTeXConfig config, ConverterPalette palette) {
|
||||
super(ofr,config,palette);
|
||||
smc = new StarMathConverter(palette.getI18n(),config);
|
||||
}
|
||||
|
||||
public void appendDeclarations(LaTeXDocumentPortion pack, LaTeXDocumentPortion decl) {
|
||||
if (bContainsFormulas) {
|
||||
if (config.useOoomath()) {
|
||||
pack.append("\\usepackage{ooomath}").nl();
|
||||
}
|
||||
else {
|
||||
smc.appendDeclarations(pack,decl);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public String convert(Node settings, Node formula) {
|
||||
// TODO: Use settings to determine display mode/text mode
|
||||
// formula must be a math:math node
|
||||
// First try to find a StarMath annotation
|
||||
Node semantics = Misc.getChildByTagName(formula,XMLString.MATH_SEMANTICS);
|
||||
if (semantics!=null) {
|
||||
Node annotation = Misc.getChildByTagName(semantics,XMLString.MATH_ANNOTATION);
|
||||
if (annotation!=null) {
|
||||
String sStarMath = "";
|
||||
if (annotation.hasChildNodes()) {
|
||||
NodeList anl = annotation.getChildNodes();
|
||||
int nLen = anl.getLength();
|
||||
for (int i=0; i<nLen; i++) {
|
||||
if (anl.item(i).getNodeType() == Node.TEXT_NODE) {
|
||||
sStarMath+=anl.item(i).getNodeValue();
|
||||
}
|
||||
}
|
||||
bContainsFormulas = true;
|
||||
return smc.convert(sStarMath);
|
||||
}
|
||||
}
|
||||
}
|
||||
// No annotation was found. In this case we should convert the mathml,
|
||||
// but currently we ignore the problem.
|
||||
// TODO: Investigate if Vasil I. Yaroshevich's MathML->LaTeX
|
||||
// XSL transformation could be used here. (Potential problem:
|
||||
// OOo uses MathML 1.01, not MathML 2)
|
||||
return "\\text{Warning: No StarMath annotation}";
|
||||
}
|
||||
|
||||
// Data for display equations
|
||||
private Element theEquation = null;
|
||||
private Element theSequence = null;
|
||||
|
||||
/**Try to convert a paragraph as a display equation:
|
||||
* A paragraph which contains exactly one formula + at most one sequence
|
||||
* number is treated as a display equation. Other content must be brackets
|
||||
* or whitespace (possible with formatting).
|
||||
* @param node the paragraph
|
||||
* @param ldp the LaTeXDocumentPortion to contain the converted equation
|
||||
* @return true if the conversion was succesful, false if the paragraph
|
||||
* did not contain a display equation
|
||||
*/
|
||||
public boolean handleDisplayEquation(Element node, LaTeXDocumentPortion ldp) {
|
||||
theEquation = null;
|
||||
theSequence = null;
|
||||
if (parseDisplayEquation(node) && theEquation!=null) {
|
||||
if (theSequence!=null) {
|
||||
// Numbered equation
|
||||
ldp.append("\\begin{equation}");
|
||||
palette.getFieldCv().handleSequenceLabel(theSequence,ldp);
|
||||
ldp.nl()
|
||||
.append(convert(null,theEquation)).nl()
|
||||
.append("\\end{equation}").nl();
|
||||
}
|
||||
else {
|
||||
// Unnumbered equation
|
||||
ldp.append("\\begin{equation*}").nl()
|
||||
.append(convert(null,theEquation)).nl()
|
||||
.append("\\end{equation*}").nl();
|
||||
}
|
||||
return true;
|
||||
}
|
||||
else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
private boolean parseDisplayEquation(Node node) {
|
||||
Node child = node.getFirstChild();
|
||||
while (child!=null) {
|
||||
Node equation = getFormula(child);
|
||||
if (equation!=null) {
|
||||
if (theEquation==null) {
|
||||
theEquation = (Element) equation;
|
||||
}
|
||||
else { // two or more equations -> not a display
|
||||
return false;
|
||||
}
|
||||
}
|
||||
else if (Misc.isElement(child)) {
|
||||
String sName = child.getNodeName();
|
||||
if (XMLString.TEXT_SEQUENCE.equals(sName)) {
|
||||
if (theSequence==null) {
|
||||
theSequence = (Element) child;
|
||||
}
|
||||
else { // two sequence numbers -> not a display
|
||||
return false;
|
||||
}
|
||||
}
|
||||
else if (XMLString.TEXT_SPAN.equals(sName)) {
|
||||
if (!parseDisplayEquation(child)) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
else if (XMLString.TEXT_S.equals(sName)) {
|
||||
// Spaces are allowed
|
||||
}
|
||||
else if (XMLString.TEXT_TAB.equals(sName)) {
|
||||
// Tab stops are allowed
|
||||
}
|
||||
else if (XMLString.TEXT_TAB_STOP.equals(sName)) { // old
|
||||
// Tab stops are allowed
|
||||
}
|
||||
else {
|
||||
// Other elements -> not a display
|
||||
return false;
|
||||
}
|
||||
}
|
||||
else if (Misc.isText(child)) {
|
||||
String s = child.getNodeValue();
|
||||
int nLen = s.length();
|
||||
for (int i=0; i<nLen; i++) {
|
||||
char c = s.charAt(i);
|
||||
if (c!='(' && c!=')' && c!='[' && c!=']' && c!='{' && c!='}' && c!=' ' && c!='\u00A0') {
|
||||
// Characters except brackets and whitespace -> not a display
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
child = child.getNextSibling();
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
// TODO: Extend OfficeReader to handle frames
|
||||
private Node getFormula(Node node) {
|
||||
if (Misc.isElement(node,XMLString.DRAW_FRAME)) {
|
||||
node=Misc.getFirstChildElement(node);
|
||||
}
|
||||
|
||||
String sHref = Misc.getAttribute(node,XMLString.XLINK_HREF);
|
||||
|
||||
if (sHref!=null) { // Embedded object in package or linked object
|
||||
if (ofr.isInPackage(sHref)) { // Embedded object in package
|
||||
if (sHref.startsWith("#")) { sHref=sHref.substring(1); }
|
||||
if (sHref.startsWith("./")) { sHref=sHref.substring(2); }
|
||||
EmbeddedObject object = palette.getEmbeddedObject(sHref);
|
||||
if (object!=null) {
|
||||
if (MIMETypes.MATH.equals(object.getType()) || MIMETypes.ODF.equals(object.getType())) { // Formula!
|
||||
try {
|
||||
Document formuladoc = ((EmbeddedXMLObject) object).getContentDOM();
|
||||
return Misc.getChildByTagName(formuladoc,XMLString.MATH_MATH);
|
||||
}
|
||||
catch (org.xml.sax.SAXException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
catch (java.io.IOException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
else { // flat xml, object is contained in node
|
||||
return Misc.getChildByTagName(node,XMLString.MATH_MATH);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
|
||||
|
||||
}
|
391
source/java/writer2latex/latex/NoteConverter.java
Normal file
391
source/java/writer2latex/latex/NoteConverter.java
Normal file
|
@ -0,0 +1,391 @@
|
|||
/************************************************************************
|
||||
*
|
||||
* NoteConverter.java
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License version 2.1, as published by the Free Software Foundation.
|
||||
*
|
||||
* This library 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
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston,
|
||||
* MA 02111-1307 USA
|
||||
*
|
||||
* Copyright: 2002-2008 by Henrik Just
|
||||
*
|
||||
* All Rights Reserved.
|
||||
*
|
||||
* Version 1.0 (2008-11-23)
|
||||
*
|
||||
*/
|
||||
|
||||
package writer2latex.latex;
|
||||
|
||||
import java.util.LinkedList;
|
||||
|
||||
import org.w3c.dom.Element;
|
||||
import org.w3c.dom.Node;
|
||||
import org.w3c.dom.NodeList;
|
||||
|
||||
import writer2latex.util.Misc;
|
||||
import writer2latex.util.ExportNameCollection;
|
||||
import writer2latex.office.OfficeReader;
|
||||
import writer2latex.office.PropertySet;
|
||||
import writer2latex.office.StyleWithProperties;
|
||||
import writer2latex.office.XMLString;
|
||||
import writer2latex.latex.util.BeforeAfter;
|
||||
import writer2latex.latex.util.Context;
|
||||
|
||||
/**
|
||||
* <p>This class handles conversion of footnotes and endnotes, including
|
||||
* references. It takes advantage of the packages <code>endnotes.sty</code>
|
||||
* and <code>perpage.sty</code> if allowed in the configuration.</p>
|
||||
*/
|
||||
public class NoteConverter extends ConverterHelper {
|
||||
|
||||
private ExportNameCollection footnotenames = new ExportNameCollection(true);
|
||||
private ExportNameCollection endnotenames = new ExportNameCollection(true);
|
||||
private boolean bContainsEndnotes = false;
|
||||
private boolean bContainsFootnotes = false;
|
||||
// Keep track of footnotes (inside minipage etc.), that should be typeset later
|
||||
private LinkedList postponedFootnotes = new LinkedList();
|
||||
|
||||
public NoteConverter(OfficeReader ofr, LaTeXConfig config, ConverterPalette palette) {
|
||||
super(ofr,config,palette);
|
||||
}
|
||||
|
||||
/** <p>Append declarations needed by the <code>NoteConverter</code> to
|
||||
* the preamble.
|
||||
* @param pack the <code>LaTeXDocumentPortion</code> to which
|
||||
* declarations of packages should be added (<code>\\usepackage</code>).
|
||||
* @param decl the <code>LaTeXDocumentPortion</code> to which
|
||||
* other declarations should be added.
|
||||
*/
|
||||
public void appendDeclarations(LaTeXDocumentPortion pack, LaTeXDocumentPortion decl) {
|
||||
if (bContainsEndnotes) { pack.append("\\usepackage{endnotes}").nl(); }
|
||||
if (bContainsFootnotes) convertFootnotesConfiguration(decl);
|
||||
if (bContainsEndnotes) convertEndnotesConfiguration(decl);
|
||||
}
|
||||
|
||||
/** <p>Process a footnote (text:footnote tag)
|
||||
* @param node The element containing the footnote
|
||||
* @param ldp the <code>LaTeXDocumentPortion</code> to which
|
||||
* LaTeX code should be added
|
||||
* @param oc the current context
|
||||
*/
|
||||
public void handleFootnote(Element node, LaTeXDocumentPortion ldp, Context oc) {
|
||||
Context ic = (Context) oc.clone();
|
||||
ic.setInFootnote(true);
|
||||
|
||||
String sId = node.getAttribute(XMLString.TEXT_ID);
|
||||
Element fntbody = Misc.getChildByTagName(node,XMLString.TEXT_FOOTNOTE_BODY);
|
||||
if (fntbody==null) { // try oasis
|
||||
fntbody = Misc.getChildByTagName(node,XMLString.TEXT_NOTE_BODY);
|
||||
}
|
||||
if (fntbody != null) {
|
||||
bContainsFootnotes = true;
|
||||
if (ic.isNoFootnotes()) {
|
||||
ldp.append("\\footnotemark{}");
|
||||
postponedFootnotes.add(fntbody);
|
||||
}
|
||||
else {
|
||||
ldp.append("\\footnote");
|
||||
ldp.append("{");
|
||||
if (sId != null && ofr.hasFootnoteRefTo(sId)) {
|
||||
ldp.append("\\label{fnt:"+footnotenames.getExportName(sId)+"}");
|
||||
}
|
||||
traverseNoteBody(fntbody,ldp,ic);
|
||||
ldp.append("}");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/** Flush the queue of postponed footnotes */
|
||||
public void flushFootnotes(LaTeXDocumentPortion ldp, Context oc) {
|
||||
// We may still be in a context with no footnotes
|
||||
if (oc.isNoFootnotes()) { return; }
|
||||
// Type out all postponed footnotes:
|
||||
Context ic = (Context) oc.clone();
|
||||
ic.setInFootnote(true);
|
||||
int n = postponedFootnotes.size();
|
||||
if (n==1) {
|
||||
ldp.append("\\footnotetext{");
|
||||
traverseNoteBody((Element) postponedFootnotes.get(0),ldp,ic);
|
||||
ldp.append("}").nl();
|
||||
postponedFootnotes.clear();
|
||||
}
|
||||
else if (n>1) {
|
||||
// Several footnotes; have to adjust the footnote counter
|
||||
ldp.append("\\addtocounter{footnote}{-"+n+"}").nl();
|
||||
for (int i=0; i<n; i++) {
|
||||
ldp.append("\\stepcounter{footnote}\\footnotetext{");
|
||||
traverseNoteBody((Element) postponedFootnotes.get(i),ldp,ic);
|
||||
ldp.append("}").nl();
|
||||
}
|
||||
postponedFootnotes.clear();
|
||||
}
|
||||
}
|
||||
|
||||
/** <p>Process an endnote (text:endnote tag)
|
||||
* @param node The element containing the endnote
|
||||
* @param ldp the <code>LaTeXDocumentPortion</code> to which
|
||||
* LaTeX code should be added
|
||||
* @param oc the current context
|
||||
*/
|
||||
public void handleEndnote(Element node, LaTeXDocumentPortion ldp, Context oc) {
|
||||
Context ic = (Context) oc.clone();
|
||||
ic.setInFootnote(true);
|
||||
|
||||
String sId = node.getAttribute(XMLString.TEXT_ID);
|
||||
Element entbody = Misc.getChildByTagName(node,XMLString.TEXT_ENDNOTE_BODY);
|
||||
if (entbody==null) { // try oasis
|
||||
entbody = Misc.getChildByTagName(node,XMLString.TEXT_NOTE_BODY);
|
||||
}
|
||||
if (entbody != null) {
|
||||
if (ic.isNoFootnotes() && !config.useEndnotes()) {
|
||||
ldp.append("\\footnotemark()");
|
||||
postponedFootnotes.add(entbody);
|
||||
}
|
||||
else {
|
||||
if (config.useEndnotes()) {
|
||||
ldp.append("\\endnote");
|
||||
bContainsEndnotes = true;
|
||||
}
|
||||
else {
|
||||
ldp.append("\\footnote");
|
||||
bContainsFootnotes = true;
|
||||
}
|
||||
ldp.append("{");
|
||||
if (sId != null && ofr.hasEndnoteRefTo(sId)) {
|
||||
ldp.append("\\label{ent:"+endnotenames.getExportName(sId)+"}");
|
||||
}
|
||||
traverseNoteBody(entbody,ldp,ic);
|
||||
ldp.append("}");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/** <p>Insert the endnotes into the documents.
|
||||
* @param ldp the <code>LaTeXDocumentPortion</code> to which
|
||||
* the endnotes should be added.
|
||||
*/
|
||||
public void insertEndnotes(LaTeXDocumentPortion ldp) {
|
||||
if (bContainsEndnotes) {
|
||||
ldp.append("\\clearpage").nl()
|
||||
.append("\\theendnotes").nl();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
/** <p>Process a note reference (text:note-ref tag, oasis)
|
||||
* @param node The element containing the note reference
|
||||
* @param ldp the <code>LaTeXDocumentPortion</code> to which
|
||||
* LaTeX code should be added
|
||||
* @param oc the current context
|
||||
*/
|
||||
public void handleNoteRef(Element node, LaTeXDocumentPortion ldp, Context oc) {
|
||||
String sClass=node.getAttribute(XMLString.TEXT_NOTE_CLASS);
|
||||
if (sClass.equals("footnote")) { handleFootnoteRef(node,ldp,oc); }
|
||||
else if (sClass.equals("endnote")) { handleEndnoteRef(node,ldp,oc); }
|
||||
}
|
||||
|
||||
/** <p>Process a footnote reference (text:footnote-ref tag)
|
||||
* @param node The element containing the footnote reference
|
||||
* @param ldp the <code>LaTeXDocumentPortion</code> to which
|
||||
* LaTeX code should be added
|
||||
* @param oc the current context
|
||||
*/
|
||||
public void handleFootnoteRef(Element node, LaTeXDocumentPortion ldp, Context oc) {
|
||||
String sFormat = node.getAttribute(XMLString.TEXT_REFERENCE_FORMAT);
|
||||
String sName = node.getAttribute(XMLString.TEXT_REF_NAME);
|
||||
if (("page".equals(sFormat) || "".equals(sFormat)) && sName!=null) {
|
||||
ldp.append("\\pageref{fnt:"+footnotenames.getExportName(sName)+"}");
|
||||
}
|
||||
else if ("text".equals(sFormat) && sName!=null) {
|
||||
ldp.append("\\ref{fnt:"+footnotenames.getExportName(sName)+"}");
|
||||
}
|
||||
else { // use current value
|
||||
palette.getInlineCv().traversePCDATA(node,ldp,oc);
|
||||
}
|
||||
}
|
||||
|
||||
/** <p>Process an endnote reference (text:endnote-ref tag)
|
||||
* @param node The element containing the endnote reference
|
||||
* @param ldp the <code>LaTeXDocumentPortion</code> to which
|
||||
* LaTeX code should be added
|
||||
* @param oc the current context
|
||||
*/
|
||||
public void handleEndnoteRef(Element node, LaTeXDocumentPortion ldp, Context oc) {
|
||||
String sFormat = node.getAttribute(XMLString.TEXT_REFERENCE_FORMAT);
|
||||
String sName = node.getAttribute(XMLString.TEXT_REF_NAME);
|
||||
if (("page".equals(sFormat) || "".equals(sFormat)) && sName!=null) {
|
||||
ldp.append("\\pageref{ent:"+endnotenames.getExportName(sName)+"}");
|
||||
}
|
||||
else if ("text".equals(sFormat) && sName!=null) {
|
||||
ldp.append("\\ref{ent:"+endnotenames.getExportName(sName)+"}");
|
||||
}
|
||||
else { // use current value
|
||||
palette.getInlineCv().traversePCDATA(node,ldp,oc);
|
||||
}
|
||||
}
|
||||
|
||||
/** <p>Add a footnote name. The method <code>handleFootnote</code> includes
|
||||
* a <code>\label</code> only if the footnote name is already known to the
|
||||
* <code>NoteConverter</code>. Hence this method is invoked by the prepass
|
||||
* for each footnote reference. The end result is, that only necessary
|
||||
* labels will be included.
|
||||
* @param sName the name (id) of the footnote
|
||||
*/
|
||||
public void addFootnoteName(String sName) { footnotenames.addName(sName); }
|
||||
|
||||
/** <p>Add an endnote name. The method <code>handleEndnote</code> includes
|
||||
* a <code>\label</code> only if the endnote name is already known to the
|
||||
* <code>NoteConverter</code>. Hence this method is invoked by the prepass
|
||||
* for each endnote reference. The end result is, that only necessary
|
||||
* labels will be included.
|
||||
* @param sName the name (id) of the endnote
|
||||
*/
|
||||
public void addEndnoteName(String sName) { endnotenames.addName(sName); }
|
||||
|
||||
/*
|
||||
* Process the contents of a footnote or endnote
|
||||
* TODO: Merge with BlockConverter.traverseBlockText?
|
||||
*/
|
||||
private void traverseNoteBody (Element node, LaTeXDocumentPortion ldp, Context oc) {
|
||||
if (node.hasChildNodes()) {
|
||||
NodeList nList = node.getChildNodes();
|
||||
int len = nList.getLength();
|
||||
|
||||
for (int i = 0; i < len; i++) {
|
||||
Node childNode = nList.item(i);
|
||||
|
||||
if (childNode.getNodeType() == Node.ELEMENT_NODE) {
|
||||
Element child = (Element)childNode;
|
||||
String nodeName = child.getTagName();
|
||||
|
||||
palette.getInfo().addDebugInfo(child,ldp);
|
||||
|
||||
if (nodeName.equals(XMLString.TEXT_H)) {
|
||||
palette.getHeadingCv().handleHeading(child,ldp,oc);
|
||||
}
|
||||
|
||||
if (nodeName.equals(XMLString.TEXT_P)) {
|
||||
palette.getInlineCv().traverseInlineText(child,ldp,oc);
|
||||
if (i<len-1) {
|
||||
if (nList.item(i+1).getNodeName().startsWith(XMLString.TEXT_)) {
|
||||
ldp.append("\\par ");
|
||||
}
|
||||
else {
|
||||
ldp.nl();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
else if (nodeName.equals(XMLString.TEXT_LIST)) { // oasis
|
||||
palette.getBlockCv().handleList(child,ldp,oc);
|
||||
}
|
||||
|
||||
if (nodeName.equals(XMLString.TEXT_ORDERED_LIST)) {
|
||||
palette.getBlockCv().handleList(child,ldp,oc);
|
||||
}
|
||||
|
||||
if (nodeName.equals(XMLString.TEXT_UNORDERED_LIST)) {
|
||||
palette.getBlockCv().handleList(child,ldp,oc);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Convert footnotes configuration.
|
||||
private void convertFootnotesConfiguration(LaTeXDocumentPortion ldp) {
|
||||
// Note: Continuation notices are not supported in LaTeX
|
||||
// TODO: Support text:footnotes-postion="document" (footnotes as endnotes)
|
||||
// TODO: Support text:start-numbering-at="page" (footnpag.sty/footmisc.sty)
|
||||
convertFootEndnotesConfiguration(ofr.getFootnotesConfiguration(),"foot",ldp);
|
||||
}
|
||||
|
||||
// Convert endnotes configuration.
|
||||
private void convertEndnotesConfiguration(LaTeXDocumentPortion ldp) {
|
||||
// Note: Continuation notices are not supported in LaTeX
|
||||
convertFootEndnotesConfiguration(ofr.getEndnotesConfiguration(),"end",ldp);
|
||||
}
|
||||
|
||||
/* Convert {foot|end}notes configuration.
|
||||
* Note: All {foot|end}notes are formatted with the default style for {foot|end}footnotes.
|
||||
* (This doesn't conform with the file format specification, but in LaTeX
|
||||
* all {foot|end}notes are usually formatted in a fixed style.)
|
||||
*/
|
||||
private void convertFootEndnotesConfiguration(PropertySet notes, String sType, LaTeXDocumentPortion ldp) {
|
||||
if (config.formatting()<LaTeXConfig.CONVERT_BASIC) { return; }
|
||||
String sTypeShort = sType.equals("foot") ? "fn" : "en";
|
||||
if (notes==null) { return; }
|
||||
ldp.append("% ").append(sType).append("notes configuration").nl()
|
||||
.append("\\makeatletter").nl();
|
||||
|
||||
// The numbering style is controlled by \the{foot|end}note
|
||||
String sFormat = notes.getProperty(XMLString.STYLE_NUM_FORMAT);
|
||||
if (sFormat!=null) {
|
||||
ldp.append("\\renewcommand\\the").append(sType).append("note{")
|
||||
.append(ListStyleConverter.numFormat(sFormat))
|
||||
.append("{").append(sType).append("note}}").nl();
|
||||
}
|
||||
|
||||
// Number {foot|end}notes by sections
|
||||
if ("chapter".equals(notes.getProperty(XMLString.TEXT_START_NUMBERING_AT))) {
|
||||
ldp.append("\\@addtoreset{").append(sType).append("note}{section}").nl();
|
||||
}
|
||||
|
||||
// Set start value offset (default 0)
|
||||
int nStartValue = Misc.getPosInteger(notes.getProperty(XMLString.TEXT_START_VALUE),0);
|
||||
if (nStartValue!=0) {
|
||||
ldp.append("\\setcounter{").append(sType).append("note}{"+nStartValue+"}").nl();
|
||||
}
|
||||
|
||||
if (config.formatting()>=LaTeXConfig.CONVERT_MOST) {
|
||||
// The formatting of the {foot|end}note citation is controlled by \@make{fn|en}mark
|
||||
String sCitBodyStyle = notes.getProperty(XMLString.TEXT_CITATION_BODY_STYLE_NAME);
|
||||
if (sCitBodyStyle!=null && ofr.getTextStyle(sCitBodyStyle)!=null) {
|
||||
BeforeAfter baText = new BeforeAfter();
|
||||
palette.getCharSc().applyTextStyle(sCitBodyStyle,baText,new Context());
|
||||
ldp.append("\\renewcommand\\@make").append(sTypeShort).append("mark{\\mbox{")
|
||||
.append(baText.getBefore())
|
||||
.append("\\@the").append(sTypeShort).append("mark")
|
||||
.append(baText.getAfter())
|
||||
.append("}}").nl();
|
||||
}
|
||||
|
||||
// The layout and formatting of the {foot|end}note is controlled by \@make{fn|en}text
|
||||
String sCitStyle = notes.getProperty(XMLString.TEXT_CITATION_STYLE_NAME);
|
||||
String sStyleName = notes.getProperty(XMLString.TEXT_DEFAULT_STYLE_NAME);
|
||||
if (sStyleName!=null) {
|
||||
BeforeAfter baText = new BeforeAfter();
|
||||
palette.getCharSc().applyTextStyle(sCitStyle,baText,new Context());
|
||||
StyleWithProperties style = ofr.getParStyle(sStyleName);
|
||||
if (style!=null) {
|
||||
BeforeAfter baPar = new BeforeAfter();
|
||||
palette.getCharSc().applyHardCharFormatting(style,baPar);
|
||||
ldp.append("\\renewcommand\\@make").append(sTypeShort)
|
||||
.append("text[1]{\\noindent")
|
||||
.append(baText.getBefore())
|
||||
.append("\\@the").append(sTypeShort).append("mark\\ ")
|
||||
.append(baText.getAfter())
|
||||
.append(baPar.getBefore())
|
||||
.append("#1")
|
||||
.append(baPar.getAfter());
|
||||
ldp.append("}").nl();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
ldp.append("\\makeatother").nl();
|
||||
}
|
||||
|
||||
|
||||
}
|
16
source/java/writer2latex/latex/Package.html
Normal file
16
source/java/writer2latex/latex/Package.html
Normal file
|
@ -0,0 +1,16 @@
|
|||
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
|
||||
|
||||
<html>
|
||||
<head>
|
||||
<title>The package writer2latex.latex</title>
|
||||
</head>
|
||||
|
||||
<body>
|
||||
<p>This package contains LaTeX specific code.</p>
|
||||
<p>It contains a <code>writerlatex.api.Converter</code> implementation for
|
||||
conversion into LaTeX.</p>
|
||||
<p>Since version 1.0 you can build Writer2LaTeX without this package if you
|
||||
don't need LaTeX support (in this case you can exclude writer2latex.bibtex as
|
||||
well).</p>
|
||||
</body>
|
||||
</html>
|
596
source/java/writer2latex/latex/PageStyleConverter.java
Normal file
596
source/java/writer2latex/latex/PageStyleConverter.java
Normal file
|
@ -0,0 +1,596 @@
|
|||
/************************************************************************
|
||||
*
|
||||
* PageStyleConverter.java
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License version 2.1, as published by the Free Software Foundation.
|
||||
*
|
||||
* This library 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
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston,
|
||||
* MA 02111-1307 USA
|
||||
*
|
||||
* Copyright: 2002-2008 by Henrik Just
|
||||
*
|
||||
* All Rights Reserved.
|
||||
*
|
||||
* Version 1.0 (2008-11-23)
|
||||
*
|
||||
*/
|
||||
|
||||
package writer2latex.latex;
|
||||
|
||||
import java.util.Enumeration;
|
||||
|
||||
import org.w3c.dom.Element;
|
||||
import org.w3c.dom.Node;
|
||||
|
||||
import writer2latex.util.CSVList;
|
||||
import writer2latex.util.Misc;
|
||||
import writer2latex.office.*;
|
||||
import writer2latex.latex.util.BeforeAfter;
|
||||
import writer2latex.latex.util.Context;
|
||||
|
||||
// TODO: chngpage.sty??
|
||||
|
||||
/* This class creates LaTeX code from OOo page layouts/master pages
|
||||
*/
|
||||
public class PageStyleConverter extends StyleConverter {
|
||||
|
||||
// Value of attribute text:display of most recent text:chapter field
|
||||
// This is used to handle chaptermarks in headings
|
||||
private String sChapterField1 = null;
|
||||
private String sChapterField2 = null;
|
||||
|
||||
// The page layout used for the page geometry
|
||||
// (LaTeX only supports one page geometry per page)
|
||||
private PageLayout mainPageLayout;
|
||||
|
||||
/** <p>Constructs a new <code>PageStyleConverter</code>.</p>
|
||||
*/
|
||||
public PageStyleConverter(OfficeReader ofr, LaTeXConfig config,
|
||||
ConverterPalette palette) {
|
||||
super(ofr,config,palette);
|
||||
// Determine the main page master
|
||||
MasterPage firstMasterPage = ofr.getFirstMasterPage();
|
||||
String sPageLayoutName = null;
|
||||
if (firstMasterPage!=null) {
|
||||
MasterPage nextMasterPage = ofr.getMasterPage(
|
||||
firstMasterPage.getProperty(XMLString.STYLE_NEXT_STYLE_NAME));
|
||||
if (nextMasterPage!=null) {
|
||||
sPageLayoutName = nextMasterPage.getPageLayoutName();
|
||||
}
|
||||
else {
|
||||
sPageLayoutName = firstMasterPage.getPageLayoutName();
|
||||
}
|
||||
}
|
||||
mainPageLayout = ofr.getPageLayout(sPageLayoutName);
|
||||
}
|
||||
|
||||
public void appendDeclarations(LaTeXDocumentPortion pack, LaTeXDocumentPortion decl) {
|
||||
if (config.useFancyhdr()) { pack.append("\\usepackage{fancyhdr}").nl(); }
|
||||
// The first master page must be known
|
||||
MasterPage firstMasterPage = ofr.getFirstMasterPage();
|
||||
if (firstMasterPage!=null) {
|
||||
styleNames.addName(getDisplayName(firstMasterPage.getName()));
|
||||
}
|
||||
// Convert page geometry
|
||||
convertPageMasterGeometry(pack,decl);
|
||||
// Convert master pages
|
||||
convertMasterPages(decl);
|
||||
if (firstMasterPage!=null) {
|
||||
BeforeAfter ba = new BeforeAfter();
|
||||
applyMasterPage(firstMasterPage.getName(),ba);
|
||||
decl.append(ba.getBefore());
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
public void setChapterField1(String s) { sChapterField1 = s; }
|
||||
|
||||
public void setChapterField2(String s) { sChapterField2 = s; }
|
||||
|
||||
public boolean isTwocolumn() {
|
||||
return mainPageLayout!=null && mainPageLayout.getColCount()>1;
|
||||
}
|
||||
|
||||
/** <p>Apply page break properties from a style.</p>
|
||||
* @param style the style to use
|
||||
* @param bInherit true if inheritance from parent style should be used
|
||||
* @param ba a <code>BeforeAfter</code> to put code into
|
||||
*/
|
||||
public void applyPageBreak(StyleWithProperties style, boolean bInherit, BeforeAfter ba) {
|
||||
if (style==null) { return; }
|
||||
if (style.isAutomatic() && config.ignoreHardPageBreaks()) { return; }
|
||||
// A page break can be a simple page break before or after...
|
||||
String s = style.getProperty(XMLString.FO_BREAK_BEFORE,bInherit);
|
||||
if ("page".equals(s)) { ba.add("\\clearpage",""); }
|
||||
s = style.getProperty(XMLString.FO_BREAK_AFTER,bInherit);
|
||||
if ("page".equals(s)) { ba.add("","\\clearpage"); }
|
||||
// ...or it can be a new master page
|
||||
String sMasterPage = style.getMasterPageName();
|
||||
if (sMasterPage==null || sMasterPage.length()==0) { return; }
|
||||
ba.add("\\clearpage","");
|
||||
String sPageNumber=style.getProperty(XMLString.STYLE_PAGE_NUMBER);
|
||||
if (sPageNumber!=null) {
|
||||
int nPageNumber = Misc.getPosInteger(sPageNumber,1);
|
||||
ba.add("\\setcounter{page}{"+nPageNumber+"}","");
|
||||
}
|
||||
applyMasterPage(sMasterPage,ba);
|
||||
}
|
||||
|
||||
/** <p>Use a Master Page (pagestyle in LaTeX)</p>
|
||||
* @param sName name of the master page to use
|
||||
* @param ba the <code>BeforeAfter</code> to add code to.
|
||||
*/
|
||||
private void applyMasterPage(String sName, BeforeAfter ba) {
|
||||
if (config.pageFormatting()==LaTeXConfig.IGNORE_ALL) return;
|
||||
MasterPage style = ofr.getMasterPage(sName);
|
||||
if (style==null) { return; }
|
||||
String sNextName = style.getProperty(XMLString.STYLE_NEXT_STYLE_NAME);
|
||||
MasterPage nextStyle = ofr.getMasterPage(sNextName);
|
||||
if (style==nextStyle || nextStyle==null) {
|
||||
ba.add("\\pagestyle{"+styleNames.getExportName(getDisplayName(sName))+"}\n", "");
|
||||
}
|
||||
else {
|
||||
ba.add("\\pagestyle{"+styleNames.getExportName(getDisplayName(sNextName))+"}\n"+
|
||||
"\\thispagestyle{"+styleNames.getExportName(getDisplayName(sName))+"}\n","");
|
||||
}
|
||||
// todo: should warn the user if next master also contains a next-style-name;
|
||||
// LaTeX's page style mechanism cannot handle that
|
||||
}
|
||||
|
||||
/*
|
||||
* Process header or footer contents
|
||||
*/
|
||||
private void convertMasterPages(LaTeXDocumentPortion ldp) {
|
||||
if (config.pageFormatting()==LaTeXConfig.IGNORE_ALL) { return; }
|
||||
|
||||
Context context = new Context();
|
||||
context.resetFormattingFromStyle(ofr.getDefaultParStyle());
|
||||
context.setInHeaderFooter(true);
|
||||
|
||||
|
||||
Enumeration styles = ofr.getMasterPages().getStylesEnumeration();
|
||||
ldp.append("% Pages styles").nl();
|
||||
if (!config.useFancyhdr()) {
|
||||
ldp.append("\\makeatletter").nl();
|
||||
}
|
||||
while (styles.hasMoreElements()) {
|
||||
MasterPage style = (MasterPage) styles.nextElement();
|
||||
String sName = style.getName();
|
||||
if (styleNames.containsName(getDisplayName(sName))) {
|
||||
sChapterField1 = null;
|
||||
sChapterField2 = null;
|
||||
|
||||
String sPageLayout = style.getPageLayoutName();
|
||||
PageLayout pageLayout = ofr.getPageLayout(sPageLayout);
|
||||
|
||||
if (config.useFancyhdr()) {
|
||||
ldp.append("\\fancypagestyle{")
|
||||
.append(styleNames.getExportName(getDisplayName(sName)))
|
||||
.append("}{\\fancyhf{}").nl();
|
||||
// Header - odd or both
|
||||
ldp.append(" \\fancyhead[")
|
||||
.append(getParAlignment(style.getHeader()))
|
||||
.append(style.getHeaderLeft()!=null ? "O" : "")
|
||||
.append("]{");
|
||||
traverseHeaderFooter((Element)style.getHeader(),ldp,context);
|
||||
ldp.append("}").nl();
|
||||
// Header - even
|
||||
if (style.getHeaderLeft()!=null) {
|
||||
ldp.append(" \\fancyhead[")
|
||||
.append(getParAlignment(style.getHeaderLeft()))
|
||||
.append("E]{");
|
||||
traverseHeaderFooter((Element)style.getHeaderLeft(),ldp,context);
|
||||
ldp.append("}").nl();
|
||||
}
|
||||
// Footer - odd or both
|
||||
ldp.append(" \\fancyfoot[")
|
||||
.append(getParAlignment(style.getFooter()))
|
||||
.append(style.getFooterLeft()!=null ? "O" : "")
|
||||
.append("]{");
|
||||
traverseHeaderFooter((Element)style.getFooter(),ldp,context);
|
||||
ldp.append("}").nl();
|
||||
// Footer - even
|
||||
if (style.getFooterLeft()!=null) {
|
||||
ldp.append(" \\fancyfoot[")
|
||||
.append(getParAlignment(style.getFooterLeft()))
|
||||
.append("E]{");
|
||||
traverseHeaderFooter((Element)style.getFooterLeft(),ldp,context);
|
||||
ldp.append("}").nl();
|
||||
}
|
||||
// Rules
|
||||
ldp.append(" \\renewcommand\\headrulewidth{")
|
||||
.append(getBorderWidth(pageLayout,true))
|
||||
.append("}").nl()
|
||||
.append(" \\renewcommand\\footrulewidth{")
|
||||
.append(getBorderWidth(pageLayout,false))
|
||||
.append("}").nl();
|
||||
}
|
||||
else { // use low-level page styles
|
||||
ldp.append("\\newcommand\\ps@")
|
||||
.append(styleNames.getExportName(getDisplayName(sName)))
|
||||
.append("{").nl();
|
||||
// Header
|
||||
ldp.append(" \\renewcommand\\@oddhead{");
|
||||
traverseHeaderFooter((Element)style.getHeader(),ldp,context);
|
||||
ldp.append("}").nl();
|
||||
ldp.append(" \\renewcommand\\@evenhead{");
|
||||
if (style.getHeaderLeft()!=null) {
|
||||
traverseHeaderFooter((Element)style.getHeaderLeft(),ldp,context);
|
||||
}
|
||||
else if (style.getHeader()!=null) {
|
||||
ldp.append("\\@oddhead");
|
||||
}
|
||||
ldp.append("}").nl();
|
||||
// Footer
|
||||
ldp.append(" \\renewcommand\\@oddfoot{");
|
||||
traverseHeaderFooter((Element)style.getFooter(),ldp,context);
|
||||
ldp.append("}").nl();
|
||||
ldp.append(" \\renewcommand\\@evenfoot{");
|
||||
if (style.getFooterLeft()!=null) {
|
||||
traverseHeaderFooter((Element)style.getFooterLeft(),ldp,context);
|
||||
}
|
||||
else if (style.getFooter()!=null) {
|
||||
ldp.append("\\@oddfoot");
|
||||
}
|
||||
ldp.append("}").nl();
|
||||
}
|
||||
|
||||
// Sectionmark and subsectionmark
|
||||
if (sChapterField1!=null) {
|
||||
ldp.append(" \\def\\sectionmark##1{\\markboth{");
|
||||
if ("name".equals(sChapterField1)) { ldp.append("##1"); }
|
||||
else if ("number".equals(sChapterField1) || "plain-number".equals(sChapterField1)) {
|
||||
ldp.append("\\thesection");
|
||||
}
|
||||
else { ldp.append("\\thesection\\ ##1"); }
|
||||
ldp.append("}{}}").nl();
|
||||
}
|
||||
if (sChapterField2!=null) {
|
||||
if (sChapterField1==null) {
|
||||
ldp.append(" \\def\\sectionmark##1{\\markboth{}{}}").nl();
|
||||
}
|
||||
ldp.append(" \\def\\subsectionmark##1{\\markright{");
|
||||
if ("name".equals(sChapterField2)) { ldp.append("##1"); }
|
||||
else if ("number".equals(sChapterField2) || "plain-number".equals(sChapterField1)) {
|
||||
ldp.append("\\thesubsection");
|
||||
}
|
||||
else { ldp.append("\\thesubsection\\ ##1"); }
|
||||
ldp.append("}{}}").nl();
|
||||
}
|
||||
// Page number (this is the only part of the page master used in each page style)
|
||||
if (pageLayout!=null) {
|
||||
String sNumFormat = pageLayout.getProperty(XMLString.STYLE_NUM_FORMAT);
|
||||
if (sNumFormat!=null) {
|
||||
ldp.append(" \\renewcommand\\thepage{")
|
||||
.append(ListStyleConverter.numFormat(sNumFormat))
|
||||
.append("{page}}").nl();
|
||||
}
|
||||
String sPageNumber = pageLayout.getProperty(XMLString.STYLE_FIRST_PAGE_NUMBER);
|
||||
if (sPageNumber!=null && !sPageNumber.equals("continue")) {
|
||||
ldp.append(" \\setcounter{page}{")
|
||||
.append(Integer.toString(Misc.getPosInteger(sPageNumber,0)))
|
||||
.append("}").nl();
|
||||
}
|
||||
}
|
||||
|
||||
ldp.append("}").nl();
|
||||
}
|
||||
}
|
||||
if (!config.useFancyhdr()) {
|
||||
ldp.append("\\makeatother").nl();
|
||||
}
|
||||
}
|
||||
|
||||
// Get alignment of first paragraph in node
|
||||
private String getParAlignment(Node node) {
|
||||
String sAlign = "L";
|
||||
if (node!=null) {
|
||||
Element par = Misc.getChildByTagName(node,XMLString.TEXT_P);
|
||||
if (par!=null) {
|
||||
String sStyleName = Misc.getAttribute(par,XMLString.TEXT_STYLE_NAME);
|
||||
StyleWithProperties style = ofr.getParStyle(sStyleName);
|
||||
if (style!=null) {
|
||||
String s = style.getProperty(XMLString.FO_TEXT_ALIGN);
|
||||
if ("center".equals(s)) { sAlign = "C"; }
|
||||
else if ("end".equals(s)) { sAlign = "R"; }
|
||||
}
|
||||
}
|
||||
}
|
||||
return sAlign;
|
||||
}
|
||||
|
||||
// Get border width from header/footer style
|
||||
private String getBorderWidth(PageLayout style, boolean bHeader) {
|
||||
if (style==null) { return "0pt"; }
|
||||
String sBorder;
|
||||
if (bHeader) {
|
||||
sBorder = style.getHeaderProperty(XMLString.FO_BORDER_BOTTOM);
|
||||
if (sBorder==null) {
|
||||
sBorder = style.getHeaderProperty(XMLString.FO_BORDER);
|
||||
}
|
||||
}
|
||||
else {
|
||||
sBorder = style.getFooterProperty(XMLString.FO_BORDER_TOP);
|
||||
if (sBorder==null) {
|
||||
sBorder = style.getFooterProperty(XMLString.FO_BORDER);
|
||||
}
|
||||
}
|
||||
if (sBorder!=null && !sBorder.equals("none")) {
|
||||
return sBorder.substring(0,sBorder.indexOf(' '));
|
||||
}
|
||||
else {
|
||||
return "0pt";
|
||||
}
|
||||
}
|
||||
|
||||
private void traverseHeaderFooter(Element node, LaTeXDocumentPortion ldp, Context context) {
|
||||
if (node==null) { return; }
|
||||
// get first paragraph; all other content is ignored
|
||||
Element par = Misc.getChildByTagName(node,XMLString.TEXT_P);
|
||||
if (par==null) { return; }
|
||||
|
||||
String sStyleName = par.getAttribute(XMLString.TEXT_STYLE_NAME);
|
||||
BeforeAfter ba = new BeforeAfter();
|
||||
// Temp solution: Ignore hard formatting in header/footer (name clash problem)
|
||||
// only in package format. TODO: Find a better solution!
|
||||
StyleWithProperties style = ofr.getParStyle(sStyleName);
|
||||
if (style!=null && (!ofr.isPackageFormat() || !style.isAutomatic())) {
|
||||
palette.getCharSc().applyHardCharFormatting(style,ba);
|
||||
}
|
||||
|
||||
if (par.hasChildNodes()) {
|
||||
ldp.append(ba.getBefore());
|
||||
palette.getInlineCv().traverseInlineText(par,ldp,context);
|
||||
ldp.append(ba.getAfter());
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
// TODO: Reenable several geometries per document??
|
||||
private void convertPageMasterGeometry(LaTeXDocumentPortion pack, LaTeXDocumentPortion ldp) {
|
||||
if (config.pageFormatting()!=LaTeXConfig.CONVERT_ALL) { return; }
|
||||
if (mainPageLayout==null) { return; }
|
||||
|
||||
// Set global document options
|
||||
if ("mirrored".equals(mainPageLayout.getPageUsage())) {
|
||||
palette.addGlobalOption("twoside");
|
||||
}
|
||||
if (isTwocolumn()) {
|
||||
palette.addGlobalOption("twocolumn");
|
||||
}
|
||||
|
||||
// Collect all page geometry
|
||||
// 1. Page size
|
||||
String sPaperHeight = mainPageLayout.getAbsoluteProperty(XMLString.FO_PAGE_HEIGHT);
|
||||
String sPaperWidth = mainPageLayout.getAbsoluteProperty(XMLString.FO_PAGE_WIDTH);
|
||||
// 2. Margins
|
||||
String sMarginTop = mainPageLayout.getAbsoluteProperty(XMLString.FO_MARGIN_TOP);
|
||||
String sMarginBottom = mainPageLayout.getAbsoluteProperty(XMLString.FO_MARGIN_BOTTOM);
|
||||
String sMarginLeft = mainPageLayout.getAbsoluteProperty(XMLString.FO_MARGIN_LEFT);
|
||||
String sMarginRight = mainPageLayout.getAbsoluteProperty(XMLString.FO_MARGIN_RIGHT);
|
||||
// 3. Header+footer dimensions
|
||||
String sHeadHeight = "0cm";
|
||||
String sHeadSep = "0cm";
|
||||
String sFootHeight = "0cm";
|
||||
String sFootSep = "0cm";
|
||||
boolean bIncludeHead = false;
|
||||
boolean bIncludeFoot = false;
|
||||
// Look through all applied page layouts and use largest heights
|
||||
Enumeration masters = ofr.getMasterPages().getStylesEnumeration();
|
||||
while (masters.hasMoreElements()) {
|
||||
MasterPage master = (MasterPage) masters.nextElement();
|
||||
if (styleNames.containsName(getDisplayName(master.getName()))) {
|
||||
PageLayout layout = ofr.getPageLayout(master.getPageLayoutName());
|
||||
if (layout!=null) {
|
||||
if (layout.hasHeaderStyle()) {
|
||||
String sThisHeadHeight = layout.getHeaderProperty(XMLString.FO_MIN_HEIGHT);
|
||||
if (sThisHeadHeight!=null && Misc.isLessThan(sHeadHeight,sThisHeadHeight)) {
|
||||
sHeadHeight = sThisHeadHeight;
|
||||
}
|
||||
String sThisHeadSep = layout.getHeaderProperty(XMLString.FO_MARGIN_BOTTOM);
|
||||
if (sThisHeadSep!=null && Misc.isLessThan(sHeadSep,sThisHeadSep)) {
|
||||
sHeadSep = sThisHeadSep;
|
||||
}
|
||||
bIncludeHead = true;
|
||||
}
|
||||
if (layout.hasFooterStyle()) {
|
||||
String sThisFootHeight = layout.getFooterProperty(XMLString.FO_MIN_HEIGHT);
|
||||
if (sThisFootHeight!=null && Misc.isLessThan(sFootHeight,sThisFootHeight)) {
|
||||
sFootHeight = sThisFootHeight;
|
||||
}
|
||||
String sThisFootSep = layout.getFooterProperty(XMLString.FO_MARGIN_TOP);
|
||||
if (sThisFootSep!=null && Misc.isLessThan(sFootSep,sThisFootSep)) {
|
||||
sFootSep = sThisFootSep;
|
||||
}
|
||||
bIncludeFoot = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
// Define 12pt as minimum height (the source may specify 0pt..)
|
||||
if (bIncludeHead && Misc.isLessThan(sHeadHeight,"12pt")) {
|
||||
sHeadHeight = "12pt";
|
||||
}
|
||||
if (bIncludeFoot && Misc.isLessThan(sFootHeight,"12pt")) {
|
||||
sFootHeight = "12pt";
|
||||
}
|
||||
|
||||
String sFootSkip = Misc.add(sFootHeight,sFootSep);
|
||||
|
||||
if (config.useGeometry()) {
|
||||
// Set up options for geometry.sty
|
||||
CSVList props = new CSVList(",");
|
||||
if (!standardPaperSize(sPaperWidth,sPaperHeight)) {
|
||||
props.addValue("paperwidth="+sPaperWidth);
|
||||
props.addValue("paperheight="+sPaperHeight);
|
||||
}
|
||||
props.addValue("top="+sMarginTop);
|
||||
props.addValue("bottom="+sMarginBottom);
|
||||
props.addValue("left="+sMarginLeft);
|
||||
props.addValue("right="+sMarginRight);
|
||||
if (bIncludeHead) {
|
||||
props.addValue("includehead");
|
||||
props.addValue("head="+sHeadHeight);
|
||||
props.addValue("headsep="+sHeadSep);
|
||||
}
|
||||
else {
|
||||
props.addValue("nohead");
|
||||
}
|
||||
if (bIncludeFoot) {
|
||||
props.addValue("includefoot");
|
||||
props.addValue("foot="+sFootHeight);
|
||||
props.addValue("footskip="+sFootSkip);
|
||||
}
|
||||
else {
|
||||
props.addValue("nofoot");
|
||||
}
|
||||
// Use the package
|
||||
pack.append("\\usepackage[").append(props.toString()).append("]{geometry}").nl();
|
||||
|
||||
}
|
||||
else {
|
||||
// Calculate text height and text width
|
||||
String sTextHeight = Misc.sub(sPaperHeight,sMarginTop);
|
||||
sTextHeight = Misc.sub(sTextHeight,sHeadHeight);
|
||||
sTextHeight = Misc.sub(sTextHeight,sHeadSep);
|
||||
sTextHeight = Misc.sub(sTextHeight,sFootSkip);
|
||||
sTextHeight = Misc.sub(sTextHeight,sMarginBottom);
|
||||
String sTextWidth = Misc.sub(sPaperWidth,sMarginLeft);
|
||||
sTextWidth = Misc.sub(sTextWidth,sMarginRight);
|
||||
|
||||
ldp.append("% Page layout (geometry)").nl();
|
||||
|
||||
// Page dimensions
|
||||
if (!standardPaperSize(sPaperWidth,sPaperHeight)) {
|
||||
ldp.append("\\setlength\\paperwidth{").append(sPaperWidth).append("}").nl()
|
||||
.append("\\setlength\\paperheight{").append(sPaperHeight).append("}").nl();
|
||||
}
|
||||
|
||||
// PDF page dimensions, only if hyperref.sty is not loaded
|
||||
if (config.getBackend()==LaTeXConfig.PDFTEX && !config.useHyperref()) {
|
||||
ldp.append("\\setlength\\pdfpagewidth{").append(sPaperWidth).append("}").nl()
|
||||
.append("\\setlength\\pdfpageheight{").append(sPaperHeight).append("}").nl();
|
||||
}
|
||||
|
||||
// Page starts in upper left corner of paper!!
|
||||
ldp.append("\\setlength\\voffset{-1in}").nl()
|
||||
.append("\\setlength\\hoffset{-1in}").nl();
|
||||
|
||||
// Margins
|
||||
ldp.append("\\setlength\\topmargin{").append(sMarginTop).append("}").nl()
|
||||
.append("\\setlength\\oddsidemargin{").append(sMarginLeft).append("}").nl();
|
||||
// Left margin for even (left) pages; only for mirrored page master
|
||||
if ("mirrored".equals(mainPageLayout.getPageUsage())) {
|
||||
ldp.append("\\setlength\\evensidemargin{").append(sMarginRight).append("}").nl();
|
||||
}
|
||||
|
||||
// Text size (sets bottom and right margins indirectly)
|
||||
ldp.append("\\setlength\\textheight{").append(sTextHeight).append("}").nl();
|
||||
ldp.append("\\setlength\\textwidth{").append(sTextWidth).append("}").nl();
|
||||
|
||||
// Header and footer
|
||||
ldp.append("\\setlength\\footskip{").append(sFootSkip).append("}").nl();
|
||||
ldp.append("\\setlength\\headheight{").append(sHeadHeight).append("}").nl();
|
||||
ldp.append("\\setlength\\headsep{").append(sHeadSep).append("}").nl();
|
||||
}
|
||||
|
||||
// Footnote rule
|
||||
// TODO: Support alignment.
|
||||
String sAdjustment = mainPageLayout.getFootnoteProperty(XMLString.STYLE_ADJUSTMENT);
|
||||
String sBefore = mainPageLayout.getFootnoteProperty(XMLString.STYLE_DISTANCE_BEFORE_SEP);
|
||||
if (sBefore==null) { sBefore = "1mm"; }
|
||||
String sAfter = mainPageLayout.getFootnoteProperty(XMLString.STYLE_DISTANCE_AFTER_SEP);
|
||||
if (sAfter==null) { sAfter = "1mm"; }
|
||||
String sHeight = mainPageLayout.getFootnoteProperty(XMLString.STYLE_WIDTH);
|
||||
if (sHeight==null) { sHeight = "0.2mm"; }
|
||||
String sWidth = mainPageLayout.getFootnoteProperty(XMLString.STYLE_REL_WIDTH);
|
||||
if (sWidth==null) { sWidth = "25%"; }
|
||||
sWidth=Float.toString(Misc.getFloat(sWidth.substring(0,sWidth.length()-1),1)/100);
|
||||
BeforeAfter baColor = new BeforeAfter();
|
||||
String sColor = mainPageLayout.getFootnoteProperty(XMLString.STYLE_COLOR);
|
||||
palette.getColorCv().applyColor(sColor,false,baColor,new Context());
|
||||
|
||||
String sSkipFootins = Misc.add(sBefore,sHeight);
|
||||
|
||||
ldp.append("% Footnote rule").nl()
|
||||
.append("\\setlength{\\skip\\footins}{").append(sSkipFootins).append("}").nl()
|
||||
.append("\\renewcommand\\footnoterule{\\vspace*{-").append(sHeight)
|
||||
.append("}");
|
||||
if ("right".equals(sAdjustment)) {
|
||||
ldp.append("\\setlength\\leftskip{0pt plus 1fil}\\setlength\\rightskip{0pt}");
|
||||
}
|
||||
else if ("center".equals(sAdjustment)) {
|
||||
ldp.append("\\setlength\\leftskip{0pt plus 1fil}\\setlength\\rightskip{0pt plus 1fil}");
|
||||
}
|
||||
else { // default left
|
||||
ldp.append("\\setlength\\leftskip{0pt}\\setlength\\rightskip{0pt plus 1fil}");
|
||||
}
|
||||
ldp.append("\\noindent")
|
||||
.append(baColor.getBefore()).append("\\rule{").append(sWidth)
|
||||
.append("\\columnwidth}{").append(sHeight).append("}")
|
||||
.append(baColor.getAfter())
|
||||
.append("\\vspace*{").append(sAfter).append("}}").nl();
|
||||
}
|
||||
|
||||
private boolean standardPaperSize(String sWidth, String sHeight) {
|
||||
if (standardPaperSize1(sWidth,sHeight)) {
|
||||
return true;
|
||||
}
|
||||
else if (standardPaperSize1(sHeight,sWidth)) {
|
||||
palette.addGlobalOption("landscape");
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
private boolean standardPaperSize1(String sWidth, String sHeight) {
|
||||
// The list of known paper sizes in LaTeX's standard classes is rather short
|
||||
if (compare(sWidth, "210mm", "0.5mm") && compare(sHeight, "297mm", "0.5mm")) {
|
||||
palette.addGlobalOption("a4paper");
|
||||
return true;
|
||||
}
|
||||
else if (compare(sWidth, "148mm", "0.5mm") && compare(sHeight, "210mm", "0.5mm")) {
|
||||
palette.addGlobalOption("a5paper");
|
||||
return true;
|
||||
}
|
||||
else if (compare(sWidth, "176mm", "0.5mm") && compare(sHeight, "250mm", "0.5mm")) {
|
||||
palette.addGlobalOption("b5paper");
|
||||
return true;
|
||||
}
|
||||
else if (compare(sWidth, "8.5in", "0.02in") && compare(sHeight, "11in", "0.02in")) {
|
||||
palette.addGlobalOption("letterpaper");
|
||||
return true;
|
||||
}
|
||||
else if (compare(sWidth, "8.5in", "0.02in") && compare(sHeight, "14in", "0.02in")) {
|
||||
palette.addGlobalOption("legalpaper");
|
||||
return true;
|
||||
}
|
||||
else if (compare(sWidth, "7.25in", "0.02in") && compare(sHeight, "10.5in", "0.02in")) {
|
||||
palette.addGlobalOption("executivepaper");
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
private boolean compare(String sLength1, String sLength2, String sTolerance) {
|
||||
return Misc.isLessThan(Misc.abs(Misc.sub(sLength1,sLength2)),sTolerance);
|
||||
}
|
||||
|
||||
/* Helper: Get display name, or original name if it doesn't exist */
|
||||
private String getDisplayName(String sName) {
|
||||
String sDisplayName = ofr.getMasterPages().getDisplayName(sName);
|
||||
return sDisplayName!=null ? sDisplayName : sName;
|
||||
}
|
||||
|
||||
|
||||
|
||||
}
|
546
source/java/writer2latex/latex/ParConverter.java
Normal file
546
source/java/writer2latex/latex/ParConverter.java
Normal file
|
@ -0,0 +1,546 @@
|
|||
/************************************************************************
|
||||
*
|
||||
* ParConverter.java
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License version 2.1, as published by the Free Software Foundation.
|
||||
*
|
||||
* This library 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
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston,
|
||||
* MA 02111-1307 USA
|
||||
*
|
||||
* Copyright: 2002-2008 by Henrik Just
|
||||
*
|
||||
* All Rights Reserved.
|
||||
*
|
||||
* Version 1.0 (2008-11-23)
|
||||
*
|
||||
*/
|
||||
|
||||
package writer2latex.latex;
|
||||
|
||||
//import java.util.Hashtable;
|
||||
|
||||
import org.w3c.dom.Element;
|
||||
//import org.w3c.dom.Node;
|
||||
//import org.w3c.dom.NodeList;
|
||||
|
||||
import writer2latex.util.*;
|
||||
import writer2latex.office.*;
|
||||
import writer2latex.latex.util.BeforeAfter;
|
||||
import writer2latex.latex.util.Context;
|
||||
//import writer2latex.latex.util.HeadingMap;
|
||||
import writer2latex.latex.util.StyleMap;
|
||||
|
||||
/* <p>This class converts OpenDocument paragraphs (<code>text:p</code>) and
|
||||
* paragraph styles/formatting into LaTeX</p>
|
||||
* <p>Export of formatting depends on the option "formatting":</p>
|
||||
* <ul>
|
||||
* <li><code>ignore_all</code>
|
||||
* <li><code>ignore_most</code>
|
||||
* <li><code>convert_basic</code>
|
||||
* <li><code>convert_most</code>
|
||||
* <li><code>convert_all</code>
|
||||
* </ul>
|
||||
* <p>TODO: Captions and {foot|end}notes should also use this class
|
||||
*/
|
||||
public class ParConverter extends StyleConverter {
|
||||
|
||||
private boolean bNeedArrayBslash = false;
|
||||
|
||||
/** <p>Constructs a new <code>ParConverter</code>.</p>
|
||||
*/
|
||||
public ParConverter(OfficeReader ofr, LaTeXConfig config,
|
||||
ConverterPalette palette) {
|
||||
super(ofr,config,palette);
|
||||
}
|
||||
|
||||
public void appendDeclarations(LaTeXDocumentPortion pack, LaTeXDocumentPortion decl) {
|
||||
if (bNeedArrayBslash) {
|
||||
// centering and raggedright redefines \\, fix this
|
||||
// Note: aviods nameclash with tabularx (arraybackslash)
|
||||
// TODO: Should perhaps choose to load tabularx instead?
|
||||
decl.append("\\makeatletter").nl()
|
||||
.append("\\newcommand\\arraybslash{\\let\\\\\\@arraycr}").nl()
|
||||
.append("\\makeatother").nl();
|
||||
}
|
||||
|
||||
|
||||
if (config.formatting()>=LaTeXConfig.CONVERT_MOST) {
|
||||
// We typeset with \raggedbottom since OOo doesn't use rubber lengths
|
||||
// TODO: Maybe turn vertical spacing from OOo into rubber lengths?
|
||||
decl.append("\\raggedbottom").nl();
|
||||
}
|
||||
|
||||
if (config.formatting()>=LaTeXConfig.CONVERT_MOST) {
|
||||
decl.append("% Paragraph styles").nl();
|
||||
// First default paragraph style
|
||||
palette.getCharSc().applyDefaultFont(ofr.getDefaultParStyle(),decl);
|
||||
super.appendDeclarations(pack,decl);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* <p> Process a text:p tag</p>
|
||||
* @param node The text:h element node containing the heading
|
||||
* @param ldp The <code>LaTeXDocumentPortion</code> to add LaTeX code to
|
||||
* @param oc The current context
|
||||
* @param bLastInBlock If this is true, the paragraph is the
|
||||
* last one in a block, and we need no trailing blank line (eg. right before
|
||||
* \end{enumerate}).
|
||||
*/
|
||||
public void handleParagraph(Element node, LaTeXDocumentPortion ldp, Context oc, boolean bLastInBlock) {
|
||||
if (palette.getMathmlCv().handleDisplayEquation(node,ldp)) { return; }
|
||||
|
||||
// Get the style name for this paragraph
|
||||
String sStyleName = node.getAttribute(XMLString.TEXT_STYLE_NAME);
|
||||
String sDisplayName = ofr.getParStyles().getDisplayName(sStyleName);
|
||||
|
||||
|
||||
// Check for strict handling of styles
|
||||
if (config.otherStyles()!=LaTeXConfig.ACCEPT && !config.getParStyleMap().contains(sDisplayName)) {
|
||||
if (config.otherStyles()==LaTeXConfig.WARNING) {
|
||||
System.err.println("Warning: A paragraph with style "+sDisplayName+" was ignored");
|
||||
}
|
||||
else if (config.otherStyles()==LaTeXConfig.ERROR) {
|
||||
ldp.append("% Error in source document: A paragraph with style ")
|
||||
.append(palette.getI18n().convert(sDisplayName,false,oc.getLang()))
|
||||
.append(" was ignored").nl();
|
||||
}
|
||||
// Ignore this paragraph:
|
||||
return;
|
||||
}
|
||||
|
||||
// Empty paragraphs are often (mis)used to achieve vertical spacing in WYSIWYG
|
||||
// word processors. Hence we translate an empty paragraph to \bigskip.
|
||||
// This also solves the problem that LaTeX ignores empty paragraphs, Writer doesn't.
|
||||
// In a well-structured document, an empty paragraph is probably a mistake,
|
||||
// hence the configuration can specify that it should be ignored.
|
||||
// Note: Don't use \bigskip in tables (this can lead to strange results)
|
||||
if (OfficeReader.isWhitespaceContent(node)) {
|
||||
// Always add page break; other formatting is ignored
|
||||
BeforeAfter baPage = new BeforeAfter();
|
||||
StyleWithProperties style = ofr.getParStyle(sStyleName);
|
||||
palette.getPageSc().applyPageBreak(style,true,baPage);
|
||||
if (!oc.isInTable()) { ldp.append(baPage.getBefore()); }
|
||||
if (!config.ignoreEmptyParagraphs()) {
|
||||
if (!oc.isInTable()) {
|
||||
ldp.nl().append("\\bigskip").nl();
|
||||
}
|
||||
else {
|
||||
ldp.append("~").nl();
|
||||
}
|
||||
if (!bLastInBlock) { ldp.nl(); }
|
||||
}
|
||||
if (!oc.isInTable()) { ldp.append(baPage.getAfter()); }
|
||||
return;
|
||||
}
|
||||
|
||||
Context ic = (Context) oc.clone();
|
||||
|
||||
// Always push the font used
|
||||
palette.getI18n().pushSpecialTable(palette.getCharSc().getFontName(ofr.getParStyle(sStyleName)));
|
||||
|
||||
// Apply the style
|
||||
BeforeAfter ba = new BeforeAfter();
|
||||
if (oc.isInTable()) {
|
||||
applyCellParStyle(sStyleName,ba,ic,OfficeReader.getCharacterCount(node)==0,bLastInBlock);
|
||||
}
|
||||
else {
|
||||
applyParStyle(sStyleName,ba,ic,OfficeReader.getCharacterCount(node)==0);
|
||||
}
|
||||
|
||||
// Do conversion
|
||||
ldp.append(ba.getBefore());
|
||||
palette.getInlineCv().traverseInlineText(node,ldp,ic);
|
||||
ldp.append(ba.getAfter());
|
||||
// Add a blank line except within verbatim and last in a block:
|
||||
if (!bLastInBlock && !ic.isVerbatim() && !ic.isInSimpleTable()) { ldp.nl(); }
|
||||
|
||||
// Flush any pending index marks, reference marks and floating frames
|
||||
palette.getFieldCv().flushReferenceMarks(ldp,oc);
|
||||
palette.getIndexCv().flushIndexMarks(ldp,oc);
|
||||
palette.getDrawCv().flushFloatingFrames(ldp,oc);
|
||||
|
||||
// pop the font name
|
||||
palette.getI18n().popSpecialTable();
|
||||
}
|
||||
|
||||
private void applyCellParStyle(String sName, BeforeAfter ba, Context context, boolean bNoTextPar, boolean bLastInBlock) {
|
||||
// Paragraph formatting for paragraphs within table cells
|
||||
// We always use simple par styles here
|
||||
|
||||
// Add newline if *between* paragraphs
|
||||
if (!bLastInBlock) { ba.add("","\n"); }
|
||||
|
||||
if (context.isInSimpleTable()) {
|
||||
if (config.formatting()!=LaTeXConfig.IGNORE_ALL) {
|
||||
// only character formatting!
|
||||
StyleWithProperties style = ofr.getParStyle(sName);
|
||||
if (style!=null) {
|
||||
palette.getI18n().applyLanguage(style,true,true,ba);
|
||||
palette.getCharSc().applyFont(style,true,true,ba,context);
|
||||
if (ba.getBefore().length()>0) { ba.add(" ",""); }
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (bNoTextPar && (config.formatting()==LaTeXConfig.CONVERT_BASIC || config.formatting()==LaTeXConfig.IGNORE_MOST) ) {
|
||||
// only alignment!
|
||||
StyleWithProperties style = ofr.getParStyle(sName);
|
||||
if (style!=null) {
|
||||
// Apply hard formatting attributes
|
||||
// Note: Left justified text is exported as full justified text!
|
||||
palette.getPageSc().applyPageBreak(style,false,ba);
|
||||
String sTextAlign = style.getProperty(XMLString.FO_TEXT_ALIGN,true);
|
||||
if (bLastInBlock && context.isInLastTableColumn()) { // no grouping needed, but need to fix problem with \\
|
||||
if ("center".equals(sTextAlign)) { ba.add("\\centering\\arraybslash ",""); }
|
||||
else if ("end".equals(sTextAlign)) { ba.add("\\raggedleft\\arraybslash ",""); }
|
||||
bNeedArrayBslash = true;
|
||||
}
|
||||
else if (bLastInBlock) { // no grouping needed
|
||||
if ("center".equals(sTextAlign)) { ba.add("\\centering ",""); }
|
||||
else if ("end".equals(sTextAlign)) { ba.add("\\raggedleft ",""); }
|
||||
}
|
||||
else {
|
||||
if ("center".equals(sTextAlign)) { ba.add("{\\centering ","\\par}"); }
|
||||
else if ("end".equals(sTextAlign)) { ba.add("{\\raggedleft ","\\par}"); }
|
||||
}
|
||||
}
|
||||
}
|
||||
else {
|
||||
// Export character formatting + alignment only
|
||||
BeforeAfter baText = new BeforeAfter();
|
||||
|
||||
// Apply hard formatting attributes
|
||||
// Note: Left justified text is exported as full justified text!
|
||||
StyleWithProperties style = ofr.getParStyle(sName);
|
||||
if (style!=null) {
|
||||
String sTextAlign = style.getProperty(XMLString.FO_TEXT_ALIGN,true);
|
||||
if (bLastInBlock && context.isInLastTableColumn()) { // no grouping needed, but need to fix problem with \\
|
||||
if ("center".equals(sTextAlign)) { ba.add("\\centering\\arraybslash ",""); }
|
||||
else if ("end".equals(sTextAlign)) { ba.add("\\raggedleft\\arraybslash ",""); }
|
||||
bNeedArrayBslash = true;
|
||||
}
|
||||
else if (bLastInBlock) { // no \par needed
|
||||
if ("center".equals(sTextAlign)) { ba.add("\\centering ",""); }
|
||||
else if ("end".equals(sTextAlign)) { ba.add("\\raggedleft ",""); }
|
||||
}
|
||||
else {
|
||||
if ("center".equals(sTextAlign)) { ba.add("\\centering ","\\par"); }
|
||||
else if ("end".equals(sTextAlign)) { ba.add("\\raggedleft ","\\par"); }
|
||||
}
|
||||
palette.getI18n().applyLanguage(style,true,true,baText);
|
||||
palette.getCharSc().applyFont(style,true,true,baText,context);
|
||||
}
|
||||
|
||||
// Assemble the bits. If there is any hard character formatting
|
||||
// or alignment we must group the contents.
|
||||
if (!baText.isEmpty() && !bLastInBlock) { ba.add("{","}"); }
|
||||
ba.add(baText.getBefore(),baText.getAfter());
|
||||
if (baText.getBefore().length()>0) { ba.add(" ",""); }
|
||||
}
|
||||
|
||||
// Update context
|
||||
StyleWithProperties style = ofr.getParStyle(sName);
|
||||
if (style==null) { return; }
|
||||
context.updateFormattingFromStyle(style);
|
||||
context.setVerbatim(styleMap.getVerbatim(sName));
|
||||
}
|
||||
|
||||
|
||||
/** <p>Use a paragraph style in LaTeX.</p>
|
||||
* @param <code>sName</code> the name of the text style
|
||||
* @param <code>ba</code> a <code>BeforeAfter</code> to put code into
|
||||
* @param <code>context</code> the current context. This method will use and update the formatting context
|
||||
* @param <code>bNoTextPar</code> true if this paragraph has no text content (hence character formatting is not needed)
|
||||
*/
|
||||
private void applyParStyle(String sName, BeforeAfter ba, Context context, boolean bNoTextPar) {
|
||||
applyParStyle(sName,ba,context,bNoTextPar,true);
|
||||
}
|
||||
|
||||
private void applyParStyle(String sName, BeforeAfter ba, Context context, boolean bNoTextPar, boolean bBreakInside) {
|
||||
// No style specified?
|
||||
if (sName==null) { return; }
|
||||
|
||||
if (context.isInSimpleTable()) {
|
||||
if (config.formatting()!=LaTeXConfig.IGNORE_ALL) {
|
||||
// only character formatting!
|
||||
StyleWithProperties style = ofr.getParStyle(sName);
|
||||
if (style!=null) {
|
||||
palette.getI18n().applyLanguage(style,true,true,ba);
|
||||
palette.getCharSc().applyFont(style,true,true,ba,context);
|
||||
if (ba.getBefore().length()>0) { ba.add(" ",""); }
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (bNoTextPar && (config.formatting()==LaTeXConfig.CONVERT_BASIC || config.formatting()==LaTeXConfig.IGNORE_MOST) ) {
|
||||
// Always end with a line break
|
||||
ba.add("","\n");
|
||||
// only alignment!
|
||||
StyleWithProperties style = ofr.getParStyle(sName);
|
||||
if (style!=null) {
|
||||
// Apply hard formatting attributes
|
||||
// Note: Left justified text is exported as full justified text!
|
||||
palette.getPageSc().applyPageBreak(style,false,ba);
|
||||
String sTextAlign = style.getProperty(XMLString.FO_TEXT_ALIGN,true);
|
||||
if ("center".equals(sTextAlign)) { ba.add("{\\centering ","\\par}"); }
|
||||
else if ("end".equals(sTextAlign)) { ba.add("{\\raggedleft ","\\par}"); }
|
||||
}
|
||||
}
|
||||
else {
|
||||
// Always end with a line break
|
||||
ba.add("","\n");
|
||||
// Apply the style
|
||||
if (!styleMap.contains(sName)) { createParStyle(sName); }
|
||||
String sBefore = styleMap.getBefore(sName);
|
||||
String sAfter = styleMap.getAfter(sName);
|
||||
ba.add(sBefore,sAfter);
|
||||
// Add line breaks inside?
|
||||
if (bBreakInside && styleMap.getLineBreak(sName)) {
|
||||
if (sBefore.length()>0) { ba.add("\n",""); }
|
||||
if (sAfter.length()>0 && !"}".equals(sAfter)) { ba.add("","\n"); }
|
||||
}
|
||||
}
|
||||
|
||||
// Update context
|
||||
StyleWithProperties style = ofr.getParStyle(sName);
|
||||
if (style==null) { return; }
|
||||
context.updateFormattingFromStyle(style);
|
||||
context.setVerbatim(styleMap.getVerbatim(sName));
|
||||
}
|
||||
|
||||
/** <p>Convert a paragraph style to LaTeX. </p>
|
||||
* <p>A soft style is declared in <code>styleDeclarations</code> as
|
||||
* <code>\newenvironment...</code></p>
|
||||
* <p>A hard style is used by applying LaTeX code directly</p>
|
||||
* @param <code>sName</code> the OOo name of the style
|
||||
*/
|
||||
private void createParStyle(String sName) {
|
||||
// A paragraph style should always be created relative to main context
|
||||
Context context = (Context) palette.getMainContext().clone();
|
||||
// The style may already be declared in the configuration:
|
||||
String sDisplayName = ofr.getParStyles().getDisplayName(sName);
|
||||
StyleMap sm = config.getParStyleMap();
|
||||
if (sm.contains(sDisplayName)) {
|
||||
styleMap.put(sName,sm.getBefore(sDisplayName),sm.getAfter(sDisplayName),
|
||||
sm.getLineBreak(sDisplayName),sm.getVerbatim(sDisplayName));
|
||||
return;
|
||||
}
|
||||
// Does the style exist?
|
||||
StyleWithProperties style = ofr.getParStyle(sName);
|
||||
if (style==null) {
|
||||
styleMap.put(sName,"","");
|
||||
return;
|
||||
}
|
||||
// Convert the style!
|
||||
switch (config.formatting()) {
|
||||
case LaTeXConfig.CONVERT_MOST:
|
||||
if (style.isAutomatic()) {
|
||||
createAutomaticParStyle(style,context);
|
||||
return;
|
||||
}
|
||||
case LaTeXConfig.CONVERT_ALL:
|
||||
createSoftParStyle(style,context);
|
||||
return;
|
||||
case LaTeXConfig.CONVERT_BASIC:
|
||||
case LaTeXConfig.IGNORE_MOST:
|
||||
createSimpleParStyle(style,context);
|
||||
return;
|
||||
case LaTeXConfig.IGNORE_ALL:
|
||||
default:
|
||||
styleMap.put(sName,"","");
|
||||
}
|
||||
}
|
||||
|
||||
private void createAutomaticParStyle(StyleWithProperties style, Context context) {
|
||||
// Hard paragraph formatting from this style should be ignored
|
||||
// (because the user wants to ignore hard paragraph formatting
|
||||
// or there is a style map for the parent.)
|
||||
BeforeAfter ba = new BeforeAfter();
|
||||
BeforeAfter baPar = new BeforeAfter();
|
||||
BeforeAfter baText = new BeforeAfter();
|
||||
|
||||
// Apply paragraph formatting from parent
|
||||
// If parent is verbatim, this is all
|
||||
String sParentName = style.getParentName();
|
||||
if (styleMap.getVerbatim(sParentName)) {
|
||||
styleMap.put(style.getName(),styleMap.getBefore(sParentName),styleMap.getAfter(sParentName),
|
||||
styleMap.getLineBreak(sParentName),styleMap.getVerbatim(sParentName));
|
||||
return;
|
||||
}
|
||||
applyParStyle(sParentName,baPar,context,false,false);
|
||||
|
||||
// Apply hard formatting properties:
|
||||
palette.getPageSc().applyPageBreak(style,false,ba);
|
||||
palette.getI18n().applyLanguage(style,true,false,baText);
|
||||
palette.getCharSc().applyFont(style,true,false,baText,context);
|
||||
|
||||
// Assemble the bits. If there is any hard character formatting
|
||||
// we must group the contents.
|
||||
if (baPar.isEmpty() && !baText.isEmpty()) { ba.add("{","}"); }
|
||||
else { ba.add(baPar.getBefore(),baPar.getAfter()); }
|
||||
ba.add(baText.getBefore(),baText.getAfter());
|
||||
boolean bLineBreak = styleMap.getLineBreak(sParentName);
|
||||
if (!bLineBreak && !baText.isEmpty()) { ba.add(" ",""); }
|
||||
styleMap.put(style.getName(),ba.getBefore(),ba.getAfter(),bLineBreak,false);
|
||||
}
|
||||
|
||||
private void createSimpleParStyle(StyleWithProperties style, Context context) {
|
||||
// Export character formatting + alignment only
|
||||
if (style.isAutomatic() && config.getParStyleMap().contains(ofr.getParStyles().getDisplayName(style.getParentName()))) {
|
||||
createAutomaticParStyle(style,context);
|
||||
return;
|
||||
}
|
||||
|
||||
BeforeAfter ba = new BeforeAfter();
|
||||
BeforeAfter baText = new BeforeAfter();
|
||||
|
||||
// Apply hard formatting attributes
|
||||
// Note: Left justified text is exported as full justified text!
|
||||
palette.getPageSc().applyPageBreak(style,false,ba);
|
||||
String sTextAlign = style.getProperty(XMLString.FO_TEXT_ALIGN,true);
|
||||
if ("center".equals(sTextAlign)) { baText.add("\\centering","\\par"); }
|
||||
else if ("end".equals(sTextAlign)) { baText.add("\\raggedleft","\\par"); }
|
||||
palette.getI18n().applyLanguage(style,true,true,baText);
|
||||
palette.getCharSc().applyFont(style,true,true,baText,context);
|
||||
|
||||
// Assemble the bits. If there is any hard character formatting
|
||||
// or alignment we must group the contents.
|
||||
if (!baText.isEmpty()) { ba.add("{","}"); }
|
||||
ba.add(baText.getBefore(),baText.getAfter());
|
||||
styleMap.put(style.getName(),ba.getBefore(),ba.getAfter());
|
||||
}
|
||||
|
||||
private void createSoftParStyle(StyleWithProperties style, Context context) {
|
||||
// This style should be converted to an enviroment, except if
|
||||
// it's automatic and there is a config style map for the parent
|
||||
if (style.isAutomatic() && config.getParStyleMap().contains(ofr.getParStyles().getDisplayName(style.getParentName()))) {
|
||||
createAutomaticParStyle(style,context);
|
||||
}
|
||||
|
||||
BeforeAfter ba = new BeforeAfter();
|
||||
applyParProperties(style,ba);
|
||||
ba.add("\\writerlistparindent\\writerlistleftskip","");
|
||||
palette.getI18n().applyLanguage(style,true,true,ba);
|
||||
ba.add("\\leavevmode","");
|
||||
palette.getCharSc().applyNormalFont(ba);
|
||||
palette.getCharSc().applyFont(style,true,true,ba,context);
|
||||
ba.add("\\writerlistlabel","");
|
||||
ba.add("\\ignorespaces","");
|
||||
// Declare the paragraph style (\newenvironment)
|
||||
String sTeXName = "style" + styleNames.getExportName(style.getDisplayName());
|
||||
styleMap.put(style.getName(),"\\begin{"+sTeXName+"}","\\end{"+sTeXName+"}");
|
||||
declarations.append("\\newenvironment{").append(sTeXName)
|
||||
.append("}{").append(ba.getBefore()).append("}{")
|
||||
.append(ba.getAfter()).append("}").nl();
|
||||
}
|
||||
|
||||
// Remaining methods are private helpers
|
||||
|
||||
/** <p>Apply line spacing from a style.</p>
|
||||
* @param <code>style</code> the paragraph style to use
|
||||
* @param <code>ba</code> a <code>BeforeAfter</code> to put code into
|
||||
*/
|
||||
private void applyLineSpacing(StyleWithProperties style, BeforeAfter ba) {
|
||||
if (style==null) { return; }
|
||||
String sLineHeight = style.getProperty(XMLString.FO_LINE_HEIGHT);
|
||||
if (sLineHeight==null || !sLineHeight.endsWith("%")) { return; }
|
||||
float fPercent=Misc.getFloat(sLineHeight.substring(0,sLineHeight.length()-1),100);
|
||||
// Do not allow less that 120% (LaTeX default)
|
||||
if (fPercent<120) { fPercent = 120; }
|
||||
ba.add("\\renewcommand\\baselinestretch{"+fPercent/120+"}","");
|
||||
}
|
||||
|
||||
/** <p>Helper: Create a horizontal border. Currently unused</p>
|
||||
*/
|
||||
/*private String createBorder(String sLeft, String sRight, String sTop,
|
||||
String sHeight, String sColor) {
|
||||
BeforeAfter baColor = new BeforeAfter();
|
||||
palette.getColorCv().applyColor(sColor,false,baColor, new Context());
|
||||
return "{\\setlength\\parindent{0pt}\\setlength\\leftskip{" + sLeft + "}"
|
||||
+ "\\setlength\\baselineskip{0pt}\\setlength\\parskip{" + sHeight + "}"
|
||||
+ baColor.getBefore()
|
||||
+ "\\rule{\\textwidth-" + sLeft + "-" + sRight + "}{" + sHeight + "}"
|
||||
+ baColor.getAfter()
|
||||
+ "\\par}";
|
||||
}*/
|
||||
|
||||
/** <p>Apply margin+alignment properties from a style.</p>
|
||||
* @param <code>style</code> the paragraph style to use
|
||||
* @param <code>ba</code> a <code>BeforeAfter</code> to put code into
|
||||
*/
|
||||
private void applyMargins(StyleWithProperties style, BeforeAfter ba) {
|
||||
// Read padding/margin/indentation properties:
|
||||
//String sPaddingTop = style.getAbsoluteLength(XMLString.FO_PADDING_TOP);
|
||||
//String sPaddingBottom = style.getAbsoluteLength(XMLString.FO_PADDING_BOTTOM);
|
||||
//String sPaddingLeft = style.getAbsoluteLength(XMLString.FO_PADDING_LEFT);
|
||||
//String sPaddingRight = style.getAbsoluteLength(XMLString.FO_PADDING_RIGHT);
|
||||
String sMarginTop = style.getAbsoluteLength(XMLString.FO_MARGIN_TOP);
|
||||
String sMarginBottom = style.getAbsoluteLength(XMLString.FO_MARGIN_BOTTOM);
|
||||
String sMarginLeft = style.getAbsoluteLength(XMLString.FO_MARGIN_LEFT);
|
||||
String sMarginRight = style.getAbsoluteLength(XMLString.FO_MARGIN_RIGHT);
|
||||
String sTextIndent;
|
||||
if ("true".equals(style.getProperty(XMLString.STYLE_AUTO_TEXT_INDENT))) {
|
||||
sTextIndent = "2em";
|
||||
}
|
||||
else {
|
||||
sTextIndent = style.getAbsoluteLength(XMLString.FO_TEXT_INDENT);
|
||||
}
|
||||
// Read alignment properties:
|
||||
boolean bRaggedLeft = false; // add 1fil to \leftskip
|
||||
boolean bRaggedRight = false; // add 1fil to \rightskip
|
||||
boolean bParFill = false; // add 1fil to \parfillskip
|
||||
String sTextAlign = style.getProperty(XMLString.FO_TEXT_ALIGN);
|
||||
if ("center".equals(sTextAlign)) {
|
||||
bRaggedLeft = true; bRaggedRight = true; // centered paragraph
|
||||
}
|
||||
else if ("start".equals(sTextAlign)) {
|
||||
bRaggedRight = true; bParFill = true; // left aligned paragraph
|
||||
}
|
||||
else if ("end".equals(sTextAlign)) {
|
||||
bRaggedLeft = true; // right aligned paragraph
|
||||
}
|
||||
else if (!"justify".equals(style.getProperty(XMLString.FO_TEXT_ALIGN_LAST))) {
|
||||
bParFill = true; // justified paragraph with ragged last line
|
||||
}
|
||||
// Create formatting:
|
||||
String sRubberMarginTop = Misc.multiply("10%",sMarginTop);
|
||||
if (Misc.length2px(sRubberMarginTop).equals("0")) { sRubberMarginTop="1pt"; }
|
||||
String sRubberMarginBottom = Misc.multiply("10%",sMarginBottom);
|
||||
if (Misc.length2px(sRubberMarginBottom).equals("0")) { sRubberMarginBottom="1pt"; }
|
||||
ba.add("\\setlength\\leftskip{"+sMarginLeft+(bRaggedLeft?" plus 1fil":"")+"}","");
|
||||
ba.add("\\setlength\\rightskip{"+sMarginRight+(bRaggedRight?" plus 1fil":"")+"}","");
|
||||
ba.add("\\setlength\\parindent{"+sTextIndent+"}","");
|
||||
ba.add("\\setlength\\parfillskip{"+(bParFill?"0pt plus 1fil":"0pt")+"}","");
|
||||
ba.add("\\setlength\\parskip{"+sMarginTop+" plus "+sRubberMarginTop+"}",
|
||||
"\\unskip\\vspace{"+sMarginBottom+" plus "+sRubberMarginBottom+"}");
|
||||
}
|
||||
|
||||
public void applyAlignment(StyleWithProperties style, boolean bIsSimple, boolean bInherit, BeforeAfter ba) {
|
||||
if (bIsSimple || style==null) { return; }
|
||||
String sTextAlign = style.getProperty(XMLString.FO_TEXT_ALIGN,bInherit);
|
||||
if ("center".equals(sTextAlign)) { ba.add("\\centering",""); }
|
||||
else if ("start".equals(sTextAlign)) { ba.add("\\raggedright",""); }
|
||||
else if ("end".equals(sTextAlign)) { ba.add("\\raggedleft",""); }
|
||||
}
|
||||
|
||||
|
||||
/** <p>Apply all paragraph properties.</p>
|
||||
* @param <code>style</code> the paragraph style to use
|
||||
* @param <code>ba</code> a <code>BeforeAfter</code> to put code into
|
||||
*/
|
||||
private void applyParProperties(StyleWithProperties style, BeforeAfter ba) {
|
||||
palette.getPageSc().applyPageBreak(style,true,ba);
|
||||
ba.add("","\\par");
|
||||
applyLineSpacing(style,ba);
|
||||
applyMargins(style,ba);
|
||||
}
|
||||
|
||||
}
|
135
source/java/writer2latex/latex/SectionConverter.java
Normal file
135
source/java/writer2latex/latex/SectionConverter.java
Normal file
|
@ -0,0 +1,135 @@
|
|||
/************************************************************************
|
||||
*
|
||||
* SectionConverter.java
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License version 2.1, as published by the Free Software Foundation.
|
||||
*
|
||||
* This library 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
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston,
|
||||
* MA 02111-1307 USA
|
||||
*
|
||||
* Copyright: 2002-2009 by Henrik Just
|
||||
*
|
||||
* All Rights Reserved.
|
||||
*
|
||||
* Version 1.0 (2009-02-17)
|
||||
*
|
||||
*/
|
||||
|
||||
package writer2latex.latex;
|
||||
|
||||
import org.w3c.dom.Element;
|
||||
import org.w3c.dom.Node;
|
||||
|
||||
import writer2latex.util.*;
|
||||
import writer2latex.office.*;
|
||||
import writer2latex.latex.i18n.ClassicI18n;
|
||||
import writer2latex.latex.util.BeforeAfter;
|
||||
import writer2latex.latex.util.Context;
|
||||
|
||||
/** <p>This class creates LaTeX code from OOo sections.
|
||||
* <p>Sections are converted to multicols environments using <code>multicol.sty</code>
|
||||
*/
|
||||
public class SectionConverter extends ConverterHelper {
|
||||
|
||||
// Do we need multicols.sty?
|
||||
private boolean bNeedMulticol = false;
|
||||
|
||||
// Filenames for external sections
|
||||
private ExportNameCollection fileNames = new ExportNameCollection(true);
|
||||
|
||||
/** <p>Constructs a new <code>SectionStyleConverter</code>.</p>
|
||||
*/
|
||||
public SectionConverter(OfficeReader ofr, LaTeXConfig config,
|
||||
ConverterPalette palette) {
|
||||
super(ofr,config,palette);
|
||||
}
|
||||
|
||||
public void appendDeclarations(LaTeXDocumentPortion pack, LaTeXDocumentPortion decl) {
|
||||
if (bNeedMulticol) { pack.append("\\usepackage{multicol}").nl(); }
|
||||
}
|
||||
|
||||
/** <p> Process a section (text:section tag)</p>
|
||||
* @param node The element containing the section
|
||||
* @param ldp the <code>LaTeXDocumentPortion</code> to which
|
||||
* LaTeX code should be added
|
||||
* @param oc the current context
|
||||
*/
|
||||
public void handleSection(Element node, LaTeXDocumentPortion ldp, Context oc) {
|
||||
// We may need a hyperlink target, add this first
|
||||
palette.getFieldCv().addTarget(node,"|region",ldp);
|
||||
|
||||
// Create new document, if desired
|
||||
String sFileName = null;
|
||||
Element source = Misc.getChildByTagName(node,XMLString.TEXT_SECTION_SOURCE);
|
||||
if (config.splitLinkedSections() && source!=null) {
|
||||
sFileName = fileNames.getExportName(Misc.removeExtension(Misc.urlDecode(source.getAttribute(XMLString.XLINK_HREF))));
|
||||
}
|
||||
else if (config.splitToplevelSections() && isToplevel(node)) {
|
||||
//sFileName = fileNames.getExportName(palette.getOutFileName()+node.getAttribute(XMLString.TEXT_NAME));
|
||||
sFileName = fileNames.getExportName(node.getAttribute(XMLString.TEXT_NAME));
|
||||
}
|
||||
|
||||
LaTeXDocumentPortion sectionLdp = ldp;
|
||||
if (sFileName!=null) {
|
||||
LaTeXDocument newDoc = new LaTeXDocument(sFileName,config.getWrapLinesAfter());
|
||||
if (config.getBackend()!=LaTeXConfig.XETEX) {
|
||||
newDoc.setEncoding(ClassicI18n.writeJavaEncoding(config.getInputencoding()));
|
||||
}
|
||||
else {
|
||||
newDoc.setEncoding("UTF-8");
|
||||
}
|
||||
palette.addDocument(newDoc);
|
||||
sectionLdp = newDoc.getContents();
|
||||
}
|
||||
|
||||
// Apply the style
|
||||
String sStyleName = node.getAttribute(XMLString.TEXT_STYLE_NAME);
|
||||
BeforeAfter ba = new BeforeAfter();
|
||||
Context ic = (Context) oc.clone();
|
||||
applySectionStyle(sStyleName,ba,ic);
|
||||
|
||||
// Do conversion
|
||||
ldp.append(ba.getBefore());
|
||||
if (sFileName!=null) {
|
||||
ldp.append("\\input{").append(sFileName).append("}").nl();
|
||||
}
|
||||
palette.getBlockCv().traverseBlockText(node,sectionLdp,ic);
|
||||
if (sectionLdp!=ldp) { sectionLdp.append("\\endinput").nl(); }
|
||||
ldp.append(ba.getAfter());
|
||||
}
|
||||
|
||||
// Create multicols environment as needed
|
||||
private void applySectionStyle(String sStyleName, BeforeAfter ba, Context context) {
|
||||
StyleWithProperties style = ofr.getSectionStyle(sStyleName);
|
||||
// Don't nest multicols and require at least 2 columns
|
||||
if (context.isInMulticols() || style==null || style.getColCount()<2) { return; }
|
||||
int nCols = style.getColCount();
|
||||
bNeedMulticol = true;
|
||||
context.setInMulticols(true);
|
||||
ba.add("\\begin{multicols}{"+(nCols>10 ? 10 : nCols)+"}\n", "\\end{multicols}\n");
|
||||
}
|
||||
|
||||
// return true if this node is *not* contained in a text:section element
|
||||
private boolean isToplevel(Node node) {
|
||||
Node parent = node.getParentNode();
|
||||
if (XMLString.TEXT_SECTION.equals(parent.getNodeName())) {
|
||||
return false;
|
||||
}
|
||||
else if (XMLString.OFFICE_BODY.equals(parent.getNodeName())) {
|
||||
return true;
|
||||
}
|
||||
return isToplevel(parent);
|
||||
}
|
||||
|
||||
|
||||
|
||||
}
|
1618
source/java/writer2latex/latex/StarMathConverter.java
Normal file
1618
source/java/writer2latex/latex/StarMathConverter.java
Normal file
File diff suppressed because it is too large
Load diff
51
source/java/writer2latex/latex/StyleConverter.java
Normal file
51
source/java/writer2latex/latex/StyleConverter.java
Normal file
|
@ -0,0 +1,51 @@
|
|||
/************************************************************************
|
||||
*
|
||||
* StyleConverter.java
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License version 2.1, as published by the Free Software Foundation.
|
||||
*
|
||||
* This library 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
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston,
|
||||
* MA 02111-1307 USA
|
||||
*
|
||||
* Copyright: 2002-2008 by Henrik Just
|
||||
*
|
||||
* All Rights Reserved.
|
||||
*
|
||||
* Version 1.0 (2008-09-08)
|
||||
*
|
||||
*/
|
||||
|
||||
package writer2latex.latex;
|
||||
|
||||
import writer2latex.latex.util.StyleMap;
|
||||
import writer2latex.util.ExportNameCollection;
|
||||
import writer2latex.office.OfficeReader;
|
||||
|
||||
/**
|
||||
* <p>This is an abstract superclass for style converters.</p>
|
||||
*/
|
||||
public abstract class StyleConverter extends ConverterHelper {
|
||||
|
||||
// Names and maps + necessary declarations for these styles
|
||||
protected ExportNameCollection styleNames = new ExportNameCollection(false);
|
||||
protected StyleMap styleMap = new StyleMap();
|
||||
protected LaTeXDocumentPortion declarations = new LaTeXDocumentPortion(false);
|
||||
|
||||
protected StyleConverter(OfficeReader ofr, LaTeXConfig config, ConverterPalette palette) {
|
||||
super(ofr,config,palette);
|
||||
}
|
||||
|
||||
public void appendDeclarations(LaTeXDocumentPortion pack, LaTeXDocumentPortion decl) {
|
||||
decl.append(declarations);
|
||||
}
|
||||
|
||||
}
|
366
source/java/writer2latex/latex/TableConverter.java
Normal file
366
source/java/writer2latex/latex/TableConverter.java
Normal file
|
@ -0,0 +1,366 @@
|
|||
/************************************************************************
|
||||
*
|
||||
* TableConverter.java
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License version 2.1, as published by the Free Software Foundation.
|
||||
*
|
||||
* This library 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
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston,
|
||||
* MA 02111-1307 USA
|
||||
*
|
||||
* Copyright: 2002-2008 by Henrik Just
|
||||
*
|
||||
* All Rights Reserved.
|
||||
*
|
||||
* Version 1.0 (2008-11-23)
|
||||
*
|
||||
*/
|
||||
|
||||
package writer2latex.latex;
|
||||
|
||||
import org.w3c.dom.Element;
|
||||
import writer2latex.util.*;
|
||||
import writer2latex.office.*;
|
||||
import writer2latex.latex.util.BeforeAfter;
|
||||
import writer2latex.latex.util.Context;
|
||||
|
||||
/** <p>This class converts OpenDocument tables to LaTeX.</p>
|
||||
* <p>The following LaTeX packages are used; some of them are optional</p>
|
||||
* <p>array.sty, longtable.sty, supertabular.sty, tabulary.sty, hhline.sty,
|
||||
* colortbl.sty.</p>
|
||||
* <p>Options:</p>
|
||||
* <ul>
|
||||
* <li>use_longtable = true|false</li>
|
||||
* <li>use_supertabular = true|false</li>
|
||||
* <li>use_tabulary = true|false</li>
|
||||
* <li>use_colortbl = true|false</li>
|
||||
* <li>float_tables = true|false</li>
|
||||
* <li>float_options = <string></li>
|
||||
* <li>table_content = accept|ignore|warning|error</li>
|
||||
* </ul>
|
||||
*
|
||||
*/
|
||||
public class TableConverter extends ConverterHelper {
|
||||
|
||||
private boolean bNeedLongtable = false;
|
||||
private boolean bNeedSupertabular = false;
|
||||
private boolean bNeedTabulary = false;
|
||||
private boolean bNeedColortbl = false;
|
||||
private boolean bContainsTables = false;
|
||||
|
||||
/** <p>Constructs a new <code>TableConverter</code>.</p>
|
||||
*/
|
||||
public TableConverter(OfficeReader ofr, LaTeXConfig config,
|
||||
ConverterPalette palette) {
|
||||
super(ofr,config,palette);
|
||||
}
|
||||
|
||||
public void appendDeclarations(LaTeXDocumentPortion pack, LaTeXDocumentPortion decl) {
|
||||
pack.append("\\usepackage{array}").nl(); // TODO: Make this optional
|
||||
if (bNeedLongtable) { pack.append("\\usepackage{longtable}").nl(); }
|
||||
if (bNeedSupertabular) { pack.append("\\usepackage{supertabular}").nl(); }
|
||||
if (bNeedTabulary) { pack.append("\\usepackage{tabulary}").nl(); }
|
||||
pack.append("\\usepackage{hhline}").nl(); // TODO: Make this optional
|
||||
if (bNeedColortbl) { pack.append("\\usepackage{colortbl}").nl(); }
|
||||
|
||||
// Set padding for table cells (1mm is default in OOo!)
|
||||
// For vertical padding we can only specify a relative size
|
||||
if (bContainsTables) {
|
||||
decl.append("\\setlength\\tabcolsep{1mm}").nl();
|
||||
decl.append("\\renewcommand\\arraystretch{1.3}").nl();
|
||||
}
|
||||
}
|
||||
|
||||
// Export a lonely table caption
|
||||
public void handleCaption(Element node, LaTeXDocumentPortion ldp, Context oc) {
|
||||
ldp.append("\\captionof{table}");
|
||||
palette.getCaptionCv().handleCaptionBody(node,ldp,oc,true);
|
||||
}
|
||||
|
||||
/** <p> Process a table (table:table or table:sub-table tag)</p>
|
||||
* @param node The element containing the table
|
||||
* @param ldp the <code>LaTeXDocumentPortion</code> to which
|
||||
* LaTeX code should be added
|
||||
* @param oc the current context
|
||||
*/
|
||||
public void handleTable(Element node, Element caption, boolean bCaptionAbove,
|
||||
LaTeXDocumentPortion ldp, Context oc) {
|
||||
|
||||
// Export table, if allowed by the configuration
|
||||
switch (config.tableContent()) {
|
||||
case LaTeXConfig.ACCEPT:
|
||||
new SingleTableConverter().handleTable(node,caption,bCaptionAbove,ldp,oc);
|
||||
bContainsTables = true;
|
||||
break;
|
||||
case LaTeXConfig.IGNORE:
|
||||
// Ignore table silently
|
||||
break;
|
||||
case LaTeXConfig.WARNING:
|
||||
System.err.println("Warning: Tables are not allowed");
|
||||
break;
|
||||
case LaTeXConfig.ERROR:
|
||||
ldp.append("% Error in document: A table was ignored");
|
||||
}
|
||||
}
|
||||
|
||||
// Inner class to convert a single table
|
||||
private class SingleTableConverter {
|
||||
private TableReader table;
|
||||
private TableFormatter formatter;
|
||||
private Element caption;
|
||||
private boolean bCaptionAbove;
|
||||
private BeforeAfter baTable;
|
||||
private BeforeAfter baTableAlign;
|
||||
|
||||
private void handleTable(Element node, Element caption, boolean bCaptionAbove,
|
||||
LaTeXDocumentPortion ldp, Context oc) {
|
||||
// Store the caption
|
||||
this.caption = caption;
|
||||
this.bCaptionAbove = bCaptionAbove;
|
||||
|
||||
// Read the table
|
||||
table = ofr.getTableReader(node);
|
||||
|
||||
// Get formatter and update flags according to formatter
|
||||
formatter = new TableFormatter(ofr,config,palette,table,!oc.isInMulticols(),oc.isInTable());
|
||||
bContainsTables = true;
|
||||
bNeedLongtable |= formatter.isLongtable();
|
||||
bNeedSupertabular |= formatter.isSupertabular();
|
||||
bNeedTabulary |= formatter.isTabulary();
|
||||
bNeedColortbl |= formatter.isColortbl();
|
||||
|
||||
// Update the context
|
||||
Context ic = (Context) oc.clone();
|
||||
ic.setInTable(true);
|
||||
ic.setInSimpleTable(formatter.isSimple());
|
||||
// Never allow footnotes in tables
|
||||
// (longtable.sty *does* allow footnotes in body, but not in head -
|
||||
// only consistent solution is to disallow all footnotes)
|
||||
ic.setNoFootnotes(true);
|
||||
|
||||
// Get table declarations
|
||||
baTable = new BeforeAfter();
|
||||
baTableAlign = new BeforeAfter();
|
||||
formatter.applyTableStyle(baTable,baTableAlign);
|
||||
|
||||
// Convert table
|
||||
if (formatter.isSupertabular()) {
|
||||
handleSupertabular(ldp,ic);
|
||||
}
|
||||
else if (formatter.isLongtable()) {
|
||||
handleLongtable(ldp,ic);
|
||||
}
|
||||
else if (config.floatTables() && !ic.isInFrame() && !table.isSubTable()) {
|
||||
handleTableFloat(ldp,ic);
|
||||
}
|
||||
else {
|
||||
handleTabular(ldp,ic);
|
||||
}
|
||||
|
||||
// Insert any pending footnotes
|
||||
palette.getNoteCv().flushFootnotes(ldp,oc);
|
||||
}
|
||||
|
||||
private void handleSupertabular(LaTeXDocumentPortion ldp, Context oc) {
|
||||
ldp.append(baTableAlign.getBefore());
|
||||
|
||||
// Caption
|
||||
if (caption!=null) {
|
||||
handleCaption(bCaptionAbove ? "\\topcaption" : "\\bottomcaption",
|
||||
ldp,oc);
|
||||
}
|
||||
|
||||
// Table head
|
||||
ldp.append("\\tablehead{");
|
||||
handleHeaderRows(ldp,oc);
|
||||
ldp.append("}");
|
||||
|
||||
// The table
|
||||
handleHyperTarget(ldp);
|
||||
ldp.append(baTable.getBefore()).nl();
|
||||
handleBodyRows(ldp,oc);
|
||||
ldp.append(baTable.getAfter()).nl();
|
||||
|
||||
ldp.append(baTableAlign.getAfter());
|
||||
}
|
||||
|
||||
private void handleLongtable(LaTeXDocumentPortion ldp, Context oc) {
|
||||
handleHyperTarget(ldp);
|
||||
ldp.append(baTable.getBefore()).nl();
|
||||
|
||||
// Caption above
|
||||
if (caption!=null && bCaptionAbove) {
|
||||
handleCaption("\\caption",ldp,oc);
|
||||
ldp.append("\\\\").nl();
|
||||
handleHeaderRows(ldp,oc);
|
||||
ldp.nl().append("\\endfirsthead").nl();
|
||||
}
|
||||
|
||||
// Table head
|
||||
if (table.getFirstBodyRow()>0) {
|
||||
handleHeaderRows(ldp,oc);
|
||||
ldp.nl().append("\\endhead").nl();
|
||||
}
|
||||
|
||||
// Caption below
|
||||
if (caption!=null && !bCaptionAbove) {
|
||||
handleCaption("\\caption",ldp,oc);
|
||||
ldp.append("\\endlastfoot").nl();
|
||||
}
|
||||
|
||||
// Table body
|
||||
handleBodyRows(ldp,oc);
|
||||
|
||||
ldp.append(baTable.getAfter()).nl();
|
||||
}
|
||||
|
||||
private void handleTableFloat(LaTeXDocumentPortion ldp, Context oc) {
|
||||
ldp.append("\\begin{table}");
|
||||
if (config.getFloatOptions().length()>0) {
|
||||
ldp.append("[").append(config.getFloatOptions()).append("]");
|
||||
}
|
||||
ldp.nl();
|
||||
|
||||
ldp.append(baTableAlign.getBefore());
|
||||
|
||||
// Caption above
|
||||
if (caption!=null && bCaptionAbove) {
|
||||
handleCaption("\\caption",ldp,oc);
|
||||
}
|
||||
|
||||
// The table
|
||||
handleHyperTarget(ldp);
|
||||
ldp.append(baTable.getBefore()).nl();
|
||||
handleHeaderRows(ldp,oc);
|
||||
ldp.nl();
|
||||
handleBodyRows(ldp,oc);
|
||||
ldp.append(baTable.getAfter()).nl();
|
||||
|
||||
// Caption below
|
||||
if (caption!=null && !bCaptionAbove) {
|
||||
handleCaption("\\caption",ldp,oc);
|
||||
}
|
||||
|
||||
ldp.append(baTableAlign.getAfter());
|
||||
|
||||
ldp.append("\\end{table}").nl();
|
||||
}
|
||||
|
||||
private void handleTabular(LaTeXDocumentPortion ldp, Context oc) {
|
||||
ldp.append(baTableAlign.getBefore());
|
||||
|
||||
// Caption above
|
||||
if (caption!=null && bCaptionAbove) {
|
||||
TableConverter.this.handleCaption(caption,ldp,oc);
|
||||
}
|
||||
|
||||
// The table
|
||||
handleHyperTarget(ldp);
|
||||
ldp.append(baTable.getBefore()).nl();
|
||||
if (table.getFirstBodyRow()>0) {
|
||||
handleHeaderRows(ldp,oc);
|
||||
ldp.nl();
|
||||
}
|
||||
handleBodyRows(ldp,oc);
|
||||
ldp.append(baTable.getAfter()).nl();
|
||||
|
||||
// Caption below
|
||||
if (caption!=null && !bCaptionAbove) {
|
||||
TableConverter.this.handleCaption(caption,ldp,oc);
|
||||
}
|
||||
|
||||
ldp.append(baTableAlign.getAfter());
|
||||
}
|
||||
|
||||
private void handleCaption(String sCommand, LaTeXDocumentPortion ldp, Context oc) {
|
||||
ldp.append(sCommand);
|
||||
palette.getCaptionCv().handleCaptionBody(caption,ldp,oc,false);
|
||||
}
|
||||
|
||||
private void handleHyperTarget(LaTeXDocumentPortion ldp) {
|
||||
// We may need a hyperlink target
|
||||
if (!table.isSubTable()) {
|
||||
palette.getFieldCv().addTarget(table.getTableName(),"|table",ldp);
|
||||
}
|
||||
}
|
||||
|
||||
private void handleHeaderRows(LaTeXDocumentPortion ldp, Context oc) {
|
||||
// Note: does *not* add newline after last row
|
||||
if (table.getFirstBodyRow()>0) {
|
||||
|
||||
// Add interrow material before first row:
|
||||
String sInter = formatter.getInterrowMaterial(0);
|
||||
if (sInter.length()>0) {
|
||||
ldp.append(sInter).nl();
|
||||
}
|
||||
|
||||
// Add header rows
|
||||
handleRows(0,table.getFirstBodyRow(),ldp,oc);
|
||||
}
|
||||
}
|
||||
|
||||
private void handleBodyRows(LaTeXDocumentPortion ldp, Context oc) {
|
||||
if (table.getFirstBodyRow()==0) {
|
||||
// No head, add interrow material before first row:
|
||||
String sInter = formatter.getInterrowMaterial(0);
|
||||
if (sInter.length()>0) {
|
||||
ldp.append(sInter).nl();
|
||||
}
|
||||
}
|
||||
|
||||
// Add body rows
|
||||
handleRows(table.getFirstBodyRow(),table.getRowCount(),ldp,oc);
|
||||
ldp.nl();
|
||||
}
|
||||
|
||||
private void handleRows(int nStart, int nEnd, LaTeXDocumentPortion ldp, Context oc) {
|
||||
int nColCount = table.getColCount();
|
||||
for (int nRow=nStart; nRow<nEnd; nRow++) {
|
||||
// Export columns in this row
|
||||
Context icRow = (Context) oc.clone();
|
||||
BeforeAfter baRow = new BeforeAfter();
|
||||
formatter.applyRowStyle(nRow,baRow,icRow);
|
||||
if (!baRow.isEmpty()) {
|
||||
ldp.append(baRow.getBefore());
|
||||
if (!formatter.isSimple()) { ldp.nl(); }
|
||||
}
|
||||
int nCol = 0;
|
||||
while (nCol<nColCount) {
|
||||
Element cell = (Element) table.getCell(nRow,nCol);
|
||||
if (XMLString.TABLE_TABLE_CELL.equals(cell.getNodeName())) {
|
||||
Context icCell = (Context) icRow.clone();
|
||||
BeforeAfter baCell = new BeforeAfter();
|
||||
formatter.applyCellStyle(nRow,nCol,baCell,icCell);
|
||||
ldp.append(baCell.getBefore());
|
||||
if (nCol==nColCount-1) { icCell.setInLastTableColumn(true); }
|
||||
palette.getBlockCv().traverseBlockText(cell,ldp,icCell);
|
||||
ldp.append(baCell.getAfter());
|
||||
}
|
||||
// Otherwise ignore; the cell is covered by a \multicolumn entry.
|
||||
// (table:covered-table-cell)
|
||||
int nColSpan = Misc.getPosInteger(cell.getAttribute(
|
||||
XMLString.TABLE_NUMBER_COLUMNS_SPANNED),1);
|
||||
if (nCol+nColSpan<nColCount) {
|
||||
if (formatter.isSimple()) { ldp.append(" & "); }
|
||||
else { ldp.append(" &").nl(); }
|
||||
}
|
||||
nCol+=nColSpan;
|
||||
}
|
||||
ldp.append("\\\\").append(formatter.getInterrowMaterial(nRow+1));
|
||||
// Add newline, except after last row
|
||||
if (nRow<nEnd-1) { ldp.nl(); }
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
}
|
451
source/java/writer2latex/latex/TableFormatter.java
Normal file
451
source/java/writer2latex/latex/TableFormatter.java
Normal file
|
@ -0,0 +1,451 @@
|
|||
/************************************************************************
|
||||
*
|
||||
* TableFormatter.java
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License version 2.1, as published by the Free Software Foundation.
|
||||
*
|
||||
* This library 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
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston,
|
||||
* MA 02111-1307 USA
|
||||
*
|
||||
* Copyright: 2002-2009 by Henrik Just
|
||||
*
|
||||
* All Rights Reserved.
|
||||
*
|
||||
* Version 1.0 (2009-02-19)
|
||||
*
|
||||
*/
|
||||
|
||||
package writer2latex.latex;
|
||||
|
||||
import org.w3c.dom.Element;
|
||||
import org.w3c.dom.Node;
|
||||
|
||||
import writer2latex.util.*;
|
||||
import writer2latex.office.*;
|
||||
import writer2latex.latex.util.BeforeAfter;
|
||||
import writer2latex.latex.util.Context;
|
||||
|
||||
/**
|
||||
* <p>This class converts OOo table styles to LaTeX.</p>
|
||||
* <p> In OOo the table style is distributed on table, column and cell styles.
|
||||
* <p> In LaTeX we have to rearrange this information slightly, so this class
|
||||
* takes care of that.</p>
|
||||
*/
|
||||
public class TableFormatter extends ConverterHelper {
|
||||
|
||||
//private boolean bApplyCellFormat;
|
||||
private TableReader table;
|
||||
private char[][] cAlign;
|
||||
private char[] cGlobalAlign;
|
||||
private boolean[][] bHBorder;
|
||||
private boolean[][] bVBorder;
|
||||
private boolean[] bGlobalVBorder;
|
||||
private String[] sRowColor;
|
||||
private String[][] sCellColor;
|
||||
private String[] sColumnWidth;
|
||||
private boolean bIsLongtable;
|
||||
private boolean bIsSupertabular;
|
||||
private boolean bIsTabulary;
|
||||
private boolean bIsColortbl;
|
||||
private boolean bIsSimple;
|
||||
|
||||
/** <p>Constructor: Create from a TableReader.</p>
|
||||
*/
|
||||
public TableFormatter(OfficeReader ofr, LaTeXConfig config, ConverterPalette palette,
|
||||
TableReader table, boolean bAllowPageBreak, boolean bIsInTable) {
|
||||
super(ofr,config,palette);
|
||||
this.table = table;
|
||||
//bApplyCellFormat = config.formatting()>=LaTeXConfig.CONVERT_MOST;
|
||||
int nRowCount = table.getRowCount();
|
||||
int nColCount = table.getColCount();
|
||||
int nSimpleTableLimit = config.getSimpleTableLimit();
|
||||
|
||||
// Step 1: Collect alignment and identify simple tables
|
||||
bIsSimple = true;
|
||||
cAlign = new char[nRowCount][nColCount];
|
||||
cGlobalAlign = new char[nColCount];
|
||||
// Keep track of characters to be counted
|
||||
int[] nPendingChars = new int[nRowCount];
|
||||
int[] nPendingColSpan = new int[nRowCount];
|
||||
int nTableWidth = 0;
|
||||
|
||||
for (int nCol=0; nCol<nColCount; nCol++) {
|
||||
// Collect chars to be counted in this column
|
||||
for (int nRow=0; nRow<nRowCount; nRow++) {
|
||||
Element cell = table.getCell(nRow, nCol);
|
||||
if (Misc.isElement(cell, XMLString.TABLE_TABLE_CELL)) {
|
||||
// Now we're here: Collect alignment
|
||||
if (OfficeReader.isSingleParagraph(cell)) {
|
||||
Node par = Misc.getChildByTagName(cell,XMLString.TEXT_P);
|
||||
StyleWithProperties style = ofr.getParStyle(Misc.getAttribute(par,XMLString.TEXT_STYLE_NAME));
|
||||
cAlign[nRow][nCol] = 'l';
|
||||
if (style!=null) {
|
||||
String sAlign = style.getProperty(XMLString.FO_TEXT_ALIGN,true);
|
||||
if ("center".equals(sAlign)) { cAlign[nRow][nCol] = 'c'; }
|
||||
else if ("end".equals(sAlign)) { cAlign[nRow][nCol] = 'r'; }
|
||||
}
|
||||
|
||||
}
|
||||
else {
|
||||
// Found cell with more than one paragraph
|
||||
bIsSimple = false;
|
||||
}
|
||||
// Collect characters (the cell contains this many characters that should be distributed over that many columns)
|
||||
nPendingChars[nRow] = OfficeReader.getCharacterCount(cell);
|
||||
nPendingColSpan[nRow] = Misc.getPosInteger(cell.getAttribute(XMLString.TABLE_NUMBER_COLUMNS_SPANNED), 1);
|
||||
}
|
||||
}
|
||||
// Determine the number of characters to count *now* (because they cannot be postponed to next column)
|
||||
int nColChars = 0;
|
||||
for (int nRow=0; nRow<nRowCount; nRow++) {
|
||||
if (nPendingColSpan[nRow]==1) {
|
||||
nColChars = Math.max(nColChars, nPendingChars[nRow]);
|
||||
}
|
||||
}
|
||||
// Reduce pending chars and increase table width
|
||||
nTableWidth += nColChars;
|
||||
for (int nRow=0; nRow<nRowCount; nRow++) {
|
||||
if (nPendingColSpan[nRow]>=1) {
|
||||
nPendingChars[nRow] = Math.max(0, nPendingChars[nRow]-nColChars);
|
||||
nPendingColSpan[nRow]--;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (nTableWidth>nSimpleTableLimit) bIsSimple = false;
|
||||
|
||||
// Step 2: Create global alignment
|
||||
for (int nCol=0; nCol<nColCount; nCol++) {
|
||||
int nCenter = 0;
|
||||
int nRight = 0;
|
||||
for (int nRow=0; nRow<nRowCount; nRow++) {
|
||||
if (cAlign[nRow][nCol]=='c') { nCenter++; }
|
||||
else if (cAlign[nRow][nCol]=='r') { nRight++; }
|
||||
}
|
||||
cGlobalAlign[nCol] = 'l';
|
||||
int nLeft = nColCount-nCenter-nRight;
|
||||
if (nCenter>nLeft) {
|
||||
if (nRight>nLeft) { cGlobalAlign[nCol] = 'r'; }
|
||||
else { cGlobalAlign[nCol] = 'c'; }
|
||||
}
|
||||
else if (nRight>nLeft) {
|
||||
cGlobalAlign[nCol] = 'r';
|
||||
}
|
||||
}
|
||||
|
||||
// Step 3: Initialize borders:
|
||||
bHBorder = new boolean[nRowCount+1][nColCount];
|
||||
for (int nRow=0; nRow<=nRowCount; nRow++) {
|
||||
for (int nCol=0; nCol<nColCount; nCol++) {
|
||||
bHBorder[nRow][nCol] = false;
|
||||
}
|
||||
}
|
||||
bVBorder = new boolean[nRowCount][nColCount+1];
|
||||
for (int nRow=0; nRow<nRowCount; nRow++) {
|
||||
for (int nCol=0; nCol<=nColCount; nCol++) {
|
||||
bVBorder[nRow][nCol] = false;
|
||||
}
|
||||
}
|
||||
|
||||
// Step 4: Collect borders from cell styles:
|
||||
for (int nRow=0; nRow<nRowCount; nRow++) {
|
||||
int nCol = 0;
|
||||
while (nCol<nColCount) {
|
||||
Node cell = table.getCell(nRow,nCol);
|
||||
String sStyleName = Misc.getAttribute(cell,XMLString.TABLE_STYLE_NAME);
|
||||
StyleWithProperties style = ofr.getCellStyle(sStyleName);
|
||||
int nColSpan = Misc.getPosInteger(Misc.getAttribute(cell,
|
||||
XMLString.TABLE_NUMBER_COLUMNS_SPANNED),1);
|
||||
boolean bLeft = false;
|
||||
boolean bRight = false;
|
||||
boolean bTop = false;
|
||||
boolean bBottom = false;
|
||||
if (style!=null) {
|
||||
String sBorder = style.getProperty(XMLString.FO_BORDER);
|
||||
if (sBorder!=null && !"none".equals(sBorder)) {
|
||||
bLeft = true; bRight = true; bTop = true; bBottom = true;
|
||||
}
|
||||
sBorder = style.getProperty(XMLString.FO_BORDER_LEFT);
|
||||
if (sBorder!=null && !"none".equals(sBorder)) {
|
||||
bLeft = true;
|
||||
}
|
||||
sBorder = style.getProperty(XMLString.FO_BORDER_RIGHT);
|
||||
if (sBorder!=null && !"none".equals(sBorder)) {
|
||||
bRight = true;
|
||||
}
|
||||
sBorder = style.getProperty(XMLString.FO_BORDER_TOP);
|
||||
if (sBorder!=null && !"none".equals(sBorder)) {
|
||||
bTop = true;
|
||||
}
|
||||
sBorder = style.getProperty(XMLString.FO_BORDER_BOTTOM);
|
||||
if (sBorder!=null && !"none".equals(sBorder)) {
|
||||
bBottom = true;
|
||||
}
|
||||
}
|
||||
bVBorder[nRow][nCol] |= bLeft;
|
||||
bVBorder[nRow][nCol+nColSpan] |= bRight;
|
||||
do {
|
||||
bHBorder[nRow][nCol] |= bTop;
|
||||
bHBorder[nRow+1][nCol] |= bBottom;
|
||||
nCol++;
|
||||
} while (--nColSpan>0);
|
||||
}
|
||||
}
|
||||
|
||||
// Step 5: Create global vertical borders based on simple majority
|
||||
// (in order to minimize the number of \multicolum{1} entries)
|
||||
bGlobalVBorder = new boolean[nColCount+1];
|
||||
for (int nCol=0; nCol<=nColCount; nCol++) {
|
||||
int nBalance = 0;
|
||||
for (int nRow=0; nRow<nRowCount; nRow++) {
|
||||
nBalance += bVBorder[nRow][nCol] ? 1 : -1;
|
||||
}
|
||||
bGlobalVBorder[nCol] = nBalance>0;
|
||||
}
|
||||
|
||||
// Step 6: Get background colors
|
||||
sRowColor = new String[nRowCount];
|
||||
sCellColor = new String[nRowCount][nColCount];
|
||||
if (config.useColortbl()) {
|
||||
// Table background
|
||||
String sTableColor = null;
|
||||
StyleWithProperties tableStyle = ofr.getTableStyle(table.getTableStyleName());
|
||||
if (tableStyle!=null) {
|
||||
sTableColor = tableStyle.getProperty(XMLString.FO_BACKGROUND_COLOR);
|
||||
}
|
||||
|
||||
// Row background
|
||||
for (int nRow=0; nRow<nRowCount; nRow++) {
|
||||
StyleWithProperties rowStyle = ofr.getRowStyle(table.getRow(nRow).getStyleName());
|
||||
if (rowStyle!=null) {
|
||||
sRowColor[nRow] = rowStyle.getProperty(XMLString.FO_BACKGROUND_COLOR);
|
||||
}
|
||||
if (sRowColor[nRow]==null) {
|
||||
sRowColor[nRow] = sTableColor;
|
||||
}
|
||||
if (sRowColor[nRow]!=null) {
|
||||
bIsColortbl = true;
|
||||
}
|
||||
}
|
||||
|
||||
// Cell background
|
||||
for (int nRow=0; nRow<nRowCount; nRow++) {
|
||||
for (int nCol=0; nCol<nColCount; nCol++) {
|
||||
StyleWithProperties cellStyle = ofr.getCellStyle(Misc.getAttribute(table.getCell(nRow,nCol),XMLString.TABLE_STYLE_NAME));
|
||||
if (cellStyle!=null) {
|
||||
sCellColor[nRow][nCol] = cellStyle.getProperty(XMLString.FO_BACKGROUND_COLOR);
|
||||
if (sCellColor[nRow][nCol]!=null) {
|
||||
bIsColortbl = true;
|
||||
if (sCellColor[nRow][nCol].equals(sRowColor[nRow])) {
|
||||
// Avoid redundant cell background
|
||||
sCellColor[nRow][nCol] = null;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
// Step 7: Read column style information
|
||||
sColumnWidth = new String[nColCount];
|
||||
for (int nCol=0; nCol<nColCount; nCol++) {
|
||||
StyleWithProperties colStyle
|
||||
= ofr.getColumnStyle(table.getCol(nCol).getStyleName());
|
||||
if (colStyle!=null) {
|
||||
sColumnWidth[nCol]
|
||||
= colStyle.getProperty(XMLString.STYLE_COLUMN_WIDTH);
|
||||
}
|
||||
if (sColumnWidth[nCol]==null) { // Emergency! should never happen!
|
||||
sColumnWidth[nCol]="2cm";
|
||||
}
|
||||
}
|
||||
|
||||
// Step 8: Identify longtable, supertabular or tabulary
|
||||
bIsLongtable = false; bIsSupertabular = false; bIsTabulary = false;
|
||||
if (!table.isSubTable() && !bIsInTable) {
|
||||
String sStyleName = table.getTableStyleName();
|
||||
StyleWithProperties style = ofr.getTableStyle(sStyleName);
|
||||
boolean bMayBreak = style==null ||
|
||||
!"false".equals(style.getProperty(XMLString.STYLE_MAY_BREAK_BETWEEN_ROWS));
|
||||
if (config.useLongtable() && bMayBreak && bAllowPageBreak) {
|
||||
bIsLongtable = true;
|
||||
}
|
||||
else if (config.useSupertabular() && bMayBreak && bAllowPageBreak) {
|
||||
bIsSupertabular = true;
|
||||
}
|
||||
else if (!bIsSimple && config.useTabulary()) {
|
||||
bIsTabulary = true;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/** is this a longtable? */
|
||||
public boolean isLongtable() { return bIsLongtable; }
|
||||
|
||||
/** is this a supertabular? */
|
||||
public boolean isSupertabular() { return bIsSupertabular; }
|
||||
|
||||
/** is this a tabulary? */
|
||||
public boolean isTabulary() { return bIsTabulary; }
|
||||
|
||||
/** is this a colortbl? */
|
||||
public boolean isColortbl() { return bIsColortbl; }
|
||||
|
||||
/** is this a simple table (lcr columns rather than p{})? */
|
||||
public boolean isSimple() { return bIsSimple; }
|
||||
|
||||
/**
|
||||
* <p>Create table environment based on table style.</p>
|
||||
* <p>Returns eg. "\begin{longtable}{m{2cm}|m{4cm}}", "\end{longtable}".</p>
|
||||
*/
|
||||
public void applyTableStyle(BeforeAfter ba, BeforeAfter baAlign) {
|
||||
// Read formatting info from table style
|
||||
// Only supported properties are alignment and may-break-between-rows.
|
||||
String sStyleName = table.getTableStyleName();
|
||||
StyleWithProperties style = ofr.getTableStyle(sStyleName);
|
||||
char cAlign = 'c';
|
||||
if (style!=null && !table.isSubTable()) {
|
||||
String s = style.getProperty(XMLString.TABLE_ALIGN);
|
||||
if ("left".equals(s)) { cAlign='l'; }
|
||||
else if ("right".equals(s)) { cAlign='r'; }
|
||||
}
|
||||
String sAlign="center";
|
||||
switch (cAlign) {
|
||||
case 'c': sAlign="center"; break;
|
||||
case 'r': sAlign="flushright"; break;
|
||||
case 'l': sAlign="flushleft";
|
||||
}
|
||||
|
||||
// Create table alignment (for supertabular, tabular and tabulary)
|
||||
if (!bIsLongtable && !table.isSubTable()) {
|
||||
baAlign.add("\\begin{"+sAlign+"}\n","\\end{"+sAlign+"}\n");
|
||||
}
|
||||
|
||||
// Create table declaration
|
||||
if (bIsLongtable) {
|
||||
ba.add("\\begin{longtable}["+cAlign+"]", "\\end{longtable}");
|
||||
}
|
||||
else if (bIsSupertabular) {
|
||||
ba.add("\\begin{supertabular}","\\end{supertabular}");
|
||||
}
|
||||
else if (bIsTabulary) {
|
||||
ba.add("\\begin{tabulary}{"+table.getTableWidth()+"}","\\end{tabulary}");
|
||||
}
|
||||
else if (!table.isSubTable()) {
|
||||
ba.add("\\begin{tabular}","\\end{tabular}");
|
||||
}
|
||||
else { // subtables should occupy the entire width, including padding!
|
||||
ba.add("\\hspace*{-\\tabcolsep}\\begin{tabular}",
|
||||
"\\end{tabular}\\hspace*{-\\tabcolsep}");
|
||||
}
|
||||
|
||||
// columns
|
||||
ba.add("{","");
|
||||
if (bGlobalVBorder[0]) { ba.add("|",""); }
|
||||
int nColCount = table.getColCount();
|
||||
for (int nCol=0; nCol<nColCount; nCol++){
|
||||
if (bIsSimple) {
|
||||
ba.add(Character.toString(cGlobalAlign[nCol]),"");
|
||||
}
|
||||
else if (!bIsTabulary) {
|
||||
// note: The column width in OOo includes padding, which we subtract
|
||||
ba.add("m{"+Misc.add(sColumnWidth[nCol],"-0.2cm")+"}","");
|
||||
}
|
||||
else {
|
||||
ba.add("J","");
|
||||
}
|
||||
if (bGlobalVBorder[nCol+1]) { ba.add("|",""); }
|
||||
}
|
||||
ba.add("}","");
|
||||
}
|
||||
|
||||
/** <p>Create interrow material</p> */
|
||||
public String getInterrowMaterial(int nRow) {
|
||||
int nColCount = table.getColCount();
|
||||
int nCount = 0;
|
||||
for (int nCol=0; nCol<nColCount; nCol++) {
|
||||
if (bHBorder[nRow][nCol]) { nCount++; }
|
||||
}
|
||||
if (nCount==0) { // no borders at this row
|
||||
return "";
|
||||
}
|
||||
else if (nCount==nColCount) { // complete set of borders
|
||||
return "\\hline";
|
||||
}
|
||||
else { // individual borders for each column
|
||||
StringBuffer buf = new StringBuffer();
|
||||
buf.append("\\hhline{");
|
||||
for (int nCol=0; nCol<nColCount; nCol++) {
|
||||
if (bHBorder[nRow][nCol]) { buf.append("-"); }
|
||||
else { buf.append("~"); }
|
||||
}
|
||||
buf.append("}");
|
||||
/* TODO: hhline.sty should be optional, and i not used, do as before:
|
||||
boolean bInCline = false;
|
||||
for (int nCol=0; nCol<nColCount; nCol++) {
|
||||
if (bInCline && !bHBorder[nRow][nCol]) { // close \cline
|
||||
buf.append(nCol).append("}");
|
||||
bInCline = false;
|
||||
}
|
||||
else if (!bInCline && bHBorder[nRow][nCol]) { // open \cline
|
||||
buf.append("\\cline{").append(nCol+1).append("-");
|
||||
bInCline = true;
|
||||
}
|
||||
}
|
||||
if (bInCline) { buf.append(nColCount).append("}"); }
|
||||
*/
|
||||
return buf.toString();
|
||||
}
|
||||
}
|
||||
|
||||
/** <p>Get material to put before a table row (background color)
|
||||
*/
|
||||
public void applyRowStyle(int nRow, BeforeAfter ba, Context context) {
|
||||
palette.getColorCv().applyBgColor("\\rowcolor",sRowColor[nRow],ba,context);
|
||||
}
|
||||
|
||||
/** Get material to put before and after a table cell.
|
||||
* In case of columnspan or different borders this will contain a \multicolumn command.
|
||||
*/
|
||||
public void applyCellStyle(int nRow, int nCol, BeforeAfter ba, Context context) {
|
||||
Node cell = table.getCell(nRow,nCol);
|
||||
int nColSpan = Misc.getPosInteger(Misc.getAttribute(cell,
|
||||
XMLString.TABLE_NUMBER_COLUMNS_SPANNED),1);
|
||||
// Construct column declaration as needed
|
||||
boolean bNeedLeft = (nCol==0) && (bVBorder[nRow][0]!=bGlobalVBorder[0]);
|
||||
boolean bNeedRight = bVBorder[nRow][nCol+1]!=bGlobalVBorder[nCol+1];
|
||||
boolean bNeedAlign = bIsSimple && cGlobalAlign[nCol]!=cAlign[nRow][nCol];
|
||||
// calculate column width
|
||||
String sTotalColumnWidth = sColumnWidth[nCol];
|
||||
for (int i=nCol+1; i<nCol+nColSpan; i++) {
|
||||
sTotalColumnWidth = Misc.add(sTotalColumnWidth,sColumnWidth[i]);
|
||||
}
|
||||
sTotalColumnWidth = Misc.add(sTotalColumnWidth,"-0.2cm");
|
||||
|
||||
if (bNeedAlign || bNeedLeft || bNeedRight || nColSpan>1) {
|
||||
ba.add("\\multicolumn{"+nColSpan+"}{","");
|
||||
if (nCol==0 && bVBorder[nRow][0]) { ba.add("|",""); }
|
||||
if (bIsSimple) {
|
||||
ba.add(Character.toString(cAlign[nRow][nCol]),"");
|
||||
}
|
||||
else {
|
||||
ba.add("m{"+sTotalColumnWidth+"}","");
|
||||
}
|
||||
if (bVBorder[nRow][nCol+nColSpan]) { ba.add("|",""); }
|
||||
ba.add("}{","}");
|
||||
}
|
||||
|
||||
palette.getColorCv().applyBgColor("\\cellcolor",sCellColor[nRow][nCol],ba,context);
|
||||
|
||||
}
|
||||
}
|
77
source/java/writer2latex/latex/config/clean.xml
Normal file
77
source/java/writer2latex/latex/config/clean.xml
Normal file
|
@ -0,0 +1,77 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!-- clean.xml
|
||||
This is a sample configuration file for Writer2LaTeX.
|
||||
The options are set to produce a clean
|
||||
LaTeX file from an arbitrary Writer document
|
||||
- at the expense of loss of formatting.
|
||||
An even cleaner LaTeX file is produced with ultraclean.xml.
|
||||
-->
|
||||
|
||||
<config>
|
||||
<option name="documentclass" value="article" />
|
||||
<option name="backend" value="generic" />
|
||||
<option name="inputencoding" value="ascii" />
|
||||
<option name="multilingual" value="false" />
|
||||
<option name="use_ooomath" value="false" />
|
||||
<option name="use_color" value="true" />
|
||||
<option name="use_colortbl" value="false" />
|
||||
<option name="use_geometry" value="true" />
|
||||
<option name="use_fancyhdr" value="false" />
|
||||
<option name="use_hyperref" value="true" />
|
||||
<option name="use_caption" value="true" />
|
||||
<option name="use_endnotes" value="false" />
|
||||
<option name="use_bibtex" value="true" />
|
||||
<option name="bibtex_style" value="plain" />
|
||||
<option name="formatting" value="ignore_most" />
|
||||
<option name="page_formatting" value="convert_geometry" />
|
||||
<option name="ignore_empty_paragraphs" value="true" />
|
||||
<option name="ignore_hard_page_breaks" value="false" />
|
||||
<option name="ignore_hard_line_breaks" value="false" />
|
||||
<option name="ignore_double_spaces" value="true" />
|
||||
<option name="debug" value="false" />
|
||||
<heading-map max-level="5">
|
||||
<heading-level-map writer-level="1" name="section" level="1" />
|
||||
<heading-level-map writer-level="2" name="subsection" level="2" />
|
||||
<heading-level-map writer-level="3" name="subsubsection" level="3" />
|
||||
<heading-level-map writer-level="4" name="paragraph" level="4" />
|
||||
<heading-level-map writer-level="5" name="subparagraph" level="5" />
|
||||
</heading-map>
|
||||
<custom-preamble />
|
||||
|
||||
<!-- Style maps: These rules defines how styles in OOo are mapped to LaTeX code.
|
||||
A number of predefined Writer styles are converted -->
|
||||
|
||||
<!-- "Title" is mapped to \maketitle. If the user chooses to export meta data,
|
||||
the author and date will be inserted automatically -->
|
||||
<style-map name="Title" class="paragraph" before="\title{" after="} \maketitle" line-break="false" />
|
||||
|
||||
<!-- "Quotations" is mapped to a quotation environment -->
|
||||
<style-map name="Quotations" family="paragraph-block" next="Quotations" before="\begin{quotation}" after="\end{quotation}" />
|
||||
<style-map name="Quotations" family="paragraph" before="" after="" />
|
||||
|
||||
<!-- Preformatted Text is mapped to a verbatim environment
|
||||
Note the attribute verbatim, which instructs OOo to output the content
|
||||
verbatim (characters not available in the inputencoding will be replaced
|
||||
by question marks; other content will be lost). -->
|
||||
<style-map name="Preformatted Text" family="paragraph-block" next="Preformatted Text" before="\begin{verbatim}" after="\end{verbatim}" />
|
||||
<style-map name="Preformatted Text" family="paragraph" before="" after="" verbatim="true" />
|
||||
|
||||
<!-- "Horizontal line" is mapped to a \hrule -->
|
||||
<style-map name="Horizontal Line" family="paragraph" before="" after=" \begin{center}\hrule\end{center}" />
|
||||
|
||||
<!-- "Emphasis" text style is mapped to \emph -->
|
||||
<style-map name="Emphasis" family="text" before="\emph{" after="}" />
|
||||
|
||||
<!-- "Strong Emphasis" text style is mapped to \textbf -->
|
||||
<style-map name="Strong Emphasis" family="text" before="\textbf{" after="}" />
|
||||
|
||||
<!-- "Teletype" text style is mapped to \texttt -->
|
||||
<style-map name="Teletype" family="text" before="\texttt{" after="}" />
|
||||
|
||||
<!-- "List Heading" and "List Contents" are mapped to a description environment -->
|
||||
<style-map name="List Heading" family="paragraph-block" next="List Heading;List Contents" before="\begin{description}" after="\end{description}"/>
|
||||
<style-map name="List Heading" family="paragraph" before="\item[" after="]" line-break="false" />
|
||||
<style-map name="List Contents" family="paragraph" before="" after="" />
|
||||
|
||||
</config>
|
||||
|
8
source/java/writer2latex/latex/config/default.xml
Normal file
8
source/java/writer2latex/latex/config/default.xml
Normal file
|
@ -0,0 +1,8 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!-- default.xml
|
||||
This is a sample configuration file for Writer2LaTeX.
|
||||
It sets no options, thus using defaults everywhere
|
||||
-->
|
||||
|
||||
<config/>
|
||||
|
43
source/java/writer2latex/latex/config/pdfprint.xml
Normal file
43
source/java/writer2latex/latex/config/pdfprint.xml
Normal file
|
@ -0,0 +1,43 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!-- pdfprint.xml
|
||||
This is a sample configuration file for Writer2LaTeX.
|
||||
The output will be for pdfTeX, using all the packages pifont, ifsym,
|
||||
wasysym, eurosym, hyperref, endnotes and ulem. -->
|
||||
|
||||
<config>
|
||||
<option name="documentclass" value="article" />
|
||||
<option name="backend" value="pdftex" />
|
||||
<option name="inputencoding" value="ascii" />
|
||||
<option name="use_geometry" value="true" />
|
||||
<option name="use_fancyhdr" value="true" />
|
||||
<option name="use_ooomath" value="true" />
|
||||
<option name="use_pifont" value="true" />
|
||||
<option name="use_ifsym" value="true" />
|
||||
<option name="use_wasysym" value="true" />
|
||||
<option name="use_eurosym" value="true" />
|
||||
<option name="use_color" value="true" />
|
||||
<option name="use_colortbl" value="true" />
|
||||
<option name="use_hyperref" value="true" />
|
||||
<option name="use_endnotes" value="true" />
|
||||
<option name="use_ulem" value="true" />
|
||||
<option name="use_lastpage" value="true" />
|
||||
<option name="formatting" value="convert_all" />
|
||||
<option name="page_formatting" value="convert_all" />
|
||||
<option name="ignore_empty_paragraphs" value="false" />
|
||||
<option name="ignore_hard_page_breaks" value="false" />
|
||||
<option name="ignore_hard_line_breaks" value="false" />
|
||||
<option name="ignore_double_spaces" value="false" />
|
||||
<option name="debug" value="false" />
|
||||
<heading-map max-level="5">
|
||||
<heading-level-map writer-level="1" name="section" level="1" />
|
||||
<heading-level-map writer-level="2" name="subsection" level="2" />
|
||||
<heading-level-map writer-level="3" name="subsubsection" level="3" />
|
||||
<heading-level-map writer-level="4" name="paragraph" level="4" />
|
||||
<heading-level-map writer-level="5" name="subparagraph" level="5" />
|
||||
</heading-map>
|
||||
<!-- We add \sloppy to avoid overful hboxes. To get better results,
|
||||
this should be removed and overful hboxes fixed by hand. -->
|
||||
<custom-preamble>\sloppy</custom-preamble>
|
||||
|
||||
</config>
|
||||
|
50
source/java/writer2latex/latex/config/pdfscreen.xml
Normal file
50
source/java/writer2latex/latex/config/pdfscreen.xml
Normal file
|
@ -0,0 +1,50 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!-- pdfscreen.xml
|
||||
This is a sample configuration file for Writer2LaTeX.
|
||||
The output will be for pdfTeX, using all the packages pifont, ifsym,
|
||||
wasysym, eurosym, hyperref, endnotes and ulem.
|
||||
The package pdfscreen.sty will be loaded to create a pdf file
|
||||
suitable for viewing on screen. -->
|
||||
|
||||
<config>
|
||||
<option name="documentclass" value="article" />
|
||||
<option name="backend" value="pdftex" />
|
||||
<option name="inputencoding" value="ascii" />
|
||||
<option name="use_ooomath" value="true" />
|
||||
<option name="use_pifont" value="true" />
|
||||
<option name="use_ifsym" value="true" />
|
||||
<option name="use_wasysym" value="true" />
|
||||
<option name="use_bbding" value="false" />
|
||||
<option name="use_eurosym" value="true" />
|
||||
<option name="use_color" value="true" />
|
||||
<option name="use_colortbl" value="true" />
|
||||
<option name="use_hyperref" value="true" />
|
||||
<option name="use_endnotes" value="true" />
|
||||
<option name="use_ulem" value="true" />
|
||||
<option name="use_lastpage" value="true" />
|
||||
<option name="formatting" value="convert_all" />
|
||||
<option name="page_formatting" value="ignore_all" />
|
||||
<option name="ignore_empty_paragraphs" value="false" />
|
||||
<option name="ignore_hard_page_breaks" value="false" />
|
||||
<option name="ignore_hard_line_breaks" value="false" />
|
||||
<option name="ignore_double_spaces" value="true" />
|
||||
<option name="debug" value="false" />
|
||||
<heading-map max-level="5">
|
||||
<heading-level-map writer-level="1" name="section" level="1" />
|
||||
<heading-level-map writer-level="2" name="subsection" level="2" />
|
||||
<heading-level-map writer-level="3" name="subsubsection" level="3" />
|
||||
<heading-level-map writer-level="4" name="paragraph" level="4" />
|
||||
<heading-level-map writer-level="5" name="subparagraph" level="5" />
|
||||
</heading-map>
|
||||
|
||||
<!-- load pdfscreen.sty with suitable options. (Note that export of page
|
||||
formatting is disabled above; pdfscreen.sty takes care of page setup.)
|
||||
The lines are relatively short, so we add \sloppy to avoid overful hboxes.
|
||||
-->
|
||||
<custom-preamble>\usepackage{palatino}
|
||||
\usepackage[bluelace,screen,nopanel,sectionbreak]{pdfscreen}
|
||||
%\hypersetup{pdfpagemode={FullScreen}}
|
||||
\margins{0.5in}{0.5in}{0.5in}{0.5in}
|
||||
\screensize{6in}{8in}
|
||||
\sloppy</custom-preamble>
|
||||
</config>
|
77
source/java/writer2latex/latex/config/ultraclean.xml
Normal file
77
source/java/writer2latex/latex/config/ultraclean.xml
Normal file
|
@ -0,0 +1,77 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!-- ultraclean.xml
|
||||
This is a sample configuration file for Writer2LaTeX.
|
||||
The options are set to produce the cleanest possible
|
||||
LaTeX file from an arbitrary Writer document
|
||||
- by removing practically all formatting.
|
||||
-->
|
||||
|
||||
|
||||
<config>
|
||||
<option name="documentclass" value="article" />
|
||||
<option name="backend" value="generic" />
|
||||
<option name="inputencoding" value="ascii" />
|
||||
<option name="multilingual" value="false" />
|
||||
<option name="use_ooomath" value="false" />
|
||||
<option name="use_color" value="false" />
|
||||
<option name="use_colortbl" value="false" />
|
||||
<option name="use_geometry" value="false" />
|
||||
<option name="use_fancyhdr" value="false" />
|
||||
<option name="use_hyperref" value="false" />
|
||||
<option name="use_caption" value="true" />
|
||||
<option name="use_endnotes" value="false" />
|
||||
<option name="use_bibtex" value="true" />
|
||||
<option name="bibtex_style" value="plain" />
|
||||
<option name="formatting" value="ignore_all" />
|
||||
<option name="page_formatting" value="ignore_all" />
|
||||
<option name="ignore_empty_paragraphs" value="true" />
|
||||
<option name="ignore_hard_page_breaks" value="true" />
|
||||
<option name="ignore_hard_line_breaks" value="true" />
|
||||
<option name="ignore_double_spaces" value="true" />
|
||||
<option name="debug" value="false" />
|
||||
<heading-map max-level="5">
|
||||
<heading-level-map writer-level="1" name="section" level="1" />
|
||||
<heading-level-map writer-level="2" name="subsection" level="2" />
|
||||
<heading-level-map writer-level="3" name="subsubsection" level="3" />
|
||||
<heading-level-map writer-level="4" name="paragraph" level="4" />
|
||||
<heading-level-map writer-level="5" name="subparagraph" level="5" />
|
||||
</heading-map>
|
||||
<custom-preamble />
|
||||
|
||||
<!-- Style maps: These rules defines how styles in OOo are mapped to LaTeX code.
|
||||
A number of predefined Writer styles are converted -->
|
||||
|
||||
<!-- "Title" is mapped to \maketitle. If the user chooses to export meta data,
|
||||
the author and date will be inserted automatically -->
|
||||
<style-map name="Title" class="paragraph" before="\title{" after="} \maketitle" line-break="false" />
|
||||
|
||||
<!-- "Quotations" is mapped to a quotation environment -->
|
||||
<style-map name="Quotations" family="paragraph-block" next="Quotations" before="\begin{quotation}" after="\end{quotation}" />
|
||||
<style-map name="Quotations" family="paragraph" before="" after="" />
|
||||
|
||||
<!-- Preformatted Text is mapped to a verbatim environment
|
||||
Note the attribute verbatim, which instructs OOo to output the content
|
||||
verbatim (characters not available in the inputencoding will be replaced
|
||||
by question marks; other content will be lost). -->
|
||||
<style-map name="Preformatted Text" family="paragraph-block" next="Preformatted Text" before="\begin{verbatim}" after="\end{verbatim}" />
|
||||
<style-map name="Preformatted Text" family="paragraph" before="" after="" verbatim="true" />
|
||||
|
||||
<!-- "Horizontal line" is mapped to a \hrule -->
|
||||
<style-map name="Horizontal Line" family="paragraph" before="" after=" \begin{center}\hrule\end{center}" />
|
||||
|
||||
<!-- "Emphasis" text style is mapped to \emph -->
|
||||
<style-map name="Emphasis" family="text" before="\emph{" after="}" />
|
||||
|
||||
<!-- "Strong Emphasis" text style is mapped to \textbf -->
|
||||
<style-map name="Strong Emphasis" family="text" before="\textbf{" after="}" />
|
||||
|
||||
<!-- "Teletype" text style is mapped to \texttt -->
|
||||
<style-map name="Teletype" family="text" before="\texttt{" after="}" />
|
||||
|
||||
<!-- "List Heading" and "List Contents" are mapped to a description environment -->
|
||||
<style-map name="List Heading" family="paragraph-block" next="List Heading;List Contents" before="\begin{description}" after="\end{description}"/>
|
||||
<style-map name="List Heading" family="paragraph" before="\item[" after="]" line-break="false" />
|
||||
<style-map name="List Contents" family="paragraph" before="" after="" />
|
||||
|
||||
</config>
|
||||
|
697
source/java/writer2latex/latex/i18n/ClassicI18n.java
Normal file
697
source/java/writer2latex/latex/i18n/ClassicI18n.java
Normal file
|
@ -0,0 +1,697 @@
|
|||
/************************************************************************
|
||||
*
|
||||
* ClassicI18n.java
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License version 2.1, as published by the Free Software Foundation.
|
||||
*
|
||||
* This library 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
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston,
|
||||
* MA 02111-1307 USA
|
||||
*
|
||||
* Copyright: 2002-2009 by Henrik Just
|
||||
*
|
||||
* All Rights Reserved.
|
||||
*
|
||||
* Version 1.0 (2009-02-16)
|
||||
*
|
||||
*/
|
||||
|
||||
package writer2latex.latex.i18n;
|
||||
|
||||
import java.io.*;
|
||||
import java.util.Hashtable;
|
||||
import java.util.Stack;
|
||||
//import java.util.Vector;
|
||||
//import java.util.Enumeration;
|
||||
import java.util.Iterator;
|
||||
|
||||
import javax.xml.parsers.SAXParserFactory;
|
||||
import javax.xml.parsers.SAXParser;
|
||||
|
||||
import writer2latex.util.CSVList;
|
||||
import writer2latex.office.*;
|
||||
import writer2latex.latex.LaTeXConfig;
|
||||
import writer2latex.latex.LaTeXDocumentPortion;
|
||||
import writer2latex.latex.ConverterPalette;
|
||||
import writer2latex.latex.util.BeforeAfter;
|
||||
|
||||
/** This class (and the helpers in the same package) takes care of i18n in
|
||||
* Writer2LaTeX. In classic LaTeX, i18n is a mixture of inputencodings, fontencodings
|
||||
* and babel languages. The class ClassicI18n thus manages these, and in particular
|
||||
* implements a Unicode->LaTeX translation that can handle different
|
||||
* inputencodings and fontencodings.
|
||||
* The translation is table driven, using symbols.xml (embedded in the jar)
|
||||
* Various sections of symbols.xml handles different cases:
|
||||
* <ul>
|
||||
* <li>common symbols in various font encodings such as T1, T2A, LGR etc.</li>
|
||||
* <li>input encodings such as ISO-8859-1 (latin-1), ISO-8859-7 (latin/greek) etc.</li>
|
||||
* <li>additional symbol fonts such as wasysym, dingbats etc.</li>
|
||||
* <li>font-specific symbols, eg. for 8-bit fonts/private use area</li>
|
||||
* </ul>
|
||||
* The class uses the packages inputenc, fontenc, babel, tipa, bbding,
|
||||
* ifsym, pifont, eurosym, amsmath, wasysym, amssymb, amsfonts and textcomp
|
||||
* in various combinations depending on the configuration.
|
||||
*/
|
||||
public class ClassicI18n extends I18n {
|
||||
// **** Static data and methods: Inputencodings ****
|
||||
public static final int ASCII = 0;
|
||||
public static final int LATIN1 = 1; // ISO Latin 1 (ISO-8859-1)
|
||||
public static final int LATIN2 = 2; // ISO Latin 1 (ISO-8859-1)
|
||||
public static final int ISO_8859_7 = 3; // ISO latin/greek
|
||||
public static final int CP1250 = 4; // Microsoft Windows Eastern European
|
||||
public static final int CP1251 = 5; // Microsoft Windows Cyrillic
|
||||
public static final int KOI8_R = 6; // Latin/russian
|
||||
public static final int UTF8 = 7; // UTF-8
|
||||
|
||||
// Read an inputencoding from a string
|
||||
public static final int readInputenc(String sInputenc) {
|
||||
if ("ascii".equals(sInputenc)) return ASCII;
|
||||
else if ("latin1".equals(sInputenc)) return LATIN1;
|
||||
else if ("latin2".equals(sInputenc)) return LATIN2;
|
||||
else if ("iso-8859-7".equals(sInputenc)) return ISO_8859_7;
|
||||
else if ("cp1250".equals(sInputenc)) return CP1250;
|
||||
else if ("cp1251".equals(sInputenc)) return CP1251;
|
||||
else if ("koi8-r".equals(sInputenc)) return KOI8_R;
|
||||
else if ("utf8".equals(sInputenc)) return UTF8;
|
||||
else return ASCII; // unknown = ascii
|
||||
}
|
||||
|
||||
// Return the LaTeX name of an inputencoding
|
||||
public static final String writeInputenc(int nInputenc) {
|
||||
switch (nInputenc) {
|
||||
case ASCII : return "ascii";
|
||||
case LATIN1 : return "latin1";
|
||||
case LATIN2 : return "latin2";
|
||||
case ISO_8859_7 : return "iso-8859-7";
|
||||
case CP1250 : return "cp1250";
|
||||
case CP1251 : return "cp1251";
|
||||
case KOI8_R : return "koi8-r";
|
||||
case UTF8 : return "utf8";
|
||||
default : return "???";
|
||||
}
|
||||
}
|
||||
|
||||
// Return the java i18n name of an inputencoding
|
||||
public static final String writeJavaEncoding(int nInputenc) {
|
||||
switch (nInputenc) {
|
||||
case ASCII : return "ASCII";
|
||||
case LATIN1 : return "ISO8859_1";
|
||||
case LATIN2 : return "ISO8859_2";
|
||||
case ISO_8859_7 : return "ISO8859_7";
|
||||
case CP1250 : return "Cp1250";
|
||||
case CP1251 : return "Cp1251";
|
||||
case KOI8_R : return "KOI8_R";
|
||||
case UTF8 : return "UTF-8";
|
||||
default : return "???";
|
||||
}
|
||||
}
|
||||
|
||||
// **** Static data and methods: Fontencodings ****
|
||||
private static final int T1_ENC = 1;
|
||||
private static final int T2A_ENC = 2;
|
||||
private static final int T3_ENC = 4;
|
||||
private static final int LGR_ENC = 8;
|
||||
private static final int ANY_ENC = 15;
|
||||
|
||||
// read set of font encodings from a string
|
||||
public static final int readFontencs(String sFontencs) {
|
||||
sFontencs = sFontencs.toUpperCase();
|
||||
if ("ANY".equals(sFontencs)) return ANY_ENC;
|
||||
int nFontencs = 0;
|
||||
if (sFontencs.indexOf("T1")>=0) nFontencs+=T1_ENC;
|
||||
if (sFontencs.indexOf("T2A")>=0) nFontencs+=T2A_ENC;
|
||||
if (sFontencs.indexOf("T3")>=0) nFontencs+=T3_ENC;
|
||||
if (sFontencs.indexOf("LGR")>=0) nFontencs+=LGR_ENC;
|
||||
return nFontencs;
|
||||
}
|
||||
|
||||
// return string representation of a single font encoding
|
||||
/*private static final String writeFontenc(int nFontenc) {
|
||||
switch (nFontenc) {
|
||||
case T1_ENC: return "T1";
|
||||
case T2A_ENC: return "T2A";
|
||||
case T3_ENC: return "T3";
|
||||
case LGR_ENC: return "LGR";
|
||||
}
|
||||
return null;
|
||||
}*/
|
||||
|
||||
// check that a given set of font encodings contains a specific font encoding
|
||||
private static final boolean supportsFontenc(int nFontencs, int nFontenc) {
|
||||
return (nFontencs & nFontenc) != 0;
|
||||
}
|
||||
|
||||
// get one fontencoding from a set of fontencodings
|
||||
private static final int getFontenc(int nFontencs) {
|
||||
if (supportsFontenc(nFontencs,T1_ENC)) return T1_ENC;
|
||||
if (supportsFontenc(nFontencs,T2A_ENC)) return T2A_ENC;
|
||||
if (supportsFontenc(nFontencs,T3_ENC)) return T3_ENC;
|
||||
if (supportsFontenc(nFontencs,LGR_ENC)) return LGR_ENC;
|
||||
return 0;
|
||||
}
|
||||
|
||||
// get the font encoding for a specific iso language
|
||||
private static final int getFontenc(String sLang) {
|
||||
// Greek uses "local greek" encoding
|
||||
if ("el".equals(sLang)) return LGR_ENC;
|
||||
// Russian, ukrainian, bulgarian and serbian uses T2A encoding
|
||||
else if ("ru".equals(sLang)) return T2A_ENC;
|
||||
else if ("uk".equals(sLang)) return T2A_ENC;
|
||||
else if ("bg".equals(sLang)) return T2A_ENC;
|
||||
else if ("sr".equals(sLang)) return T2A_ENC;
|
||||
// Other languages uses T1 encoding
|
||||
else return T1_ENC;
|
||||
}
|
||||
|
||||
// return cs for a fontencoding
|
||||
private static final String getFontencCs(int nFontenc) {
|
||||
switch (nFontenc) {
|
||||
case T1_ENC: return "\\textlatin"; // requires babel
|
||||
case T2A_ENC: return "\\textcyrillic"; // requires babel with russian, bulgarian or ukrainian option
|
||||
case T3_ENC: return "\\textipa"; // requires tipa.sty
|
||||
case LGR_ENC: return "\\textgreek"; // requires babel with greek option
|
||||
default: return null;
|
||||
}
|
||||
}
|
||||
|
||||
// End of static part of I18n!
|
||||
|
||||
// **** Global variables ****
|
||||
private Hashtable babelLanguages; // mappings iso->babel language
|
||||
|
||||
// Unicode translation
|
||||
private Hashtable tableSet; // all tables
|
||||
private UnicodeTable table; // currently active table (top of stack)
|
||||
private Stack tableStack; // stack of active tables
|
||||
private UnicodeStringParser ucparser; // Unicode string parser
|
||||
|
||||
// Collected data
|
||||
private int nDefaultFontenc; // Fontenc for the default language
|
||||
private boolean bT2A = false; // Do we use cyrillic letters?
|
||||
private boolean bGreek = false; // Do we use greek letters?
|
||||
private boolean bPolytonicGreek = false; // Do we use polytonic greek letters?
|
||||
|
||||
// **** Constructors ****
|
||||
|
||||
/** Construct a new ClassicI18n as ConverterHelper
|
||||
* @param ofr the OfficeReader to get language information from
|
||||
* @param config the configuration which determines the symbols to use
|
||||
* @param palette the ConverterPalette (unused)
|
||||
*/
|
||||
public ClassicI18n(OfficeReader ofr, LaTeXConfig config, ConverterPalette palette) {
|
||||
super(ofr,config,palette);
|
||||
// We don't need the palette and the office reader is only used to
|
||||
// identify the default language
|
||||
|
||||
// Set up table for iso->babel translation
|
||||
prepareBabelLanguages();
|
||||
|
||||
nDefaultFontenc = getFontenc(sDefaultLanguage);
|
||||
|
||||
// Unicode stuff
|
||||
ucparser = new UnicodeStringParser();
|
||||
|
||||
String sSymbols="ascii"; // always load common symbols
|
||||
if (config.getInputencoding()!=ASCII) {
|
||||
sSymbols+="|"+writeInputenc(config.getInputencoding());
|
||||
}
|
||||
|
||||
if (config.useWasysym()) sSymbols+="|wasysym";
|
||||
if (config.useBbding()) sSymbols+="|bbding";
|
||||
if (config.useIfsym()) sSymbols+="|ifsym";
|
||||
if (config.usePifont()) sSymbols+="|dingbats";
|
||||
if (config.useEurosym()) sSymbols+="|eurosym";
|
||||
if (config.useTipa()) sSymbols+="|tipa";
|
||||
|
||||
tableSet = new Hashtable();
|
||||
UnicodeTableHandler handler=new UnicodeTableHandler(tableSet, sSymbols);
|
||||
SAXParserFactory factory=SAXParserFactory.newInstance();
|
||||
InputStream is = this.getClass().getResourceAsStream("symbols.xml");
|
||||
try {
|
||||
SAXParser saxParser=factory.newSAXParser();
|
||||
saxParser.parse(is,handler);
|
||||
}
|
||||
catch (Throwable t){
|
||||
System.err.println("Oops - Unable to read symbols.xml");
|
||||
t.printStackTrace();
|
||||
}
|
||||
// put root table at top of stack
|
||||
tableStack = new Stack();
|
||||
tableStack.push((UnicodeTable) tableSet.get("root"));
|
||||
table = (UnicodeTable) tableSet.get("root");
|
||||
}
|
||||
|
||||
/** Construct a new I18n for general use
|
||||
* @param config the configuration which determines the symbols to use
|
||||
*/
|
||||
public ClassicI18n(LaTeXConfig config) {
|
||||
this (null, config, null);
|
||||
}
|
||||
|
||||
/** Add declarations to the preamble to load the required packages
|
||||
* @param pack usepackage declarations
|
||||
* @param decl other declarations
|
||||
*/
|
||||
public void appendDeclarations(LaTeXDocumentPortion pack, LaTeXDocumentPortion decl) {
|
||||
pack.append("\\usepackage[")
|
||||
.append(writeInputenc(config.getInputencoding()))
|
||||
.append("]{inputenc}").nl();
|
||||
|
||||
// usepackage fontenc
|
||||
CSVList fontencs = new CSVList(',');
|
||||
if (bT2A) { fontencs.addValue("T2A"); }
|
||||
if (bGreek) { fontencs.addValue("LGR"); }
|
||||
if (config.useTipa()) { fontencs.addValue("T3"); }
|
||||
fontencs.addValue("T1");
|
||||
pack.append("\\usepackage[").append(fontencs.toString())
|
||||
.append("]{fontenc}").nl();
|
||||
|
||||
// usepackage babel
|
||||
|
||||
// If the document contains "anonymous" greek letters we need greek in any case
|
||||
// If the document contains "anonymous cyrillic letters we need one of the
|
||||
// languages russian, ukrainian or bulgarian
|
||||
if (greek() && !languages.contains("el")) languages.add("el");
|
||||
if (cyrillic() && !(languages.contains("ru") || languages.contains("uk") || languages.contains("bg"))) {
|
||||
languages.add("ru");
|
||||
}
|
||||
|
||||
// Load babel with the used languages
|
||||
CSVList babelopt = new CSVList(",");
|
||||
Iterator langiter = languages.iterator();
|
||||
while (langiter.hasNext()) {
|
||||
String sLang = (String) langiter.next();
|
||||
if (!sLang.equals(sDefaultLanguage)) {
|
||||
if ("el".equals(sLang) && this.polytonicGreek()) {
|
||||
babelopt.addValue("polutonikogreek");
|
||||
}
|
||||
else {
|
||||
babelopt.addValue(getBabelLanguage(sLang));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// The default language must be the last one
|
||||
if (sDefaultLanguage!=null) {
|
||||
if ("el".equals(sDefaultLanguage) && this.polytonicGreek()) {
|
||||
babelopt.addValue("polutonikogreek");
|
||||
}
|
||||
else {
|
||||
babelopt.addValue(getBabelLanguage(sDefaultLanguage));
|
||||
}
|
||||
}
|
||||
|
||||
if (!babelopt.isEmpty()) {
|
||||
pack.append("\\usepackage[")
|
||||
.append(babelopt.toString())
|
||||
.append("]{babel}").nl();
|
||||
}
|
||||
|
||||
// usepackage tipa
|
||||
if (config.useTipa()) {
|
||||
pack.append("\\usepackage[noenc]{tipa}").nl()
|
||||
.append("\\usepackage{tipx}").nl();
|
||||
}
|
||||
|
||||
// usepackage bbding (Has to avoid some nameclashes.)
|
||||
if (config.useBbding()) {
|
||||
pack.append("\\usepackage{bbding}").nl()
|
||||
.append("\\let\\bbCross\\Cross\\let\\Cross\\undefined").nl()
|
||||
.append("\\let\\bbSquare\\Square\\let\\Square\\undefined").nl()
|
||||
.append("\\let\\bbTrianbleUp\\TriangleUp\\let\\TriangleUp\\undefined").nl()
|
||||
.append("\\let\\bbTrianlgeDown\\TriangleDown\\let\\TriangleDown\\undefined").nl();
|
||||
}
|
||||
|
||||
// usepackage ifsym
|
||||
if (config.useIfsym()) {
|
||||
pack.append("\\usepackage[geometry,weather,misc,clock]{ifsym}").nl();
|
||||
}
|
||||
|
||||
// usepackage pifont
|
||||
if (config.usePifont()) { pack.append("\\usepackage{pifont}").nl(); }
|
||||
|
||||
// usepackage eurosym
|
||||
if (config.useEurosym()) { pack.append("\\usepackage{eurosym}").nl(); }
|
||||
|
||||
// usepackage amsmath (always!)
|
||||
pack.append("\\usepackage{amsmath}").nl();
|
||||
|
||||
// usepackage wasysym (*must* be loaded between amsmath and amsfonts!)
|
||||
if (config.useWasysym()) {
|
||||
pack.append("\\usepackage{wasysym}").nl();
|
||||
}
|
||||
|
||||
// usepackage amssymb, amsfonts, textcomp (always!)
|
||||
pack.append("\\usepackage{amssymb,amsfonts,textcomp}").nl();
|
||||
|
||||
}
|
||||
|
||||
/** Apply a language language
|
||||
* @param style the OOo style to read attributesfrom
|
||||
* @param bDecl true if declaration form is required
|
||||
* @param bInherit true if inherited properties should be used
|
||||
* @param ba the <code>BeforeAfter</code> to add LaTeX code to.
|
||||
*/
|
||||
public void applyLanguage(StyleWithProperties style, boolean bDecl, boolean bInherit, BeforeAfter ba) {
|
||||
if (!bAlwaysUseDefaultLang && style!=null) {
|
||||
String sISOLang = style.getProperty(XMLString.FO_LANGUAGE,bInherit);
|
||||
if (sISOLang!=null) {
|
||||
languages.add(sISOLang);
|
||||
String sLang = getBabelLanguage(sISOLang);
|
||||
if (sLang!=null) {
|
||||
if (bDecl) {
|
||||
ba.add("\\selectlanguage{"+sLang+"}","");
|
||||
//ba.add("\\begin{otherlanguage}{"+sLang+"}","\\end{otherlanguage}");
|
||||
}
|
||||
else {
|
||||
ba.add("\\foreignlanguage{"+sLang+"}{","}");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/** Push a font to the font stack
|
||||
* @param sName the name of the font
|
||||
*/
|
||||
public void pushSpecialTable(String sName) {
|
||||
// If no name is specified we should keep the current table
|
||||
// Otherwise try to find the table, and use root if it's not available
|
||||
if (sName!=null) {
|
||||
table = (UnicodeTable) tableSet.get(sName);
|
||||
if (table==null) { table = (UnicodeTable) tableSet.get("root"); }
|
||||
}
|
||||
tableStack.push(table);
|
||||
}
|
||||
|
||||
/** Pop a font from the font stack
|
||||
*/
|
||||
public void popSpecialTable() {
|
||||
tableStack.pop();
|
||||
table = (UnicodeTable) tableStack.peek();
|
||||
}
|
||||
|
||||
/** Get the number of characters defined in the current table
|
||||
* (for informational purposes only)
|
||||
* @return the number of characters
|
||||
*/
|
||||
public int getCharCount() { return table.getCharCount(); }
|
||||
|
||||
/** Convert a string of characters into LaTeX
|
||||
* @param s the source string
|
||||
* @param bMathMode true if the string should be rendered in math mode
|
||||
* @param sLang the iso language of the string
|
||||
* @return the LaTeX string
|
||||
*/
|
||||
public String convert(String s, boolean bMathMode, String sLang){
|
||||
if (!bAlwaysUseDefaultLang && sLang!=null) { languages.add(sLang); }
|
||||
StringBuffer buf=new StringBuffer();
|
||||
int nFontenc = bAlwaysUseDefaultLang ? nDefaultFontenc : getFontenc(sLang);
|
||||
int nLen = s.length();
|
||||
int i = 0;
|
||||
int nStart = i;
|
||||
while (i<nLen) {
|
||||
ReplacementTrieNode node = stringReplace.get(s,i,nLen);
|
||||
if (node!=null) {
|
||||
if (i>nStart) {
|
||||
convert(s,nStart,i,bMathMode,sLang,buf,nFontenc);
|
||||
}
|
||||
boolean bOtherFontenc = !supportsFontenc(node.getFontencs(),nFontenc);
|
||||
if (bOtherFontenc) {
|
||||
buf.append(getFontencCs(getFontenc(node.getFontencs()))).append("{");
|
||||
}
|
||||
buf.append(node.getLaTeXCode());
|
||||
if (bOtherFontenc) {
|
||||
buf.append("}");
|
||||
}
|
||||
i += node.getInputLength();
|
||||
nStart = i;
|
||||
}
|
||||
else {
|
||||
i++;
|
||||
}
|
||||
}
|
||||
if (nStart<nLen) {
|
||||
convert(s,nStart,nLen,bMathMode,sLang,buf,nFontenc);
|
||||
}
|
||||
return buf.toString();
|
||||
}
|
||||
|
||||
private void convert(String s, int nStart, int nEnd, boolean bMathMode, String sLang, StringBuffer buf, int nFontenc) {
|
||||
int nCurFontenc = nFontenc;
|
||||
ucparser.reset(table,s,nStart,nEnd);
|
||||
boolean bProtectDashes = true;
|
||||
boolean bTempMathMode = false;
|
||||
while (ucparser.next()) {
|
||||
char c = ucparser.getChar();
|
||||
if (bMathMode) {
|
||||
buf.append(convertMathChar(c,nFontenc));
|
||||
}
|
||||
else if (greekMath(c,nFontenc) || (table.hasMathChar(c) && !table.hasTextChar(c))) {
|
||||
if (!bTempMathMode) { // switch to math mode
|
||||
buf.append("$");
|
||||
bTempMathMode = true;
|
||||
}
|
||||
buf.append(convertMathChar(c,nFontenc));
|
||||
bProtectDashes = false;
|
||||
}
|
||||
else if (table.hasTextChar(c)) {
|
||||
if (bTempMathMode) { // switch to text mode
|
||||
buf.append("$");
|
||||
bTempMathMode = false;
|
||||
}
|
||||
int nFontencs = table.getFontencs(c);
|
||||
if (supportsFontenc(nFontencs,nCurFontenc)) {
|
||||
// The text character is valid in the current font encoding
|
||||
// Note: Change of font encoding is greedy - change?
|
||||
|
||||
// Prevent unwanted --- ligatures
|
||||
if (table.isDashes(c)) {
|
||||
if (bProtectDashes) { buf.append("{}"); }
|
||||
bProtectDashes = true;
|
||||
}
|
||||
else {
|
||||
bProtectDashes = false;
|
||||
}
|
||||
|
||||
setFlags(c,nCurFontenc);
|
||||
if (ucparser.hasCombiningChar()) {
|
||||
char cc = ucparser.getCombiningChar();
|
||||
if (supportsFontenc(table.getFontencs(cc),nCurFontenc)) {
|
||||
buf.append(table.getTextChar(cc)).append("{")
|
||||
.append(table.getTextChar(c)).append("}");
|
||||
}
|
||||
else { // ignore combining char if not valid in this font encoding
|
||||
buf.append(table.getTextChar(c));
|
||||
}
|
||||
}
|
||||
else {
|
||||
buf.append(table.getTextChar(c));
|
||||
}
|
||||
}
|
||||
else {
|
||||
// The text character is valid in another font encoding
|
||||
|
||||
bProtectDashes = table.isDashes(c);
|
||||
|
||||
int nFontenc1 = getFontenc(nFontencs);
|
||||
setFlags(c,nFontenc1);
|
||||
if (nCurFontenc!=nFontenc) { // end "other font encoding"
|
||||
buf.append("}");
|
||||
}
|
||||
if (nFontenc1!=nFontenc) { // start "other font encoding"
|
||||
buf.append(getFontencCs(nFontenc1)).append("{");
|
||||
}
|
||||
|
||||
if (ucparser.hasCombiningChar()) {
|
||||
char cc = ucparser.getCombiningChar();
|
||||
if (supportsFontenc(table.getFontencs(cc),nCurFontenc)) {
|
||||
buf.append(table.getTextChar(cc)).append("{")
|
||||
.append(table.getTextChar(c)).append("}");
|
||||
}
|
||||
else { // ignore combining char if not valid in this font encoding
|
||||
buf.append(table.getTextChar(c));
|
||||
}
|
||||
}
|
||||
else {
|
||||
buf.append(table.getTextChar(c));
|
||||
}
|
||||
nCurFontenc = nFontenc1;
|
||||
}
|
||||
}
|
||||
else {
|
||||
buf.append(notFound(c,nCurFontenc));
|
||||
}
|
||||
}
|
||||
|
||||
if (bTempMathMode) { // turn of math mode
|
||||
buf.append("$");
|
||||
}
|
||||
|
||||
if (nCurFontenc!=nFontenc) { // end unfinished "other font encoding"
|
||||
buf.append("}");
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
// convert a single math character
|
||||
private String convertMathChar(char c, int nFontenc) {
|
||||
if (table.hasMathChar(c)) {
|
||||
return table.getMathChar(c);
|
||||
}
|
||||
else if (table.hasTextChar(c)) { // use text mode as a fallback
|
||||
int nFontencs = table.getFontencs(c);
|
||||
if (supportsFontenc(nFontencs,nFontenc)) {
|
||||
// The text character is valid in the current font encoding
|
||||
setFlags(c,nFontenc);
|
||||
if (table.getCharType(c)==UnicodeCharacter.COMBINING) {
|
||||
return "\\text{" + table.getTextChar(c) +"{}}";
|
||||
}
|
||||
else {
|
||||
return "\\text{" + table.getTextChar(c) +"}";
|
||||
}
|
||||
}
|
||||
else {
|
||||
// The text character is valid in another font encoding
|
||||
int nFontenc1 = getFontenc(nFontencs);
|
||||
setFlags(c,nFontenc1);
|
||||
if (table.getCharType(c)==UnicodeCharacter.COMBINING) {
|
||||
return "\\text{" + getFontencCs(nFontenc1) + "{" + table.getTextChar(c) +"{}}}";
|
||||
}
|
||||
else {
|
||||
return "\\text{" + getFontencCs(nFontenc1) + "{" + table.getTextChar(c) +"}}";
|
||||
}
|
||||
}
|
||||
}
|
||||
else {
|
||||
return "\\text{" + notFound(c,nFontenc) + "}";
|
||||
}
|
||||
}
|
||||
|
||||
// Missing symbol
|
||||
private String notFound(char c,int nFontenc) {
|
||||
//String sErrorMsg = "[Warning: Missing symbol " + Integer.toHexString(c).toUpperCase() +"]";
|
||||
String sErrorMsg = "["+Integer.toHexString(c).toUpperCase() +"?]";
|
||||
if (nFontenc==T1_ENC) return sErrorMsg;
|
||||
else return "\\textlatin{"+sErrorMsg+"}";
|
||||
}
|
||||
|
||||
|
||||
// Convert a single character
|
||||
/*private String convert(char c, boolean bMathMode, String sLang){
|
||||
int nFontenc = bAlwaysUseDefaultLang ? nDefaultFontenc : getFontenc(sLang);
|
||||
if (bMathMode) {
|
||||
return convertMathChar(c,nFontenc);
|
||||
}
|
||||
else if (greekMath(c,nFontenc) || (table.hasMathChar(c) && !table.hasTextChar(c))) {
|
||||
return "$" + convertMathChar(c,nFontenc) + "$";
|
||||
}
|
||||
else if (table.hasTextChar(c)) {
|
||||
int nFontencs = table.getFontencs(c);
|
||||
if (supportsFontenc(nFontencs,nFontenc)) {
|
||||
// The text character is valid in the current font encoding
|
||||
setFlags(c,nFontenc);
|
||||
if (table.getCharType(c)==UnicodeCharacter.COMBINING) {
|
||||
return table.getTextChar(c)+"{}";
|
||||
}
|
||||
else {
|
||||
return table.getTextChar(c);
|
||||
}
|
||||
}
|
||||
else {
|
||||
// The text character is valid in another font encoding
|
||||
int nFontenc1 = getFontenc(nFontencs);
|
||||
setFlags(c,nFontenc1);
|
||||
if (table.getCharType(c)==UnicodeCharacter.COMBINING) {
|
||||
return getFontencCs(nFontenc1) + "{" + table.getTextChar(c) +"{}}";
|
||||
}
|
||||
else {
|
||||
return getFontencCs(nFontenc1) + "{" + table.getTextChar(c) +"}";
|
||||
}
|
||||
}
|
||||
}
|
||||
else {
|
||||
return notFound(c,nFontenc);
|
||||
}
|
||||
}*/
|
||||
|
||||
|
||||
|
||||
// **** Languages ****
|
||||
|
||||
// Convert iso language to babel language
|
||||
// todo: include iso country
|
||||
// todo: support automatic choice of inputenc (see comments)?
|
||||
private String getBabelLanguage(String sLang) {
|
||||
if (babelLanguages.containsKey(sLang)) {
|
||||
return (String) babelLanguages.get(sLang);
|
||||
}
|
||||
else {
|
||||
return "english"; // interpret unknown languages as English
|
||||
}
|
||||
}
|
||||
|
||||
private void prepareBabelLanguages() {
|
||||
babelLanguages = new Hashtable();
|
||||
babelLanguages.put("en", "english"); // latin1
|
||||
babelLanguages.put("bg", "bulgarian"); // cp1251?
|
||||
babelLanguages.put("cs", "czech"); // latin2
|
||||
babelLanguages.put("da", "danish"); // latin1
|
||||
babelLanguages.put("de", "ngerman"); // latin1
|
||||
babelLanguages.put("el", "greek"); // iso-8859-7
|
||||
babelLanguages.put("es", "spanish"); // latin1
|
||||
babelLanguages.put("fi", "finnish"); // latin1 (latin9?)
|
||||
babelLanguages.put("fr", "french"); // latin1 (latin9?)
|
||||
babelLanguages.put("ga", "irish"); // latin1
|
||||
babelLanguages.put("hr", "croatian"); // latin2
|
||||
babelLanguages.put("hu", "magyar"); // latin2
|
||||
babelLanguages.put("la", "latin"); // ascii
|
||||
babelLanguages.put("is", "icelandic"); // latin1
|
||||
babelLanguages.put("it", "italian"); // latin1
|
||||
babelLanguages.put("nl", "dutch"); // latin1
|
||||
babelLanguages.put("no", "norsk"); // latin1
|
||||
babelLanguages.put("pl", "polish"); // latin2
|
||||
babelLanguages.put("pt", "portuges"); // latin1
|
||||
babelLanguages.put("ro", "romanian"); // latin2
|
||||
babelLanguages.put("ru", "russian"); // cp1251?
|
||||
babelLanguages.put("sk", "slovak"); // latin2
|
||||
babelLanguages.put("sl", "slovene"); // latin2
|
||||
babelLanguages.put("sr", "serbian"); // cp1251?
|
||||
babelLanguages.put("sv", "swedish"); // latin1
|
||||
babelLanguages.put("tr", "turkish");
|
||||
babelLanguages.put("uk", "ukrainian"); // cp1251?
|
||||
}
|
||||
|
||||
// **** Helpers to collect various information ****
|
||||
|
||||
// Did we use cyrillic?
|
||||
private boolean cyrillic() { return bT2A; }
|
||||
|
||||
// Did we use greek?
|
||||
private boolean greek() { return bGreek; }
|
||||
|
||||
// Did we use polytonic greek?
|
||||
private boolean polytonicGreek() { return bPolytonicGreek; }
|
||||
|
||||
// Outside greek text, greek letters may be rendered in math mode,
|
||||
// if the user requires that in the configuration.
|
||||
private boolean greekMath(char c, int nFontenc) {
|
||||
return bGreekMath && nFontenc!=LGR_ENC && table.getFontencs(c)==LGR_ENC;
|
||||
}
|
||||
|
||||
// Set cyrillic and greek flags
|
||||
private void setFlags(char c, int nFontenc) {
|
||||
if ((c>='\u1F00') && (c<='\u1FFF')) bPolytonicGreek = true;
|
||||
if (nFontenc==LGR_ENC) bGreek = true;
|
||||
if (nFontenc==T2A_ENC) bT2A = true;
|
||||
}
|
||||
|
||||
}
|
118
source/java/writer2latex/latex/i18n/I18n.java
Normal file
118
source/java/writer2latex/latex/i18n/I18n.java
Normal file
|
@ -0,0 +1,118 @@
|
|||
/************************************************************************
|
||||
*
|
||||
* I18n.java
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License version 2.1, as published by the Free Software Foundation.
|
||||
*
|
||||
* This library 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
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston,
|
||||
* MA 02111-1307 USA
|
||||
*
|
||||
* Copyright: 2002-2009 by Henrik Just
|
||||
*
|
||||
* All Rights Reserved.
|
||||
*
|
||||
* Version 1.0 (2009-02-16)
|
||||
*
|
||||
*/
|
||||
|
||||
package writer2latex.latex.i18n;
|
||||
|
||||
import java.util.HashSet;
|
||||
|
||||
import writer2latex.office.*;
|
||||
import writer2latex.latex.LaTeXConfig;
|
||||
import writer2latex.latex.LaTeXDocumentPortion;
|
||||
import writer2latex.latex.ConverterPalette;
|
||||
import writer2latex.latex.util.BeforeAfter;
|
||||
|
||||
/** This abstract class takes care of i18n in the LaTeX export.
|
||||
* Since i18n is handled quite differently in LaTeX "Classic"
|
||||
* and XeTeX, we use two different classes
|
||||
*/
|
||||
public abstract class I18n {
|
||||
// **** Global variables ****
|
||||
|
||||
// Configuration items
|
||||
protected LaTeXConfig config;
|
||||
protected ReplacementTrie stringReplace;
|
||||
protected boolean bGreekMath; // Use math mode for greek letters
|
||||
protected boolean bAlwaysUseDefaultLang; // Ignore sLang parameter to convert()
|
||||
|
||||
// Collected data
|
||||
protected String sDefaultLanguage; // The default iso language to use
|
||||
protected HashSet languages = new HashSet(); // All languages used
|
||||
|
||||
// **** Constructors ****
|
||||
|
||||
/** Construct a new I18n as ConverterHelper
|
||||
* @param ofr the OfficeReader to get language information from
|
||||
* @param config the configuration which determines the symbols to use
|
||||
* @param palette the ConverterPalette (unused)
|
||||
*/
|
||||
public I18n(OfficeReader ofr, LaTeXConfig config, ConverterPalette palette) {
|
||||
// We don't need the palette and the office reader is only used to
|
||||
// identify the default language
|
||||
|
||||
// Set up config items
|
||||
this.config = config;
|
||||
stringReplace = config.getStringReplace();
|
||||
bGreekMath = config.greekMath();
|
||||
bAlwaysUseDefaultLang = !config.multilingual();
|
||||
|
||||
// Default language
|
||||
if (ofr!=null) {
|
||||
if (config.multilingual()) {
|
||||
// Read the default language from the default paragraph style
|
||||
StyleWithProperties style = ofr.getDefaultParStyle();
|
||||
if (style!=null) {
|
||||
sDefaultLanguage = style.getProperty(XMLString.FO_LANGUAGE);
|
||||
}
|
||||
}
|
||||
else {
|
||||
// the most common language is the only language
|
||||
sDefaultLanguage = ofr.getMajorityLanguage();
|
||||
}
|
||||
}
|
||||
if (sDefaultLanguage==null) { sDefaultLanguage="en"; }
|
||||
}
|
||||
|
||||
/** Add declarations to the preamble to load the required packages
|
||||
* @param pack usepackage declarations
|
||||
* @param decl other declarations
|
||||
*/
|
||||
public abstract void appendDeclarations(LaTeXDocumentPortion pack, LaTeXDocumentPortion decl);
|
||||
|
||||
/** Apply a language language
|
||||
* @param style the OOo style to read attributesfrom
|
||||
* @param bDecl true if declaration form is required
|
||||
* @param bInherit true if inherited properties should be used
|
||||
* @param ba the <code>BeforeAfter</code> to add LaTeX code to.
|
||||
*/
|
||||
public abstract void applyLanguage(StyleWithProperties style, boolean bDecl, boolean bInherit, BeforeAfter ba);
|
||||
|
||||
/** Push a font to the font stack
|
||||
* @param sName the name of the font
|
||||
*/
|
||||
public abstract void pushSpecialTable(String sName);
|
||||
|
||||
/** Pop a font from the font stack
|
||||
*/
|
||||
public abstract void popSpecialTable();
|
||||
|
||||
/** Convert a string of characters into LaTeX
|
||||
* @param s the source string
|
||||
* @param bMathMode true if the string should be rendered in math mode
|
||||
* @param sLang the iso language of the string
|
||||
* @return the LaTeX string
|
||||
*/
|
||||
public abstract String convert(String s, boolean bMathMode, String sLang);
|
||||
}
|
16
source/java/writer2latex/latex/i18n/Package.html
Normal file
16
source/java/writer2latex/latex/i18n/Package.html
Normal file
|
@ -0,0 +1,16 @@
|
|||
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
|
||||
|
||||
<html>
|
||||
<head>
|
||||
<title>The package writer2latex.xhtml.i18n</title>
|
||||
</head>
|
||||
|
||||
<body>
|
||||
<p>This package takes care of i18n for LaTeX.</p>
|
||||
<p>In LaTeX, i18n is a mixture of inputencodings, fontencodings
|
||||
and babel languages. In particualar, the package provides a Unicode->LaTeX
|
||||
translation that can handle different inputencodings and fontencodings.</p>
|
||||
<p>The pacakge could (with modification) in theory be used in other programs
|
||||
that convert unicode to LaTeX.</p>
|
||||
</body>
|
||||
</html>
|
56
source/java/writer2latex/latex/i18n/ReplacementTrie.java
Normal file
56
source/java/writer2latex/latex/i18n/ReplacementTrie.java
Normal file
|
@ -0,0 +1,56 @@
|
|||
/************************************************************************
|
||||
*
|
||||
* ReplacementTrie.java
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License version 2.1, as published by the Free Software Foundation.
|
||||
*
|
||||
* This library 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
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston,
|
||||
* MA 02111-1307 USA
|
||||
*
|
||||
* Copyright: 2002-2006 by Henrik Just
|
||||
*
|
||||
* All Rights Reserved.
|
||||
*
|
||||
* Version 0.5 (2006-11-02)
|
||||
*
|
||||
*/
|
||||
|
||||
package writer2latex.latex.i18n;
|
||||
|
||||
/** This class contains a trie of string -> LaTeX code replacements
|
||||
*/
|
||||
public class ReplacementTrie extends ReplacementTrieNode {
|
||||
|
||||
public ReplacementTrie() {
|
||||
super('*',0);
|
||||
}
|
||||
|
||||
public ReplacementTrieNode get(String sInput) {
|
||||
return get(sInput,0,sInput.length());
|
||||
}
|
||||
|
||||
public ReplacementTrieNode get(String sInput, int nStart, int nEnd) {
|
||||
if (sInput.length()==0) { return null; }
|
||||
else { return super.get(sInput,nStart,nEnd); }
|
||||
}
|
||||
|
||||
public void put(String sInput, String sLaTeXCode, int nFontencs) {
|
||||
if (sInput.length()==0) { return; }
|
||||
else { super.put(sInput,sLaTeXCode,nFontencs); }
|
||||
}
|
||||
|
||||
public String[] getInputStrings() {
|
||||
return null; //TODO
|
||||
}
|
||||
|
||||
|
||||
}
|
127
source/java/writer2latex/latex/i18n/ReplacementTrieNode.java
Normal file
127
source/java/writer2latex/latex/i18n/ReplacementTrieNode.java
Normal file
|
@ -0,0 +1,127 @@
|
|||
/************************************************************************
|
||||
*
|
||||
* ReplacementTrieNode.java
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License version 2.1, as published by the Free Software Foundation.
|
||||
*
|
||||
* This library 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
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston,
|
||||
* MA 02111-1307 USA
|
||||
*
|
||||
* Copyright: 2002-2006 by Henrik Just
|
||||
*
|
||||
* All Rights Reserved.
|
||||
*
|
||||
* Version 0.5 (2006-11-02)
|
||||
*
|
||||
*/
|
||||
|
||||
package writer2latex.latex.i18n;
|
||||
|
||||
/** This class contains a node in a trie of string -> LaTeX code replacements
|
||||
*/
|
||||
public class ReplacementTrieNode {
|
||||
|
||||
private char cLetter;
|
||||
private int nInputLength;
|
||||
private String sLaTeXCode = null;
|
||||
private int nFontencs = 0;
|
||||
private ReplacementTrieNode son = null;
|
||||
private ReplacementTrieNode brother = null;
|
||||
|
||||
public ReplacementTrieNode(char cLetter, int nInputLength) {
|
||||
this.cLetter = cLetter;
|
||||
this.nInputLength = nInputLength;
|
||||
}
|
||||
|
||||
public char getLetter() { return this.cLetter; }
|
||||
|
||||
public int getInputLength() { return this.nInputLength; }
|
||||
|
||||
public String getLaTeXCode() { return this.sLaTeXCode; }
|
||||
|
||||
public int getFontencs() { return this.nFontencs; }
|
||||
|
||||
protected void setLaTeXCode(String sLaTeXCode) {
|
||||
this.sLaTeXCode = sLaTeXCode;
|
||||
}
|
||||
|
||||
protected void setFontencs(int nFontencs) {
|
||||
this.nFontencs = nFontencs;
|
||||
}
|
||||
|
||||
protected ReplacementTrieNode getFirstChild() {
|
||||
return this.son;
|
||||
}
|
||||
|
||||
protected ReplacementTrieNode getNextSibling() {
|
||||
return this.brother;
|
||||
}
|
||||
|
||||
protected ReplacementTrieNode getChildByLetter(char cLetter) {
|
||||
ReplacementTrieNode child = this.getFirstChild();
|
||||
while (child!=null) {
|
||||
if (cLetter==child.getLetter()) { return child; }
|
||||
child = child.getNextSibling();
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
protected void appendChild(ReplacementTrieNode node) {
|
||||
if (son==null) { son = node; }
|
||||
else { son.appendSibling(node); }
|
||||
}
|
||||
|
||||
protected void appendSibling(ReplacementTrieNode node) {
|
||||
if (brother==null) { brother = node; }
|
||||
else { brother.appendSibling(node); }
|
||||
}
|
||||
|
||||
protected ReplacementTrieNode get(String sInput, int nStart, int nEnd) {
|
||||
if (nStart>=nEnd) { return null; }
|
||||
char c = sInput.charAt(nStart);
|
||||
ReplacementTrieNode child = this.getFirstChild();
|
||||
while (child!=null) {
|
||||
if (child.getLetter()==c) {
|
||||
if (child.getLaTeXCode()!=null) { return child; }
|
||||
else { return child.get(sInput,nStart+1,nEnd); }
|
||||
}
|
||||
child = child.getNextSibling();
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
protected void put(String sInput, String sLaTeXCode, int nFontencs) {
|
||||
char c = sInput.charAt(0);
|
||||
ReplacementTrieNode child = this.getChildByLetter(c);
|
||||
if (child==null) {
|
||||
child = new ReplacementTrieNode(c,this.getInputLength()+1);
|
||||
this.appendChild(child);
|
||||
}
|
||||
if (sInput.length()>1) {
|
||||
child.put(sInput.substring(1),sLaTeXCode,nFontencs);
|
||||
}
|
||||
else {
|
||||
child.setLaTeXCode(sLaTeXCode);
|
||||
child.setFontencs(nFontencs);
|
||||
}
|
||||
}
|
||||
|
||||
public String toString() {
|
||||
String s = Character.toString(cLetter);
|
||||
if (brother!=null) { s+=brother.toString(); }
|
||||
if (son!=null) { s+="\nInputLength "+(nInputLength+1)+", "+son.toString(); }
|
||||
else { s+="\n"; }
|
||||
return s;
|
||||
}
|
||||
|
||||
|
||||
}
|
52
source/java/writer2latex/latex/i18n/UnicodeCharacter.java
Normal file
52
source/java/writer2latex/latex/i18n/UnicodeCharacter.java
Normal file
|
@ -0,0 +1,52 @@
|
|||
/************************************************************************
|
||||
*
|
||||
* UnicodeCharacter.java
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License version 2.1, as published by the Free Software Foundation.
|
||||
*
|
||||
* This library 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
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston,
|
||||
* MA 02111-1307 USA
|
||||
*
|
||||
* Copyright: 2002-2007 by Henrik Just
|
||||
*
|
||||
* All Rights Reserved.
|
||||
*
|
||||
* Version 0.5 (2007-07-24)
|
||||
*
|
||||
*/
|
||||
|
||||
package writer2latex.latex.i18n;
|
||||
|
||||
// Helper class: A struct to hold the LaTeX representations of a unicode character
|
||||
class UnicodeCharacter implements Cloneable {
|
||||
final static int NORMAL = 0; // this is a normal character
|
||||
final static int COMBINING = 1; // this character should be ignored
|
||||
final static int IGNORE = 2; // this is a combining character
|
||||
final static int UNKNOWN = 3; // this character is unknown
|
||||
|
||||
int nType; // The type of character
|
||||
String sMath; // LaTeX representation in math mode
|
||||
String sText; // LaTeX representation in text mode
|
||||
int nFontencs; // Valid font encoding(s) for the text mode representation
|
||||
boolean bDashes; // This character is represented by dashes (-,--,---)
|
||||
|
||||
protected Object clone() {
|
||||
UnicodeCharacter uc = new UnicodeCharacter();
|
||||
uc.nType = this.nType;
|
||||
uc.sMath = this.sMath;
|
||||
uc.sText = this.sText;
|
||||
uc.nFontencs = this.nFontencs;
|
||||
uc.bDashes = this.bDashes;
|
||||
return uc;
|
||||
}
|
||||
}
|
||||
|
43
source/java/writer2latex/latex/i18n/UnicodeRow.java
Normal file
43
source/java/writer2latex/latex/i18n/UnicodeRow.java
Normal file
|
@ -0,0 +1,43 @@
|
|||
/************************************************************************
|
||||
*
|
||||
* UnicodeRow.java
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License version 2.1, as published by the Free Software Foundation.
|
||||
*
|
||||
* This library 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
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston,
|
||||
* MA 02111-1307 USA
|
||||
*
|
||||
* Copyright: 2002-2007 by Henrik Just
|
||||
*
|
||||
* All Rights Reserved.
|
||||
*
|
||||
* Version 0.5 (2007-07-24)
|
||||
*
|
||||
*/
|
||||
|
||||
package writer2latex.latex.i18n;
|
||||
|
||||
// Helper class: A row of 256 unicode characters
|
||||
class UnicodeRow implements Cloneable {
|
||||
UnicodeCharacter[] entries;
|
||||
UnicodeRow(){ entries=new UnicodeCharacter[256]; }
|
||||
|
||||
protected Object clone() {
|
||||
UnicodeRow ur = new UnicodeRow();
|
||||
for (int i=0; i<256; i++) {
|
||||
if (this.entries[i]!=null) {
|
||||
ur.entries[i] = (UnicodeCharacter) this.entries[i].clone();
|
||||
}
|
||||
}
|
||||
return ur;
|
||||
}
|
||||
}
|
79
source/java/writer2latex/latex/i18n/UnicodeStringParser.java
Normal file
79
source/java/writer2latex/latex/i18n/UnicodeStringParser.java
Normal file
|
@ -0,0 +1,79 @@
|
|||
/************************************************************************
|
||||
*
|
||||
* UnicodeStringParser.java
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License version 2.1, as published by the Free Software Foundation.
|
||||
*
|
||||
* This library 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
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston,
|
||||
* MA 02111-1307 USA
|
||||
*
|
||||
* Copyright: 2002-2007 by Henrik Just
|
||||
*
|
||||
* All Rights Reserved.
|
||||
*
|
||||
* Version 0.5 (2007-07-24)
|
||||
*
|
||||
*/
|
||||
|
||||
package writer2latex.latex.i18n;
|
||||
|
||||
// Helper class: Parse a unicode string.
|
||||
// Note: Some 8-bit fonts have additional "spacer" characters that are used
|
||||
// for manual placement of accents. These are ignored between the base character
|
||||
// and the combining character, thus we are parsing according to the rule
|
||||
// <base char> <spacer char>* <combining char>?
|
||||
class UnicodeStringParser {
|
||||
private UnicodeTable table; // the table to use
|
||||
private String s; // the string
|
||||
private int i; // the current index
|
||||
private int nEnd; // the maximal index
|
||||
private char c; // the current character
|
||||
private char cc; // the current combining character
|
||||
|
||||
protected void reset(UnicodeTable table, String s, int i, int nEnd) {
|
||||
this.table=table;
|
||||
this.s=s;
|
||||
this.i=i;
|
||||
this.nEnd=nEnd;
|
||||
}
|
||||
|
||||
protected boolean next() {
|
||||
if (i>=nEnd) { return false; }
|
||||
// Pick up base character
|
||||
c = s.charAt(i++);
|
||||
if (table.getCharType(c)==UnicodeCharacter.COMBINING) {
|
||||
// Lonely combining character - combine with space
|
||||
cc = c;
|
||||
c = ' ';
|
||||
return true;
|
||||
}
|
||||
|
||||
// Skip characters that should be ignored
|
||||
while (i<s.length() && table.getCharType(s.charAt(i))==UnicodeCharacter.IGNORE) { i++; }
|
||||
// Pick up combining character, if any
|
||||
if (i<s.length() && table.getCharType(s.charAt(i))==UnicodeCharacter.COMBINING) {
|
||||
cc = s.charAt(i++);
|
||||
}
|
||||
else {
|
||||
cc = '\u0000';
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
protected char getChar() { return c; }
|
||||
|
||||
protected boolean hasCombiningChar() { return cc!='\u0000'; }
|
||||
|
||||
protected char getCombiningChar() { return cc; }
|
||||
|
||||
}
|
169
source/java/writer2latex/latex/i18n/UnicodeTable.java
Normal file
169
source/java/writer2latex/latex/i18n/UnicodeTable.java
Normal file
|
@ -0,0 +1,169 @@
|
|||
/************************************************************************
|
||||
*
|
||||
* UnicodeTable.java
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License version 2.1, as published by the Free Software Foundation.
|
||||
*
|
||||
* This library 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
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston,
|
||||
* MA 02111-1307 USA
|
||||
*
|
||||
* Copyright: 2002-2007 by Henrik Just
|
||||
*
|
||||
* All Rights Reserved.
|
||||
*
|
||||
* Version 0.5 (2007-07-24)
|
||||
*
|
||||
*/
|
||||
|
||||
package writer2latex.latex.i18n;
|
||||
|
||||
// Helper class: Table of up to 65536 unicode characters
|
||||
class UnicodeTable {
|
||||
protected UnicodeRow[] table=new UnicodeRow[256];
|
||||
private UnicodeTable parent;
|
||||
|
||||
// Constructor; creates a new table, possibly based on a parent
|
||||
// Note: The parent must be fully loaded before the child is created.
|
||||
public UnicodeTable(UnicodeTable parent){
|
||||
this.parent = parent;
|
||||
if (parent!=null) {
|
||||
// *Copy* the rows from the parent
|
||||
for (int i=0; i<256; i++) {
|
||||
table[i] = parent.table[i];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Make sure the required entry exists
|
||||
private void createEntry(int nRow, int nCol) {
|
||||
if (table[nRow]==null) {
|
||||
table[nRow]=new UnicodeRow();
|
||||
}
|
||||
else if (parent!=null && table[nRow]==parent.table[nRow]) {
|
||||
// Before changing a row it must be *cloned*
|
||||
table[nRow] = (UnicodeRow) parent.table[nRow].clone();
|
||||
}
|
||||
if (table[nRow].entries[nCol]==null) {
|
||||
table[nRow].entries[nCol]=new UnicodeCharacter();
|
||||
}
|
||||
}
|
||||
|
||||
// Addd a single character (type only), by number
|
||||
protected void addCharType(char c, int nType) {
|
||||
int nRow=c/256; int nCol=c%256;
|
||||
createEntry(nRow,nCol);
|
||||
table[nRow].entries[nCol].nType = nType;
|
||||
}
|
||||
|
||||
// Addd a single character (type only), by name
|
||||
protected void addCharType(char c, String sType) {
|
||||
int nRow=c/256; int nCol=c%256;
|
||||
createEntry(nRow,nCol);
|
||||
if ("combining".equals(sType)) {
|
||||
table[nRow].entries[nCol].nType = UnicodeCharacter.COMBINING;
|
||||
}
|
||||
else if ("ignore".equals(sType)) {
|
||||
table[nRow].entries[nCol].nType = UnicodeCharacter.IGNORE;
|
||||
}
|
||||
else {
|
||||
table[nRow].entries[nCol].nType = UnicodeCharacter.NORMAL;
|
||||
}
|
||||
}
|
||||
|
||||
// Add a single math character to the table
|
||||
protected void addMathChar(char c, String sLaTeX){
|
||||
int nRow=c/256; int nCol=c%256;
|
||||
createEntry(nRow,nCol);
|
||||
table[nRow].entries[nCol].sMath=sLaTeX;
|
||||
}
|
||||
|
||||
// Add a single text character to the table
|
||||
protected void addTextChar(char c, String sLaTeX, int nFontencs, boolean bDashes){
|
||||
int nRow=c/256; int nCol=c%256;
|
||||
createEntry(nRow,nCol);
|
||||
table[nRow].entries[nCol].sText=sLaTeX;
|
||||
table[nRow].entries[nCol].nFontencs=nFontencs;
|
||||
table[nRow].entries[nCol].bDashes=bDashes;
|
||||
}
|
||||
|
||||
// Retrieve entry for a character (or null)
|
||||
private UnicodeCharacter getEntry(char c) {
|
||||
int nRow=c/256; int nCol=c%256;
|
||||
if (table[nRow]==null) return null;
|
||||
return table[nRow].entries[nCol];
|
||||
}
|
||||
|
||||
// Get character type
|
||||
public int getCharType(char c) {
|
||||
UnicodeCharacter entry = getEntry(c);
|
||||
if (entry==null) return UnicodeCharacter.UNKNOWN;
|
||||
return entry.nType;
|
||||
}
|
||||
|
||||
// Check to see if this math character exists?
|
||||
public boolean hasMathChar(char c) {
|
||||
UnicodeCharacter entry = getEntry(c);
|
||||
if (entry==null) return false;
|
||||
return entry.sMath!=null;
|
||||
}
|
||||
|
||||
// Get math character (or null)
|
||||
public String getMathChar(char c) {
|
||||
UnicodeCharacter entry = getEntry(c);
|
||||
if (entry==null) return null;
|
||||
return entry.sMath;
|
||||
}
|
||||
|
||||
// Check to see if this text character exists?
|
||||
public boolean hasTextChar(char c) {
|
||||
UnicodeCharacter entry = getEntry(c);
|
||||
if (entry==null) return false;
|
||||
return entry.sText!=null;
|
||||
}
|
||||
|
||||
// Get text character (or null)
|
||||
public String getTextChar(char c) {
|
||||
UnicodeCharacter entry = getEntry(c);
|
||||
if (entry==null) return null;
|
||||
return entry.sText;
|
||||
}
|
||||
|
||||
// Get font encoding(s) for text character (or 0)
|
||||
public int getFontencs(char c) {
|
||||
UnicodeCharacter entry = getEntry(c);
|
||||
if (entry==null) return 0;
|
||||
return entry.nFontencs;
|
||||
}
|
||||
|
||||
// Get dashes for text character
|
||||
public boolean isDashes(char c) {
|
||||
UnicodeCharacter entry = getEntry(c);
|
||||
if (entry==null) return false;
|
||||
return entry.bDashes;
|
||||
}
|
||||
|
||||
// Get number of defined characters
|
||||
public int getCharCount() {
|
||||
int nCount = 0;
|
||||
for (int nRow=0; nRow<256; nRow++) {
|
||||
if (table[nRow]!=null) {
|
||||
for (int nCol=0; nCol<256; nCol++) {
|
||||
UnicodeCharacter entry = table[nRow].entries[nCol];
|
||||
if (entry!=null) nCount++;
|
||||
}
|
||||
}
|
||||
}
|
||||
return nCount;
|
||||
}
|
||||
|
||||
}
|
||||
|
166
source/java/writer2latex/latex/i18n/UnicodeTableHandler.java
Normal file
166
source/java/writer2latex/latex/i18n/UnicodeTableHandler.java
Normal file
|
@ -0,0 +1,166 @@
|
|||
/************************************************************************
|
||||
*
|
||||
* UnicodeTableHandler.java
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License version 2.1, as published by the Free Software Foundation.
|
||||
*
|
||||
* This library 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
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston,
|
||||
* MA 02111-1307 USA
|
||||
*
|
||||
* Copyright: 2002-2009 by Henrik Just
|
||||
*
|
||||
* All Rights Reserved.
|
||||
*
|
||||
* Version 1.0 (2009-02-17)
|
||||
*
|
||||
*/
|
||||
|
||||
package writer2latex.latex.i18n;
|
||||
|
||||
import java.util.Hashtable;
|
||||
|
||||
import org.xml.sax.Attributes;
|
||||
import org.xml.sax.helpers.DefaultHandler;
|
||||
|
||||
// Helper classs: SAX handler to parse symbols.xml from jar
|
||||
class UnicodeTableHandler extends DefaultHandler{
|
||||
private Hashtable tableSet; // collection of all tables
|
||||
private UnicodeTable table; // the current table
|
||||
private String sSymbolSets;
|
||||
private boolean bGlobalReadThisSet;
|
||||
private boolean bReadThisSet;
|
||||
private int nGlobalFontencs = 0; // The global fontencodings for current symbol set
|
||||
private int nFontencs = 0; // The currently active fontencodings
|
||||
private boolean b8bit = false;
|
||||
|
||||
UnicodeTableHandler(Hashtable tableSet, String sSymbolSets){
|
||||
this.sSymbolSets = sSymbolSets;
|
||||
this.tableSet = tableSet;
|
||||
}
|
||||
|
||||
public void startElement(String nameSpace, String localName, String qName, Attributes attributes){
|
||||
if (qName.equals("symbols")) {
|
||||
//root element - create root table!
|
||||
table = new UnicodeTable(null);
|
||||
tableSet.put("root",table);
|
||||
}
|
||||
else if (qName.equals("symbol-set")) {
|
||||
// start a new symbol set; maybe we want to include it?
|
||||
bGlobalReadThisSet = sSymbolSets.indexOf(attributes.getValue("name")) >= 0;
|
||||
bReadThisSet = bGlobalReadThisSet;
|
||||
// Change global and current fontencodings
|
||||
nGlobalFontencs = ClassicI18n.readFontencs(attributes.getValue("fontenc"));
|
||||
nFontencs = nGlobalFontencs;
|
||||
}
|
||||
else if (qName.equals("special-symbol-set")) {
|
||||
// start a new special symbol set; this requires a new table
|
||||
table = new UnicodeTable((UnicodeTable) tableSet.get("root"));
|
||||
tableSet.put(attributes.getValue("name"),table);
|
||||
|
||||
// Read it if it requires nothing, or something we read
|
||||
bGlobalReadThisSet = attributes.getValue("requires")==null ||
|
||||
sSymbolSets.indexOf(attributes.getValue("requires")) >= 0;
|
||||
bReadThisSet = bGlobalReadThisSet;
|
||||
b8bit = "true".equals(attributes.getValue("eight-bit"));
|
||||
// Change global and current fontencodings
|
||||
nGlobalFontencs = ClassicI18n.readFontencs(attributes.getValue("fontenc"));
|
||||
nFontencs = nGlobalFontencs;
|
||||
}
|
||||
else if (qName.equals("symbol-subset")) {
|
||||
// Do we requires something here?
|
||||
if (attributes.getValue("requires")!=null) {
|
||||
bReadThisSet = sSymbolSets.indexOf(attributes.getValue("requires")) >= 0;
|
||||
}
|
||||
// Change current fontencodings
|
||||
nFontencs = ClassicI18n.readFontencs(attributes.getValue("fontenc"));
|
||||
}
|
||||
else if (qName.equals("symbol")) {
|
||||
if (bReadThisSet) {
|
||||
char c=(char)Integer.parseInt(attributes.getValue("char"),16);
|
||||
String sEqChar=attributes.getValue("eq-char");
|
||||
if (sEqChar!=null) { // copy existing definitions, if any
|
||||
char eqc = (char)Integer.parseInt(sEqChar,16);
|
||||
if (table.getCharType(eqc)!=UnicodeCharacter.UNKNOWN) {
|
||||
table.addCharType(c,table.getCharType(eqc));
|
||||
}
|
||||
if (table.hasMathChar(eqc)) {
|
||||
table.addMathChar(c,table.getMathChar(eqc));
|
||||
}
|
||||
if (table.hasTextChar(eqc)) {
|
||||
table.addTextChar(c,table.getTextChar(eqc),table.getFontencs(eqc),table.isDashes(eqc));
|
||||
}
|
||||
}
|
||||
else {
|
||||
String sType=attributes.getValue("char-type");
|
||||
String sMath=attributes.getValue("math");
|
||||
String sText=attributes.getValue("text");
|
||||
boolean bDashes="true".equals(attributes.getValue("dashes"));
|
||||
if (sType!=null) table.addCharType(c,sType);
|
||||
if (sMath!=null) table.addMathChar(c,sMath);
|
||||
if (sText!=null) table.addTextChar(c,sText,nFontencs,bDashes);
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (qName.equals("preserve-symbol")) {
|
||||
if (bReadThisSet) {
|
||||
String sMode=attributes.getValue("mode");
|
||||
char c=(char)Integer.parseInt(attributes.getValue("char"),16);
|
||||
table.addCharType(c,attributes.getValue("char-type"));
|
||||
if ("math".equals(sMode) || "both".equals(sMode)) {
|
||||
table.addMathChar(c,Character.toString(c));
|
||||
}
|
||||
if ("text".equals(sMode) || "both".equals(sMode)) {
|
||||
table.addTextChar(c,Character.toString(c),nFontencs,false);
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (qName.equals("preserve-symbols")) {
|
||||
if (bReadThisSet) {
|
||||
String sMode=attributes.getValue("mode");
|
||||
String sType=attributes.getValue("char-type");
|
||||
char c1=(char)Integer.parseInt(attributes.getValue("first-char"),16);
|
||||
char c2=(char)Integer.parseInt(attributes.getValue("last-char"),16);
|
||||
boolean bMath = "math".equals(sMode) || "both".equals(sMode);
|
||||
boolean bText = "text".equals(sMode) || "both".equals(sMode);
|
||||
for (char c=c1; c<=c2; c++) {
|
||||
table.addCharType(c,sType);
|
||||
if (bMath) {
|
||||
table.addMathChar(c,Character.toString(c));
|
||||
}
|
||||
if (bText) {
|
||||
table.addTextChar(c,Character.toString(c),nFontencs,false);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void endElement(String nameSpace, String localName, String qName){
|
||||
if (qName.equals("symbol-subset")) {
|
||||
// Revert to global setting of reading status
|
||||
bReadThisSet = bGlobalReadThisSet;
|
||||
// Revert to global fontencoding
|
||||
nFontencs = nGlobalFontencs;
|
||||
}
|
||||
else if (qName.equals("special-symbol-set")) {
|
||||
if (b8bit) {
|
||||
// Row 0 = Row 240 (F0)
|
||||
// Note: 8-bit fonts are supposed to be relocated to F000..F0FF
|
||||
// This may fail on import from msword, hence this hack
|
||||
table.table[0] = table.table[240];
|
||||
}
|
||||
b8bit = false;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
120
source/java/writer2latex/latex/i18n/XeTeXI18n.java
Normal file
120
source/java/writer2latex/latex/i18n/XeTeXI18n.java
Normal file
|
@ -0,0 +1,120 @@
|
|||
/************************************************************************
|
||||
*
|
||||
* XeTeXI18n.java
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License version 2.1, as published by the Free Software Foundation.
|
||||
*
|
||||
* This library 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
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston,
|
||||
* MA 02111-1307 USA
|
||||
*
|
||||
* Copyright: 2002-2009 by Henrik Just
|
||||
*
|
||||
* All Rights Reserved.
|
||||
*
|
||||
* Version 1.0 (2009-02-17)
|
||||
*
|
||||
*/
|
||||
|
||||
package writer2latex.latex.i18n;
|
||||
|
||||
import writer2latex.office.*;
|
||||
import writer2latex.latex.LaTeXConfig;
|
||||
import writer2latex.latex.LaTeXDocumentPortion;
|
||||
import writer2latex.latex.ConverterPalette;
|
||||
import writer2latex.latex.util.BeforeAfter;
|
||||
|
||||
/** This class takes care of i18n in XeLaTeX
|
||||
*/
|
||||
public class XeTeXI18n extends I18n {
|
||||
|
||||
// **** Constructors ****
|
||||
|
||||
/** Construct a new XeTeXI18n as ConverterHelper
|
||||
* @param ofr the OfficeReader to get language information from
|
||||
* @param config the configuration which determines the symbols to use
|
||||
* @param palette the ConverterPalette (unused)
|
||||
*/
|
||||
public XeTeXI18n(OfficeReader ofr, LaTeXConfig config, ConverterPalette palette) {
|
||||
super(ofr,config,palette);
|
||||
}
|
||||
|
||||
/** Add declarations to the preamble to load the required packages
|
||||
* @param pack usepackage declarations
|
||||
* @param decl other declarations
|
||||
*/
|
||||
public void appendDeclarations(LaTeXDocumentPortion pack, LaTeXDocumentPortion decl) {
|
||||
pack.append("\\usepackage{fontspec}").nl()
|
||||
.append("\\usepackage{xunicode}").nl()
|
||||
.append("\\usepackage{xltxtra}").nl()
|
||||
.append("\\usepackage{amsmath,amssymb,amsfonts}").nl();
|
||||
}
|
||||
|
||||
/** Apply a language language
|
||||
* @param style the OOo style to read attributesfrom
|
||||
* @param bDecl true if declaration form is required
|
||||
* @param bInherit true if inherited properties should be used
|
||||
* @param ba the <code>BeforeAfter</code> to add LaTeX code to.
|
||||
*/
|
||||
public void applyLanguage(StyleWithProperties style, boolean bDecl, boolean bInherit, BeforeAfter ba) {
|
||||
// TODO (polyglossia)
|
||||
}
|
||||
|
||||
/** Push a font to the font stack
|
||||
* @param sName the name of the font
|
||||
*/
|
||||
public void pushSpecialTable(String sName) {
|
||||
// TODO
|
||||
}
|
||||
|
||||
/** Pop a font from the font stack
|
||||
*/
|
||||
public void popSpecialTable() {
|
||||
// TODO
|
||||
}
|
||||
|
||||
/** Convert a string of characters into LaTeX
|
||||
* @param s the source string
|
||||
* @param bMathMode true if the string should be rendered in math mode
|
||||
* @param sLang the iso language of the string
|
||||
* @return the LaTeX string
|
||||
*/
|
||||
public String convert(String s, boolean bMathMode, String sLang){
|
||||
StringBuffer buf = new StringBuffer();
|
||||
int nLen = s.length();
|
||||
char c;
|
||||
for (int i=0; i<nLen; i++) {
|
||||
c = s.charAt(i);
|
||||
switch (c) {
|
||||
case '"' : buf.append("\\textquotedbl{}"); break;
|
||||
case '#' : buf.append("\\#"); break;
|
||||
case '$' : buf.append("\\$"); break;
|
||||
case '%' : buf.append("\\%"); break;
|
||||
case '&' : buf.append("\\&"); break;
|
||||
case '\'' : buf.append("\\textbackslash{}"); break;
|
||||
case '<' : buf.append("\\textless{}"); break;
|
||||
case '>' : buf.append("\\textgreater{}"); break;
|
||||
case '\\' : buf.append("\\textbackslash{}"); break;
|
||||
case '\u005e' : buf.append("\\^{}"); break;
|
||||
case '_' : buf.append("\\_"); break;
|
||||
case '\u0060' : buf.append("\\textasciigrave{}"); break;
|
||||
case '{' : buf.append("\\{"); break;
|
||||
case '|' : buf.append("\\textbar{}"); break;
|
||||
case '}' : buf.append("\\}"); break;
|
||||
case '~' : buf.append("\\~{}"); break;
|
||||
default: buf.append(c);
|
||||
}
|
||||
}
|
||||
return buf.toString();
|
||||
}
|
||||
|
||||
|
||||
}
|
3824
source/java/writer2latex/latex/i18n/symbols.xml
Normal file
3824
source/java/writer2latex/latex/i18n/symbols.xml
Normal file
File diff suppressed because it is too large
Load diff
75
source/java/writer2latex/latex/util/BeforeAfter.java
Normal file
75
source/java/writer2latex/latex/util/BeforeAfter.java
Normal file
|
@ -0,0 +1,75 @@
|
|||
/************************************************************************
|
||||
*
|
||||
* BeforeAfter.java
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License version 2.1, as published by the Free Software Foundation.
|
||||
*
|
||||
* This library 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
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston,
|
||||
* MA 02111-1307 USA
|
||||
*
|
||||
* Copyright: 2002-2008 by Henrik Just
|
||||
*
|
||||
* All Rights Reserved.
|
||||
*
|
||||
* Version 1.0 (2008-12-02)
|
||||
*
|
||||
*/
|
||||
|
||||
package writer2latex.latex.util;
|
||||
|
||||
/** Utility class to hold LaTeX code to put before/after other LaTeX code
|
||||
*/
|
||||
public class BeforeAfter {
|
||||
private String sBefore="";
|
||||
private String sAfter="";
|
||||
|
||||
/** Constructor to initialize the object with a pair of strings
|
||||
* @param sBefore1 LaTeX code to put before
|
||||
* @param sAfter1 LaTeX code to put after
|
||||
*/
|
||||
public BeforeAfter(String sBefore1, String sAfter1) {
|
||||
sBefore=sBefore1; sAfter=sAfter1;
|
||||
}
|
||||
|
||||
/** Default constructor: Create with empty strings
|
||||
*/
|
||||
public BeforeAfter() { }
|
||||
|
||||
/** <p>Add data to the <code>BeforeAfter</code></p>
|
||||
* <p>The new data will be be added "inside", thus for example</p>
|
||||
* <ul><li><code>add("\textsf{","}");</code>
|
||||
* <li><code>add("\textit{","}");</code></ul>
|
||||
* <p>will create the pair <code>\textsf{\textit{</code>, <code>}}</code></p>
|
||||
*
|
||||
* @param sBefore1 LaTeX code to put before
|
||||
* @param sAfter1 LaTeX code to put after
|
||||
*/
|
||||
public void add(String sBefore1, String sAfter1) {
|
||||
sBefore+=sBefore1; sAfter=sAfter1+sAfter;
|
||||
}
|
||||
|
||||
/** Get LaTeX code to put before
|
||||
* @return then LaTeX code
|
||||
*/
|
||||
public String getBefore() { return sBefore; }
|
||||
|
||||
/** Get LaTeX code to put after
|
||||
* @return then LaTeX code
|
||||
*/
|
||||
public String getAfter() { return sAfter; }
|
||||
|
||||
/** Check if this <code>BeforeAfter</code> contains any data
|
||||
* @return true if there is data in at least one part
|
||||
*/
|
||||
public boolean isEmpty() { return sBefore.length()==0 && sAfter.length()==0; }
|
||||
|
||||
}
|
310
source/java/writer2latex/latex/util/Context.java
Normal file
310
source/java/writer2latex/latex/util/Context.java
Normal file
|
@ -0,0 +1,310 @@
|
|||
/************************************************************************
|
||||
*
|
||||
* Context.java
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License version 2.1, as published by the Free Software Foundation.
|
||||
*
|
||||
* This library 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
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston,
|
||||
* MA 02111-1307 USA
|
||||
*
|
||||
* Copyright: 2002-2007 by Henrik Just
|
||||
*
|
||||
* All Rights Reserved.
|
||||
*
|
||||
* Version 1.0 (2007-11-23)
|
||||
*
|
||||
*/
|
||||
|
||||
package writer2latex.latex.util;
|
||||
|
||||
import writer2latex.office.XMLString;
|
||||
import writer2latex.office.StyleWithProperties;
|
||||
|
||||
/** <p>LaTeX code is in general very context dependent. This class tracks the
|
||||
* current context, which is the used by the converter to create valid and
|
||||
* optimal LaTeX code.</p>
|
||||
*/
|
||||
public class Context {
|
||||
|
||||
// *** Formatting Info (current values in the source OOo document) ***
|
||||
|
||||
// Current list style
|
||||
private String sListStyleName = null;
|
||||
|
||||
// Current background color
|
||||
private String sBgColor = null;
|
||||
|
||||
// Current character formatting attributes
|
||||
private String sFontName = null;
|
||||
private String sFontStyle = null;
|
||||
private String sFontVariant = null;
|
||||
private String sFontWeight = null;
|
||||
private String sFontSize = null;
|
||||
private String sFontColor = null;
|
||||
private String sLang = null;
|
||||
private String sCountry = null;
|
||||
|
||||
// *** Structural Info (identifies contructions in the LaTeX document) ***
|
||||
|
||||
// within the header or footer of a pagestyle
|
||||
private boolean bInHeaderFooter = false;
|
||||
|
||||
// within a table cell
|
||||
private boolean bInTable = false; // any column
|
||||
private boolean bInLastTableColumn = false; // last column
|
||||
private boolean bInSimpleTable = false; // l, c or r-column
|
||||
|
||||
// within a multicols environment
|
||||
private boolean bInMulticols = false;
|
||||
|
||||
// within a list of this level
|
||||
private int nListLevel = 0;
|
||||
|
||||
// within a section command
|
||||
private boolean bInSection = false;
|
||||
|
||||
// within a caption
|
||||
private boolean bInCaption = false;
|
||||
|
||||
// within a floating figure (figure environment)
|
||||
private boolean bInFigureFloat = false;
|
||||
|
||||
// within a floating table (table envrionment)
|
||||
private boolean bInTableFloat = false;
|
||||
|
||||
// within a minipage environment
|
||||
private boolean bInFrame = false;
|
||||
|
||||
// within a \footnote or \endnote
|
||||
private boolean bInFootnote = false;
|
||||
|
||||
// in verbatim mode
|
||||
private boolean bVerbatim = false;
|
||||
|
||||
// in math mode
|
||||
private boolean bMathMode = false;
|
||||
|
||||
// *** Special Info ***
|
||||
|
||||
// Inside (inline) verbatim text, where line breaks are disallowed
|
||||
private boolean bNoLineBreaks = false;
|
||||
|
||||
// Inside a construction, where footnotes are disallowed
|
||||
private boolean bNoFootnotes = false;
|
||||
|
||||
// Inside an area, where lists are ignored
|
||||
private boolean bIgnoreLists = false;
|
||||
|
||||
// *** Accessor Methods ***
|
||||
|
||||
public void setBgColor(String sBgColor) { this.sBgColor = sBgColor; }
|
||||
|
||||
public String getBgColor() { return sBgColor; }
|
||||
|
||||
public void setListStyleName(String sListStyleName) { this.sListStyleName = sListStyleName; }
|
||||
|
||||
public String getListStyleName() { return sListStyleName; }
|
||||
|
||||
public void setFontName(String sFontName) { this.sFontName = sFontName; }
|
||||
|
||||
public String getFontName() { return sFontName; }
|
||||
|
||||
public void setFontStyle(String sFontStyle) { this.sFontStyle = sFontStyle; }
|
||||
|
||||
public String getFontStyle() { return sFontStyle; }
|
||||
|
||||
public void setFontVariant(String sFontVariant) { this.sFontVariant = sFontVariant; }
|
||||
|
||||
public String getFontVariant() { return sFontVariant; }
|
||||
|
||||
public void setFontWeight(String sFontWeight) { this.sFontWeight = sFontWeight; }
|
||||
|
||||
public String getFontWeight() { return sFontWeight; }
|
||||
|
||||
public void setFontSize(String sFontSize) { this.sFontSize = sFontSize; }
|
||||
|
||||
public String getFontSize() { return sFontSize; }
|
||||
|
||||
public void setFontColor(String sFontColor) { this.sFontColor = sFontColor; }
|
||||
|
||||
public String getFontColor() { return sFontColor; }
|
||||
|
||||
public void setLang(String sLang) { this.sLang = sLang; }
|
||||
|
||||
public String getLang() { return sLang; }
|
||||
|
||||
public void setCountry(String sCountry) { this.sCountry = sCountry; }
|
||||
|
||||
public String getCountry() { return sCountry; }
|
||||
|
||||
public void setInHeaderFooter(boolean bInHeaderFooter) {
|
||||
this.bInHeaderFooter = bInHeaderFooter;
|
||||
}
|
||||
|
||||
public boolean isInHeaderFooter() { return bInHeaderFooter; }
|
||||
|
||||
public void setInTable(boolean bInTable) { this.bInTable = bInTable; }
|
||||
|
||||
public boolean isInTable() { return bInTable; }
|
||||
|
||||
public void setInLastTableColumn(boolean bInLastTableColumn) { this.bInLastTableColumn = bInLastTableColumn; }
|
||||
|
||||
public boolean isInLastTableColumn() { return bInLastTableColumn; }
|
||||
|
||||
public void setInSimpleTable(boolean bInSimpleTable) { this.bInSimpleTable = bInSimpleTable; }
|
||||
|
||||
public boolean isInSimpleTable() { return bInSimpleTable; }
|
||||
|
||||
public void setInMulticols(boolean bInMulticols) {
|
||||
this.bInMulticols = bInMulticols;
|
||||
}
|
||||
|
||||
public boolean isInMulticols() { return bInMulticols; }
|
||||
|
||||
public void setListLevel(int nListLevel) { this.nListLevel = nListLevel; }
|
||||
|
||||
public void incListLevel() { nListLevel++; }
|
||||
|
||||
public int getListLevel() { return nListLevel; }
|
||||
|
||||
public void setInSection(boolean bInSection) { this.bInSection = bInSection; }
|
||||
|
||||
public boolean isInSection() { return bInSection; }
|
||||
|
||||
public void setInCaption(boolean bInCaption) { this.bInCaption = bInCaption; }
|
||||
|
||||
public boolean isInCaption() { return bInCaption; }
|
||||
|
||||
public void setInFigureFloat(boolean bInFigureFloat) { this.bInFigureFloat = bInFigureFloat; }
|
||||
|
||||
public boolean isInFigureFloat() { return bInFigureFloat; }
|
||||
|
||||
public void setInTableFloat(boolean bInTableFloat) { this.bInTableFloat = bInTableFloat; }
|
||||
|
||||
public boolean isInTableFloat() { return bInTableFloat; }
|
||||
|
||||
public void setInFrame(boolean bInFrame) { this.bInFrame = bInFrame; }
|
||||
|
||||
public boolean isInFrame() { return bInFrame; }
|
||||
|
||||
public void setInFootnote(boolean bInFootnote) {
|
||||
this.bInFootnote = bInFootnote;
|
||||
}
|
||||
|
||||
public boolean isInFootnote() { return bInFootnote; }
|
||||
|
||||
public void setNoFootnotes(boolean bNoFootnotes) {
|
||||
this.bNoFootnotes = bNoFootnotes;
|
||||
}
|
||||
|
||||
public boolean isNoFootnotes() { return bNoFootnotes; }
|
||||
|
||||
public void setIgnoreLists(boolean bIgnoreLists) {
|
||||
this.bIgnoreLists = bIgnoreLists;
|
||||
}
|
||||
|
||||
public boolean isIgnoreLists() { return bIgnoreLists; }
|
||||
|
||||
public void setNoLineBreaks(boolean bNoLineBreaks) {
|
||||
this.bNoLineBreaks = bNoLineBreaks;
|
||||
}
|
||||
public boolean isNoLineBreaks() { return bNoLineBreaks; }
|
||||
|
||||
public boolean isVerbatim() { return bVerbatim; }
|
||||
|
||||
public void setVerbatim(boolean bVerbatim) { this.bVerbatim = bVerbatim; }
|
||||
|
||||
public boolean isMathMode() { return bMathMode; }
|
||||
|
||||
public void setMathMode(boolean bMathMode) { this.bMathMode = bMathMode; }
|
||||
|
||||
// update context
|
||||
|
||||
public void updateFormattingFromStyle(StyleWithProperties style) {
|
||||
String s;
|
||||
|
||||
if (style==null) { return; }
|
||||
|
||||
s = style.getProperty(XMLString.STYLE_FONT_NAME);
|
||||
if (s!=null) { setFontName(s); }
|
||||
|
||||
s = style.getProperty(XMLString.FO_FONT_STYLE);
|
||||
if (s!=null) { setFontStyle(s); }
|
||||
|
||||
s = style.getProperty(XMLString.FO_FONT_VARIANT);
|
||||
if (s!=null) { setFontVariant(s); }
|
||||
|
||||
s = style.getProperty(XMLString.FO_FONT_WEIGHT);
|
||||
if (s!=null) { setFontWeight(s); }
|
||||
|
||||
s = style.getProperty(XMLString.FO_FONT_SIZE);
|
||||
if (s!=null) { setFontSize(s); }
|
||||
|
||||
s = style.getProperty(XMLString.FO_COLOR);
|
||||
if (s!=null) { setFontColor(s); }
|
||||
|
||||
s = style.getProperty(XMLString.FO_LANGUAGE);
|
||||
if (s!=null) { setLang(s); }
|
||||
|
||||
s = style.getProperty(XMLString.FO_COUNTRY);
|
||||
if (s!=null) { setCountry(s); }
|
||||
}
|
||||
|
||||
public void resetFormattingFromStyle(StyleWithProperties style) {
|
||||
setFontName(null);
|
||||
setFontStyle(null);
|
||||
setFontVariant(null);
|
||||
setFontWeight(null);
|
||||
setFontSize(null);
|
||||
setFontColor(null);
|
||||
setLang(null);
|
||||
setCountry(null);
|
||||
updateFormattingFromStyle(style);
|
||||
}
|
||||
|
||||
|
||||
// clone this Context
|
||||
public Object clone() {
|
||||
Context newContext = new Context();
|
||||
|
||||
newContext.setListStyleName(sListStyleName);
|
||||
newContext.setBgColor(sBgColor);
|
||||
newContext.setFontName(sFontName);
|
||||
newContext.setFontStyle(sFontStyle);
|
||||
newContext.setFontVariant(sFontVariant);
|
||||
newContext.setFontWeight(sFontWeight);
|
||||
newContext.setFontSize(sFontSize);
|
||||
newContext.setFontColor(sFontColor);
|
||||
newContext.setLang(sLang);
|
||||
newContext.setCountry(sCountry);
|
||||
newContext.setInHeaderFooter(bInHeaderFooter);
|
||||
newContext.setInTable(bInTable);
|
||||
newContext.setInLastTableColumn(bInLastTableColumn);
|
||||
newContext.setInSimpleTable(bInSimpleTable);
|
||||
newContext.setInMulticols(bInMulticols);
|
||||
newContext.setListLevel(nListLevel);
|
||||
newContext.setInSection(bInSection);
|
||||
newContext.setInCaption(bInCaption);
|
||||
newContext.setInFigureFloat(bInFigureFloat);
|
||||
newContext.setInTableFloat(bInTableFloat);
|
||||
newContext.setInFrame(bInFrame);
|
||||
newContext.setInFootnote(bInFootnote);
|
||||
newContext.setVerbatim(bVerbatim);
|
||||
newContext.setMathMode(bMathMode);
|
||||
newContext.setNoFootnotes(bNoFootnotes);
|
||||
newContext.setIgnoreLists(bIgnoreLists);
|
||||
newContext.setNoLineBreaks(bNoLineBreaks);
|
||||
|
||||
return newContext;
|
||||
}
|
||||
|
||||
}
|
69
source/java/writer2latex/latex/util/HeadingMap.java
Normal file
69
source/java/writer2latex/latex/util/HeadingMap.java
Normal file
|
@ -0,0 +1,69 @@
|
|||
/************************************************************************
|
||||
*
|
||||
* HeadingMap.java
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License version 2.1, as published by the Free Software Foundation.
|
||||
*
|
||||
* This library 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
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston,
|
||||
* MA 02111-1307 USA
|
||||
*
|
||||
* Copyright: 2002-2006 by Henrik Just
|
||||
*
|
||||
* All Rights Reserved.
|
||||
*
|
||||
* Version 0.5 (2006-11-02)
|
||||
*
|
||||
*/
|
||||
|
||||
package writer2latex.latex.util;
|
||||
|
||||
/** This class contains data for the mapping of OOo headings to LaTeX headings.
|
||||
A LaTeX heading is characterized by a name and a level.
|
||||
The heading is inserted with \name{...} or \name[...]{...}
|
||||
The headings are supposed to be "normal" LaTeX headings,
|
||||
ie. the names are also counter names, and the headings
|
||||
can be reformatted using \@startsection etc.
|
||||
Otherwise max-level should be zero.
|
||||
*/
|
||||
public class HeadingMap {
|
||||
private int nMaxLevel;
|
||||
private String[] sName;
|
||||
private int[] nLevel;
|
||||
|
||||
/** Constructor: Create a new HeadingMap
|
||||
@param nMaxLevel the maximal level of headings that are mapped */
|
||||
public HeadingMap(int nMaxLevel) {
|
||||
reset(nMaxLevel);
|
||||
}
|
||||
|
||||
/** Clear all data associated with this HeadingMap (in order to reuse it) */
|
||||
public void reset(int nMaxLevel) {
|
||||
this.nMaxLevel = nMaxLevel;
|
||||
sName = new String[nMaxLevel+1];
|
||||
nLevel = new int[nMaxLevel+1];
|
||||
}
|
||||
|
||||
/** Set data associated with a specific heading level */
|
||||
public void setLevelData(int nWriterLevel, String sName, int nLevel) {
|
||||
this.sName[nWriterLevel] = sName;
|
||||
this.nLevel[nWriterLevel] = nLevel;
|
||||
}
|
||||
|
||||
/** Returns the maximal Writer level associated with this HeadingMap */
|
||||
public int getMaxLevel() { return nMaxLevel; }
|
||||
|
||||
/** Return the name (for counter and \@startsection) for this level */
|
||||
public String getName(int nWriterLevel) { return sName[nWriterLevel]; }
|
||||
|
||||
/** Return the LaTeX level for this Writer level (for \@startsection) */
|
||||
public int getLevel(int nWriterLevel) { return nLevel[nWriterLevel]; }
|
||||
}
|
76
source/java/writer2latex/latex/util/Info.java
Normal file
76
source/java/writer2latex/latex/util/Info.java
Normal file
|
@ -0,0 +1,76 @@
|
|||
/************************************************************************
|
||||
*
|
||||
* Info.java
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License version 2.1, as published by the Free Software Foundation.
|
||||
*
|
||||
* This library 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
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston,
|
||||
* MA 02111-1307 USA
|
||||
*
|
||||
* Copyright: 2002-2008 by Henrik Just
|
||||
*
|
||||
* All Rights Reserved.
|
||||
*
|
||||
* Version 1.0 (2008-09-08)
|
||||
*
|
||||
*/
|
||||
|
||||
package writer2latex.latex.util;
|
||||
|
||||
import org.w3c.dom.Element;
|
||||
|
||||
import writer2latex.latex.LaTeXConfig;
|
||||
import writer2latex.util.Misc;
|
||||
import writer2latex.office.OfficeReader;
|
||||
import writer2latex.office.StyleWithProperties;
|
||||
import writer2latex.office.XMLString;
|
||||
import writer2latex.latex.LaTeXDocumentPortion;
|
||||
import writer2latex.latex.ConverterHelper;
|
||||
import writer2latex.latex.ConverterPalette;
|
||||
|
||||
|
||||
/**
|
||||
* <p>This class creates various information to the user about the conversion.</p>
|
||||
*/
|
||||
public class Info extends ConverterHelper {
|
||||
|
||||
public Info(OfficeReader ofr, LaTeXConfig config, ConverterPalette palette) {
|
||||
super(ofr,config,palette);
|
||||
}
|
||||
|
||||
public void addDebugInfo(Element node, LaTeXDocumentPortion ldp) {
|
||||
if (config.debug()) {
|
||||
ldp.append("% ").append(node.getNodeName());
|
||||
addDebugInfo(node,ldp,XMLString.TEXT_ID);
|
||||
addDebugInfo(node,ldp,XMLString.TEXT_NAME);
|
||||
addDebugInfo(node,ldp,XMLString.TABLE_NAME);
|
||||
addDebugInfo(node,ldp,XMLString.TEXT_STYLE_NAME);
|
||||
if (node.getNodeName().equals(XMLString.TEXT_P) || node.getNodeName().equals(XMLString.TEXT_H)) {
|
||||
StyleWithProperties style = ofr.getParStyle(node.getAttribute(XMLString.TEXT_STYLE_NAME));
|
||||
if (style!=null && style.isAutomatic()) {
|
||||
ldp.append(" ("+style.getParentName()+")");
|
||||
}
|
||||
ldp.append(" ("+ofr.getParStyles().getDisplayName(node.getAttribute(XMLString.TEXT_STYLE_NAME))+")");
|
||||
}
|
||||
ldp.nl();
|
||||
}
|
||||
}
|
||||
|
||||
private void addDebugInfo(Element node, LaTeXDocumentPortion ldp, String sAttribute) {
|
||||
String sValue = Misc.getAttribute(node,sAttribute);
|
||||
if (sValue!=null) {
|
||||
ldp.append(" ").append(sAttribute).append("=\"").append(sValue).append("\"");
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
}
|
11
source/java/writer2latex/latex/util/Package.html
Normal file
11
source/java/writer2latex/latex/util/Package.html
Normal file
|
@ -0,0 +1,11 @@
|
|||
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
|
||||
|
||||
<html>
|
||||
<head>
|
||||
<title>The package writer2latex.xhtml.util</title>
|
||||
</head>
|
||||
|
||||
<body>
|
||||
<p>Some general utility classes for LaTeX export.</p>
|
||||
</body>
|
||||
</html>
|
99
source/java/writer2latex/latex/util/StyleMap.java
Normal file
99
source/java/writer2latex/latex/util/StyleMap.java
Normal file
|
@ -0,0 +1,99 @@
|
|||
/************************************************************************
|
||||
*
|
||||
* StyleMap.java
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License version 2.1, as published by the Free Software Foundation.
|
||||
*
|
||||
* This library 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
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston,
|
||||
* MA 02111-1307 USA
|
||||
*
|
||||
* Copyright: 2002-2007 by Henrik Just
|
||||
*
|
||||
* All Rights Reserved.
|
||||
*
|
||||
* Version 1.0 (2007-07-30)
|
||||
*
|
||||
*/
|
||||
|
||||
package writer2latex.latex.util;
|
||||
|
||||
import java.util.Hashtable;
|
||||
import java.util.Enumeration;
|
||||
|
||||
public class StyleMap {
|
||||
private Hashtable items = new Hashtable();
|
||||
|
||||
public void put(String sName, String sBefore, String sAfter, boolean bLineBreak, boolean bVerbatim) {
|
||||
StyleMapItem item = new StyleMapItem();
|
||||
item.sBefore = sBefore;
|
||||
item.sAfter = sAfter;
|
||||
item.sNext = ";;";
|
||||
item.bLineBreak = bLineBreak;
|
||||
item.bVerbatim = bVerbatim;
|
||||
items.put(sName,item);
|
||||
}
|
||||
|
||||
public void put(String sName, String sBefore, String sAfter, String sNext, boolean bVerbatim) {
|
||||
StyleMapItem item = new StyleMapItem();
|
||||
item.sBefore = sBefore;
|
||||
item.sAfter = sAfter;
|
||||
item.sNext = ";"+sNext+";";
|
||||
item.bLineBreak = true;
|
||||
item.bVerbatim = bVerbatim;
|
||||
items.put(sName,item);
|
||||
}
|
||||
|
||||
public void put(String sName, String sBefore, String sAfter) {
|
||||
StyleMapItem item = new StyleMapItem();
|
||||
item.sBefore = sBefore;
|
||||
item.sAfter = sAfter;
|
||||
item.sNext = ";;";
|
||||
item.bLineBreak = true;
|
||||
item.bVerbatim = false;
|
||||
items.put(sName,item);
|
||||
}
|
||||
|
||||
public boolean contains(String sName) {
|
||||
return sName!=null && items.containsKey(sName);
|
||||
}
|
||||
|
||||
public String getBefore(String sName) {
|
||||
return ((StyleMapItem) items.get(sName)).sBefore;
|
||||
}
|
||||
|
||||
public String getAfter(String sName) {
|
||||
return ((StyleMapItem) items.get(sName)).sAfter;
|
||||
}
|
||||
|
||||
public String getNext(String sName) {
|
||||
String sNext = ((StyleMapItem) items.get(sName)).sNext;
|
||||
return sNext.substring(1,sNext.length()-1);
|
||||
}
|
||||
|
||||
public boolean isNext(String sName, String sNext) {
|
||||
String sNext1 = ((StyleMapItem) items.get(sName)).sNext;
|
||||
return sNext1.indexOf(";"+sNext+";")>-1;
|
||||
}
|
||||
|
||||
public boolean getLineBreak(String sName) {
|
||||
return contains(sName) && ((StyleMapItem) items.get(sName)).bLineBreak;
|
||||
}
|
||||
|
||||
public boolean getVerbatim(String sName) {
|
||||
return contains(sName) && ((StyleMapItem) items.get(sName)).bVerbatim;
|
||||
}
|
||||
|
||||
public Enumeration getNames() {
|
||||
return items.keys();
|
||||
}
|
||||
|
||||
}
|
36
source/java/writer2latex/latex/util/StyleMapItem.java
Normal file
36
source/java/writer2latex/latex/util/StyleMapItem.java
Normal file
|
@ -0,0 +1,36 @@
|
|||
/************************************************************************
|
||||
*
|
||||
* StyleMapItem.java
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License version 2.1, as published by the Free Software Foundation.
|
||||
*
|
||||
* This library 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
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston,
|
||||
* MA 02111-1307 USA
|
||||
*
|
||||
* Copyright: 2002-2007 by Henrik Just
|
||||
*
|
||||
* All Rights Reserved.
|
||||
*
|
||||
* Version 1.0 (2007-07-30)
|
||||
*
|
||||
*/
|
||||
|
||||
package writer2latex.latex.util;
|
||||
|
||||
// A struct to hold data about a style map
|
||||
class StyleMapItem {
|
||||
String sBefore;
|
||||
String sAfter;
|
||||
String sNext;
|
||||
boolean bLineBreak;
|
||||
boolean bVerbatim;
|
||||
}
|
146
source/java/writer2latex/office/BibMark.java
Normal file
146
source/java/writer2latex/office/BibMark.java
Normal file
|
@ -0,0 +1,146 @@
|
|||
/************************************************************************
|
||||
*
|
||||
* BibMark.java
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License version 2.1, as published by the Free Software Foundation.
|
||||
*
|
||||
* This library 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
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston,
|
||||
* MA 02111-1307 USA
|
||||
*
|
||||
* Copyright: 2002-2008 by Henrik Just
|
||||
*
|
||||
* All Rights Reserved.
|
||||
*
|
||||
* Version 1.0 (2008-11-22)
|
||||
*
|
||||
*/
|
||||
|
||||
package writer2latex.office;
|
||||
|
||||
import org.w3c.dom.Node;
|
||||
|
||||
import writer2latex.util.*;
|
||||
//import writer2latex.office.*;
|
||||
|
||||
/**
|
||||
* <p>This class represents a single bibliography-mark.</p>
|
||||
*/
|
||||
public final class BibMark {
|
||||
// Available fields
|
||||
public static final int ADDRESS = 0;
|
||||
public static final int ANNOTE = 1;
|
||||
public static final int AUTHOR = 2;
|
||||
public static final int BOOKTITLE = 3;
|
||||
public static final int CHAPTER = 4;
|
||||
// public static final int CROSSREF = 5; // BibTeX, missing in OOo
|
||||
public static final int EDITION = 6;
|
||||
public static final int EDITOR = 7;
|
||||
public static final int HOWPUBLISHED = 8;
|
||||
public static final int INSTITUTION = 9;
|
||||
public static final int JOURNAL = 10;
|
||||
// public static final int KEY = 11; // BibTeX, missing in OOo
|
||||
public static final int MONTH = 12;
|
||||
public static final int NOTE = 13;
|
||||
public static final int NUMBER = 14;
|
||||
public static final int ORGANIZATIONS = 15; // BibTeX: organization
|
||||
public static final int PAGES = 16;
|
||||
public static final int PUBLISHER = 17;
|
||||
public static final int SCHOOL = 18;
|
||||
public static final int SERIES = 19;
|
||||
public static final int TITLE = 20 ;
|
||||
public static final int REPORT_TYPE = 21; // BibTeX: report
|
||||
public static final int VOLUME = 22;
|
||||
public static final int YEAR = 23;
|
||||
// remaining fields are not standard in BibTeX
|
||||
public static final int URL = 24;
|
||||
public static final int CUSTOM1 = 25;
|
||||
public static final int CUSTOM2 = 26;
|
||||
public static final int CUSTOM3 = 27;
|
||||
public static final int CUSTOM4 = 28;
|
||||
public static final int CUSTOM5 = 29;
|
||||
public static final int ISBN = 30;
|
||||
public static final int FIELD_COUNT = 31;
|
||||
|
||||
|
||||
// Private data
|
||||
private String sIdentifier;
|
||||
private String sEntryType;
|
||||
private String[] fields = new String[FIELD_COUNT];
|
||||
|
||||
/**
|
||||
* <p>Create a new BibMark from scratch.</p>
|
||||
*/
|
||||
public BibMark(String sIdentifier, String sEntryType) {
|
||||
this.sIdentifier = sIdentifier;
|
||||
this.sEntryType = sEntryType;
|
||||
}
|
||||
|
||||
/**
|
||||
* <p>Create a new BibMark from a text:bibliography-mark node.</p>
|
||||
*/
|
||||
public BibMark(Node node) {
|
||||
sIdentifier = Misc.getAttribute(node,XMLString.TEXT_IDENTIFIER);
|
||||
sEntryType = Misc.getAttribute(node,XMLString.TEXT_BIBLIOGRAPHY_TYPE);
|
||||
if (sEntryType==null) { // bug in OOo 1.0!
|
||||
sEntryType = Misc.getAttribute(node,XMLString.TEXT_BIBILIOGRAPHIC_TYPE);
|
||||
}
|
||||
fields[ADDRESS] = Misc.getAttribute(node,XMLString.TEXT_ADDRESS);
|
||||
fields[ANNOTE] = Misc.getAttribute(node,XMLString.TEXT_ANNOTE);
|
||||
fields[AUTHOR] = Misc.getAttribute(node,XMLString.TEXT_AUTHOR);
|
||||
fields[BOOKTITLE] = Misc.getAttribute(node,XMLString.TEXT_BOOKTITLE);
|
||||
fields[CHAPTER] = Misc.getAttribute(node,XMLString.TEXT_CHAPTER);
|
||||
fields[EDITION] = Misc.getAttribute(node,XMLString.TEXT_EDITION);
|
||||
fields[EDITOR] = Misc.getAttribute(node,XMLString.TEXT_EDITOR);
|
||||
fields[HOWPUBLISHED] = Misc.getAttribute(node,XMLString.TEXT_HOWPUBLISHED);
|
||||
fields[INSTITUTION] = Misc.getAttribute(node,XMLString.TEXT_INSTITUTION);
|
||||
fields[JOURNAL] = Misc.getAttribute(node,XMLString.TEXT_JOURNAL);
|
||||
fields[MONTH] = Misc.getAttribute(node,XMLString.TEXT_MONTH);
|
||||
fields[NOTE] = Misc.getAttribute(node,XMLString.TEXT_NOTE);
|
||||
fields[NUMBER] = Misc.getAttribute(node,XMLString.TEXT_NUMBER);
|
||||
fields[ORGANIZATIONS] = Misc.getAttribute(node,XMLString.TEXT_ORGANIZATIONS);
|
||||
fields[PAGES] = Misc.getAttribute(node,XMLString.TEXT_PAGES);
|
||||
fields[PUBLISHER] = Misc.getAttribute(node,XMLString.TEXT_PUBLISHER);
|
||||
fields[SCHOOL] = Misc.getAttribute(node,XMLString.TEXT_SCHOOL);
|
||||
fields[SERIES] = Misc.getAttribute(node,XMLString.TEXT_SERIES);
|
||||
fields[TITLE] = Misc.getAttribute(node,XMLString.TEXT_TITLE);
|
||||
fields[REPORT_TYPE] = Misc.getAttribute(node,XMLString.TEXT_REPORT_TYPE);
|
||||
fields[VOLUME] = Misc.getAttribute(node,XMLString.TEXT_VOLUME);
|
||||
fields[YEAR] = Misc.getAttribute(node,XMLString.TEXT_YEAR);
|
||||
fields[URL] = Misc.getAttribute(node,XMLString.TEXT_URL);
|
||||
fields[CUSTOM1] = Misc.getAttribute(node,XMLString.TEXT_CUSTOM1);
|
||||
fields[CUSTOM2] = Misc.getAttribute(node,XMLString.TEXT_CUSTOM2);
|
||||
fields[CUSTOM3] = Misc.getAttribute(node,XMLString.TEXT_CUSTOM3);
|
||||
fields[CUSTOM4] = Misc.getAttribute(node,XMLString.TEXT_CUSTOM4);
|
||||
fields[CUSTOM5] = Misc.getAttribute(node,XMLString.TEXT_CUSTOM5);
|
||||
fields[ISBN] = Misc.getAttribute(node,XMLString.TEXT_ISBN);
|
||||
}
|
||||
|
||||
/**
|
||||
* <p>Get the identifier.</p>
|
||||
*/
|
||||
public String getIdentifier() { return sIdentifier; }
|
||||
|
||||
/**
|
||||
* <p>Get the entry type.</p>
|
||||
*/
|
||||
public String getEntryType() { return sEntryType; }
|
||||
|
||||
/**
|
||||
* <p>Set a specific field.</p>
|
||||
*/
|
||||
public void setField(int nField,String sValue) { fields[nField] = sValue; }
|
||||
|
||||
/**
|
||||
* <p>Return a specific field.</p>
|
||||
*/
|
||||
public String getField(int nField) { return fields[nField]; }
|
||||
}
|
40
source/java/writer2latex/office/CellView.java
Normal file
40
source/java/writer2latex/office/CellView.java
Normal file
|
@ -0,0 +1,40 @@
|
|||
/************************************************************************
|
||||
*
|
||||
* CellView.java
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License version 2.1, as published by the Free Software Foundation.
|
||||
*
|
||||
* This library 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
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston,
|
||||
* MA 02111-1307 USA
|
||||
*
|
||||
* Copyright: 2002-2008 by Henrik Just
|
||||
*
|
||||
* All Rights Reserved.
|
||||
*
|
||||
* Version 1.0 (2008-09-07)
|
||||
*
|
||||
*/
|
||||
|
||||
package writer2latex.office;
|
||||
|
||||
import org.w3c.dom.Element;
|
||||
|
||||
/**
|
||||
* This class represent a cell in a table view</p>
|
||||
*/
|
||||
public class CellView {
|
||||
public Element cell = null;
|
||||
public int nRowSpan = 1;
|
||||
public int nColSpan = 1;
|
||||
public int nOriginalRow = -1;
|
||||
public int nOriginalCol = -1;
|
||||
}
|
151
source/java/writer2latex/office/ControlReader.java
Normal file
151
source/java/writer2latex/office/ControlReader.java
Normal file
|
@ -0,0 +1,151 @@
|
|||
/************************************************************************
|
||||
*
|
||||
* ControlReader.java
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License version 2.1, as published by the Free Software Foundation.
|
||||
*
|
||||
* This library 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
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston,
|
||||
* MA 02111-1307 USA
|
||||
*
|
||||
* Copyright: 2002-2008 by Henrik Just
|
||||
*
|
||||
* All Rights Reserved.
|
||||
*
|
||||
* Version 1.0 (2008-11-23)
|
||||
*
|
||||
*/
|
||||
|
||||
package writer2latex.office;
|
||||
|
||||
//import java.util.Hashtable;
|
||||
import java.util.Vector;
|
||||
import org.w3c.dom.Element;
|
||||
import org.w3c.dom.Node;
|
||||
import writer2latex.util.Misc;
|
||||
|
||||
/** <p> This class reads a form control in an OOo document (a form:control
|
||||
* node). A control always has an owner form.
|
||||
* Properties and events are ignored.</p>
|
||||
*/
|
||||
public class ControlReader {
|
||||
|
||||
private FormReader ownerForm; // a control always belongs to a form
|
||||
private String sId; // a control is identified by id
|
||||
private Element control; // the control element
|
||||
private Element controlType; // the type specific child element
|
||||
private Vector items = new Vector(); // the options/items of a list/combobox
|
||||
|
||||
/** <p>The constructor reads the content of a control element</p>
|
||||
* The representation in OpenDocument differs slightly from OOo 1.x.
|
||||
|
||||
* @param control a DOM element, which must be control node
|
||||
*/
|
||||
public ControlReader(Element control, FormReader ownerForm) {
|
||||
this.ownerForm = ownerForm;
|
||||
this.control = control;
|
||||
sId = control.getAttribute(XMLString.FORM_ID);
|
||||
// Read the control type specific info
|
||||
if (control.getTagName().equals(XMLString.FORM_CONTROL)) { // old format
|
||||
controlType = Misc.getFirstChildElement(control);
|
||||
}
|
||||
else { // oasos
|
||||
controlType = control;
|
||||
}
|
||||
if (controlType!=null) { // must always be the case!
|
||||
// Collect options/items
|
||||
Node child = controlType.getFirstChild();
|
||||
while (child!=null) {
|
||||
if (child.getNodeType()==Node.ELEMENT_NODE && (
|
||||
child.getNodeName().equals(XMLString.FORM_OPTION) ||
|
||||
child.getNodeName().equals(XMLString.FORM_ITEM))) {
|
||||
items.add(child);
|
||||
}
|
||||
child = child.getNextSibling();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/** <p>A control in OOo is identified by id (<code>form:control-id</code>
|
||||
* attribute. The id is accessed by this method.</p>
|
||||
* @return the id of the control
|
||||
*/
|
||||
public String getId() { return sId; }
|
||||
|
||||
/** <p>A control in OOo belongs to a form.</p>
|
||||
* @return the form containing this control
|
||||
*/
|
||||
public FormReader getOwnerForm() { return ownerForm; }
|
||||
|
||||
/** <p>Get an attribute of the control. If the attribute does not exist,
|
||||
* this method returns <code>null</code>.
|
||||
* @param sName the name of the attribute
|
||||
* @return the value of the attribute, or <code>null</code>
|
||||
*/
|
||||
public String getAttribute(String sName) {
|
||||
return control.hasAttribute(sName) ? control.getAttribute(sName) : null;
|
||||
}
|
||||
|
||||
/** <p>The type of the control is identified by a name, eg. form:submit</p>
|
||||
* @return the type of this control
|
||||
*/
|
||||
public String getControlType() { return controlType.getTagName(); }
|
||||
|
||||
/** <p>Get an attribute specific to this type of control.
|
||||
* If the attribute does not exist, this method returns <code>null</code>.
|
||||
* @param sName the name of the attribute
|
||||
* @return the value of the attribute, or <code>null</code>
|
||||
*/
|
||||
public String getTypeAttribute(String sName) {
|
||||
return controlType!=null && controlType.hasAttribute(sName) ?
|
||||
controlType.getAttribute(sName) : null;
|
||||
}
|
||||
|
||||
/** <p>Return the number of options/items in this control.
|
||||
* Only listbox (options) and combobox (items) controls can have these,
|
||||
* for other controls this will return 0.
|
||||
* @return the number of options/items
|
||||
*/
|
||||
public int getItemCount() { return items.size(); }
|
||||
|
||||
/** <p>Get an attribute of an option/item.
|
||||
* If the index and/or the attribute does not exist, this method returns
|
||||
* <code>null</code>.
|
||||
* @param nIndex the index of the option/item
|
||||
* @param sName the name of the attribute
|
||||
* @return the value of the attribute, or <code>null</code>
|
||||
*/
|
||||
public String getItemAttribute(int nIndex, String sName) {
|
||||
if (0<=nIndex && nIndex<=items.size()) {
|
||||
return ((Element)items.get(nIndex)).hasAttribute(sName) ?
|
||||
((Element)items.get(nIndex)).getAttribute(sName) : null;
|
||||
}
|
||||
else {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
/** <p>Get the value of an option/item.
|
||||
* If the index does not exist, this method returns
|
||||
* <code>null</code>.
|
||||
* @param nIndex the index of the option/item
|
||||
* @return the value of the option/item, or <code>null</code>
|
||||
*/
|
||||
public String getItemValue(int nIndex) {
|
||||
if (0<=nIndex && nIndex<=items.size()) {
|
||||
return Misc.getPCDATA((Element)items.get(nIndex));
|
||||
}
|
||||
else {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
61
source/java/writer2latex/office/FontDeclaration.java
Normal file
61
source/java/writer2latex/office/FontDeclaration.java
Normal file
|
@ -0,0 +1,61 @@
|
|||
/************************************************************************
|
||||
*
|
||||
* FontDeclaration.java
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License version 2.1, as published by the Free Software Foundation.
|
||||
*
|
||||
* This library 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
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston,
|
||||
* MA 02111-1307 USA
|
||||
*
|
||||
* Copyright: 2002-2005 by Henrik Just
|
||||
*
|
||||
* All Rights Reserved.
|
||||
*
|
||||
* Version 0.5 (2005-10-10)
|
||||
*
|
||||
*/
|
||||
|
||||
package writer2latex.office;
|
||||
|
||||
import org.w3c.dom.Node;
|
||||
|
||||
/** <p> Class representing a font declaration in OOo</p>
|
||||
*/
|
||||
public class FontDeclaration extends OfficeStyle {
|
||||
private PropertySet properties = new PropertySet();
|
||||
|
||||
private String sFontFamily = null;
|
||||
private String sFontFamilyGeneric = null;
|
||||
private String sFontPitch = null;
|
||||
|
||||
public void loadStyleFromDOM(Node node) {
|
||||
super.loadStyleFromDOM(node);
|
||||
properties.loadFromDOM(node);
|
||||
sFontFamily = properties.getProperty(XMLString.FO_FONT_FAMILY);
|
||||
if (sFontFamily==null) { // oasis
|
||||
sFontFamily = properties.getProperty(XMLString.SVG_FONT_FAMILY);
|
||||
}
|
||||
sFontFamilyGeneric = properties.getProperty(XMLString.STYLE_FONT_FAMILY_GENERIC);
|
||||
sFontPitch = properties.getProperty(XMLString.STYLE_FONT_PITCH);
|
||||
}
|
||||
|
||||
public String getProperty(String sProperty){
|
||||
return properties.getProperty(sProperty);
|
||||
}
|
||||
|
||||
public String getFontFamily() { return sFontFamily; }
|
||||
|
||||
public String getFontFamilyGeneric() { return sFontFamilyGeneric; }
|
||||
|
||||
public String getFontPitch() { return sFontPitch; }
|
||||
|
||||
}
|
Some files were not shown because too many files have changed in this diff Show more
Loading…
Add table
Add a link
Reference in a new issue