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
 {

Reply via email to