*/
#include <config.h>
+#include <algorithm>
#include "InsetBibitem.h"
+#include "BiblioInfo.h"
#include "Buffer.h"
+#include "buffer_funcs.h"
+#include "BufferParams.h"
#include "BufferView.h"
+#include "Counters.h"
#include "DispatchResult.h"
+#include "Encoding.h"
#include "FuncRequest.h"
-#include "LyXFont.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/lstrings.h"
-#include "support/std_ostream.h"
#include "support/convert.h"
+#include "support/debug.h"
+#include "support/docstream.h"
+#include "support/gettext.h"
+#include "support/lstrings.h"
+using namespace std;
+using namespace lyx::support;
namespace lyx {
-using support::prefixIs;
-
-using std::max;
-using std::string;
-using std::auto_ptr;
-using std::ostream;
int InsetBibitem::key_counter = 0;
docstring const key_prefix = from_ascii("key-");
-InsetBibitem::InsetBibitem(InsetCommandParams const & p)
- : InsetCommand(p, "bibitem"), counter(1)
+
+InsetBibitem::InsetBibitem(Buffer * buf, InsetCommandParams const & p)
+ : InsetCommand(buf, p, "bibitem")
{
+ buffer_->invalidateBibinfoCache();
if (getParam("key").empty())
setParam("key", key_prefix + convert<docstring>(++key_counter));
}
-auto_ptr<Inset> InsetBibitem::doClone() const
+InsetBibitem::~InsetBibitem()
+{
+ if (isBufferValid())
+ buffer_->invalidateBibinfoCache();
+}
+
+
+void InsetBibitem::initView()
+{
+ updateCommand(getParam("key"));
+}
+
+
+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()) {
+ // generate unique label
+ key = new_key + '-' + convert<docstring>(i);
+ while (find(bibkeys.begin(), bibkeys.end(), key) != bibkeys.end()) {
+ ++i;
+ key = new_key + '-' + convert<docstring>(i);
+ }
+ frontend::Alert::warning(_("Keys must be unique!"),
+ bformat(_("The key %1$s already exists,\n"
+ "it will be changed to %2$s."), new_key, key));
+ }
+ setParam("key", key);
+
+ buffer().updateBuffer();
+}
+
+
+ParamInfo const & InsetBibitem::findInfo(string const & /* cmdName */)
{
- auto_ptr<InsetBibitem> b(new InsetBibitem(params()));
- b->setCounter(counter);
- return auto_ptr<Inset>(b);
+ static ParamInfo param_info_;
+ if (param_info_.empty()) {
+ param_info_.add("label", ParamInfo::LATEX_OPTIONAL,
+ ParamInfo::HANDLING_LATEXIFY);
+ param_info_.add("key", ParamInfo::LATEX_REQUIRED,
+ ParamInfo::HANDLING_ESCAPE);
+ }
+ return param_info_;
}
switch (cmd.action) {
case LFUN_INSET_MODIFY: {
- InsetCommandParams p("bibitem");
- InsetCommandMailer::string2params("bibitem", to_utf8(cmd.argument()), p);
+ InsetCommandParams p(BIBITEM_CODE);
+ InsetCommand::string2params("bibitem", to_utf8(cmd.argument()), p);
if (p.getCmdName().empty()) {
- cur.noUpdate();
+ cur.noUpdate();
break;
}
- if (p["key"] != params()["key"])
- cur.bv().buffer()->changeRefsIfUnique(params()["key"],
- p["key"], Inset::CITE_CODE);
- setParams(p);
+ docstring const & old_key = params()["key"];
+ setParam("label", p["label"]);
+ if (p["key"] != old_key) {
+ updateCommand(p["key"]);
+ cur.bv().buffer().changeRefsIfUnique(old_key,
+ params()["key"], CITE_CODE);
+ }
+ buffer_->invalidateBibinfoCache();
+ break;
}
default:
}
-void InsetBibitem::setCounter(int c)
-{
- counter = c;
-}
-
-
-void InsetBibitem::read(Buffer const & buf, Lexer & lex)
+void InsetBibitem::read(Lexer & lex)
{
- InsetCommand::read(buf, lex);
+ InsetCommand::read(lex);
if (prefixIs(getParam("key"), key_prefix)) {
int const key = convert<int>(getParam("key").substr(key_prefix.length()));
}
-docstring const InsetBibitem::getBibLabel() const
+docstring InsetBibitem::bibLabel() const
{
docstring const & label = getParam("label");
- return label.empty() ? convert<docstring>(counter) : label;
+ return label.empty() ? autolabel_ : label;
}
-docstring const InsetBibitem::getScreenLabel(Buffer const &) const
+docstring InsetBibitem::screenLabel() const
{
- return getParam("key") + " [" + getBibLabel() + ']';
+ return getParam("key") + " [" + bibLabel() + ']';
}
-int InsetBibitem::plaintext(Buffer const &, odocstream & os,
- OutputParams const &) const
+int InsetBibitem::plaintext(odocstream & os, OutputParams const &) const
{
odocstringstream oss;
- oss << '[' << getCounter() << "] ";
+ oss << '[' << bibLabel() << "] ";
docstring const str = oss.str();
os << str;
// ale070405
-docstring const bibitemWidest(Buffer const & buffer)
+docstring bibitemWidest(Buffer const & buffer, OutputParams const & runparams)
{
int w = 0;
// FIXME: this font is used unitialized 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
- output, because that is needed as an argument of the bibliography
- environment to dtermine the correct indentation. To be 100% correct we
- would need the metrics of the font that is used in the output, but usually
+ bibitemWidest() is supposed to find the bibitem with the widest label in the
+ output, because that is needed as an argument of the bibliography
+ environment to determine the correct indentation. To be 100% correct we
+ would need the metrics of the font that is used in the output, but usually
we don't have access to these.
- In practice, any proportional font is probably good enough, since we don't
- need to know the final with, we only need to know the which label is the
+ In practice, any proportional font is probably good enough, since we don't
+ need to know the final with, we only need to know the which label is the
widest.
- Unless there is an easy way to get the metrics of the output font I suggest
+ Unless there is an easy way to get the metrics of the output font I suggest
to use a hardcoded font like "Times" or so.
- It is very important that the result of this function is the same both with
- and without GUI. After thinking about this it is clear that no LyXFont
- metrics should be used here, since these come from the gui. If we can't
- easily get the LaTeX font metrics we should make our own poor mans front
- metrics replacement, e.g. by hardcoding the metrics of the standard TeX
+ It is very important that the result of this function is the same both with
+ and without GUI. After thinking about this it is clear that no Font
+ metrics should be used here, since these come from the gui. If we can't
+ easily get the LaTeX font metrics we should make our own poor mans font
+ metrics replacement, e.g. by hardcoding the metrics of the standard TeX
font.
*/
- LyXFont font;
+
+ docstring lbl;
ParagraphList::const_iterator it = buffer.paragraphs().begin();
ParagraphList::const_iterator end = buffer.paragraphs().end();
for (; it != end; ++it) {
- if (it->bibitem()) {
- docstring const label = it->bibitem()->getBibLabel();
-
- // FIXME: we can't be sure using the following that the GUI
- // version and the command-line version will give the same
- // result.
- //
- //int const wx = use_gui?
- // theFontMetrics(font).width(label): label.size();
- //
- // 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();
-
- if (wx > w) {
- w = wx;
- bitem = it->bibitem();
- }
+ if (it->insetList().empty())
+ continue;
+ Inset * inset = it->insetList().begin()->inset;
+ if (inset->lyxCode() != BIBITEM_CODE)
+ continue;
+
+ bitem = static_cast<InsetBibitem const *>(inset);
+ docstring const label = bitem->bibLabel();
+
+ // FIXME: we can't be sure using the following that the GUI
+ // version and the command-line version will give the same
+ // result.
+ //
+ //int const wx = use_gui?
+ // theFontMetrics(font).width(label): label.size();
+ //
+ // 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();
+
+ if (wx > w) {
+ w = wx;
+ lbl = label;
}
}
- if (bitem && !bitem->getBibLabel().empty())
- return bitem->getBibLabel();
+ if (!lbl.empty()) {
+ docstring latex_lbl;
+ for (size_t n = 0; n < lbl.size(); ++n) {
+ try {
+ latex_lbl += runparams.encoding->latexChar(lbl[n]);
+ } catch (EncodingException & /* e */) {
+ if (runparams.dryrun) {
+ latex_lbl += "<" + _("LyX Warning: ")
+ + _("uncodable character") + " '";
+ latex_lbl += docstring(1, lbl[n]);
+ latex_lbl += "'>";
+ }
+ }
+ }
+ return latex_lbl;
+ }
return from_ascii("99");
}
+void InsetBibitem::fillWithBibKeys(BiblioInfo & keys, InsetIterator const & it) const
+{
+ docstring const key = getParam("key");
+ BibTeXInfo keyvalmap(false);
+ keyvalmap.label(bibLabel());
+ DocIterator doc_it(it);
+ doc_it.forwardPos();
+ keyvalmap[from_ascii("ref")] = doc_it.paragraph().asString();
+ keys[key] = keyvalmap;
+}
+
+
+// Update the counters of this inset and of its contents
+void InsetBibitem::updateBuffer(ParIterator const & it, UpdateType utype)
+{
+ 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, utype);
+ string const & lang = it.paragraph().getParLanguage(bp)->code();
+ autolabel_ = counters.theCounter(bibitem, lang);
+ } else {
+ autolabel_ = from_ascii("??");
+ }
+}
+
+
+docstring InsetBibitem::xhtml(XHTMLStream & xs, OutputParams const &) const
+{
+ // FIXME XHTML
+ // XHTML 1.1 doesn't have the "name" attribute for <a>, so we have to use
+ // the "id" atttribute 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='" + to_utf8(getParam("key")) + "'";
+ xs << html::CompTag("a", attrs);
+ xs << html::StartTag("span", "class='bibitemlabel'");
+ xs << bibLabel();
+ xs << html::EndTag("span");
+ return docstring();
+}
+
+
} // namespace lyx