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>
* insettext.C (doDispatch): reduce some debug blabbering

View File

@ -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 <boost/tokenizer.hpp>
#include <fstream>
#include <sstream>
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<char> Separator;
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
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;
}

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

View File

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