* \author Angus Leeming
* \author Herbert Voß
* \author Richard Heck
+ * \author Julien Rioux
*
* Full author contact details are available in file CREDITS.
*/
#include "Encoding.h"
#include "InsetIterator.h"
#include "Language.h"
+#include "output_xhtml.h"
#include "Paragraph.h"
#include "TextClass.h"
#include "TocBackend.h"
vector<docstring>::const_iterator it = pieces.begin();
vector<docstring>::const_iterator en = pieces.end();
for (; it != en; ++it) {
- if ((*it).size() == 0)
+ if ((*it).empty())
continue;
char_type const c = (*it)[0];
if (isLower(c))
return retval;
}
+
// converts a string containing LaTeX commands into unicode
// for display.
docstring convertLaTeXCommands(docstring const & str)
bool scanning_cmd = false;
bool scanning_math = false;
bool escaped = false; // used to catch \$, etc.
- while (val.size()) {
+ while (!val.empty()) {
char_type const ch = val[0];
// if we're scanning math, we output everything until we
// unicodesymbols has things in the form: \"{u},
// whereas we may see things like: \"u. So we'll
// look for that and change it, if necessary.
+ // FIXME: This is a sort of mini-tex2lyx.
+ // Use the real tex2lyx instead!
static lyx::regex const reg("^\\\\\\W\\w");
if (lyx::regex_search(to_utf8(val), reg)) {
val.insert(3, from_ascii("}"));
val.insert(2, from_ascii("{"));
}
+ bool termination;
docstring rem;
docstring const cnvtd = Encodings::fromLaTeXCommand(val,
- Encodings::TEXT_CMD, rem);
+ Encodings::TEXT_CMD, termination, rem);
if (!cnvtd.empty()) {
// it did, so we'll take that bit and proceed with what's left
ret += cnvtd;
return ret;
}
+
+// Escape '<' and '>' and remove richtext markers (e.g. {!this is richtext!}) from a string.
+docstring processRichtext(docstring const & str, bool richtext)
+{
+ docstring val = str;
+ docstring ret;
+
+ bool scanning_rich = false;
+ while (!val.empty()) {
+ char_type const ch = val[0];
+ if (ch == '{' && val.size() > 1 && val[1] == '!') {
+ // beginning of rich text
+ scanning_rich = true;
+ val = val.substr(2);
+ continue;
+ }
+ if (scanning_rich && ch == '!' && val.size() > 1 && val[1] == '}') {
+ // end of rich text
+ scanning_rich = false;
+ val = val.substr(2);
+ continue;
+ }
+ if (richtext) {
+ if (scanning_rich)
+ ret += ch;
+ else {
+ // we need to escape '<' and '>'
+ if (ch == '<')
+ ret += "<";
+ else if (ch == '>')
+ ret += ">";
+ else
+ ret += ch;
+ }
+ } else if (!scanning_rich /* && !richtext */)
+ ret += ch;
+ // else the character is discarded, which will happen only if
+ // richtext == false and we are scanning rich text
+ val = val.substr(1);
+ }
+ return ret;
+}
+
} // anon namespace
{}
-docstring const BibTeXInfo::getAbbreviatedAuthor() const
+docstring const BibTeXInfo::getAbbreviatedAuthor(bool jurabib_style) const
{
if (!is_bibtex_) {
docstring const opt = label();
return authors;
}
- docstring author = convertLaTeXCommands(operator[]("author"));
+ docstring author = operator[]("author");
if (author.empty()) {
- author = convertLaTeXCommands(operator[]("editor"));
+ author = operator[]("editor");
if (author.empty())
- return bib_key_;
+ return author;
}
// FIXME Move this to a separate routine that can
vector<docstring> const authors =
getVectorFromString(author, from_ascii(" and "));
- if (authors.size() == 2)
- return bformat(_("%1$s and %2$s"),
+ if (jurabib_style && (authors.size() == 2 || authors.size() == 3)) {
+ docstring shortauthor = familyName(authors[0])
+ + "/" + familyName(authors[1]);
+ if (authors.size() == 3)
+ shortauthor += "/" + familyName(authors[2]);
+ return convertLaTeXCommands(shortauthor);
+ }
+
+ docstring retval = familyName(authors[0]);
+
+ if (authors.size() == 2 && authors[1] != "others")
+ retval = bformat(from_ascii("%1$s and %2$s"),
familyName(authors[0]), familyName(authors[1]));
- if (authors.size() > 2)
- return bformat(_("%1$s et al."), familyName(authors[0]));
+ if (authors.size() >= 2)
+ retval = bformat(from_ascii("%1$s et al."),
+ familyName(authors[0]));
+
+ return convertLaTeXCommands(retval);
+}
+
- return familyName(authors[0]);
+docstring const BibTeXInfo::getAbbreviatedAuthor(Buffer const & buf, bool jurabib_style) const
+{
+ docstring const author = getAbbreviatedAuthor(jurabib_style);
+ if (!is_bibtex_)
+ return author;
+ vector<docstring> const authors = getVectorFromString(author, from_ascii(" and "));
+ if (authors.size() == 2)
+ return bformat(buf.B_("%1$s and %2$s"), authors[0], authors[1]);
+ docstring::size_type const idx = author.rfind(from_ascii(" et al."));
+ if (idx != docstring::npos)
+ return bformat(buf.B_("%1$s et al."), author.substr(0, idx));
+ return author;
}
namespace {
- string parseOptions(string const & format, string & optkey,
- string & ifpart, string & elsepart);
-
- // Calls parseOptions to deal with an embedded option, such as:
- // {%number%[[, no.~%number%]]}
- // which must appear at the start of format. ifelsepart gets the
- // whole of the option, and we return what's left after the option.
- // we return format if there is an error.
- string parseEmbeddedOption(string const & format, string & ifelsepart)
- {
- LASSERT(format[0] == '{' && format[1] == '%', return format);
- string optkey;
- string ifpart;
- string elsepart;
- string const rest = parseOptions(format, optkey, ifpart, elsepart);
- if (format == rest) { // parse error
- LYXERR0("ERROR! Couldn't parse `" << format <<"'.");
- return format;
- }
- LASSERT(rest.size() <= format.size(), /* */);
- ifelsepart = format.substr(0, format.size() - rest.size());
- return rest;
+
+docstring parseOptions(docstring const & format, string & optkey,
+ docstring & ifpart, docstring & elsepart);
+
+// Calls parseOptions to deal with an embedded option, such as:
+// {%number%[[, no.~%number%]]}
+// which must appear at the start of format. ifelsepart gets the
+// whole of the option, and we return what's left after the option.
+// we return format if there is an error.
+docstring parseEmbeddedOption(docstring const & format, docstring & ifelsepart)
+{
+ LASSERT(format[0] == '{' && format[1] == '%', return format);
+ string optkey;
+ docstring ifpart;
+ docstring elsepart;
+ docstring const rest = parseOptions(format, optkey, ifpart, elsepart);
+ if (format == rest) { // parse error
+ LYXERR0("ERROR! Couldn't parse `" << format <<"'.");
+ return format;
}
+ LASSERT(rest.size() <= format.size(),
+ { ifelsepart = docstring(); return format; });
+ ifelsepart = format.substr(0, format.size() - rest.size());
+ return rest;
+}
- // Gets a "clause" from a format string, where the clause is
- // delimited by '[[' and ']]'. Returns what is left after the
- // clause is removed, and returns format if there is an error.
- string getClause(string const & format, string & clause)
- {
- string fmt = format;
- // remove '[['
- fmt = fmt.substr(2);
- // we'll remove characters from the front of fmt as we
- // deal with them
- while (fmt.size()) {
- if (fmt[0] == ']' && fmt.size() > 1 && fmt[1] == ']') {
- // that's the end
- fmt = fmt.substr(2);
- break;
+// Gets a "clause" from a format string, where the clause is
+// delimited by '[[' and ']]'. Returns what is left after the
+// clause is removed, and returns format if there is an error.
+docstring getClause(docstring const & format, docstring & clause)
+{
+ docstring fmt = format;
+ // remove '[['
+ fmt = fmt.substr(2);
+ // we'll remove characters from the front of fmt as we
+ // deal with them
+ while (!fmt.empty()) {
+ if (fmt[0] == ']' && fmt.size() > 1 && fmt[1] == ']') {
+ // that's the end
+ fmt = fmt.substr(2);
+ break;
+ }
+ // check for an embedded option
+ if (fmt[0] == '{' && fmt.size() > 1 && fmt[1] == '%') {
+ docstring part;
+ docstring const rest = parseEmbeddedOption(fmt, part);
+ if (fmt == rest) {
+ LYXERR0("ERROR! Couldn't parse embedded option in `" << format <<"'.");
+ return format;
}
- // check for an embedded option
- if (fmt[0] == '{' && fmt.size() > 1 && fmt[1] == '%') {
- string part;
- string const rest = parseEmbeddedOption(fmt, part);
- if (fmt == rest) {
- LYXERR0("ERROR! Couldn't parse embedded option in `" << format <<"'.");
- return format;
- }
- clause += part;
- fmt = rest;
- } else { // it's just a normal character
+ clause += part;
+ fmt = rest;
+ } else { // it's just a normal character
clause += fmt[0];
fmt = fmt.substr(1);
- }
}
- return fmt;
}
+ return fmt;
+}
- // parse an options string, which must appear at the start of the
- // format parameter. puts the parsed bits in optkey, ifpart, and
- // elsepart and returns what's left after the option is removed.
- // if there's an error, it returns format itself.
- string parseOptions(string const & format, string & optkey,
- string & ifpart, string & elsepart)
- {
- LASSERT(format[0] == '{' && format[1] == '%', return format);
- // strip '{%'
- string fmt = format.substr(2);
- size_t pos = fmt.find('%'); // end of key
- if (pos == string::npos) {
- LYXERR0("Error parsing `" << format <<"'. Can't find end of key.");
- return format;
- }
- optkey = fmt.substr(0,pos);
- fmt = fmt.substr(pos + 1);
- // [[format]] should be next
- if (fmt[0] != '[' || fmt[1] != '[') {
- LYXERR0("Error parsing `" << format <<"'. Can't find '[[' after key.");
- return format;
- }
+// parse an options string, which must appear at the start of the
+// format parameter. puts the parsed bits in optkey, ifpart, and
+// elsepart and returns what's left after the option is removed.
+// if there's an error, it returns format itself.
+docstring parseOptions(docstring const & format, string & optkey,
+ docstring & ifpart, docstring & elsepart)
+{
+ LASSERT(format[0] == '{' && format[1] == '%', return format);
+ // strip '{%'
+ docstring fmt = format.substr(2);
+ size_t pos = fmt.find('%'); // end of key
+ if (pos == string::npos) {
+ LYXERR0("Error parsing `" << format <<"'. Can't find end of key.");
+ return format;
+ }
+ optkey = to_utf8(fmt.substr(0, pos));
+ fmt = fmt.substr(pos + 1);
+ // [[format]] should be next
+ if (fmt[0] != '[' || fmt[1] != '[') {
+ LYXERR0("Error parsing `" << format <<"'. Can't find '[[' after key.");
+ return format;
+ }
- string curfmt = fmt;
- fmt = getClause(curfmt, ifpart);
- if (fmt == curfmt) {
- LYXERR0("Error parsing `" << format <<"'. Couldn't get if clause.");
- return format;
- }
+ docstring curfmt = fmt;
+ fmt = getClause(curfmt, ifpart);
+ if (fmt == curfmt) {
+ LYXERR0("Error parsing `" << format <<"'. Couldn't get if clause.");
+ return format;
+ }
- if (fmt[0] == '}') // we're done, no else clause
- return fmt.substr(1);
+ if (fmt[0] == '}') // we're done, no else clause
+ return fmt.substr(1);
- // else part should follow
- if (fmt[0] != '[' || fmt[1] != '[') {
- LYXERR0("Error parsing `" << format <<"'. Can't find else clause.");
- return format;
- }
+ // else part should follow
+ if (fmt[0] != '[' || fmt[1] != '[') {
+ LYXERR0("Error parsing `" << format <<"'. Can't find else clause.");
+ return format;
+ }
- curfmt = fmt;
- fmt = getClause(curfmt, elsepart);
- // we should be done
- if (fmt == curfmt || fmt[0] != '}') {
- LYXERR0("Error parsing `" << format <<"'. Can't find end of option.");
- return format;
- }
- return fmt.substr(1);
+ curfmt = fmt;
+ fmt = getClause(curfmt, elsepart);
+ // we should be done
+ if (fmt == curfmt || fmt[0] != '}') {
+ LYXERR0("Error parsing `" << format <<"'. Can't find end of option.");
+ return format;
+ }
+ return fmt.substr(1);
}
+
} // anon namespace
-docstring BibTeXInfo::expandFormat(string const & format,
+docstring BibTeXInfo::expandFormat(docstring const & format,
BibTeXInfo const * const xref, int & counter, Buffer const & buf,
- bool richtext) const
+ docstring before, docstring after, docstring dialog, bool next) const
{
// incorrect use of macros could put us in an infinite loop
- static int max_passes = 5000;
- docstring ret; // return value
+ static int const max_passes = 5000;
+ // the use of overly large keys can lead to performance problems, due
+ // to eventual attempts to convert LaTeX macros to unicode. See bug
+ // #8944. This is perhaps not the best solution, but it will have to
+ // do for now.
+ static size_t const max_keysize = 128;
+ odocstringstream ret; // return value
string key;
bool scanning_key = false;
bool scanning_rich = false;
- string fmt = format;
+ CiteEngineType const engine_type = buf.params().citeEngineType();
+ docstring fmt = format;
// we'll remove characters from the front of fmt as we
// deal with them
- while (fmt.size()) {
+ while (!fmt.empty()) {
if (counter++ > max_passes) {
LYXERR0("Recursion limit reached while parsing `"
<< format << "'.");
if (key[0] == '!') {
// macro
string const val =
- buf.params().documentClass().getCiteMacro(key);
- fmt = val + fmt.substr(1);
+ buf.params().documentClass().getCiteMacro(engine_type, key);
+ fmt = from_utf8(val) + fmt.substr(1);
continue;
} else if (key[0] == '_') {
// a translatable bit
string const val =
- buf.params().documentClass().getCiteMacro(key);
+ buf.params().documentClass().getCiteMacro(engine_type, key);
docstring const trans =
translateIfPossible(from_utf8(val), buf.params().language->code());
- ret += trans;
+ ret << trans;
} else {
- docstring const val = getValueForKey(key, xref);
- ret += val;
+ docstring const val =
+ getValueForKey(key, buf, before, after, dialog, xref, max_keysize);
+ if (!scanning_rich)
+ ret << from_ascii("{!<span class=\"bib-" + key + "\">!}");
+ ret << val;
+ if (!scanning_rich)
+ ret << from_ascii("{!</span>!}");
}
} else {
// beginning of key
if (fmt[1] == '%') {
// it is the beginning of an optional format
string optkey;
- string ifpart;
- string elsepart;
- string const newfmt =
+ docstring ifpart;
+ docstring elsepart;
+ docstring const newfmt =
parseOptions(fmt, optkey, ifpart, elsepart);
if (newfmt == fmt) // parse error
return _("ERROR!");
fmt = newfmt;
- docstring const val = getValueForKey(optkey, xref);
- if (!val.empty())
- ret += expandFormat(ifpart, xref, counter, buf, richtext);
+ docstring const val =
+ getValueForKey(optkey, buf, before, after, dialog, xref);
+ if (optkey == "next" && next)
+ ret << ifpart; // without expansion
+ else if (!val.empty())
+ ret << expandFormat(ifpart, xref, counter, buf,
+ before, after, dialog, next);
else if (!elsepart.empty())
- ret += expandFormat(elsepart, xref, counter, buf, richtext);
+ ret << expandFormat(elsepart, xref, counter, buf,
+ before, after, dialog, next);
// fmt will have been shortened for us already
continue;
}
// beginning of rich text
scanning_rich = true;
fmt = fmt.substr(2);
+ ret << from_ascii("{!");
continue;
}
}
// we are here if '{' was not followed by % or !.
// So it's just a character.
- ret += thischar;
+ ret << thischar;
}
else if (scanning_rich && thischar == '!'
&& fmt.size() > 1 && fmt[1] == '}') {
// end of rich text
scanning_rich = false;
fmt = fmt.substr(2);
+ ret << from_ascii("!}");
continue;
}
else if (scanning_key)
key += char(thischar);
- else if (richtext) {
- if (scanning_rich)
- ret += thischar;
- else {
- // we need to escape '<' and '>'
- if (thischar == '<')
- ret += "<";
- else if (thischar == '>')
- ret += ">";
- else
- ret += thischar;
+ else {
+ try {
+ ret.put(thischar);
+ } catch (EncodingException & /* e */) {
+ LYXERR0("Uncodable character '" << docstring(1, thischar) << " in citation label!");
}
- } else if (!scanning_rich /* && !richtext */)
- ret += thischar;
- // else the character is discarded, which will happen only if
- // richtext == false and we are scanning rich text
+ }
fmt = fmt.substr(1);
} // for loop
if (scanning_key) {
LYXERR0("Never found end of rich text in `" << format << "'!");
return _("ERROR!");
}
- return ret;
+ return ret.str();
}
docstring const & BibTeXInfo::getInfo(BibTeXInfo const * const xref,
Buffer const & buf, bool richtext) const
{
- if (!info_.empty())
+ if (!richtext && !info_.empty())
return info_;
+ if (richtext && !info_richtext_.empty())
+ return info_richtext_;
if (!is_bibtex_) {
BibTeXInfo::const_iterator it = find(from_ascii("ref"));
return info_;
}
+ CiteEngineType const engine_type = buf.params().citeEngineType();
DocumentClass const & dc = buf.params().documentClass();
- string const & format = dc.getCiteFormat(to_utf8(entry_type_));
+ docstring const & format =
+ from_utf8(dc.getCiteFormat(engine_type, to_utf8(entry_type_)));
int counter = 0;
- info_ = expandFormat(format, xref, counter, buf, richtext);
-
- if (!info_.empty())
- info_ = convertLaTeXCommands(info_);
+ info_ = expandFormat(format, xref, counter, buf,
+ docstring(), docstring(), docstring(), false);
+
+ if (!info_.empty()) {
+ info_richtext_ = convertLaTeXCommands(processRichtext(info_, true));
+ info_ = convertLaTeXCommands(processRichtext(info_, false));
+ if (richtext)
+ return info_richtext_;
+ }
return info_;
}
+docstring const BibTeXInfo::getLabel(BibTeXInfo const * const xref,
+ Buffer const & buf, docstring const & format, bool richtext,
+ docstring before, docstring after, docstring dialog, bool next) const
+{
+ docstring loclabel;
+
+ int counter = 0;
+ loclabel = expandFormat(format, xref, counter, buf,
+ before, after, dialog, next);
+
+ if (!loclabel.empty() && !next) {
+ loclabel = processRichtext(loclabel, richtext);
+ loclabel = convertLaTeXCommands(loclabel);
+ }
+
+ return loclabel;
+}
+
+
docstring const & BibTeXInfo::operator[](docstring const & field) const
{
BibTeXInfo::const_iterator it = find(field);
}
-docstring BibTeXInfo::getValueForKey(string const & key,
- BibTeXInfo const * const xref) const
+docstring BibTeXInfo::getValueForKey(string const & oldkey, Buffer const & buf,
+ docstring const & before, docstring const & after, docstring const & dialog,
+ BibTeXInfo const * const xref, size_t maxsize) const
{
- docstring const ret = operator[](key);
- if (!ret.empty() || !xref)
- return ret;
- return (*xref)[key];
+ // anything less is pointless
+ LASSERT(maxsize >= 16, maxsize = 16);
+ string key = oldkey;
+ bool cleanit = false;
+ if (prefixIs(oldkey, "clean:")) {
+ key = oldkey.substr(6);
+ cleanit = true;
+ }
+
+ docstring ret = operator[](key);
+ if (ret.empty() && xref)
+ ret = (*xref)[key];
+ if (ret.empty()) {
+ // some special keys
+ // FIXME: dialog, textbefore and textafter have nothing to do with this
+ if (key == "dialog")
+ ret = dialog;
+ else if (key == "entrytype")
+ ret = entry_type_;
+ else if (key == "key")
+ ret = bib_key_;
+ else if (key == "label")
+ ret = label_;
+ else if (key == "modifier" && modifier_ != 0)
+ ret = modifier_;
+ else if (key == "numericallabel")
+ ret = cite_number_;
+ else if (key == "abbrvauthor")
+ // Special key to provide abbreviated author names.
+ ret = getAbbreviatedAuthor(buf, false);
+ else if (key == "shortauthor")
+ // When shortauthor is not defined, jurabib automatically
+ // provides jurabib-style abbreviated author names. We do
+ // this as well.
+ ret = getAbbreviatedAuthor(buf, true);
+ else if (key == "shorttitle") {
+ // When shorttitle is not defined, jurabib uses for `article'
+ // and `periodical' entries the form `journal volume [year]'
+ // and for other types of entries it uses the `title' field.
+ if (entry_type_ == "article" || entry_type_ == "periodical")
+ ret = operator[]("journal") + " " + operator[]("volume")
+ + " [" + operator[]("year") + "]";
+ else
+ ret = operator[]("title");
+ } else if (key == "bibentry") {
+ // Special key to provide the full bibliography entry: see getInfo()
+ CiteEngineType const engine_type = buf.params().citeEngineType();
+ DocumentClass const & dc = buf.params().documentClass();
+ docstring const & format =
+ from_utf8(dc.getCiteFormat(engine_type, to_utf8(entry_type_)));
+ int counter = 0;
+ ret = expandFormat(format, xref, counter, buf,
+ docstring(), docstring(), docstring(), false);
+ } else if (key == "textbefore")
+ ret = before;
+ else if (key == "textafter")
+ ret = after;
+ else if (key == "year")
+ ret = getYear();
+ }
+
+ if (cleanit)
+ ret = html::cleanAttr(ret);
+
+ // make sure it is not too big
+ if (ret.size() > maxsize)
+ ret = ret.substr(0, maxsize - 3) + from_ascii("...");
+ return ret;
}
//////////////////////////////////////////////////////////////////////
namespace {
+
// A functor for use with sort, leading to case insensitive sorting
- class compareNoCase: public binary_function<docstring, docstring, bool>
- {
- public:
- bool operator()(docstring const & s1, docstring const & s2) const {
- return compare_no_case(s1, s2) < 0;
- }
- };
+class compareNoCase: public binary_function<docstring, docstring, bool>
+{
+public:
+ bool operator()(docstring const & s1, docstring const & s2) const {
+ return compare_no_case(s1, s2) < 0;
+ }
+};
+
} // namespace anon
}
-docstring const BiblioInfo::getAbbreviatedAuthor(docstring const & key) const
+docstring const BiblioInfo::getAbbreviatedAuthor(docstring const & key, Buffer const & buf) const
{
BiblioInfo::const_iterator it = find(key);
if (it == end())
return docstring();
BibTeXInfo const & data = it->second;
- return data.getAbbreviatedAuthor();
+ return data.getAbbreviatedAuthor(buf, false);
}
// let's try the crossref
docstring const xref = data.getXRef();
if (xref.empty())
- return _("No year"); // no luck
+ // no luck
+ return docstring();
BiblioInfo::const_iterator const xrefit = find(xref);
if (xrefit == end())
- return _("No year"); // no luck again
+ // no luck again
+ return docstring();
BibTeXInfo const & xref_data = xrefit->second;
year = xref_data.getYear();
}
}
+docstring const BiblioInfo::getYear(docstring const & key, Buffer const & buf, bool use_modifier) const
+{
+ docstring const year = getYear(key, use_modifier);
+ if (year.empty())
+ return buf.B_("No year");
+ return year;
+}
+
+
docstring const BiblioInfo::getInfo(docstring const & key,
Buffer const & buf, bool richtext) const
{
}
+docstring const BiblioInfo::getLabel(vector<docstring> const & keys,
+ Buffer const & buf, string const & style, bool richtext,
+ docstring const & before, docstring const & after, docstring const & dialog) const
+{
+ CiteEngineType const engine_type = buf.params().citeEngineType();
+ DocumentClass const & dc = buf.params().documentClass();
+ docstring const & format = from_utf8(dc.getCiteFormat(engine_type, style, "cite"));
+ docstring ret = format;
+ vector<docstring>::const_iterator key = keys.begin();
+ vector<docstring>::const_iterator ken = keys.end();
+ for (; key != ken; ++key) {
+ BiblioInfo::const_iterator it = find(*key);
+ BibTeXInfo empty_data;
+ empty_data.key(*key);
+ BibTeXInfo & data = empty_data;
+ BibTeXInfo const * xrefptr = 0;
+ if (it != end()) {
+ data = it->second;
+ docstring const xref = data.getXRef();
+ if (!xref.empty()) {
+ BiblioInfo::const_iterator const xrefit = find(xref);
+ if (xrefit != end())
+ xrefptr = &(xrefit->second);
+ }
+ }
+ ret = data.getLabel(xrefptr, buf, ret, richtext,
+ before, after, dialog, key+1 != ken);
+ }
+ return ret;
+}
+
+
bool BiblioInfo::isBibtex(docstring const & key) const
{
BiblioInfo::const_iterator it = find(key);
}
-
vector<docstring> const BiblioInfo::getCiteStrings(
- docstring const & key, Buffer const & buf) const
-{
- CiteEngineType const engine_type = buf.params().citeEngineType();
- if (engine_type == ENGINE_TYPE_NUMERICAL)
- return getNumericalStrings(key, buf);
- else
- return getAuthorYearStrings(key, buf);
-}
-
-
-vector<docstring> const BiblioInfo::getNumericalStrings(
- docstring const & key, Buffer const & buf) const
+ vector<docstring> const & keys, vector<CitationStyle> const & styles,
+ Buffer const & buf, bool richtext, docstring const & before,
+ docstring const & after, docstring const & dialog) const
{
if (empty())
return vector<docstring>();
- docstring const author = getAbbreviatedAuthor(key);
- docstring const year = getYear(key);
- if (author.empty() || year.empty())
- return vector<docstring>();
-
- vector<CiteStyle> const & styles = citeStyles(buf.params().citeEngine(),
- buf.params().citeEngineType());
-
+ string style;
vector<docstring> vec(styles.size());
for (size_t i = 0; i != vec.size(); ++i) {
- docstring str;
-
- switch (styles[i]) {
- case CITE:
- case CITEP:
- str = from_ascii("[#ID]");
- break;
-
- case NOCITE:
- str = _("Add to bibliography only.");
- break;
-
- case CITET:
- str = author + " [#ID]";
- break;
-
- case CITEALT:
- str = author + " #ID";
- break;
-
- case CITEALP:
- str = from_ascii("#ID");
- break;
-
- case CITEAUTHOR:
- str = author;
- break;
-
- case CITEYEAR:
- str = year;
- break;
-
- case CITEYEARPAR:
- str = '(' + year + ')';
- break;
- }
-
- vec[i] = str;
+ style = styles[i].cmd;
+ vec[i] = getLabel(keys, buf, style, richtext, before, after, dialog);
}
return vec;
}
-vector<docstring> const BiblioInfo::getAuthorYearStrings(
- docstring const & key, Buffer const & buf) const
-{
- if (empty())
- return vector<docstring>();
-
- docstring const author = getAbbreviatedAuthor(key);
- docstring const year = getYear(key);
- if (author.empty() || year.empty())
- return vector<docstring>();
-
- vector<CiteStyle> const & styles = citeStyles(buf.params().citeEngine(),
- buf.params().citeEngineType());
-
- vector<docstring> vec(styles.size());
- for (size_t i = 0; i != vec.size(); ++i) {
- docstring str;
-
- switch (styles[i]) {
- case CITE:
- // jurabib only: Author/Annotator
- // (i.e. the "before" field, 2nd opt arg)
- str = author + "/<" + _("before") + '>';
- break;
-
- case NOCITE:
- str = _("Add to bibliography only.");
- break;
-
- case CITET:
- str = author + " (" + year + ')';
- break;
-
- case CITEP:
- str = '(' + author + ", " + year + ')';
- break;
-
- case CITEALT:
- str = author + ' ' + year ;
- break;
-
- case CITEALP:
- str = author + ", " + year ;
- break;
-
- case CITEAUTHOR:
- str = author;
- break;
-
- case CITEYEAR:
- str = year;
- break;
-
- case CITEYEARPAR:
- str = '(' + year + ')';
- break;
- }
- vec[i] = str;
- }
- return vec;
-}
-
-
void BiblioInfo::mergeBiblioInfo(BiblioInfo const & info)
{
bimap_.insert(info.begin(), info.end());
namespace {
- // used in xhtml to sort a list of BibTeXInfo objects
- bool lSorter(BibTeXInfo const * lhs, BibTeXInfo const * rhs)
- {
- docstring const lauth = lhs->getAbbreviatedAuthor();
- docstring const rauth = rhs->getAbbreviatedAuthor();
- docstring const lyear = lhs->getYear();
- docstring const ryear = rhs->getYear();
- docstring const ltitl = lhs->operator[]("title");
- docstring const rtitl = rhs->operator[]("title");
- return (lauth < rauth)
- || (lauth == rauth && lyear < ryear)
- || (lauth == rauth && lyear == ryear && ltitl < rtitl);
- }
+
+// used in xhtml to sort a list of BibTeXInfo objects
+bool lSorter(BibTeXInfo const * lhs, BibTeXInfo const * rhs)
+{
+ docstring const lauth = lhs->getAbbreviatedAuthor();
+ docstring const rauth = rhs->getAbbreviatedAuthor();
+ docstring const lyear = lhs->getYear();
+ docstring const ryear = rhs->getYear();
+ docstring const ltitl = lhs->operator[]("title");
+ docstring const rtitl = rhs->operator[]("title");
+ return (lauth < rauth)
+ || (lauth == rauth && lyear < ryear)
+ || (lauth == rauth && lyear == ryear && ltitl < rtitl);
+}
+
}
{
collectCitedEntries(buf);
CiteEngineType const engine_type = buf.params().citeEngineType();
- bool const numbers = (engine_type == ENGINE_TYPE_NUMERICAL);
+ bool const numbers = (engine_type & ENGINE_TYPE_NUMERICAL);
int keynumber = 0;
char modifier = 0;
last = biit;
}
}
+ // Set the labels
+ it = cited_entries_.begin();
+ for (; it != en; ++it) {
+ map<docstring, BibTeXInfo>::iterator const biit = bimap_.find(*it);
+ // this shouldn't happen, but...
+ if (biit == bimap_.end())
+ // ...fail gracefully, anyway.
+ continue;
+ BibTeXInfo & entry = biit->second;
+ if (numbers) {
+ entry.label(entry.citeNumber());
+ } else {
+ docstring const auth = entry.getAbbreviatedAuthor(buf, false);
+ // we do it this way so as to access the xref, if necessary
+ // note that this also gives us the modifier
+ docstring const year = getYear(*it, buf, true);
+ if (!auth.empty() && !year.empty())
+ entry.label(auth + ' ' + year);
+ else
+ entry.label(entry.key());
+ }
+ }
}
//
//////////////////////////////////////////////////////////////////////
-namespace {
-
-
-char const * const citeCommands[] = {
- "cite", "citet", "citep", "citealt", "citealp",
- "citeauthor", "citeyear", "citeyearpar", "nocite" };
-
-unsigned int const nCiteCommands =
- sizeof(citeCommands) / sizeof(char *);
-
-CiteStyle const citeStylesArray[] = {
- CITE, CITET, CITEP, CITEALT, CITEALP,
- CITEAUTHOR, CITEYEAR, CITEYEARPAR, NOCITE };
-
-unsigned int const nCiteStyles =
- sizeof(citeStylesArray) / sizeof(CiteStyle);
-
-CiteStyle const citeStylesFull[] = {
- CITET, CITEP, CITEALT, CITEALP, CITEAUTHOR };
-
-unsigned int const nCiteStylesFull =
- sizeof(citeStylesFull) / sizeof(CiteStyle);
-
-CiteStyle const citeStylesUCase[] = {
- CITET, CITEP, CITEALT, CITEALP, CITEAUTHOR };
-
-unsigned int const nCiteStylesUCase =
- sizeof(citeStylesUCase) / sizeof(CiteStyle);
-
-} // namespace anon
-
CitationStyle citationStyleFromString(string const & command)
{
- CitationStyle s;
+ CitationStyle cs;
if (command.empty())
- return s;
+ return cs;
string cmd = command;
if (cmd[0] == 'C') {
- s.forceUpperCase = true;
+ cs.forceUpperCase = true;
cmd[0] = 'c';
}
size_t const n = cmd.size() - 1;
- if (cmd != "cite" && cmd[n] == '*') {
- s.full = true;
+ if (cmd[n] == '*') {
+ cs.fullAuthorList = true;
cmd = cmd.substr(0, n);
}
- char const * const * const last = citeCommands + nCiteCommands;
- char const * const * const ptr = find(citeCommands, last, cmd);
-
- if (ptr != last) {
- size_t idx = ptr - citeCommands;
- s.style = citeStylesArray[idx];
- }
- return s;
+ cs.cmd = cmd;
+ return cs;
}
-string citationStyleToString(const CitationStyle & s)
+string citationStyleToString(const CitationStyle & cs)
{
- string cite = citeCommands[s.style];
- if (s.full) {
- CiteStyle const * last = citeStylesFull + nCiteStylesFull;
- if (std::find(citeStylesFull, last, s.style) != last)
- cite += '*';
- }
-
- if (s.forceUpperCase) {
- CiteStyle const * last = citeStylesUCase + nCiteStylesUCase;
- if (std::find(citeStylesUCase, last, s.style) != last)
- cite[0] = 'C';
- }
-
- return cite;
-}
-
-vector<CiteStyle> citeStyles(CiteEngine engine, CiteEngineType engine_type)
-{
- vector<CiteStyle> styles(0);
-
- if (engine_type == ENGINE_TYPE_AUTHORYEAR) {
- switch (engine) {
- case ENGINE_BASIC:
- styles.push_back(CITE);
- break;
- case ENGINE_JURABIB:
- styles.push_back(CITE);
- case ENGINE_NATBIB:
- styles.push_back(CITET);
- styles.push_back(CITEP);
- styles.push_back(CITEALT);
- styles.push_back(CITEALP);
- styles.push_back(CITEAUTHOR);
- styles.push_back(CITEYEAR);
- styles.push_back(CITEYEARPAR);
- break;
- }
- } else {
- switch (engine) {
- case ENGINE_BASIC:
- styles.push_back(CITE);
- break;
- case ENGINE_JURABIB:
- styles.push_back(CITE);
- case ENGINE_NATBIB:
- styles.push_back(CITET);
- styles.push_back(CITEALT);
- styles.push_back(CITEAUTHOR);
- styles.push_back(CITEP);
- styles.push_back(CITEALP);
- styles.push_back(CITEYEAR);
- styles.push_back(CITEYEARPAR);
- break;
- }
- }
-
- styles.push_back(NOCITE);
-
- return styles;
+ string cmd = cs.cmd;
+ if (cs.forceUpperCase)
+ cmd[0] = 'C';
+ if (cs.fullAuthorList)
+ cmd += '*';
+ return cmd;
}
} // namespace lyx
-