Angus Leeming wrote:
If you can confirm that it fixes your problems then I'll move it onto the wiki.
It resolved the problem on my one test document (the one I sent you), and at this stage of my career (acute laziness) I'm happy to generalize from samples of size 1. So, yes, I think the problem is fixed.
Great!
Jean-Marc, are you happy for me to commit this patch? Angus
Index: src/insets/insetgraphics.C =================================================================== RCS file: /usr/local/lyx/cvsroot/lyx-devel/src/insets/insetgraphics.C,v retrieving revision 1.146.2.12 diff -u -a -u -r1.146.2.12 insetgraphics.C --- src/insets/insetgraphics.C 4 Jul 2005 11:26:41 -0000 1.146.2.12 +++ src/insets/insetgraphics.C 9 Jul 2005 09:32:58 -0000 @@ -91,6 +91,7 @@ #include "BoostFormat.h" #include <algorithm> // For the std::max +#include <map> using std::ostream; using std::endl; @@ -523,6 +524,60 @@ } +namespace { + +// Create a human-readable filename version of the input absolute path. +// Eg /home/angus/foo\ bar/image.eps -> ID_home_angus_foo_bar_image.eps +// where ID is a unique integer ID. +string const mangled_filename(string const & input, int const max_length) +{ + // We need to make sure that every FileName instance for a given + // filename returns the same mangled name. + typedef std::map<string, string> MangledMap; + static MangledMap mangledNames; + MangledMap::const_iterator const it = mangledNames.find(input); + if (it != mangledNames.end()) + return (*it).second; + + // Now the real work + string mname = os::internal_path(input); + // Remove the extension. + mname = ChangeExtension(input, string()); + // Replace '/' in the file name with '_' + mname = subst(mname, "/", "_"); + // Replace '.' in the file name with '_' + mname = subst(mname, ".", "_"); + // Replace ' ' in the file name with '_' + mname = subst(mname, " ", "_"); + // Replace ':' in the file name with '_' + mname = subst(mname, ":", "_"); + // Add the extension back on + mname = ChangeExtension(mname, GetExtension(input)); + + // Prepend a counter to the filename. This is necessary to make + // the mangled name unique. + static int counter = 0; + std::ostringstream s; + s << counter++ << mname; + mname = STRCONV(s.str()); + + // If the mangled file name is too long, hack it to fit. + // We know we're guaranteed to have a unique file name because + // of the counter. + if (int(mname.size()) > max_length) { + int const half = (max_length / 2) - 2; + if (half > 0) { + mname = mname.substr(0, half) + "___" + + mname.substr(mname.size() - half); + } + } + mangledNames[input] = mname; + return mname; +} + +} + + string const InsetGraphics::prepareFile(Buffer const * buf) const { // LaTeX can cope if the graphics file doesn't exist, so just @@ -619,37 +674,30 @@ << "\tthe orig file is: " << orig_file_with_path << endl; if (lyxrc.use_tempdir) { - string const ext_tmp = GetExtension(orig_file_with_path); - // without ext and / - temp_file = subst( - ChangeExtension(orig_file_with_path, string()), "/", "_"); - // Replace ' ' in the file name with '_' - temp_file = subst(temp_file, " ", "_"); - // without dots and again with ext - temp_file = ChangeExtension( - subst(temp_file, ".", "_"), ext_tmp); - -#if defined(__CYGWIN__) || defined(__CYGWIN32__) || defined(_WIN32) - // Mangle the drive letter in a Windows-style path. - if (temp_file.size() >= 2 && temp_file[1] == ':') - temp_file[1] = '_'; -#endif - - // now we have any_dir_file.ext + // Experiments show that MiKTeX's YAP (version 2.4.1803) + // will crash if the string referencing the file name in + // the .dvi file is longer than 220 characters. + // This string contains about 50 chars-worth of other data, + // leaving us, say, 165 characters for the file name itself. + int const max_length = 165 - (int(buf->tmppath.size()) + 1); + temp_file = mangled_filename(orig_file_with_path, max_length); temp_file = MakeAbsPath(temp_file, buf->tmppath); + lyxerr[Debug::GRAPHICS] << "\tchanged to: " << temp_file << endl; - // if the file doen't exists, copy it into the tempdir + // if the file doesn't exist, copy it into the tempdir if (file_has_changed || !IsFileReadable(temp_file)) { bool const success = lyx::copy(orig_file_with_path, temp_file); lyxerr[Debug::GRAPHICS] - << "\tcopying from " << orig_file_with_path << " to " + << "\tcopying from " + << orig_file_with_path << " to " << temp_file << (success ? " succeeded\n" : " failed\n"); if (!success) { - Alert::alert(_("Cannot copy file"), orig_file_with_path, - _("into tempdir")); + Alert::alert(_("Cannot copy file"), + orig_file_with_path, + _("into tempdir")); return orig_file; } }