X-Git-Url: https://git.lyx.org/gitweb/?a=blobdiff_plain;f=src%2Finsets%2FInsetBibtex.cpp;h=2d164969e73bd14c2724b3b5e78428656da7fa4e;hb=ac61e1c77b4461b1033ac8039ec41533aecdbbae;hp=88ff6649676b3c9bfc5ec5a4038d82bb054e9d4c;hpb=c420c81ec214796f3bbacc123991ae3ddf92a21f;p=lyx.git diff --git a/src/insets/InsetBibtex.cpp b/src/insets/InsetBibtex.cpp index 88ff664967..2d164969e7 100644 --- a/src/insets/InsetBibtex.cpp +++ b/src/insets/InsetBibtex.cpp @@ -5,6 +5,7 @@ * * \author Alejandro Aguilar Sierra * \author Richard Heck (BibTeX parser improvements) + * \author Jürgen Spitzmüller * * Full author contact details are available in file CREDITS. */ @@ -16,17 +17,19 @@ #include "BiblioInfo.h" #include "Buffer.h" #include "BufferParams.h" +#include "CiteEnginesList.h" #include "Cursor.h" #include "DispatchResult.h" #include "Encoding.h" +#include "Exporter.h" #include "Format.h" #include "FuncRequest.h" #include "FuncStatus.h" -#include "Language.h" #include "LaTeXFeatures.h" #include "output_xhtml.h" #include "OutputParams.h" #include "PDFOptions.h" +#include "texstream.h" #include "TextClass.h" #include "frontends/alert.h" @@ -40,7 +43,7 @@ #include "support/gettext.h" #include "support/lstrings.h" #include "support/os.h" -#include "support/Path.h" +#include "support/PathChanger.h" #include "support/textutils.h" #include @@ -57,14 +60,20 @@ namespace os = support::os; InsetBibtex::InsetBibtex(Buffer * buf, InsetCommandParams const & p) : InsetCommand(buf, p) { - buffer().invalidateBibinfoCache(); + buffer().invalidateBibfileCache(); + buffer().removeBiblioTempFiles(); } InsetBibtex::~InsetBibtex() { - if (isBufferLoaded()) - buffer().invalidateBibfileCache(); + 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_-> invalidateBibfileCache(); + buffer_->removeBiblioTempFiles(); + } } @@ -75,6 +84,7 @@ ParamInfo const & InsetBibtex::findInfo(string const & /* cmdName */) param_info_.add("btprint", ParamInfo::LATEX_OPTIONAL); param_info_.add("bibfiles", ParamInfo::LATEX_REQUIRED); param_info_.add("options", ParamInfo::LYX_INTERNAL); + param_info_.add("biblatexopts", ParamInfo::LATEX_OPTIONAL); } return param_info_; } @@ -99,13 +109,15 @@ void InsetBibtex::doDispatch(Cursor & cur, FuncRequest & cmd) if (message.type_ == WarningException) { Alert::warning(message.title_, message.details_); cur.noScreenUpdate(); - } else - throw message; + } else + throw; break; } - // + + cur.recordUndo(); setParams(p); buffer().invalidateBibfileCache(); + buffer().removeBiblioTempFiles(); cur.forceBufferUpdate(); break; } @@ -140,9 +152,10 @@ void InsetBibtex::editDatabases() const int nr_databases = bibfilelist.size(); if (nr_databases > 1) { - docstring message = bformat(_("The BibTeX inset includes %1$s databases.\n" + docstring const engine = usingBiblatex() ? _("Biblatex") : _("BibTeX"); + docstring message = bformat(_("The %1$s[[BibTeX/Biblatex]] inset includes %2$s databases.\n" "If you proceed, all of them will be opened."), - convert(nr_databases)); + engine, convert(nr_databases)); int const ret = Alert::prompt(_("Open Databases?"), message, 0, 1, _("&Cancel"), _("&Proceed")); @@ -154,35 +167,37 @@ void InsetBibtex::editDatabases() const vector::const_iterator en = bibfilelist.end(); for (; it != en; ++it) { FileName const bibfile = getBibTeXPath(*it, buffer()); - formats.edit(buffer(), bibfile, - formats.getFormatFromFile(bibfile)); + theFormats().edit(buffer(), bibfile, + theFormats().getFormatFromFile(bibfile)); } } +bool InsetBibtex::usingBiblatex() const +{ + return buffer().masterParams().useBiblatex(); +} + + docstring InsetBibtex::screenLabel() const { - return _("BibTeX Generated Bibliography"); + return usingBiblatex() ? _("Biblatex Generated Bibliography") + : _("BibTeX Generated Bibliography"); } docstring InsetBibtex::toolTip(BufferView const & /*bv*/, int /*x*/, int /*y*/) const { - docstring item = from_ascii("* "); - docstring tip = _("Databases:") + "\n"; + docstring tip = _("Databases:"); vector bibfilelist = getVectorFromString(getParam("bibfiles")); - if (bibfilelist.empty()) { - tip += item; - tip += _("none"); - } else { - vector::const_iterator it = bibfilelist.begin(); - vector::const_iterator en = bibfilelist.end(); - for (; it != en; ++it) { - tip += item; - tip += *it + "\n"; - } - } + tip += "
    "; + if (bibfilelist.empty()) + tip += "
  • " + _("none") + "
  • "; + else + for (docstring const & bibfile : bibfilelist) + tip += "
  • " + bibfile + "
  • "; + tip += "
