/*
* Zettelkasten - nach Luhmann
* Copyright (C) 2001-2015 by Daniel Lüdecke (http://www.danielluedecke.de)
*
* Homepage: http://zettelkasten.danielluedecke.de
*
*
* 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, see <http://www.gnu.org/licenses/>.
*
*
* Dieses Programm ist freie Software. Sie können es unter den Bedingungen der GNU
* General Public License, wie von der Free Software Foundation veröffentlicht, weitergeben
* und/oder modifizieren, entweder gemäß Version 3 der Lizenz oder (wenn Sie möchten)
* jeder späteren Version.
*
* Die Veröffentlichung dieses Programms erfolgt in der Hoffnung, daß es Ihnen von Nutzen sein
* wird, aber OHNE IRGENDEINE GARANTIE, sogar ohne die implizite Garantie der MARKTREIFE oder
* der VERWENDBARKEIT FÜR EINEN BESTIMMTEN ZWECK. Details finden Sie in der
* GNU General Public License.
*
* Sie sollten ein Exemplar der GNU General Public License zusammen mit diesem Programm
* erhalten haben. Falls nicht, siehe <http://www.gnu.org/licenses/>.
*/
package de.danielluedecke.zettelkasten.tasks.export;
import de.danielluedecke.zettelkasten.database.BibTex;
import de.danielluedecke.zettelkasten.database.Daten;
import de.danielluedecke.zettelkasten.database.DesktopData;
import de.danielluedecke.zettelkasten.database.Settings;
import de.danielluedecke.zettelkasten.database.TasksData;
import de.danielluedecke.zettelkasten.util.Constants;
import de.danielluedecke.zettelkasten.util.HtmlUbbUtil;
import de.danielluedecke.zettelkasten.util.Tools;
import de.danielluedecke.zettelkasten.util.FileOperationsUtil;
import de.danielluedecke.zettelkasten.util.TreeUtil;
import java.io.File;
import java.util.ArrayList;
import java.util.Enumeration;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import javax.swing.JOptionPane;
import javax.swing.tree.DefaultMutableTreeNode;
/**
*
* @author danielludecke
*/
public class ExportToTexTask extends org.jdesktop.application.Task<Object, Void> {
/**
* Reference to the CDaten object, which contains the XML data of the Zettelkasten will be
* passed as parameter in the constructor, see below
*/
private final Daten dataObj;
/**
*
*/
private final DesktopData desktopObj;
/**
*
*/
private final BibTex bibtexObj;
/**
*
*/
private final TasksData taskinfo;
/**
*
*/
private final Settings settingsObj;
/**
* Indicates whether or not a bibtex-file from the exported entries should be created or not
*/
private final boolean exportbibtex;
/**
*
*/
private final boolean createTOC;
/**
*
*/
private boolean zettelHasForms = false;
/**
* Defines whether each headline of any entry has its entry-number as prefix. If set to
* {@code true}, each entry's title will appear as <i>Entry XY: entry title</i>, if set to
* {@code false}, a title will just appear as <i>entry title</i>, or left out if title is empty.
*/
private final boolean zettelNumberAsPrefix;
/**
*
*/
private final boolean isHeadingVisible;
/**
* This variable stores the parts which should be exported. It's a mix of ORed constants, see
* below
*/
private final int exportparts;
/**
* indicates which type of data format should be exported to. refer to the Zettelkasten.view
* properties file (resources) to see which number is which file type.
*/
private final int exporttype;
/**
* file path to export file
*/
private final File filepath;
/**
*
*/
private StringBuilder exportPage = new StringBuilder("");
/**
*
*/
private StringBuilder exportPageHeader = new StringBuilder("");
/**
*
*/
private DefaultMutableTreeNode treenode = null;
/**
*
*/
private ArrayList<Object> exportentries;
/**
*
*/
private boolean exportOk;
/**
*
*/
private boolean showOkMessage = true;
private final boolean separateFiles;
/**
*
*/
private final javax.swing.JDialog parentDialog;
private final javax.swing.JLabel msgLabel;
/**
* get the strings for file descriptions from the resource map
*/
private final org.jdesktop.application.ResourceMap resourceMap
= org.jdesktop.application.Application.getInstance(de.danielluedecke.zettelkasten.ZettelkastenApp.class).
getContext().getResourceMap(ExportTask.class);
/**
*
* @param app
* @param parent
* @param label
* @param td
* @param d
* @param dt
* @param s
* @param bto
* @param fp
* @param ee
* @param type
* @param part
* @param n
* @param bibtex
* @param ihv
* @param numberprefix
* @param contenttable
* @param sf whether each note should be saved as separate file
*/
public ExportToTexTask(org.jdesktop.application.Application app, javax.swing.JDialog parent, javax.swing.JLabel label,
TasksData td, Daten d, DesktopData dt, Settings s, BibTex bto, File fp, ArrayList<Object> ee, int type, int part,
DefaultMutableTreeNode n, boolean bibtex, boolean ihv, boolean numberprefix, boolean contenttable, boolean sf) {
super(app);
dataObj = d;
settingsObj = s;
desktopObj = dt;
bibtexObj = bto;
filepath = fp;
exporttype = type;
exportparts = part;
exportbibtex = bibtex;
exportentries = ee;
zettelNumberAsPrefix = numberprefix;
isHeadingVisible = ihv;
exportOk = true;
createTOC = contenttable;
taskinfo = td;
treenode = n;
separateFiles = sf;
parentDialog = parent;
msgLabel = label;
// the variable "exportentries" stores all entry-numbers of those entries that should be exported.
// if this array is null, we assume that *all* entries have to be exported. thus, insert
// all entry-numbers here
if (null == exportentries) {
exportentries = new ArrayList<>();
// copy all entry-numbers to array. remember that the entrynumbers range from 1 to site of file.
for (int cnt = 0; cnt < dataObj.getCount(Daten.ZKNCOUNT); cnt++) {
// only add entries that are not empty
if (!dataObj.isEmpty(cnt + 1)) {
exportentries.add(cnt + 1);
}
}
}
// show status text
msgLabel.setText(resourceMap.getString("msg1"));
}
@Override
protected Object doInBackground() {
// Your Task's code here. This method runs
// on a background thread, so don't reference
// the Swing GUI from here.
// prevent task from processing when the file path is incorrect
// if no file exists, exit task
if (null == filepath) {
showOkMessage = false;
return null;
}
// get destination directory for separate files
String separateFileDir = "";
// if separate file for each note, check whether we have a slash at the end
if (separateFiles) {
if (filepath.isDirectory() && !filepath.toString().endsWith(String.valueOf(java.io.File.separatorChar))) {
// if not, add slash
separateFileDir = filepath.toString() + String.valueOf(java.io.File.separatorChar);
} else {
// else get file path
separateFileDir = FileOperationsUtil.getFilePath(filepath);
}
}
// check whether file already exists
if (!filepath.isDirectory() && filepath.exists()) {
// file exists, ask user to overwrite it...
int optionDocExists = JOptionPane.showConfirmDialog(null, resourceMap.getString("askForOverwriteFileMsg", "", filepath.getName()), resourceMap.getString("askForOverwriteFileTitle"), JOptionPane.YES_NO_OPTION, JOptionPane.PLAIN_MESSAGE);
// if the user does *not* choose to overwrite, quit...
if (optionDocExists != JOptionPane.YES_OPTION) {
// don't show "export was OK" message in main frame
showOkMessage = false;
return null;
}
}
// create a new stringbuilder that will contain the final string, i.e.
// the html-page which we set to the jeditorpane
exportPage = new StringBuilder("");
exportPageHeader = new StringBuilder("");
// and create a counter for the progressbar's position
int counter;
switch (exporttype) {
case Constants.EXP_TYPE_TEX:
// get the size of the export data, used for progressbar
int contentsize = exportentries.size();
// go through all elements of the data file
for (counter = 0; counter < exportentries.size(); counter++) {
try {
// retrieve zettelnumber
int zettelnummer = Integer.parseInt(exportentries.get(counter).toString());
String zetteltitle = "";
// check whether the user wants to export titles.
if ((exportparts & Constants.EXPORT_TITLE) != 0) {
// first check whether we have a title or not
zetteltitle = dataObj.getZettelTitle(zettelnummer);
// only prepare a title when we want to have the entry's number as title-prefix,
// or if we have a title.
if (!zetteltitle.isEmpty() || zettelNumberAsPrefix) {
// start section, i.e. LaTex heading 1. level
exportPage.append("\\section{");
// each entry has at least the title "entry" plus its number.
// we need this to search through the entries when the user clicks an entry on the
// jTreeDesktop in the desktop-window
if (zettelNumberAsPrefix) {
exportPage.append(resourceMap.getString("entryText")).append(" ").append(String.valueOf(zettelnummer));
}
// if we have a "real" title, append it...
if (!zetteltitle.isEmpty()) {
if (zettelNumberAsPrefix) {
exportPage.append(": ");
}
exportPage.append(zetteltitle);
}
exportPage.append("}");
exportPage.append(System.lineSeparator()).append(System.lineSeparator());
}
}
// check whether the user wants to export content
if ((exportparts & Constants.EXPORT_CONTENT) != 0) {
// get the zettelcontent
String zettelcontent = getConvertedTex(dataObj.getZettelContent(zettelnummer));
// if we have content, add it.
if (!zettelcontent.isEmpty()) {
// check whether we have form-tags
if (zettelcontent.contains(Constants.FORMAT_FORM_TAG)) {
zettelHasForms = true;
}
// first, replace all footnotes with bibkeys
// to appropriate cite-tag in latex
zettelcontent = ExportTools.createLatexFootnotes(dataObj, zettelcontent, settingsObj.getLatexExportFootnoteRef());
// then add content
exportPage.append(zettelcontent);
} else {
// else add remark that entry is deleted
exportPage.append(resourceMap.getString("deletedEntry"));
}
exportPage.append(System.lineSeparator()).append(System.lineSeparator());
}
// if the user wants to export remarks, do this here.
if ((exportparts & Constants.EXPORT_REMARKS) != 0) {
// get entry's remarks
String remarks = dataObj.getCleanRemarks(zettelnummer);
// check whether we have any
if (!remarks.isEmpty()) {
// set headline indicating that we have remarks here
exportPage.append("\\subsection{").append(resourceMap.getString("remarksHeader")).append("}").append(System.lineSeparator()).append(System.lineSeparator());
// init paragraph with class-attribute, so the user may change style aftwerwards
exportPage.append(remarks).append(System.lineSeparator()).append(System.lineSeparator());
}
}
// check whether the user wants to export authors
if ((exportparts & Constants.EXPORT_AUTHOR) != 0 && dataObj.hasAuthors(zettelnummer)) {
exportPage.append(ExportTools.createPlainList(dataObj.getAuthors(zettelnummer), resourceMap.getString("NoAuthor"), resourceMap.getString("authorHeader"), "\\subsection{", "}"));
}
// check whether user wants to export keywords.
if ((exportparts & Constants.EXPORT_KEYWORDS) != 0 && dataObj.hasKeywords(zettelnummer)) {
exportPage.append(ExportTools.createPlainList(dataObj.getKeywords(zettelnummer, true), resourceMap.getString("NoKeyword"), resourceMap.getString("keywordHeader"), "\\subsection{", "}"));
}
if ((exportparts & Constants.EXPORT_LINKS) != 0 && dataObj.hasAttachments(zettelnummer)) {
exportPage.append(ExportTools.createPlainList(dataObj.getAttachmentsAsString(zettelnummer, false), resourceMap.getString("NoAttachment"), resourceMap.getString("attachmentHeader"), "\\subsection{", "}"));
}
if ((exportparts & Constants.EXPORT_MANLINKS) != 0 && dataObj.hasManLinks(zettelnummer)) {
exportPage.append(ExportTools.createPlainCommaList(dataObj.getManualLinksAsString(zettelnummer), resourceMap.getString("NoManLinks"), resourceMap.getString("manlinksHeader"), "\\subsection{", "}"));
}
if ((exportparts & Constants.EXPORT_LUHMANN) != 0 && dataObj.hasLuhmannNumbers(zettelnummer)) {
exportPage.append(ExportTools.createPlainCommaList(dataObj.getLuhmannNumbersAsString(zettelnummer), resourceMap.getString("NoLuhmann"), resourceMap.getString("luhmannHeader"), "\\subsection{", "}"));
}
if ((exportparts & Constants.EXPORT_TIMESTAMP) != 0) {
String timestamp = dataObj.getTimestampCreated(zettelnummer);
// check whether we have a timestamp at all
if (timestamp != null && !timestamp.isEmpty()) {
// and add the created-timestamp
exportPage.append(resourceMap.getString("timestampCreated")).append(" ").append(Tools.getProperDate(timestamp, false));
}
// check whether we have a modified-timestamp
timestamp = dataObj.getTimestampEdited(zettelnummer);
// check whether we have a timestamp at all
if (timestamp != null && !timestamp.isEmpty()) {
exportPage.append(System.lineSeparator()).append(resourceMap.getString("timestampEdited")).append(" ").append(Tools.getProperDate(timestamp, false));
}
// and close the tags of the html-part
exportPage.append(System.lineSeparator()).append(System.lineSeparator());
}
// separate files for each note?
if (separateFiles) {
// conver tags to tex
exportPage = new StringBuilder(HtmlUbbUtil.convertUbbToTex(settingsObj, dataObj, bibtexObj, exportPage.toString(), settingsObj.getLatexExportFootnoteRef(), settingsObj.getLatexExportCreateFormTags(), Constants.EXP_TYPE_DESKTOP_TEX == exporttype, settingsObj.getLatexExportRemoveNonStandardTags()));
// get note number and title for filepath
String fname = String.valueOf(zettelnummer) + " " + FileOperationsUtil.getCleanFilePath(zetteltitle);
// create file path
File fp = new File(separateFileDir + fname.trim() + ".tex");
// write export file
ExportTools.writeExportData(exportPage.toString(), fp);
// reset string builder
exportPage = new StringBuilder("");
} else {
// uncomment this, if the "end{zettel}" command should be enabled. As this leads to errors when comiling the latex file,
// the begin{zettel} and end{zettel} tags are not used.
// exportPage.append(System.lineSeparator()).append("\\end{zettel}").append(System.lineSeparator()).append(System.lineSeparator());
// close zettel-tags
exportPage.append(System.lineSeparator()).append(System.lineSeparator());
}
} catch (NumberFormatException e) {
// leave out first char, which is always a "H", set by the method
// "createExportEntries()".
exportPage.append(System.lineSeparator()).append(exportentries.get(counter).toString().substring(2)).append(System.lineSeparator()).append(System.lineSeparator());
}
// update progress bar
setProgress(counter, 0, contentsize);
}
break;
case Constants.EXP_TYPE_DESKTOP_TEX:
// get comment-export-options
int commentExport = settingsObj.getDesktopCommentExport();
switch (commentExport) {
case Constants.EXP_COMMENTS_NO:
exportEntriesWithComments(treenode, false);
break;
case Constants.EXP_COMMENTS_YES:
exportEntriesWithComments(treenode, true);
break;
case Constants.EXP_COMMENTS_ONLY:
exportEntriesWithCommentsOnly(treenode);
break;
}
break;
}
if (!separateFiles) {
// create document-header
createLatexHeader();
// create footer with final information, including enddocument tag
createLatexFooter();
// show status text that string will be converted from UBB to LaTex
msgLabel.setText(resourceMap.getString("msg4"));
// convert all ubb into html...
// save content that should be exported and written to a file
// into a string. the write-procedure is done later, see below
exportPage = new StringBuilder(HtmlUbbUtil.convertUbbToTex(settingsObj, dataObj, bibtexObj, exportPage.toString(), settingsObj.getLatexExportFootnoteRef(), settingsObj.getLatexExportCreateFormTags(), Constants.EXP_TYPE_DESKTOP_TEX == exporttype, settingsObj.getLatexExportRemoveNonStandardTags()));
// insert document-header
exportPage.insert(0, exportPageHeader.toString());
// show status text that file will be written
msgLabel.setText(resourceMap.getString("msg2"));
// write export file
exportOk = ExportTools.writeExportData(exportPage.toString(), filepath);
// if the user requested a bibtex-export, do this now
if (exportbibtex) {
// show status text
msgLabel.setText(resourceMap.getString("msgBibtextExport"));
// write bibtex file
ExportTools.writeBibTexFile(dataObj, bibtexObj, exportentries, filepath, resourceMap);
}
}
return null; // return your result
}
@Override
protected void succeeded(Object result) {
// Runs on the EDT. Update the GUI based on
// the result computed by doInBackground().
}
@Override
protected void finished() {
super.finished();
taskinfo.setExportOk(exportOk);
taskinfo.setShowExportOkMessage(showOkMessage);
// Close Window
parentDialog.setVisible(false);
parentDialog.dispose();
}
/**
*
*/
private void createLatexHeader() {
// check if preamble is requested
if (settingsObj.getLatexExportNoPreamble()) {
return;
}
// init default document class
String defaultdocclass = "[12pt,oneside,a4paper]{scrartcl}";
// check for user defined document class
int docclass = settingsObj.getLastUsedLatexDocClass();
// check if it differs from default value
if (docclass != 0 && docclass < Constants.LATEX_DOCUMENT_CLASS.length) {
// set user defined document class
defaultdocclass = "{" + Constants.LATEX_DOCUMENT_CLASS[docclass] + "}";
}
// first, we need the document class
exportPageHeader.append("% Dokumentenklasse: 1-seitiger DIN-A4-Artikel (wissenschaftlich)").append(System.lineSeparator());
exportPageHeader.append("\\documentclass").append(defaultdocclass).append(System.lineSeparator()).append(System.lineSeparator());
// include package for new German orthography
// exportPageHeader.append("% Neue deutsche Rechtschreibung").append(System.lineSeparator());
// exportPageHeader.append("\\usepackage{ngerman}").append(System.lineSeparator()).append(System.lineSeparator());
// include math package for spencer brown forms
// exportPageHeader.append("% Neue deutsche Rechtschreibung").append(System.lineSeparator());
exportPageHeader.append("\\usepackage{amsmath,xcolor}").append(System.lineSeparator()).append(System.lineSeparator());
// include package for UTF8-umlaut-endocing
exportPageHeader.append("% Eingabe von Umlauten").append(System.lineSeparator());
exportPageHeader.append("% Siehe http://www.tug.org/texlive/devsrc/Master/texmf-dist/doc/latex/base/inputenc.pdf").append(System.lineSeparator());
exportPageHeader.append("\\usepackage[utf8]{inputenc}").append(System.lineSeparator()).append(System.lineSeparator());
// include package for quotes;
exportPageHeader.append("% Anführungszeichen einfach setzen").append(System.lineSeparator());
exportPageHeader.append("% Siehe http://mirrors.ctan.org/macros/latex/contrib/csquotes/csquotes.pdf").append(System.lineSeparator());
exportPageHeader.append("\\usepackage[german=quotes]{csquotes}").append(System.lineSeparator()).append(System.lineSeparator());
// include package for footer / page count
// but only, when non-standard is chosen
if (docclass != 0) {
exportPageHeader.append("% Seitenzahlen in Fußzeile rechts").append(System.lineSeparator());
exportPageHeader.append("\\usepackage{scrpage2}").append(System.lineSeparator());
exportPageHeader.append("\\pagestyle{scrheadings}").append(System.lineSeparator());
exportPageHeader.append("\\rofoot{\\pagemark}").append(System.lineSeparator()).append(System.lineSeparator());
}
// include package for graphics
exportPageHeader.append("% Paket für Grafiken einbinden").append(System.lineSeparator());
exportPageHeader.append("\\usepackage{graphicx}").append(System.lineSeparator()).append(System.lineSeparator());
// include package for colors
exportPageHeader.append("% Paket für farbige und flexible Tabellenzellen").append(System.lineSeparator());
exportPageHeader.append("\\usepackage{colortbl}").append(System.lineSeparator());
exportPageHeader.append("\\usepackage{tabularx}").append(System.lineSeparator());
exportPageHeader.append("\\definecolor{DarkGray}{gray}{0.7}").append(System.lineSeparator());
exportPageHeader.append("\\definecolor{LightGray}{gray}{0.9}").append(System.lineSeparator());
exportPageHeader.append("\\renewcommand{\\arraystretch}{1.2}").append(System.lineSeparator()).append(System.lineSeparator());
// include package for references
exportPageHeader.append("% Paket für Literaturverweise einbinden").append(System.lineSeparator());
exportPageHeader.append("\\usepackage{multibib} % Hier ändern für eigene Literatur-Stil-Pakete").append(System.lineSeparator());
// no paragraph indent
exportPageHeader.append("% Standardmäßig kein Einrücken von Absätzen").append(System.lineSeparator());
exportPageHeader.append("\\parindent 0pt").append(System.lineSeparator()).append(System.lineSeparator());
// check whether document contains form-tags
if (zettelHasForms && settingsObj.getLatexExportCreateFormTags()) {
// if so, append makro to document-header
doTheSpencerBrown();
}
// begin document
exportPageHeader.append("\\begin{document}").append(System.lineSeparator());
// create title
exportPageHeader.append("\\title{");
// in case we export a desktop, use that name as title
if (Constants.EXP_TYPE_DESKTOP_TEX == exporttype) {
exportPageHeader.append(desktopObj.getCurrentDesktopName());
} // else, use data file's name as title
else {
settingsObj.getFileName();
}
exportPageHeader.append("}").append(System.lineSeparator());
// check whether author-name or email should be set
if (settingsObj.getLatexExportShowMail() || settingsObj.getLatexExportShowAuthor()) {
// retrieve author and mail values
String doc_author = settingsObj.getLatexExportAuthorValue();
String doc_mail = settingsObj.getLatexExportMailValue();
// check whether we have values here
exportPageHeader.append("\\author{");
if (doc_author != null && !doc_author.isEmpty()) {
exportPageHeader.append(doc_author).append("\\\\").append(System.lineSeparator());
}
if (doc_mail != null && !doc_mail.isEmpty()) {
exportPageHeader.append("\\texttt{").append(doc_mail).append("}");
}
exportPageHeader.append("}").append(System.lineSeparator());
}
exportPageHeader.append("\\maketitle").append(System.lineSeparator());
// create table of contents, if requestet
if (createTOC) {
exportPageHeader.append("\\tableofcontents").append(System.lineSeparator());
}
exportPageHeader.append(System.lineSeparator());
}
/**
*
*/
private void createLatexFooter() {
// check if preamble is requested
if (settingsObj.getLatexExportNoPreamble()) {
return;
}
// retrieve filename of data file and bibtex file
String filename = FileOperationsUtil.getFileName(filepath);
String bibname = bibtexObj.getFileName();
// check whether one is empty or null
if (null == filename) {
filename = "";
}
if (null == bibname) {
bibname = "";
}
// new line
exportPage.append(System.lineSeparator());
// include bibtex-file. in case the user created a separate bibtex-file, this filename is used. else,
// the filename of the default-attached bibtex-file is used.
exportPage.append("\\bibliography{").append((exportbibtex) ? filename : bibname).append("}").append(System.lineSeparator());
// create default bibliography style
exportPage.append("\\bibliographystyle{").append(Constants.LATEX_BIB_STYLECODE[settingsObj.getLastUsedLatexBibStyle()]).append("} % Auskommentieren, wenn eigener Literatur-Stil eingebunden wird.").append(System.lineSeparator()).append(System.lineSeparator());
// print references
exportPage.append("% kann anstelle der beiden vorigen Zeilen verwendet werden,").append(System.lineSeparator());
exportPage.append("% um eigene Literatur-Stile zu nutzen.").append(System.lineSeparator());
exportPage.append("% \\printbibliography").append(System.lineSeparator());
// close document-tag
exportPage.append(System.lineSeparator()).append("\\end{document}");
}
/**
*
*/
private void doTheSpencerBrown() {
exportPageHeader.append("% Dieses Makro erstellt Befehle, um die Form-Notation von George Spencer Brown").append(System.lineSeparator());
exportPageHeader.append("% zu imitieren, die oft von Autoren im Bereich Systemtheorie verwendet wird.").append(System.lineSeparator());
exportPageHeader.append("% Vielen Dank an die Benutzer des Mr. Unix Forums für die hilfreichen Tipps zur Umsetzung!").append(System.lineSeparator());
exportPageHeader.append("% http://www.mrunix.de/forums/showthread.php?t=66803&page=2").append(System.lineSeparator());
exportPageHeader.append("%").append(System.lineSeparator());
exportPageHeader.append("% Beispiele: Form =\\cross{Innenseite}%").append(System.lineSeparator());
exportPageHeader.append("% Beispiele: Form =\\cross{Innenseite}Außenseite%").append(System.lineSeparator());
exportPageHeader.append("% Beispiele: Form =\\ReEntry{\\cross{\\cross{\\cross{Innenseite}Kontext 1}Kontext 2}Kontex 3}Außenseite").append(System.lineSeparator());
exportPageHeader.append("%").append(System.lineSeparator());
exportPageHeader.append("\\newlength\\crossleftdist %Abstand links vom\\cross").append(System.lineSeparator());
exportPageHeader.append("\\newlength\\crossrightdist %Abstand rechts vom\\cross").append(System.lineSeparator());
exportPageHeader.append("\\newlength\\crosscontleftdist %Abstand Inhalt links zum \\cross").append(System.lineSeparator());
exportPageHeader.append("\\newlength\\crosscontrightdist %Abstand Inhalt rechts zum \\cross").append(System.lineSeparator());
exportPageHeader.append("\\newlength\\crosscontabovedist %Freiraum Inhalt oben zum \\cross").append(System.lineSeparator());
exportPageHeader.append("\\newlength\\crossdepth %Tiefe fürs \\cross (Freiraum unterm Inhalt)").append(System.lineSeparator());
exportPageHeader.append("\\newlength\\crosslinethickness %Linienstärke fürs \\cross").append(System.lineSeparator());
exportPageHeader.append("\\newlength\\crosshooklength %die Länge des Hakens").append(System.lineSeparator());
exportPageHeader.append("\\newlength\\crosscontdepth").append(System.lineSeparator());
exportPageHeader.append("\\newlength\\crosscontbelowdist").append(System.lineSeparator());
exportPageHeader.append("\\newlength\\crossAbove").append(System.lineSeparator());
exportPageHeader.append("\\newlength\\crossBelow").append(System.lineSeparator());
exportPageHeader.append("\\newlength\\formabovedist").append(System.lineSeparator());
exportPageHeader.append("\\newlength\\formbelowdist").append(System.lineSeparator());
exportPageHeader.append(System.lineSeparator());
exportPageHeader.append("\\setlength\\formabovedist{4ex} %Ändern für Abstand über Form").append(System.lineSeparator());
exportPageHeader.append("\\setlength\\formbelowdist{2ex} %Ändern für Abstand unter Form").append(System.lineSeparator());
exportPageHeader.append("\\setlength\\crossleftdist{0.5em}").append(System.lineSeparator());
exportPageHeader.append("\\setlength\\crossrightdist{0.5em}").append(System.lineSeparator());
exportPageHeader.append("\\setlength\\crosscontleftdist{1pt}").append(System.lineSeparator());
exportPageHeader.append("\\setlength\\crosscontrightdist{4pt}").append(System.lineSeparator());
exportPageHeader.append("\\setlength\\crosscontabovedist{3.5pt}").append(System.lineSeparator());
exportPageHeader.append("\\setlength\\crossdepth{5pt}").append(System.lineSeparator());
exportPageHeader.append("\\setlength\\crosslinethickness{0.4pt}").append(System.lineSeparator());
exportPageHeader.append("\\setlength\\crosshooklength{\\dimexpr\\crossdepth-3pt\\relax}").append(System.lineSeparator()).append(System.lineSeparator());
exportPageHeader.append("\\newcommand*\\cross[1]{%").append(System.lineSeparator());
exportPageHeader.append(" \\settodepth\\crosscontdepth{#1}%").append(System.lineSeparator());
exportPageHeader.append(" \\setlength\\crosscontbelowdist{0pt}%").append(System.lineSeparator());
exportPageHeader.append(" \\ifdim\\crosscontdepth=0pt").append(System.lineSeparator());
exportPageHeader.append(" \\settodepth\\crosscontdepth{g}%").append(System.lineSeparator());
exportPageHeader.append(" \\addtolength\\crosscontbelowdist{\\crosscontdepth}%").append(System.lineSeparator());
exportPageHeader.append(" \\fi").append(System.lineSeparator());
exportPageHeader.append(" \\raisebox{-\\crosscontdepth}{%").append(System.lineSeparator());
exportPageHeader.append(" \\mbox{%").append(System.lineSeparator());
exportPageHeader.append(" \\hbox{%").append(System.lineSeparator());
exportPageHeader.append(" \\kern \\crossleftdist").append(System.lineSeparator());
exportPageHeader.append(" \\vbox{%").append(System.lineSeparator());
exportPageHeader.append(" \\hrule height \\crosslinethickness").append(System.lineSeparator());
exportPageHeader.append(" \\kern\\crosscontabovedist").append(System.lineSeparator());
exportPageHeader.append(" \\hbox{%").append(System.lineSeparator());
exportPageHeader.append(" \\kern \\crosscontleftdist").append(System.lineSeparator());
exportPageHeader.append(" \\raisebox{-\\crosscontdepth}{%").append(System.lineSeparator());
exportPageHeader.append(" \\begingroup").append(System.lineSeparator());
exportPageHeader.append(" \\setlength\\crossleftdist{-\\crosscontleftdist}%").append(System.lineSeparator());
exportPageHeader.append(" \\vphantom{b}#1%").append(System.lineSeparator());
exportPageHeader.append(" \\endgroup").append(System.lineSeparator());
exportPageHeader.append(" }%").append(System.lineSeparator());
exportPageHeader.append(" \\kern \\crosscontrightdist").append(System.lineSeparator());
exportPageHeader.append(" }%").append(System.lineSeparator());
exportPageHeader.append(" \\kern \\crosscontbelowdist").append(System.lineSeparator());
exportPageHeader.append(" }%").append(System.lineSeparator());
exportPageHeader.append(" \\vrule width \\crosslinethickness %depth \\crosscontdepth").append(System.lineSeparator());
exportPageHeader.append(" \\kern \\crossrightdist").append(System.lineSeparator());
exportPageHeader.append(" }%").append(System.lineSeparator());
exportPageHeader.append(" }%").append(System.lineSeparator());
exportPageHeader.append(" }%").append(System.lineSeparator());
exportPageHeader.append("}").append(System.lineSeparator());
exportPageHeader.append("").append(System.lineSeparator());
exportPageHeader.append("\\newcommand*\\ReEntry[1]{%").append(System.lineSeparator());
exportPageHeader.append(" \\settodepth\\crosscontdepth{#1}%").append(System.lineSeparator());
exportPageHeader.append(" \\settoheight\\crossAbove{#1}%").append(System.lineSeparator());
exportPageHeader.append(" \\addtolength\\crossAbove{\\crosslinethickness}%").append(System.lineSeparator());
exportPageHeader.append(" \\setlength\\crossBelow{\\dimexpr\\crosscontdepth+\\crossdepth\\relax}%").append(System.lineSeparator());
exportPageHeader.append(" \\raisebox{-\\crossBelow}[\\crossAbove][\\dimexpr\\crossBelow+\\crosslinethickness\\relax]{%").append(System.lineSeparator());
exportPageHeader.append(" \\mbox{%").append(System.lineSeparator());
exportPageHeader.append(" \\hbox{%").append(System.lineSeparator());
exportPageHeader.append(" \\kern \\crossleftdist").append(System.lineSeparator());
exportPageHeader.append(" \\vrule width \\crosslinethickness height \\dimexpr\\crosshooklength+\\crosscontdepth\\relax").append(System.lineSeparator());
exportPageHeader.append(" \\kern-\\crosslinethickness").append(System.lineSeparator());
exportPageHeader.append(" \\vbox{%").append(System.lineSeparator());
exportPageHeader.append(" \\hrule height \\crosslinethickness").append(System.lineSeparator());
exportPageHeader.append(" \\kern \\crosscontabovedist").append(System.lineSeparator());
exportPageHeader.append(" \\hbox{%").append(System.lineSeparator());
exportPageHeader.append(" \\kern \\crosscontleftdist").append(System.lineSeparator());
exportPageHeader.append(" \\begingroup").append(System.lineSeparator());
exportPageHeader.append(" \\setlength\\crossleftdist{-\\crosscontleftdist}%").append(System.lineSeparator());
exportPageHeader.append(" #1%").append(System.lineSeparator());
exportPageHeader.append(" \\endgroup").append(System.lineSeparator());
exportPageHeader.append(" \\kern \\crosscontrightdist").append(System.lineSeparator());
exportPageHeader.append(" }%").append(System.lineSeparator());
exportPageHeader.append(" \\kern \\crossdepth").append(System.lineSeparator());
exportPageHeader.append(" \\hrule height 0pt depth \\crosslinethickness").append(System.lineSeparator());
exportPageHeader.append(" }%").append(System.lineSeparator());
exportPageHeader.append(" \\vrule width\\crosslinethickness").append(System.lineSeparator());
exportPageHeader.append(" \\kern \\crossrightdist").append(System.lineSeparator());
exportPageHeader.append(" }%").append(System.lineSeparator());
exportPageHeader.append(" }%").append(System.lineSeparator());
exportPageHeader.append(" }%").append(System.lineSeparator());
exportPageHeader.append("}").append(System.lineSeparator()).append(System.lineSeparator());
exportPageHeader.append("\\newcommand*\\FormAbstand[1]{%").append(System.lineSeparator());
// prepare form-paragraph
String formtag = "\\raisebox{0pt}[\\formabovedist][\\formbelowdist]#1";
// check whether formtag should be centred
if (settingsObj.getLatexExportCenterForm()) {
formtag = "\\begin{center}" + formtag + "\\end{center}";
}
// enter % for significant empty spaces
formtag = formtag + "%";
// insert string
exportPageHeader.append(" ").append(formtag).append(System.lineSeparator());
exportPageHeader.append("}").append(System.lineSeparator()).append(System.lineSeparator());
}
/**
*
* @param zettelnummer
* @param comment
* @return
*/
private String latexBeginTag(String comment) {
StringBuilder sb = new StringBuilder("");
// check whether a comment should be added
if (comment != null && !comment.isEmpty()) {
// insert line-wrapped comment first...
sb.append(Tools.lineWrapText(comment, 40, "%"));
}
// return result
return sb.toString();
}
/**
* This method creates a HTML-page that contains all the desktop-data (i.e. all entries or
* modified entries on the desktop), where the output of the HTML-page is identical to the view
* of the desktop. I.e. if the user turned off entry-titles, these are also not exportet to the
* output file.
*
* @param node the starting point for the jTree-enumeration, either the root node or a bullet
* (if only a bullet should be exported, see
* {@link #exportDesktopBullet() exportDesktopBullet()}).
* @param sb the stringbuilder which finally will contain all content in html-format
* @param exportcomments {@code true} if comments should also be exported, {@code false} if
* comments should not be exported.
*/
private void exportEntriesWithComments(DefaultMutableTreeNode node, boolean exportcomments) {
// get a list with all children of the node
Enumeration en = node.children();
// go through all children
while (en.hasMoreElements()) {
// get the child
node = (DefaultMutableTreeNode) en.nextElement();
// if the child is a bullet...
if (node.getAllowsChildren()) {
// append bullet point
exportPage.append(createExportBullet(node, exportcomments));
} // now we know we have an entry. so get the entry number...
else {
// add entry
exportPage.append(createExportEntry(node, exportcomments));
}
// when the new node also has children, call this method again,
// so we go through the strucuture recursively...
if (node.getChildCount() > 0) {
exportEntriesWithComments(node, exportcomments);
}
}
}
/**
* This method creates a HTML-page that contains all the desktop-data (i.e. all entries or
* modified entries on the desktop), where the output of the HTML-page is identical to the view
* of the desktop. I.e. if the user turned off entry-titles, these are also not exportet to the
* output file.
*
* @param node the starting point for the jTree-enumeration, either the root node or a bullet
* (if only a bullet should be exported, see
* {@link #exportDesktopBullet() exportDesktopBullet()}).
* @param sb the stringbuilder which finally will contain all content in html-format
* @param exportcomments {@code true} if comments should also be exported, {@code false} if
* comments should not be exported.
*/
private void exportEntriesWithCommentsOnly(DefaultMutableTreeNode node) {
// get a list with all children of the node
Enumeration en = node.children();
// go through all children
while (en.hasMoreElements()) {
// get the child
node = (DefaultMutableTreeNode) en.nextElement();
// retrieve comment
String com = desktopObj.getComment(TreeUtil.getNodeTimestamp(node), System.lineSeparator());
// check for valid comment
if (com != null && !com.isEmpty()) {
// if the child is a bullet...
if (node.getAllowsChildren()) {
// append bullet point
exportPage.append(createExportBullet(node, true));
} // now we know we have an entry. so get the entry number...
else {
// add entry
exportPage.append(createExportEntry(node, true));
}
}
// when the new node also has children, call this method again,
// so we go through the strucuture recursively...
if (node.getChildCount() > 0) {
exportEntriesWithCommentsOnly(node);
}
}
}
/**
* This method prepares the html-content for an exported entry. this method is used by {@link #exportEntriesWithCommentsToPDF(javax.swing.tree.DefaultMutableTreeNode, java.lang.StringBuilder, boolean) exportEntriesWithCommentsToPDF()
* }
* and
* {@link #exportEntriesWithCommentsOnlyToPDF(javax.swing.tree.DefaultMutableTreeNode, java.lang.StringBuilder) exportEntriesWithCommentsOnlyToPDF()}.
*
* @param node the entry-node, needed for timestamp and entry-text
* @return a html-snippet with the entry as content
*/
private String createExportEntry(DefaultMutableTreeNode node, boolean exportcomments) {
StringBuilder sb = new StringBuilder("");
// we now want to check whether the user has made modifications to the entry's
// content, which are only made to the desktop (the content of the entry in the main database
// is not changed, so you can edit the desktop-entry without changing the entry's original
// content - this is useful when you want to add some words/phrases between entries etc., which
// should be applied only to the final text on the desktop, but not to the original entries).
//
// in case we have modified an entry on the desktop, this entry has a "content" element. to
// retrieve the correct entry, we need to look for the unique timestamp of that entry - since
// an entry could appear multiple times on the desktop, thus the entry number itself is no
// valid value for retrieving the right entry. Therefore, each treenode has a user-object
// assigned, which holds the unique timestamp
String text = desktopObj.retrieveModifiedEntryContentFromTimestamp(TreeUtil.getNodeTimestamp(node));
// retrieve entry-number
int nr = TreeUtil.extractEntryNumberFromNode(node);
// if nothing found, retrieve regular entry
// that means, if the entry with the unique-timestamp has no or an empty content-element, the
// entry was not modified - thus we retrieve the "original" entry.
if (null == text || text.isEmpty()) {
// retrieve regular content
text = dataObj.getZettelContent(nr);
}
// convert special chars and enquote quotes
text = getConvertedTex(text);
// retrieve comment
String com = (exportcomments) ? desktopObj.getComment(TreeUtil.getNodeTimestamp(node), System.lineSeparator()) : "";
// add each beginning entry-tag
sb.append(latexBeginTag(com));
// check whether the user wants to export titles.
// check whether the user wants to export titles.
if (isHeadingVisible) {
// first check whether we have a title or not
String zetteltitle = dataObj.getZettelTitle(nr);
// only prepare a title when we want to have the entry's number as title-prefix,
// or if we have a title.
if (!zetteltitle.isEmpty() || zettelNumberAsPrefix) {
// don't start section here, because the bullets indicate a new section.
// instead, use bold formatting
sb.append("\\textbf{");
// each entry has at least the title "entry" plus its number.
// we need this to search through the entries when the user clicks an entry on the
// jTreeDesktop in the desktop-window
if (zettelNumberAsPrefix) {
sb.append(resourceMap.getString("entryText")).append(" ").append(String.valueOf(nr));
}
// if we have a "real" title, append it...
if (!zetteltitle.isEmpty()) {
if (zettelNumberAsPrefix) {
sb.append(": ");
}
sb.append(zetteltitle);
}
sb.append("}");
sb.append(System.lineSeparator()).append(System.lineSeparator());
}
}
// if we have content, add it.
if (!text.isEmpty()) {
// check whether we have form-tags
if (text.contains(Constants.FORMAT_FORM_TAG)) {
zettelHasForms = true;
}
// first, replace all footnotes with bibkeys
// to appropriate cite-tag in latex
text = ExportTools.createLatexFootnotes(dataObj, text, settingsObj.getLatexExportFootnoteRef());
// then append the content
sb.append(text);
} else {
// else add remark that entry is deleted
sb.append(resourceMap.getString("deletedEntry"));
}
// if the user wants to export remarks, do this here.
if ((settingsObj.getDesktopDisplayItems() & Constants.DESKTOP_SHOW_REMARKS) != 0) {
// get entry's remarks
String remarks = dataObj.getCleanRemarks(nr);
// check whether we have any
if (!remarks.isEmpty()) {
// set headline indicating that we have remarks here
sb.append(System.lineSeparator()).append("\\textit{").append(resourceMap.getString("remarksHeader")).append("}");
// init paragraph with class-attribute, so the user may change style aftwerwards
sb.append(remarks);
}
}
// close zettel-tags
// uncomment this, if the "end{zettel}" command should be enabled. As this leads to errors when comiling the latex file,
// the begin{zettel} and end{zettel} tags are not used, see method "latexBeginTag()"
// sb.append(System.lineSeparator()).append("\\end{zettel}").append(System.lineSeparator());
sb.append(System.lineSeparator()).append(System.lineSeparator());
// if the user wishes to remove multiple line-breaks, do this here
if (settingsObj.getRemoveLinesForDesktopExport()) {
// retrieve current content
text = sb.toString();
// remove double line separaters
text = text.replace(System.lineSeparator() + System.lineSeparator(), System.lineSeparator());
// set back content
sb = new StringBuilder(text);
}
return sb.toString();
}
/**
* This method prepares the html-content for an exported bullet-point. this method is used by {@link #exportEntriesWithCommentsToPDF(javax.swing.tree.DefaultMutableTreeNode, java.lang.StringBuilder, boolean) exportEntriesWithCommentsToPDF()
* }
* and
* {@link #exportEntriesWithCommentsOnlyToPDF(javax.swing.tree.DefaultMutableTreeNode, java.lang.StringBuilder) exportEntriesWithCommentsOnlyToPDF()}.
*
* @param node the bullet-node, needed for timestamp and title-text
* @return a html-snippet with the bullet as headline
*/
private String createExportBullet(DefaultMutableTreeNode node, boolean exportcomments) {
StringBuilder sb = new StringBuilder("");
// check whether comments should be exported as well
if (exportcomments) {
// retrieve comment
String com = desktopObj.getComment(TreeUtil.getNodeTimestamp(node), System.lineSeparator());
// check for valid comment
if (com != null && !com.isEmpty()) {
// append comment
sb.append(Tools.lineWrapText(com, 40, "%"));
}
}
// retrieve bullet-level, so we can use subsections according to the bullet-level
int bulletlevel = node.getLevel();
// check which level the bullet is, so we can either indicate this heading as section
// or sub(sub)section...
switch (bulletlevel) {
case 1:
sb.append("\\section{");
break;
case 2:
sb.append("\\subsection{");
break;
case 3:
sb.append("\\subsubsection{");
break;
case 4:
sb.append("\\paragraph{");
break;
case 5:
sb.append("\\subparagraph{");
break;
}
// get bullet-text
String text = TreeUtil.getNodeText(node);
// get converted special chars and enquotes quotes
text = getConvertedTex(text);
// append text
sb.append(text).append("}").append(System.lineSeparator()).append(System.lineSeparator());
return sb.toString();
}
/**
* This method enquotes all quotes in a string, so " will be converted to {@code \enquote}.
*
* @param content
* @return
*/
private String enquoteQuotes(String content) {
// check for valid value
if (null == content) {
return null;
}
if (content.isEmpty()) {
return "";
}
// check whether french quotes should be converted
if (settingsObj.getLatexExportConvertQuotes()) {
// convert french quotes into normal quotes
content = content.replaceAll(Pattern.quote("»"), Matcher.quoteReplacement("\""));
content = content.replaceAll(Pattern.quote("«"), Matcher.quoteReplacement("\""));
content = content.replaceAll(Pattern.quote("›"), Matcher.quoteReplacement("\""));
content = content.replaceAll(Pattern.quote("‹"), Matcher.quoteReplacement("\""));
}
// init pos-variables
int pos = 0;
int endpos;
// search for quotes until we don't find anymore.
while (pos != -1) {
// find start of quotes
pos = content.indexOf("\"", pos);
// check whether it was found or not
if (pos != -1) {
// find end of quotes
endpos = content.indexOf("\"", pos + 1);
// if we also found an endquote, replace quotes with latex-command
if (endpos != -1) {
// replace quotes with enquote-tag
content = content.substring(0, pos) + "\\enquote{" + content.substring(pos + 1, endpos) + "}" + content.substring(endpos + 1);
} // if no endquote was found, quit loop
else {
pos = -1;
}
}
}
return content;
}
private String convertSpecialChars(String dummy) {
if (null == dummy) {
return null;
}
if (dummy.isEmpty()) {
return "";
}
// convert signs and special chars
// dummy = dummy.replaceAll(Pattern.quote("#"), Matcher.quoteReplacement("\\#"));
dummy = dummy.replaceAll(Pattern.quote("{"), Matcher.quoteReplacement("\\{"));
dummy = dummy.replaceAll(Pattern.quote("}"), Matcher.quoteReplacement("\\}"));
dummy = dummy.replaceAll(Pattern.quote("$"), Matcher.quoteReplacement("\\$"));
dummy = dummy.replaceAll(Pattern.quote("%"), Matcher.quoteReplacement("\\%"));
dummy = dummy.replaceAll(Pattern.quote("&"), Matcher.quoteReplacement("\\&"));
dummy = dummy.replaceAll(Pattern.quote("_"), Matcher.quoteReplacement("\\_"));
dummy = dummy.replaceAll(Pattern.quote("→"), Matcher.quoteReplacement("\\textrightarrow"));
dummy = dummy.replaceAll(Pattern.quote("←"), Matcher.quoteReplacement("\\textleftarrow"));
dummy = dummy.replaceAll(Pattern.quote("↑"), Matcher.quoteReplacement("\\textuparrow"));
dummy = dummy.replaceAll(Pattern.quote("↓"), Matcher.quoteReplacement("\\textdownarrow"));
dummy = dummy.replaceAll(Pattern.quote("<"), Matcher.quoteReplacement("\\langle"));
// TODO XXX Hack: ">" should only be convered if Markdown is not enabled, otherwise, it will be
// taken as a quotation by subsequent components. (fixes bug reproduced by
// "testBugMarkdownZitatWirdNichtKorrektNachLatexExportiert")
if (!settingsObj.getMarkdownActivated()) {
dummy = dummy.replaceAll(Pattern.quote(">"), Matcher.quoteReplacement("\\rangle"));
}
dummy = dummy.replaceAll(Pattern.quote("§"), Matcher.quoteReplacement("\\textsection"));
dummy = dummy.replaceAll(Pattern.quote("$"), Matcher.quoteReplacement("\\$"));
dummy = dummy.replaceAll(Pattern.quote("€"), Matcher.quoteReplacement("\\texteuro"));
dummy = dummy.replaceAll(Pattern.quote("£"), Matcher.quoteReplacement("\\textsterling"));
dummy = dummy.replaceAll(Pattern.quote("¼"), Matcher.quoteReplacement("\\textonequarter"));
dummy = dummy.replaceAll(Pattern.quote("½"), Matcher.quoteReplacement("\\textonehalf"));
dummy = dummy.replaceAll(Pattern.quote("¾"), Matcher.quoteReplacement("\\textthreequarters"));
// check whether french quotes should be converted
if (!settingsObj.getLatexExportConvertQuotes()) {
dummy = dummy.replaceAll(Pattern.quote("»"), Matcher.quoteReplacement("\\guillemotright"));
dummy = dummy.replaceAll(Pattern.quote("«"), Matcher.quoteReplacement("\\guillemotleft"));
}
return dummy;
}
private String convertSpecialChars2(String dummy) {
// need to convert umlauts?
if (null == dummy || dummy.isEmpty() || !settingsObj.getLatexExportConvertUmlaut()) {
return dummy;
}
// convert signs and special chars
dummy = dummy.replaceAll(Pattern.quote("ä"), Matcher.quoteReplacement("{\\\"a}"));
dummy = dummy.replaceAll(Pattern.quote("ö"), Matcher.quoteReplacement("{\\\"o}"));
dummy = dummy.replaceAll(Pattern.quote("ü"), Matcher.quoteReplacement("{\\\"u}"));
dummy = dummy.replaceAll(Pattern.quote("Ä"), Matcher.quoteReplacement("{\\\"A}"));
dummy = dummy.replaceAll(Pattern.quote("Ö"), Matcher.quoteReplacement("{\\\"O}"));
dummy = dummy.replaceAll(Pattern.quote("Ü"), Matcher.quoteReplacement("{\\\"U}"));
dummy = dummy.replaceAll(Pattern.quote("ß"), Matcher.quoteReplacement("{\\ss}"));
return dummy;
}
private String getConvertedTex(String text) {
return convertSpecialChars2(enquoteQuotes(convertSpecialChars(text)));
}
}