http://www.lyx.org/trac/ticket/6534

This post on lyx-docs
http://marc.info/?l=lyx-docs&m=126595372224033&w=2

pointed me towards various unicode problems in the bibitem inset. Two issues:

1. if the label of a bibitem has a unicode glyph that is unknown to the output 
encoding, this has to be transformed to proper LaTeX.

2. if the key has a unicode glyph, this needs to be escaped both in the 
bibitem and the citation macros.

Currenty, a unicode glyph (outside the output file's encoding) either in the 
label or in the key yields a silent iconv error (the document is not output, 
but the user gets no warning either).

The attached patch against branch solves both issues.

Objections, comments?
Jürgen
Index: src/insets/InsetBibitem.cpp
===================================================================
--- src/insets/InsetBibitem.cpp	(Revision 33420)
+++ src/insets/InsetBibitem.cpp	(Arbeitskopie)
@@ -20,10 +20,12 @@
 #include "BufferView.h"
 #include "Counters.h"
 #include "DispatchResult.h"
+#include "Encoding.h"
 #include "FuncRequest.h"
 #include "InsetIterator.h"
 #include "InsetList.h"
 #include "Lexer.h"
+#include "OutputParams.h"
 #include "Paragraph.h"
 #include "ParagraphList.h"
 #include "TextClass.h"
@@ -31,6 +33,7 @@
 #include "frontends/alert.h"
 
 #include "support/convert.h"
+#include "support/debug.h"
 #include "support/docstream.h"
 #include "support/gettext.h"
 #include "support/lstrings.h"
@@ -170,8 +173,48 @@
 }
 
 
+int InsetBibitem::latex(odocstream & os, OutputParams const & runparams) const
+{
+	docstring cmd = '\\' + from_ascii(defaultCommand());
+	docstring uncodable;
+	if (!getParam("label").empty()) {
+		cmd += '[';
+		docstring orig = getParam("label");
+		for (size_t n = 0; n < orig.size(); ++n) {
+			try {
+				cmd += runparams.encoding->latexChar(orig[n]);
+			} catch (EncodingException & /* e */) {
+				LYXERR0("Uncodable character in bibitem!");
+				if (runparams.dryrun) {
+					cmd += "<" + _("LyX Warning: ")
+					    + _("uncodable character") + " '";
+					cmd += docstring(1, orig[n]);
+					cmd += "'>";
+				} else
+					uncodable += orig[n];
+			}
+		}
+		cmd += ']';
+	}
+	cmd += '{' + escape(getParam("key")) + '}';
+
+	os << cmd;
+
+	if (!uncodable.empty()) {
+		// issue a warning about omitted characters
+		// FIXME: should be passed to the error dialog
+		frontend::Alert::warning(_("Uncodable characters in bibliography item"),
+			bformat(_("The following characters in one of the bibliography items are\n"
+				  "not representable in the current encoding and have been omitted:\n%1$s."),
+			uncodable));
+	}
+	
+	return 0;
+}
+
+
 // ale070405
-docstring bibitemWidest(Buffer const & buffer)
+docstring bibitemWidest(Buffer const & buffer, OutputParams const & runparams)
 {
 	int w = 0;
 
@@ -228,8 +271,23 @@
 			w = wx;
 	}
 
-	if (bitem && !bitem->bibLabel().empty())
-		return bitem->bibLabel();
+	if (bitem && !bitem->bibLabel().empty()) {
+		docstring lbl = bitem->bibLabel();
+		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");
 }
Index: src/insets/InsetBibitem.h
===================================================================
--- src/insets/InsetBibitem.h	(Revision 33420)
+++ src/insets/InsetBibitem.h	(Arbeitskopie)
@@ -61,6 +61,8 @@
 	///
 	int plaintext(odocstream &, OutputParams const &) const;
 	///
+	int latex(odocstream &, OutputParams const &) const;
+	///
 	virtual void fillWithBibKeys(BiblioInfo &, InsetIterator const &) const;
 	/// Update the counter of this inset
 	virtual void updateLabels(ParIterator const &);
