X-Git-Url: https://git.lyx.org/gitweb/?a=blobdiff_plain;f=src%2Finsets%2FInsetBibtex.cpp;h=40632057697579d6e06e7c325f73846043fbc884;hb=2c357c1d23b7b83839a9beb8225d4f1ae4f793b4;hp=726b93e234bbfc73b60a8fbe25c1141e027f596c;hpb=9383f4c3c6f9cfab2d658701ba66e2b54cd68bea;p=lyx.git diff --git a/src/insets/InsetBibtex.cpp b/src/insets/InsetBibtex.cpp index 726b93e234..4063205769 100644 --- a/src/insets/InsetBibtex.cpp +++ b/src/insets/InsetBibtex.cpp @@ -16,10 +16,9 @@ #include "Buffer.h" #include "BufferParams.h" #include "DispatchResult.h" -#include "support/debug.h" +#include "EmbeddedFiles.h" #include "Encoding.h" #include "FuncRequest.h" -#include "support/gettext.h" #include "LaTeXFeatures.h" #include "MetricsInfo.h" #include "OutputParams.h" @@ -27,45 +26,24 @@ #include "frontends/alert.h" +#include "support/debug.h" #include "support/ExceptionMessage.h" #include "support/docstream.h" -#include "support/FileNameList.h" #include "support/filetools.h" +#include "support/gettext.h" #include "support/lstrings.h" -#include "support/lyxlib.h" #include "support/os.h" #include "support/Path.h" #include "support/textutils.h" #include +#include using namespace std; +using namespace lyx::support; namespace lyx { -using support::absolutePath; -using support::ascii_lowercase; -using support::changeExtension; -using support::contains; -using support::copy; -using support::DocFileName; -using support::FileName; -using support::FileNameList; -using support::findtexfile; -using support::isValidLaTeXFilename; -using support::latex_path; -using support::ltrim; -using support::makeAbsPath; -using support::makeRelPath; -using support::prefixIs; -using support::removeExtension; -using support::rtrim; -using support::split; -using support::subst; -using support::tokenPos; -using support::trim; -using support::lowercase; - namespace Alert = frontend::Alert; namespace os = support::os; @@ -75,12 +53,12 @@ InsetBibtex::InsetBibtex(InsetCommandParams const & p) {} -CommandInfo const * InsetBibtex::findInfo(std::string const & /* cmdName */) +CommandInfo const * InsetBibtex::findInfo(string const & /* cmdName */) { static const char * const paramnames[] = - {"options", "btprint", "bibfiles", ""}; - static const bool isoptional[] = {true, true, false}; - static const CommandInfo info = {3, paramnames, isoptional}; + {"options", "btprint", "bibfiles", "embed", ""}; + static const bool isoptional[] = {true, true, false, false}; + static const CommandInfo info = {4, paramnames, isoptional}; return &info; } @@ -103,15 +81,57 @@ void InsetBibtex::doDispatch(Cursor & cur, FuncRequest & cmd) cur.noUpdate(); break; } - } catch (support::ExceptionMessage const & message) { - if (message.type_ == support::WarningException) { + } catch (ExceptionMessage const & message) { + if (message.type_ == WarningException) { Alert::warning(message.title_, message.details_); cur.noUpdate(); } else throw message; break; } + // + InsetCommandParams orig = params(); + // returned "embed" is composed of "true" or "false", which needs to be adjusted + string tmp; + string emb; + + string newBibfiles; + string newEmbedStatus; + + string bibfiles = to_utf8(p["bibfiles"]); + string embedStatus = to_utf8(p["embed"]); + + bibfiles = split(bibfiles, tmp, ','); + embedStatus = split(embedStatus, emb, ','); + while (!tmp.empty()) { + EmbeddedFile file(changeExtension(tmp, "bib"), cur.buffer().filePath()); + if (!newBibfiles.empty()) + newBibfiles += ","; + newBibfiles += tmp; + if (!newEmbedStatus.empty()) + newEmbedStatus += ","; + if (emb == "true") + newEmbedStatus += file.inzipName(); + // Get next file name + bibfiles = split(bibfiles, tmp, ','); + embedStatus = split(embedStatus, emb, ','); + } + LYXERR(Debug::FILES, "Update parameters from " << p["bibfiles"] + << " " << p["embed"] << " to " << newBibfiles << " " + << newEmbedStatus); + p["bibfiles"] = from_utf8(newBibfiles); + p["embed"] = from_utf8(newEmbedStatus); + setParams(p); + try { + // test parameter and copy files + getFiles(cur.buffer()); + } catch (ExceptionMessage const & message) { + Alert::error(message.title_, message.details_); + // do not set parameter if an error happens + setParams(orig); + break; + } cur.buffer().updateBibfilesCache(); break; } @@ -135,7 +155,7 @@ string normalizeName(Buffer const & buffer, OutputParams const & runparams, string const & name, string const & ext) { string const fname = makeAbsPath(name, buffer.filePath()).absFilename(); - if (absolutePath(name) || !FileName(fname + ext).isReadableFile()) + if (FileName(name).isAbsolute() || !FileName(fname + ext).isReadableFile()) return name; if (!runparams.nice) return fname; @@ -171,22 +191,12 @@ int InsetBibtex::latex(Buffer const & buffer, odocstream & os, // 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(from_ascii(",").c_str()); - // The tokenizer must not be called with temporary strings, since - // it does not make a copy and uses iterators of the string further - // down. getParam returns a reference, so this is OK. - Tokenizer const tokens(getParam("bibfiles"), separator); - Tokenizer::const_iterator const begin = tokens.begin(); - Tokenizer::const_iterator const end = tokens.end(); - + EmbeddedFileList const bibs = getFiles(buffer); + EmbeddedFileList::const_iterator it = bibs.begin(); + EmbeddedFileList::const_iterator it_end = bibs.end(); odocstringstream dbs; - for (Tokenizer::const_iterator it = begin; it != end; ++it) { - docstring const input = trim(*it); - // FIXME UNICODE - string utf8input = to_utf8(input); + for (; it != it_end; ++it) { + string utf8input = removeExtension(it->availableFile().absFilename()); string database = normalizeName(buffer, runparams, utf8input, ".bib"); FileName const try_in_file(makeAbsPath(database + ".bib", buffer.filePath())); @@ -201,7 +211,7 @@ int InsetBibtex::latex(Buffer const & buffer, odocstream & os, FileName const out_file = makeAbsPath(database + ".bib", buffer.masterBuffer()->temppath()); - bool const success = copy(in_file, out_file); + bool const success = in_file.copyTo(out_file); if (!success) { lyxerr << "Failed to copy '" << in_file << "' to '" << out_file << "'" @@ -215,7 +225,7 @@ int InsetBibtex::latex(Buffer const & buffer, odocstream & os, from_utf8(database)); } - if (it != begin) + if (it != bibs.begin()) dbs << ','; // FIXME UNICODE dbs << from_utf8(latex_path(database)); @@ -260,7 +270,7 @@ int InsetBibtex::latex(Buffer const & buffer, odocstream & os, base = removeExtension(in_file.mangledFilename()); FileName const out_file(makeAbsPath(base + ".bst", buffer.masterBuffer()->temppath())); - bool const success = copy(in_file, out_file); + bool const success = in_file.copyTo(out_file); if (!success) { lyxerr << "Failed to copy '" << in_file << "' to '" << out_file << "'" @@ -320,6 +330,11 @@ int InsetBibtex::latex(Buffer const & buffer, odocstream & os, } if (!db_out.empty() && !buffer.params().use_bibtopic){ + docstring btprint = getParam("btprint"); + if (btprint == "btPrintAll") { + os << "\\nocite{*}\n"; + nlines += 1; + } os << "\\bibliography{" << db_out << "}\n"; nlines += 1; } @@ -328,27 +343,43 @@ int InsetBibtex::latex(Buffer const & buffer, odocstream & os, } -FileNameList const InsetBibtex::getFiles(Buffer const & buffer) const +EmbeddedFileList const InsetBibtex::getFiles(Buffer const & buffer) const { FileName path(buffer.filePath()); - support::PathChanger p(path); + PathChanger p(path); - FileNameList vec; + EmbeddedFileList vec; string tmp; + string emb; // FIXME UNICODE string bibfiles = to_utf8(getParam("bibfiles")); + string embedStatus = to_utf8(getParam("embed")); bibfiles = split(bibfiles, tmp, ','); + embedStatus = split(embedStatus, emb, ','); while (!tmp.empty()) { - FileName const file = findtexfile(changeExtension(tmp, "bib"), "bib"); - LYXERR(Debug::LATEX, "Bibfile: " << file); - - // If we didn't find a matching file name just fail silently - if (!file.empty()) + if (!emb.empty()) { + EmbeddedFile file(changeExtension(tmp, "bib"), buffer.filePath()); + // If the file structure is correct, this should not fail. + file.setEmbed(true); + file.enable(buffer.embedded(), &buffer); vec.push_back(file); + } else { + // this includes the cases when the embed parameter is empty + FileName const file = findtexfile(changeExtension(tmp, "bib"), "bib"); + + // If we didn't find a matching file name just fail silently + if (!file.empty()) { + EmbeddedFile efile = EmbeddedFile(file.absFilename(), buffer.filePath()); + efile.setEmbed(false); + efile.enable(buffer.embedded(), &buffer); + vec.push_back(efile); + } + } // Get next file name bibfiles = split(bibfiles, tmp, ','); + embedStatus = split(embedStatus, emb, ','); } return vec; @@ -596,8 +627,8 @@ namespace { void InsetBibtex::fillWithBibKeys(Buffer const & buffer, BiblioInfo & keylist, InsetIterator const & /*di*/) const { - FileNameList const files = getFiles(buffer); - for (vector::const_iterator it = files.begin(); + EmbeddedFileList const files = getFiles(buffer); + for (vector::const_iterator it = files.begin(); it != files.end(); ++ it) { // This bibtex parser is a first step to parse bibtex files // more precisely. @@ -618,8 +649,8 @@ void InsetBibtex::fillWithBibKeys(Buffer const & buffer, // InsetBibitem can generate non-ASCII keys, and nonstandard // 8bit clean bibtex forks exist. - idocfstream ifs(it->toFilesystemEncoding().c_str(), - std::ios_base::in, + idocfstream ifs(it->availableFile().toFilesystemEncoding().c_str(), + ios_base::in, buffer.params().encoding().iconvName()); char_type ch; @@ -642,7 +673,7 @@ void InsetBibtex::fillWithBibKeys(Buffer const & buffer, if (entryType == from_ascii("comment")) { - ifs.ignore(std::numeric_limits::max(), '\n'); + ifs.ignore(numeric_limits::max(), '\n'); continue; } @@ -709,8 +740,7 @@ void InsetBibtex::fillWithBibKeys(Buffer const & buffer, docstring value; docstring commaNewline; docstring data; - BibTeXInfo keyvalmap; - keyvalmap.entryType = entryType; + BibTeXInfo keyvalmap(key, entryType); bool readNext = removeWSAndComma(ifs); @@ -736,15 +766,13 @@ void InsetBibtex::fillWithBibKeys(Buffer const & buffer, keyvalmap[name] = value; data += "\n\n" + value; - keylist.fieldNames.insert(name); + keylist.addFieldName(name); readNext = removeWSAndComma(ifs); } // add the new entry - keylist.entryTypes.insert(entryType); - keyvalmap.allData = data; - keyvalmap.isBibTeX = true; - keyvalmap.bibKey = key; + keylist.addEntryType(entryType); + keyvalmap.setAllData(data); keylist[key] = keyvalmap; } } //< searching '@' @@ -795,4 +823,41 @@ void InsetBibtex::validate(LaTeXFeatures & features) const } +void InsetBibtex::registerEmbeddedFiles(Buffer const & buffer, EmbeddedFileList & files) const +{ + EmbeddedFileList const dbs = getFiles(buffer); + for (vector::const_iterator it = dbs.begin(); + it != dbs.end(); ++ it) + files.registerFile(*it, this, buffer); +} + + +void InsetBibtex::updateEmbeddedFile(Buffer const & buf, EmbeddedFile const & file) +{ + // look for the item and update status + docstring bibfiles; + docstring embed; + + bool first = true; + EmbeddedFileList dbs = getFiles(buf); + for (EmbeddedFileList::iterator it = dbs.begin(); + it != dbs.end(); ++ it) { + // update from file + if (it->absFilename() == file.absFilename()) + it->setEmbed(file.embedded()); + // write parameter string + if (!first) { + bibfiles += ','; + embed += ','; + } else + first = false; + bibfiles += from_utf8(it->outputFilename(buf.filePath())); + if (it->embedded()) + embed += from_utf8(it->inzipName()); + } + setParam("bibfiles", bibfiles); + setParam("embed", embed); +} + + } // namespace lyx