X-Git-Url: https://git.lyx.org/gitweb/?a=blobdiff_plain;ds=sidebyside;f=src%2Finsets%2FInsetBibitem.cpp;h=b16687e7d70a2769af07323d81c88536cbbfa935;hb=7d38a4d126e8e2dab08c6a47947b913921c3f083;hp=a679dd6dbdd8539b6dae42e4613d2e0524d33887;hpb=c355edfb6da71b5efc9ed1ce548bd206ad9f57cb;p=lyx.git diff --git a/src/insets/InsetBibitem.cpp b/src/insets/InsetBibitem.cpp index a679dd6dbd..b16687e7d7 100644 --- a/src/insets/InsetBibitem.cpp +++ b/src/insets/InsetBibitem.cpp @@ -15,26 +15,34 @@ #include "BiblioInfo.h" #include "Buffer.h" +#include "Cursor.h" #include "buffer_funcs.h" #include "BufferParams.h" #include "BufferView.h" #include "Counters.h" #include "DispatchResult.h" +#include "Encoding.h" #include "FuncRequest.h" #include "InsetIterator.h" #include "InsetList.h" +#include "Language.h" #include "Lexer.h" #include "output_xhtml.h" +#include "OutputParams.h" #include "Paragraph.h" #include "ParagraphList.h" +#include "ParIterator.h" #include "TextClass.h" #include "frontends/alert.h" +#include "support/lassert.h" #include "support/convert.h" +#include "support/debug.h" #include "support/docstream.h" #include "support/gettext.h" #include "support/lstrings.h" +#include "support/mutex.h" using namespace std; using namespace lyx::support; @@ -43,23 +51,29 @@ namespace lyx { int InsetBibitem::key_counter = 0; +static Mutex counter_mutex; docstring const key_prefix = from_ascii("key-"); -InsetBibitem::InsetBibitem(Buffer const & buf, InsetCommandParams const & p) - : InsetCommand(p, "bibitem") +InsetBibitem::InsetBibitem(Buffer * buf, InsetCommandParams const & p) + : InsetCommand(buf, p) { - Inset::setBuffer(const_cast(buf)); - buffer_->invalidateBibinfoCache(); - if (getParam("key").empty()) + buffer().invalidateBibinfoCache(); + if (getParam("key").empty()) { + Mutex::Locker lock(&counter_mutex); setParam("key", key_prefix + convert(++key_counter)); + } } InsetBibitem::~InsetBibitem() { - if (isBufferValid()) + if (isBufferLoaded()) { + /* We do not use buffer() because Coverity believes that this + * may throw an exception. Actually this code path is not + * taken when buffer_ == 0 */ buffer_->invalidateBibinfoCache(); + } } @@ -71,14 +85,11 @@ void InsetBibitem::initView() void InsetBibitem::updateCommand(docstring const & new_key, bool) { - docstring const old_key = getParam("key"); docstring key = new_key; - vector bibkeys = buffer().masterBibInfo().getKeys(); - int i = 1; - if (find(bibkeys.begin(), bibkeys.end(), key) != bibkeys.end()) { + int i = 1; // generate unique label key = new_key + '-' + convert(i); while (find(bibkeys.begin(), bibkeys.end(), key) != bibkeys.end()) { @@ -90,8 +101,7 @@ void InsetBibitem::updateCommand(docstring const & new_key, bool) "it will be changed to %2$s."), new_key, key)); } setParam("key", key); - - buffer().updateLabels(); + buffer().invalidateBibinfoCache(); } @@ -99,8 +109,12 @@ ParamInfo const & InsetBibitem::findInfo(string const & /* cmdName */) { static ParamInfo param_info_; if (param_info_.empty()) { - param_info_.add("label", ParamInfo::LATEX_OPTIONAL); - param_info_.add("key", ParamInfo::LATEX_REQUIRED); + param_info_.add("label", ParamInfo::LATEX_OPTIONAL, + ParamInfo::HANDLING_LATEXIFY); + param_info_.add("key", ParamInfo::LATEX_REQUIRED, + ParamInfo::ParamHandling(ParamInfo::HANDLING_ESCAPE + | ParamInfo::HANDLING_LTRIM)); + param_info_.add("literal", ParamInfo::LYX_INTERNAL); } return param_info_; } @@ -108,23 +122,45 @@ ParamInfo const & InsetBibitem::findInfo(string const & /* cmdName */) void InsetBibitem::doDispatch(Cursor & cur, FuncRequest & cmd) { - switch (cmd.action) { + switch (cmd.action()) { case LFUN_INSET_MODIFY: { InsetCommandParams p(BIBITEM_CODE); - InsetCommand::string2params("bibitem", to_utf8(cmd.argument()), p); + InsetCommand::string2params(to_utf8(cmd.argument()), p); if (p.getCmdName().empty()) { - cur.noUpdate(); + cur.noScreenUpdate(); break; } + + cur.recordUndo(); + docstring const & old_key = params()["key"]; + docstring const & old_label = params()["label"]; + docstring const & old_literal = params()["literal"]; + docstring label = p["label"]; + docstring literal = p["literal"]; + + if (old_label != label) { + p["label"] = label; + cur.forceBufferUpdate(); + buffer().invalidateBibinfoCache(); + } setParam("label", p["label"]); + + if (old_literal != literal) { + p["literal"] = literal; + cur.forceBufferUpdate(); + buffer().invalidateBibinfoCache(); + } + setParam("literal", p["literal"]); + if (p["key"] != old_key) { + // changeRefsIfUnique handles undo + cur.bv().buffer().changeRefsIfUnique(old_key, p["key"]); updateCommand(p["key"]); - cur.bv().buffer().changeRefsIfUnique(old_key, - params()["key"], CITE_CODE); + cur.forceBufferUpdate(); + buffer().invalidateBibinfoCache(); } - buffer_->invalidateBibinfoCache(); break; } @@ -141,6 +177,7 @@ void InsetBibitem::read(Lexer & lex) if (prefixIs(getParam("key"), key_prefix)) { int const key = convert(getParam("key").substr(key_prefix.length())); + Mutex::Locker lock(&counter_mutex); key_counter = max(key_counter, key); } } @@ -148,7 +185,19 @@ void InsetBibitem::read(Lexer & lex) docstring InsetBibitem::bibLabel() const { - docstring const & label = getParam("label"); + BufferParams const & bp = buffer().masterBuffer()->params(); + if (bp.citeEngineType() == ENGINE_TYPE_NUMERICAL) + return autolabel_; + docstring label = getParam("label"); + if (!label.empty() && bp.citeEngine() == "natbib") { + // Add a space before opening paren + label = subst(label, from_ascii("("), from_ascii(" (")); + // and strip off long author list + docstring striplabel; + label = rsplit(label, striplabel, ')'); + if (!striplabel.empty()) + label = striplabel + ")"; + } return label.empty() ? autolabel_ : label; } @@ -159,7 +208,8 @@ docstring InsetBibitem::screenLabel() const } -int InsetBibitem::plaintext(odocstream & os, OutputParams const &) const +int InsetBibitem::plaintext(odocstringstream & os, + OutputParams const &, size_t) const { odocstringstream oss; oss << '[' << bibLabel() << "] "; @@ -167,18 +217,22 @@ int InsetBibitem::plaintext(odocstream & os, OutputParams const &) const docstring const str = oss.str(); os << str; - return str.size(); + return int(str.size()); } // ale070405 -docstring bibitemWidest(Buffer const & buffer) +docstring bibitemWidest(Buffer const & buffer, OutputParams const & runparams) { + BufferParams const & bp = buffer.masterBuffer()->params(); + if (bp.citeEngineType() == ENGINE_TYPE_NUMERICAL) + return from_ascii("99"); + int w = 0; - InsetBibitem const * bitem = 0; + InsetBibitem const * bitem = nullptr; - // FIXME: this font is used unitialized for now but should be set to + // FIXME: this font is used uninitialized for now but should be set to // a proportional font. Here is what Georg Baum has to say about it: /* bibitemWidest() is supposed to find the bibitem with the widest label in the @@ -205,6 +259,7 @@ docstring bibitemWidest(Buffer const & buffer) ParagraphList::const_iterator it = buffer.paragraphs().begin(); ParagraphList::const_iterator end = buffer.paragraphs().end(); + bool is_literal = false; for (; it != end; ++it) { if (it->insetList().empty()) continue; @@ -225,51 +280,89 @@ docstring bibitemWidest(Buffer const & buffer) // So for now we just use the label size in order to be sure // that GUI and no-GUI gives the same bibitem (even if that is // potentially the wrong one. - int const wx = label.size(); + int const wx = int(label.size()); if (wx > w) { w = wx; lbl = label; + is_literal = (bitem->getParam("literal") == "true"); } } - if (!lbl.empty()) - return lbl; + if (!lbl.empty()) { + InsetCommandParams p(BIBITEM_CODE); + if (is_literal) + p["literal"] = from_ascii("true"); + return p.prepareCommand(runparams, lbl, ParamInfo::HANDLING_LATEXIFY); + } return from_ascii("99"); } -void InsetBibitem::fillWithBibKeys(BiblioInfo & keys, InsetIterator const & it) const +void InsetBibitem::collectBibKeys(InsetIterator const & it, FileNameList & /*checkedFiles*/) const { docstring const key = getParam("key"); + docstring const label = getParam("label"); BibTeXInfo keyvalmap(false); - keyvalmap.label(bibLabel()); - DocIterator doc_it(it); + keyvalmap.key(key); + keyvalmap.label(label); + + BufferParams const & bp = buffer().masterBuffer()->params(); + Counters & counters = bp.documentClass().counters(); + docstring const bibitem = from_ascii("bibitem"); + if (bp.citeEngineType() == ENGINE_TYPE_NUMERICAL || getParam("label").empty()) { + if (counters.hasCounter(bibitem)) + counters.step(bibitem, InternalUpdate); + string const & lang = it.paragraph().getParLanguage(bp)->code(); + keyvalmap.setCiteNumber(counters.theCounter(bibitem, lang)); + } + + DocIterator doc_it(it); doc_it.forwardPos(); - keyvalmap[from_ascii("ref")] = doc_it.paragraph().asString(); - keys[key] = keyvalmap; + keyvalmap[from_ascii("ref")] = doc_it.paragraph().asString( + AS_STR_INSETS | AS_STR_SKIPDELETE); + buffer().addBibTeXInfo(key, keyvalmap); } // Update the counters of this inset and of its contents -void InsetBibitem::updateLabels(ParIterator const &) +void InsetBibitem::updateBuffer(ParIterator const & it, UpdateType utype, bool const /*deleted*/) { - Counters & counters = buffer().masterBuffer()->params().documentClass().counters(); + BufferParams const & bp = buffer().masterBuffer()->params(); + Counters & counters = bp.documentClass().counters(); docstring const bibitem = from_ascii("bibitem"); - if (counters.hasCounter(bibitem) && getParam("label").empty()) { - counters.step(bibitem); - autolabel_ = counters.theCounter(bibitem); + if (bp.citeEngineType() == ENGINE_TYPE_NUMERICAL || getParam("label").empty()) { + if (counters.hasCounter(bibitem)) + counters.step(bibitem, utype); + string const & lang = it.paragraph().getParLanguage(bp)->code(); + autolabel_ = counters.theCounter(bibitem, lang); } else { autolabel_ = from_ascii("??"); } } -docstring InsetBibitem::xhtml(odocstream & os, OutputParams const &) const +void InsetBibitem::docbook(XMLStream &, OutputParams const &) const +{ + // Nothing to do: everything is implemented in makeParagraphBibliography. +} + + +docstring InsetBibitem::xhtml(XMLStream & xs, OutputParams const &) const { - os << ""; - os << "" << bibLabel() << " "; + // FIXME XHTML + // XHTML 1.1 doesn't have the "name" attribute for , so we have to use + // the "id" attribute to get the document to validate. Probably, we will + // need to use "name" anyway, eventually, because some browsers do not + // handle jumping to ids. If we don't do that, though, we can just put the + // id into the span tag. + string const attrs = + "id='LyXCite-" + to_utf8(xml::cleanAttr(getParam("key"))) + "'"; + xs << xml::CompTag("a", attrs); + xs << xml::StartTag("span", "class='bibitemlabel'"); + xs << bibLabel(); + xs << xml::EndTag("span"); return docstring(); }