Am Montag, 10. Mai 2004 15:49 schrieb Angus Leeming: > > What do you think? Should I use the hack described above and collect > > the data in latex(), or should I do it in validate(), and how should > > I pass the files to Exporter::Export()? > > However you think it should be done best.
Here comes the patch, I did it the easy way. It fixes bug 1244, but has one problem concerning external insets: It copies every file, even if it is a .tex file and therefore the content is already in the .dvi file. I am not sure how to solve this. First I thought this should depend on the format of the converted file (only copy it if it is some kind of ps), but then it is perfectly legal to input a .eps file verbatim (maybe in a tutorial about eps), and in this case it does not need to be copied either. The only clean solution that I can imagine is to introduce a switch in the external template that tells wether a file is "input like" or "includegraphics like", because the template is the only place where this is known. Any other ideas? > It seems to me that what you are describing is that Export should no > longer be thought of as a simple '1 file' to '1 file' conversion > process. Instead it is a 'many files' to, possibly, many files > conversion process. That being the case, it might well end up easiest > if you try and model what is really going on. > > Maybe something like this: > > class Conversion { > string from_file; > string to_file; > Converter converter; > }; > class ExportProcess { > // All these must be generated for the process > // to be classed as a success. > list<string> to_files; > > // A list of each, individual conversion process > list<Conversion> converstion; > }; Right now, we don't use the information about exported files outside the exporter. If this is needed later, the exporter can probably be converted easily to such a scheme. A first step could be done if the hardcoded 'if (format == "dvi")' needs to be extended. Apart from the external inset problem above, is the patch ok? Georg
diff -p -r -U 4 -X excl.tmp lyx-1.4-clean/src/ChangeLog lyx-1.4-cvs/src/ChangeLog --- lyx-1.4-clean/src/ChangeLog 2004-05-14 19:53:10.000000000 +0200 +++ lyx-1.4-cvs/src/ChangeLog 2004-05-15 12:03:44.000000000 +0200 @@ -1,4 +1,13 @@ +2004-05-15 Georg Baum <[EMAIL PROTECTED]> + + * exporter.C (checkOverwrite): new method + * exporter.C (copyFile): new method + * exporter.C: copy included graphics when exporting as DVI + * exporter.[Ch]: add class ExportData. Contains currently the + included graphics file names + * outputparams.h: add exportdata member. + 2004-05-14 José Matos <[EMAIL PROTECTED]> * buffer.C (makeDocBookFile): add a default Formal Public Identifier if the textclass does not provide it. Have it different for sgml and diff -p -r -U 4 -X excl.tmp lyx-1.4-clean/src/exporter.C lyx-1.4-cvs/src/exporter.C --- lyx-1.4-clean/src/exporter.C 2004-02-25 13:00:48.000000000 +0100 +++ lyx-1.4-cvs/src/exporter.C 2004-05-15 12:29:11.000000000 +0200 @@ -28,9 +28,11 @@ #include "output_plaintext.h" #include "outputparams.h" #include "frontends/Alert.h" +#include "support/FileInfo.h" #include "support/filetools.h" +#include "support/lyxlib.h" using lyx::support::AddName; using lyx::support::bformat; using lyx::support::ChangeExtension; @@ -52,8 +54,47 @@ vector<string> const Backends(Buffer con v.push_back("text"); return v; } + +int checkOverwrite(string const & filename) +{ + if (lyx::support::FileInfo(filename, true).exist()) { + string text = bformat(_("The file %1$s already exists.\n\n" + "Do you want to over-write that file?"), + MakeDisplayPath(filename)); + return Alert::prompt(_("Over-write file?"), + text, 0, 2, + _("&Over-write"), _("Over-write &all"), + _("&Cancel")); + } + return 0; +} + + +/** + * copy file \p sourceFile to \p destFile. If \p force is false, the user + * will be asked before existing files are overwritten. + * \return true if subsequent calls should not ask for confirmation before + * overwriting files anymore. + */ +bool copyFile(string const & sourceFile, string const & destFile, bool force) +{ + int ret = force ? 1 : 0; + if (!force) { + ret = checkOverwrite(destFile); + if (ret == 2) + return false; + } + + if (!lyx::support::copy(sourceFile, destFile)) + Alert::error(_("Couldn't copy file"), + bformat(_("Copying %1$s to %2$s failed."), + MakeDisplayPath(sourceFile), + MakeDisplayPath(destFile))); + return ret; +} + } //namespace anon bool Exporter::Export(Buffer * buffer, string const & format, @@ -62,8 +103,10 @@ bool Exporter::Export(Buffer * buffer, s string backend_format; OutputParams runparams; runparams.flavor = OutputParams::LATEX; runparams.linelen = lyxrc.ascii_linelen; + ExportData exportdata; + runparams.exportdata = &exportdata; vector<string> backends = Backends(*buffer); if (find(backends.begin(), backends.end(), format) == backends.end()) { for (vector<string>::const_iterator it = backends.begin(); it != backends.end(); ++it) { @@ -122,12 +166,24 @@ bool Exporter::Export(Buffer * buffer, s backend_format, format, result_file)) return false; - if (!put_in_tempdir) + if (!put_in_tempdir) { buffer->message(_("Document exported as ") + formats.prettyName(format) + _(" to file `") + MakeDisplayPath(result_file) +'\''); + if (format == "dvi") { + // We need to copy included graphics to the result + // dir, because the dvi format does not contain them. + vector<string> const & files = exportdata.externalFiles(); + string const dest = lyx::support::OnlyPath(result_file); + bool force = false; + for (vector<string>::const_iterator it = files.begin(); + it != files.end(); ++it) + force = copyFile(*it, AddName(dest, *it), force); + } + } + return true; } @@ -172,4 +229,22 @@ Exporter::GetExportableFormats(Buffer co result.insert(result.end(), r.begin(), r.end()); } return result; } + + +void ExportData::addExternalFile(string const & file) +{ + BOOST_ASSERT(lyx::support::AbsolutePath(file)); + + // Make sure that we have every file only once, otherwise copyFile() + // would ask several times if it should overwrite a file. + if (find(externalfiles.begin(), externalfiles.end(), file) + == externalfiles.end()) + externalfiles.push_back(file); +} + + +vector<string> const & ExportData::externalFiles() const +{ + return externalfiles; +} diff -p -r -U 4 -X excl.tmp lyx-1.4-clean/src/exporter.h lyx-1.4-cvs/src/exporter.h --- lyx-1.4-clean/src/exporter.h 2003-10-07 08:45:24.000000000 +0200 +++ lyx-1.4-cvs/src/exporter.h 2004-05-15 11:55:28.000000000 +0200 @@ -41,5 +41,15 @@ public: std::vector<Format const *> const GetExportableFormats(Buffer const & buffer, bool only_viewable); /// }; + +class ExportData { +public: + void addExternalFile(std::string const &); + std::vector<std::string> const & externalFiles() const; +private: + /// Files that are referenced by the DVI file of this document + std::vector<std::string> externalfiles; +}; + #endif diff -p -r -U 4 -X excl.tmp lyx-1.4-clean/src/insets/ChangeLog lyx-1.4-cvs/src/insets/ChangeLog --- lyx-1.4-clean/src/insets/ChangeLog 2004-05-14 19:53:56.000000000 +0200 +++ lyx-1.4-cvs/src/insets/ChangeLog 2004-05-15 14:09:33.000000000 +0200 @@ -1,4 +1,21 @@ +2004-05-15 Georg Baum <[EMAIL PROTECTED]> + + * ExternalSupport.[Ch] (doSubstitution): exchange filename argument + by external_in_tmpdir and compute filename ourself + * ExternalSupport.[Ch] (updateExternal): returns now the generated + filename + * ExternalSupport.C (writeExternal): don't call updateExternal + anymore + * ExternalSupport.C (writeExternal): write relative filename if + running latex + * insetexternal.C (latex, plaintext, linuxdoc, docbook): call + updateExternal + * insetexternal.C, insetgraphics.C (latex): add file to + runparams.exportdata (needed for DVI export) + * insetgraphics.C (prepareFile): write relative filename if + running latex + 2004-05-14 José Matos <[EMAIL PROTECTED]> * insetlabel (docbook): do not ouput label, for the moment. diff -p -r -U 4 -X excl.tmp lyx-1.4-clean/src/insets/ExternalSupport.C lyx-1.4-cvs/src/insets/ExternalSupport.C --- lyx-1.4-clean/src/insets/ExternalSupport.C 2004-04-13 12:36:09.000000000 +0200 +++ lyx-1.4-cvs/src/insets/ExternalSupport.C 2004-05-15 13:49:59.000000000 +0200 @@ -57,33 +57,34 @@ void editExternal(InsetExternalParams co support::getExtFromContents(file_with_path)); } -namespace { - -/** Substitute meta-variables in the string \p s. - \p filename has to be the filename as read from the .lyx file (this - can be an absolute path or a path relative to the parent document). - Otherwise, the $$AbsOrRelPath* variables would not work. - If we are using a temporary directory, \p filename is the mangled name. -*/ string const doSubstitution(InsetExternalParams const & params, Buffer const & buffer, string const & s, - string const & filename) + bool external_in_tmpdir) { + 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 result; string const basename = support::ChangeExtension( support::OnlyFilename(filename), string()); - string const absname = support::MakeAbsPath(filename, buffer.filePath()); + string const absname = support::MakeAbsPath(filename, parentpath); string const filepath = support::OnlyPath(filename); string const abspath = support::OnlyPath(absname); - Buffer const * m_buffer = buffer.getMasterBuffer(); + string const masterpath = external_in_tmpdir ? + m_buffer->temppath() : + m_buffer->filePath(); string relToMasterPath = support::OnlyPath( - support::MakeRelPath(absname, m_buffer->filePath())); + support::MakeRelPath(absname, masterpath)); if (relToMasterPath == "./") relToMasterPath.clear(); string relToParentPath = support::OnlyPath( - support::MakeRelPath(absname, buffer.filePath())); + support::MakeRelPath(absname, parentpath)); if (relToParentPath == "./") relToParentPath.clear(); result = support::subst(s, "$$FName", filename); @@ -130,64 +131,59 @@ string const doSubstitution(InsetExterna return result; } -/** update the file represented by the template. - If \param external_in_tmpdir == true, then the generated file is - place in the buffer's temporary directory. -*/ -void updateExternal(InsetExternalParams const & params, - string const & format, - Buffer const & buffer, - bool external_in_tmpdir) + +string updateExternal(InsetExternalParams const & params, + string const & format, + Buffer const & buffer, + bool external_in_tmpdir) { Template const * const et_ptr = getTemplatePtr(params); if (!et_ptr) - return; // FAILURE + return string(); // FAILURE Template const & et = *et_ptr; if (!et.automaticProduction) - return; // NOT_NEEDED + return string(); // NOT_NEEDED Template::Formats::const_iterator cit = et.formats.find(format); if (cit == et.formats.end()) - return; // FAILURE + return string(); // FAILURE Template::Format const & outputFormat = cit->second; if (outputFormat.updateResult.empty()) - return; // NOT_NEEDED + return string(); // NOT_NEEDED string from_format = et.inputFormat; if (from_format.empty()) - return; // NOT_NEEDED + return string(); // NOT_NEEDED string abs_from_file = params.filename.absFilename(); if (from_format == "*") { if (abs_from_file.empty()) - return; // NOT_NEEDED + return string(); // NOT_NEEDED // Try and ascertain the file format from its contents. from_format = support::getExtFromContents(abs_from_file); if (from_format.empty()) - return; // FAILURE + return string(); // FAILURE } string const to_format = outputFormat.updateFormat; if (to_format.empty()) - return; // NOT_NEEDED + return string(); // NOT_NEEDED if (!converters.isReachable(from_format, to_format)) { lyxerr[Debug::EXTERNAL] << "external::updateExternal. " << "Unable to convert from " << from_format << " to " << to_format << endl; - return; // FAILURE + return string(); // FAILURE } - string from_file = params.filename.outputFilename(buffer.filePath()); - // The master buffer. This is useful when there are multiple levels // of include files Buffer const * m_buffer = buffer.getMasterBuffer(); @@ -204,19 +200,18 @@ void updateExternal(InsetExternalParams lyxerr[Debug::EXTERNAL] << "external::updateExternal. " << "Unable to copy " << abs_from_file << " to " << temp_file << endl; - return; // FAILURE + return string(); // FAILURE } } - from_file = temp_file; abs_from_file = temp_file; } string const to_file = doSubstitution(params, buffer, outputFormat.updateResult, - from_file); + external_in_tmpdir); string const abs_to_file = support::MakeAbsPath(to_file, external_in_tmpdir ? m_buffer->temppath() @@ -224,19 +219,21 @@ void updateExternal(InsetExternalParams // 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(abs_from_file, abs_to_file) < 0) - return; // SUCCESS + return abs_to_file; // SUCCESS string const to_file_base = support::ChangeExtension(to_file, string()); /* bool const success = */ converters.convert(&buffer, abs_from_file, to_file_base, - from_format, to_format); - // return success + from_format, to_format); + return abs_to_file; // SUCCESS } +namespace { + string const substituteCommands(InsetExternalParams const & params, string const & input, string const & format); string const substituteOptions(InsetExternalParams const & params, @@ -263,36 +260,16 @@ int writeExternal(InsetExternalParams co << params.templatename() << endl; return 0; } - updateExternal(params, format, buffer, external_in_tmpdir); - - string from_file = params.filename.outputFilename(buffer.filePath()); - if (external_in_tmpdir && !from_file.empty()) { - // We are running stuff through LaTeX - from_file = - support::MakeAbsPath(params.filename.mangledFilename(), - buffer.getMasterBuffer()->temppath()); - } - string str = doSubstitution(params, buffer, cit->second.product, - from_file); + external_in_tmpdir); str = substituteCommands(params, str, format); str = substituteOptions(params, str, format); os << str; return int(lyx::count(str.begin(), str.end(),'\n') + 1); } - -/// Substitute meta-variables in this string -string const doSubstitution(InsetExternalParams const & params, - Buffer const & buffer, string const & s) -{ - string const buffer_path = buffer.filePath(); - string const filename = params.filename.outputFilename(buffer_path); - return doSubstitution(params, buffer, s, filename); -} - namespace { // Empty template, specialised below. template <typename TransformType> diff -p -r -U 4 -X excl.tmp lyx-1.4-clean/src/insets/ExternalSupport.h lyx-1.4-cvs/src/insets/ExternalSupport.h --- lyx-1.4-clean/src/insets/ExternalSupport.h 2003-10-07 22:25:10.000000000 +0200 +++ lyx-1.4-cvs/src/insets/ExternalSupport.h 2004-05-15 14:04:32.000000000 +0200 @@ -32,12 +32,30 @@ Template const * getTemplatePtr(InsetExt void editExternal(InsetExternalParams const & params, Buffer const & buffer); -/// Substitute meta-variables in string s, making use of params and buffer. +/** Substitute meta-variables in string \p s, making use of \p params and + \p buffer. + If \p external_in_tmpdir is true, all files are assumed to be in the + master buffers temp path, and the mangled filename is used. + Otherwise, the output filename (absolute or relative to the parent + document, as written in the .lyx file) is used. +*/ std::string const doSubstitution(InsetExternalParams const & params, Buffer const & buffer, - std::string const & s); + std::string const & s, + bool external_in_tmpdir = false); + + +/** update the file represented by the template. + If \p external_in_tmpdir == true, then the generated file is + place in the buffer's temporary directory. + \return the absolute name of the generated file. +*/ +std::string updateExternal(InsetExternalParams const &, + std::string const & format, + Buffer const &, + bool external_in_tmpdir = false); /** Write the output for a specific file format and generate any external data files. Nur in lyx-1.4-cvs/src/insets: insetexternal-2.C. diff -p -r -U 4 -X excl.tmp lyx-1.4-clean/src/insets/insetexternal.C lyx-1.4-cvs/src/insets/insetexternal.C --- lyx-1.4-clean/src/insets/insetexternal.C 2004-04-19 20:06:35.000000000 +0200 +++ lyx-1.4-cvs/src/insets/insetexternal.C 2004-05-14 19:14:01.000000000 +0200 @@ -21,8 +21,9 @@ #include "BufferView.h" #include "cursor.h" #include "debug.h" #include "dispatchresult.h" +#include "exporter.h" #include "funcrequest.h" #include "gettext.h" #include "LaTeXFeatures.h" #include "lyx_main.h" @@ -688,31 +689,38 @@ int InsetExternal::latex(Buffer const & if (cit != et.formats.end()) return external::writeExternal(params_, "PDFLaTeX", buf, os, external_in_tmpdir); } - + string const to_file = external::updateExternal(params_, + "LaTeX", buf, + external_in_tmpdir); + if (!to_file.empty()) + runparams.exportdata->addExternalFile(to_file); return external::writeExternal(params_, "LaTeX", buf, os, external_in_tmpdir); } int InsetExternal::plaintext(Buffer const & buf, ostream & os, OutputParams const &) const { + external::updateExternal(params_, "Ascii", buf); return external::writeExternal(params_, "Ascii", buf, os); } int InsetExternal::linuxdoc(Buffer const & buf, ostream & os, OutputParams const &) const { + external::updateExternal(params_, "LinuxDoc", buf); return external::writeExternal(params_, "LinuxDoc", buf, os); } int InsetExternal::docbook(Buffer const & buf, ostream & os, OutputParams const &) const { + external::updateExternal(params_, "DocBook", buf); return external::writeExternal(params_, "DocBook", buf, os); } diff -p -r -U 4 -X excl.tmp lyx-1.4-clean/src/insets/insetgraphics.C lyx-1.4-cvs/src/insets/insetgraphics.C --- lyx-1.4-clean/src/insets/insetgraphics.C 2004-05-07 13:41:40.000000000 +0200 +++ lyx-1.4-cvs/src/insets/insetgraphics.C 2004-05-14 21:57:52.000000000 +0200 @@ -57,8 +57,9 @@ TODO #include "converter.h" #include "cursor.h" #include "debug.h" #include "dispatchresult.h" +#include "exporter.h" #include "format.h" #include "funcrequest.h" #include "gettext.h" #include "LaTeXFeatures.h" @@ -92,8 +93,9 @@ using lyx::support::float_equal; using lyx::support::GetExtension; using lyx::support::getExtFromContents; using lyx::support::IsFileReadable; using lyx::support::LibFileSearch; +using lyx::support::OnlyFilename; using lyx::support::rtrim; using lyx::support::subst; using lyx::support::Systemcall; using lyx::support::unzipFile; @@ -461,9 +463,10 @@ string const InsetGraphics::prepareFile( copyFileIfNeeded(ChangeExtension(orig_file, "bb"), ChangeExtension(temp_file, "bb")); if (status == FAILURE) return orig_file; - return temp_file; + runparams.exportdata->addExternalFile(temp_file); + return OnlyFilename(temp_file); } string const unzipped_temp_file = unzippedFileName(temp_file); if (compare_timestamps(unzipped_temp_file, temp_file) > 0) { @@ -492,10 +495,13 @@ string const InsetGraphics::prepareFile( lyxerr[Debug::GRAPHICS] << "\tthe orig file is: " << orig_file << endl; - if (from == to) - return stripExtensionIfPossible(temp_file, to); + if (from == to) { + // The extension of temp_file might be != to! + runparams.exportdata->addExternalFile(temp_file); + return OnlyFilename(stripExtensionIfPossible(temp_file, to)); + } string const to_file_base = RemoveExtension(temp_file); string const to_file = ChangeExtension(to_file_base, to); @@ -506,9 +512,10 @@ string const InsetGraphics::prepareFile( lyxerr[Debug::GRAPHICS] << bformat(_("No conversion of %1$s is needed after all"), rel_file) << std::endl; - return to_file_base; + runparams.exportdata->addExternalFile(to_file); + return OnlyFilename(to_file_base); } lyxerr[Debug::GRAPHICS] << "\tThe original file is " << orig_file << "\n" @@ -518,22 +525,24 @@ string const InsetGraphics::prepareFile( string const command = "sh " + LibFileSearch("scripts", "convertDefault.sh") + ' ' + from + ':' + temp_file + ' ' + - to + ':' + to_file_base + '.' + to; + to + ':' + to_file; lyxerr[Debug::GRAPHICS] << "No converter defined! I use convertDefault.sh:\n\t" << command << endl; Systemcall one; one.startscript(Systemcall::Wait, command); - if (!IsFileReadable(ChangeExtension(to_file_base, to))) { + if (IsFileReadable(to_file)) { + runparams.exportdata->addExternalFile(to_file); + } else { string str = bformat(_("No information for converting %1$s " "format files to %2$s.\n" "Try defining a convertor in the preferences."), from, to); Alert::error(_("Could not convert image"), str); } } - return to_file_base; + return OnlyFilename(to_file_base); } int InsetGraphics::latex(Buffer const & buf, ostream & os, @@ -657,9 +667,9 @@ int InsetGraphics::linuxdoc(Buffer const } // For explanation on inserting graphics into DocBook checkout: -// http://en.tldp.org/LDP/LDP-Author-Guide/inserting-pictures.html +// http://en.tldp.org/LDP/LDP-Author-Guide/html/inserting-pictures.html // See also the docbook guide at http://www.docbook.org/ int InsetGraphics::docbook(Buffer const &, ostream & os, OutputParams const &) const {