]> git.lyx.org Git - features.git/commitdiff
Fix export of graphics images when compiling latex file.
authorAngus Leeming <leeming@lyx.org>
Wed, 3 Sep 2003 17:23:38 +0000 (17:23 +0000)
committerAngus Leeming <leeming@lyx.org>
Wed, 3 Sep 2003 17:23:38 +0000 (17:23 +0000)
git-svn-id: svn://svn.lyx.org/lyx/lyx-devel/trunk@7649 a592a061-630c-0410-9148-cb99ea01b6c8

src/insets/ChangeLog
src/insets/insetexternal.C
src/insets/insetgraphics.C
src/support/ChangeLog
src/support/filename.C
src/support/filename.h
src/support/filetools.C
src/support/filetools.h

index e008e172d37dfc9112db8deb6b23387720b9116b..adcff625bee821587d5696e2bb93cb465f538555 100644 (file)
@@ -1,3 +1,9 @@
+2003-09-03  Angus Leeming  <leeming@lyx.org>
+
+       * insetexternal.C (updateExternal):
+       * insetgraphics.C (prepareFile): Fix the conversion when exporting to
+       latex.
+
 2003-09-03  Angus Leeming  <leeming@lyx.org>
 
        * insetexternal.C: don't bring namespace lyx::support into the global
index eb4142fedd6ac2fba7706da890ac50eecf2a99e2..5681bd9a22574d4c16379103540c827b18a52b7c 100644 (file)
@@ -518,28 +518,33 @@ void InsetExternal::updateExternal(string const & format,
 
        if (external_in_tmpdir && !from_file.empty()) {
                // We are running stuff through LaTeX
-               from_file = support::copyFileToDir(buf.tmppath, from_file);
-               if (from_file.empty())
+               string const temp_file =
+                       support::MakeAbsPath(params_.filename.mangledFilename(),
+                                            buf.tmppath);
+               unsigned long const from_checksum = support::sum(from_file);
+               unsigned long const temp_checksum = support::sum(temp_file);
+
+               // Nothing to do...
+               if (from_checksum == temp_checksum)
                        return;
+
+               // Cannot proceed...
+               if (!support::copy(from_file, temp_file))
+                       return;
+               from_file = temp_file;
        }
 
        string const to_file = doSubstitution(params_, buf,
                                              outputFormat.updateResult);
+       string const abs_to_file = support::MakeAbsPath(to_file, buf.filePath());
 
-       support::FileInfo fi(from_file);
-       string abs_to_file = to_file;
-       if (!support::AbsolutePath(to_file))
-               abs_to_file = support::MakeAbsPath(to_file,
-                                                  support::OnlyPath(from_file));
-       support::FileInfo fi2(abs_to_file);
-       if (fi2.exist() && fi.exist() &&
-           difftime(fi2.getModificationTime(),
-                    fi.getModificationTime()) >= 0) {
-       } else {
-               string const to_filebase = support::ChangeExtension(to_file, string());
-               converters.convert(&buf, from_file, to_filebase,
-                                  from_format, to_format);
-       }
+       // 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(from_file, abs_to_file) < 0)
+               return;
+       
+       string const to_filebase = support::ChangeExtension(to_file, string());
+       converters.convert(&buf, from_file, to_filebase, from_format, to_format);
 }
 
 
index 59b811390ddeb4c4230b658e5d65e5825d741504..ec7b4e0e95debd56d5c712fa63dd42eaee41c890 100644 (file)
@@ -74,6 +74,7 @@ TODO
 #include "frontends/Alert.h"
 #include "frontends/Dialogs.h"
 
+#include "support/LAssert.h"
 #include "support/filetools.h"
 #include "support/lyxalgo.h" // lyx::count
 #include "support/lyxlib.h" // float_equal
@@ -81,11 +82,13 @@ TODO
 #include "support/systemcall.h"
 
 #include <boost/bind.hpp>
+#include <boost/tuple/tuple.hpp>
 
 #include <algorithm> // For the std::max
 
 // set by Exporters
 
+namespace support = lyx::support;
 using namespace lyx::support;
 
 using std::ostream;
@@ -328,14 +331,79 @@ string const InsetGraphics::createLatexOptions() const
 }
 
 
