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
This commit is contained in:
Angus Leeming 2005-07-14 12:53:12 +00:00
parent 8120816f1a
commit 6e7b2e9016
5 changed files with 134 additions and 33 deletions

View File

@ -1,3 +1,10 @@
2005-07-14 Angus Leeming <leeming@lyx.org>
* 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 <larsbj@lyx.org> 2005-07-14 Lars Gullik Bjønnes <larsbj@lyx.org>
* insettext.C (doDispatch): reduce some debug blabbering * insettext.C (doDispatch): reduce some debug blabbering

View File

@ -17,22 +17,31 @@
#include "dispatchresult.h" #include "dispatchresult.h"
#include "debug.h" #include "debug.h"
#include "funcrequest.h" #include "funcrequest.h"
#include "LaTeXFeatures.h"
#include "gettext.h" #include "gettext.h"
#include "LaTeXFeatures.h"
#include "metricsinfo.h" #include "metricsinfo.h"
#include "outputparams.h" #include "outputparams.h"
#include "frontends/Alert.h"
#include "support/filename.h"
#include "support/filetools.h" #include "support/filetools.h"
#include "support/lstrings.h" #include "support/lstrings.h"
#include "support/lyxlib.h"
#include "support/os.h" #include "support/os.h"
#include "support/path.h" #include "support/path.h"
#include <boost/tokenizer.hpp>
#include <fstream> #include <fstream>
#include <sstream>
using lyx::support::AbsolutePath; using lyx::support::AbsolutePath;
using lyx::support::ascii_lowercase; using lyx::support::ascii_lowercase;
using lyx::support::ChangeExtension; using lyx::support::ChangeExtension;
using lyx::support::contains; using lyx::support::contains;
using lyx::support::copy;
using lyx::support::FileName;
using lyx::support::findtexfile; using lyx::support::findtexfile;
using lyx::support::IsFileReadable; using lyx::support::IsFileReadable;
using lyx::support::latex_path; using lyx::support::latex_path;
@ -126,20 +135,62 @@ int InsetBibtex::latex(Buffer const & buffer, ostream & os,
// 3. \btPrint{Cited|NotCited|All} // 3. \btPrint{Cited|NotCited|All}
// 4. \end{btSect} // 4. \end{btSect}
// the database string // Database(s)
string adb; // If we are processing the LaTeX file in a temp directory then
string db_in = getContents(); // copy the .bib databases to this temp directory, mangling their
db_in = split(db_in, adb, ','); // names in the process. Store this mangled name in the list of
// If we generate in a temp dir, we might need to give an // all databases.
// absolute path there. This is a bit complicated since we can // (We need to do all this because BibTeX *really*, *really*
// have a comma-separated list of bibliographies // can't handle "files with spaces" and Windows users tend to
string db_out; // use such filenames.)
while (!adb.empty()) { // Otherwise, store the (maybe absolute) path to the original,
db_out += latex_path(normalize_name(buffer, runparams, adb, ".bib")); // unmangled database name.
db_out += ','; typedef boost::char_separator<char> Separator;
db_in = split(db_in, adb,','); typedef boost::tokenizer<Separator> 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 // Style-Options
string style = getOptions(); // maybe empty! and with bibtotoc string style = getOptions(); // maybe empty! and with bibtotoc
@ -152,16 +203,16 @@ int InsetBibtex::latex(Buffer const & buffer, ostream & os,
} }
// line count // line count
int i = 0; int nlines = 0;
if (!style.empty()) { if (!style.empty()) {
os << "\\bibliographystyle{" os << "\\bibliographystyle{"
<< latex_path(normalize_name(buffer, runparams, style, ".bst")) << latex_path(normalize_name(buffer, runparams, style, ".bst"))
<< "}\n"; << "}\n";
i += 1; nlines += 1;
} }
if (buffer.params().use_bibtopic){ if (!db_out.empty() && buffer.params().use_bibtopic){
os << "\\begin{btSect}{" << db_out << "}\n"; os << "\\begin{btSect}{" << db_out << "}\n";
string btprint = getSecOptions(); string btprint = getSecOptions();
if (btprint.empty()) if (btprint.empty())
@ -169,7 +220,7 @@ int InsetBibtex::latex(Buffer const & buffer, ostream & os,
btprint = "btPrintCited"; btprint = "btPrintCited";
os << "\\" << btprint << "\n" os << "\\" << btprint << "\n"
<< "\\end{btSect}\n"; << "\\end{btSect}\n";
i += 3; nlines += 3;
} }
// bibtotoc-Option // 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"; os << "\\bibliography{" << db_out << "}\n";
i += 1; nlines += 1;
} }
return i; return nlines;
} }

View File

@ -1,3 +1,11 @@
2005-07-14 Angus Leeming <leeming@lyx.org>
* 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 <Georg.Baum@post.rwth-aachen.de> 2005-07-10 Georg Baum <Georg.Baum@post.rwth-aachen.de>
* filetools.[Ch] (latex_path): convert boolean exclude_extension * filetools.[Ch] (latex_path): convert boolean exclude_extension

View File

@ -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 // We need to make sure that every FileName instance for a given
// filename returns the same mangled name. // filename returns the same mangled name.
@ -86,21 +86,42 @@ string const FileName::mangledFilename() const
mname = subst(mname, ".", "_"); mname = subst(mname, ".", "_");
// Replace ' ' in the file name with '_' // Replace ' ' in the file name with '_'
mname = subst(mname, " ", "_"); mname = subst(mname, " ", "_");
// Replace ':' in the file name with '_'
mname = subst(mname, ":", "_");
// Add the extension back on // Add the extension back on
mname = ChangeExtension(mname, GetExtension(name_)); 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 // Prepend a counter to the filename. This is necessary to make
// the mangled name unique. // the mangled name unique.
static int counter = 0; static int counter = 0;
std::ostringstream s; std::ostringstream s;
s << counter++; s << counter++ << mname;
mname = s.str() + 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; mangledNames[name_] = mname;
return mname; return mname;
} }

View File

@ -43,15 +43,29 @@ public:
std::string const relFilename(std::string const & buffer_path = std::string()) const; std::string const relFilename(std::string const & buffer_path = std::string()) const;
/// \param buf_path if empty, uses `pwd` /// \param buf_path if empty, uses `pwd`
std::string const outputFilename(std::string const & buf_path = std::string()) const; 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 * suitable for use in the temp dir when, for example, converting
* an image file to another format. * 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 * It is guaranteed that
* - two different filenames have different mangled names * - two different filenames have different mangled names
* - two FileName instances with the same filename have identical * - 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. /// \return true if the file is compressed.
bool isZipped() const; bool isZipped() const;