/* Copyright (C) 2013-2020 Nicola L.C. Talbot www.dickimaw-books.com This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ package com.dickimawbooks.makeglossariesgui; import java.io.*; import java.nio.charset.*; import java.net.*; import java.util.*; import java.util.regex.Pattern; import java.util.regex.Matcher; public class MakeGlossariesInvoker { public MakeGlossariesInvoker() { setMessageSystem(new GlossaryBatchMessage(this)); try { loadDictionary(); } catch (IOException e) { getMessageSystem().error( String.format("Unable to load dictionary file:%n%s", e.getMessage())); } initLanguageMappings(); try { properties = MakeGlossariesProperties.fetchProperties(); } catch (IOException e) { getMessageSystem().error( getLabelWithValues("error.prop_io", e.getMessage())); properties = new MakeGlossariesProperties(); } } public void setFile(File file) { setFile(file.getAbsolutePath()); } public void setFile(String filename) { if (filename.toLowerCase().endsWith(".tex")) { int idx = filename.length()-4; filename = filename.substring(0, idx)+".aux"; } else if (!filename.endsWith(".aux")) { filename = filename+".aux"; } currentFileName = filename; } public void load(File file) { String lc = file.getName().toLowerCase(); if (lc.endsWith(".tex") || lc.endsWith(".log")) { int idx = file.getName().length()-4; file = new File(file.getParentFile(), file.getName().substring(0, idx)+".aux"); } setFile(file); reload(file); } public void reload() { reload(new File(currentFileName)); } public void reload(File file) { if (!file.exists()) { // Does the log file exists? File log = null; String name = file.getName(); if (!isBatchMode() && name.toLowerCase().endsWith(".aux")) { name = name.substring(0, name.length()-4); log = new File(file.getParentFile(), name+".log"); if (!log.exists()) { log = null; } else { glossaries = new Glossaries(this); glossaries.addDiagnosticMessage( getLabel("diagnostics.no_aux")); glossaries.addErrorMessage(getLabelWithValues( "error.io.file_doesnt_exist", file)); try { glossaries.parseLog(log.getParentFile(), name); } catch (Exception e) { getMessageSystem().error(e); } getMessageSystem().showMessages(); } } if (log == null) { getMessageSystem().error(getLabelWithValues( "error.io.file_doesnt_exist", file.getAbsolutePath())); } return; } try { glossaries = Glossaries.loadGlossaries(this, file); glossaries.process(); } catch (InterruptedException e) { getMessageSystem().error(e); } catch (GlossaryException e) { String mess = e.getDiagnosticMessage(); if (mess != null) { glossaries.addDiagnosticMessage(mess); } getMessageSystem().message(e); } catch (IOException e) { glossaries.addDiagnosticMessage(getLabel("diagnostics.io_error")); getMessageSystem().error(e); } String errMess = glossaries.getErrorMessages(); if (errMess != null) { getMessageSystem().error(errMess); } getMessageSystem().showMessages(); } public void setMessageSystem(GlossaryMessage msg) { messageSystem = msg; } public GlossaryMessage getMessageSystem() { return messageSystem; } public static String escapeHTML(String text) { if (text == null || text.isEmpty()) return ""; int n = text.length(); StringBuilder builder = new StringBuilder(n); for (int i = 0; i < n; i++) { char c = text.charAt(i); if (c == '&') { builder.append("&"); } else if (c == '<') { builder.append("<"); } else if (c == '>') { builder.append(">"); } else { builder.append(c); } } return builder.toString(); } public String getLabelOrDef(String label, String alt) { if (messages == null) { return alt; } String val = messages.getMessageIfExists(label); return val == null ? alt : val; } public String getLabel(String label) { return getLabel(null, label); } public String getLabel(String parent, String label) { if (messages == null) { messageSystem.debug("Dictionary not loaded."); return null; } String propLabel; if (parent == null) { propLabel = label; } else { propLabel = String.format("%s.%s", parent, label); } return messages.getMessage(propLabel); } public int getMnemonic(String label) { return getMnemonic(null, label); } public int getMnemonic(String parent, String label) { if (messages == null) { messageSystem.debug("Dictionary not loaded."); return -1; } String propLabel = label+".mnemonic"; if (parent != null) { propLabel = String.format("%s.%s", parent, propLabel); } String val = messages.getMessageIfExists(propLabel); if (val == null || val.isEmpty()) { return -1; } return val.codePointAt(0); } public String getLabelWithValues(String label, Object... values) { if (messages == null) { return null; } return messages.getMessage(label, values); } public MakeGlossariesProperties getProperties() { return properties; } public boolean isDocDefCheckOn() { return properties.isDocDefsCheckOn(); } public boolean isMissingLangCheckOn() { return properties.isMissingLangCheckOn(); } public String getDefaultLanguage() { return properties.getDefaultLanguage(); } public String getDefaultXindyVariant() { return properties.getDefaultXindyVariant(); } public String getDefaultCodePage() { return properties.getDefaultCodePage(); } // Convert xindy and inputenc encoding labels to Charset // Uses String.contains rather than String.equals as // the xindy codepage may contain additional information, // such as din5007- public static Charset getCharset(String encodingLabel) throws IllegalCharsetNameException, IllegalArgumentException, UnsupportedCharsetException { if (encodingLabel == null) { throw new IllegalArgumentException( "Illegal encoding label (null)"); } if (encodingLabel.contains("utf8")) { return StandardCharsets.UTF_8; } if (encodingLabel.contains("ascii")) { return Charset.forName("US-ASCII"); } if (encodingLabel.contains("latin10")) { return Charset.forName("ISO-8859-16"); } if (encodingLabel.contains("latin1")) { return StandardCharsets.ISO_8859_1; } if (encodingLabel.contains("latin2")) { return Charset.forName("ISO-8859-2"); } if (encodingLabel.contains("latin3")) { return Charset.forName("ISO-8859-3"); } if (encodingLabel.contains("latin4")) { return Charset.forName("ISO-8859-4"); } if (encodingLabel.contains("latin5")) { return Charset.forName("ISO-8859-9"); } if (encodingLabel.contains("latin6")) { return Charset.forName("ISO-8859-10"); } if (encodingLabel.contains("latin7")) { return Charset.forName("ISO-8859-13"); } if (encodingLabel.contains("latin8")) { return Charset.forName("ISO-8859-14"); } if (encodingLabel.contains("latin9")) { return Charset.forName("ISO-8859-15"); } if (encodingLabel.contains("cp1250")) { return Charset.forName("Cp1250"); } if (encodingLabel.contains("cp1252") || encodingLabel.contains("ansinew")) { return Charset.forName("Cp1252"); } if (encodingLabel.contains("cp1257")) { return Charset.forName("Cp1257"); } if (encodingLabel.contains("cp437")) { return Charset.forName("Cp437"); } if (encodingLabel.contains("cp850")) { return Charset.forName("Cp850"); } if (encodingLabel.contains("cp852")) { return Charset.forName("Cp852"); } if (encodingLabel.contains("cp858")) { return Charset.forName("Cp858"); } if (encodingLabel.contains("cp865")) { return Charset.forName("Cp865"); } if (encodingLabel.contains("decmulti")) { return Charset.forName("DEC-MCS"); } if (encodingLabel.contains("applemac")) { return Charset.forName("MacRoman"); } if (encodingLabel.contains("macce")) { return Charset.forName("MacCentralEurope"); } // don't know appropriate Java name for inputenc's 'next' return null; } // indexer character encoding public Charset getEncoding() { return defaultCharset; } public void setEncoding(Charset charset) { defaultCharset = charset; } private void loadDictionary() throws IOException { Locale locale = Locale.getDefault(); String lang = locale.getLanguage(); String resource = "/resources/dictionaries/makeglossariesgui-" +lang+".prop"; InputStream in = getClass().getResourceAsStream(resource); if (in == null && !lang.equals("en")) { resource = "/resources/dictionaries/makeglossariesgui-en.prop"; in = getClass().getResourceAsStream(resource); } BufferedReader reader = null; try { Charset defCharset = Charset.defaultCharset(); reader = new BufferedReader(new InputStreamReader(in, defCharset)); // First line should be # Encoding: Charset charset = null; String encoding=null; try { String line = reader.readLine(); Pattern p = Pattern.compile("# Encoding: (.+)"); Matcher m = p.matcher(line); if (!m.matches()) { throw new InvalidSyntaxException( "Missing encoding comment on line 1 of dictionary file: !" + resource); } encoding = m.group(1); charset = Charset.forName(encoding); } catch (UnsupportedCharsetException|IllegalCharsetNameException e) { throw new InvalidSyntaxException(String.format( "Invalid encoding '%s' on line 1 of dictionary file: !%s", encoding, resource), e); } if (!charset.equals(defCharset)) { reader.close(); reader = new BufferedReader(new InputStreamReader(in, charset)); } Properties dictionary = new Properties(); dictionary.load(reader); messages = new MakeGlossariesDictionary(dictionary); } finally { if (reader != null) { reader.close(); } in.close(); } } public Glossaries getGlossaries() { return glossaries; } public String getFileName() { return currentFileName; } public File getFile() { return currentFileName == null ? null : new File(currentFileName); } public File getCurrentDirectory() { if (currentFileName == null) { return new File(properties.getDefaultDirectory()); } File file = getFile().getParentFile(); if (file == null) { file = new File(properties.getDefaultDirectory()); } return file; } public String getCurrentDirectoryName() { return getCurrentDirectory().getAbsolutePath(); } public String getXindyApp() { return properties.getXindyApp(); } public String getMakeIndexApp() { return properties.getMakeIndexApp(); } private void initLanguageMappings() { languageMap = new Hashtable(); languageMap.put("american", "english"); languageMap.put("british", "english"); languageMap.put("francais", "french"); languageMap.put("frenchb", "french"); languageMap.put("germanb", "german"); languageMap.put("magyar", "hungarian"); languageMap.put("ngermanb", "german"); languageMap.put("ngerman", "german"); languageMap.put("norsk", "norwegian"); languageMap.put("portuges", "portuguese"); languageMap.put("russianb", "russian"); languageMap.put("UKenglish", "english"); languageMap.put("ukraineb", "ukrainian"); languageMap.put("USenglish", "english"); languageMap.put("usorbian", "upper-sorbian"); } public String getLanguage(String language) { String map = languageMap.get(language); return map == null ? language : map; } public File findApp(String name) { return findApp(name, name+".exe", null); } public File findApp(String name, String altName, String altName2) { String filename = name; String filename2 = (altName == null ? null : altName); String filename3 = (altName2 == null ? null : altName2); String path = System.getenv("PATH"); String[] split = path.split(File.pathSeparator); for (int i = 0; i < split.length; i++) { File file = new File(split[i], filename); if (file.exists()) { return file; } if (filename2 != null) { file = new File(split[i], filename2); if (file.exists()) { return file; } } if (filename3 != null) { file = new File(split[i], filename3); if (file.exists()) { return file; } } } return null; } public void help() { System.out.println(getLabel("syntax.cmdline")); System.out.println(); System.out.println(getLabelWithValues("syntax.filename", "--batch")); System.out.println(); System.out.println(getLabel("syntax.options")); System.out.println(); System.out.println(getLabelWithValues("syntax.help", "--help", "-h")); System.out.println(getLabelWithValues("syntax.version", "--version", "-v")); System.out.println(getLabelWithValues("syntax.debug", "--debug")); System.out.println(getLabelWithValues("syntax.dryrun", "--dry-run", "-n")); System.out.println(getLabelWithValues("syntax.nodryrun", "--nodry-run")); System.out.println(getLabelWithValues("syntax.batch", "--batch", "-b")); System.out.println(getLabelWithValues("syntax.gui", "--gui")); System.out.println(getLabelWithValues("syntax.quiet", "--quiet")); } public void version() { String translator = getLabelOrDef("about.translator_info", null); System.out.println(APP_NAME); System.out.println(getLabelWithValues("about.version", APP_VERSION, APP_DATE)); System.out.println(getLabelWithValues("about.copyright", "Nicola L. C. Talbot", String.format("2011-%s", APP_DATE.substring(0, 4)))); System.out.println("https://www.dickimaw-books.com/"); if (translator != null && !translator.isEmpty()) { System.out.println(translator); } } public boolean isQuiet() { return quiet; } public void setQuietMode(boolean isSet) { quiet = isSet; } public boolean isDebugMode() { return debug; } public void setDebugMode(boolean isSet) { debug = isSet; } public boolean isBatchMode() { return batchMode; } public void setDryRunMode(boolean isDryRun) { dryRun = isDryRun; } public boolean isDryRunMode() { return dryRun; } public static void main(String[] args) { MakeGlossariesInvoker invoker = new MakeGlossariesInvoker(); for (int i = 0; i < args.length; i++) { if (args[i].equals("--help") || args[i].equals("-h")) { invoker.batchMode = true; invoker.help(); System.exit(0); } else if (args[i].equals("--version") || args[i].equals("-v")) { invoker.batchMode = true; invoker.version(); System.exit(0); } else if (args[i].equals("--batch") || args[i].equals("-b")) { invoker.batchMode = true; } else if (args[i].equals("--gui")) { invoker.batchMode = false; } else if (args[i].equals("--quiet")) { invoker.setQuietMode(true); } else if (args[i].equals("--debug")) { invoker.setDebugMode(true); } else if (args[i].equals("--dry-run") || args[i].equals("-n")) { invoker.setDryRunMode(true); } else if (args[i].equals("--nodry-run")) { invoker.setDryRunMode(false); } else if (args[i].startsWith("-")) { System.err.println(invoker.getLabelWithValues("error.unknown_opt", args[i])); System.exit(1); } else if (invoker.getFileName() == null) { invoker.setFile(args[i]); } else { System.err.println(invoker.getLabel("error.one_input")); System.exit(1); } } if (invoker.batchMode) { if (invoker.getFileName() == null) { System.err.println(invoker.getLabel("error.input_required")); System.exit(1); } invoker.reload(); } else { MakeGlossariesGUI.createAndShowGUI(invoker); } } private String currentFileName = null; private MakeGlossariesProperties properties; private MakeGlossariesDictionary messages; public static final String APP_NAME = "MakeGlossariesGUI"; public static final String APP_VERSION = "2.2"; public static final String APP_DATE = "2020-03-09"; private boolean quiet=false, debug=false, batchMode=false, dryRun=false; protected Glossaries glossaries; private Charset defaultCharset=Charset.defaultCharset(); private Hashtable languageMap; private GlossaryMessage messageSystem; }