X-Git-Url: https://git.lyx.org/gitweb/?a=blobdiff_plain;f=src%2Finsets%2FInsetBibitem.cpp;h=82d81852000f674aca14831f367a23334bdfd8cd;hb=8124e6c02ea1fd6779bb6c47ffe2bca2c8bd2d97;hp=2840ad5c8fff621f51992f53c8595845513940d3;hpb=9da74fe2078e24e1e7891784ecbfe33ff77e7f85;p=lyx.git diff --git a/src/insets/InsetBibitem.cpp b/src/insets/InsetBibitem.cpp index 2840ad5c8f..82d8185200 100644 --- a/src/insets/InsetBibitem.cpp +++ b/src/insets/InsetBibitem.cpp @@ -28,7 +28,6 @@ #include "Language.h" #include "Lexer.h" #include "output_xhtml.h" -#include "OutputParams.h" #include "Paragraph.h" #include "ParagraphList.h" #include "ParIterator.h" @@ -36,11 +35,13 @@ #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; @@ -49,6 +50,7 @@ namespace lyx { int InsetBibitem::key_counter = 0; +static Mutex counter_mutex; docstring const key_prefix = from_ascii("key-"); @@ -56,15 +58,21 @@ InsetBibitem::InsetBibitem(Buffer * buf, InsetCommandParams const & p) : InsetCommand(buf, p) { buffer().invalidateBibinfoCache(); - if (getParam("key").empty()) + if (getParam("key").empty()) { + Mutex::Locker lock(&counter_mutex); setParam("key", key_prefix + convert(++key_counter)); + } } InsetBibitem::~InsetBibitem() { - if (isBufferLoaded()) - buffer().invalidateBibinfoCache(); + 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(); + } } @@ -77,12 +85,10 @@ void InsetBibitem::initView() void InsetBibitem::updateCommand(docstring const & new_key, bool) { 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()) { @@ -105,7 +111,9 @@ ParamInfo const & InsetBibitem::findInfo(string const & /* cmdName */) param_info_.add("label", ParamInfo::LATEX_OPTIONAL, ParamInfo::HANDLING_LATEXIFY); param_info_.add("key", ParamInfo::LATEX_REQUIRED, - ParamInfo::HANDLING_ESCAPE); + ParamInfo::ParamHandling(ParamInfo::HANDLING_ESCAPE + | ParamInfo::HANDLING_LTRIM)); + param_info_.add("literal", ParamInfo::LYX_INTERNAL); } return param_info_; } @@ -127,57 +135,28 @@ void InsetBibitem::doDispatch(Cursor & cur, FuncRequest & cmd) docstring const & old_key = params()["key"]; docstring const & old_label = params()["label"]; + docstring const & old_literal = params()["literal"]; docstring label = p["label"]; - - // definitions for escaping - int previous; - static docstring const backslash = from_ascii("\\"); - static docstring const lbrace = from_ascii("{"); - static docstring const rbrace = from_ascii("}"); - static char_type const chars_escape[6] = { - '&', '_', '$', '%', '#', '^'}; - static char_type const brackets_escape[2] = {'[', ']'}; - - if (!label.empty()) { - // The characters in chars_name[] need to be changed to a command when - // they are in the name field. - for (int k = 0; k < 6; k++) - for (size_t i = 0, pos; - (pos = label.find(chars_escape[k], i)) != string::npos; - i = pos + 2) { - if (pos == 0) - previous = 0; - else - previous = pos - 1; - // only if not already escaped - if (label[previous] != '\\') - label.replace(pos, 1, backslash + chars_escape[k] + lbrace + rbrace); - } - // The characters '[' and ']' need to be put into braces - for (int k = 0; k < 2; k++) - for (size_t i = 0, pos; - (pos = label.find(brackets_escape[k], i)) != string::npos; - i = pos + 2) { - if (pos == 0) - previous = 0; - else - previous = pos - 1; - // only if not already escaped - if (label[previous] != '{') - label.replace(pos, 1, lbrace + brackets_escape[k] + rbrace); - } - } + 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"]); cur.forceBufferUpdate(); buffer().invalidateBibinfoCache(); } @@ -197,6 +176,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); } } @@ -207,7 +187,16 @@ docstring InsetBibitem::bibLabel() const BufferParams const & bp = buffer().masterBuffer()->params(); if (bp.citeEngineType() == ENGINE_TYPE_NUMERICAL) return autolabel_; - docstring const & label = getParam("label"); + 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; } @@ -227,7 +216,7 @@ int InsetBibitem::plaintext(odocstringstream & os, docstring const str = oss.str(); os << str; - return str.size(); + return int(str.size()); } @@ -240,9 +229,9 @@ docstring bibitemWidest(Buffer const & buffer, OutputParams const & runparams) 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 @@ -269,6 +258,7 @@ docstring bibitemWidest(Buffer const & buffer, OutputParams const & runparams) 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; @@ -289,25 +279,27 @@ docstring bibitemWidest(Buffer const & buffer, OutputParams const & runparams) // 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()) { - pair latex_lbl = - runparams.encoding->latexString(lbl, runparams.dryrun); - return latex_lbl.first; + 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::collectBibKeys(InsetIterator const & it) const +void InsetBibitem::collectBibKeys(InsetIterator const & it, FileNameList & /*checkedFiles*/) const { docstring const key = getParam("key"); docstring const label = getParam("label"); @@ -334,7 +326,7 @@ void InsetBibitem::collectBibKeys(InsetIterator const & it) const // Update the counters of this inset and of its contents -void InsetBibitem::updateBuffer(ParIterator const & it, UpdateType utype) +void InsetBibitem::updateBuffer(ParIterator const & it, UpdateType utype, bool const /*deleted*/) { BufferParams const & bp = buffer().masterBuffer()->params(); Counters & counters = bp.documentClass().counters(); @@ -350,20 +342,26 @@ void InsetBibitem::updateBuffer(ParIterator const & it, UpdateType utype) } -docstring InsetBibitem::xhtml(XHTMLStream & xs, 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 { // FIXME XHTML // XHTML 1.1 doesn't have the "name" attribute for , so we have to use - // the "id" atttribute to get the document to validate. Probably, we will + // 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(html::cleanAttr(getParam("key"))) + "'"; - xs << html::CompTag("a", attrs); - xs << html::StartTag("span", "class='bibitemlabel'"); + "id='LyXCite-" + to_utf8(xml::cleanAttr(getParam("key"))) + "'"; + xs << xml::CompTag("a", attrs); + xs << xml::StartTag("span", "class='bibitemlabel'"); xs << bibLabel(); - xs << html::EndTag("span"); + xs << xml::EndTag("span"); return docstring(); }