+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
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);
}
#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
#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;
}
+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"
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";
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);
}
}
- return RemoveExtension(temp_file);
+ return to_file_base;
}
+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...
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>
#include "filename.h"
#include "support/filetools.h"
+#include "lstrings.h"
+#include "LAssert.h"
namespace lyx {
{}
+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);
}
+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() &&
return !(lhs == rhs);
}
-} //namespace support
+} // namespace support
} // namespace lyx
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);
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_;
}
+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;
}
-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
/// 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);
/// 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;