+namespace {
+
+enum CopyStatus {
+       SUCCESS,
+       FAILURE,
+       IDENTICAL_PATHS,
+       IDENTICAL_CONTENTS
+};
+
+
+std::pair<CopyStatus, string> const
+copyToDirIfNeeded(string const & file_in, string const & dir)
+{
+       using support::rtrim;
+
+       support::Assert(AbsolutePath(file_in));
+
+       string const only_path = support::OnlyPath(file_in);
+       if (rtrim(support::OnlyPath(file_in) , "/") == rtrim(dir, "/"))
+               return std::make_pair(IDENTICAL_PATHS, file_in);
+
+       string mangled;
+       if (support::zippedFile(file_in)) {
+               string const ext = GetExtension(file_in);
+               string const unzipped = support::unzippedFileName(file_in);
+               mangled = FileName(unzipped).mangledFilename();
+               mangled += "." + ext;
+       } else
+               mangled = FileName(file_in).mangledFilename();
+
+       string const file_out = support::MakeAbsPath(mangled, dir);
+       
+       unsigned long const checksum_in  = support::sum(file_in);
+       unsigned long const checksum_out = support::sum(file_out);
+
+       if (checksum_in == checksum_out)
+               // Nothing to do...
+               return std::make_pair(IDENTICAL_CONTENTS, file_out);
+
+       bool const success = support::copy(file_in, file_out);
+       if (!success) {
+               lyxerr[Debug::GRAPHICS]
+                       << support::bformat(_("Could not copy the file\n%1$s\n"
+                                             "into the temporary directory."),
+                                           file_in)
+                       << std::endl;
+       }
+
+       CopyStatus status = success ? SUCCESS : FAILURE;
+       return std::make_pair(status, file_out);
+}
+
+
+string const stripExtensionIfPossible(string const & file, string const & to)
+{
+       // No conversion is needed. LaTeX can handle the graphic file as is.
+       // This is true even if the orig_file is compressed.
+       if (formats.getFormat(to)->extension() == GetExtension(file))
+               return RemoveExtension(file);
+       return file;
+}
+
+} // namespace anon
+
+
 string const InsetGraphics::prepareFile(Buffer const & buf,
                                        LatexRunParams const & runparams) const
 {
-       // LaTeX can cope if the graphics file doesn't exist, so just return the
-       // filename.
        string orig_file = params().filename.absFilename();
        string const rel_file = params().filename.relFilename(buf.filePath());
 
+       // LaTeX can cope if the graphics file doesn't exist, so just return the
+       // filename.
        if (!IsFileReadable(orig_file)) {
                lyxerr[Debug::GRAPHICS]
                        << "InsetGraphics::prepareFile\n"
@@ -343,11 +411,11 @@ string const InsetGraphics::prepareFile(Buffer const & buf,
                return rel_file;
        }
 
-       bool const zipped = zippedFile(orig_file);
-
        // If the file is compressed and we have specified that it
        // should not be uncompressed, then just return its name and
        // let LaTeX do the rest!
+       bool const zipped = params().filename.isZipped();
+
        if (zipped && params().noUnzip) {
                lyxerr[Debug::GRAPHICS]
                        << "\tpass zipped file to LaTeX but with full path.\n";
@@ -361,95 +429,85 @@ string const InsetGraphics::prepareFile(Buffer const & buf,
        string temp_file = orig_file;
 
        if (zipped) {
-               // Uncompress the file if necessary.
-               // If it has been uncompressed in a previous call to
-               // prepareFile, do nothing.
-               temp_file = MakeAbsPath(OnlyFilename(temp_file), buf.tmppath);
-               lyxerr[Debug::GRAPHICS]
-                       << "\ttemp_file: " << temp_file << endl;
-               if (graphic_->hasFileChanged() || !IsFileReadable(temp_file)) {
-                       bool const success = copy(orig_file, temp_file);
-                       lyxerr[Debug::GRAPHICS]
-                               << "\tCopying zipped file from "
-                               << orig_file << " to " << temp_file
-                               << (success ? " succeeded\n" : " failed\n");
-               } else
+               CopyStatus status;
+               boost::tie(status, temp_file) =
+                       copyToDirIfNeeded(orig_file, buf.tmppath);
+
+               if (status == FAILURE)
+                       return orig_file;
+
+               orig_file = unzippedFileName(temp_file);
+               if (!IsFileReadable(orig_file)) {
+                       unzipFile(temp_file);
                        lyxerr[Debug::GRAPHICS]
-                               << "\tzipped file " << temp_file
-                               << " exists! Maybe no tempdir ...\n";
-               orig_file = unzipFile(temp_file);
-               lyxerr[Debug::GRAPHICS]
-                       << "\tunzipped to " << orig_file << endl;
+                               << "\tunzipped to " << orig_file << endl;
+               }
        }
-
+       
        string const from = getExtFromContents(orig_file);
        string const to   = findTargetFormat(from, runparams);
        lyxerr[Debug::GRAPHICS]
                << "\t we have: from " << from << " to " << to << '\n';
 
-       if (from == to && !lyxrc.use_tempdir) {
-               // No conversion is needed. LaTeX can handle the
-               // graphic file as is.
-               // This is true even if the orig_file is compressed.
-               if (formats.getFormat(to)->extension() == GetExtension(orig_file))
-                       return RemoveExtension(orig_file);
-               return orig_file;
-       }
+       if (from == to && !lyxrc.use_tempdir)
+               return stripExtensionIfPossible(orig_file, to);
 
        // We're going to be running the exported buffer through the LaTeX
        // compiler, so must ensure that LaTeX can cope with the graphics
        // file format.
 
-       // Perform all these manipulations on a temporary file if possible.
-       // If we are not using a temp dir, then temp_file contains the
-       // original file.
-       // to allow files with the same name in different dirs
-       // we manipulate the original file "any.dir/file.ext"
-       // to "any_dir_file.ext"! changing the dots in the
-       // dirname is important for the use of ChangeExtension
        lyxerr[Debug::GRAPHICS]
                << "\tthe orig file is: " << orig_file << endl;
 
+       bool conversion_needed = true;
        if (lyxrc.use_tempdir) {
-               temp_file = copyFileToDir(buf.tmppath, orig_file);
-               if (temp_file.empty()) {
-                       string str = bformat(_("Could not copy the file\n%1$s\n"
-                                              "into the temporary directory."),
-                                            orig_file);
-                       Alert::error(_("Graphics display failed"), str);
+               CopyStatus status;
+               boost::tie(status, temp_file) =
+                       copyToDirIfNeeded(orig_file, buf.tmppath);
+
+               if (status == FAILURE)
                        return orig_file;
-               }
+               else if (status == IDENTICAL_CONTENTS)
+                       conversion_needed = false;
+       }
 
-               if (from == to) {
-                       // No conversion is needed. LaTeX can handle the
-                       // graphic file as is.
-                       if (formats.getFormat(to)->extension() == GetExtension(orig_file))
-                               return RemoveExtension(temp_file);
-                       return temp_file;
-               }
+       if (from == to)
+               return stripExtensionIfPossible(temp_file, to);
+
+       string const to_file_base = RemoveExtension(temp_file);
+       string const to_file = ChangeExtension(to_file_base, to);
+
+       // Do we need to perform the conversion?
+       // Yes if to_file does not exist or if temp_file is newer than to_file
+       if (!conversion_needed ||
+           support::compare_timestamps(temp_file, to_file) < 0) {
+               lyxerr[Debug::GRAPHICS]
+                       << bformat(_("No conversion of %1$s is needed after all"),
+                                  rel_file)
+                       << std::endl;
+               return to_file_base;
        }
 
-       string const outfile_base = RemoveExtension(temp_file);
        lyxerr[Debug::GRAPHICS]
                << "\tThe original file is " << orig_file << "\n"
                << "\tA copy has been made and convert is to be called with:\n"
                << "\tfile to convert = " << temp_file << '\n'
-               << "\toutfile_base = " << outfile_base << '\n'
+               << "\tto_file_base = " << to_file_base << '\n'
                << "\t from " << from << " to " << to << '\n';
 
        // if no special converter defined, than we take the default one
        // from ImageMagic: convert from:inname.from to:outname.to
-       if (!converters.convert(&buf, temp_file, outfile_base, from, to)) {
+       if (!converters.convert(&buf, temp_file, to_file_base, from, to)) {
                string const command =
                        "sh " + LibFileSearch("scripts", "convertDefault.sh") +
                                ' ' + from + ':' + temp_file + ' ' +
-                               to + ':' + outfile_base + '.' + to;
+                               to + ':' + to_file_base + '.' + to;
                lyxerr[Debug::GRAPHICS]
                        << "No converter defined! I use convertDefault.sh:\n\t"
                        << command << endl;
                Systemcall one;
                one.startscript(Systemcall::Wait, command);
-               if (!IsFileReadable(ChangeExtension(outfile_base, to))) {
+               if (!IsFileReadable(ChangeExtension(to_file_base, to))) {
                        string str = bformat(_("No information for converting %1$s "
                                "format files to %2$s.\n"
                                "Try defining a convertor in the preferences."), from, to);
@@ -457,7 +515,7 @@ string const InsetGraphics::prepareFile(Buffer const & buf,
                }
        }
 
-       return RemoveExtension(temp_file);
+       return to_file_base;
 }
 
 
index f9041cab9126921b529fa518becf997c5eeefb91..bd049f820eefa4ea531ba9e1fbedee7908af33ea 100644 (file)
@@ -1,3 +1,13 @@
+2003-09-03  Angus Leeming  <leeming@lyx.org>
+
+       * filename.[Ch] (FileName): new c-tor takes abs_filename arg.
+       (mangledFilename): new function, returning a mangled version of the
+       absolute file name, suitable for use in the temp dir when, for example,
+       converting an image file to another format.
+
+       * filetools.[Ch] (copyFileToDir): removed.
+       (compare_timestamps): new function.
+
 2003-09-03  Angus Leeming  <leeming@lyx.org>
 
        * translator.h: Assert is in namespace lyx::support...
@@ -22,7 +32,7 @@
 
 2003-07-29  Lars Gullik Bjønnes  <larsbj@gullik.net>
 
-       * Makefile.am: contidionalize USE_COMPRESSION
+       * Makefile.am: conditionalize USE_COMPRESSION.
 
 2003-07-28  Lars Gullik Bjønnes  <larsbj@gullik.net>
 
index fa23523d181850311ae23ed70ba9720fc81db11f..121925250eda6ca16f4092c745064d27af5d56be 100644 (file)
@@ -13,6 +13,8 @@
 
 #include "filename.h"
 #include "support/filetools.h"
+#include "lstrings.h"
+#include "LAssert.h"
 
 
 namespace lyx {
@@ -24,6 +26,13 @@ FileName::FileName()
 {}
 
 
+FileName::FileName(string const & abs_filename, bool save_abs)
+       : name_(abs_filename), save_abs_path_(save_abs)
+{
+       Assert(AbsolutePath(name_));
+}
+
+
 void FileName::set(string const & name, string const & buffer_path)
 {
        save_abs_path_ = AbsolutePath(name);
@@ -49,6 +58,32 @@ string const FileName::outputFilename(string const & path) const
 }
 
 
+string const FileName::mangledFilename() const
+{
+       string mname = os::slashify_path(name_);
+       // Remove the extension.
+       mname = ChangeExtension(name_, string());
+       // Replace '/' in the file name with '_'
+       mname = subst(mname, "/", "_");
+       // Replace '.' in the file name with '_'
+       mname = subst(mname, ".", "_");
+       // Add the extension back on
+       return ChangeExtension(mname, GetExtension(name_));
+}
+
+
+bool FileName::isZipped() const
+{
+       return zippedFile(name_);
+}
+
+
+string const FileName::unzippedFilename() const
+{
+       return unzippedFileName(name_);
+}
+
+
 bool operator==(FileName const & lhs, FileName const & rhs)
 {
        return lhs.absFilename() == rhs.absFilename() &&
@@ -61,5 +96,5 @@ bool operator!=(FileName const & lhs, FileName const & rhs)
        return !(lhs == rhs);
 }
 
-} //namespace support
+} // namespace support
 } // namespace lyx
index e3571be478ec3d22b65d9c29b6047b1e4022c598..feba602a6b3e075378cdd1adcdb1516aaebb4aaf 100644 (file)
@@ -22,11 +22,15 @@ namespace support {
 class FileName {
 public:
        FileName();
+       /** \param filename the file in question. Must have an absolute path.
+        *  \param save_abs_path how is the file to be output to file?
+        */
+       FileName(string const & abs_filename, bool save_abs_path = true);
 
        /** \param filename the file in question. May have either a relative
-           or an absolute path.
-           \param buffer_path if \c filename has a relative path, generate
-           the absolute path using this.
+        *  or an absolute path.
+        *  \param buffer_path if \c filename has a relative path, generate
+        *  the absolute path using this.
         */
        void set(string const & filename, string const & buffer_path);
 
@@ -39,6 +43,16 @@ public:
        string const relFilename(string const & buffer_path = string()) const;
        /// \param buf_path if empty, uses `pwd`
        string const outputFilename(string const & buf_path = string()) const;
+       /** \return a mangled version of the absolute file name,
+        *  suitable for use in the temp dir when, for example, converting
+        *  an image file to another format.
+        */
+       string const mangledFilename() const;
+
+       /// \return true if the file is compressed.
+       bool isZipped() const;
+       /// \return the absolute file name without its .gz, .z, .Z extension
+       string const unzippedFilename() const;
 
 private:
        string name_;
index bf0ba6197315a2c2f6f01cf49998081ccbdf9878..f87a0cf7e0269952c20e5e87ccb038f3a7c3ad20 100644 (file)
@@ -1134,10 +1134,18 @@ bool zippedFile(string const & name)
 }
 
 
+string const unzippedFileName(string const & zipped_file)
+{
+       string const ext = GetExtension(zipped_file);
+       if (ext == "gz" || ext == "z" || ext == "Z")
+               return ChangeExtension(zipped_file, string());
+       return "unzipped_" + zipped_file;
+}
+
+
 string const unzipFile(string const & zipped_file)
 {
-       string const file = ChangeExtension(zipped_file, string());
-       string  const tempfile = tempName(string(), file);
+       string  const tempfile = unzippedFileName(zipped_file);
        // Run gunzip
        string const command = "gunzip -c " + zipped_file + " > " + tempfile;
        Systemcall one;
@@ -1333,43 +1341,29 @@ string const readBB_from_PSFile(string const & file)
 }
 
 
-string const copyFileToDir(string const & path, string const & file_in)
+int compare_timestamps(string const & file1, string const & file2)
 {
-       Assert(AbsolutePath(path));
-
-       // First, make the file path relative to path.
-       string file_out = MakeRelPath(path, NormalizePath(file_in));
-       file_out = os::slashify_path(file_out);
-
-       // Now generate a unique filename.
-       // Remove the extension.
-       file_out = ChangeExtension(file_out, string());
-       // Replace '/' in the file name with '_'
-       file_out = subst(file_out, "/", "_");
-       // Replace '.' in the file name with '_'
-       file_out = subst(file_out, ".", "_");
-       // Append a unique ID
-//     static int id;
-//     file_out += '_' + tostr(id++);
-       // Add the extension back on
-       file_out = ChangeExtension(file_out, GetExtension(file_in));
-       // Put this file in the buffer's temp dir
-       file_out = MakeAbsPath(file_out, path);
+       Assert(AbsolutePath(file1) && AbsolutePath(file2));
 
        // If the original is newer than the copy, then copy the original
        // to the new directory.
-       FileInfo fi(file_in);
-       FileInfo fi2(file_out);
-
-       bool success = true;
-       if (fi.exist()) {
-               if (!fi2.exist() ||
-                   difftime(fi.getModificationTime(),
-                            fi2.getModificationTime()) >= 0)
-                       success = copy(file_in, file_out);
+       FileInfo f1(file1);
+       FileInfo f2(file2);
+
+       int cmp = 0;
+       if (f1.exist() && f2.exist()) {
+               double const tmp = difftime(f1.getModificationTime(),
+                                           f2.getModificationTime());
+               if (tmp != 0)
+                       cmp = tmp > 0 ? 1 : -1;
+
+       } else if (f1.exist()) {
+               cmp = 1;
+       } else if (f2.exist()) {
+               cmp = -1;
        }
 
-       return success ? file_out : string();
+       return cmp;
 }
 
 } //namespace support
index 8203d3aaa7b549cfade443c4de2e680bf6abb262..d576a4f74402a9d8a3ca35810c1cfd495eca3534 100644 (file)
@@ -143,6 +143,9 @@ string const getExtFromContents(string const & name);
 /// check for zipped file
 bool zippedFile(string const & name);
 
+/// \return the name that LyX will give to the unzipped file.
+string const unzippedFileName(string const & zipped_file);
+
 /// unzip a file
 string const unzipFile(string const & zipped_file);
 
@@ -210,14 +213,14 @@ void removeAutosaveFile(string const & filename);
 /// read the BoundingBox entry from a ps/eps/pdf-file
 string const readBB_from_PSFile(string const & file);
 
-/** Copy \c file to directory \c path. The file name is manipulated
-    so that eg some/path/to/file becomes some_path_to_file.
-    \param path where to put the file
-    \param file the file that is copied
   \returns this file name if the file is copied successfully, else
   \returns an empty string.
+/** \param file1, file2 the two files to be compared. Must have absolute paths.
+ *  \returns 1 if \c file1 has a more recent timestamp than \c file2,
+ *           0 if their timestamps are the same,
+ *          -1 if \c file2 has a more recent timestamp than \c file1.
*  If one of the files does not exist, the return value indicates the file
*  which does exist. Eg, if \c file1 exists but \c file2 does not, return 1.
  */
-string const copyFileToDir(string const & path, string const & file);
+int compare_timestamps(string const & file1, string const & file2);
 
 typedef std::pair<int, string> cmd_ret;