diff --git a/source/java/org/openoffice/da/comp/writer2latex/ApplicationsDialog.java b/source/java/org/openoffice/da/comp/writer2latex/ApplicationsDialog.java new file mode 100644 index 0000000..b02c972 --- /dev/null +++ b/source/java/org/openoffice/da/comp/writer2latex/ApplicationsDialog.java @@ -0,0 +1,485 @@ +/************************************************************************ + * + * ApplicationsDialog.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-2014 by Henrik Just + * + * All Rights Reserved. + * + * Version 1.6 (2014-10-29) + * + */ + +package org.openoffice.da.comp.writer2latex; + +import java.io.File; +import java.io.IOException; +import java.net.URI; +import java.net.URISyntaxException; +import java.util.Vector; + +import com.sun.star.awt.XControl; +import com.sun.star.awt.XControlContainer; +import com.sun.star.awt.XControlModel; +import com.sun.star.awt.XContainerWindowEventHandler; +import com.sun.star.awt.XDialog; +import com.sun.star.awt.XDialogProvider2; +import com.sun.star.awt.XWindow; +import com.sun.star.beans.XPropertySet; +import com.sun.star.lang.XMultiComponentFactory; +import com.sun.star.lang.XServiceInfo; +import com.sun.star.uno.AnyConverter; +import com.sun.star.uno.UnoRuntime; +import com.sun.star.uno.XComponentContext; + +import com.sun.star.lib.uno.helper.WeakBase; + +import org.openoffice.da.comp.w2lcommon.helper.DialogAccess; +import org.openoffice.da.comp.w2lcommon.helper.FilePicker; + +/** This class provides a uno component which implements the configuration + * of applications for the Writer2LaTeX toolbar + */ +public final class ApplicationsDialog + extends WeakBase + implements XServiceInfo, XContainerWindowEventHandler { + + private XComponentContext xContext; + private FilePicker filePicker; + + private ExternalApps externalApps; + + /** The component will be registered under this name. + */ + public static String __serviceName = "org.openoffice.da.writer2latex.ApplicationsDialog"; + + /** The component should also have an implementation name. + */ + public static String __implementationName = "org.openoffice.da.comp.writer2latex.ApplicationsDialog"; + + /** Create a new ApplicationsDialog */ + public ApplicationsDialog(XComponentContext xContext) { + this.xContext = xContext; + externalApps = new ExternalApps(xContext); + filePicker = new FilePicker(xContext); + } + + // Implement XContainerWindowEventHandler + public boolean callHandlerMethod(XWindow xWindow, Object event, String sMethod) + throws com.sun.star.lang.WrappedTargetException { + try { + if (sMethod.equals("external_event") ){ + return handleExternalEvent(xWindow, event); + } + else if (sMethod.equals("ApplicationChange")) { + return changeApplication(xWindow); + } + else if (sMethod.equals("BrowseClick")) { + return browseForExecutable(xWindow); + } + else if (sMethod.equals("ExecutableUnfocus")) { + return updateApplication(xWindow); + } + else if (sMethod.equals("OptionsUnfocus")) { + return updateApplication(xWindow); + } + else if (sMethod.equals("AutomaticClick")) { + return autoConfigure(xWindow); + } + } + catch (com.sun.star.uno.RuntimeException e) { + throw e; + } + catch (com.sun.star.uno.Exception e) { + throw new com.sun.star.lang.WrappedTargetException(sMethod, this, e); + } + return false; + } + + public String[] getSupportedMethodNames() { + String[] sNames = { "external_event", "ApplicationChange", "BrowseClick", "ExecutableUnfocus", "OptionsUnfocus", "AutomaticClick" }; + return sNames; + } + + // 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; + } + + // Private stuff + + private boolean handleExternalEvent(com.sun.star.awt.XWindow xWindow, Object aEventObject) + throws com.sun.star.uno.Exception { + try { + String sMethod = AnyConverter.toString(aEventObject); + if (sMethod.equals("ok")) { + externalApps.save(); + return true; + } else if (sMethod.equals("back") || sMethod.equals("initialize")) { + externalApps.load(); + return changeApplication(xWindow); + } + } + catch (com.sun.star.lang.IllegalArgumentException e) { + throw new com.sun.star.lang.IllegalArgumentException( + "Method external_event requires a string in the event object argument.", this,(short) -1); + } + return false; + } + + private boolean changeApplication(XWindow xWindow) { + String sAppName = getSelectedAppName(xWindow); + if (sAppName!=null) { + String[] s = externalApps.getApplication(sAppName); + setComboBoxText(xWindow, "Executable", s[0]); + setComboBoxText(xWindow, "Options", s[1]); + } + return true; + } + + private boolean browseForExecutable(XWindow xWindow) { + String sPath = filePicker.getPath(); + if (sPath!=null) { + try { + setComboBoxText(xWindow, "Executable", new File(new URI(sPath)).getCanonicalPath()); + } + catch (IOException e) { + } + catch (URISyntaxException e) { + } + updateApplication(xWindow); + } + return true; + } + + private boolean updateApplication(XWindow xWindow) { + String sAppName = getSelectedAppName(xWindow); + if (sAppName!=null) { + externalApps.setApplication(sAppName, getComboBoxText(xWindow, "Executable"), getComboBoxText(xWindow, "Options")); + } + return true; + } + + // Unix: Test to determine whether a certain application is available in the OS + // Requires "which", hence Unix only + private boolean hasApp(String sAppName) { + try { + Vector command = new Vector(); + command.add("which"); + command.add(sAppName); + + ProcessBuilder pb = new ProcessBuilder(command); + Process proc = pb.start(); + + // Gobble the error stream of the application + StreamGobbler errorGobbler = new + StreamGobbler(proc.getErrorStream(), "ERROR"); + + // Gobble the output stream of the application + StreamGobbler outputGobbler = new + StreamGobbler(proc.getInputStream(), "OUTPUT"); + + errorGobbler.start(); + outputGobbler.start(); + + // The application exists if the process exits with 0 + return proc.waitFor()==0; + } + catch (InterruptedException e) { + return false; + } + catch (IOException e) { + return false; + } + } + + // Unix: Configure a certain application testing the availability + private boolean configureApp(String sName, String sAppName, String sArguments) { + if (hasApp(sAppName)) { + externalApps.setApplication(sName, sAppName, sArguments); + return true; + } + else { + externalApps.setApplication(sName, "???", "???"); + return false; + } + } + + // Unix: Configure a certain application, reporting the availability + private boolean configureApp(String sName, String sAppName, String sArguments, StringBuilder info) { + if (hasApp(sAppName)) { + externalApps.setApplication(sName, sAppName, sArguments); + info.append("Found "+sAppName+" - OK\n"); + return true; + } + else { + externalApps.setApplication(sName, "???", "???"); + info.append("Failed to find "+sAppName+"\n"); + return false; + } + } + + // Unix: Configure a certain application testing the availability + // This variant uses an array of potential apps + private boolean configureApp(String sName, String[] sAppNames, String sArguments, StringBuilder info) { + for (String sAppName : sAppNames) { + if (configureApp(sName, sAppName, sArguments)) { + info.append("Found "+sName+": "+sAppName+" - OK\n"); + return true; + } + } + info.append("Failed to find "+sName+"\n"); + return false; + } + + // Windows: Test that the given path contains a given executable + private boolean containsExecutable(String sPath,String sExecutable) { + File dir = new File(sPath); + if (dir.exists() && dir.canRead()) { + File exe = new File(dir,sExecutable); + return exe.exists(); + } + return false; + } + + // Windows: Configure a certain MikTeX application + private boolean configureMikTeX(String sPath, String sName, String sAppName, String sArguments, StringBuilder info, boolean bRequired) { + File app = new File(new File(sPath),sAppName+".exe"); + if (app.exists()) { + externalApps.setApplication(sName, sAppName, sArguments); + info.append(" Found "+sName+": "+sAppName+" - OK\n"); + return true; + } + else if (bRequired) { + externalApps.setApplication(sName, "???", "???"); + info.append(" Failed to find "+sName+"\n"); + } + return false; + } + + // Configure the applications automatically (OS dependent) + private boolean autoConfigure(XWindow xWindow) { + String sOsName = System.getProperty("os.name"); + String sOsVersion = System.getProperty("os.version"); + String sOsArch = System.getProperty("os.arch"); + StringBuilder info = new StringBuilder(); + info.append("Results of configuration:\n\n"); + info.append("Your system identifies itself as "+sOsName+" version "+sOsVersion+ " (" + sOsArch +")\n\n"); + if (sOsName.startsWith("Windows")) { + // Assume MikTeX + String sMikTeXPath = null; + String[] sPaths = System.getenv("PATH").split(";"); + for (String s : sPaths) { + if (s.toLowerCase().indexOf("miktex")>-1 && containsExecutable(s,"latex.exe")) { + sMikTeXPath = s; + break; + } + } + if (sMikTeXPath==null) { + for (String s : sPaths) { + if (containsExecutable(s,"latex.exe")) { + sMikTeXPath = s; + break; + } + } + } + + boolean bFoundTexworks = false; + if (sMikTeXPath!=null) { + info.append("Found MikTeX\n"); + configureMikTeX(sMikTeXPath, ExternalApps.LATEX, "latex", "--interaction=batchmode %s", info, true); + configureMikTeX(sMikTeXPath, ExternalApps.PDFLATEX, "pdflatex", "--interaction=batchmode %s", info, true); + configureMikTeX(sMikTeXPath, ExternalApps.XELATEX, "xelatex", "--interaction=batchmode %s", info, true); + configureMikTeX(sMikTeXPath, ExternalApps.DVIPS, "dvips", "%s", info, true); + configureMikTeX(sMikTeXPath, ExternalApps.BIBTEX, "bibtex", "%s", info, true); + configureMikTeX(sMikTeXPath, ExternalApps.MAKEINDEX, "makeindex", "%s", info, true); + //configureMikTeX(sMikTeXPath, ExternalApps.MK4HT, "mk4ht", "%c %s", info, true); + configureMikTeX(sMikTeXPath, ExternalApps.DVIVIEWER, "yap", "--single-instance %s", info, true); + // MikTeX 2.8 provides texworks for pdf viewing + bFoundTexworks = configureMikTeX(sMikTeXPath, ExternalApps.PDFVIEWER, "texworks", "%s", info, true); + } + else { + info.append("Failed to find MikTeX\n"); + info.append("Writer2LaTeX has been configured to work if MikTeX is added to your path\n"); + externalApps.setApplication(ExternalApps.LATEX, "latex", "--interaction=batchmode %s"); + externalApps.setApplication(ExternalApps.PDFLATEX, "pdflatex", "--interaction=batchmode %s"); + externalApps.setApplication(ExternalApps.XELATEX, "xelatex", "--interaction=batchmode %s"); + externalApps.setApplication(ExternalApps.DVIPS, "dvips", "%s"); + externalApps.setApplication(ExternalApps.BIBTEX, "bibtex", "%s"); + externalApps.setApplication(ExternalApps.MAKEINDEX, "makeindex", "%s"); + //externalApps.setApplication(ExternalApps.MK4HT, "mk4ht", "%c %s"); + externalApps.setApplication(ExternalApps.DVIVIEWER, "yap", "--single-instance %s"); + } + info.append("\n"); + + // Assume gsview for pdf and ps + String sGsview = null; + String sProgramFiles = System.getenv("ProgramFiles"); + if (sProgramFiles!=null) { + if (containsExecutable(sProgramFiles+"\\ghostgum\\gsview","gsview32.exe")) { + sGsview = sProgramFiles+"\\ghostgum\\gsview\\gsview32.exe"; + } + } + + if (sGsview!=null) { + info.append("Found gsview - OK\n"); + } + else { + info.append("Failed to find gsview\n"); + sGsview = "gsview32.exe"; // at least this helps a bit.. + } + if (!bFoundTexworks) { + externalApps.setApplication(ExternalApps.PDFVIEWER, sGsview, "-e \"%s\""); + } + externalApps.setApplication(ExternalApps.POSTSCRIPTVIEWER, sGsview, "-e \"%s\""); + + } + else { // Assume a Unix-like system supporting the "which" command + configureApp(ExternalApps.LATEX, "latex", "--interaction=batchmode %s",info); + configureApp(ExternalApps.PDFLATEX, "pdflatex", "--interaction=batchmode %s",info); + configureApp(ExternalApps.XELATEX, "xelatex", "--interaction=batchmode %s",info); + configureApp(ExternalApps.DVIPS, "dvips", "%s",info); + configureApp(ExternalApps.BIBTEX, "bibtex", "%s",info); + configureApp(ExternalApps.MAKEINDEX, "makeindex", "%s",info); + //configureApp(ExternalApps.MK4HT, "mk4ht", "%c %s",info); + // We have several possible viewers + String[] sDviViewers = {"evince", "okular", "xdvi"}; + configureApp(ExternalApps.DVIVIEWER, sDviViewers, "%s",info); + String[] sPdfViewers = {"evince", "okular", "xpdf"}; + configureApp(ExternalApps.PDFVIEWER, sPdfViewers, "%s",info); + String[] sPsViewers = {"evince", "okular", "ghostview"}; + configureApp(ExternalApps.POSTSCRIPTVIEWER, sPsViewers, "%s",info); + + } + // Maybe add some info for Ubuntu users + // sudo apt-get install texlive + // sudo apt-get install texlive-xetex + // sudo apt-get install texlive-latex-extra + // sudo apt-get install tex4ht + displayAutoConfigInfo(info.toString()); + changeApplication(xWindow); + return true; + } + + private String getSelectedAppName(XWindow xWindow) { + short nItem = getListBoxSelectedItem(xWindow, "Application"); + //String sAppName = null; + switch (nItem) { + case 0: return ExternalApps.LATEX; + case 1: return ExternalApps.PDFLATEX; + case 2: return ExternalApps.XELATEX; + case 3: return ExternalApps.DVIPS; + case 4: return ExternalApps.BIBTEX; + case 5: return ExternalApps.MAKEINDEX; + //case 6: return ExternalApps.MK4HT; + case 6: return ExternalApps.DVIVIEWER; + case 7: return ExternalApps.PDFVIEWER; + case 8: return ExternalApps.POSTSCRIPTVIEWER; + } + return "???"; + } + + 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 void displayAutoConfigInfo(String sText) { + XDialog xDialog = getDialog("W4LDialogs.AutoConfigInfo"); + if (xDialog!=null) { + DialogAccess info = new DialogAccess(xDialog); + info.setTextFieldText("Info", sText); + xDialog.execute(); + xDialog.endExecute(); + } + } + + // Some helpers copied from DialogBase + private XPropertySet getControlProperties(XWindow xWindow, String sControlName) { + XControlContainer xContainer = (XControlContainer) + UnoRuntime.queryInterface(XControlContainer.class, xWindow); + XControl xControl = xContainer.getControl(sControlName); + XControlModel xModel = xControl.getModel(); + XPropertySet xPropertySet = (XPropertySet) + UnoRuntime.queryInterface(XPropertySet.class, xModel); + return xPropertySet; + } + + private String getComboBoxText(XWindow xWindow, String sControlName) { + // Returns the text of a combobox + XPropertySet xPropertySet = getControlProperties(xWindow, sControlName); + try { + return (String) xPropertySet.getPropertyValue("Text"); + } + catch (Exception e) { + // Will fail if the control does not exist or is not a combo + return ""; + } + } + + private void setComboBoxText(XWindow xWindow, String sControlName, String sText) { + XPropertySet xPropertySet = getControlProperties(xWindow, 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 + } + } + + private short getListBoxSelectedItem(XWindow xWindow, String sControlName) { + // Returns the first selected element in case of a multiselection + XPropertySet xPropertySet = getControlProperties(xWindow, 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; + } + } + + + + + +} + + + diff --git a/source/java/org/openoffice/da/comp/writer2latex/BibliographyDialog.java b/source/java/org/openoffice/da/comp/writer2latex/BibliographyDialog.java new file mode 100644 index 0000000..4d9f078 --- /dev/null +++ b/source/java/org/openoffice/da/comp/writer2latex/BibliographyDialog.java @@ -0,0 +1,351 @@ +/************************************************************************ + * + * BibliographyDialog.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-2014 by Henrik Just + * + * All Rights Reserved. + * + * Version 1.6 (2014-10-29) + * + */ + +package org.openoffice.da.comp.writer2latex; + +import java.io.File; +import java.io.IOException; +import java.net.URI; +import java.net.URISyntaxException; + +import com.sun.star.awt.XContainerWindowEventHandler; +import com.sun.star.awt.XDialog; +import com.sun.star.awt.XWindow; +import com.sun.star.beans.XPropertySet; +import com.sun.star.frame.XDesktop; +import com.sun.star.frame.XModel; +import com.sun.star.lang.XComponent; +import com.sun.star.lang.XServiceInfo; +import com.sun.star.uno.AnyConverter; +import com.sun.star.uno.Exception; +import com.sun.star.uno.UnoRuntime; +import com.sun.star.uno.XComponentContext; +import com.sun.star.util.XChangesBatch; + +import com.sun.star.lib.uno.helper.WeakBase; + +import org.openoffice.da.comp.w2lcommon.helper.DialogAccess; +import org.openoffice.da.comp.w2lcommon.helper.FolderPicker; +import org.openoffice.da.comp.w2lcommon.helper.MessageBox; +import org.openoffice.da.comp.w2lcommon.helper.RegistryHelper; +import org.openoffice.da.comp.w2lcommon.helper.XPropertySetHelper; + +/** This class provides a uno component which implements the configuration + * of the bibliography for the Writer2LaTeX toolbar + */ +public final class BibliographyDialog + extends WeakBase + implements XServiceInfo, XContainerWindowEventHandler { + + public static final String REGISTRY_PATH = "/org.openoffice.da.Writer2LaTeX.toolbar.ToolbarOptions/BibliographyOptions"; + + private XComponentContext xContext; + private FolderPicker folderPicker; + + /** The component will be registered under this name. + */ + public static String __serviceName = "org.openoffice.da.writer2latex.BibliographyDialog"; + + /** The component should also have an implementation name. + */ + public static String __implementationName = "org.openoffice.da.comp.writer2latex.BibliographyDialog"; + + /** Create a new ConfigurationDialog */ + public BibliographyDialog(XComponentContext xContext) { + this.xContext = xContext; + folderPicker = new FolderPicker(xContext); + } + + + // Implement XContainerWindowEventHandler + public boolean callHandlerMethod(XWindow xWindow, Object event, String sMethod) + throws com.sun.star.lang.WrappedTargetException { + XDialog xDialog = (XDialog)UnoRuntime.queryInterface(XDialog.class, xWindow); + DialogAccess dlg = new DialogAccess(xDialog); + + try { + if (sMethod.equals("external_event") ){ + return handleExternalEvent(dlg, event); + } + else if (sMethod.equals("ConvertZoteroCitationsChange")) { + return convertZoteroCitationsChange(dlg); + } + else if (sMethod.equals("ConvertJabRefCitationsChange")) { + return convertJabRefCitationsChange(dlg); + } + else if (sMethod.equals("UseExternalBibTeXFilesChange")) { + return useExternalBibTeXFilesChange(dlg); + } + else if (sMethod.equals("UseNatbibChange")) { + return useNatbibChange(dlg); + } + else if (sMethod.equals("BibTeXLocationChange")) { + return bibTeXLocationChange(dlg); + } + else if (sMethod.equals("BibTeXDirClick")) { + return bibTeXDirClick(dlg); + } + } + catch (com.sun.star.uno.RuntimeException e) { + throw e; + } + catch (com.sun.star.uno.Exception e) { + throw new com.sun.star.lang.WrappedTargetException(sMethod, this, e); + } + return false; + } + + public String[] getSupportedMethodNames() { + String[] sNames = { "external_event", "UseExternalBibTeXFilesChange", "ConvertZoteroCitationsChange", + "ConvertJabRefCitationsChange", "UseNatbibChange", "BibTeXLocationChange", "ExternalBibTeXDirClick" }; + return sNames; + } + + // 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; + } + + // Private stuff + + private boolean handleExternalEvent(DialogAccess dlg, Object aEventObject) + throws com.sun.star.uno.Exception { + try { + String sMethod = AnyConverter.toString(aEventObject); + if (sMethod.equals("ok")) { + saveConfiguration(dlg); + return true; + } else if (sMethod.equals("back") || sMethod.equals("initialize")) { + loadConfiguration(dlg); + enableBibTeXSettings(dlg); + useNatbibChange(dlg); + return true; + } + } + catch (com.sun.star.lang.IllegalArgumentException e) { + throw new com.sun.star.lang.IllegalArgumentException( + "Method external_event requires a string in the event object argument.", this,(short) -1); + } + return false; + } + + // Load settings from the registry into the dialog + private void loadConfiguration(DialogAccess dlg) { + RegistryHelper registry = new RegistryHelper(xContext); + try { + Object view = registry.getRegistryView(REGISTRY_PATH, false); + XPropertySet xProps = (XPropertySet) UnoRuntime.queryInterface(XPropertySet.class,view); + dlg.setCheckBoxStateAsBoolean("UseExternalBibTeXFiles", + XPropertySetHelper.getPropertyValueAsBoolean(xProps, "UseExternalBibTeXFiles")); + dlg.setCheckBoxStateAsBoolean("ConvertZoteroCitations", + XPropertySetHelper.getPropertyValueAsBoolean(xProps, "ConvertZoteroCitations")); + dlg.setCheckBoxStateAsBoolean("ConvertJabRefCitations", + XPropertySetHelper.getPropertyValueAsBoolean(xProps, "ConvertJabRefCitations")); + dlg.setCheckBoxStateAsBoolean("IncludeOriginalCitations", + XPropertySetHelper.getPropertyValueAsBoolean(xProps, "IncludeOriginalCitations")); + dlg.setListBoxSelectedItem("BibTeXLocation", + XPropertySetHelper.getPropertyValueAsShort(xProps, "BibTeXLocation")); + dlg.setTextFieldText("BibTeXDir", + XPropertySetHelper.getPropertyValueAsString(xProps, "BibTeXDir")); + dlg.setCheckBoxStateAsBoolean("UseNatbib", + XPropertySetHelper.getPropertyValueAsBoolean(xProps, "UseNatbib")); + dlg.setTextFieldText("NatbibOptions", + XPropertySetHelper.getPropertyValueAsString(xProps, "NatbibOptions")); + registry.disposeRegistryView(view); + } + catch (Exception e) { + // Failed to get registry view + } + + // Update dialog according to the settings + convertZoteroCitationsChange(dlg); + useExternalBibTeXFilesChange(dlg); + } + + // Save settings from the dialog to the registry + private void saveConfiguration(DialogAccess dlg) { + RegistryHelper registry = new RegistryHelper(xContext); + try { + Object view = registry.getRegistryView(REGISTRY_PATH, true); + XPropertySet xProps = (XPropertySet) UnoRuntime.queryInterface(XPropertySet.class,view); + XPropertySetHelper.setPropertyValue(xProps, "UseExternalBibTeXFiles", dlg.getCheckBoxStateAsBoolean("UseExternalBibTeXFiles")); + XPropertySetHelper.setPropertyValue(xProps, "ConvertZoteroCitations", dlg.getCheckBoxStateAsBoolean("ConvertZoteroCitations")); + XPropertySetHelper.setPropertyValue(xProps, "ConvertJabRefCitations", dlg.getCheckBoxStateAsBoolean("ConvertJabRefCitations")); + XPropertySetHelper.setPropertyValue(xProps, "IncludeOriginalCitations", dlg.getCheckBoxStateAsBoolean("IncludeOriginalCitations")); + XPropertySetHelper.setPropertyValue(xProps, "BibTeXLocation", dlg.getListBoxSelectedItem("BibTeXLocation")); + XPropertySetHelper.setPropertyValue(xProps, "BibTeXDir", dlg.getTextFieldText("BibTeXDir")); + XPropertySetHelper.setPropertyValue(xProps, "UseNatbib", dlg.getCheckBoxStateAsBoolean("UseNatbib")); + XPropertySetHelper.setPropertyValue(xProps, "NatbibOptions", dlg.getTextFieldText("NatbibOptions")); + + // Commit registry changes + XChangesBatch xUpdateContext = (XChangesBatch) + UnoRuntime.queryInterface(XChangesBatch.class,view); + try { + xUpdateContext.commitChanges(); + } + catch (Exception e) { + // ignore + } + + registry.disposeRegistryView(view); + } + catch (Exception e) { + // Failed to get registry view + } + } + + private boolean useExternalBibTeXFilesChange(DialogAccess dlg) { + enableBibTeXSettings(dlg); + return true; + } + + private boolean convertZoteroCitationsChange(DialogAccess dlg) { + enableBibTeXSettings(dlg); + return true; + } + + private boolean convertJabRefCitationsChange(DialogAccess dlg) { + enableBibTeXSettings(dlg); + return true; + } + + private boolean useNatbibChange(DialogAccess dlg) { + boolean bUseNatbib = dlg.getCheckBoxStateAsBoolean("UseNatbib"); + dlg.setControlEnabled("NatbibOptionsLabel", bUseNatbib); + dlg.setControlEnabled("NatbibOptions", bUseNatbib); + return true; + } + + private boolean bibTeXLocationChange(DialogAccess dlg) { + enableBibTeXSettings(dlg); + return true; + } + + private void enableBibTeXSettings(DialogAccess dlg) { + boolean bConvertZoteroJabRef = dlg.getCheckBoxStateAsBoolean("ConvertZoteroCitations") + || dlg.getCheckBoxStateAsBoolean("ConvertJabRefCitations"); + boolean bEnableLocation = dlg.getCheckBoxStateAsBoolean("UseExternalBibTeXFiles") || bConvertZoteroJabRef; + boolean bEnableDir = dlg.getListBoxSelectedItem("BibTeXLocation")<2; + dlg.setControlEnabled("IncludeOriginalCitations", bConvertZoteroJabRef); + dlg.setControlEnabled("BibTeXLocationLabel", bEnableLocation); + dlg.setControlEnabled("BibTeXLocation", bEnableLocation); + dlg.setControlEnabled("BibTeXDirLabel", bEnableLocation && bEnableDir); + dlg.setControlEnabled("BibTeXDir", bEnableLocation && bEnableDir); + dlg.setControlEnabled("BibTeXDirButton", bEnableLocation && bEnableDir); + } + + private String getDocumentDirURL() { + // Get the desktop from the service manager + Object desktop=null; + try { + desktop = xContext.getServiceManager().createInstanceWithContext("com.sun.star.frame.Desktop", xContext); + } catch (Exception e) { + // Failed to get the desktop service + return ""; + } + XDesktop xDesktop = (XDesktop) UnoRuntime.queryInterface(XDesktop.class, desktop); + + // Get the current component and verify that it really is a text document + if (xDesktop!=null) { + XComponent xComponent = xDesktop.getCurrentComponent(); + XServiceInfo xInfo = (XServiceInfo)UnoRuntime.queryInterface(XServiceInfo.class, xComponent); + if (xInfo!=null && xInfo.supportsService("com.sun.star.text.TextDocument")) { + // Get the model, which provides the URL + XModel xModel = (XModel) UnoRuntime.queryInterface(XModel.class, xComponent); + if (xModel!=null) { + String sURL = xModel.getURL(); + int nSlash = sURL.lastIndexOf('/'); + return nSlash>-1 ? sURL.substring(0, nSlash) : ""; + } + } + } + + return ""; + } + + private boolean hasBibTeXFiles(File dir) { + if (dir.isDirectory()) { + File[] files = dir.listFiles(); + for (File file : files) { + if (file.isFile() && file.getName().endsWith(".bib")) { + return true; + } + } + } + return false; + } + + private boolean bibTeXDirClick(DialogAccess dlg) { + String sPath = folderPicker.getPath(); + if (sPath!=null) { + try { + File bibDir = new File(new URI(sPath)); + String sBibPath = bibDir.getCanonicalPath(); + if (dlg.getListBoxSelectedItem("BibTeXLocation")==1) { + // Path relative to document directory, remove the document directory part + String sDocumentDirURL = getDocumentDirURL(); + if (sDocumentDirURL.length()>0) { + String sDocumentDirPath = new File(new URI(sDocumentDirURL)).getCanonicalPath(); + if (sBibPath.startsWith(sDocumentDirPath)) { + if (sBibPath.length()>sDocumentDirPath.length()) { + sBibPath = sBibPath.substring(sDocumentDirPath.length()+1); + } + else { // Same as document directory + sBibPath = ""; + } + } + else { // not a subdirectory + sBibPath = ""; + } + } + } + dlg.setTextFieldText("BibTeXDir", sBibPath); + if (!hasBibTeXFiles(bibDir)) { + MessageBox msgBox = new MessageBox(xContext); + msgBox.showMessage("Writer2LaTeX", "Warning: The selected directory does not contain any BibTeX files"); + } + } + catch (IOException e) { + } + catch (URISyntaxException e) { + } + } + return true; + } + +} + + + diff --git a/source/java/org/openoffice/da/comp/writer2latex/DeTeXtive.java b/source/java/org/openoffice/da/comp/writer2latex/DeTeXtive.java new file mode 100644 index 0000000..2a6fdba --- /dev/null +++ b/source/java/org/openoffice/da/comp/writer2latex/DeTeXtive.java @@ -0,0 +1,221 @@ +/************************************************************************ + * + * DeTeXtive.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-2014 by Henrik Just + * + * All Rights Reserved. + * + * Version 1.4 (2014-09-24) + * + */ + +package org.openoffice.da.comp.writer2latex; + +import java.io.InputStream; +import java.io.InputStreamReader; +import java.io.IOException; +import java.util.HashSet; + +import org.openoffice.da.comp.w2lcommon.tex.tokenizer.Mouth; +import org.openoffice.da.comp.w2lcommon.tex.tokenizer.Token; +import org.openoffice.da.comp.w2lcommon.tex.tokenizer.TokenType; + +/** This class analyzes a stream and detects if it is a TeX stream. + * Currently it is able to identify LaTeX and XeLaTeX (ConTeXt and plain TeX may be + * added later). + */ +public class DeTeXtive { + private Mouth mouth; + private Token token; + + private HashSet packages; + + /** Construct a new DeTeXtive + */ + public DeTeXtive() { + } + + /** Detect the format of a given stream + * + * @param is the input stream + * @return a string representing the detected format; null if the format is unknown. + * Currently the values "LaTeX", "XeLaTeX" are supported. + * @throws IOException if we fail to read the stream + */ + public String deTeXt(InputStream is) throws IOException { + // It makes no harm to assume that the stream uses ISO Latin1 - we only consider ASCII characters + mouth = new Mouth(new InputStreamReader(is,"ISO8859_1")); + token = mouth.getTokenObject(); + + packages = new HashSet(); + + mouth.getToken(); + + if (parseHeader() && parsePreamble()) { + if (packages.contains("xunicode")) { + return "XeLaTeX"; + } + else { + return "LaTeX"; + } + } + + // Unknown format + return null; + + } + + // The parser! + + // Parse a LaTeX header such as \documentclass[a4paper]{article} + // Return true in case of success + private boolean parseHeader() throws IOException { + skipBlanks(); + if (token.isCS("documentclass") || token.isCS("documentstyle")) { + // The first non-blank token is \documentclass or \documentstyle => could be a LaTeX document + //System.out.println("** Found "+token.toString()); + mouth.getToken(); + skipSpaces(); + // Skip options, if any + if (token.is('[',TokenType.OTHER)) { + skipOptional(); + skipSpaces(); + } + if (token.getType()==TokenType.BEGIN_GROUP) { + // Get class name + String sClassName = parseArgumentAsString(); + //System.out.println("** Found the class name "+sClassName); + // Accept any class name of one or more characters + if (sClassName.length()>0) { return true; } + } + } + //System.out.println("** Doesn't look like LaTeX; failed to get class name"); + return false; + } + + // Parse a LaTeX preamble + // Return true in case of success (that is, \begin{document} was found) + private boolean parsePreamble() throws IOException { + while (token.getType()!=TokenType.ENDINPUT) { + if (token.isCS("usepackage")) { + // We collect the names of all used packages, but discard their options + // (Recall that this is only relevant for LaTeX 2e) + mouth.getToken(); + skipSpaces(); + if (token.is('[',TokenType.OTHER)) { + skipOptional(); + skipSpaces(); + } + String sName = parseArgumentAsString(); + //System.out.println("** Found package "+sName); + packages.add(sName); + } + else if (token.getType()==TokenType.BEGIN_GROUP) { + // We ignore anything inside a group + skipGroup(); + } + else if (token.isCS("begin")) { + // This would usually indicate the end of the preamble + mouth.getToken(); + skipSpaces(); + if ("document".equals(parseArgumentAsString())) { + //System.out.println("Found \\begin{document}"); + return true; + } + } + else { + // Any other content in the preamble is simply ignored + mouth.getToken(); + } + } + //System.out.println("** Doesn't look like LaTeX; failed to find \\begin{document}"); + return false; + } + + private void skipBlanks() throws IOException { + while (token.getType()==TokenType.SPACE || token.isCS("par")) { + mouth.getToken(); + } + } + + private void skipSpaces() throws IOException { + // Actually, we will never get two space tokens in a row + while (token.getType()==TokenType.SPACE) { + mouth.getToken(); + } + } + + private void skipOptional() throws IOException { + assert token.is('[', TokenType.OTHER); + + mouth.getToken(); // skip the [ + while (!token.is(']',TokenType.OTHER) && token.getType()!=TokenType.ENDINPUT) { + if (token.getType()==TokenType.BEGIN_GROUP) { + skipGroup(); + } + else { + mouth.getToken(); // skip this token + } + } + mouth.getToken(); // skip the ] + } + + private void skipGroup() throws IOException { + assert token.getType()==TokenType.BEGIN_GROUP; + + mouth.getToken(); // skip the { + while (token.getType()!=TokenType.END_GROUP && token.getType()!=TokenType.ENDINPUT) { + if (token.getType()==TokenType.BEGIN_GROUP) { + skipGroup(); + } + else { + mouth.getToken(); // skip this token + } + } + mouth.getToken(); // skip the } + } + + private String parseArgumentAsString() throws IOException { + if (token.getType()==TokenType.BEGIN_GROUP) { + // Argument is contained in a group + mouth.getToken(); // skip the { + StringBuilder sb = new StringBuilder(); + while (token.getType()!=TokenType.END_GROUP && token.getType()!=TokenType.ENDINPUT) { + if (token.getType()!=TokenType.COMMAND_SEQUENCE) { + // should not include cs, ignore if it happens + sb.append(token.getChar()); + } + mouth.getToken(); + } + mouth.getToken(); // skip the } + return sb.toString(); + } + else { + // Argument is a single token + String s = ""; + if (token.getType()!=TokenType.COMMAND_SEQUENCE) { + // should not include cs, ignore if it happens + s = token.getString(); + } + mouth.getToken(); + return s; + } + } + + +} diff --git a/source/java/org/openoffice/da/comp/writer2latex/ExternalApps.java b/source/java/org/openoffice/da/comp/writer2latex/ExternalApps.java new file mode 100644 index 0000000..c086e7b --- /dev/null +++ b/source/java/org/openoffice/da/comp/writer2latex/ExternalApps.java @@ -0,0 +1,236 @@ +/************************************************************************ + * + * ExternalApps.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-2014 by Henrik Just + * + * All Rights Reserved. + * + * Version 1.6 (2014-10-29) + * + */ + +package org.openoffice.da.comp.writer2latex; + +import java.io.File; +import java.io.IOException; +import java.lang.Process; +import java.lang.ProcessBuilder; +import java.util.HashMap; +import java.util.Map; +import java.util.Vector; + +import org.openoffice.da.comp.w2lcommon.helper.RegistryHelper; +//import java.util.Map; + +import com.sun.star.beans.XMultiHierarchicalPropertySet; +import com.sun.star.uno.UnoRuntime; +import com.sun.star.uno.XComponentContext; +import com.sun.star.util.XChangesBatch; + + +/** This class manages and executes external applications used by the Writer2LaTeX toolbar. + * These include TeX and friends as well as viewers for the various backend formats. + * The registry is used for persistent storage of the settings. + */ +public class ExternalApps { + + public final static String LATEX = "LaTeX"; + public final static String PDFLATEX = "PdfLaTeX"; + public final static String XELATEX = "XeLaTeX"; + public final static String BIBTEX = "BibTeX"; + public final static String MAKEINDEX = "Makeindex"; + public final static String MK4HT = "Mk4ht"; + public final static String DVIPS = "Dvips"; + public final static String DVIVIEWER = "DVIViewer"; + public final static String POSTSCRIPTVIEWER = "PostscriptViewer"; + public final static String PDFVIEWER = "PdfViewer"; + + private final static String[] sApps = { LATEX, PDFLATEX, XELATEX, BIBTEX, MAKEINDEX, MK4HT, DVIPS, DVIVIEWER, POSTSCRIPTVIEWER, PDFVIEWER }; + + private XComponentContext xContext; + + private HashMap apps; + + /** Construct a new ExternalApps object, with empty definitions */ + public ExternalApps(XComponentContext xContext) { + this.xContext = xContext; + apps = new HashMap(); + for (int i=0; i env, boolean bWaitFor) { + return execute(sAppName, "", sFileName, workDir, env, bWaitFor); + } + + /** Execute an external application + * @param sAppName the name of the application to execute + * @param sCommand subcommand/option to pass to the command + * @param sFileName the file name to use + * @param workDir the working directory to use + * @param env map of environment variables to set (or null if no variables needs to be set) + * @param bWaitFor true if the method should wait for the execution to finish + * @return error code + */ + public int execute(String sAppName, String sCommand, String sFileName, File workDir, Map env, boolean bWaitFor) { + // Assemble the command + String[] sApp = getApplication(sAppName); + if (sApp==null) { return 1; } + + try { + Vector command = new Vector(); + command.add(sApp[0]); + String[] sArguments = sApp[1].split(" "); + for (String s : sArguments) { + command.add(s.replace("%c",sCommand).replace("%s",sFileName)); + } + + ProcessBuilder pb = new ProcessBuilder(command); + pb.directory(workDir); + if (env!=null) { + pb.environment().putAll(env); + } + Process proc = pb.start(); + + // Gobble the error stream of the application + StreamGobbler errorGobbler = new + StreamGobbler(proc.getErrorStream(), "ERROR"); + + // Gobble the output stream of the application + StreamGobbler outputGobbler = new + StreamGobbler(proc.getInputStream(), "OUTPUT"); + + // Kick them off + errorGobbler.start(); + outputGobbler.start(); + + // Any error? + return bWaitFor ? proc.waitFor() : 0; + } + catch (InterruptedException e) { + return 1; + } + catch (IOException e) { + return 1; + } + } + + /** Load the external applications from the registry + */ + public void load() { + RegistryHelper registry = new RegistryHelper(xContext); + Object view; + try { + // Prepare registry view + view = registry.getRegistryView("/org.openoffice.da.Writer2LaTeX.toolbar.ToolbarOptions/Applications",false); + } + catch (com.sun.star.uno.Exception e) { + // Give up... + return; + } + + XMultiHierarchicalPropertySet xProps = (XMultiHierarchicalPropertySet) + UnoRuntime.queryInterface(XMultiHierarchicalPropertySet.class, view); + for (int i=0; i 0 ) { + if (object[0] instanceof String) { + sBaseUrl = (String) object[0]; + } + } + } + + // Implement XDialogEventHandler + public boolean callHandlerMethod(XDialog xDialog, Object event, String sMethod) { + if (sMethod.equals("ViewLaTeXLog")) { + setComboBoxText("LogContents", sLaTeXLog); + } + else if (sMethod.equals("ViewBibTeXLog")) { + setComboBoxText("LogContents", sBibTeXLog); + } + else if (sMethod.equals("ViewMakeindexLog")) { + setComboBoxText("LogContents", sMakeindexLog); + } + return true; + } + + public String[] getSupportedMethodNames() { + String[] sNames = { "ViewLaTeXLog", "ViewBibTeXLog", "ViewMakeindexLog" }; + return sNames; + } + + // Utility methods + + private String readTextFile(String sUrl) { + StringBuilder buf = new StringBuilder(); + try { + File file = new File(new URI(sUrl)); + if (file.exists() && file.isFile()) { + InputStreamReader isr = new InputStreamReader(new FileInputStream(file)); + int n; + do { + n = isr.read(); + if (n>-1) { buf.append((char)n); } + } + while (n>-1); + isr.close(); + } + } + catch (URISyntaxException e) { + return ""; + } + catch (IOException e) { + return ""; + } + return buf.toString(); + } + +} + + + diff --git a/source/java/org/openoffice/da/comp/writer2latex/StreamGobbler.java b/source/java/org/openoffice/da/comp/writer2latex/StreamGobbler.java new file mode 100644 index 0000000..fecefec --- /dev/null +++ b/source/java/org/openoffice/da/comp/writer2latex/StreamGobbler.java @@ -0,0 +1,55 @@ +/************************************************************************ + * + * StreamGobbler.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.2 (2009-03-30) + * + */ + +package org.openoffice.da.comp.writer2latex; + +import java.io.*; + +class StreamGobbler extends Thread { + InputStream is; + String type; + + StreamGobbler(InputStream is, String type) { + this.is = is; + this.type = type; + } + + public void run() { + try { + InputStreamReader isr = new InputStreamReader(is); + BufferedReader br = new BufferedReader(isr); + //String line=null; + //while ( (line = br.readLine()) != null) { + while ( br.readLine() != null) { + // Do nothing... + } + } + catch (IOException ioe) { + ioe.printStackTrace(); + } + } +} + diff --git a/source/java/org/openoffice/da/comp/writer2latex/TeXDetectService.java b/source/java/org/openoffice/da/comp/writer2latex/TeXDetectService.java new file mode 100644 index 0000000..751d7f4 --- /dev/null +++ b/source/java/org/openoffice/da/comp/writer2latex/TeXDetectService.java @@ -0,0 +1,174 @@ +/************************************************************************ + * + * TeXDetectService.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-2014 by Henrik Just + * + * All Rights Reserved. + * + * Version 1.6 (2014-10-29) + * + */ + +package org.openoffice.da.comp.writer2latex; + +import java.io.IOException; + + +import com.sun.star.lib.uno.adapter.XInputStreamToInputStreamAdapter; +import com.sun.star.lib.uno.helper.WeakBase; + +import com.sun.star.beans.PropertyValue; +import com.sun.star.document.XExtendedFilterDetection; +import com.sun.star.lang.XServiceInfo; +import com.sun.star.io.XInputStream; +import com.sun.star.ucb.XSimpleFileAccess2; +import com.sun.star.uno.AnyConverter; +import com.sun.star.uno.UnoRuntime; +import com.sun.star.uno.XComponentContext; + + + +/** This class provides detect services for TeX documents + * It is thus an implementation of the service com.sun.star.document.ExtendedTypeDetection + */ + +public class TeXDetectService extends WeakBase implements XExtendedFilterDetection, XServiceInfo { + + // Constants + + // Identify this service + public static final String __implementationName = TeXDetectService.class.getName(); + public static final String __serviceName = "com.sun.star.document.ExtendedTypeDetection"; + private static final String[] m_serviceNames = { __serviceName }; + + // The type names + private static final String LATEX_FILE = "org.openoffice.da.writer2latex.LaTeX_File"; + private static final String XELATEX_FILE = "org.openoffice.da.writer2latex.XeLaTeX_File"; + + // From constructor+initialization +private final XComponentContext m_xContext; + + /** Construct a new TeXDetectService + * + * @param xContext The Component Context + */ + public TeXDetectService( XComponentContext xContext ) { + m_xContext = xContext; + } + + // Implement com.sun.star.lang.XServiceInfo: + public String getImplementationName() { + return __implementationName; + } + + public boolean supportsService( String sService ) { + int len = m_serviceNames.length; + + for(int i=0; i < len; i++) { + if (sService.equals(m_serviceNames[i])) + return true; + } + return false; + } + + public String[] getSupportedServiceNames() { + return m_serviceNames; + } + + // Implement XExtendedFilterDetection + public String detect(PropertyValue[][] mediaDescriptor) { + // Read the media properties + String sURL = null; + String sTypeName = null; + if (mediaDescriptor.length>0) { + int nLength = mediaDescriptor[0].length; + for (int i=0; iTeXImportFilter + * + * @param xContext The Component Context + */ + public TeXImportFilter( XComponentContext xContext ) { + m_xContext = xContext; + m_sFilterName = ""; + m_xTargetDoc = null; + m_nState = FILTERPROC_STOPPED; + } + + // Implement com.sun.star.lang.XServiceInfo: + public String getImplementationName() { + return __implementationName; + } + + public boolean supportsService( String sService ) { + int len = m_serviceNames.length; + + for(int i=0; i < len; i++) { + if (sService.equals(m_serviceNames[i])) + return true; + } + return false; + } + + public String[] getSupportedServiceNames() { + return m_serviceNames; + } + + // The following methods may be called from multiple threads (e.g. if someone wants to cancel the filtering), + // thus all access to class members must be synchronized + + // Implement XInitialization: + public void initialize( Object[] arguments ) throws com.sun.star.uno.Exception { + if (arguments.length>0) { + // The first argument contains configuration data, from which we extract the filter name for further reference + // We need this to know which flavour of TeX we're supposed to handle + PropertyValue[] config = (PropertyValue[]) arguments[0]; + int nLen = config.length; + for (int i=0; i0) { + throw new IOException("Error executing dvi viewer"); + } + } + else if (nBackend==PDFTEX) { + bResult = doTeXify(pdfTexify, file, sBibinputs); + if (!bResult) return false; + if (externalApps.execute(ExternalApps.PDFVIEWER, + new File(file.getParentFile(),file.getName()+".pdf").getPath(), + file.getParentFile(), null, false)>0) { + throw new IOException("Error executing pdf viewer"); + } + } + else if (nBackend==DVIPS) { + bResult = doTeXify(dvipsTexify, file, sBibinputs); + if (!bResult) return false; + if (externalApps.execute(ExternalApps.POSTSCRIPTVIEWER, + new File(file.getParentFile(),file.getName()+".ps").getPath(), + file.getParentFile(), null, false)>0) { + throw new IOException("Error executing postscript viewer"); + } + } + else if (nBackend==XETEX) { + bResult = doTeXify(xeTexify, file, sBibinputs); + if (!bResult) return false; + if (externalApps.execute(ExternalApps.PDFVIEWER, + new File(file.getParentFile(),file.getName()+".pdf").getPath(), + file.getParentFile(), null, false)>0) { + throw new IOException("Error executing pdf viewer"); + } + } + return bResult; + + } + + private boolean doTeXify(String[] sAppList, File file, String sBibinputs) throws IOException { + // Remove the .aux file first (to avoid potential error messages) + File aux = new File(file.getParentFile(), file.getName()+".aux"); + aux.delete(); + for (int i=0; i env =null; + if (ExternalApps.BIBTEX.equals(sAppList[i]) && sBibinputs!=null) { + env = new HashMap(); + env.put("BIBINPUTS", sBibinputs); + } + int nReturnCode = externalApps.execute( + sAppList[i], file.getName(), file.getParentFile(), env, true); + if (i==0 && nReturnCode>0) { + return false; + //throw new IOException("Error executing "+sAppList[i]); + } + } + + return true; + } + +} \ No newline at end of file diff --git a/source/java/org/openoffice/da/comp/writer2latex/W2LRegistration.java b/source/java/org/openoffice/da/comp/writer2latex/W2LRegistration.java index c1cda7d..dc4198e 100644 --- a/source/java/org/openoffice/da/comp/writer2latex/W2LRegistration.java +++ b/source/java/org/openoffice/da/comp/writer2latex/W2LRegistration.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-2014 by Henrik Just * * All Rights Reserved. * - * Version 1.2 (2009-09-06) + * Version 1.4 (2014-10-29) * */ @@ -84,6 +84,42 @@ public class W2LRegistration { multiFactory, regKey); } + else if (implName.equals(Writer2LaTeX.__implementationName) ) { + xSingleServiceFactory = FactoryHelper.getServiceFactory(Writer2LaTeX.class, + Writer2LaTeX.__serviceName, + multiFactory, + regKey); + } + else if (implName.equals(TeXImportFilter.__implementationName) ) { + xSingleServiceFactory = FactoryHelper.getServiceFactory(TeXImportFilter.class, + TeXImportFilter.__serviceName, + multiFactory, + regKey); + } + else if (implName.equals(TeXDetectService.__implementationName) ) { + xSingleServiceFactory = FactoryHelper.getServiceFactory(TeXDetectService.class, + TeXDetectService.__serviceName, + multiFactory, + regKey); + } + else if (implName.equals(ApplicationsDialog.__implementationName) ) { + xSingleServiceFactory = FactoryHelper.getServiceFactory(ApplicationsDialog.class, + ApplicationsDialog.__serviceName, + multiFactory, + regKey); + } + else if (implName.equals(BibliographyDialog.__implementationName) ) { + xSingleServiceFactory = FactoryHelper.getServiceFactory(BibliographyDialog.class, + BibliographyDialog.__serviceName, + multiFactory, + regKey); + } + else if (implName.equals(LogViewerDialog.__implementationName) ) { + xSingleServiceFactory = FactoryHelper.getServiceFactory(LogViewerDialog.class, + LogViewerDialog.__serviceName, + multiFactory, + regKey); + } return xSingleServiceFactory; } @@ -105,7 +141,19 @@ public class W2LRegistration { FactoryHelper.writeRegistryServiceInfo(W2LStarMathConverter.__implementationName, W2LStarMathConverter.__serviceName, regKey) & FactoryHelper.writeRegistryServiceInfo(ConfigurationDialog.__implementationName, - ConfigurationDialog.__serviceName, regKey); + ConfigurationDialog.__serviceName, regKey) & + FactoryHelper.writeRegistryServiceInfo(Writer2LaTeX.__implementationName, + Writer2LaTeX.__serviceName, regKey) & + FactoryHelper.writeRegistryServiceInfo(TeXImportFilter.__implementationName, + TeXImportFilter.__serviceName, regKey) & + FactoryHelper.writeRegistryServiceInfo(TeXDetectService.__implementationName, + TeXDetectService.__serviceName, regKey) & + FactoryHelper.writeRegistryServiceInfo(ApplicationsDialog.__implementationName, + ApplicationsDialog.__serviceName, regKey) & + FactoryHelper.writeRegistryServiceInfo(BibliographyDialog.__implementationName, + BibliographyDialog.__serviceName, regKey) & + FactoryHelper.writeRegistryServiceInfo(LogViewerDialog.__implementationName, + LogViewerDialog.__serviceName, regKey); } } diff --git a/source/java/org/openoffice/da/comp/writer2latex/Writer2LaTeX.java b/source/java/org/openoffice/da/comp/writer2latex/Writer2LaTeX.java new file mode 100644 index 0000000..c25b661 --- /dev/null +++ b/source/java/org/openoffice/da/comp/writer2latex/Writer2LaTeX.java @@ -0,0 +1,700 @@ +/************************************************************************ + * + * Writer2LaTeX.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-2014 by Henrik Just + * + * All Rights Reserved. + * + * Version 1.6 (2014-10-29) + * + */ + +package org.openoffice.da.comp.writer2latex; + +import java.io.File; +import java.io.IOException; +import java.net.URI; +import java.net.URISyntaxException; +import java.util.regex.Pattern; + +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.frame.XController; +import com.sun.star.frame.XFrame; +import com.sun.star.frame.XModel; +import com.sun.star.frame.XStorable; +import com.sun.star.lib.uno.helper.WeakBase; +import com.sun.star.task.XStatusIndicator; +import com.sun.star.task.XStatusIndicatorFactory; +import com.sun.star.ui.dialogs.ExecutableDialogResults; +import com.sun.star.ui.dialogs.XExecutableDialog; +import com.sun.star.uno.Exception; +import com.sun.star.uno.UnoRuntime; +import com.sun.star.uno.XComponentContext; + +import org.openoffice.da.comp.w2lcommon.helper.MacroExpander; +import org.openoffice.da.comp.w2lcommon.helper.MessageBox; +import org.openoffice.da.comp.w2lcommon.helper.PropertyHelper; +import org.openoffice.da.comp.w2lcommon.helper.RegistryHelper; +import org.openoffice.da.comp.w2lcommon.helper.XPropertySetHelper; + +import writer2latex.util.CSVList; +import writer2latex.util.Misc; + +/** This class implements the ui (dispatch) commands provided by the Writer2LaTeX toolbar. + * The actual processing is done by the three core classes TeXify, + * LaTeXImporter and BibTeXImporter + */ +public final class Writer2LaTeX extends WeakBase + implements com.sun.star.lang.XServiceInfo, + com.sun.star.frame.XDispatchProvider, + com.sun.star.lang.XInitialization, + com.sun.star.frame.XDispatch { + + private static final String PROTOCOL = "org.openoffice.da.writer2latex:"; + + // From constructor+initialization + private final XComponentContext m_xContext; + private XFrame m_xFrame; + private XModel xModel = null; + + // Global data + private TeXify texify = null; + private PropertyValue[] mediaProps = null; + private String sBasePath = null; + private String sBaseFileName = null; + + public static final String __implementationName = Writer2LaTeX.class.getName(); + public static final String __serviceName = "com.sun.star.frame.ProtocolHandler"; + private static final String[] m_serviceNames = { __serviceName }; + + public Writer2LaTeX( XComponentContext xContext ) { + m_xContext = xContext; + } + + // com.sun.star.lang.XInitialization: + public void initialize( Object[] object ) + throws com.sun.star.uno.Exception { + if ( object.length > 0 ) { + // The first item is the current frame + m_xFrame = (com.sun.star.frame.XFrame) UnoRuntime.queryInterface( + com.sun.star.frame.XFrame.class, object[0]); + // Get the model for the document from the frame + XController xController = m_xFrame.getController(); + if (xController!=null) { + xModel = xController.getModel(); + } + } + } + + // com.sun.star.lang.XServiceInfo: + public String getImplementationName() { + return __implementationName; + } + + public boolean supportsService( String sService ) { + int len = m_serviceNames.length; + + for( int i=0; i < len; i++) { + if (sService.equals(m_serviceNames[i])) + return true; + } + return false; + } + + public String[] getSupportedServiceNames() { + return m_serviceNames; + } + + + // com.sun.star.frame.XDispatchProvider: + public com.sun.star.frame.XDispatch queryDispatch( com.sun.star.util.URL aURL, + String sTargetFrameName, int iSearchFlags ) { + if ( aURL.Protocol.compareTo(PROTOCOL) == 0 ) { + if ( aURL.Path.compareTo("ProcessDocument") == 0 ) + return this; + else if ( aURL.Path.compareTo("ProcessDirectly") == 0 ) + return this; + else if ( aURL.Path.compareTo("ViewLog") == 0 ) + return this; + else if ( aURL.Path.compareTo("InsertBibTeX") == 0 ) + return this; + } + return null; + } + + public com.sun.star.frame.XDispatch[] queryDispatches( + com.sun.star.frame.DispatchDescriptor[] seqDescriptors ) { + int nCount = seqDescriptors.length; + com.sun.star.frame.XDispatch[] seqDispatcher = + new com.sun.star.frame.XDispatch[seqDescriptors.length]; + + for( int i=0; i < nCount; ++i ) { + seqDispatcher[i] = queryDispatch(seqDescriptors[i].FeatureURL, + seqDescriptors[i].FrameName, + seqDescriptors[i].SearchFlags ); + } + return seqDispatcher; + } + + + // com.sun.star.frame.XDispatch: + public void dispatch( com.sun.star.util.URL aURL, + com.sun.star.beans.PropertyValue[] aArguments ) { + if ( aURL.Protocol.compareTo(PROTOCOL) == 0 ) { + if ( aURL.Path.compareTo("ProcessDocument") == 0 ) { + if (updateLocation() && updateMediaProperties()) { + process(); + } + return; + } + else if ( aURL.Path.compareTo("ProcessDirectly") == 0 ) { + if (updateLocation()) { + updateMediaPropertiesSilent(); + process(); + } + return; + } + else if ( aURL.Path.compareTo("ViewLog") == 0 ) { + viewLog(); + return; + } + else if ( aURL.Path.compareTo("InsertBibTeX") == 0 ) { + insertBibTeX(); + return; + } + } + } + + public void addStatusListener( com.sun.star.frame.XStatusListener xControl, + com.sun.star.util.URL aURL ) { + } + + public void removeStatusListener( com.sun.star.frame.XStatusListener xControl, + com.sun.star.util.URL aURL ) { + } + + // The actual commands... + + private void process() { + // Create a (somewhat coarse grained) status indicator/progress bar + XStatusIndicatorFactory xFactory = (com.sun.star.task.XStatusIndicatorFactory) + UnoRuntime.queryInterface(com.sun.star.task.XStatusIndicatorFactory.class, m_xFrame); + XStatusIndicator xStatus = xFactory.createStatusIndicator(); + xStatus.start("Writer2LaTeX",10); + xStatus.setValue(1); // At least we have started, that's 10% :-) + + // First work a bit on the FilterData (get the backend and set bibliography options) + String sBackend = "generic"; + String sBibinputs = null; + + PropertyHelper mediaHelper = new PropertyHelper(mediaProps); + Object filterData = mediaHelper.get("FilterData"); + if (filterData instanceof PropertyValue[]) { + PropertyHelper filterHelper = new PropertyHelper((PropertyValue[])filterData); + // Get the backend + Object backend = filterHelper.get("backend"); + if (backend instanceof String) { + sBackend = (String) backend; + } + + // Set the bibliography options according to the settings + RegistryHelper registry = new RegistryHelper(m_xContext); + try { + Object view = registry.getRegistryView(BibliographyDialog.REGISTRY_PATH, false); + XPropertySet xProps = (XPropertySet) UnoRuntime.queryInterface(XPropertySet.class,view); + String sBibTeXFiles = getFileList(XPropertySetHelper.getPropertyValueAsShort(xProps, "BibTeXLocation"), + XPropertySetHelper.getPropertyValueAsString(xProps, "BibTeXDir")); + if (XPropertySetHelper.getPropertyValueAsBoolean(xProps, "ConvertZoteroCitations")) { + filterHelper.put("zotero_bibtex_files", sBibTeXFiles); + } + if (XPropertySetHelper.getPropertyValueAsBoolean(xProps, "ConvertJabRefCitations")) { + filterHelper.put("jabref_bibtex_files", sBibTeXFiles); + } + if (XPropertySetHelper.getPropertyValueAsBoolean(xProps, "UseExternalBibTeXFiles")) { + filterHelper.put("external_bibtex_files", sBibTeXFiles); + } + filterHelper.put("include_original_citations", + Boolean.toString(XPropertySetHelper.getPropertyValueAsBoolean(xProps, "IncludeOriginalCitations"))); + String sBibTeXDir = XPropertySetHelper.getPropertyValueAsString(xProps, "BibTeXDir"); + if (sBibTeXDir.length()>0) { + // The separator character in BIBINPUTS is OS specific + sBibinputs = sBibTeXDir+File.pathSeparatorChar; + } + filterHelper.put("use_natbib", Boolean.toString(XPropertySetHelper.getPropertyValueAsBoolean(xProps, "UseNatbib"))); + filterHelper.put("natbib_options", XPropertySetHelper.getPropertyValueAsString(xProps, "NatbibOptions")); + + mediaHelper.put("FilterData",filterHelper.toArray()); + mediaProps = mediaHelper.toArray(); + registry.disposeRegistryView(view); + } + catch (Exception e) { + // Failed to get registry view + } + } + + try { + // Convert to LaTeX + String sTargetUrl = sBasePath+sBaseFileName+".tex"; + XStorable xStorable = (XStorable) UnoRuntime.queryInterface(XStorable.class, xModel); + xStorable.storeToURL(sTargetUrl, mediaProps); + } + catch (com.sun.star.io.IOException e) { + xStatus.end(); + MessageBox msgBox = new MessageBox(m_xContext, m_xFrame); + msgBox.showMessage("Writer2LaTeX","Error: Failed to export document to LaTeX"); + return; + } + + xStatus.setValue(6); // Export is finished, that's more than half :-) + + if (texify==null) { texify = new TeXify(m_xContext); } + File file = new File(urlToFile(sBasePath),sBaseFileName); + + boolean bResult = true; + + try { + if (sBackend=="pdftex") { + bResult = texify.process(file, sBibinputs, TeXify.PDFTEX, true); + } + else if (sBackend=="dvips") { + bResult = texify.process(file, sBibinputs, TeXify.DVIPS, true); + } + else if (sBackend=="xetex") { + bResult = texify.process(file, sBibinputs, TeXify.XETEX, true); + } + else if (sBackend=="generic") { + bResult = texify.process(file, sBibinputs, TeXify.GENERIC, true); + } + } + catch (IOException e) { + MessageBox msgBox = new MessageBox(m_xContext, m_xFrame); + msgBox.showMessage("Writer2LaTeX","Error: "+e.getMessage()); + } + + xStatus.setValue(10); // The user will usually not see this... + + if (!bResult) { + MessageBox msgBox = new MessageBox(m_xContext, m_xFrame); + msgBox.showMessage("Writer2LaTeX","Error: Failed to execute LaTeX - see log for details"); + } + + xStatus.end(); + } + + private String getFileList(short nType, String sDirectory) { + File dir; + switch (nType) { + case 0: // absolute path + dir = new File(sDirectory); + break; + case 1: // relative path + dir = new File(urlToFile(sBasePath),sDirectory); + break; + default: // document directory + dir = urlToFile(sBasePath); + } + + CSVList filelist = new CSVList(","); + if (dir.isDirectory()) { + File[] files = dir.listFiles(); + for (File file : files) { + if (file.isFile() && file.getName().endsWith(".bib")) { + //filelist.addValue(file.getAbsolutePath()); + filelist.addValue(Misc.removeExtension(file.getName())); + } + } + } + String sFileList = filelist.toString(); + return sFileList.length()>0 ? sFileList : "dummy"; + } + + private void viewLog() { + if (updateLocation()) { + // Execute the log viewer dialog + try { + Object[] args = new Object[1]; + args[0] = sBasePath+sBaseFileName; + Object dialog = m_xContext.getServiceManager() + .createInstanceWithArgumentsAndContext( + "org.openoffice.da.writer2latex.LogViewerDialog", args, m_xContext); + XExecutableDialog xDialog = (XExecutableDialog) + UnoRuntime.queryInterface(XExecutableDialog.class, dialog); + if (xDialog.execute()==ExecutableDialogResults.OK) { + // Closed with the close button + } + } + catch (com.sun.star.uno.Exception e) { + } + } + } + + private void insertBibTeX() { + MessageBox msgBox = new MessageBox(m_xContext, m_xFrame); + msgBox.showMessage("Writer2LaTeX","This feature is not implemented yet"); + } + + // Some utility methods + private void prepareMediaProperties() { + // Create inital media properties + mediaProps = new PropertyValue[2]; + mediaProps[0] = new PropertyValue(); + mediaProps[0].Name = "FilterName"; + mediaProps[0].Value = "org.openoffice.da.writer2latex"; + mediaProps[1] = new PropertyValue(); + mediaProps[1].Name = "Overwrite"; + mediaProps[1].Value = "true"; + } + + private boolean updateMediaProperties() { + prepareMediaProperties(); + + try { + // Display options dialog + Object dialog = m_xContext.getServiceManager() + .createInstanceWithContext("org.openoffice.da.writer2latex.LaTeXOptionsDialog", m_xContext); + + XPropertyAccess xPropertyAccess = (XPropertyAccess) + UnoRuntime.queryInterface(XPropertyAccess.class, dialog); + xPropertyAccess.setPropertyValues(mediaProps); + + XExecutableDialog xDialog = (XExecutableDialog) + UnoRuntime.queryInterface(XExecutableDialog.class, dialog); + if (xDialog.execute()==ExecutableDialogResults.OK) { + mediaProps = xPropertyAccess.getPropertyValues(); + return true; + } + else { + mediaProps = null; + return false; + } + } + catch (com.sun.star.beans.UnknownPropertyException e) { + // setPropertyValues will not fail.. + mediaProps = null; + return false; + } + catch (com.sun.star.uno.Exception e) { + // getServiceManager will not fail.. + mediaProps = null; + return false; + } + } + + private String getOptionAsString(XPropertySet xProps, String sName) { + Object value = XPropertySetHelper.getPropertyValue(xProps, sName); + // Try to convert the value to a string + if (value instanceof String) return (String) value; + else if (value instanceof Boolean) return ((Boolean) value).toString(); + else if (value instanceof Integer) return ((Integer) value).toString(); + else if (value instanceof Short) return ((Short) value).toString(); + else return null; + } + + private void loadOption(XPropertySet xProps, PropertyHelper filterData, String sRegName, String sOptionName) { + String sValue = getOptionAsString(xProps,sRegName); + if (sValue!=null) { + // Set the filter data + filterData.put(sOptionName, sValue); + } + } + + // Read the configuration directly from the registry rather than using the dialog + // TODO: Should probably do some refactoring in the Options dialogs to avoid this solution + private void updateMediaPropertiesSilent() { + prepareMediaProperties(); + + RegistryHelper registry = new RegistryHelper(m_xContext); + + // Read the stored settings from the registry rather than displaying a dialog + try { + // Prepare registry view + Object view = registry.getRegistryView("/org.openoffice.da.Writer2LaTeX.Options/LaTeXOptions",true); + XPropertySet xProps = (XPropertySet) UnoRuntime.queryInterface(XPropertySet.class,view); + + PropertyHelper filterData = new PropertyHelper(); + + // Read the configuration file + short nConfig = XPropertySetHelper.getPropertyValueAsShort(xProps, "Config"); + 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"); break; + default: + // Get the actual URL from the registry + String sConfigName = XPropertySetHelper.getPropertyValueAsString(xProps, "ConfigName"); + + Object configurations = XPropertySetHelper.getPropertyValue(xProps,"Configurations"); + XNameAccess xNameAccess = (XNameAccess) UnoRuntime.queryInterface(XNameAccess.class,configurations); + Object config = xNameAccess.getByName(sConfigName); + XPropertySet xCfgProps = (XPropertySet) UnoRuntime.queryInterface(XPropertySet.class,config); + + MacroExpander expander = new MacroExpander(m_xContext); + filterData.put("ConfigURL",expander.expandMacros(XPropertySetHelper.getPropertyValueAsString(xCfgProps,"ConfigURL"))); + } + + // Read the options + // General + short nBackend = XPropertySetHelper.getPropertyValueAsShort(xProps,"Backend"); + switch (nBackend) { + case 0: filterData.put("backend","generic"); break; + case 1: filterData.put("backend","pdftex"); break; + case 2: filterData.put("backend","dvips"); break; + case 3: filterData.put("backend","xetex"); break; + case 4: filterData.put("backend","unspecified"); + } + short nInputencoding = XPropertySetHelper.getPropertyValueAsShort(xProps,"Inputencoding"); + switch (nInputencoding) { + case 0: filterData.put("inputencoding", "ascii"); break; + case 1: filterData.put("inputencoding", "latin1"); break; + case 2: filterData.put("inputencoding", "latin2"); break; + case 3: filterData.put("inputencoding", "iso-8859-7"); break; + case 4: filterData.put("inputencoding", "cp1250"); break; + case 5: filterData.put("inputencoding", "cp1251"); break; + case 6: filterData.put("inputencoding", "koi8-r"); break; + case 7: filterData.put("inputencoding", "utf8"); + } + loadOption(xProps,filterData,"Multilingual","multilingual"); + loadOption(xProps,filterData,"GreekMath","greek_math"); + loadOption(xProps,filterData,"AdditionalSymbols","use_pifont"); + loadOption(xProps,filterData,"AdditionalSymbols","use_ifsym"); + loadOption(xProps,filterData,"AdditionalSymbols","use_wasysym"); + loadOption(xProps,filterData,"AdditionalSymbols","use_eurosym"); + loadOption(xProps,filterData,"AdditionalSymbols","use_tipa"); + + // Bibliography + loadOption(xProps,filterData,"UseBibtex","use_bibtex"); + loadOption(xProps,filterData,"BibtexStyle","bibtex_style"); + + // Files + boolean bWrapLines = XPropertySetHelper.getPropertyValueAsBoolean(xProps,"WrapLines"); + if (bWrapLines) { + loadOption(xProps,filterData,"WrapLinesAfter","wrap_lines_after"); + } + else { + filterData.put("wrap_lines_after", "0"); + } + loadOption(xProps,filterData,"SplitLinkedSections","split_linked_sections"); + loadOption(xProps,filterData,"SplitToplevelSections","split_toplevel_sections"); + loadOption(xProps,filterData,"SaveImagesInSubdir","save_images_in_subdir"); + + // Special content + short nNotes = XPropertySetHelper.getPropertyValueAsShort(xProps, "Notes"); + switch (nNotes) { + case 0: filterData.put("notes","ignore"); break; + case 1: filterData.put("notes","comment"); break; + case 2: filterData.put("notes","pdfannotation"); break; + case 3: filterData.put("notes","marginpar"); + } + loadOption(xProps,filterData,"Metadata","metadata"); + + // Figures and tables + loadOption(xProps,filterData,"OriginalImageSize","original_image_size"); + boolean bOptimizeSimpleTables = XPropertySetHelper.getPropertyValueAsBoolean(xProps,"OptimizeSimpleTables"); + if (bOptimizeSimpleTables) { + loadOption(xProps,filterData,"SimpleTableLimit","simple_table_limit"); + } + else { + filterData.put("simple_table_limit", "0"); + } + loadOption(xProps,filterData,"FloatTables","float_tables"); + loadOption(xProps,filterData,"FloatFigures","float_figures"); + loadOption(xProps,filterData,"FloatOptions","float_options"); + short nFloatOptions = XPropertySetHelper.getPropertyValueAsShort(xProps, "FloatOptions"); + switch (nFloatOptions) { + case 0: filterData.put("float_options", ""); break; + case 1: filterData.put("float_options", "tp"); break; + case 2: filterData.put("float_options", "bp"); break; + case 3: filterData.put("float_options", "htp"); break; + case 4: filterData.put("float_options", "hbp"); + } + + // AutoCorrect + loadOption(xProps,filterData,"IgnoreHardPageBreaks","ignore_hard_page_breaks"); + loadOption(xProps,filterData,"IgnoreHardLineBreaks","ignore_hard_line_breaks"); + loadOption(xProps,filterData,"IgnoreEmptyParagraphs","ignore_empty_paragraphs"); + loadOption(xProps,filterData,"IgnoreDoubleSpaces","ignore_empty_spaces"); + + registry.disposeRegistryView(view); + + // 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, ignore + } + } + + private boolean updateLocation() { + String sDocumentUrl = xModel.getURL(); + if (sDocumentUrl.length()!=0) { + if (sDocumentUrl.startsWith("file:")) { + if (System.getProperty("os.name").startsWith("Windows")) { + Pattern windowsPattern = Pattern.compile("^file:///[A-Za-z][|:].*"); + if (!windowsPattern.matcher(sDocumentUrl).matches()) { + MessageBox msgBox = new MessageBox(m_xContext, m_xFrame); + msgBox.showMessage("Please save the document on a location with a drive name!", + "LaTeX does not support UNC paths"); + return false; + } + } + // Get the file name (without extension) + File f = urlToFile(sDocumentUrl); + sBaseFileName = f.getName(); + int iDot = sBaseFileName.lastIndexOf("."); + if (iDot>-1) { // remove extension + sBaseFileName = sBaseFileName.substring(0,iDot); + } + sBaseFileName=makeTeXSafe(sBaseFileName); + + // Get the path + int iSlash = sDocumentUrl.lastIndexOf("/"); + if (iSlash>-1) { + sBasePath = sDocumentUrl.substring(0,iSlash+1); + } + else { + sBasePath = ""; + } + + return true; + } + else { + MessageBox msgBox = new MessageBox(m_xContext, m_xFrame); + msgBox.showMessage("Please save the document locally!","LaTeX does not support documents in remote storages"); + return false; + } + } + else { + MessageBox msgBox = new MessageBox(m_xContext, m_xFrame); + msgBox.showMessage("Document not saved!","Please save the document before processing the file"); + return false; + } + } + + private String makeTeXSafe(String sArgument) { + String sResult = ""; + for (int i=0; i='a' && c<='z') || (c>='A' && c<='Z') || (c>='0' && c<='9')) { + sResult += Character.toString(c); + } + else { + switch (c) { + case '.': sResult += "."; break; + case '-': sResult += "-"; break; + case ' ' : sResult += "-"; break; + case '_' : sResult += "-"; break; + // Replace accented and national characters + case '\u00c0' : sResult += "A"; break; + case '\u00c1' : sResult += "A"; break; + case '\u00c2' : sResult += "A"; break; + case '\u00c3' : sResult += "A"; break; + case '\u00c4' : sResult += "AE"; break; + case '\u00c5' : sResult += "AA"; break; + case '\u00c6' : sResult += "AE"; break; + case '\u00c7' : sResult += "C"; break; + case '\u00c8' : sResult += "E"; break; + case '\u00c9' : sResult += "E"; break; + case '\u00ca' : sResult += "E"; break; + case '\u00cb' : sResult += "E"; break; + case '\u00cc' : sResult += "I"; break; + case '\u00cd' : sResult += "I"; break; + case '\u00ce' : sResult += "I"; break; + case '\u00cf' : sResult += "I"; break; + case '\u00d0' : sResult += "D"; break; + case '\u00d1' : sResult += "N"; break; + case '\u00d2' : sResult += "O"; break; + case '\u00d3' : sResult += "O"; break; + case '\u00d4' : sResult += "O"; break; + case '\u00d5' : sResult += "O"; break; + case '\u00d6' : sResult += "OE"; break; + case '\u00d8' : sResult += "OE"; break; + case '\u00d9' : sResult += "U"; break; + case '\u00da' : sResult += "U"; break; + case '\u00db' : sResult += "U"; break; + case '\u00dc' : sResult += "UE"; break; + case '\u00dd' : sResult += "Y"; break; + case '\u00df' : sResult += "sz"; break; + case '\u00e0' : sResult += "a"; break; + case '\u00e1' : sResult += "a"; break; + case '\u00e2' : sResult += "a"; break; + case '\u00e3' : sResult += "a"; break; + case '\u00e4' : sResult += "ae"; break; + case '\u00e5' : sResult += "aa"; break; + case '\u00e6' : sResult += "ae"; break; + case '\u00e7' : sResult += "c"; break; + case '\u00e8' : sResult += "e"; break; + case '\u00e9' : sResult += "e"; break; + case '\u00ea' : sResult += "e"; break; + case '\u00eb' : sResult += "e"; break; + case '\u00ec' : sResult += "i"; break; + case '\u00ed' : sResult += "i"; break; + case '\u00ee' : sResult += "i"; break; + case '\u00ef' : sResult += "i"; break; + case '\u00f0' : sResult += "d"; break; + case '\u00f1' : sResult += "n"; break; + case '\u00f2' : sResult += "o"; break; + case '\u00f3' : sResult += "o"; break; + case '\u00f4' : sResult += "o"; break; + case '\u00f5' : sResult += "o"; break; + case '\u00f6' : sResult += "oe"; break; + case '\u00f8' : sResult += "oe"; break; + case '\u00f9' : sResult += "u"; break; + case '\u00fa' : sResult += "u"; break; + case '\u00fb' : sResult += "u"; break; + case '\u00fc' : sResult += "ue"; break; + case '\u00fd' : sResult += "y"; break; + case '\u00ff' : sResult += "y"; break; + } + } + } + if (sResult.length()==0) { return "writer2latex"; } + else { return sResult; } + } + + private File urlToFile(String sUrl) { + try { + return new File(new URI(sUrl)); + } + catch (URISyntaxException e) { + return new File("."); + } + } + + /*private String urlToPath(String sUrl) { + try { + return (new File(new URI(sUrl))).getCanonicalPath(); + } + catch (URISyntaxException e) { + return "."; + } + catch (IOException e) { + return "."; + } + }*/ + +} \ No newline at end of file