X-Git-Url: https://git.lyx.org/gitweb/?a=blobdiff_plain;f=src%2Finsets%2FInsetCitation.cpp;h=859ceba81f4e050b65cb2c9f4c3b78dd3888c0c4;hb=0c68af937aabad17f06085f80c142065a773b216;hp=d224c5dd4945af5d40feea79ad36dca325589aee;hpb=2f4d0ae27ed43f639c75ad8b42abcfe920604eeb;p=lyx.git diff --git a/src/insets/InsetCitation.cpp b/src/insets/InsetCitation.cpp index d224c5dd49..859ceba81f 100644 --- a/src/insets/InsetCitation.cpp +++ b/src/insets/InsetCitation.cpp @@ -14,45 +14,33 @@ #include "InsetCitation.h" #include "Buffer.h" +#include "buffer_funcs.h" #include "BufferParams.h" -#include "debug.h" #include "DispatchResult.h" #include "FuncRequest.h" #include "LaTeXFeatures.h" +#include "ParIterator.h" +#include "TocBackend.h" -#include "support/fs_extras.h" +#include "support/debug.h" +#include "support/docstream.h" +#include "support/FileNameList.h" +#include "support/gettext.h" #include "support/lstrings.h" #include -#include -#include - +using namespace std; +using namespace lyx::support; namespace lyx { -using support::FileName; -using support::getStringFromVector; -using support::getVectorFromString; -using support::ltrim; -using support::prefixIs; -using support::rtrim; -using support::split; -using support::tokenPos; - -using std::endl; -using std::string; -using std::vector; - -namespace fs = boost::filesystem; - - namespace { vector const init_possible_cite_commands() { char const * const possible[] = { - "cite", "citet", "citep", "citealt", "citealp", + "cite", "nocite", "citet", "citep", "citealt", "citealp", "citeauthor", "citeyear", "citeyearpar", "citet*", "citep*", "citealt*", "citealp*", "citeauthor*", "Citet", "Citep", "Citealt", "Citealp", "Citeauthor", @@ -68,59 +56,54 @@ vector const init_possible_cite_commands() } -vector const & possible_cite_commands() +vector const & possibleCiteCommands() { static vector const possible = init_possible_cite_commands(); return possible; } -bool is_possible_cite_command(string const & input) -{ - vector const & possibles = possible_cite_commands(); - vector::const_iterator const end = possibles.end(); - return std::find(possibles.begin(), end, input) != end; -} - - -string const default_cite_command(biblio::CiteEngine engine) +// FIXME See the header for the issue. +string defaultCiteCommand(CiteEngine engine) { string str; switch (engine) { - case biblio::ENGINE_BASIC: + case ENGINE_BASIC: str = "cite"; break; - case biblio::ENGINE_NATBIB_AUTHORYEAR: + case ENGINE_NATBIB_AUTHORYEAR: str = "citet"; break; - case biblio::ENGINE_NATBIB_NUMERICAL: + case ENGINE_NATBIB_NUMERICAL: str = "citep"; break; - case biblio::ENGINE_JURABIB: + case ENGINE_JURABIB: str = "cite"; break; } return str; } - -string const - asValidLatexCommand(string const & input, biblio::CiteEngine const engine) + +string asValidLatexCommand(string const & input, CiteEngine const engine) { - string const default_str = default_cite_command(engine); - if (!is_possible_cite_command(input)) + string const default_str = defaultCiteCommand(engine); + if (!InsetCitation::isCompatibleCommand(input)) return default_str; string output; switch (engine) { - case biblio::ENGINE_BASIC: - output = default_str; + case ENGINE_BASIC: + if (input == "nocite") + output = input; + else + output = default_str; break; - case biblio::ENGINE_NATBIB_AUTHORYEAR: - case biblio::ENGINE_NATBIB_NUMERICAL: - if (input == "cite" || input == "citefield" || - input == "citetitle" || input == "cite*") + case ENGINE_NATBIB_AUTHORYEAR: + case ENGINE_NATBIB_NUMERICAL: + if (input == "cite" || input == "citefield" + || input == "citetitle" || input == "cite*") output = default_str; else if (prefixIs(input, "foot")) output = input.substr(4); @@ -128,7 +111,7 @@ string const output = input; break; - case biblio::ENGINE_JURABIB: { + case ENGINE_JURABIB: { // Jurabib does not support the 'uppercase' natbib style. if (input[0] == 'C') output = string(1, 'c') + input.substr(1); @@ -148,55 +131,16 @@ string const } -docstring const getNatbibLabel(Buffer const & buffer, +docstring complexLabel(Buffer const & buffer, string const & citeType, docstring const & keyList, docstring const & before, docstring const & after, - biblio::CiteEngine engine) + CiteEngine engine) { // Only start the process off after the buffer is loaded from file. if (!buffer.isFullyLoaded()) return docstring(); - // Cache the labels - typedef std::map CachedMap; - static CachedMap cached_keys; - - // and cache the timestamp of the bibliography files. - static std::map bibfileStatus; - - BiblioInfo biblist; - - vector const & bibfilesCache = buffer.getBibfilesCache(); - // compare the cached timestamps with the actual ones. - bool changed = false; - for (vector::const_iterator it = bibfilesCache.begin(); - it != bibfilesCache.end(); ++ it) { - FileName const f = *it; - try { - std::time_t lastw = f.lastModified(); - if (lastw != bibfileStatus[f]) { - changed = true; - bibfileStatus[f] = lastw; - } - } - catch (fs::filesystem_error & fserr) { - changed = true; - lyxerr << "Couldn't find or read bibtex file " - << f << endl; - LYXERR(Debug::DEBUG) << "Fs error: " - << fserr.what() << endl; - } - } - - // build the list only if the bibfiles have been changed - if (cached_keys[&buffer].empty() || bibfileStatus.empty() || changed) { - biblist.fillWithBibKeys(&buffer); - cached_keys[&buffer] = biblist; - } else { - // use the cached keys - biblist = cached_keys[&buffer]; - } - + BiblioInfo const & biblist = buffer.masterBibInfo(); if (biblist.empty()) return docstring(); @@ -241,16 +185,25 @@ docstring const getNatbibLabel(Buffer const & buffer, } docstring after_str; - if (!after.empty()) { - // The "after" key is appended only to the end of the whole. + // The "after" key is appended only to the end of the whole. + if (cite_type == "nocite") + after_str = " (" + _("not cited") + ')'; + else if (!after.empty()) { after_str = ", " + after; } // One day, these might be tunable (as they are in BibTeX). - char const op = '('; // opening parenthesis. - char const cp = ')'; // closing parenthesis. - // puctuation mark separating citation entries. - char const * const sep = ";"; + char op, cp; // opening and closing parenthesis. + char * sep; // punctuation mark separating citation entries. + if (engine == ENGINE_BASIC) { + op = '['; + cp = ']'; + sep = ","; + } else { + op = '('; + cp = ')'; + sep = ";"; + } docstring const op_str = ' ' + docstring(1, op); docstring const cp_str = docstring(1, cp) + ' '; @@ -271,35 +224,43 @@ docstring const getNatbibLabel(Buffer const & buffer, // authors1/; ... ; // authors_last, - if (cite_type == "cite" && engine == biblio::ENGINE_JURABIB) { - if (it == keys.begin()) - label += author + before_str + sep_str; - else - label += author + sep_str; + if (cite_type == "cite") { + if (engine == ENGINE_BASIC) { + label += *it + sep_str; + } else if (engine == ENGINE_JURABIB) { + if (it == keys.begin()) + label += author + before_str + sep_str; + else + label += author + sep_str; + } + + // nocite + } else if (cite_type == "nocite") { + label += *it + sep_str; // (authors1 ( year); ... ; // authors_last ( year, ) } else if (cite_type == "citet") { switch (engine) { - case biblio::ENGINE_NATBIB_AUTHORYEAR: + case ENGINE_NATBIB_AUTHORYEAR: label += author + op_str + before_str + year + cp + sep_str; break; - case biblio::ENGINE_NATBIB_NUMERICAL: + case ENGINE_NATBIB_NUMERICAL: label += author + op_str + before_str + '#' + *it + cp + sep_str; break; - case biblio::ENGINE_JURABIB: + case ENGINE_JURABIB: label += before_str + author + op_str + year + cp + sep_str; break; - case biblio::ENGINE_BASIC: + case ENGINE_BASIC: break; } // author, year; author, year; ... } else if (cite_type == "citep" || cite_type == "citealp") { - if (engine == biblio::ENGINE_NATBIB_NUMERICAL) { + if (engine == ENGINE_NATBIB_NUMERICAL) { label += *it + sep_str; } else { label += author + ", " + year + sep_str; @@ -309,18 +270,18 @@ docstring const getNatbibLabel(Buffer const & buffer, // authors_last year, ) } else if (cite_type == "citealt") { switch (engine) { - case biblio::ENGINE_NATBIB_AUTHORYEAR: + case ENGINE_NATBIB_AUTHORYEAR: label += author + ' ' + before_str + year + sep_str; break; - case biblio::ENGINE_NATBIB_NUMERICAL: + case ENGINE_NATBIB_NUMERICAL: label += author + ' ' + before_str + '#' + *it + sep_str; break; - case biblio::ENGINE_JURABIB: + case ENGINE_JURABIB: label += before_str + author + ' ' + year + sep_str; break; - case biblio::ENGINE_BASIC: + case ENGINE_BASIC: break; } @@ -342,7 +303,7 @@ docstring const getNatbibLabel(Buffer const & buffer, label.insert(label.size() - 1, after_str); } else { bool const add = - !(engine == biblio::ENGINE_NATBIB_NUMERICAL && + !(engine == ENGINE_NATBIB_NUMERICAL && (cite_type == "citeauthor" || cite_type == "citeyear")); if (add) @@ -356,17 +317,16 @@ docstring const getNatbibLabel(Buffer const & buffer, label = before_str + label; } - if (cite_type == "citep" || cite_type == "citeyearpar") + if (cite_type == "citep" || cite_type == "citeyearpar" || + (cite_type == "cite" && engine == ENGINE_BASIC) ) label = op + label + cp; return label; } -docstring const getBasicLabel(docstring const & keyList, docstring const & after) +docstring basicLabel(docstring const & keyList, docstring const & after) { - using support::contains; - docstring keys = keyList; docstring label; @@ -378,8 +338,9 @@ docstring const getBasicLabel(docstring const & keyList, docstring const & after keys = ltrim(split(keys, key, ',')); label += ", " + key; } - } else + } else { label = keys; + } if (!after.empty()) label += ", " + after; @@ -390,40 +351,69 @@ docstring const getBasicLabel(docstring const & keyList, docstring const & after } // anon namespace +ParamInfo InsetCitation::param_info_; + + InsetCitation::InsetCitation(InsetCommandParams const & p) : InsetCommand(p, "citation") {} -docstring const InsetCitation::generateLabel(Buffer const & buffer) const +ParamInfo const & InsetCitation::findInfo(string const & /* cmdName */) +{ + // standard cite does only take one argument if jurabib is + // not used, but jurabib extends this to two arguments, so + // we have to allow both here. InsetCitation takes care that + // LaTeX output is nevertheless correct. + if (param_info_.empty()) { + param_info_.add("after", ParamInfo::LATEX_OPTIONAL); + param_info_.add("before", ParamInfo::LATEX_OPTIONAL); + param_info_.add("key", ParamInfo::LATEX_REQUIRED); + } + return param_info_; +} + + +bool InsetCitation::isCompatibleCommand(string const & cmd) +{ + vector const & possibles = possibleCiteCommands(); + vector::const_iterator const end = possibles.end(); + return find(possibles.begin(), end, cmd) != end; +} + + +docstring InsetCitation::generateLabel() const { docstring const before = getParam("before"); docstring const after = getParam("after"); docstring label; - biblio::CiteEngine const engine = buffer.params().getEngine(); - if (engine != biblio::ENGINE_BASIC) { - label = getNatbibLabel(buffer, getCmdName(), getParam("key"), - before, after, engine); - } + CiteEngine const engine = buffer().params().citeEngine(); + label = complexLabel(buffer(), getCmdName(), getParam("key"), + before, after, engine); // Fallback to fail-safe - if (label.empty()) { - label = getBasicLabel(getParam("key"), after); - } + if (label.empty()) + label = basicLabel(getParam("key"), after); return label; } -docstring const InsetCitation::getScreenLabel(Buffer const & buffer) const +docstring InsetCitation::screenLabel() const { - biblio::CiteEngine const engine = buffer.params().getEngine(); + return cache.screen_label; +} + + +void InsetCitation::updateLabels(ParIterator const &) +{ + CiteEngine const engine = buffer().params().citeEngine(); if (cache.params == params() && cache.engine == engine) - return cache.screen_label; + return; // The label has changed, so we have to re-create it. - docstring const glabel = generateLabel(buffer); + docstring const glabel = generateLabel(); unsigned int const maxLabelChars = 45; @@ -437,24 +427,20 @@ docstring const InsetCitation::getScreenLabel(Buffer const & buffer) const cache.params = params(); cache.generated_label = glabel; cache.screen_label = label; - - return label; } -int InsetCitation::plaintext(Buffer const & buffer, odocstream & os, - OutputParams const &) const +void InsetCitation::addToToc(DocIterator const & cpit) { - docstring str; + Toc & toc = buffer().tocBackend().toc("citation"); + toc.push_back(TocItem(cpit, 0, cache.screen_label)); +} - if (cache.params == params() && - cache.engine == buffer.params().getEngine()) - str = cache.generated_label; - else - str = generateLabel(buffer); - os << str; - return str.size(); +int InsetCitation::plaintext(odocstream & os, OutputParams const &) const +{ + os << cache.generated_label; + return cache.generated_label.size(); } @@ -476,20 +462,18 @@ static docstring const cleanupWhitespace(docstring const & citelist) } -int InsetCitation::docbook(Buffer const &, odocstream & os, - OutputParams const &) const +int InsetCitation::docbook(odocstream & os, OutputParams const &) const { - os << "" + os << from_ascii("") << cleanupWhitespace(getParam("key")) - << ""; + << from_ascii(""); return 0; } -int InsetCitation::textString(Buffer const & buf, odocstream & os, - OutputParams const & op) const +void InsetCitation::textString(odocstream & os) const { - return plaintext(buf, os, op); + plaintext(os, OutputParams(0)); } @@ -497,10 +481,9 @@ int InsetCitation::textString(Buffer const & buf, odocstream & os, // the \cite command is valid. Eg, the user has natbib enabled, inputs some // citations and then changes his mind, turning natbib support off. The output // should revert to \cite[]{} -int InsetCitation::latex(Buffer const & buffer, odocstream & os, - OutputParams const &) const +int InsetCitation::latex(odocstream & os, OutputParams const &) const { - biblio::CiteEngine cite_engine = buffer.params().getEngine(); + CiteEngine cite_engine = buffer().params().citeEngine(); // FIXME UNICODE docstring const cite_str = from_utf8( asValidLatexCommand(getCmdName(), cite_engine)); @@ -509,7 +492,7 @@ int InsetCitation::latex(Buffer const & buffer, odocstream & os, docstring const & before = getParam("before"); docstring const & after = getParam("after"); - if (!before.empty() && cite_engine != biblio::ENGINE_BASIC) + if (!before.empty() && cite_engine != ENGINE_BASIC) os << '[' << before << "][" << after << ']'; else if (!after.empty()) os << '[' << after << ']'; @@ -522,18 +505,24 @@ int InsetCitation::latex(Buffer const & buffer, odocstream & os, void InsetCitation::validate(LaTeXFeatures & features) const { - switch (features.bufferParams().getEngine()) { - case biblio::ENGINE_BASIC: + switch (features.bufferParams().citeEngine()) { + case ENGINE_BASIC: break; - case biblio::ENGINE_NATBIB_AUTHORYEAR: - case biblio::ENGINE_NATBIB_NUMERICAL: + case ENGINE_NATBIB_AUTHORYEAR: + case ENGINE_NATBIB_NUMERICAL: features.require("natbib"); break; - case biblio::ENGINE_JURABIB: + case ENGINE_JURABIB: features.require("jurabib"); break; } } +docstring InsetCitation::contextMenu(BufferView const &, int, int) const +{ + return from_ascii("context-citation"); +} + + } // namespace lyx