From 6e7b2e9016df5379857f9a88b7c065f643d96566 Mon Sep 17 00:00:00 2001 From: Angus Leeming Date: Thu, 14 Jul 2005 12:53:12 +0000 Subject: [PATCH] Forward port the name-mangling code from 1.3.x. git-svn-id: svn://svn.lyx.org/lyx/lyx-devel/trunk@10182 a592a061-630c-0410-9148-cb99ea01b6c8 --- src/insets/ChangeLog | 7 +++ src/insets/insetbibtex.C | 93 +++++++++++++++++++++++++++++++--------- src/support/ChangeLog | 8 ++++ src/support/filename.C | 39 +++++++++++++---- src/support/filename.h | 20 +++++++-- 5 files changed, 134 insertions(+), 33 deletions(-) diff --git a/src/insets/ChangeLog b/src/insets/ChangeLog index f7371690d6..31a448d434 100644 --- a/src/insets/ChangeLog +++ b/src/insets/ChangeLog @@ -1,3 +1,10 @@ +2005-07-14 Angus Leeming + + * insetbibtex.C (latex): when processing the LaTeX file in + a temp directory, copy the BibTeX databases there, mangling their + names in the process. Do this so that BibTeX can process the database + because it *really*, *really* can't handle "files with spaces". + 2005-07-14 Lars Gullik Bjønnes * insettext.C (doDispatch): reduce some debug blabbering diff --git a/src/insets/insetbibtex.C b/src/insets/insetbibtex.C index df3f6bde4b..3168106360 100644 --- a/src/insets/insetbibtex.C +++ b/src/insets/insetbibtex.C @@ -17,22 +17,31 @@ #include "dispatchresult.h" #include "debug.h" #include "funcrequest.h" -#include "LaTeXFeatures.h" #include "gettext.h" +#include "LaTeXFeatures.h" #include "metricsinfo.h" #include "outputparams.h" +#include "frontends/Alert.h" + +#include "support/filename.h" #include "support/filetools.h" #include "support/lstrings.h" +#include "support/lyxlib.h" #include "support/os.h" #include "support/path.h" +#include + #include +#include using lyx::support::AbsolutePath; using lyx::support::ascii_lowercase; using lyx::support::ChangeExtension; using lyx::support::contains; +using lyx::support::copy; +using lyx::support::FileName; using lyx::support::findtexfile; using lyx::support::IsFileReadable; using lyx::support::latex_path; @@ -126,20 +135,62 @@ int InsetBibtex::latex(Buffer const & buffer, ostream & os, // 3. \btPrint{Cited|NotCited|All} // 4. \end{btSect} - // the database string - string adb; - string db_in = getContents(); - db_in = split(db_in, adb, ','); - // If we generate in a temp dir, we might need to give an - // absolute path there. This is a bit complicated since we can - // have a comma-separated list of bibliographies - string db_out; - while (!adb.empty()) { - db_out += latex_path(normalize_name(buffer, runparams, adb, ".bib")); - db_out += ','; - db_in = split(db_in, adb,','); + // Database(s) + // If we are processing the LaTeX file in a temp directory then + // copy the .bib databases to this temp directory, mangling their + // names in the process. Store this mangled name in the list of + // all databases. + // (We need to do all this because BibTeX *really*, *really* + // can't handle "files with spaces" and Windows users tend to + // use such filenames.) + // Otherwise, store the (maybe absolute) path to the original, + // unmangled database name. + typedef boost::char_separator Separator; + typedef boost::tokenizer Tokenizer; + + Separator const separator(","); + Tokenizer const tokens(getContents(), separator); + Tokenizer::const_iterator const begin = tokens.begin(); + Tokenizer::const_iterator const end = tokens.end(); + + std::ostringstream dbs; + for (Tokenizer::const_iterator it = begin; it != end; ++it) { + string const input = trim(*it); + string database = + normalize_name(buffer, runparams, input, ".bib"); + string const in_file = database + ".bib"; + + if (!runparams.nice && IsFileReadable(in_file)) { + + database = FileName(database).mangledFilename(); + string const out_file = MakeAbsPath(database + ".bib", + buffer.temppath()); + + bool const success = copy(in_file, out_file); + if (!success) { + lyxerr << "Failed to copy '" << in_file + << "' to '" << out_file << "'" + << endl; + } + } + + if (it != begin) + dbs << ','; + dbs << latex_path(database); + } + string const db_out = dbs.str(); + + // Post this warning only once. + static bool warned_about_spaces = false; + if (!warned_about_spaces && + runparams.nice && db_out.find(' ') != string::npos) { + warned_about_spaces = true; + + Alert::warning(_("Export Warning!"), + _("There are spaces in the paths to your BibTeX databases.\n" + "BibTeX will be unable to find them.")); + } - db_out = rtrim(db_out, ","); // Style-Options string style = getOptions(); // maybe empty! and with bibtotoc @@ -152,16 +203,16 @@ int InsetBibtex::latex(Buffer const & buffer, ostream & os, } // line count - int i = 0; + int nlines = 0; if (!style.empty()) { os << "\\bibliographystyle{" << latex_path(normalize_name(buffer, runparams, style, ".bst")) << "}\n"; - i += 1; + nlines += 1; } - if (buffer.params().use_bibtopic){ + if (!db_out.empty() && buffer.params().use_bibtopic){ os << "\\begin{btSect}{" << db_out << "}\n"; string btprint = getSecOptions(); if (btprint.empty()) @@ -169,7 +220,7 @@ int InsetBibtex::latex(Buffer const & buffer, ostream & os, btprint = "btPrintCited"; os << "\\" << btprint << "\n" << "\\end{btSect}\n"; - i += 3; + nlines += 3; } // bibtotoc-Option @@ -197,12 +248,12 @@ int InsetBibtex::latex(Buffer const & buffer, ostream & os, } } - if (!buffer.params().use_bibtopic){ + if (!db_out.empty() && !buffer.params().use_bibtopic){ os << "\\bibliography{" << db_out << "}\n"; - i += 1; + nlines += 1; } - return i; + return nlines; } diff --git a/src/support/ChangeLog b/src/support/ChangeLog index 52cf9c73ae..9698f22f2d 100644 --- a/src/support/ChangeLog +++ b/src/support/ChangeLog @@ -1,3 +1,11 @@ +2005-07-14 Angus Leeming + + * filename.[Ch] (mangledFilename): add an optional "dir" parameter + that is used to help determine the length of the mangled file name. + Do this because MiKTeX's YAP (version 2.4.1803) will crash if the string + referencing the file name in the .dvi file is "too long". MikTeX bug: + http://sourceforge.net/tracker/index.php?func=detail&aid=1238065&group_id=10783&atid=110783 + 2005-07-10 Georg Baum * filetools.[Ch] (latex_path): convert boolean exclude_extension diff --git a/src/support/filename.C b/src/support/filename.C index f72073c3b1..3019db3d80 100644 --- a/src/support/filename.C +++ b/src/support/filename.C @@ -66,7 +66,7 @@ string const FileName::outputFilename(string const & path) const } -string const FileName::mangledFilename() const +string const FileName::mangledFilename(std::string const & dir) const { // We need to make sure that every FileName instance for a given // filename returns the same mangled name. @@ -86,21 +86,42 @@ string const FileName::mangledFilename() const 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(name_)); -#if defined(__CYGWIN__) || defined(__CYGWIN32__) || defined(_WIN32) - // Mangle the drive letter in a Windows-style path. - if (mname.size() >= 2 && mname[1] == ':') - mname[1] = '_'; -#endif - // 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 = s.str() + mname; + s << counter++ << mname; + mname = s.str(); + + // 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, 160 characters for the file name itself. + // (Erring on the side of caution.) + string::size_type max_length = 160; + if (dir.size() - 1 < max_length) { + // If dir.size() > max_length, all bets are off anyway. + // "+ 1" for the directory separator. + max_length -= dir.size() + 1; + + // 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 (mname.size() > max_length) { + int const half = (int(max_length) / 2) - 2; + if (half > 0) { + mname = mname.substr(0, half) + "___" + + mname.substr(mname.size() - half); + } + } + } + mangledNames[name_] = mname; return mname; } diff --git a/src/support/filename.h b/src/support/filename.h index 06b164c2e4..0448d3db50 100644 --- a/src/support/filename.h +++ b/src/support/filename.h @@ -43,15 +43,29 @@ public: std::string const relFilename(std::string const & buffer_path = std::string()) const; /// \param buf_path if empty, uses `pwd` std::string const outputFilename(std::string const & buf_path = std::string()) const; - /** \return a mangled version of the absolute file name, + + /** @returns a mangled representation of the absolute file name * suitable for use in the temp dir when, for example, converting * an image file to another format. + * + * @param dir the directory that will contain this file with + * its mangled name. This information is used by the mangling + * algorithm when determining the maximum allowable length of + * the mangled name. + * + * An example of a mangled name: + * C:/foo bar/baz.eps -> 0C__foo_bar_baz.eps + * * It is guaranteed that * - two different filenames have different mangled names * - two FileName instances with the same filename have identical - * mangled names + * mangled names. + * + * Only the mangled file name is returned. It is not prepended + * with @c dir. */ - std::string const mangledFilename() const; + std::string const + mangledFilename(std::string const & dir = std::string()) const; /// \return true if the file is compressed. bool isZipped() const; -- 2.39.5