diff --git a/source/distro/changelog.txt b/source/distro/changelog.txt index 7aa2880..d538d71 100644 --- a/source/distro/changelog.txt +++ b/source/distro/changelog.txt @@ -2,7 +2,22 @@ Changelog for Writer2LaTeX version 1.0 -> 1.2 ---------- version 1.1.9 ---------- -[all] Custom config ui: Style controls are now disabled if there are no definitions for the current style famlily +[w2x] EPUB export now uses user-defined meta data to support meta data features that are not defined in ODF + +[w2x] The option use_dublin_core now also works for EPUB export + +[all] API extension: The metadata interface now provides title, subject, keywords, description, creator, language, date + and all user defined metadata + +[w2l] The default value for wrap_lines_after is changed to 120 + +[w2l] Bugfix: Norwegian Nynorsk and Bokmål are exported correctly to babel languages + +[w2l] Added support for polyglossia.sty (if backend=xetex and multilingual=true) + +[w2l] The option "Use greek letters as symbols" is now disabled in the ui if the backend is XeTeX + +[all] Custom config ui: Style controls are now disabled if there are no definitions for the current style family [w2l] Custom config ui: The table and figure sequence name can now be selected from existing field masters diff --git a/source/distro/doc/user-manual.odt b/source/distro/doc/user-manual.odt index e20be04..32d6a1a 100644 Binary files a/source/distro/doc/user-manual.odt and b/source/distro/doc/user-manual.odt differ diff --git a/source/java/org/openoffice/da/comp/writer2latex/ConfigurationDialog.java b/source/java/org/openoffice/da/comp/writer2latex/ConfigurationDialog.java index d400d2a..cadb262 100644 --- a/source/java/org/openoffice/da/comp/writer2latex/ConfigurationDialog.java +++ b/source/java/org/openoffice/da/comp/writer2latex/ConfigurationDialog.java @@ -20,13 +20,14 @@ * * All Rights Reserved. * - * Version 1.2 (2010-12-09) + * Version 1.2 (2010-12-14) * */ package org.openoffice.da.comp.writer2latex; import java.util.HashMap; +import java.util.HashSet; import java.util.Map; import writer2latex.api.ComplexOption; @@ -86,7 +87,7 @@ public final class ConfigurationDialog extends ConfigurationDialogBase implement pageHandlers.put("Pages", new PagesHandler()); pageHandlers.put("Tables", new TablesHandler()); pageHandlers.put("Figures", new FiguresHandler()); - //pageHandlers.put("TextAndMath", new Handler()); + pageHandlers.put("TextAndMath", new TextAndMathHandler()); } // Implement remaining method from XContainerWindowEventHandler @@ -491,20 +492,16 @@ public final class ConfigurationDialog extends ConfigurationDialogBase implement // The page "Characters" // This page handles the options use_color, use_soul, use_ulem and use_hyperref // In addition it handles style maps for formatting attributes - // TODO: Should extend AttributePageHandler - private class CharactersHandler extends PageHandler { - private final String[] sAttributeNames = { "bold", "italic", "small-caps", "superscript", "subscipt" }; - private ComplexOption attributeMap = new ComplexOption(); // Cache of attribute maps - short nCurrentAttribute = -1; // Currently displayed map - + private class CharactersHandler extends AttributePageHandler { + private final String[] sLaTeXAttributeNames = { "bold", "italic", "small-caps", "superscript", "subscipt" }; + + protected CharactersHandler() { + super(); + sAttributeNames = sLaTeXAttributeNames; + } + @Override protected void setControls(DialogAccess dlg) { - // Load attribute style map from config and select the first map - attributeMap.clear(); - attributeMap.copyAll(config.getComplexOption("text-attribute-map")); - nCurrentAttribute = -1; - dlg.setListBoxSelectedItem("FormattingAttribute", (short)0); - - // Load other controls from config + super.setControls(dlg); checkBoxFromConfig(dlg,"UseHyperref","use_hyperref"); checkBoxFromConfig(dlg,"UseColor","use_color"); checkBoxFromConfig(dlg,"UseSoul","use_soul"); @@ -512,37 +509,40 @@ public final class ConfigurationDialog extends ConfigurationDialogBase implement } @Override protected void getControls(DialogAccess dlg) { - updateAttributeMap(dlg); - - // Save the attribute style map to config - config.getComplexOption("text-attribute-map").clear(); - for (String s : attributeMap.keySet()) { - if (!attributeMap.get(s).containsKey("deleted")) { - config.getComplexOption("text-attribute-map").copy(s, attributeMap.get(s)); - } - } - - // Save other controls to config + super.getControls(dlg); checkBoxToConfig(dlg,"UseHyperref","use_hyperref"); checkBoxToConfig(dlg,"UseColor","use_color"); checkBoxToConfig(dlg,"UseSoul","use_soul"); checkBoxToConfig(dlg,"UseUlem","use_ulem"); } - @Override protected boolean handleEvent(DialogAccess dlg, String sMethod) { + @Override protected void setControls(DialogAccess dlg, Map attr) { + if (!attr.containsKey("before")) { attr.put("before", ""); } + if (!attr.containsKey("after")) { attr.put("after", ""); } + dlg.setTextFieldText("Before", attr.get("before")); + dlg.setTextFieldText("After", attr.get("after")); + } + + @Override protected void getControls(DialogAccess dlg, Map attr) { + attr.put("before", dlg.getComboBoxText("Before")); + attr.put("after", dlg.getComboBoxText("After")); + } + + @Override protected void prepareControls(DialogAccess dlg, boolean bEnable) { + dlg.setControlEnabled("BeforeLabel", bEnable); + dlg.setControlEnabled("Before", bEnable); + dlg.setControlEnabled("AfterLabel", bEnable); + dlg.setControlEnabled("After", bEnable); + } + + @Override protected boolean handleEvent(DialogAccess dlg, String sMethod) { if (sMethod.equals("UseSoulChange")) { useSoulChange(dlg); return true; } - else if (sMethod.equals("FormattingAttributeChange")) { - formattingAttributeChange(dlg); - return true; + else { + return super.handleEvent(dlg, sMethod); } - else if (sMethod.equals("CustomAttributeChange")) { - customAttributeChange(dlg); - return true; - } - return false; } private void useSoulChange(DialogAccess dlg) { @@ -552,49 +552,7 @@ public final class ConfigurationDialog extends ConfigurationDialogBase implement //boolean bUseSoul = dlg.getCheckBoxStateAsBoolean("UseSoul"); //dlg.setControlEnabled("UseUlem", !bUseSoul); } - - private void formattingAttributeChange(DialogAccess dlg) { - updateAttributeMap(dlg); - - short nNewAttribute = dlg.getListBoxSelectedItem("FormattingAttribute"); - if (nNewAttribute>-1) { - String sName = sAttributeNames[nNewAttribute]; - if (attributeMap.containsKey(sName)) { - Map attr = attributeMap.get(sName); - dlg.setCheckBoxStateAsBoolean("CustomAttribute", !attr.containsKey("deleted")); - dlg.setTextFieldText("Before", attr.containsKey("before") ? attr.get("before") : ""); - dlg.setTextFieldText("After", attr.containsKey("after") ? attr.get("after") : ""); - } - else { - dlg.setCheckBoxStateAsBoolean("CustomAttribute", false); - dlg.setTextFieldText("Before", ""); - dlg.setTextFieldText("After", ""); - } - customAttributeChange(dlg); // setCheckBoxStateAsBoolean does not trigger this - nCurrentAttribute = nNewAttribute; - } - } - private void customAttributeChange(DialogAccess dlg) { - boolean bCustom = dlg.getCheckBoxStateAsBoolean("CustomAttribute"); - dlg.setControlEnabled("Before", bCustom); - dlg.setControlEnabled("After", bCustom); - } - - private void updateAttributeMap(DialogAccess dlg) { - // Save the current attribute map, if any - if (nCurrentAttribute>-1) { - Map attr = new HashMap(); - if (!dlg.getCheckBoxStateAsBoolean("CustomAttribute")) { - // don't delete the map now, but defer this to the dialog is closed - attr.put("deleted", "true"); - } - attr.put("before", dlg.getTextFieldText("Before")); - attr.put("after", dlg.getTextFieldText("After")); - attributeMap.put(sAttributeNames[nCurrentAttribute], attr); - } - } - } // The page "Fonts" @@ -846,399 +804,203 @@ public final class ConfigurationDialog extends ConfigurationDialogBase implement } - - /* - - - private XComponentContext xContext; - private XSimpleFileAccess2 sfa2; - private String sConfigFileName = null; - Config config; - // Local cache of complex options - ComplexOption[] styleMap; - ComplexOption mathSymbols; - ComplexOption stringReplace; - short nCurrentFamily = -1; - String sCurrentStyleName = null; - String sCurrentMathSymbol = null; - String sCurrentText = null; - private String sTitle = null; - private DialogAccess dlg = null; - private StyleNameProvider styleNameProvider = null; - private CustomSymbolNameProvider customSymbolNameProvider = null; - - /** Create a new ConfigurationDialog */ - /*public ConfigurationDialog(XComponentContext xContext) { - this.xContext = xContext; - - // Get the SimpleFileAccess service - sfa2 = null; - try { - Object sfaObject = xContext.getServiceManager().createInstanceWithContext( - "com.sun.star.ucb.SimpleFileAccess", xContext); - sfa2 = (XSimpleFileAccess2) UnoRuntime.queryInterface(XSimpleFileAccess2.class, sfaObject); - } - catch (com.sun.star.uno.Exception e) { - // failed to get SimpleFileAccess service (should not happen) - } - - // Create the config file name - XStringSubstitution xPathSub = null; - try { - Object psObject = xContext.getServiceManager().createInstanceWithContext( - "com.sun.star.util.PathSubstitution", xContext); - xPathSub = (XStringSubstitution) UnoRuntime.queryInterface(XStringSubstitution.class, psObject); - sConfigFileName = xPathSub.substituteVariables("$(user)/writer2latex.xml", false); - } - catch (com.sun.star.uno.Exception e) { - // failed to get PathSubstitution service (should not happen) - } - - // Create the configuration - config = ConverterFactory.createConverter("application/x-latex").getConfig(); - - // Initialize the local cache of complex options - styleMap = new ComplexOption[5]; - for (int i=0; i<5; i++) { styleMap[i]=new ComplexOption(); } - mathSymbols = new ComplexOption(); - stringReplace = new ComplexOption(); - - styleNameProvider = new StyleNameProvider(xContext); - customSymbolNameProvider = new CustomSymbolNameProvider(xContext); - }*/ - - - - /*// Display a dialog - private XDialog getDialog(String sDialogName) { - XMultiComponentFactory xMCF = xContext.getServiceManager(); - try { - Object provider = xMCF.createInstanceWithContext( - "com.sun.star.awt.DialogProvider2", xContext); - XDialogProvider2 xDialogProvider = (XDialogProvider2) - UnoRuntime.queryInterface(XDialogProvider2.class, provider); - String sDialogUrl = "vnd.sun.star.script:"+sDialogName+"?location=application"; - return xDialogProvider.createDialogWithHandler(sDialogUrl, this); - } - catch (Exception e) { - return null; - } - } - - private boolean deleteItem(String sName) { - XDialog xDialog=getDialog("W2LDialogs2.DeleteDialog"); - if (xDialog!=null) { - DialogAccess ddlg = new DialogAccess(xDialog); - String sLabel = ddlg.getLabelText("DeleteLabel"); - sLabel = sLabel.replaceAll("%s", sName); - ddlg.setLabelText("DeleteLabel", sLabel); - boolean bDelete = xDialog.execute()==ExecutableDialogResults.OK; - xDialog.endExecute(); - return bDelete; - } - return false; - } - - private boolean deleteCurrentItem(String sListName) { - String[] sItems = dlg.getListBoxStringItemList(sListName); - short nSelected = dlg.getListBoxSelectedItem(sListName); - if (nSelected>=0 && deleteItem(sItems[nSelected])) { - int nOldLen = sItems.length; - String[] sNewItems = new String[nOldLen-1]; - if (nSelected>0) { - System.arraycopy(sItems, 0, sNewItems, 0, nSelected); - } - if (nSelected suggestions) { - XDialog xDialog=getDialog("W2LDialogs2.NewDialog"); - if (xDialog!=null) { - int nCount = suggestions.size(); - String[] sItems = new String[nCount]; - int i=0; - for (String s : suggestions) { - sItems[i++] = s; - } - sortStringArray(sItems); - DialogAccess ndlg = new DialogAccess(xDialog); - ndlg.setListBoxStringItemList("Name", sItems); - String sResult = null; - if (xDialog.execute()==ExecutableDialogResults.OK) { - DialogAccess dlg = new DialogAccess(xDialog); - sResult = dlg.getTextFieldText("Name"); - } - xDialog.endExecute(); - return sResult; - } - return null; - } - - private String appendItem(String sListName, Set suggestions) { - String[] sItems = dlg.getListBoxStringItemList(sListName); - String sNewItem = newItem(suggestions); - if (sNewItem!=null) { - int nOldLen = sItems.length; - for (short i=0; i attr = new HashMap(); - attr.put("latex", dlg.getTextFieldText("MathLaTeX")); - mathSymbols.put(sCurrentMathSymbol, attr); - } - - // Save the current string replace in our cache - if (sCurrentText!=null) { - Map attr = new HashMap(); - attr.put("latex-code", dlg.getTextFieldText("LaTeX")); - attr.put("fontenc", "any"); - stringReplace.put(sCurrentText, attr); - } - } - - private void updateTextAndMathControls() { - updateTextAndMathMaps(); - - // Get the current math symbol, if any - short nSymbolItem = dlg.getListBoxSelectedItem("MathSymbolName"); - if (nSymbolItem>=0) { - sCurrentMathSymbol = dlg.getListBoxStringItemList("MathSymbolName")[nSymbolItem]; - - Map attributes = mathSymbols.get(sCurrentMathSymbol); - dlg.setTextFieldText("MathLaTeX", attributes.get("latex")); - dlg.setControlEnabled("DeleteSymbolButton", true); - } - else { + @Override protected void setControls(DialogAccess dlg) { + // Get math symbols from config + if (mathSymbols!=null) { mathSymbols.clear(); } + else { mathSymbols = new ComplexOption(); } + mathSymbols.copyAll(config.getComplexOption("math-symbol-map")); sCurrentMathSymbol = null; - dlg.setTextFieldText("MathLaTeX", ""); - dlg.setControlEnabled("DeleteSymbolButton", false); + dlg.setListBoxStringItemList("MathSymbolName", sortStringSet(mathSymbols.keySet())); + // This triggers an onchange event + dlg.setListBoxSelectedItem("MathSymbolName", (short)Math.min(0,mathSymbols.keySet().size()-1)); + + // Get string replace from config + if (stringReplace!=null) { stringReplace.clear(); } + else { stringReplace = new ComplexOption(); } + stringReplace.copyAll(config.getComplexOption("string-replace")); + sCurrentText = null; + dlg.setListBoxStringItemList("TextInput", sortStringSet(stringReplace.keySet())); + // This triggers an onchange event + dlg.setListBoxSelectedItem("TextInput", (short)Math.min(0,stringReplace.keySet().size()-1)); + + // Get other options from config + checkBoxFromConfig(dlg,"UseOoomath","use_ooomath"); + textFieldFromConfig(dlg,"TabStopLaTeX", "tabstop"); } - // Get the current input string, if any - short nItem = dlg.getListBoxSelectedItem("TextInput"); - if (nItem>=0) { - sCurrentText = dlg.getListBoxStringItemList("TextInput")[nItem]; - - Map attributes = stringReplace.get(sCurrentText); - dlg.setTextFieldText("LaTeX", attributes.get("latex-code")); - //dlg.setTextFieldText("Fontenc", attributes.get("fontenc")); - dlg.setControlEnabled("DeleteTextButton", - !"\u00A0!".equals(sCurrentText) && !"\u00A0?".equals(sCurrentText) && - !"\u00A0:".equals(sCurrentText) && !"\u00A0;".equals(sCurrentText) && - !"\u00A0\u2014".equals(sCurrentText)); - } - else { - sCurrentText = null; - dlg.setTextFieldText("LaTeX", ""); - //dlg.setTextFieldText("Fontenc", "any"); - dlg.setControlEnabled("DeleteTextButton", false); + @Override protected void getControls(DialogAccess dlg) { + // Save math symbols to config + updateSymbol(dlg); + config.getComplexOption("math-symbol-map").clear(); + config.getComplexOption("math-symbol-map").copyAll(mathSymbols); + + // Save string replace to config + updateText(dlg); + config.getComplexOption("string-replace").clear(); + config.getComplexOption("string-replace").copyAll(stringReplace); + + // Save other options to config + checkBoxToConfig(dlg,"UseOoomath","use_ooomath"); + textFieldToConfig(dlg,"TabStopLaTeX", "tabstop"); } - } - - private void newSymbolClick() { - String sNewName = appendItem("MathSymbolName",customSymbolNameProvider.getNames()); - if (sNewName!=null) { - Map attr = new HashMap(); - attr.put("latex", ""); - mathSymbols.put(sNewName, attr); - saveTextAndMath(); - dlg.setTextFieldText("MathLaTeX", ""); - updateTextAndMathControls(); + @Override protected boolean handleEvent(DialogAccess dlg, String sMethod) { + if (sMethod.equals("MathSymbolNameChange")) { + mathSymbolNameChange(dlg); + return true; + } + else if (sMethod.equals("NewSymbolClick")) { + newSymbolClick(dlg); + return true; + } + else if (sMethod.equals("DeleteSymbolClick")) { + deleteSymbolClick(dlg); + return true; + } + else if (sMethod.equals("TextInputChange")) { + textInputChange(dlg); + return true; + } + else if (sMethod.equals("NewTextClick")) { + newTextClick(dlg); + return true; + } + else if (sMethod.equals("DeleteTextClick")) { + deleteTextClick(dlg); + return true; + } + return false; + } + + private void mathSymbolNameChange(DialogAccess dlg) { + updateSymbol(dlg); + updateSymbolControls(dlg); + } + + private void newSymbolClick(DialogAccess dlg) { + // This triggers an onchange event + appendItem(dlg,"MathSymbolName",customSymbolNameProvider.getNames()); + } + + private void deleteSymbolClick(DialogAccess dlg) { + String sMathSymbol = sCurrentMathSymbol; + // This triggers an onchange event + if (deleteCurrentItem(dlg,"MathSymbolName")) { + mathSymbols.remove(sMathSymbol); + } + } + + private void updateSymbol(DialogAccess dlg) { + // Save the current math symbol in our cache + if (sCurrentMathSymbol!=null) { + Map attr = new HashMap(); + attr.put("latex", dlg.getTextFieldText("MathLaTeX")); + mathSymbols.put(sCurrentMathSymbol, attr); + } + } + + // Update symbol controls based on currently selected list item + private void updateSymbolControls(DialogAccess dlg) { + short nSymbolItem = dlg.getListBoxSelectedItem("MathSymbolName"); + if (nSymbolItem>=0) { + sCurrentMathSymbol = dlg.getListBoxStringItemList("MathSymbolName")[nSymbolItem]; + Map attributes; + if (mathSymbols.containsKey(sCurrentMathSymbol)) { + attributes = mathSymbols.get(sCurrentMathSymbol); + } + else { // New symbol, add empty definition to cache + attributes = new HashMap(); + attributes.put("latex", ""); + mathSymbols.put(sCurrentMathSymbol, attributes); + } + dlg.setTextFieldText("MathLaTeX", attributes.get("latex")); + dlg.setControlEnabled("MathLaTeX", true); + dlg.setControlEnabled("DeleteSymbolButton", true); + } + else { // The list is empty, or nothing is selected + sCurrentMathSymbol = null; + dlg.setTextFieldText("MathLaTeX", ""); + dlg.setControlEnabled("MathLaTeX", false); + dlg.setControlEnabled("DeleteSymbolButton", false); + } + } + + private void textInputChange(DialogAccess dlg) { + updateText(dlg); + updateTextControls(dlg); + } + + private void newTextClick(DialogAccess dlg) { + // This triggers an onchange event + appendItem(dlg, "TextInput", new HashSet()); + } + + private void deleteTextClick(DialogAccess dlg) { + String sText = sCurrentText; + // This triggers an onchange event + if (deleteCurrentItem(dlg, "TextInput")) { + stringReplace.remove(sText); + } + } + + private void updateText(DialogAccess dlg) { + // Save the current string replace in our cache + if (sCurrentText!=null) { + Map attr = new HashMap(); + attr.put("latex-code", dlg.getTextFieldText("LaTeX")); + attr.put("fontenc", "any"); + stringReplace.put(sCurrentText, attr); + } + } + + // Update text controls based on currently selected list item + private void updateTextControls(DialogAccess dlg) { + // Get the current input string, if any + short nItem = dlg.getListBoxSelectedItem("TextInput"); + if (nItem>=0) { + sCurrentText = dlg.getListBoxStringItemList("TextInput")[nItem]; + + Map attributes; + if (stringReplace.containsKey(sCurrentText)) { + attributes = stringReplace.get(sCurrentText); + } + else { // New string replace, add empty definition to cache + attributes = new HashMap(); + attributes.put("latex-code", ""); + attributes.put("fontenc", "any"); + stringReplace.put(sCurrentText, attributes); + } + + dlg.setTextFieldText("LaTeX", attributes.get("latex-code")); + //dlg.setTextFieldText("Fontenc", attributes.get("fontenc")); + dlg.setControlEnabled("LaTeX", true); + dlg.setControlEnabled("DeleteTextButton", + !"\u00A0!".equals(sCurrentText) && !"\u00A0?".equals(sCurrentText) && + !"\u00A0:".equals(sCurrentText) && !"\u00A0;".equals(sCurrentText) && + !"\u00A0\u2014".equals(sCurrentText)); + } + else { // The list is empty, or nothing is selected + sCurrentText = null; + dlg.setTextFieldText("LaTeX", ""); + //dlg.setTextFieldText("Fontenc", "any"); + dlg.setControlEnabled("DeleteTextButton", false); + } } } - private void deleteSymbolClick() { - if (deleteCurrentItem("MathSymbolName")) { - mathSymbols.remove(sCurrentMathSymbol); - sCurrentMathSymbol = null; - updateTextAndMathControls(); - } - } - - private void newTextClick() { - String sNewName = appendItem("TextInput", new HashSet()); - if (sNewName!=null) { - Map attr = new HashMap(); - attr.put("latex-code", ""); - attr.put("fontenc", "any"); - stringReplace.put(sNewName, attr); - dlg.setTextFieldText("LaTeX", ""); - saveTextAndMath(); - updateTextAndMathControls(); - } - } - - private void deleteTextClick() { - if (deleteCurrentItem("TextInput")) { - stringReplace.remove(sCurrentText); - sCurrentText = null; - updateTextAndMathControls(); - } - } - - // Utilities - private String[] sortStringSet(Set theSet) { - String[] theArray = new String[theSet.size()]; - int i=0; - for (String s : theSet) { - theArray[i++] = s; - } - sortStringArray(theArray); - return theArray; - } - - private void sortStringArray(String[] theArray) { - // TODO: Get locale from OOo rather than the system - Collator collator = Collator.getInstance(); - Arrays.sort(theArray, collator); - } - */ } diff --git a/source/java/org/openoffice/da/comp/writer2latex/LaTeXOptionsDialog.java b/source/java/org/openoffice/da/comp/writer2latex/LaTeXOptionsDialog.java index e18a72e..c592a95 100644 --- a/source/java/org/openoffice/da/comp/writer2latex/LaTeXOptionsDialog.java +++ b/source/java/org/openoffice/da/comp/writer2latex/LaTeXOptionsDialog.java @@ -16,11 +16,11 @@ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, * MA 02111-1307 USA * - * Copyright: 2002-2009 by Henrik Just + * Copyright: 2002-2010 by Henrik Just * * All Rights Reserved. * - * Version 1.2 (2009-03-31) + * Version 1.2 (2010-12-14) * */ @@ -37,7 +37,7 @@ 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 +/** This class provides a UNO component which implements a filter ui for the * LaTeX export */ public class LaTeXOptionsDialog extends OptionsDialogBase { @@ -241,6 +241,10 @@ public class LaTeXOptionsDialog extends OptionsDialogBase { // backend=xetex locks the encoding to utf8 return getListBoxSelectedItem("Backend")==3 || super.isLocked(sOptionName); } + else if ("greek_math".equals(sOptionName)) { + // this option has no effect if backend=xetex + return getListBoxSelectedItem("Backend")==3 || 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) diff --git a/source/java/writer2latex/api/ConverterFactory.java b/source/java/writer2latex/api/ConverterFactory.java index b8af8bc..1f25989 100644 --- a/source/java/writer2latex/api/ConverterFactory.java +++ b/source/java/writer2latex/api/ConverterFactory.java @@ -20,7 +20,7 @@ * * All Rights Reserved. * - * Version 1.2 (2010-12-08) + * Version 1.2 (2010-12-16) * */ @@ -33,7 +33,7 @@ public class ConverterFactory { // Version information private static final String VERSION = "1.1.9"; - private static final String DATE = "2010-12-08"; + private static final String DATE = "2010-12-16"; /** Return the Writer2LaTeX version in the form * (major version).(minor version).(patch level)
diff --git a/source/java/writer2latex/api/MetaData.java b/source/java/writer2latex/api/MetaData.java index ddb64be..8e74331 100644 --- a/source/java/writer2latex/api/MetaData.java +++ b/source/java/writer2latex/api/MetaData.java @@ -20,12 +20,14 @@ * * All Rights Reserved. * - * Version 1.2 (2010-03-15) + * Version 1.2 (2010-12-15) * */ package writer2latex.api; +import java.util.Map; + /** This interface provides access to the predefined meta data of the * source document (currently incomplete) */ @@ -36,10 +38,45 @@ public interface MetaData { */ public String getTitle(); + /** Get the subject of the source document + * + * @return the subject (may return an empty string) + */ + public String getSubject(); + + /** Get the keywords of the source document + * + * @return the keywords as a comma separated list (may return an empty string) + */ + public String getKeywords(); + + /** Get the description of the source document + * + * @return the description (may return an empty string) + */ + public String getDescription(); + + /** Get the creator of the source document (or the initial creator if none is specified) + * + * @return the creator (may return an empty string) + */ + public String getCreator(); + /** Get the (main) language of the document * * @return the language */ public String getLanguage(); + /** Get the date of the source document + * + * @return the date (may return an empty string) + */ + public String getDate(); + + /** Get the user-defined meta data + * + * @return the user-defined meta data as a name-value map + */ + public Map getUserDefinedMetaData(); } diff --git a/source/java/writer2latex/epub/EPUBConverter.java b/source/java/writer2latex/epub/EPUBConverter.java index 9c238f7..3f19968 100644 --- a/source/java/writer2latex/epub/EPUBConverter.java +++ b/source/java/writer2latex/epub/EPUBConverter.java @@ -20,7 +20,7 @@ * * All Rights Reserved. * - * version 1.2 (2010-03-28) + * version 1.2 (2010-12-15) * */ @@ -48,7 +48,7 @@ public final class EPUBConverter extends Xhtml11Converter { ConverterResult xhtmlResult = super.convert(is, sTargetFileName); ConverterResultImpl epubResult = new ConverterResultImpl(); - epubResult.addDocument(new EPUBWriter(xhtmlResult,sTargetFileName)); + epubResult.addDocument(new EPUBWriter(xhtmlResult,sTargetFileName,getXhtmlConfig())); epubResult.setMetaData(xhtmlResult.getMetaData()); return epubResult; } diff --git a/source/java/writer2latex/epub/EPUBWriter.java b/source/java/writer2latex/epub/EPUBWriter.java index 7235c08..0f70b65 100644 --- a/source/java/writer2latex/epub/EPUBWriter.java +++ b/source/java/writer2latex/epub/EPUBWriter.java @@ -20,7 +20,7 @@ * * All Rights Reserved. * - * version 1.2 (2010-03-31) + * version 1.2 (2010-12-15) * */ @@ -37,6 +37,7 @@ import java.util.zip.ZipOutputStream; import writer2latex.api.ConverterResult; import writer2latex.api.OutputFile; import writer2latex.util.Misc; +import writer2latex.xhtml.XhtmlConfig; /** This class repackages an XHTML document into EPUB format. * Some filenames are hard wired in this implementation: The main directory is OEBPS and @@ -49,10 +50,12 @@ public class EPUBWriter implements OutputFile { private ConverterResult xhtmlResult; private String sFileName; + private XhtmlConfig config; - public EPUBWriter(ConverterResult xhtmlResult, String sFileName) { + public EPUBWriter(ConverterResult xhtmlResult, String sFileName, XhtmlConfig config) { this.xhtmlResult = xhtmlResult; this.sFileName = Misc.removeExtension(sFileName); + this.config = config; } public String getFileName() { @@ -90,7 +93,7 @@ public class EPUBWriter implements OutputFile { zos.closeEntry(); // Then manifest - OutputFile manifest = new OPFWriter(xhtmlResult, sUUID); + OutputFile manifest = new OPFWriter(xhtmlResult, sUUID, config.xhtmlUseDublinCore()); ZipEntry manifestEntry = new ZipEntry("OEBPS/book.opf"); zos.putNextEntry(manifestEntry); writeZipEntry(manifest,zos); diff --git a/source/java/writer2latex/epub/OPFWriter.java b/source/java/writer2latex/epub/OPFWriter.java index 8a23f6c..8e28b5f 100644 --- a/source/java/writer2latex/epub/OPFWriter.java +++ b/source/java/writer2latex/epub/OPFWriter.java @@ -20,13 +20,14 @@ * * All Rights Reserved. * - * version 1.2 (2010-07-02) + * version 1.2 (2010-12-16) * */ package writer2latex.epub; import java.util.Iterator; +import java.util.Map; import javax.xml.parsers.DocumentBuilder; import javax.xml.parsers.DocumentBuilderFactory; @@ -47,7 +48,7 @@ import writer2latex.xmerge.NewDOMDocument; */ public class OPFWriter extends NewDOMDocument { - public OPFWriter(ConverterResult cr, String sUUID) { + public OPFWriter(ConverterResult cr, String sUUID, boolean bUseDublinCore) { super("book", "opf"); // create DOM @@ -83,11 +84,139 @@ public class OPFWriter extends NewDOMDocument { metadata.appendChild(language); language.appendChild(contentDOM.createTextNode(cr.getMetaData().getLanguage())); - Element identifier = contentDOM.createElement("dc:identifier"); - identifier.setAttribute("id", "BookId"); - identifier.setAttribute("opf:scheme", "UUID"); - metadata.appendChild(identifier); - identifier.appendChild(contentDOM.createTextNode(sUUID)); + // Additional meta data + if (bUseDublinCore) { + // Subject and keywords in ODF both map to Dublin core subjects + if (cr.getMetaData().getSubject().length()>0) { + Element subject = contentDOM.createElement("dc:subject"); + metadata.appendChild(subject); + subject.appendChild(contentDOM.createTextNode(cr.getMetaData().getSubject())); + } + if (cr.getMetaData().getKeywords().length()>0) { + String[] sKeywords = cr.getMetaData().getKeywords().split(","); + for (String sKeyword : sKeywords) { + Element subject = contentDOM.createElement("dc:subject"); + metadata.appendChild(subject); + subject.appendChild(contentDOM.createTextNode(sKeyword.trim())); + } + } + if (cr.getMetaData().getDescription().length()>0) { + Element description = contentDOM.createElement("dc:description"); + metadata.appendChild(description); + description.appendChild(contentDOM.createTextNode(cr.getMetaData().getDescription())); + } + } + + // User defined meta data + // The identifier, creator, contributor and date has an optional attribute and there may be multiple instances of + // the first three. The key can be in any of the forms name, name.attribute, name.attribute.id, name..id + // where the id is some unique id amongst the instances with the same name + // Thus you can have e.g. creator.aut.1="John Doe" and creator.aut.2="Jane Doe" + boolean bHasIdentifier = false; + boolean bHasCreator = false; + boolean bHasDate = false; + Map userDefined = cr.getMetaData().getUserDefinedMetaData(); + for (String sKey : userDefined.keySet()) { + if (sKey.length()>0) { + String[] sKeyElements = sKey.toLowerCase().split("\\."); + String sValue = userDefined.get(sKey); + if ("identifier".equals(sKeyElements[0])) { + Element identifier = contentDOM.createElement("dc:identifier"); + identifier.setAttribute("id", "BookId"); + if (sKeyElements.length>1 && sKeyElements[1].length()>0) { + identifier.setAttribute("opf:scheme", sKeyElements[1]); + } + metadata.appendChild(identifier); + identifier.appendChild(contentDOM.createTextNode(sValue)); + bHasIdentifier = true; + } + else if ("creator".equals(sKeyElements[0])) { + Element creator = contentDOM.createElement("dc:creator"); + if (sKeyElements.length>1 && sKeyElements[1].length()>0) { + creator.setAttribute("opf:role", sKeyElements[1]); + } + metadata.appendChild(creator); + creator.appendChild(contentDOM.createTextNode(sValue)); + bHasCreator = true; + } + else if ("contributor".equals(sKeyElements[0])) { + Element contributor = contentDOM.createElement("dc:contributor"); + if (sKeyElements.length>1 && sKeyElements[1].length()>0) { + contributor.setAttribute("opf:role", sKeyElements[1]); + } + metadata.appendChild(contributor); + contributor.appendChild(contentDOM.createTextNode(sValue)); + } + else if ("date".equals(sKeyElements[0])) { + Element date = contentDOM.createElement("dc:date"); + if (sKeyElements.length>1 && sKeyElements[1].length()>0) { + date.setAttribute("opf:event", sKeyElements[1]); + } + metadata.appendChild(date); + date.appendChild(contentDOM.createTextNode(sValue)); + bHasDate = true; + } + else if (sKeyElements.length==1) { + // Remaining meta data elements must be unique + if ("publisher".equals(sKeyElements[0])) { + Element publisher = contentDOM.createElement("dc:publisher"); + metadata.appendChild(publisher); + publisher.appendChild(contentDOM.createTextNode(sValue)); + } + else if ("type".equals(sKeyElements[0])) { + Element type = contentDOM.createElement("dc:type"); + metadata.appendChild(type); + type.appendChild(contentDOM.createTextNode(sValue)); + } + else if ("format".equals(sKeyElements[0])) { + Element format = contentDOM.createElement("dc:format"); + metadata.appendChild(format); + format.appendChild(contentDOM.createTextNode(sValue)); + } + else if ("source".equals(sKeyElements[0])) { + Element source = contentDOM.createElement("dc:source"); + metadata.appendChild(source); + source.appendChild(contentDOM.createTextNode(sValue)); + } + else if ("relation".equals(sKeyElements[0])) { + Element relation = contentDOM.createElement("dc:relation"); + metadata.appendChild(relation); + relation.appendChild(contentDOM.createTextNode(sValue)); + } + else if ("coverage".equals(sKeyElements[0])) { + Element coverage = contentDOM.createElement("dc:coverage"); + metadata.appendChild(coverage); + coverage.appendChild(contentDOM.createTextNode(sValue)); + } + else if ("rights".equals(sKeyElements[0])) { + Element rights = contentDOM.createElement("dc:rights"); + metadata.appendChild(rights); + rights.appendChild(contentDOM.createTextNode(sValue)); + } + } + } + } + + // Fall back values for creator and date + if (bUseDublinCore) { + if (!bHasIdentifier) { + Element identifier = contentDOM.createElement("dc:identifier"); + identifier.setAttribute("id", "BookId"); + identifier.setAttribute("opf:scheme", "UUID"); + metadata.appendChild(identifier); + identifier.appendChild(contentDOM.createTextNode(sUUID)); + } + if (!bHasCreator && cr.getMetaData().getCreator().length()>0) { + Element creator = contentDOM.createElement("dc:creator"); + metadata.appendChild(creator); + creator.appendChild(contentDOM.createTextNode(cr.getMetaData().getCreator())); + } + if (!bHasDate && cr.getMetaData().getDate().length()>0) { + Element date = contentDOM.createElement("dc:date"); + metadata.appendChild(date); + date.appendChild(contentDOM.createTextNode(cr.getMetaData().getDate())); + } + } // Manifest must contain references to all the files in the XHTML converter result // Spine should contain references to all the master documents within the converter result diff --git a/source/java/writer2latex/latex/LaTeXConfig.java b/source/java/writer2latex/latex/LaTeXConfig.java index 57fe60d..0f1d4cc 100644 --- a/source/java/writer2latex/latex/LaTeXConfig.java +++ b/source/java/writer2latex/latex/LaTeXConfig.java @@ -20,7 +20,7 @@ * * All Rights Reserved. * - * Version 1.2 (2010-10-09) + * Version 1.2 (2010-12-15) * */ @@ -308,7 +308,7 @@ public class LaTeXConfig extends writer2latex.base.ConfigBase { }; options[METADATA] = new BooleanOption("metadata","true"); options[TABSTOP] = new Option("tabstop",""); - options[WRAP_LINES_AFTER] = new IntegerOption("wrap_lines_after","72") { + options[WRAP_LINES_AFTER] = new IntegerOption("wrap_lines_after","120") { public void setString(String sValue) { super.setString(sValue); nValue = Misc.getPosInteger(sValue,0); diff --git a/source/java/writer2latex/latex/i18n/ClassicI18n.java b/source/java/writer2latex/latex/i18n/ClassicI18n.java index fc6ec27..00f57a0 100644 --- a/source/java/writer2latex/latex/i18n/ClassicI18n.java +++ b/source/java/writer2latex/latex/i18n/ClassicI18n.java @@ -20,7 +20,7 @@ * * All Rights Reserved. * - * Version 1.2 (2010-05-11) + * Version 1.2 (2010-12-15) * */ @@ -359,7 +359,7 @@ public class ClassicI18n extends I18n { } /** Apply a language language - * @param style the OOo style to read attributesfrom + * @param style the OOo style to read attributes from * @param bDecl true if declaration form is required * @param bInherit true if inherited properties should be used * @param ba the BeforeAfter to add LaTeX code to. @@ -662,7 +662,8 @@ public class ClassicI18n extends I18n { babelLanguages.put("is", "icelandic"); // latin1 babelLanguages.put("it", "italian"); // latin1 babelLanguages.put("nl", "dutch"); // latin1 - babelLanguages.put("no", "norsk"); // latin1 + babelLanguages.put("nb", "norsk"); // latin1 + babelLanguages.put("nn", "nynorsk"); // latin1 babelLanguages.put("pl", "polish"); // latin2 babelLanguages.put("pt", "portuges"); // latin1 babelLanguages.put("ro", "romanian"); // latin2 diff --git a/source/java/writer2latex/latex/i18n/I18n.java b/source/java/writer2latex/latex/i18n/I18n.java index 2ebdd7a..6bf7f5a 100644 --- a/source/java/writer2latex/latex/i18n/I18n.java +++ b/source/java/writer2latex/latex/i18n/I18n.java @@ -20,7 +20,7 @@ * * All Rights Reserved. * - * Version 1.2 (2010-10-30) + * Version 1.2 (2010-12-14) * */ @@ -118,7 +118,7 @@ public abstract class I18n { /** Get the default language (either the document language or the most used language) * - * @param the default language + * @return the default language */ public String getDefaultLanguage() { return sDefaultLanguage; diff --git a/source/java/writer2latex/latex/i18n/Polyglossia.java b/source/java/writer2latex/latex/i18n/Polyglossia.java new file mode 100644 index 0000000..709e225 --- /dev/null +++ b/source/java/writer2latex/latex/i18n/Polyglossia.java @@ -0,0 +1,217 @@ +/************************************************************************ + * + * 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-2010 by Henrik Just + * + * All Rights Reserved. + * + * Version 1.2 (2010-12-15) + * + */ + +package writer2latex.latex.i18n; + +import java.util.ArrayList; +import java.util.HashMap; +import java.util.HashSet; +import java.util.List; +import java.util.Map; +import java.util.Set; + +public class Polyglossia { + private static Map languageMap; + private static Map variantMap; + + static { + languageMap = new HashMap(); + languageMap.put("am", "amharic"); + languageMap.put("ar", "arabic"); + languageMap.put("ast", "asturian"); + languageMap.put("bg", "bulgarian"); + languageMap.put("bn", "bengali"); + languageMap.put("br", "breton"); + languageMap.put("ca", "catalan"); + languageMap.put("cop", "coptic"); + languageMap.put("cs", "czech"); + languageMap.put("cy", "welsh"); + languageMap.put("da", "danish"); + languageMap.put("de", "german"); + languageMap.put("dsb", "lsorbian"); + languageMap.put("dv", "divehi"); + languageMap.put("el", "greek"); + languageMap.put("en", "english"); + languageMap.put("eo", "esperanto"); + languageMap.put("es", "spanish"); + languageMap.put("et", "estonian"); + languageMap.put("eu", "basque"); + languageMap.put("fa", "farsi"); + languageMap.put("fi", "finnish"); + languageMap.put("fr", "french"); + languageMap.put("ga", "irish"); + languageMap.put("gd", "scottish"); + languageMap.put("gl", "galician"); + languageMap.put("grc", "greek"); + languageMap.put("he", "hebrew"); + languageMap.put("hi", "hindi"); + languageMap.put("hr", "croatian"); + languageMap.put("hsb", "usorbian"); + languageMap.put("hu", "magyar"); + languageMap.put("hy", "armenian"); + languageMap.put("id", "bahasai"); // Bahasa Indonesia + languageMap.put("ie", "interlingua"); + languageMap.put("is", "icelandic"); + languageMap.put("it", "italian"); + languageMap.put("la", "latin"); + languageMap.put("lo", "lao"); + languageMap.put("lt", "lithuanian"); + languageMap.put("lv", "latvian"); + languageMap.put("ml", "malayalam"); + languageMap.put("mr", "marathi"); + languageMap.put("ms", "bahasam"); // Bahasa Melayu + languageMap.put("nb", "norsk"); + languageMap.put("nl", "dutch"); + languageMap.put("nn", "nynorsk"); + languageMap.put("oc", "occitan"); + languageMap.put("pl", "polish"); + languageMap.put("pt", "portuges"); + languageMap.put("pt-BR", "brazilian"); + languageMap.put("ro", "romanian"); + languageMap.put("ru", "russian"); + languageMap.put("sa", "sanskrit"); + languageMap.put("sk", "slovak"); + languageMap.put("sl", "slovenian"); + languageMap.put("sq", "albanian"); + languageMap.put("sr", "serbian"); + languageMap.put("sv", "swedish"); + languageMap.put("syr", "syriac"); + languageMap.put("ta", "tamil"); + languageMap.put("te", "telugu"); + languageMap.put("th", "thai"); + languageMap.put("tk", "turkmen"); + languageMap.put("tr", "turkish"); + languageMap.put("uk", "ukrainian"); + languageMap.put("ur", "urdu"); + languageMap.put("vi", "vietnamese"); + // TODO: Which language is samin?? One guess could be sami with the n for north? + //languageMap.put("??", "samin"); + + variantMap = new HashMap(); + // English variants + variantMap.put("en-US", "american"); + variantMap.put("en-GB", "british"); + variantMap.put("en-AU", "australian"); + variantMap.put("en-NZ", "newzealand"); + // Greek variants + variantMap.put("el", "monotonic"); + variantMap.put("grc", "ancient"); // Supported in OOo since 3.2 + } + + private static String getEntry(Map map, String sLocale, String sLang) { + if (map.containsKey(sLocale)) { + return map.get(sLocale); + } + else if (map.containsKey(sLang)) { + return map.get(sLang); + } + return null; + } + + // This ended the static part of Polyglossia + + private Set languages = new HashSet(); + private List declarations = new ArrayList(); + private Map commands = new HashMap(); + + /**

Get the declarations for the applied languages, in the form

+ *

\\usepackage{polyglossia}

+ *

\\setdefaultlanguage{language1}

+ *

\\setotherlanguage{language2}

+ *

\\setotherlanguage{language3}

+ *

...

+ * + * @return the declarations as a string array + */ + public String[] getDeclarations() { + return declarations.toArray(new String[declarations.size()]); + } + + /**

Add the given locale to the list of applied locales and return definitions for applying the + * language to a text portion:

+ *
    + *
  • A command of the forn \textlanguage[variant=languagevariant]
  • + *
  • An environment in the form + * \begin{language}[variant=languagevariant]...\end{language}
  • + *
+ *

The first applied language is the default language

+ * + * @param sLang The language + * @param sCountry The country (may be null) + * @return a string array containing definitions to apply the language: Entry 0 contains a command + * and Entry 1 and 2 contains an environment + */ + public String[] applyLanguage(String sLang, String sCountry) { + String sLocale = sCountry!=null ? sLang+"-"+sCountry : sLang; + if (commands.containsKey(sLocale)) { + return commands.get(sLocale); + } + else { + // Get the Polyglossia language and variant + String sPolyLang = getEntry(languageMap,sLocale,sLang); + if (sPolyLang!=null) { + String sVariant = getEntry(variantMap,sLocale,sLang); + if (sVariant!=null) { + sVariant = "[variant="+sVariant+"]"; + } + else { + sVariant = ""; + } + + if (languages.size()==0) { + // First language, load Polyglossia and make the language default + declarations.add("\\usepackage{polyglossia}"); + declarations.add("\\setdefaultlanguage"+sVariant+"{"+sPolyLang+"}"); + languages.add(sPolyLang); + sVariant = ""; // Do not apply variant directly + } + else if (!languages.contains(sPolyLang)) { + // New language, add to declarations + declarations.add("\\setotherlanguage"+sVariant+"{"+sPolyLang+"}"); + languages.add(sPolyLang); + sVariant = ""; // Do not apply variant directly + } + + String[] sCommand = new String[3]; + sCommand[0] = "\\text"+sPolyLang+sVariant; + if ("arabic".equals(sPolyLang)) { sPolyLang="Arabic"; } + sCommand[1] = "\\begin{"+sPolyLang+"}"+sVariant; + sCommand[2] = "\\end{"+sPolyLang+"}"; + commands.put(sLocale, sCommand); + return sCommand; + } + else { + // Unknown language + String[] sCommand = new String[3]; + sCommand[0] = ""; + sCommand[1] = ""; + sCommand[2] = ""; + commands.put(sLocale, sCommand); + return sCommand; + } + } + } +} diff --git a/source/java/writer2latex/latex/i18n/XeTeXI18n.java b/source/java/writer2latex/latex/i18n/XeTeXI18n.java index 09d585c..4a85a10 100644 --- a/source/java/writer2latex/latex/i18n/XeTeXI18n.java +++ b/source/java/writer2latex/latex/i18n/XeTeXI18n.java @@ -20,7 +20,7 @@ * * All Rights Reserved. * - * Version 1.2 (2010-11-30) + * Version 1.2 (2010-12-15) * */ @@ -36,7 +36,7 @@ import writer2latex.latex.util.BeforeAfter; */ public class XeTeXI18n extends I18n { - // **** Constructors **** + private Polyglossia polyglossia; /** Construct a new XeTeXI18n as ConverterHelper * @param ofr the OfficeReader to get language information from @@ -45,6 +45,7 @@ public class XeTeXI18n extends I18n { */ public XeTeXI18n(OfficeReader ofr, LaTeXConfig config, ConverterPalette palette) { super(ofr,config,palette); + polyglossia = new Polyglossia(); } /** Add declarations to the preamble to load the required packages @@ -56,17 +57,33 @@ public class XeTeXI18n extends I18n { .append("\\usepackage{fontspec}").nl() .append("\\usepackage{xunicode}").nl() .append("\\usepackage{xltxtra}").nl(); - + String[] polyglossiaDeclarations = polyglossia.getDeclarations(); + for (String s: polyglossiaDeclarations) { + pack.append(s).nl(); + } } /** Apply a language language - * @param style the OOo style to read attributesfrom + * @param style the OOo style to read attributes from * @param bDecl true if declaration form is required * @param bInherit true if inherited properties should be used * @param ba the BeforeAfter to add LaTeX code to. */ public void applyLanguage(StyleWithProperties style, boolean bDecl, boolean bInherit, BeforeAfter ba) { - // TODO (polyglossia) + if (!bAlwaysUseDefaultLang && style!=null) { + // TODO: Support CTL and CJK + String sISOLang = style.getProperty(XMLString.FO_LANGUAGE,bInherit); + String sISOCountry = style.getProperty(XMLString.FO_COUNTRY, bInherit); + if (sISOLang!=null) { + String[] sCommand = polyglossia.applyLanguage(sISOLang, sISOCountry); + if (bDecl) { + ba.add(sCommand[1],sCommand[2]); + } + else { + ba.add(sCommand[0]+"{","}"); + } + } + } } /** Push a font to the font stack diff --git a/source/java/writer2latex/office/MetaData.java b/source/java/writer2latex/office/MetaData.java index 111aba8..d78c7b5 100644 --- a/source/java/writer2latex/office/MetaData.java +++ b/source/java/writer2latex/office/MetaData.java @@ -26,6 +26,9 @@ package writer2latex.office; +import java.util.HashMap; +import java.util.Map; + import org.w3c.dom.Document; import org.w3c.dom.Node; import org.w3c.dom.NodeList; @@ -49,6 +52,8 @@ public class MetaData implements writer2latex.api.MetaData { private String sSubject = ""; // Keywords private String sKeywords = ""; + // User-defined + private Map userdefined = new HashMap(); /**

Construct a new instance from an OOo Writer document.

* @param oooDoc is the OOo document @@ -74,28 +79,28 @@ public class MetaData implements writer2latex.api.MetaData { if (XMLString.DC_TITLE.equals(sName)) { sTitle = getContent(child); } - if (XMLString.DC_CREATOR.equals(sName)) { + else if (XMLString.DC_CREATOR.equals(sName)) { sCreator = getContent(child); } - if (XMLString.DC_DATE.equals(sName)) { + else if (XMLString.DC_DATE.equals(sName)) { sDate = getContent(child); } - if (XMLString.DC_DESCRIPTION.equals(sName)) { + else if (XMLString.DC_DESCRIPTION.equals(sName)) { sDescription = getContent(child); } - if (XMLString.DC_LANGUAGE.equals(sName)) { + else if (XMLString.DC_LANGUAGE.equals(sName)) { sLanguage = getContent(child); } - if (XMLString.DC_SUBJECT.equals(sName)) { + else if (XMLString.DC_SUBJECT.equals(sName)) { sSubject = getContent(child); } - if (XMLString.META_INITIAL_CREATOR.equals(sName)) { + else if (XMLString.META_INITIAL_CREATOR.equals(sName)) { sInitialCreator = getContent(child); } - if (XMLString.META_KEYWORD.equals(sName)) { // oasis + else if (XMLString.META_KEYWORD.equals(sName)) { // oasis keywords.addValue(getContent(child)); } - if (XMLString.META_KEYWORDS.equals(sName)) { + else if (XMLString.META_KEYWORDS.equals(sName)) { // Old format: Keywords are contained within meta:keywords if (child.hasChildNodes()) { // traverse the keywords @@ -109,36 +114,42 @@ public class MetaData implements writer2latex.api.MetaData { } } } + else if (XMLString.META_USER_DEFINED.equals(sName)) { + String sPropertyName = Misc.getAttribute(child, XMLString.META_NAME); + if (sPropertyName!=null) { + userdefined.put(sPropertyName,getContent(child)); + } + } } sKeywords = keywords.toString(); } - /**

Get the title of this document (may be null)

+ /**

Get the title of this document (may be empty)

* @return the title of the document */ public String getTitle() { return sTitle; } - /**

Get the creator of this document (may be null)

+ /**

Get the creator of this document (may be empty)

* @return the creator of the document (or the initial creator if none is specified) */ public String getCreator() { return sCreator==null ? sInitialCreator : sCreator; } - /**

Get the initial creator of this document (may be null)

+ /**

Get the initial creator of this document (may be empty)

* @return the initial creator of the document */ public String getInitialCreator() { return sInitialCreator; } - /**

Get the date of this document (may be null)

+ /**

Get the date of this document (may be empty)

* @return the date of the document */ public String getDate() { return sDate; } - /**

Get the description of this document (may be null)

+ /**

Get the description of this document (may be empty)

* @return the description of the document */ public String getDescription() { return sDescription; } - /**

Get the language of this document (may be null)

+ /**

Get the language of this document (may be empty)

* @return the language of the document */ public String getLanguage() { return sLanguage; } @@ -147,27 +158,32 @@ public class MetaData implements writer2latex.api.MetaData { this.sLanguage = sLanguage; } - /**

Get the subject of this document (may be null)

+ /**

Get the subject of this document (may be empty)

* @return the subject of the document */ public String getSubject() { return sSubject; } - /**

Get the keywords of this document as a comma separated list (may be null)

+ /**

Get the keywords of this document as a comma separated list (may be epmty)

* @return the keywords of the document */ public String getKeywords() { return sKeywords; } + /** Get the user-defined meta data + * + * @return the user-defined meta data as a name-value map + */ + public Map getUserDefinedMetaData() { return userdefined; } + private String getContent(Node node) { - if (!node.hasChildNodes()) { return null; } - String s=""; - NodeList list = node.getChildNodes(); - int nLen = list.getLength(); - for (int i=0; iDocument name. + * @param sName Document name. */ public CssDocument(String sName) { this.sName = sName; diff --git a/source/oxt/writer2latex/Options.xcu b/source/oxt/writer2latex/Options.xcu index 9c63f38..0515edc 100644 --- a/source/oxt/writer2latex/Options.xcu +++ b/source/oxt/writer2latex/Options.xcu @@ -36,7 +36,7 @@ true - 72 + 120 false diff --git a/source/oxt/writer2latex/help/en/org.openoffice.da.writer2latex.oxt/export.xhp b/source/oxt/writer2latex/help/en/org.openoffice.da.writer2latex.oxt/export.xhp index cf0ba98..85a702d 100644 --- a/source/oxt/writer2latex/help/en/org.openoffice.da.writer2latex.oxt/export.xhp +++ b/source/oxt/writer2latex/help/en/org.openoffice.da.writer2latex.oxt/export.xhp @@ -118,7 +118,8 @@ Use greek letters as symbols Check this treat greek characters as symbols rather than as text Greek letters used in latin text are often used as symbols, such as the - number π or the word γ-radiation. By checking this option, all greek letters used within latin or cyrillic text + number π or the word γ-radiation. By checking this option (not available if XeTeX is the backend), + all greek letters used within latin or cyrillic text will be treated as mathematical symbols, which will produce a slightly better result – and also not require that greek text fonts are available in the LaTeX installation. This option has no effect on greek text (provided the language is set correctly in the %PRODUCTNAME Writer document).