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;
                        }
                }

Reply via email to