src_insets_files = Split('''
- ExternalSupport.C
- ExternalTemplate.C
- ExternalTransforms.C
+ ExternalSupport.cpp
+ ExternalTemplate.cpp
+ ExternalTransforms.cpp
Inset.cpp
InsetBase.cpp
InsetBibitem.cpp
+++ /dev/null
-/**
- * \file ExternalSupport.C
- * This file is part of LyX, the document processor.
- * Licence details can be found in the file COPYING.
- *
- * \author Asger Alstrup Nielsen
- * \author Angus Leeming
- *
- * Full author contact details are available in file CREDITS.
- */
-
-#include <config.h>
-
-#include "ExternalSupport.h"
-#include "ExternalTemplate.h"
-#include "ExternalTransforms.h"
-#include "InsetExternal.h"
-
-#include "Buffer.h"
-#include "Converter.h"
-#include "debug.h"
-#include "Exporter.h"
-#include "Format.h"
-#include "Mover.h"
-
-#include "support/filetools.h"
-#include "support/Forkedcall.h"
-#include "support/lstrings.h"
-#include "support/lyxalgo.h"
-#include "support/lyxlib.h"
-#include "support/os.h"
-#include "support/Package.h"
-
-#include <boost/filesystem/operations.hpp>
-
-using std::endl;
-using std::string;
-using std::vector;
-
-using boost::filesystem::is_directory;
-
-
-namespace lyx {
-
-using support::FileName;
-
-namespace external {
-
-Template const * getTemplatePtr(InsetExternalParams const & params)
-{
- TemplateManager const & etm = TemplateManager::get();
- return etm.getTemplateByName(params.templatename());
-}
-
-
-void editExternal(InsetExternalParams const & params, Buffer const & buffer)
-{
- formats.edit(buffer, params.filename,
- formats.getFormatFromFile(params.filename));
-}
-
-
-namespace {
-
-string const subst_path(string const & input,
- string const & placeholder,
- string const & path,
- bool use_latex_path,
- support::latex_path_extension ext = support::PROTECT_EXTENSION,
- support::latex_path_dots dots = support::LEAVE_DOTS)
-{
- if (input.find(placeholder) == string::npos)
- return input;
- // Don't use external_path here when use_latex_path is false, as the
- // path will be compared with another one in internal style later
- // in Converters::move.
- string const path2 = use_latex_path ?
- support::latex_path(path, ext, dots) : path;
- return support::subst(input, placeholder, path2);
-}
-
-} // namespace anon
-
-
-string const doSubstitution(InsetExternalParams const & params,
- Buffer const & buffer, string const & s,
- bool use_latex_path,
- bool external_in_tmpdir,
- Substitute what)
-{
- Buffer const * m_buffer = buffer.getMasterBuffer();
- string const parentpath = external_in_tmpdir ?
- m_buffer->temppath() :
- buffer.filePath();
- string const filename = external_in_tmpdir ?
- params.filename.mangledFilename() :
- params.filename.outputFilename(parentpath);
- string const basename = support::changeExtension(
- support::onlyFilename(filename), string());
- string const absname = support::makeAbsPath(filename, parentpath).absFilename();
-
- string result = s;
- if (what != ALL_BUT_PATHS) {
- string const filepath = support::onlyPath(filename);
- string const abspath = support::onlyPath(absname);
- string const masterpath = external_in_tmpdir ?
- m_buffer->temppath() :
- m_buffer->filePath();
- // FIXME UNICODE
- string relToMasterPath = support::onlyPath(
- to_utf8(support::makeRelPath(from_utf8(absname),
- from_utf8(masterpath))));
- if (relToMasterPath == "./")
- relToMasterPath.clear();
- // FIXME UNICODE
- string relToParentPath = support::onlyPath(
- to_utf8(support::makeRelPath(from_utf8(absname),
- from_utf8(parentpath))));
- if (relToParentPath == "./")
- relToParentPath.clear();
-
- result = subst_path(result, "$$FPath", filepath,
- use_latex_path,
- support::PROTECT_EXTENSION,
- support::ESCAPE_DOTS);
- result = subst_path(result, "$$AbsPath", abspath,
- use_latex_path,
- support::PROTECT_EXTENSION,
- support::ESCAPE_DOTS);
- result = subst_path(result, "$$RelPathMaster",
- relToMasterPath, use_latex_path,
- support::PROTECT_EXTENSION,
- support::ESCAPE_DOTS);
- result = subst_path(result, "$$RelPathParent",
- relToParentPath, use_latex_path,
- support::PROTECT_EXTENSION,
- support::ESCAPE_DOTS);
- if (support::absolutePath(filename)) {
- result = subst_path(result, "$$AbsOrRelPathMaster",
- abspath, use_latex_path,
- support::PROTECT_EXTENSION,
- support::ESCAPE_DOTS);
- result = subst_path(result, "$$AbsOrRelPathParent",
- abspath, use_latex_path,
- support::PROTECT_EXTENSION,
- support::ESCAPE_DOTS);
- } else {
- result = subst_path(result, "$$AbsOrRelPathMaster",
- relToMasterPath, use_latex_path,
- support::PROTECT_EXTENSION,
- support::ESCAPE_DOTS);
- result = subst_path(result, "$$AbsOrRelPathParent",
- relToParentPath, use_latex_path,
- support::PROTECT_EXTENSION,
- support::ESCAPE_DOTS);
- }
- }
-
- if (what == PATHS)
- return result;
-
- result = subst_path(result, "$$FName", filename, use_latex_path,
- support::EXCLUDE_EXTENSION);
- result = subst_path(result, "$$Basename", basename, use_latex_path,
- support::PROTECT_EXTENSION, support::ESCAPE_DOTS);
- result = subst_path(result, "$$Extension",
- '.' + support::getExtension(filename), use_latex_path);
- result = subst_path(result, "$$Tempname", params.tempname().absFilename(), use_latex_path);
- result = subst_path(result, "$$Sysdir",
- support::package().system_support().absFilename(), use_latex_path);
-
- // Handle the $$Contents(filename) syntax
- if (support::contains(result, "$$Contents(\"")) {
- // Since use_latex_path may be true we must extract the file
- // name from s instead of result and do the substitutions
- // again, this time with use_latex_path false.
- string::size_type const spos = s.find("$$Contents(\"");
- string::size_type const send = s.find("\")", spos);
- string const file_template = s.substr(spos + 12, send - (spos + 12));
- string const file = doSubstitution(params, buffer,
- file_template, false,
- external_in_tmpdir, what);
- string contents;
-
- FileName const absfile(
- support::makeAbsPath(file, m_buffer->temppath()));
- if (support::isFileReadable(absfile))
- contents = support::getFileContents(absfile);
-
- string::size_type const pos = result.find("$$Contents(\"");
- string::size_type const end = result.find("\")", pos);
- result.replace(pos, end + 2, contents);
- }
-
- return result;
-}
-
-
-namespace {
-
-/** update the file represented by the template.
- If \p external_in_tmpdir == true, then the generated file is
- placed in the buffer's temporary directory.
-*/
-void updateExternal(InsetExternalParams const & params,
- string const & format,
- Buffer const & buffer,
- ExportData & exportdata,
- bool external_in_tmpdir,
- bool dryrun)
-{
- Template const * const et_ptr = getTemplatePtr(params);
- if (!et_ptr)
- return; // FAILURE
- Template const & et = *et_ptr;
-
- if (!et.automaticProduction)
- return; // NOT_NEEDED
-
- Template::Formats::const_iterator cit = et.formats.find(format);
- if (cit == et.formats.end())
- return; // FAILURE
-
- Template::Format const & outputFormat = cit->second;
- if (outputFormat.updateResult.empty())
- return; // NOT_NEEDED
-
- string from_format = et.inputFormat;
- if (from_format.empty())
- return; // NOT_NEEDED
-
- if (from_format == "*") {
- if (params.filename.empty())
- return; // NOT_NEEDED
-
- // Try and ascertain the file format from its contents.
- from_format = formats.getFormatFromFile(params.filename);
- if (from_format.empty())
- return; // FAILURE
-
- }
-
- string const to_format = outputFormat.updateFormat;
- if (to_format.empty())
- return; // NOT_NEEDED
-
- // The master buffer. This is useful when there are multiple levels
- // of include files
- Buffer const * m_buffer = buffer.getMasterBuffer();
-
- // We copy the source file to the temp dir and do the conversion
- // there if necessary
- FileName const temp_file(
- support::makeAbsPath(params.filename.mangledFilename(),
- m_buffer->temppath()));
- if (!params.filename.empty() && !is_directory(params.filename.toFilesystemEncoding())) {
- unsigned long const from_checksum = support::sum(params.filename);
- unsigned long const temp_checksum = support::sum(temp_file);
-
- if (from_checksum != temp_checksum) {
- Mover const & mover = getMover(from_format);
- if (!mover.copy(params.filename, temp_file)) {
- LYXERR(Debug::EXTERNAL)
- << "external::updateExternal. "
- << "Unable to copy "
- << params.filename << " to " << temp_file << endl;
- return; // FAILURE
- }
- }
- }
-
- // the generated file (always in the temp dir)
- string const to_file = doSubstitution(params, buffer,
- outputFormat.updateResult,
- false, true);
- FileName const abs_to_file(
- support::makeAbsPath(to_file, m_buffer->temppath()));
-
- if (!dryrun) {
- // Record the referenced files for the exporter.
- // The exporter will copy them to the export dir.
- typedef Template::Format::FileMap FileMap;
- FileMap::const_iterator rit = outputFormat.referencedFiles.begin();
- FileMap::const_iterator rend = outputFormat.referencedFiles.end();
- for (; rit != rend; ++rit) {
- vector<string>::const_iterator fit = rit->second.begin();
- vector<string>::const_iterator fend = rit->second.end();
- for (; fit != fend; ++fit) {
- FileName const source(support::makeAbsPath(
- doSubstitution(params, buffer, *fit,
- false, true),
- m_buffer->temppath()));
- // The path of the referenced file is never the
- // temp path, but the filename may be the mangled
- // or the real name. Therefore we substitute the
- // paths and names separately.
- string file = support::subst(*fit, "$$FName",
- "$$FPath$$Basename$$Extension");
- file = doSubstitution(params, buffer, file, false, false,
- PATHS);
- file = doSubstitution(params, buffer, file,
- false, external_in_tmpdir,
- ALL_BUT_PATHS);
- // if file is a relative name, it is interpreted
- // relative to the master document.
- exportdata.addExternalFile(rit->first, source, file);
- }
- }
- }
-
- // Do we need to perform the conversion?
- // Yes if to_file does not exist or if from_file is newer than to_file
- if (support::compare_timestamps(temp_file, abs_to_file) < 0)
- return; // SUCCESS
-
- // FIXME (Abdel 12/08/06): Is there a need to show these errors?
- ErrorList el;
- bool const success =
- theConverters().convert(&buffer, temp_file, abs_to_file,
- params.filename, from_format, to_format, el,
- Converters::try_default | Converters::try_cache);
-
- if (!success)
- LYXERR(Debug::EXTERNAL)
- << "external::updateExternal. "
- << "Unable to convert from "
- << from_format << " to " << to_format << endl;
-
- // return success
-}
-
-
-string const substituteCommands(InsetExternalParams const & params,
- string const & input, string const & format);
-
-string const substituteOptions(InsetExternalParams const & params,
- string const & input, string const & format);
-
-} // namespace anon
-
-
-int writeExternal(InsetExternalParams const & params,
- string const & format,
- Buffer const & buffer, odocstream & os,
- ExportData & exportdata,
- bool external_in_tmpdir,
- bool dryrun)
-{
- Template const * const et_ptr = getTemplatePtr(params);
- if (!et_ptr)
- return 0;
- Template const & et = *et_ptr;
-
- Template::Formats::const_iterator cit = et.formats.find(format);
- if (cit == et.formats.end()) {
- LYXERR(Debug::EXTERNAL)
- << "External template format '" << format
- << "' not specified in template "
- << params.templatename() << endl;
- return 0;
- }
-
- if (!dryrun || support::contains(cit->second.product, "$$Contents"))
- updateExternal(params, format, buffer, exportdata,
- external_in_tmpdir, dryrun);
-
- bool const use_latex_path = format == "LaTeX";
- string str = doSubstitution(params, buffer, cit->second.product,
- use_latex_path, external_in_tmpdir);
- str = substituteCommands(params, str, format);
- str = substituteOptions(params, str, format);
- // FIXME UNICODE
- os << from_utf8(str);
- return int(lyx::count(str.begin(), str.end(),'\n'));
-}
-
-namespace {
-
-// Empty template, specialised below.
-template <typename TransformType>
-string const substituteIt(string const &,
- TransformID,
- string const &,
- Template::Format const &,
- InsetExternalParams const &);
-
-
-template <>
-string const substituteIt<TransformCommand>(string const & input,
- TransformID id,
- string const & /* formatname */,
- Template::Format const & format,
- InsetExternalParams const & params)
-{
- typedef std::map<TransformID, TransformStore> Transformers;
- Transformers::const_iterator it = format.command_transformers.find(id);
- if (it == format.command_transformers.end())
- return input;
-
- TransformStore const & store = it->second;
-
- TransformCommand::ptr_type ptr;
- if (id == Rotate)
- ptr = store.getCommandTransformer(params.rotationdata);
- else if (id == Resize)
- ptr = store.getCommandTransformer(params.resizedata);
-
- if (!ptr.get())
- return input;
-
- string result =
- support::subst(input, ptr->front_placeholder(), ptr->front());
- return support::subst(result, ptr->back_placeholder(), ptr->back());
-}
-
-
-template <>
-string const substituteIt<TransformOption>(string const & input,
- TransformID id,
- string const & fname,
- Template::Format const & format,
- InsetExternalParams const & params)
-{
- typedef std::map<TransformID, TransformStore> Transformers;
- Transformers::const_iterator it = format.option_transformers.find(id);
- if (it == format.option_transformers.end())
- return input;
-
- TransformStore const & store = it->second;
-
- TransformOption::ptr_type ptr;
- switch (id) {
- case Clip:
- ptr = store.getOptionTransformer(params.clipdata);
- break;
- case Extra:
- ptr = store.getOptionTransformer(params.extradata.get(fname));
- break;
- case Rotate:
- ptr = store.getOptionTransformer(params.rotationdata);
- break;
- case Resize:
- ptr = store.getOptionTransformer(params.resizedata);
- break;
- }
-
- if (!ptr.get())
- return input;
-
- return support::subst(input, ptr->placeholder(), ptr->option());
-}
-
-
-template <typename TransformerType>
-string const transformIt(InsetExternalParams const & params,
- string const & s, string const & formatname)
-{
- Template const * const et = getTemplatePtr(params);
- if (!et || et->transformIds.empty())
- return s;
-
- Template::Formats::const_iterator fit = et->formats.find(formatname);
- if (fit == et->formats.end())
- return s;
-
- string result = s;
- Template::Format const & format = fit->second;
-
- typedef vector<TransformID> TransformsIDs;
- TransformsIDs::const_iterator it = et->transformIds.begin();
- TransformsIDs::const_iterator end = et->transformIds.end();
- for (; it != end; ++it) {
- result = substituteIt<TransformerType>(result, *it, formatname,
- format, params);
- }
- return result;
-}
-
-
-string const substituteCommands(InsetExternalParams const & params,
- string const & input, string const & format)
-{
- return transformIt<TransformCommand>(params, input, format);
-}
-
-
-string const substituteOption(InsetExternalParams const & params,
- string const & input, string const & format)
-{
- string opt = transformIt<TransformOption>(params, input, format);
-
- if (format == "LaTeX" || format == "PDFLaTeX")
- return sanitizeLatexOption(opt);
- if (format == "DocBook")
- return sanitizeDocBookOption(opt);
- return opt;
-}
-
-
-string const substituteOptions(InsetExternalParams const & params,
- string const & input, string const & format)
-{
- string output = input;
-
- Template const * const et = getTemplatePtr(params);
- if (!et || et->transformIds.empty())
- return output;
-
- Template::Formats::const_iterator fit = et->formats.find(format);
- if (fit == et->formats.end() || fit->second.options.empty())
- return output;
-
- typedef vector<Template::Option> Options;
- Options const & options = fit->second.options;
- Options::const_iterator it = options.begin();
- Options::const_iterator end = options.end();
- for (; it != end; ++it) {
- string const opt = substituteOption(params, it->option, format);
- string const placeholder = "$$" + it->name;
- output = support::subst(output, placeholder, opt);
- }
-
- return output;
-}
-
-} // namespace anon
-
-} // namespace external
-
-} // namespace lyx
--- /dev/null
+/**
+ * \file ExternalSupport.cpp
+ * This file is part of LyX, the document processor.
+ * Licence details can be found in the file COPYING.
+ *
+ * \author Asger Alstrup Nielsen
+ * \author Angus Leeming
+ *
+ * Full author contact details are available in file CREDITS.
+ */
+
+#include <config.h>
+
+#include "ExternalSupport.h"
+#include "ExternalTemplate.h"
+#include "ExternalTransforms.h"
+#include "InsetExternal.h"
+
+#include "Buffer.h"
+#include "Converter.h"
+#include "debug.h"
+#include "Exporter.h"
+#include "Format.h"
+#include "Mover.h"
+
+#include "support/filetools.h"
+#include "support/Forkedcall.h"
+#include "support/lstrings.h"
+#include "support/lyxalgo.h"
+#include "support/lyxlib.h"
+#include "support/os.h"
+#include "support/Package.h"
+
+#include <boost/filesystem/operations.hpp>
+
+using std::endl;
+using std::string;
+using std::vector;
+
+using boost::filesystem::is_directory;
+
+
+namespace lyx {
+
+using support::FileName;
+
+namespace external {
+
+Template const * getTemplatePtr(InsetExternalParams const & params)
+{
+ TemplateManager const & etm = TemplateManager::get();
+ return etm.getTemplateByName(params.templatename());
+}
+
+
+void editExternal(InsetExternalParams const & params, Buffer const & buffer)
+{
+ formats.edit(buffer, params.filename,
+ formats.getFormatFromFile(params.filename));
+}
+
+
+namespace {
+
+string const subst_path(string const & input,
+ string const & placeholder,
+ string const & path,
+ bool use_latex_path,
+ support::latex_path_extension ext = support::PROTECT_EXTENSION,
+ support::latex_path_dots dots = support::LEAVE_DOTS)
+{
+ if (input.find(placeholder) == string::npos)
+ return input;
+ // Don't use external_path here when use_latex_path is false, as the
+ // path will be compared with another one in internal style later
+ // in Converters::move.
+ string const path2 = use_latex_path ?
+ support::latex_path(path, ext, dots) : path;
+ return support::subst(input, placeholder, path2);
+}
+
+} // namespace anon
+
+
+string const doSubstitution(InsetExternalParams const & params,
+ Buffer const & buffer, string const & s,
+ bool use_latex_path,
+ bool external_in_tmpdir,
+ Substitute what)
+{
+ Buffer const * m_buffer = buffer.getMasterBuffer();
+ string const parentpath = external_in_tmpdir ?
+ m_buffer->temppath() :
+ buffer.filePath();
+ string const filename = external_in_tmpdir ?
+ params.filename.mangledFilename() :
+ params.filename.outputFilename(parentpath);
+ string const basename = support::changeExtension(
+ support::onlyFilename(filename), string());
+ string const absname = support::makeAbsPath(filename, parentpath).absFilename();
+
+ string result = s;
+ if (what != ALL_BUT_PATHS) {
+ string const filepath = support::onlyPath(filename);
+ string const abspath = support::onlyPath(absname);
+ string const masterpath = external_in_tmpdir ?
+ m_buffer->temppath() :
+ m_buffer->filePath();
+ // FIXME UNICODE
+ string relToMasterPath = support::onlyPath(
+ to_utf8(support::makeRelPath(from_utf8(absname),
+ from_utf8(masterpath))));
+ if (relToMasterPath == "./")
+ relToMasterPath.clear();
+ // FIXME UNICODE
+ string relToParentPath = support::onlyPath(
+ to_utf8(support::makeRelPath(from_utf8(absname),
+ from_utf8(parentpath))));
+ if (relToParentPath == "./")
+ relToParentPath.clear();
+
+ result = subst_path(result, "$$FPath", filepath,
+ use_latex_path,
+ support::PROTECT_EXTENSION,
+ support::ESCAPE_DOTS);
+ result = subst_path(result, "$$AbsPath", abspath,
+ use_latex_path,
+ support::PROTECT_EXTENSION,
+ support::ESCAPE_DOTS);
+ result = subst_path(result, "$$RelPathMaster",
+ relToMasterPath, use_latex_path,
+ support::PROTECT_EXTENSION,
+ support::ESCAPE_DOTS);
+ result = subst_path(result, "$$RelPathParent",
+ relToParentPath, use_latex_path,
+ support::PROTECT_EXTENSION,
+ support::ESCAPE_DOTS);
+ if (support::absolutePath(filename)) {
+ result = subst_path(result, "$$AbsOrRelPathMaster",
+ abspath, use_latex_path,
+ support::PROTECT_EXTENSION,
+ support::ESCAPE_DOTS);
+ result = subst_path(result, "$$AbsOrRelPathParent",
+ abspath, use_latex_path,
+ support::PROTECT_EXTENSION,
+ support::ESCAPE_DOTS);
+ } else {
+ result = subst_path(result, "$$AbsOrRelPathMaster",
+ relToMasterPath, use_latex_path,
+ support::PROTECT_EXTENSION,
+ support::ESCAPE_DOTS);
+ result = subst_path(result, "$$AbsOrRelPathParent",
+ relToParentPath, use_latex_path,
+ support::PROTECT_EXTENSION,
+ support::ESCAPE_DOTS);
+ }
+ }
+
+ if (what == PATHS)
+ return result;
+
+ result = subst_path(result, "$$FName", filename, use_latex_path,
+ support::EXCLUDE_EXTENSION);
+ result = subst_path(result, "$$Basename", basename, use_latex_path,
+ support::PROTECT_EXTENSION, support::ESCAPE_DOTS);
+ result = subst_path(result, "$$Extension",
+ '.' + support::getExtension(filename), use_latex_path);
+ result = subst_path(result, "$$Tempname", params.tempname().absFilename(), use_latex_path);
+ result = subst_path(result, "$$Sysdir",
+ support::package().system_support().absFilename(), use_latex_path);
+
+ // Handle the $$Contents(filename) syntax
+ if (support::contains(result, "$$Contents(\"")) {
+ // Since use_latex_path may be true we must extract the file
+ // name from s instead of result and do the substitutions
+ // again, this time with use_latex_path false.
+ string::size_type const spos = s.find("$$Contents(\"");
+ string::size_type const send = s.find("\")", spos);
+ string const file_template = s.substr(spos + 12, send - (spos + 12));
+ string const file = doSubstitution(params, buffer,
+ file_template, false,
+ external_in_tmpdir, what);
+ string contents;
+
+ FileName const absfile(
+ support::makeAbsPath(file, m_buffer->temppath()));
+ if (support::isFileReadable(absfile))
+ contents = support::getFileContents(absfile);
+
+ string::size_type const pos = result.find("$$Contents(\"");
+ string::size_type const end = result.find("\")", pos);
+ result.replace(pos, end + 2, contents);
+ }
+
+ return result;
+}
+
+
+namespace {
+
+/** update the file represented by the template.
+ If \p external_in_tmpdir == true, then the generated file is
+ placed in the buffer's temporary directory.
+*/
+void updateExternal(InsetExternalParams const & params,
+ string const & format,
+ Buffer const & buffer,
+ ExportData & exportdata,
+ bool external_in_tmpdir,
+ bool dryrun)
+{
+ Template const * const et_ptr = getTemplatePtr(params);
+ if (!et_ptr)
+ return; // FAILURE
+ Template const & et = *et_ptr;
+
+ if (!et.automaticProduction)
+ return; // NOT_NEEDED
+
+ Template::Formats::const_iterator cit = et.formats.find(format);
+ if (cit == et.formats.end())
+ return; // FAILURE
+
+ Template::Format const & outputFormat = cit->second;
+ if (outputFormat.updateResult.empty())
+ return; // NOT_NEEDED
+
+ string from_format = et.inputFormat;
+ if (from_format.empty())
+ return; // NOT_NEEDED
+
+ if (from_format == "*") {
+ if (params.filename.empty())
+ return; // NOT_NEEDED
+
+ // Try and ascertain the file format from its contents.
+ from_format = formats.getFormatFromFile(params.filename);
+ if (from_format.empty())
+ return; // FAILURE
+
+ }
+
+ string const to_format = outputFormat.updateFormat;
+ if (to_format.empty())
+ return; // NOT_NEEDED
+
+ // The master buffer. This is useful when there are multiple levels
+ // of include files
+ Buffer const * m_buffer = buffer.getMasterBuffer();
+
+ // We copy the source file to the temp dir and do the conversion
+ // there if necessary
+ FileName const temp_file(
+ support::makeAbsPath(params.filename.mangledFilename(),
+ m_buffer->temppath()));
+ if (!params.filename.empty() && !is_directory(params.filename.toFilesystemEncoding())) {
+ unsigned long const from_checksum = support::sum(params.filename);
+ unsigned long const temp_checksum = support::sum(temp_file);
+
+ if (from_checksum != temp_checksum) {
+ Mover const & mover = getMover(from_format);
+ if (!mover.copy(params.filename, temp_file)) {
+ LYXERR(Debug::EXTERNAL)
+ << "external::updateExternal. "
+ << "Unable to copy "
+ << params.filename << " to " << temp_file << endl;
+ return; // FAILURE
+ }
+ }
+ }
+
+ // the generated file (always in the temp dir)
+ string const to_file = doSubstitution(params, buffer,
+ outputFormat.updateResult,
+ false, true);
+ FileName const abs_to_file(
+ support::makeAbsPath(to_file, m_buffer->temppath()));
+
+ if (!dryrun) {
+ // Record the referenced files for the exporter.
+ // The exporter will copy them to the export dir.
+ typedef Template::Format::FileMap FileMap;
+ FileMap::const_iterator rit = outputFormat.referencedFiles.begin();
+ FileMap::const_iterator rend = outputFormat.referencedFiles.end();
+ for (; rit != rend; ++rit) {
+ vector<string>::const_iterator fit = rit->second.begin();
+ vector<string>::const_iterator fend = rit->second.end();
+ for (; fit != fend; ++fit) {
+ FileName const source(support::makeAbsPath(
+ doSubstitution(params, buffer, *fit,
+ false, true),
+ m_buffer->temppath()));
+ // The path of the referenced file is never the
+ // temp path, but the filename may be the mangled
+ // or the real name. Therefore we substitute the
+ // paths and names separately.
+ string file = support::subst(*fit, "$$FName",
+ "$$FPath$$Basename$$Extension");
+ file = doSubstitution(params, buffer, file, false, false,
+ PATHS);
+ file = doSubstitution(params, buffer, file,
+ false, external_in_tmpdir,
+ ALL_BUT_PATHS);
+ // if file is a relative name, it is interpreted
+ // relative to the master document.
+ exportdata.addExternalFile(rit->first, source, file);
+ }
+ }
+ }
+
+ // Do we need to perform the conversion?
+ // Yes if to_file does not exist or if from_file is newer than to_file
+ if (support::compare_timestamps(temp_file, abs_to_file) < 0)
+ return; // SUCCESS
+
+ // FIXME (Abdel 12/08/06): Is there a need to show these errors?
+ ErrorList el;
+ bool const success =
+ theConverters().convert(&buffer, temp_file, abs_to_file,
+ params.filename, from_format, to_format, el,
+ Converters::try_default | Converters::try_cache);
+
+ if (!success)
+ LYXERR(Debug::EXTERNAL)
+ << "external::updateExternal. "
+ << "Unable to convert from "
+ << from_format << " to " << to_format << endl;
+
+ // return success
+}
+
+
+string const substituteCommands(InsetExternalParams const & params,
+ string const & input, string const & format);
+
+string const substituteOptions(InsetExternalParams const & params,
+ string const & input, string const & format);
+
+} // namespace anon
+
+
+int writeExternal(InsetExternalParams const & params,
+ string const & format,
+ Buffer const & buffer, odocstream & os,
+ ExportData & exportdata,
+ bool external_in_tmpdir,
+ bool dryrun)
+{
+ Template const * const et_ptr = getTemplatePtr(params);
+ if (!et_ptr)
+ return 0;
+ Template const & et = *et_ptr;
+
+ Template::Formats::const_iterator cit = et.formats.find(format);
+ if (cit == et.formats.end()) {
+ LYXERR(Debug::EXTERNAL)
+ << "External template format '" << format
+ << "' not specified in template "
+ << params.templatename() << endl;
+ return 0;
+ }
+
+ if (!dryrun || support::contains(cit->second.product, "$$Contents"))
+ updateExternal(params, format, buffer, exportdata,
+ external_in_tmpdir, dryrun);
+
+ bool const use_latex_path = format == "LaTeX";
+ string str = doSubstitution(params, buffer, cit->second.product,
+ use_latex_path, external_in_tmpdir);
+ str = substituteCommands(params, str, format);
+ str = substituteOptions(params, str, format);
+ // FIXME UNICODE
+ os << from_utf8(str);
+ return int(lyx::count(str.begin(), str.end(),'\n'));
+}
+
+namespace {
+
+// Empty template, specialised below.
+template <typename TransformType>
+string const substituteIt(string const &,
+ TransformID,
+ string const &,
+ Template::Format const &,
+ InsetExternalParams const &);
+
+
+template <>
+string const substituteIt<TransformCommand>(string const & input,
+ TransformID id,
+ string const & /* formatname */,
+ Template::Format const & format,
+ InsetExternalParams const & params)
+{
+ typedef std::map<TransformID, TransformStore> Transformers;
+ Transformers::const_iterator it = format.command_transformers.find(id);
+ if (it == format.command_transformers.end())
+ return input;
+
+ TransformStore const & store = it->second;
+
+ TransformCommand::ptr_type ptr;
+ if (id == Rotate)
+ ptr = store.getCommandTransformer(params.rotationdata);
+ else if (id == Resize)
+ ptr = store.getCommandTransformer(params.resizedata);
+
+ if (!ptr.get())
+ return input;
+
+ string result =
+ support::subst(input, ptr->front_placeholder(), ptr->front());
+ return support::subst(result, ptr->back_placeholder(), ptr->back());
+}
+
+
+template <>
+string const substituteIt<TransformOption>(string const & input,
+ TransformID id,
+ string const & fname,
+ Template::Format const & format,
+ InsetExternalParams const & params)
+{
+ typedef std::map<TransformID, TransformStore> Transformers;
+ Transformers::const_iterator it = format.option_transformers.find(id);
+ if (it == format.option_transformers.end())
+ return input;
+
+ TransformStore const & store = it->second;
+
+ TransformOption::ptr_type ptr;
+ switch (id) {
+ case Clip:
+ ptr = store.getOptionTransformer(params.clipdata);
+ break;
+ case Extra:
+ ptr = store.getOptionTransformer(params.extradata.get(fname));
+ break;
+ case Rotate:
+ ptr = store.getOptionTransformer(params.rotationdata);
+ break;
+ case Resize:
+ ptr = store.getOptionTransformer(params.resizedata);
+ break;
+ }
+
+ if (!ptr.get())
+ return input;
+
+ return support::subst(input, ptr->placeholder(), ptr->option());
+}
+
+
+template <typename TransformerType>
+string const transformIt(InsetExternalParams const & params,
+ string const & s, string const & formatname)
+{
+ Template const * const et = getTemplatePtr(params);
+ if (!et || et->transformIds.empty())
+ return s;
+
+ Template::Formats::const_iterator fit = et->formats.find(formatname);
+ if (fit == et->formats.end())
+ return s;
+
+ string result = s;
+ Template::Format const & format = fit->second;
+
+ typedef vector<TransformID> TransformsIDs;
+ TransformsIDs::const_iterator it = et->transformIds.begin();
+ TransformsIDs::const_iterator end = et->transformIds.end();
+ for (; it != end; ++it) {
+ result = substituteIt<TransformerType>(result, *it, formatname,
+ format, params);
+ }
+ return result;
+}
+
+
+string const substituteCommands(InsetExternalParams const & params,
+ string const & input, string const & format)
+{
+ return transformIt<TransformCommand>(params, input, format);
+}
+
+
+string const substituteOption(InsetExternalParams const & params,
+ string const & input, string const & format)
+{
+ string opt = transformIt<TransformOption>(params, input, format);
+
+ if (format == "LaTeX" || format == "PDFLaTeX")
+ return sanitizeLatexOption(opt);
+ if (format == "DocBook")
+ return sanitizeDocBookOption(opt);
+ return opt;
+}
+
+
+string const substituteOptions(InsetExternalParams const & params,
+ string const & input, string const & format)
+{
+ string output = input;
+
+ Template const * const et = getTemplatePtr(params);
+ if (!et || et->transformIds.empty())
+ return output;
+
+ Template::Formats::const_iterator fit = et->formats.find(format);
+ if (fit == et->formats.end() || fit->second.options.empty())
+ return output;
+
+ typedef vector<Template::Option> Options;
+ Options const & options = fit->second.options;
+ Options::const_iterator it = options.begin();
+ Options::const_iterator end = options.end();
+ for (; it != end; ++it) {
+ string const opt = substituteOption(params, it->option, format);
+ string const placeholder = "$$" + it->name;
+ output = support::subst(output, placeholder, opt);
+ }
+
+ return output;
+}
+
+} // namespace anon
+
+} // namespace external
+
+} // namespace lyx
+++ /dev/null
-/**
- * \file ExternalTemplate.C
- * This file is part of LyX, the document processor.
- * Licence details can be found in the file COPYING.
- *
- * \author Asger Alstrup Nielsen
- * \author Angus Leeming
- *
- * Full author contact details are available in file CREDITS.
- */
-
-#include <config.h>
-
-#include "ExternalTemplate.h"
-
-#include "debug.h"
-#include "LyXLex.h"
-
-#include "support/filetools.h"
-#include "support/lstrings.h"
-#include "support/Package.h"
-#include "support/Path.h"
-
-using std::endl;
-using std::for_each;
-using std::string;
-using std::ostream;
-using std::vector;
-
-namespace lyx {
-namespace external {
-
-
-typedef Translator<TransformID, string> TransformIDTranslator;
-
-static TransformIDTranslator const initIDTranslator()
-{
- TransformIDTranslator translator(TransformID(-1), "");
- translator.addPair(Rotate, "Rotate");
- translator.addPair(Resize, "Resize");
- translator.addPair(Clip, "Clip");
- translator.addPair(Extra, "Extra");
- return translator;
-}
-
-static TransformIDTranslator const & transformIDTranslator()
-{
- static TransformIDTranslator const translator = initIDTranslator();
- return translator;
-}
-
-// We have to have dummy default commands for security reasons!
-Template::Template()
- : inputFormat("*")
-{}
-
-
-Template::Format::Format()
-{}
-
-
-TemplateManager::TemplateManager()
-{
- readTemplates(support::package().user_support());
- if (lyxerr.debugging(Debug::EXTERNAL)) {
- dumpPreambleDefs(lyxerr);
- lyxerr << '\n';
- dumpTemplates(lyxerr);
- }
-}
-
-
-class dumpPreambleDef {
-public:
- typedef TemplateManager::PreambleDefs::value_type value_type;
-
- dumpPreambleDef(ostream & o) : ost(o) {}
-
- void operator()(value_type const & vt) {
- ost << "PreambleDef " << vt.first << '\n'
- << vt.second
- << "PreambleDefEnd" << endl;
- }
-
-private:
- ostream & ost;
-};
-
-
-class dumpTemplate {
-public:
- typedef TemplateManager::Templates::value_type value_type;
-
- dumpTemplate(ostream & o) : ost(o) {}
-
- void operator()(value_type const & vt) {
- Template const & et = vt.second;
-
- ost << "Template " << et.lyxName << '\n'
- << "\tGuiName " << et.guiName << '\n'
- << "\tHelpText\n"
- << et.helpText
- << "\tHelpTextEnd\n"
- << "\tInputFormat " << et.inputFormat << '\n'
- << "\tFileFilter " << et.fileRegExp << '\n'
- << "\tAutomaticProduction " << et.automaticProduction << '\n';
-
- typedef vector<TransformID> IDs;
- IDs::const_iterator it = et.transformIds.begin();
- IDs::const_iterator end = et.transformIds.end();
- for (; it != end; ++it) {
- ost << "\tTransform "
- << transformIDTranslator().find(*it) << '\n';
- }
-
- et.dumpFormats(ost);
- ost << "TemplateEnd" << endl;
-
- }
-
-private:
- ostream & ost;
-};
-
-class dumpFormat {
-public:
- typedef Template::Formats::value_type value_type;
-
- dumpFormat(ostream & o) : ost(o) {}
-
- void operator()(value_type const & vt) const {
- Template::Format const & ft = vt.second;
- ost << "\tFormat " << vt.first << '\n'
- << "\t\tProduct " << ft.product << '\n'
- << "\t\tUpdateFormat " << ft.updateFormat << '\n'
- << "\t\tUpdateResult " << ft.updateResult << '\n';
-
- vector<string>::const_iterator qit = ft.requirements.begin();
- vector<string>::const_iterator qend = ft.requirements.end();
- for (; qit != qend; ++qit) {
- lyxerr << "req:" << *qit << std::endl;
- ost << "\t\tRequirement " << *qit << '\n';
- }
-
- typedef vector<Template::Option> Options;
- Options::const_iterator oit = ft.options.begin();
- Options::const_iterator oend = ft.options.end();
- for (; oit != oend; ++oit) {
- ost << "\t\tOption "
- << oit->name
- << ": "
- << oit->option
- << '\n';
- }
-
- vector<string>::const_iterator pit = ft.preambleNames.begin();
- vector<string>::const_iterator pend = ft.preambleNames.end();
- for (; pit != pend; ++pit) {
- ost << "\t\tPreamble " << *pit << '\n';
- }
-
- typedef Template::Format::FileMap FileMap;
- FileMap::const_iterator rit = ft.referencedFiles.begin();
- FileMap::const_iterator rend = ft.referencedFiles.end();
- for (; rit != rend; ++rit) {
- vector<string>::const_iterator fit = rit->second.begin();
- vector<string>::const_iterator fend = rit->second.end();
- for (; fit != fend; ++fit) {
- ost << "\t\tReferencedFile " << rit->first
- << " \"" << *fit << "\"\n";
- }
- }
-
- ost << "\tFormatEnd\n";
- }
-private:
- ostream & ost;
-};
-
-
-void Template::dumpFormats(ostream & os) const
-{
- for_each(formats.begin(), formats.end(), dumpFormat(os));
-}
-
-
-void TemplateManager::dumpPreambleDefs(ostream & os) const
-{
- for_each(preambledefs.begin(), preambledefs.end(), dumpPreambleDef(os));
-}
-
-
-void TemplateManager::dumpTemplates(ostream & os) const
-{
- for_each(templates.begin(), templates.end(), dumpTemplate(os));
-}
-
-
-TemplateManager & TemplateManager::get()
-{
- static TemplateManager externalTemplateManager;
- return externalTemplateManager;
-}
-
-
-TemplateManager::Templates const &
-TemplateManager::getTemplates() const
-{
- return templates;
-}
-
-
-Template const *
-TemplateManager::getTemplateByName(string const & name) const
-{
- Templates::const_iterator it = templates.find(name);
- return (it == templates.end()) ? 0 : &it->second;
-}
-
-
-string const
-TemplateManager::getPreambleDefByName(string const & name) const
-{
- string const trimmed_name = support::trim(name);
- if (trimmed_name.empty())
- return string();
-
- PreambleDefs::const_iterator it = preambledefs.find(trimmed_name);
- if (it == preambledefs.end())
- return string();
-
- return it->second;
-}
-
-
-void TemplateManager::readTemplates(support::FileName const & path)
-{
- support::Path p(path);
-
- enum TemplateTags {
- TM_PREAMBLEDEF = 1,
- TM_PREAMBLEDEF_END,
- TM_TEMPLATE,
- TM_TEMPLATE_END
- };
-
- keyword_item templatetags[] = {
- { "preambledef", TM_PREAMBLEDEF },
- { "preambledefend", TM_PREAMBLEDEF_END },
- { "template", TM_TEMPLATE },
- { "templateend", TM_TEMPLATE_END }
- };
-
- LyXLex lex(templatetags, TM_TEMPLATE_END);
-
- support::FileName const filename = support::libFileSearch("", "external_templates");
- if (filename.empty() || !lex.setFile(filename)) {
- lex.printError("external::TemplateManager::readTemplates: "
- "No template file");
- return;
- }
-
- char const * const preamble_end_tag =
- templatetags[TM_PREAMBLEDEF_END-1].tag;
-
- while (lex.isOK()) {
- switch (lex.lex()) {
- case TM_PREAMBLEDEF: {
- lex.next();
- string const name = lex.getString();
- preambledefs[name] = lex.getLongString(preamble_end_tag);
- }
- break;
-
- case TM_TEMPLATE: {
- lex.next();
- string const name = lex.getString();
- Template & tmp = templates[name];
- tmp.lyxName = name;
- tmp.readTemplate(lex);
- }
- break;
-
- case TM_TEMPLATE_END:
- lex.printError("Warning: End outside Template.");
- break;
-
- case TM_PREAMBLEDEF_END:
- lex.printError("Warning: End outside PreambleDef.");
- break;
- }
- }
-}
-
-
-namespace {
-
-void add(vector<TransformID> & ids, string const & name)
-{
- TransformID id = transformIDTranslator().find(name);
- if (int(id) == -1) {
- lyxerr << "external::Template::readTemplate\n"
- << "Transform " << name << " is not recognized"
- << std::endl;
- } else {
- ids.push_back(id);
- }
-}
-
-} // namespace anon
-
-
-void Template::readTemplate(LyXLex & lex)
-{
- enum TemplateOptionTags {
- TO_GUINAME = 1,
- TO_HELPTEXT,
- TO_INPUTFORMAT,
- TO_FILTER,
- TO_AUTOMATIC,
- TO_TRANSFORM,
- TO_FORMAT,
- TO_END
- };
-
- keyword_item templateoptiontags[] = {
- { "automaticproduction", TO_AUTOMATIC },
- { "filefilter", TO_FILTER },
- { "format", TO_FORMAT },
- { "guiname", TO_GUINAME },
- { "helptext", TO_HELPTEXT },
- { "inputformat", TO_INPUTFORMAT },
- { "templateend", TO_END },
- { "transform", TO_TRANSFORM }
- };
-
- pushpophelper pph(lex, templateoptiontags, TO_END);
-
- while (lex.isOK()) {
- switch (lex.lex()) {
- case TO_GUINAME:
- lex.next(true);
- guiName = lex.getString();
- break;
-
- case TO_HELPTEXT:
- helpText = lex.getLongString("HelpTextEnd");
- break;
-
- case TO_INPUTFORMAT:
- lex.next(true);
- inputFormat = lex.getString();
- break;
-
- case TO_FILTER:
- lex.next(true);
- fileRegExp = lex.getString();
- break;
-
- case TO_AUTOMATIC:
- lex.next();
- automaticProduction = lex.getBool();
- break;
-
- case TO_TRANSFORM:
- lex.next(true);
- add(transformIds, lex.getString());
- break;
-
- case TO_FORMAT:
- lex.next(true);
- formats[lex.getString()].readFormat(lex);
- break;
-
- case TO_END:
- return;
-
- default:
- lex.printError("external::Template::readTemplate: "
- "Wrong tag: $$Token");
- BOOST_ASSERT(false);
- break;
- }
- }
-}
-
-
-namespace {
-
-void transform_not_found(std::ostream & os, string const & transform)
-{
- os << "external::Format::readFormat. Transformation \""
- << transform << "\" is unrecognized." << std::endl;
-}
-
-
-void transform_class_not_found(std::ostream & os, string const & tclass)
-{
- os << "external::Format::readFormat. Transformation class \""
- << tclass << "\" is unrecognized." << std::endl;
-}
-
-
-void setCommandFactory(Template::Format & format, string const & transform,
- string const & transformer_class)
-{
- bool class_found = false;
- if (transform == "Resize" && transformer_class == "ResizeLatexCommand") {
- class_found = true;
- ResizeCommandFactory factory = ResizeLatexCommand::factory;
- format.command_transformers[Resize] =
- TransformStore(Resize, factory);
-
- } else if (transform == "Rotate" &&
- transformer_class == "RotationLatexCommand") {
- class_found = true;
- RotationCommandFactory factory = RotationLatexCommand::factory;
- format.command_transformers[Rotate] =
- TransformStore(Rotate, factory);
-
- } else
- transform_not_found(lyxerr, transform);
-
- if (!class_found)
- transform_class_not_found(lyxerr, transformer_class);
-}
-
-
-void setOptionFactory(Template::Format & format, string const & transform,
- string const & transformer_class)
-{
- bool class_found = false;
- if (transform == "Clip" && transformer_class == "ClipLatexOption") {
- class_found = true;
- ClipOptionFactory factory = ClipLatexOption::factory;
- format.option_transformers[Clip] =
- TransformStore(Clip, factory);
-
- } else if (transform == "Extra" && transformer_class == "ExtraOption") {
- class_found = true;
- ExtraOptionFactory factory = ExtraOption::factory;
- format.option_transformers[Extra] =
- TransformStore(Extra, factory);
-
- } else if (transform == "Resize" &&
- transformer_class == "ResizeLatexOption") {
- class_found = true;
- ResizeOptionFactory factory = ResizeLatexOption::factory;
- format.option_transformers[Resize] =
- TransformStore(Resize, factory);
-
- } else if (transform == "Rotate" &&
- transformer_class == "RotationLatexOption") {
- class_found = true;
- RotationOptionFactory factory = RotationLatexOption::factory;
- format.option_transformers[Rotate] =
- TransformStore(Rotate, factory);
-
- } else
- transform_not_found(lyxerr, transform);
-
- if (!class_found)
- transform_class_not_found(lyxerr, transformer_class);
-}
-
-} // namespace anon
-
-
-void Template::Format::readFormat(LyXLex & lex)
-{
- enum FormatTags {
- FO_PRODUCT = 1,
- FO_UPDATEFORMAT,
- FO_UPDATERESULT,
- FO_REQUIREMENT,
- FO_OPTION,
- FO_PREAMBLE,
- FO_TRANSFORMCOMMAND,
- FO_TRANSFORMOPTION,
- FO_REFERENCEDFILE,
- FO_END
- };
-
- keyword_item formattags[] = {
- { "formatend", FO_END },
- { "option", FO_OPTION },
- { "preamble", FO_PREAMBLE },
- { "product", FO_PRODUCT },
- { "referencedfile", FO_REFERENCEDFILE },
- { "requirement", FO_REQUIREMENT },
- { "transformcommand", FO_TRANSFORMCOMMAND },
- { "transformoption", FO_TRANSFORMOPTION },
- { "updateformat", FO_UPDATEFORMAT },
- { "updateresult", FO_UPDATERESULT }
- };
-
- pushpophelper pph(lex, formattags, FO_END);
-
- while (lex.isOK()) {
- switch (lex.lex()) {
- case FO_PRODUCT:
- lex.next(true);
- product = lex.getString();
- break;
-
- case FO_UPDATEFORMAT:
- lex.next(true);
- updateFormat = lex.getString();
- break;
-
- case FO_UPDATERESULT:
- lex.next(true);
- updateResult = lex.getString();
- break;
-
- case FO_REQUIREMENT:
- lex.next(true);
- requirements.push_back(lex.getString());
- break;
-
- case FO_PREAMBLE:
- lex.next(true);
- preambleNames.push_back(lex.getString());
- break;
-
- case FO_TRANSFORMCOMMAND: {
- lex.next(true);
- string const name = lex.getString();
- lex.next(true);
- setCommandFactory(*this, name, lex.getString());
- break;
- }
-
- case FO_TRANSFORMOPTION: {
- lex.next(true);
- string const name = lex.getString();
- lex.next(true);
- setOptionFactory(*this, name, lex.getString());
- break;
- }
-
- case FO_OPTION: {
- lex.next(true);
- string const name = lex.getString();
- lex.next(true);
- string const opt = lex.getString();
- options.push_back(Option(name, opt));
- break;
- }
-
- case FO_REFERENCEDFILE: {
- lex.next(true);
- string const format = lex.getString();
- lex.next(true);
- string const file = lex.getString();
- referencedFiles[format].push_back(file);
- break;
- }
-
- case FO_END:
- return;
- }
- }
-}
-
-} // namespace external
-} // namespace lyx
--- /dev/null
+/**
+ * \file ExternalTemplate.cpp
+ * This file is part of LyX, the document processor.
+ * Licence details can be found in the file COPYING.
+ *
+ * \author Asger Alstrup Nielsen
+ * \author Angus Leeming
+ *
+ * Full author contact details are available in file CREDITS.
+ */
+
+#include <config.h>
+
+#include "ExternalTemplate.h"
+
+#include "debug.h"
+#include "LyXLex.h"
+
+#include "support/filetools.h"
+#include "support/lstrings.h"
+#include "support/Package.h"
+#include "support/Path.h"
+
+using std::endl;
+using std::for_each;
+using std::string;
+using std::ostream;
+using std::vector;
+
+namespace lyx {
+namespace external {
+
+
+typedef Translator<TransformID, string> TransformIDTranslator;
+
+static TransformIDTranslator const initIDTranslator()
+{
+ TransformIDTranslator translator(TransformID(-1), "");
+ translator.addPair(Rotate, "Rotate");
+ translator.addPair(Resize, "Resize");
+ translator.addPair(Clip, "Clip");
+ translator.addPair(Extra, "Extra");
+ return translator;
+}
+
+static TransformIDTranslator const & transformIDTranslator()
+{
+ static TransformIDTranslator const translator = initIDTranslator();
+ return translator;
+}
+
+// We have to have dummy default commands for security reasons!
+Template::Template()
+ : inputFormat("*")
+{}
+
+
+Template::Format::Format()
+{}
+
+
+TemplateManager::TemplateManager()
+{
+ readTemplates(support::package().user_support());
+ if (lyxerr.debugging(Debug::EXTERNAL)) {
+ dumpPreambleDefs(lyxerr);
+ lyxerr << '\n';
+ dumpTemplates(lyxerr);
+ }
+}
+
+
+class dumpPreambleDef {
+public:
+ typedef TemplateManager::PreambleDefs::value_type value_type;
+
+ dumpPreambleDef(ostream & o) : ost(o) {}
+
+ void operator()(value_type const & vt) {
+ ost << "PreambleDef " << vt.first << '\n'
+ << vt.second
+ << "PreambleDefEnd" << endl;
+ }
+
+private:
+ ostream & ost;
+};
+
+
+class dumpTemplate {
+public:
+ typedef TemplateManager::Templates::value_type value_type;
+
+ dumpTemplate(ostream & o) : ost(o) {}
+
+ void operator()(value_type const & vt) {
+ Template const & et = vt.second;
+
+ ost << "Template " << et.lyxName << '\n'
+ << "\tGuiName " << et.guiName << '\n'
+ << "\tHelpText\n"
+ << et.helpText
+ << "\tHelpTextEnd\n"
+ << "\tInputFormat " << et.inputFormat << '\n'
+ << "\tFileFilter " << et.fileRegExp << '\n'
+ << "\tAutomaticProduction " << et.automaticProduction << '\n';
+
+ typedef vector<TransformID> IDs;
+ IDs::const_iterator it = et.transformIds.begin();
+ IDs::const_iterator end = et.transformIds.end();
+ for (; it != end; ++it) {
+ ost << "\tTransform "
+ << transformIDTranslator().find(*it) << '\n';
+ }
+
+ et.dumpFormats(ost);
+ ost << "TemplateEnd" << endl;
+
+ }
+
+private:
+ ostream & ost;
+};
+
+class dumpFormat {
+public:
+ typedef Template::Formats::value_type value_type;
+
+ dumpFormat(ostream & o) : ost(o) {}
+
+ void operator()(value_type const & vt) const {
+ Template::Format const & ft = vt.second;
+ ost << "\tFormat " << vt.first << '\n'
+ << "\t\tProduct " << ft.product << '\n'
+ << "\t\tUpdateFormat " << ft.updateFormat << '\n'
+ << "\t\tUpdateResult " << ft.updateResult << '\n';
+
+ vector<string>::const_iterator qit = ft.requirements.begin();
+ vector<string>::const_iterator qend = ft.requirements.end();
+ for (; qit != qend; ++qit) {
+ lyxerr << "req:" << *qit << std::endl;
+ ost << "\t\tRequirement " << *qit << '\n';
+ }
+
+ typedef vector<Template::Option> Options;
+ Options::const_iterator oit = ft.options.begin();
+ Options::const_iterator oend = ft.options.end();
+ for (; oit != oend; ++oit) {
+ ost << "\t\tOption "
+ << oit->name
+ << ": "
+ << oit->option
+ << '\n';
+ }
+
+ vector<string>::const_iterator pit = ft.preambleNames.begin();
+ vector<string>::const_iterator pend = ft.preambleNames.end();
+ for (; pit != pend; ++pit) {
+ ost << "\t\tPreamble " << *pit << '\n';
+ }
+
+ typedef Template::Format::FileMap FileMap;
+ FileMap::const_iterator rit = ft.referencedFiles.begin();
+ FileMap::const_iterator rend = ft.referencedFiles.end();
+ for (; rit != rend; ++rit) {
+ vector<string>::const_iterator fit = rit->second.begin();
+ vector<string>::const_iterator fend = rit->second.end();
+ for (; fit != fend; ++fit) {
+ ost << "\t\tReferencedFile " << rit->first
+ << " \"" << *fit << "\"\n";
+ }
+ }
+
+ ost << "\tFormatEnd\n";
+ }
+private:
+ ostream & ost;
+};
+
+
+void Template::dumpFormats(ostream & os) const
+{
+ for_each(formats.begin(), formats.end(), dumpFormat(os));
+}
+
+
+void TemplateManager::dumpPreambleDefs(ostream & os) const
+{
+ for_each(preambledefs.begin(), preambledefs.end(), dumpPreambleDef(os));
+}
+
+
+void TemplateManager::dumpTemplates(ostream & os) const
+{
+ for_each(templates.begin(), templates.end(), dumpTemplate(os));
+}
+
+
+TemplateManager & TemplateManager::get()
+{
+ static TemplateManager externalTemplateManager;
+ return externalTemplateManager;
+}
+
+
+TemplateManager::Templates const &
+TemplateManager::getTemplates() const
+{
+ return templates;
+}
+
+
+Template const *
+TemplateManager::getTemplateByName(string const & name) const
+{
+ Templates::const_iterator it = templates.find(name);
+ return (it == templates.end()) ? 0 : &it->second;
+}
+
+
+string const
+TemplateManager::getPreambleDefByName(string const & name) const
+{
+ string const trimmed_name = support::trim(name);
+ if (trimmed_name.empty())
+ return string();
+
+ PreambleDefs::const_iterator it = preambledefs.find(trimmed_name);
+ if (it == preambledefs.end())
+ return string();
+
+ return it->second;
+}
+
+
+void TemplateManager::readTemplates(support::FileName const & path)
+{
+ support::Path p(path);
+
+ enum TemplateTags {
+ TM_PREAMBLEDEF = 1,
+ TM_PREAMBLEDEF_END,
+ TM_TEMPLATE,
+ TM_TEMPLATE_END
+ };
+
+ keyword_item templatetags[] = {
+ { "preambledef", TM_PREAMBLEDEF },
+ { "preambledefend", TM_PREAMBLEDEF_END },
+ { "template", TM_TEMPLATE },
+ { "templateend", TM_TEMPLATE_END }
+ };
+
+ LyXLex lex(templatetags, TM_TEMPLATE_END);
+
+ support::FileName const filename = support::libFileSearch("", "external_templates");
+ if (filename.empty() || !lex.setFile(filename)) {
+ lex.printError("external::TemplateManager::readTemplates: "
+ "No template file");
+ return;
+ }
+
+ char const * const preamble_end_tag =
+ templatetags[TM_PREAMBLEDEF_END-1].tag;
+
+ while (lex.isOK()) {
+ switch (lex.lex()) {
+ case TM_PREAMBLEDEF: {
+ lex.next();
+ string const name = lex.getString();
+ preambledefs[name] = lex.getLongString(preamble_end_tag);
+ }
+ break;
+
+ case TM_TEMPLATE: {
+ lex.next();
+ string const name = lex.getString();
+ Template & tmp = templates[name];
+ tmp.lyxName = name;
+ tmp.readTemplate(lex);
+ }
+ break;
+
+ case TM_TEMPLATE_END:
+ lex.printError("Warning: End outside Template.");
+ break;
+
+ case TM_PREAMBLEDEF_END:
+ lex.printError("Warning: End outside PreambleDef.");
+ break;
+ }
+ }
+}
+
+
+namespace {
+
+void add(vector<TransformID> & ids, string const & name)
+{
+ TransformID id = transformIDTranslator().find(name);
+ if (int(id) == -1) {
+ lyxerr << "external::Template::readTemplate\n"
+ << "Transform " << name << " is not recognized"
+ << std::endl;
+ } else {
+ ids.push_back(id);
+ }
+}
+
+} // namespace anon
+
+
+void Template::readTemplate(LyXLex & lex)
+{
+ enum TemplateOptionTags {
+ TO_GUINAME = 1,
+ TO_HELPTEXT,
+ TO_INPUTFORMAT,
+ TO_FILTER,
+ TO_AUTOMATIC,
+ TO_TRANSFORM,
+ TO_FORMAT,
+ TO_END
+ };
+
+ keyword_item templateoptiontags[] = {
+ { "automaticproduction", TO_AUTOMATIC },
+ { "filefilter", TO_FILTER },
+ { "format", TO_FORMAT },
+ { "guiname", TO_GUINAME },
+ { "helptext", TO_HELPTEXT },
+ { "inputformat", TO_INPUTFORMAT },
+ { "templateend", TO_END },
+ { "transform", TO_TRANSFORM }
+ };
+
+ pushpophelper pph(lex, templateoptiontags, TO_END);
+
+ while (lex.isOK()) {
+ switch (lex.lex()) {
+ case TO_GUINAME:
+ lex.next(true);
+ guiName = lex.getString();
+ break;
+
+ case TO_HELPTEXT:
+ helpText = lex.getLongString("HelpTextEnd");
+ break;
+
+ case TO_INPUTFORMAT:
+ lex.next(true);
+ inputFormat = lex.getString();
+ break;
+
+ case TO_FILTER:
+ lex.next(true);
+ fileRegExp = lex.getString();
+ break;
+
+ case TO_AUTOMATIC:
+ lex.next();
+ automaticProduction = lex.getBool();
+ break;
+
+ case TO_TRANSFORM:
+ lex.next(true);
+ add(transformIds, lex.getString());
+ break;
+
+ case TO_FORMAT:
+ lex.next(true);
+ formats[lex.getString()].readFormat(lex);
+ break;
+
+ case TO_END:
+ return;
+
+ default:
+ lex.printError("external::Template::readTemplate: "
+ "Wrong tag: $$Token");
+ BOOST_ASSERT(false);
+ break;
+ }
+ }
+}
+
+
+namespace {
+
+void transform_not_found(std::ostream & os, string const & transform)
+{
+ os << "external::Format::readFormat. Transformation \""
+ << transform << "\" is unrecognized." << std::endl;
+}
+
+
+void transform_class_not_found(std::ostream & os, string const & tclass)
+{
+ os << "external::Format::readFormat. Transformation class \""
+ << tclass << "\" is unrecognized." << std::endl;
+}
+
+
+void setCommandFactory(Template::Format & format, string const & transform,
+ string const & transformer_class)
+{
+ bool class_found = false;
+ if (transform == "Resize" && transformer_class == "ResizeLatexCommand") {
+ class_found = true;
+ ResizeCommandFactory factory = ResizeLatexCommand::factory;
+ format.command_transformers[Resize] =
+ TransformStore(Resize, factory);
+
+ } else if (transform == "Rotate" &&
+ transformer_class == "RotationLatexCommand") {
+ class_found = true;
+ RotationCommandFactory factory = RotationLatexCommand::factory;
+ format.command_transformers[Rotate] =
+ TransformStore(Rotate, factory);
+
+ } else
+ transform_not_found(lyxerr, transform);
+
+ if (!class_found)
+ transform_class_not_found(lyxerr, transformer_class);
+}
+
+
+void setOptionFactory(Template::Format & format, string const & transform,
+ string const & transformer_class)
+{
+ bool class_found = false;
+ if (transform == "Clip" && transformer_class == "ClipLatexOption") {
+ class_found = true;
+ ClipOptionFactory factory = ClipLatexOption::factory;
+ format.option_transformers[Clip] =
+ TransformStore(Clip, factory);
+
+ } else if (transform == "Extra" && transformer_class == "ExtraOption") {
+ class_found = true;
+ ExtraOptionFactory factory = ExtraOption::factory;
+ format.option_transformers[Extra] =
+ TransformStore(Extra, factory);
+
+ } else if (transform == "Resize" &&
+ transformer_class == "ResizeLatexOption") {
+ class_found = true;
+ ResizeOptionFactory factory = ResizeLatexOption::factory;
+ format.option_transformers[Resize] =
+ TransformStore(Resize, factory);
+
+ } else if (transform == "Rotate" &&
+ transformer_class == "RotationLatexOption") {
+ class_found = true;
+ RotationOptionFactory factory = RotationLatexOption::factory;
+ format.option_transformers[Rotate] =
+ TransformStore(Rotate, factory);
+
+ } else
+ transform_not_found(lyxerr, transform);
+
+ if (!class_found)
+ transform_class_not_found(lyxerr, transformer_class);
+}
+
+} // namespace anon
+
+
+void Template::Format::readFormat(LyXLex & lex)
+{
+ enum FormatTags {
+ FO_PRODUCT = 1,
+ FO_UPDATEFORMAT,
+ FO_UPDATERESULT,
+ FO_REQUIREMENT,
+ FO_OPTION,
+ FO_PREAMBLE,
+ FO_TRANSFORMCOMMAND,
+ FO_TRANSFORMOPTION,
+ FO_REFERENCEDFILE,
+ FO_END
+ };
+
+ keyword_item formattags[] = {
+ { "formatend", FO_END },
+ { "option", FO_OPTION },
+ { "preamble", FO_PREAMBLE },
+ { "product", FO_PRODUCT },
+ { "referencedfile", FO_REFERENCEDFILE },
+ { "requirement", FO_REQUIREMENT },
+ { "transformcommand", FO_TRANSFORMCOMMAND },
+ { "transformoption", FO_TRANSFORMOPTION },
+ { "updateformat", FO_UPDATEFORMAT },
+ { "updateresult", FO_UPDATERESULT }
+ };
+
+ pushpophelper pph(lex, formattags, FO_END);
+
+ while (lex.isOK()) {
+ switch (lex.lex()) {
+ case FO_PRODUCT:
+ lex.next(true);
+ product = lex.getString();
+ break;
+
+ case FO_UPDATEFORMAT:
+ lex.next(true);
+ updateFormat = lex.getString();
+ break;
+
+ case FO_UPDATERESULT:
+ lex.next(true);
+ updateResult = lex.getString();
+ break;
+
+ case FO_REQUIREMENT:
+ lex.next(true);
+ requirements.push_back(lex.getString());
+ break;
+
+ case FO_PREAMBLE:
+ lex.next(true);
+ preambleNames.push_back(lex.getString());
+ break;
+
+ case FO_TRANSFORMCOMMAND: {
+ lex.next(true);
+ string const name = lex.getString();
+ lex.next(true);
+ setCommandFactory(*this, name, lex.getString());
+ break;
+ }
+
+ case FO_TRANSFORMOPTION: {
+ lex.next(true);
+ string const name = lex.getString();
+ lex.next(true);
+ setOptionFactory(*this, name, lex.getString());
+ break;
+ }
+
+ case FO_OPTION: {
+ lex.next(true);
+ string const name = lex.getString();
+ lex.next(true);
+ string const opt = lex.getString();
+ options.push_back(Option(name, opt));
+ break;
+ }
+
+ case FO_REFERENCEDFILE: {
+ lex.next(true);
+ string const format = lex.getString();
+ lex.next(true);
+ string const file = lex.getString();
+ referencedFiles[format].push_back(file);
+ break;
+ }
+
+ case FO_END:
+ return;
+ }
+ }
+}
+
+} // namespace external
+} // namespace lyx
+++ /dev/null
-/**
- * \file ExternalTransforms.C
- * This file is part of LyX, the document processor.
- * Licence details can be found in the file COPYING.
- *
- * \author Angus Leeming
- *
- * Full author contact details are available in file CREDITS.
- */
-
-#include <config.h>
-
-#include "ExternalTransforms.h"
-
-#include "debug.h"
-
-#include "support/lstrings.h"
-#include "support/lyxlib.h" // float_equal
-#include "support/convert.h"
-#include "support/Translator.h"
-
-#include <boost/regex.hpp>
-
-#include <cmath> // std::abs
-#include <sstream>
-
-
-namespace lyx {
-namespace external {
-
-using support::float_equal;
-using std::string;
-
-
-string const ExtraData::get(string const & id) const
-{
- std::map<string, string>::const_iterator it = data_.find(id);
- return it == data_.end() ? string() : it->second;
-}
-
-
-void ExtraData::set(string const & id, string const & data)
-{
- data_[id] = data;
-}
-
-
-bool ResizeData::no_resize() const
-{
- return !usingScale() && width.zero() && height.zero();
-}
-
-
-bool ResizeData::usingScale() const
-{
- return (!scale.empty() && !float_equal(convert<double>(scale), 0.0, 0.05));
-}
-
-
-bool RotationData::no_rotation() const
-{
- return (angle.empty() || std::abs(convert<double>(angle)) < 0.1);
-}
-
-
-string const RotationData::adjAngle() const
-{
- // Ensure that angle lies in the range -360 < angle < 360
- double rotAngle = convert<double>(angle);
- if (std::abs(rotAngle) > 360.0) {
- rotAngle -= 360.0 * floor(rotAngle / 360.0);
- return convert<string>(rotAngle);
- }
- return angle;
-}
-
-
-namespace {
-
-typedef Translator<RotationData::OriginType, string> OriginTranslator;
-OriginTranslator const & originTranslator();
-
-} // namespace anon
-
-
-void RotationData::origin(string const & o)
-{
- origin_ = originTranslator().find(o);
-}
-
-
-string const RotationData::originString() const
-{
- return originTranslator().find(origin_);
-}
-
-
-string const ResizeLatexCommand::front_impl() const
-{
- if (data.no_resize())
- return string();
-
- std::ostringstream os;
- if (data.usingScale()) {
- double const scl = convert<double>(data.scale) / 100.0;
- os << "\\scalebox{" << scl << "}[" << scl << "]{";
- } else {
- string width = "!";
- string height = "!";
- if (data.keepAspectRatio) {
- if (data.width.inPixels(10) > data.height.inPixels(10))
- width = data.width.asLatexString();
- else
- height = data.height.asLatexString();
- } else {
- if (!data.width.zero())
- width = data.width.asLatexString();
- if (!data.height.zero())
- height = data.height.asLatexString();
- }
-
- os << "\\resizebox{"
- << width << "}{"
- << height << "}{";
- }
- return os.str();
-}
-
-
-string const ResizeLatexCommand::back_impl() const
-{
- if (data.no_resize())
- return string();
-
- return "}";
-}
-
-
-namespace {
-
-std::ostream & operator<<(std::ostream & os, RotationData::OriginType type)
-{
- switch (type) {
- case RotationData::DEFAULT:
- case RotationData::CENTER:
- break;
- case RotationData::TOPLEFT:
- case RotationData::TOPCENTER:
- case RotationData::TOPRIGHT:
- os << 't';
- break;
- case RotationData::BOTTOMLEFT:
- case RotationData::BOTTOMCENTER:
- case RotationData::BOTTOMRIGHT:
- os << 'b';
- break;
- case RotationData::BASELINELEFT:
- case RotationData::BASELINECENTER:
- case RotationData::BASELINERIGHT:
- os << 'B';
- break;
- }
-
- switch (type) {
- case RotationData::DEFAULT:
- break;
- case RotationData::TOPLEFT:
- case RotationData::BOTTOMLEFT:
- case RotationData::BASELINELEFT:
- os << 'l';
- break;
- case RotationData::CENTER:
- case RotationData::TOPCENTER:
- case RotationData::BOTTOMCENTER:
- case RotationData::BASELINECENTER:
- os << 'c';
- break;
- case RotationData::TOPRIGHT:
- case RotationData::BOTTOMRIGHT:
- case RotationData::BASELINERIGHT:
- os << 'r';
- break;
- }
-
- return os;
-}
-
-} // namespace anon
-
-
-string const RotationLatexCommand::front_impl() const
-{
- if (data.no_rotation())
- return string();
-
- std::ostringstream os;
- os << "\\rotatebox";
-
- if (data.origin() != RotationData::DEFAULT)
- os << "[origin=" << data.origin() << ']';
-
- os << '{' << data.angle << "}{";
- return os.str();
-}
-
-
-string const RotationLatexCommand::back_impl() const
-{
- if (data.no_rotation())
- return string();
-
- return "}";
-}
-
-
-string const ClipLatexOption::option_impl() const
-{
- if (!data.clip || data.bbox.empty())
- return string();
-
- std::ostringstream os;
- if (!data.bbox.empty())
- os << "bb=" << data.bbox << ',';
- if (data.clip)
- os << "clip,";
- return os.str();
-}
-
-
-string const ResizeLatexOption::option_impl() const
-{
- if (data.no_resize())
- return string();
-
- std::ostringstream os;
- if (data.usingScale()) {
- double const scl = convert<double>(data.scale);
- if (!float_equal(scl, 100.0, 0.05))
- os << "scale=" << scl / 100.0 << ',';
- return os.str();
- }
-
- if (!data.width.zero())
- os << "width=" << data.width.asLatexString() << ',';
- if (!data.height.zero())
- os << "height=" << data.height.asLatexString() << ',';
- if (data.keepAspectRatio)
- os << "keepaspectratio,";
-
- return os.str();
-}
-
-
-string const RotationLatexOption ::option_impl() const
-{
- if (data.no_rotation())
- return string();
-
- std::ostringstream os;
- os << "angle=" << data.angle << ',';
-
- if (data.origin() != RotationData::DEFAULT)
- os << "origin=" << data.origin() << ',';
-
- return os.str();
-}
-
-
-string const sanitizeDocBookOption(string const & input)
-{
- return input;
-}
-
-
-string const sanitizeLatexOption(string const & input)
-{
- string::const_iterator begin = input.begin();
- string::const_iterator end = input.end();
- string::const_iterator it = begin;
-
- // Strip any leading commas
- // "[,,,,foo..." -> "foo..." ("foo..." may be empty)
- string output;
- boost::smatch what;
- static boost::regex const front("^( *[[],*)(.*)$");
-
- regex_match(it, end, what, front, boost::match_partial);
- if (!what[0].matched) {
- lyxerr << "Unable to sanitize LaTeX \"Option\": "
- << input << '\n';
- return string();
- }
- it = what[1].second;
-
- // Replace any consecutive commas with a single one
- // "foo,,,,bar" -> "foo,bar"
- // with iterator now pointing to 'b'
- static boost::regex const commas("([^,]*)(,,*)(.*)$");
- for (; it != end;) {
- regex_match(it, end, what, commas, boost::match_partial);
- if (!what[0].matched) {
- output += string(it, end);
- break;
- }
- output += what.str(1) + ",";
- it = what[3].first;
- }
-
- // Strip any trailing commas
- // "...foo,,,]" -> "...foo" ("...foo,,," may be empty)
- static boost::regex const back("^(.*[^,])?,*[]] *$");
- regex_match(output, what, back);
- if (!what[0].matched) {
- lyxerr << "Unable to sanitize LaTeX \"Option\": "
- << output << '\n';
- return string();
- }
- output = what.str(1);
-
- // Remove any surrounding whitespace
- output = support::trim(output);
-
- // If the thing is empty, leave it so, else wrap it in square brackets.
- return output.empty() ? output : "[" + output + "]";
-}
-
-
-namespace {
-
-template <typename Factory, typename Data, typename Transformer>
-void extractIt(boost::any const & any_factory,
- Data const & data, Transformer & transformer)
-{
- if (any_factory.type() != typeid(Factory))
- return;
-
- Factory factory = boost::any_cast<Factory>(any_factory);
- if (!factory.empty())
- transformer = factory(data);
-}
-
-} // namespace anon
-
-
-TransformCommand::ptr_type
-TransformStore::getCommandTransformer(RotationData const & data) const
-{
- TransformCommand::ptr_type ptr;
- if (id == Rotate)
- extractIt<RotationCommandFactory>(any_factory, data, ptr);
- return ptr;
-}
-
-
-TransformCommand::ptr_type
-TransformStore::getCommandTransformer(ResizeData const & data) const
-{
- TransformCommand::ptr_type ptr;
- if (id == Resize)
- extractIt<ResizeCommandFactory>(any_factory, data, ptr);
- return ptr;
-}
-
-
-TransformOption::ptr_type
-TransformStore::getOptionTransformer(RotationData const & data) const
-{
- TransformOption::ptr_type ptr;
- if (id == Rotate)
- extractIt<RotationOptionFactory>(any_factory, data, ptr);
- return ptr;
-}
-
-
-TransformOption::ptr_type
-TransformStore::getOptionTransformer(ResizeData const & data) const
-{
- TransformOption::ptr_type ptr;
- if (id == Resize)
- extractIt<ResizeOptionFactory>(any_factory, data, ptr);
- return ptr;
-}
-
-
-TransformOption::ptr_type
-TransformStore::getOptionTransformer(ClipData const & data) const
-{
- TransformOption::ptr_type ptr;
- if (id == Clip)
- extractIt<ClipOptionFactory>(any_factory, data, ptr);
- return ptr;
-}
-
-
-
-TransformOption::ptr_type
-TransformStore::getOptionTransformer(string const & data) const
-{
- TransformOption::ptr_type ptr;
- if (id == Extra)
- extractIt<ExtraOptionFactory>(any_factory, data, ptr);
- return ptr;
-}
-
-
-namespace {
-
-OriginTranslator const initOriginTranslator()
-{
- OriginTranslator translator(RotationData::DEFAULT, "default");
- translator.addPair(RotationData::TOPLEFT, "topleft");
- translator.addPair(RotationData::BOTTOMLEFT, "bottomleft");
- translator.addPair(RotationData::BASELINELEFT, "baselineleft");
- translator.addPair(RotationData::CENTER, "center");
- translator.addPair(RotationData::TOPCENTER, "topcenter");
- translator.addPair(RotationData::BOTTOMCENTER, "bottomcenter");
- translator.addPair(RotationData::BASELINECENTER, "baselinecenter");
- translator.addPair(RotationData::TOPRIGHT, "topright");
- translator.addPair(RotationData::BOTTOMRIGHT, "bottomright");
- translator.addPair(RotationData::BASELINERIGHT, "baselineright");
- return translator;
-}
-
-
-OriginTranslator const & originTranslator()
-{
- static OriginTranslator const translator = initOriginTranslator();
- return translator;
-}
-
-} // namespace anon
-
-} // namespace external
-} // namespace lyx
--- /dev/null
+/**
+ * \file ExternalTransforms.cpp
+ * This file is part of LyX, the document processor.
+ * Licence details can be found in the file COPYING.
+ *
+ * \author Angus Leeming
+ *
+ * Full author contact details are available in file CREDITS.
+ */
+
+#include <config.h>
+
+#include "ExternalTransforms.h"
+
+#include "debug.h"
+
+#include "support/lstrings.h"
+#include "support/lyxlib.h" // float_equal
+#include "support/convert.h"
+#include "support/Translator.h"
+
+#include <boost/regex.hpp>
+
+#include <cmath> // std::abs
+#include <sstream>
+
+
+namespace lyx {
+namespace external {
+
+using support::float_equal;
+using std::string;
+
+
+string const ExtraData::get(string const & id) const
+{
+ std::map<string, string>::const_iterator it = data_.find(id);
+ return it == data_.end() ? string() : it->second;
+}
+
+
+void ExtraData::set(string const & id, string const & data)
+{
+ data_[id] = data;
+}
+
+
+bool ResizeData::no_resize() const
+{
+ return !usingScale() && width.zero() && height.zero();
+}
+
+
+bool ResizeData::usingScale() const
+{
+ return (!scale.empty() && !float_equal(convert<double>(scale), 0.0, 0.05));
+}
+
+
+bool RotationData::no_rotation() const
+{
+ return (angle.empty() || std::abs(convert<double>(angle)) < 0.1);
+}
+
+
+string const RotationData::adjAngle() const
+{
+ // Ensure that angle lies in the range -360 < angle < 360
+ double rotAngle = convert<double>(angle);
+ if (std::abs(rotAngle) > 360.0) {
+ rotAngle -= 360.0 * floor(rotAngle / 360.0);
+ return convert<string>(rotAngle);
+ }
+ return angle;
+}
+
+
+namespace {
+
+typedef Translator<RotationData::OriginType, string> OriginTranslator;
+OriginTranslator const & originTranslator();
+
+} // namespace anon
+
+
+void RotationData::origin(string const & o)
+{
+ origin_ = originTranslator().find(o);
+}
+
+
+string const RotationData::originString() const
+{
+ return originTranslator().find(origin_);
+}
+
+
+string const ResizeLatexCommand::front_impl() const
+{
+ if (data.no_resize())
+ return string();
+
+ std::ostringstream os;
+ if (data.usingScale()) {
+ double const scl = convert<double>(data.scale) / 100.0;
+ os << "\\scalebox{" << scl << "}[" << scl << "]{";
+ } else {
+ string width = "!";
+ string height = "!";
+ if (data.keepAspectRatio) {
+ if (data.width.inPixels(10) > data.height.inPixels(10))
+ width = data.width.asLatexString();
+ else
+ height = data.height.asLatexString();
+ } else {
+ if (!data.width.zero())
+ width = data.width.asLatexString();
+ if (!data.height.zero())
+ height = data.height.asLatexString();
+ }
+
+ os << "\\resizebox{"
+ << width << "}{"
+ << height << "}{";
+ }
+ return os.str();
+}
+
+
+string const ResizeLatexCommand::back_impl() const
+{
+ if (data.no_resize())
+ return string();
+
+ return "}";
+}
+
+
+namespace {
+
+std::ostream & operator<<(std::ostream & os, RotationData::OriginType type)
+{
+ switch (type) {
+ case RotationData::DEFAULT:
+ case RotationData::CENTER:
+ break;
+ case RotationData::TOPLEFT:
+ case RotationData::TOPCENTER:
+ case RotationData::TOPRIGHT:
+ os << 't';
+ break;
+ case RotationData::BOTTOMLEFT:
+ case RotationData::BOTTOMCENTER:
+ case RotationData::BOTTOMRIGHT:
+ os << 'b';
+ break;
+ case RotationData::BASELINELEFT:
+ case RotationData::BASELINECENTER:
+ case RotationData::BASELINERIGHT:
+ os << 'B';
+ break;
+ }
+
+ switch (type) {
+ case RotationData::DEFAULT:
+ break;
+ case RotationData::TOPLEFT:
+ case RotationData::BOTTOMLEFT:
+ case RotationData::BASELINELEFT:
+ os << 'l';
+ break;
+ case RotationData::CENTER:
+ case RotationData::TOPCENTER:
+ case RotationData::BOTTOMCENTER:
+ case RotationData::BASELINECENTER:
+ os << 'c';
+ break;
+ case RotationData::TOPRIGHT:
+ case RotationData::BOTTOMRIGHT:
+ case RotationData::BASELINERIGHT:
+ os << 'r';
+ break;
+ }
+
+ return os;
+}
+
+} // namespace anon
+
+
+string const RotationLatexCommand::front_impl() const
+{
+ if (data.no_rotation())
+ return string();
+
+ std::ostringstream os;
+ os << "\\rotatebox";
+
+ if (data.origin() != RotationData::DEFAULT)
+ os << "[origin=" << data.origin() << ']';
+
+ os << '{' << data.angle << "}{";
+ return os.str();
+}
+
+
+string const RotationLatexCommand::back_impl() const
+{
+ if (data.no_rotation())
+ return string();
+
+ return "}";
+}
+
+
+string const ClipLatexOption::option_impl() const
+{
+ if (!data.clip || data.bbox.empty())
+ return string();
+
+ std::ostringstream os;
+ if (!data.bbox.empty())
+ os << "bb=" << data.bbox << ',';
+ if (data.clip)
+ os << "clip,";
+ return os.str();
+}
+
+
+string const ResizeLatexOption::option_impl() const
+{
+ if (data.no_resize())
+ return string();
+
+ std::ostringstream os;
+ if (data.usingScale()) {
+ double const scl = convert<double>(data.scale);
+ if (!float_equal(scl, 100.0, 0.05))
+ os << "scale=" << scl / 100.0 << ',';
+ return os.str();
+ }
+
+ if (!data.width.zero())
+ os << "width=" << data.width.asLatexString() << ',';
+ if (!data.height.zero())
+ os << "height=" << data.height.asLatexString() << ',';
+ if (data.keepAspectRatio)
+ os << "keepaspectratio,";
+
+ return os.str();
+}
+
+
+string const RotationLatexOption ::option_impl() const
+{
+ if (data.no_rotation())
+ return string();
+
+ std::ostringstream os;
+ os << "angle=" << data.angle << ',';
+
+ if (data.origin() != RotationData::DEFAULT)
+ os << "origin=" << data.origin() << ',';
+
+ return os.str();
+}
+
+
+string const sanitizeDocBookOption(string const & input)
+{
+ return input;
+}
+
+
+string const sanitizeLatexOption(string const & input)
+{
+ string::const_iterator begin = input.begin();
+ string::const_iterator end = input.end();
+ string::const_iterator it = begin;
+
+ // Strip any leading commas
+ // "[,,,,foo..." -> "foo..." ("foo..." may be empty)
+ string output;
+ boost::smatch what;
+ static boost::regex const front("^( *[[],*)(.*)$");
+
+ regex_match(it, end, what, front, boost::match_partial);
+ if (!what[0].matched) {
+ lyxerr << "Unable to sanitize LaTeX \"Option\": "
+ << input << '\n';
+ return string();
+ }
+ it = what[1].second;
+
+ // Replace any consecutive commas with a single one
+ // "foo,,,,bar" -> "foo,bar"
+ // with iterator now pointing to 'b'
+ static boost::regex const commas("([^,]*)(,,*)(.*)$");
+ for (; it != end;) {
+ regex_match(it, end, what, commas, boost::match_partial);
+ if (!what[0].matched) {
+ output += string(it, end);
+ break;
+ }
+ output += what.str(1) + ",";
+ it = what[3].first;
+ }
+
+ // Strip any trailing commas
+ // "...foo,,,]" -> "...foo" ("...foo,,," may be empty)
+ static boost::regex const back("^(.*[^,])?,*[]] *$");
+ regex_match(output, what, back);
+ if (!what[0].matched) {
+ lyxerr << "Unable to sanitize LaTeX \"Option\": "
+ << output << '\n';
+ return string();
+ }
+ output = what.str(1);
+
+ // Remove any surrounding whitespace
+ output = support::trim(output);
+
+ // If the thing is empty, leave it so, else wrap it in square brackets.
+ return output.empty() ? output : "[" + output + "]";
+}
+
+
+namespace {
+
+template <typename Factory, typename Data, typename Transformer>
+void extractIt(boost::any const & any_factory,
+ Data const & data, Transformer & transformer)
+{
+ if (any_factory.type() != typeid(Factory))
+ return;
+
+ Factory factory = boost::any_cast<Factory>(any_factory);
+ if (!factory.empty())
+ transformer = factory(data);
+}
+
+} // namespace anon
+
+
+TransformCommand::ptr_type
+TransformStore::getCommandTransformer(RotationData const & data) const
+{
+ TransformCommand::ptr_type ptr;
+ if (id == Rotate)
+ extractIt<RotationCommandFactory>(any_factory, data, ptr);
+ return ptr;
+}
+
+
+TransformCommand::ptr_type
+TransformStore::getCommandTransformer(ResizeData const & data) const
+{
+ TransformCommand::ptr_type ptr;
+ if (id == Resize)
+ extractIt<ResizeCommandFactory>(any_factory, data, ptr);
+ return ptr;
+}
+
+
+TransformOption::ptr_type
+TransformStore::getOptionTransformer(RotationData const & data) const
+{
+ TransformOption::ptr_type ptr;
+ if (id == Rotate)
+ extractIt<RotationOptionFactory>(any_factory, data, ptr);
+ return ptr;
+}
+
+
+TransformOption::ptr_type
+TransformStore::getOptionTransformer(ResizeData const & data) const
+{
+ TransformOption::ptr_type ptr;
+ if (id == Resize)
+ extractIt<ResizeOptionFactory>(any_factory, data, ptr);
+ return ptr;
+}
+
+
+TransformOption::ptr_type
+TransformStore::getOptionTransformer(ClipData const & data) const
+{
+ TransformOption::ptr_type ptr;
+ if (id == Clip)
+ extractIt<ClipOptionFactory>(any_factory, data, ptr);
+ return ptr;
+}
+
+
+
+TransformOption::ptr_type
+TransformStore::getOptionTransformer(string const & data) const
+{
+ TransformOption::ptr_type ptr;
+ if (id == Extra)
+ extractIt<ExtraOptionFactory>(any_factory, data, ptr);
+ return ptr;
+}
+
+
+namespace {
+
+OriginTranslator const initOriginTranslator()
+{
+ OriginTranslator translator(RotationData::DEFAULT, "default");
+ translator.addPair(RotationData::TOPLEFT, "topleft");
+ translator.addPair(RotationData::BOTTOMLEFT, "bottomleft");
+ translator.addPair(RotationData::BASELINELEFT, "baselineleft");
+ translator.addPair(RotationData::CENTER, "center");
+ translator.addPair(RotationData::TOPCENTER, "topcenter");
+ translator.addPair(RotationData::BOTTOMCENTER, "bottomcenter");
+ translator.addPair(RotationData::BASELINECENTER, "baselinecenter");
+ translator.addPair(RotationData::TOPRIGHT, "topright");
+ translator.addPair(RotationData::BOTTOMRIGHT, "bottomright");
+ translator.addPair(RotationData::BASELINERIGHT, "baselineright");
+ return translator;
+}
+
+
+OriginTranslator const & originTranslator()
+{
+ static OriginTranslator const translator = initOriginTranslator();
+ return translator;
+}
+
+} // namespace anon
+
+} // namespace external
+} // namespace lyx
libinsets_la_SOURCES = \
MailInset.cpp \
MailInset.h \
- ExternalSupport.C \
+ ExternalSupport.cpp \
ExternalSupport.h \
- ExternalTemplate.C \
+ ExternalTemplate.cpp \
ExternalTemplate.h \
- ExternalTransforms.C \
+ ExternalTransforms.cpp \
ExternalTransforms.h \
RenderBase.h \
RenderButton.cpp \