"; // Style-Options bool toc = false; @@ -194,131 +209,72 @@ docstring InsetBibtex::toolTip(BufferView const & /*bv*/, int /*x*/, int /*y*/) style = split(style, bibtotoc, char_type(',')); } - tip += _("Style File:") +"\n"; - tip += item; - if (!style.empty()) - tip += style; - else - tip += _("none"); + docstring const btprint = getParam("btprint"); + if (!usingBiblatex()) { + tip += _("Style File:"); + tip += "
  • " + (style.empty() ? _("none") : style) + "
"; - tip += "\n" + _("Lists:") + " "; - docstring btprint = getParam("btprint"); + tip += _("Lists:") + " "; if (btprint == "btPrintAll") tip += _("all references"); else if (btprint == "btPrintNotCited") tip += _("all uncited references"); else tip += _("all cited references"); - - if (toc) { - tip += ", "; - tip += _("included in TOC"); + if (toc) { + tip += ", "; + tip += _("included in TOC"); + } + if (!buffer().parent() + && buffer().params().multibib == "child") { + tip += "
"; + tip += _("Note: This bibliography is not output, since bibliographies in the master file " + "are not allowed with the setting 'Multiple bibliographies per child document'"); + } + } else { + tip += _("Lists:") + " "; + if (btprint == "bibbysection") + tip += _("all reference units"); + else if (btprint == "btPrintAll") + tip += _("all references"); + else + tip += _("all cited references"); + if (toc) { + tip += ", "; + tip += _("included in TOC"); + } + if (!getParam("biblatexopts").empty()) { + tip += "
"; + tip += _("Options: ") + getParam("biblatexopts"); + } } return tip; } -static string normalizeName(Buffer const & buffer, - OutputParams const & runparams, string const & name, string const & ext) +void InsetBibtex::latex(otexstream & os, OutputParams const & runparams) const { - string const fname = makeAbsPath(name, buffer.filePath()).absFileName(); - if (FileName::isAbsolute(name) || !FileName(fname + ext).isReadableFile()) - return name; - if (!runparams.nice) - return fname; - - // FIXME UNICODE - return to_utf8(makeRelPath(from_utf8(fname), - from_utf8(buffer.masterBuffer()->filePath()))); -} - - -int InsetBibtex::latex(odocstream & os, OutputParams const & runparams) const -{ - // the sequence of the commands: + // The sequence of the commands: + // With normal BibTeX: // 1. \bibliographystyle{style} // 2. \addcontentsline{...} - if option bibtotoc set // 3. \bibliography{database} - // and with bibtopic: + // With bibtopic: // 1. \bibliographystyle{style} // 2. \begin{btSect}{database} // 3. \btPrint{Cited|NotCited|All} // 4. \end{btSect} + // With Biblatex: + // \printbibliography[biblatexopts] + // or + // \bibbysection[biblatexopts] - if btprint is "bibbysection" + + // chapterbib does not allow bibliographies in the master + if (!usingBiblatex() && !runparams.is_child + && buffer().params().multibib == "child") + return; - // Database(s) - // If we are processing the LaTeX file in a temp directory then - // copy the .bib databases to this temp directory, mangling their - // names in the process. Store this mangled name in the list of - // all databases. - // (We need to do all this because BibTeX *really*, *really* - // can't handle "files with spaces" and Windows users tend to - // use such filenames.) - // Otherwise, store the (maybe absolute) path to the original, - // unmangled database name. - vector bibfilelist = getVectorFromString(getParam("bibfiles")); - vector::const_iterator it = bibfilelist.begin(); - vector::const_iterator en = bibfilelist.end(); - odocstringstream dbs; - bool didone = false; - - for (; it != en; ++it) { - string utf8input = to_utf8(*it); - string database = - normalizeName(buffer(), runparams, utf8input, ".bib"); - FileName const try_in_file = - makeAbsPath(database + ".bib", buffer().filePath()); - bool const not_from_texmf = try_in_file.isReadableFile(); - - if (!runparams.inComment && !runparams.dryrun && !runparams.nice && - not_from_texmf) { - // mangledFileName() needs the extension - DocFileName const in_file = DocFileName(try_in_file); - database = removeExtension(in_file.mangledFileName()); - FileName const out_file = makeAbsPath(database + ".bib", - buffer().masterBuffer()->temppath()); - - bool const success = in_file.copyTo(out_file); - if (!success) { - lyxerr << "Failed to copy '" << in_file - << "' to '" << out_file << "'" - << endl; - } - } else if (!runparams.inComment && runparams.nice && not_from_texmf) { - if (!isValidLaTeXFileName(database)) { - frontend::Alert::warning(_("Invalid filename"), - _("The following filename will cause troubles " - "when running the exported file through LaTeX: ") + - from_utf8(database)); - } - if (!isValidDVIFileName(database)) { - frontend::Alert::warning(_("Problematic filename for DVI"), - _("The following filename can cause troubles " - "when running the exported file through LaTeX " - "and opening the resulting DVI: ") + - from_utf8(database), true); - } - } - - if (didone) - dbs << ','; - else - didone = true; - // FIXME UNICODE - dbs << from_utf8(latex_path(database)); - } - docstring const db_out = dbs.str(); - - // Post this warning only once. - static bool warned_about_spaces = false; - if (!warned_about_spaces && - runparams.nice && db_out.find(' ') != docstring::npos) { - warned_about_spaces = true; - Alert::warning(_("Export Warning!"), - _("There are spaces in the paths to your BibTeX databases.\n" - "BibTeX will be unable to find them.")); - } - // Style-Options string style = to_utf8(getParam("options")); // maybe empty! and with bibtotoc string bibtotoc; if (prefixIs(style, "bibtotoc")) { @@ -327,91 +283,110 @@ int InsetBibtex::latex(odocstream & os, OutputParams const & runparams) const style = split(style, bibtotoc, ','); } - // line count - int nlines = 0; - - if (!style.empty()) { - string base = normalizeName(buffer(), runparams, style, ".bst"); - FileName const try_in_file = - makeAbsPath(base + ".bst", buffer().filePath()); - bool const not_from_texmf = try_in_file.isReadableFile(); - // If this style does not come from texmf and we are not - // exporting to .tex copy it to the tmp directory. - // This prevents problems with spaces and 8bit charcaters - // in the file name. - if (!runparams.inComment && !runparams.dryrun && !runparams.nice && - not_from_texmf) { - // use new style name - DocFileName const in_file = DocFileName(try_in_file); - base = removeExtension(in_file.mangledFileName()); - FileName const out_file = makeAbsPath(base + ".bst", - buffer().masterBuffer()->temppath()); - bool const success = in_file.copyTo(out_file); - if (!success) { - lyxerr << "Failed to copy '" << in_file - << "' to '" << out_file << "'" - << endl; - } - } - // FIXME UNICODE - os << "\\bibliographystyle{" - << from_utf8(latex_path(normalizeName(buffer(), runparams, base, ".bst"))) - << "}\n"; - nlines += 1; - } - - // Post this warning only once. - static bool warned_about_bst_spaces = false; - if (!warned_about_bst_spaces && runparams.nice && contains(style, ' ')) { - warned_about_bst_spaces = true; - Alert::warning(_("Export Warning!"), - _("There are spaces in the path to your BibTeX style file.\n" - "BibTeX will be unable to find it.")); - } - - if (!db_out.empty() && buffer().params().use_bibtopic) { - os << "\\begin{btSect}{" << db_out << "}\n"; + if (usingBiblatex()) { + // Options + string opts = to_utf8(getParam("biblatexopts")); + // bibtotoc-Option + if (!bibtotoc.empty()) + opts = opts.empty() ? "heading=bibintoc" : "heading=bibintoc," + opts; + // The bibliography command docstring btprint = getParam("btprint"); - if (btprint.empty()) - // default - btprint = from_ascii("btPrintCited"); - os << "\\" << btprint << "\n" - << "\\end{btSect}\n"; - nlines += 3; - } - - // bibtotoc-Option - if (!bibtotoc.empty() && !buffer().params().use_bibtopic) { - // set label for hyperref, see http://www.lyx.org/trac/ticket/6470 - if (buffer().params().pdfoptions().use_hyperref) - os << "\\phantomsection"; - if (buffer().params().documentClass().hasLaTeXLayout("chapter")) - os << "\\addcontentsline{toc}{chapter}{\\bibname}"; - else if (buffer().params().documentClass().hasLaTeXLayout("section")) - os << "\\addcontentsline{toc}{section}{\\refname}"; - } - - if (!db_out.empty() && !buffer().params().use_bibtopic) { - docstring btprint = getParam("btprint"); - if (btprint == "btPrintAll") { + if (btprint == "btPrintAll") os << "\\nocite{*}\n"; - nlines += 1; + if (btprint == "bibbysection" && !buffer().masterParams().multibib.empty()) + os << "\\bibbysection"; + else + os << "\\printbibliography"; + if (!opts.empty()) + os << "[" << opts << "]"; + os << "\n"; + } else {// using BibTeX + // Database(s) + vector const db_out = + buffer().prepareBibFilePaths(runparams, getBibFiles(), false); + // Style options + if (style == "default") + style = buffer().masterParams().defaultBiblioStyle(); + if (!style.empty() && !buffer().masterParams().useBibtopic()) { + string base = buffer().masterBuffer()->prepareFileNameForLaTeX(style, ".bst", runparams.nice); + FileName const try_in_file = + makeAbsPath(base + ".bst", buffer().filePath()); + bool const not_from_texmf = try_in_file.isReadableFile(); + // If this style does not come from texmf and we are not + // exporting to .tex copy it to the tmp directory. + // This prevents problems with spaces and 8bit characters + // in the file name. + if (!runparams.inComment && !runparams.dryrun && !runparams.nice && + not_from_texmf) { + // use new style name + DocFileName const in_file = DocFileName(try_in_file); + base = removeExtension(in_file.mangledFileName()); + FileName const out_file = makeAbsPath(base + ".bst", + buffer().masterBuffer()->temppath()); + bool const success = in_file.copyTo(out_file); + if (!success) { + LYXERR0("Failed to copy '" << in_file + << "' to '" << out_file << "'"); + } + } + // FIXME UNICODE + os << "\\bibliographystyle{" + << from_utf8(latex_path(buffer().prepareFileNameForLaTeX(base, ".bst", runparams.nice))) + << "}\n"; + } + // Warn about spaces in bst path. Warn only once. + static bool warned_about_bst_spaces = false; + if (!warned_about_bst_spaces && runparams.nice && contains(style, ' ')) { + warned_about_bst_spaces = true; + Alert::warning(_("Export Warning!"), + _("There are spaces in the path to your BibTeX style file.\n" + "BibTeX will be unable to find it.")); + } + // Handle the bibtopic case + if (!db_out.empty() && buffer().masterParams().useBibtopic()) { + os << "\\begin{btSect}"; + if (!style.empty()) + os << "[" << style << "]"; + os << "{" << getStringFromVector(db_out) << "}\n"; + docstring btprint = getParam("btprint"); + if (btprint.empty()) + // default + btprint = from_ascii("btPrintCited"); + os << "\\" << btprint << "\n" + << "\\end{btSect}\n"; + } + // bibtotoc option + if (!bibtotoc.empty() && !buffer().masterParams().useBibtopic()) { + // set label for hyperref, see http://www.lyx.org/trac/ticket/6470 + if (buffer().masterParams().pdfoptions().use_hyperref) + os << "\\phantomsection"; + if (buffer().masterParams().documentClass().hasLaTeXLayout("chapter")) + os << "\\addcontentsline{toc}{chapter}{\\bibname}"; + else if (buffer().masterParams().documentClass().hasLaTeXLayout("section")) + os << "\\addcontentsline{toc}{section}{\\refname}"; + } + // The bibliography command + if (!db_out.empty() && !buffer().masterParams().useBibtopic()) { + docstring btprint = getParam("btprint"); + if (btprint == "btPrintAll") { + os << "\\nocite{*}\n"; + } + os << "\\bibliography{" << getStringFromVector(db_out) << "}\n"; } - os << "\\bibliography{" << db_out << "}\n"; - nlines += 1; } - - return nlines; } -support::FileNameList InsetBibtex::getBibFiles() const +support::FileNamePairList InsetBibtex::getBibFiles() const { FileName path(buffer().filePath()); support::PathChanger p(path); - - support::FileNameList vec; - + + // We need to store both the real FileName and the way it is entered + // (with full path, rel path or as a single file name). + // The latter is needed for biblatex's central bibfile macro. + support::FileNamePairList vec; + vector bibfilelist = getVectorFromString(getParam("bibfiles")); vector::const_iterator it = bibfilelist.begin(); vector::const_iterator en = bibfilelist.end(); @@ -419,11 +394,11 @@ support::FileNameList InsetBibtex::getBibFiles() const FileName const file = getBibTeXPath(*it, buffer()); if (!file.empty()) - vec.push_back(file); + vec.push_back(make_pair(*it, file)); else LYXERR0("Couldn't find " + to_utf8(*it) + " in InsetBibtex::getBibFiles()!"); } - + return vec; } @@ -482,7 +457,7 @@ namespace { /// @return true if a string of length > 0 could be read. /// bool readTypeOrKey(docstring & val, ifdocstream & ifs, - docstring const & delimChars, docstring const & illegalChars, + docstring const & delimChars, docstring const & illegalChars, charCase chCase) { char_type ch; @@ -502,10 +477,10 @@ namespace { // read value bool legalChar = true; - while (ifs && !isSpace(ch) && + while (ifs && !isSpace(ch) && delimChars.find(ch) == docstring::npos && (legalChar = (illegalChars.find(ch) == docstring::npos)) - ) + ) { if (chCase == makeLowerCase) val += lowercase(ch); @@ -513,7 +488,7 @@ namespace { val += ch; ifs.get(ch); } - + if (!legalChar) { ifs.putback(ch); return false; @@ -574,33 +549,33 @@ namespace { do { ifs.get(ch); } while (ifs && isSpace(ch)); - + if (!ifs) return false; - + // We now have the first non-whitespace character // We'll collapse adjacent whitespace. bool lastWasWhiteSpace = false; - + // inside this delimited text braces must match. // Thus we can have a closing delimiter only // when nestLevel == 0 int nestLevel = 0; - + while (ifs && (nestLevel > 0 || ch != delim)) { if (isSpace(ch)) { lastWasWhiteSpace = true; ifs.get(ch); continue; } - // We output the space only after we stop getting + // We output the space only after we stop getting // whitespace so as not to output any whitespace // at the end of the value. if (lastWasWhiteSpace) { lastWasWhiteSpace = false; val += ' '; } - + val += ch; // update nesting level @@ -610,7 +585,7 @@ namespace { break; case '}': --nestLevel; - if (nestLevel < 0) + if (nestLevel < 0) return false; break; } @@ -666,16 +641,16 @@ namespace { return true; } -} +} // namespace -void InsetBibtex::collectBibKeys(InsetIterator const & /*di*/) const +void InsetBibtex::collectBibKeys(InsetIterator const & /*di*/, FileNameList & checkedFiles) const { - parseBibTeXFiles(); + parseBibTeXFiles(checkedFiles); } -void InsetBibtex::parseBibTeXFiles() const +void InsetBibtex::parseBibTeXFiles(FileNameList & checkedFiles) const { // This bibtex parser is a first step to parse bibtex files // more precisely. @@ -698,12 +673,19 @@ void InsetBibtex::parseBibTeXFiles() const BiblioInfo keylist; - support::FileNameList const files = getBibFiles(); - support::FileNameList::const_iterator it = files.begin(); - support::FileNameList::const_iterator en = files.end(); + support::FileNamePairList const files = getBibFiles(); + support::FileNamePairList::const_iterator it = files.begin(); + support::FileNamePairList::const_iterator en = files.end(); for (; it != en; ++ it) { - ifdocstream ifs(it->toFilesystemEncoding().c_str(), - ios_base::in, buffer().params().encoding().iconvName()); + FileName const bibfile = it->second; + if (find(checkedFiles.begin(), checkedFiles.end(), bibfile) != checkedFiles.end()) + // already checked this one. Skip. + continue; + else + // record that we check this. + checkedFiles.push_back(bibfile); + ifdocstream ifs(bibfile.toFilesystemEncoding().c_str(), + ios_base::in, buffer().masterParams().encoding().iconvName()); char_type ch; VarMap strings; @@ -767,13 +749,13 @@ void InsetBibtex::parseBibTeXFiles() const // next char must be an equal sign ifs.get(ch); if (!ifs || ch != '=') { - lyxerr << "BibTeX Parser: No `=' after string name: " << + lyxerr << "BibTeX Parser: No `=' after string name: " << name << "." << std::endl; continue; } if (!readValue(value, ifs, strings)) { - lyxerr << "BibTeX Parser: Unable to read value for string: " << + lyxerr << "BibTeX Parser: Unable to read value for string: " << name << "." << std::endl; continue; } @@ -797,7 +779,7 @@ void InsetBibtex::parseBibTeXFiles() const docstring key; if (!readTypeOrKey(key, ifs, from_ascii(","), from_ascii("}"), keepCase)) { - lyxerr << "BibTeX Parser: Unable to read key for entry type:" << + lyxerr << "BibTeX Parser: Unable to read key for entry type:" << entryType << "." << std::endl; continue; } @@ -808,7 +790,7 @@ void InsetBibtex::parseBibTeXFiles() const } ///////////////////////////////////////////// - // now we have a key, so we will add an entry + // now we have a key, so we will add an entry // (even if it's empty, as bibtex does) // // we now read the field = value pairs. @@ -819,13 +801,13 @@ void InsetBibtex::parseBibTeXFiles() const docstring value; docstring data; BibTeXInfo keyvalmap(key, entryType); - + bool readNext = removeWSAndComma(ifs); - + while (ifs && readNext) { // read field name - if (!readTypeOrKey(name, ifs, from_ascii("="), + if (!readTypeOrKey(name, ifs, from_ascii("="), from_ascii("{}(),"), makeLowerCase) || !ifs) break; @@ -871,14 +853,14 @@ void InsetBibtex::parseBibTeXFiles() const FileName InsetBibtex::getBibTeXPath(docstring const & filename, Buffer const & buf) { string texfile = changeExtension(to_utf8(filename), "bib"); - // note that, if the filename can be found directly from the path, + // note that, if the filename can be found directly from the path, // findtexfile will just return a FileName object for that path. FileName file(findtexfile(texfile, "bib")); if (file.empty()) file = FileName(makeAbsPath(texfile, buf.filePath())); return file; } - + bool InsetBibtex::addDatabase(docstring const & db) { @@ -914,36 +896,85 @@ bool InsetBibtex::delDatabase(docstring const & db) void InsetBibtex::validate(LaTeXFeatures & features) const { - if (features.bufferParams().use_bibtopic) + BufferParams const & mparams = features.buffer().masterParams(); + if (mparams.useBibtopic()) features.require("bibtopic"); + else if (!mparams.useBiblatex() && mparams.multibib == "child") + features.require("chapterbib"); // FIXME XHTML // It'd be better to be able to get this from an InsetLayout, but at present // InsetLayouts do not seem really to work for things that aren't InsetTexts. if (features.runparams().flavor == OutputParams::HTML) - features.addPreambleSnippet(""); + "span.bibtexlabel:after{ content: \"] \"; }"); +} + + +int InsetBibtex::plaintext(odocstringstream & os, + OutputParams const & op, size_t max_length) const +{ + docstring const reflabel = buffer().B_("References"); + + // We could output more information here, e.g., what databases are included + // and information about options. But I don't necessarily see any reason to + // do this right now. + if (op.for_tooltip || op.for_toc || op.for_search) { + os << '[' << reflabel << ']' << '\n'; + return PLAINTEXT_NEWLINE; + } + + BiblioInfo bibinfo = buffer().masterBibInfo(); + bibinfo.makeCitationLabels(buffer()); + vector const & cites = bibinfo.citedEntries(); + + size_t start_size = os.str().size(); + docstring refoutput; + refoutput += reflabel + "\n\n"; + + // Tell BiblioInfo our purpose + CiteItem ci; + ci.context = CiteItem::Export; + + // Now we loop over the entries + vector::const_iterator vit = cites.begin(); + vector::const_iterator const ven = cites.end(); + for (; vit != ven; ++vit) { + if (start_size + refoutput.size() >= max_length) + break; + BiblioInfo::const_iterator const biit = bibinfo.find(*vit); + if (biit == bibinfo.end()) + continue; + BibTeXInfo const & entry = biit->second; + refoutput += "[" + entry.label() + "] "; + // FIXME Right now, we are calling BibInfo::getInfo on the key, + // which will give us all the cross-referenced info. But for every + // entry, so there's a lot of repitition. This should be fixed. + refoutput += bibinfo.getInfo(entry.key(), buffer(), ci) + "\n\n"; + } + os << refoutput; + return refoutput.size(); } -// FIXME +// FIXME // docstring InsetBibtex::entriesAsXHTML(vector const & entries) // And then here just: entriesAsXHTML(buffer().masterBibInfo().citedEntries()) docstring InsetBibtex::xhtml(XHTMLStream & xs, OutputParams const &) const { BiblioInfo const & bibinfo = buffer().masterBibInfo(); - vector const & cites = bibinfo.citedEntries(); - CiteEngine const engine = buffer().params().citeEngine(); - bool const numbers = - (engine == ENGINE_BASIC || engine == ENGINE_NATBIB_NUMERICAL); - - docstring reflabel = from_ascii("References"); - Language const * l = buffer().params().language; - if (l) - reflabel = translateIfPossible(reflabel, l->code()); - + bool const all_entries = getParam("btprint") == "btPrintAll"; + vector const & cites = + all_entries ? bibinfo.getKeys() : bibinfo.citedEntries(); + + docstring const reflabel = buffer().B_("References"); + + // tell BiblioInfo our purpose + CiteItem ci; + ci.context = CiteItem::Export; + ci.richtext = true; + ci.max_key_size = UINT_MAX; + xs << html::StartTag("h2", "class='bibtex'") << reflabel << html::EndTag("h2") @@ -956,49 +987,43 @@ docstring InsetBibtex::xhtml(XHTMLStream & xs, OutputParams const &) const BiblioInfo::const_iterator const biit = bibinfo.find(*vit); if (biit == bibinfo.end()) continue; + BibTeXInfo const & entry = biit->second; - xs << html::StartTag("div", "class='bibtexentry'"); - // FIXME XHTML - // The same name/id problem we have elsewhere. - string const attr = "id='" + to_utf8(entry.key()) + "'"; - xs << html::CompTag("a", attr); - docstring citekey; - if (numbers) - citekey = entry.citeNumber(); - else { - docstring const auth = entry.getAbbreviatedAuthor(); - // we do it this way so as to access the xref, if necessary - // note that this also gives us the modifier - docstring const year = bibinfo.getYear(*vit, true); - if (!auth.empty() && !year.empty()) - citekey = auth + ' ' + year; + string const attr = "class='bibtexentry' id='LyXCite-" + + to_utf8(html::cleanAttr(entry.key())) + "'"; + xs << html::StartTag("div", attr); + + // don't print labels if we're outputting all entries + if (!all_entries) { + xs << html::StartTag("span", "class='bibtexlabel'") + << entry.label() + << html::EndTag("span"); } - if (citekey.empty()) { - citekey = entry.label(); - if (citekey.empty()) - citekey = entry.key(); - } - xs << html::StartTag("span", "class='bibtexlabel'") - << citekey - << html::EndTag("span"); + // FIXME Right now, we are calling BibInfo::getInfo on the key, // which will give us all the cross-referenced info. But for every // entry, so there's a lot of repitition. This should be fixed. - xs << html::StartTag("span", "class='bibtexinfo'") - << XHTMLStream::ESCAPE_AND - << bibinfo.getInfo(entry.key(), buffer(), true) - << html::EndTag("span") - << html::EndTag("div"); - xs.cr(); + xs << html::StartTag("span", "class='bibtexinfo'") + << XHTMLStream::ESCAPE_AND + << bibinfo.getInfo(entry.key(), buffer(), ci) + << html::EndTag("span") + << html::EndTag("div") + << html::CR(); } xs << html::EndTag("div"); return docstring(); } -docstring InsetBibtex::contextMenuName() const +void InsetBibtex::write(ostream & os) const +{ + params().Write(os, &buffer()); +} + + +string InsetBibtex::contextMenuName() const { - return from_ascii("context-bibtex"); + return "context-bibtex"; }