@@ -71,7 +73,7 @@
 	///
 	Inset * clone() const { return new InsetBibitem(*this); }
 
-	friend docstring bibitemWidest(Buffer const & buffer);
+	friend docstring bibitemWidest(Buffer const & buffer, OutputParams const &);
 	/// The label that is set by updateLabels
 	docstring autolabel_;
 	///
@@ -80,7 +82,7 @@
 
 
 /// Return the widest label in the Bibliography.
-docstring bibitemWidest(Buffer const &);
+docstring bibitemWidest(Buffer const &, OutputParams const &);
 
 } // namespace lyx
 
Index: src/insets/InsetCitation.cpp
===================================================================
--- src/insets/InsetCitation.cpp	(Revision 33420)
+++ src/insets/InsetCitation.cpp	(Arbeitskopie)
@@ -517,6 +517,7 @@
 int InsetCitation::latex(odocstream & os, OutputParams const &) const
 {
 	CiteEngine cite_engine = buffer().params().citeEngine();
+	BiblioInfo const & bi = buffer().masterBibInfo();
 	// FIXME UNICODE
 	docstring const cite_str = from_utf8(
 		asValidLatexCommand(getCmdName(), cite_engine));
@@ -530,7 +531,11 @@
 	else if (!after.empty())
 		os << '[' << after << ']';
 
-	os << '{' << cleanupWhitespace(getParam("key")) << '}';
+	if (!bi.isBibtex(getParam("key")))
+		// escape chars with bibitems
+		os << '{' << escape(cleanupWhitespace(getParam("key"))) << '}';
+	else
+		os << '{' << cleanupWhitespace(getParam("key")) << '}';
 
 	return 0;
 }
Index: src/BiblioInfo.h
===================================================================
--- src/BiblioInfo.h	(Revision 33420)
+++ src/BiblioInfo.h	(Arbeitskopie)
@@ -53,6 +53,8 @@
 	/// constructor that sets the entryType
 	BibTeXInfo(docstring const & key, docstring const & type);
 	///
+	bool isBibtex() const { return is_bibtex_; }
+	///
 	bool hasField(docstring const & field) const;
 	/// return the short form of an authorlist
 	docstring const getAbbreviatedAuthor() const;
@@ -126,6 +128,9 @@
 	/// Empty if no info exists. 
 	/// Note that this will retrieve data from the crossref as needed.
 	docstring const getInfo(docstring const & key) const;
+	/// Is this a reference from a bibtex database
+	/// or from a bibliography environment?
+	bool const isBibtex(docstring const & key) const;
 	
 	/**
 	  * "Translates" the available Citation Styles into strings for a given key,
Index: src/BiblioInfo.cpp
===================================================================
--- src/BiblioInfo.cpp	(Revision 33420)
+++ src/BiblioInfo.cpp	(Arbeitskopie)
@@ -472,6 +472,16 @@
 }
 
 
+bool const BiblioInfo::isBibtex(docstring const & key) const
+{
+	BiblioInfo::const_iterator it = find(key);
+	if (it == end())
+		return false;
+	return it->second.isBibtex();
+}
+
+
+
 vector<docstring> const BiblioInfo::getCiteStrings(
 	docstring const & key, Buffer const & buf) const
 {
Index: src/output_latex.cpp
===================================================================
--- src/output_latex.cpp	(Revision 33420)
+++ src/output_latex.cpp	(Arbeitskopie)
@@ -189,7 +189,7 @@
 			   << "}\n";
 		} else if (style.labeltype == LABEL_BIBLIO) {
 			// ale970405
-			os << '{' << bibitemWidest(buf) << "}\n";
+			os << '{' << bibitemWidest(buf, runparams) << "}\n";
 		} else
 			os << from_ascii(style.latexparam()) << '\n';
 		texrow.newline();

Reply via email to