]> git.lyx.org Git - lyx.git/blobdiff - src/graphics/GraphicsConverter.C
* src/LaTeX.C
[lyx.git] / src / graphics / GraphicsConverter.C
index 2fbad942f41a7b77f4a511bd37b141e003e39e05..3a11012ba7ed81d67a7d7c73f8b54e0b652ae236 100644 (file)
 
 namespace support = lyx::support;
 
+using support::addExtension;
 using support::changeExtension;
+using support::FileName;
 using support::Forkedcall;
 using support::ForkedCallQueue;
 using support::getExtension;
-using support::libFileSearch;
 using support::libScriptSearch;
 using support::onlyPath;
 using support::onlyFilename;
@@ -56,7 +57,7 @@ namespace graphics {
 class Converter::Impl : public boost::signals::trackable {
 public:
        ///
-       Impl(string const &, string const &, string const &, string const &);
+       Impl(FileName const &, string const &, string const &, string const &);
 
        ///
        void startConversion();
@@ -78,9 +79,9 @@ public:
        ///
        string script_command_;
        ///
-       string script_file_;
+       FileName script_file_;
        ///
-       string to_file_;
+       FileName to_file_;
        ///
        bool valid_process_;
        ///
@@ -91,11 +92,11 @@ public:
 bool Converter::isReachable(string const & from_format_name,
                            string const & to_format_name)
 {
-       return converters.isReachable(from_format_name, to_format_name);
+       return theConverters().isReachable(from_format_name, to_format_name);
 }
 
 
-Converter::Converter(string const & from_file,   string const & to_file_base,
+Converter::Converter(FileName const & from_file, string const & to_file_base,
                     string const & from_format, string const & to_format)
        : pimpl_(new Impl(from_file, to_file_base, from_format, to_format))
 {}
@@ -118,36 +119,21 @@ boost::signals::connection Converter::connect(slot_type const & slot) const
 }
 
 
-string const & Converter::convertedFile() const
+FileName const & Converter::convertedFile() const
 {
-       static string const empty;
+       static FileName const empty;
        return pimpl_->finished_ ? pimpl_->to_file_ : empty;
 }
 
-} // namespace graphics
-} // namespace lyx
-
-
-//------------------------------
-// Implementation details follow
-//------------------------------
-
-namespace {
-
 /** Build the conversion script.
  *  The script is output to the stream \p script.
  */
-void build_script(string const & from_file, string const & to_file_base,
+static void build_script(FileName const & from_file, string const & to_file_base,
                  string const & from_format, string const & to_format,
                  ostream & script);
 
-} // namespace anon
-
-
-namespace lyx {
-namespace graphics {
 
-Converter::Impl::Impl(string const & from_file,   string const & to_file_base,
+Converter::Impl::Impl(FileName const & from_file, string const & to_file_base,
                      string const & from_format, string const & to_format)
        : valid_process_(false), finished_(false)
 {
@@ -160,7 +146,7 @@ Converter::Impl::Impl(string const & from_file,   string const & to_file_base,
        // The converted image is to be stored in this file (we do not
        // use ChangeExtension because this is a basename which may
        // nevertheless contain a '.')
-       to_file_ = to_file_base + '.' +  formats.extension(to_format);
+       to_file_ = FileName(to_file_base + '.' +  formats.extension(to_format));
 
        // The conversion commands are stored in a stringstream
        ostringstream script;
@@ -172,10 +158,10 @@ Converter::Impl::Impl(string const & from_file,   string const & to_file_base,
 
        // Output the script to file.
        static int counter = 0;
-       script_file_ = onlyPath(to_file_base) + "lyxconvert" +
-               convert<string>(counter++) + ".py";
+       script_file_ = FileName(onlyPath(to_file_base) + "lyxconvert" +
+               convert<string>(counter++) + ".py");
 
-       std::ofstream fs(script_file_.c_str());
+       std::ofstream fs(script_file_.toFilesystemEncoding().c_str());
        if (!fs.good()) {
                lyxerr << "Unable to write the conversion script to \""
                       << script_file_ << '\n'
@@ -192,8 +178,8 @@ Converter::Impl::Impl(string const & from_file,   string const & to_file_base,
        // list of forked processes.
        // Note: 'python ' is absolutely essential, or execvp will fail.
        script_command_ = support::os::python() + ' ' +
-               quoteName(script_file_) + ' ' +
-               quoteName(onlyFilename(from_file)) + ' ' +
+               quoteName(script_file_.toFilesystemEncoding()) + ' ' +
+               quoteName(onlyFilename(from_file.toFilesystemEncoding())) + ' ' +
                quoteName(to_format);
        // All is ready to go
        valid_process_ = true;
@@ -233,12 +219,8 @@ void Converter::Impl::converted(pid_t /* pid */, int retval)
        }
 }
 
-} // namespace graphics
-} // namespace lyx
-
-namespace {
 
-string const move_file(string const & from_file, string const & to_file)
+static string const move_file(string const & from_file, string const & to_file)
 {
        if (from_file == to_file)
                return string();
@@ -259,7 +241,7 @@ string const move_file(string const & from_file, string const & to_file)
 }
 
 
-void build_conversion_command(string const & command, ostream & script)
+static void build_conversion_command(string const & command, ostream & script)
 {
        // Store in the python script
        script << "\nif os.system(r'" << command << "') != 0:\n";
@@ -288,7 +270,7 @@ void build_conversion_command(string const & command, ostream & script)
 }
 
 
-void build_script(string const & from_file,
+static void build_script(FileName const & from_file,
                  string const & to_file_base,
                  string const & from_format,
                  string const & to_format,
@@ -299,13 +281,23 @@ void build_script(string const & from_file,
        typedef Converters::EdgePath EdgePath;
 
        script << "#!/usr/bin/env python\n"
-                 "import os, shutil, sys\n\n"
+                 "# -*- coding: utf-8 -*-\n"
+                 "import os, shutil, sys, locale\n\n"
                  "def unlinkNoThrow(file):\n"
                  "  ''' remove a file, do not throw if an error occurs '''\n"
                  "  try:\n"
                  "    os.unlink(file)\n"
                  "  except:\n"
-                 "    pass\n\n";
+                 "    pass\n\n"
+                 "def utf8ToDefaultEncoding(file):\n"
+                 "  ''' if possible, convert to the default encoding '''\n"
+                 "  try:\n"
+                 "    language, output_encoding = locale.getdefaultlocale()\n"
+                 "    if output_encoding == None:\n"
+                 "      output_encoding = 'latin1'\n"
+                 "    return unicode(file, 'utf8').encode(output_encoding)\n"
+                 "  except:\n"
+                 "    return file\n\n";
 
        // we do not use ChangeExtension because this is a basename
        // which may nevertheless contain a '.'
@@ -314,24 +306,33 @@ void build_script(string const & from_file,
 
        EdgePath const edgepath = from_format.empty() ?
                EdgePath() :
-               converters.getPath(from_format, to_format);
+               theConverters().getPath(from_format, to_format);
 
        // Create a temporary base file-name for all intermediate steps.
        // Remember to remove the temp file because we only want the name...
        static int counter = 0;
        string const tmp = "gconvert" + convert<string>(counter++);
-       string const to_base = tempName(string(), tmp);
+       FileName const to_base(tempName(FileName(), tmp));
        unlink(to_base);
 
        // Create a copy of the file in case the original name contains
        // problematic characters like ' or ". We can work around that problem
        // in python, but the converters might be shell scripts and have more
        // troubles with it.
-       string outfile = changeExtension(to_base, getExtension(from_file));
-       script << "infile = " << quoteName(from_file, quote_python) << "\n"
+       string outfile = addExtension(to_base.absFilename(), getExtension(from_file.absFilename()));
+       script << "infile = utf8ToDefaultEncoding("
+                       << quoteName(from_file.absFilename(), quote_python)
+                       << ")\n"
                  "outfile = " << quoteName(outfile, quote_python) << "\n"
                  "shutil.copy(infile, outfile)\n";
 
+       // Some converters (e.g. lilypond) can only output files to the
+       // current directory, so we need to change the current directory.
+       // This has the added benefit that all other files that may be
+       // generated by the converter are deleted when LyX closes and do not
+       // clutter the real working directory.
+       script << "os.chdir(" << quoteName(onlyPath(outfile)) << ")\n";
+
        if (edgepath.empty()) {
                // Either from_format is unknown or we don't have a
                // converter path from from_format to to_format, so we use
@@ -370,12 +371,12 @@ void build_script(string const & from_file,
        EdgePath::const_iterator end = edgepath.end();
 
        for (; it != end; ++it) {
-               ::Converter const & conv = converters.get(*it);
+               lyx::Converter const & conv = theConverters().get(*it);
 
                // Build the conversion command
                string const infile      = outfile;
                string const infile_base = changeExtension(infile, string());
-               outfile = changeExtension(to_base, conv.To->extension());
+               outfile = addExtension(to_base.absFilename(), conv.To->extension());
 
                // Store these names in the python script
                script << "infile = "      << quoteName(infile, quote_python) << "\n"
@@ -398,4 +399,6 @@ void build_script(string const & from_file,
        lyxerr[Debug::GRAPHICS] << "ready!" << endl;
 }
 
-} // namespace anon
+} // namespace graphics
+
+} // namespace lyx