]> git.lyx.org Git - lyx.git/blobdiff - src/insets/InsetBibitem.cpp
Update comment: a function was renamed.
[lyx.git] / src / insets / InsetBibitem.cpp
index fe5c07be5760d13474b4321bf596a4a761d0c459..6336da32d40b620acc029bb1d822dc90ae07df48 100644 (file)
 
 #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 "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 +50,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<Buffer &>(buf));
-       buffer_->invalidateBibinfoCache();
-       if (getParam("key").empty())
+       buffer().invalidateBibinfoCache();
+       if (getParam("key").empty()) {
+               Mutex::Locker lock(&counter_mutex);
                setParam("key", key_prefix + convert<docstring>(++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 +84,11 @@ void InsetBibitem::initView()
 
 void InsetBibitem::updateCommand(docstring const & new_key, bool)
 {
-       docstring const old_key = getParam("key");
        docstring key = new_key;
-
        vector<docstring> 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<docstring>(i);
                while (find(bibkeys.begin(), bibkeys.end(), key) != bibkeys.end()) {
@@ -90,8 +100,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 +108,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 +121,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 +176,7 @@ void InsetBibitem::read(Lexer & lex)
 
        if (prefixIs(getParam("key"), key_prefix)) {
                int const key = convert<int>(getParam("key").substr(key_prefix.length()));
+               Mutex::Locker lock(&counter_mutex);
                key_counter = max(key_counter, key);
        }
 }
@@ -148,7 +184,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 +207,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 +216,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 +258,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 +279,90 @@ 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("??");
        }
 }
 
 
-void InsetBibitem::xhtml(odocstream & os, OutputParams const &) const
+void InsetBibitem::docbook(XMLStream &, OutputParams const &) const
+{
+       // Nothing to do: everything is implemented in makeBibliography.
+}
+
+
+docstring InsetBibitem::xhtml(XMLStream & xs, OutputParams const &) const
 {
-       os << "<a name='" << html::htmlize(getParam("key")) << "'></a>";
-       os << "<span class='biblabel'>" << bibLabel() << "</span> "; 
+       // FIXME XHTML
+       // XHTML 1.1 doesn't have the "name" attribute for <a>, 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();
 }