]> git.lyx.org Git - lyx.git/blobdiff - src/insets/InsetBibtex.cpp
de.po
[lyx.git] / src / insets / InsetBibtex.cpp
index a90511077365d563a34635cc79d4743a31560244..ae76a7f26c0c2bd7e8270fc35e322f3ec501e63c 100644 (file)
 #include "FuncRequest.h"
 #include "FuncStatus.h"
 #include "LaTeXFeatures.h"
+#include "output_latex.h"
 #include "output_xhtml.h"
 #include "OutputParams.h"
 #include "PDFOptions.h"
 #include "texstream.h"
 #include "TextClass.h"
+#include "TocBackend.h"
 
 #include "frontends/alert.h"
 
 #include "support/convert.h"
 #include "support/debug.h"
 #include "support/docstream.h"
+#include "support/docstring_list.h"
 #include "support/ExceptionMessage.h"
 #include "support/FileNameList.h"
 #include "support/filetools.h"
@@ -59,22 +62,7 @@ namespace os = support::os;
 
 InsetBibtex::InsetBibtex(Buffer * buf, InsetCommandParams const & p)
        : InsetCommand(buf, p)
-{
-       buffer().invalidateBibfileCache();
-       buffer().removeBiblioTempFiles();
-}
-
-
-InsetBibtex::~InsetBibtex()
-{
-       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();
-       }
-}
+{}
 
 
 ParamInfo const & InsetBibtex::findInfo(string const & /* cmdName */)
@@ -84,6 +72,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("encoding", ParamInfo::LYX_INTERNAL);
                param_info_.add("biblatexopts", ParamInfo::LATEX_OPTIONAL);
        }
        return param_info_;
@@ -116,8 +105,7 @@ void InsetBibtex::doDispatch(Cursor & cur, FuncRequest & cmd)
 
                cur.recordUndo();
                setParams(p);
-               buffer().invalidateBibfileCache();
-               buffer().removeBiblioTempFiles();
+               cur.buffer()->clearBibFileCache();
                cur.forceBufferUpdate();
                break;
        }
@@ -166,7 +154,7 @@ void InsetBibtex::editDatabases() const
        vector<docstring>::const_iterator it = bibfilelist.begin();
        vector<docstring>::const_iterator en = bibfilelist.end();
        for (; it != en; ++it) {
-               FileName const bibfile = getBibTeXPath(*it, buffer());
+               FileName const bibfile = buffer().getBibfilePath(*it);
                theFormats().edit(buffer(), bibfile,
                     theFormats().getFormatFromFile(bibfile));
        }
@@ -244,8 +232,7 @@ docstring InsetBibtex::toolTip(BufferView const & /*bv*/, int /*x*/, int /*y*/)
                        tip += _("included in TOC");
                }
                if (!getParam("biblatexopts").empty()) {
-                       if (toc)
-                               tip += "<br />";
+                       tip += "<br />";
                        tip += _("Options: ") + getParam("biblatexopts");
                }
        }
@@ -343,6 +330,19 @@ void InsetBibtex::latex(otexstream & os, OutputParams const & runparams) const
                                       _("There are spaces in the path to your BibTeX style file.\n"
                                                      "BibTeX will be unable to find it."));
                }
+               // Encoding
+               bool encoding_switched = false;
+               Encoding const * const save_enc = runparams.encoding;
+               docstring const encoding = getParam("encoding");
+               if (!encoding.empty() && encoding != from_ascii("default")) {
+                       Encoding const * const enc = encodings.fromLyXName(to_ascii(encoding));
+                       if (enc != runparams.encoding) {
+                               os << "\\bgroup";
+                               switchEncoding(os.os(), buffer().params(), runparams, *enc, true);
+                               runparams.encoding = enc;
+                               encoding_switched = true;
+                       }
+               }
                // Handle the bibtopic case
                if (!db_out.empty() && buffer().masterParams().useBibtopic()) {
                        os << "\\begin{btSect}";
@@ -374,34 +374,20 @@ void InsetBibtex::latex(otexstream & os, OutputParams const & runparams) const
                        }
                        os << "\\bibliography{" << getStringFromVector(db_out) << "}\n";
                }
+               if (encoding_switched){
+                       // Switch back
+                       switchEncoding(os.os(), buffer().params(),
+                                      runparams, *save_enc, true, true);
+                       os << "\\egroup" << breakln;
+                       runparams.encoding = save_enc;
+               }
        }
 }
 
 
-support::FileNamePairList InsetBibtex::getBibFiles() const
+docstring_list InsetBibtex::getBibFiles() const
 {
-       FileName path(buffer().filePath());
-       support::PathChanger p(path);
-
-       // 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<docstring> bibfilelist = getVectorFromString(getParam("bibfiles"));
-       vector<docstring>::const_iterator it = bibfilelist.begin();
-       vector<docstring>::const_iterator en = bibfilelist.end();
-       for (; it != en; ++it) {
-               FileName const file = getBibTeXPath(*it, buffer());
-
-               if (!file.empty())
-                       vec.push_back(make_pair(*it, file));
-               else
-                       LYXERR0("Couldn't find " + to_utf8(*it) + " in InsetBibtex::getBibFiles()!");
-       }
-
-       return vec;
-
+       return getVectorFromString(getParam("bibfiles"));
 }
 
 namespace {
@@ -477,11 +463,9 @@ namespace {
                        return false;
 
                // read value
-               bool legalChar = true;
                while (ifs && !isSpace(ch) &&
-                                                delimChars.find(ch) == docstring::npos &&
-                                                (legalChar = (illegalChars.find(ch) == docstring::npos))
-                                       )
+                      delimChars.find(ch) == docstring::npos &&
+                      illegalChars.find(ch) == docstring::npos)
                {
                        if (chCase == makeLowerCase)
                                val += lowercase(ch);
@@ -490,7 +474,7 @@ namespace {
                        ifs.get(ch);
                }
 
-               if (!legalChar) {
+               if (illegalChars.find(ch) != docstring::npos) {
                        ifs.putback(ch);
                        return false;
                }
@@ -645,13 +629,13 @@ namespace {
 } // 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.
@@ -665,27 +649,39 @@ void InsetBibtex::parseBibTeXFiles() const
        //   bibtex does.
        //
        // Officially bibtex does only support ASCII, but in practice
-       // you can use the encoding of the main document as long as
-       // some elements like keys and names are pure ASCII. Therefore
-       // we convert the file from the buffer encoding.
+       // you can use any encoding as long as some elements like keys
+       // and names are pure ASCII. We support specifying an encoding,
+       // and we convert the file from that (default is buffer encoding).
        // We don't restrict keys to ASCII in LyX, since our own
        // InsetBibitem can generate non-ASCII keys, and nonstandard
        // 8bit clean bibtex forks exist.
 
        BiblioInfo keylist;
 
-       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->second.toFilesystemEncoding().c_str(),
-                       ios_base::in, buffer().masterParams().encoding().iconvName());
+       docstring_list const files = getBibFiles();
+       for (auto const & bf : files) {
+               FileName const bibfile = buffer().getBibfilePath(bf);
+               if (bibfile.empty()) {
+                       LYXERR0("Unable to find path for " << bf << "!");
+                       continue;
+               }
+               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);
+               string encoding = buffer().masterParams().encoding().iconvName();
+               string const ienc = to_ascii(params()["encoding"]);
+               if (!ienc.empty() && ienc != "default" && encodings.fromLyXName(ienc))
+                       encoding = encodings.fromLyXName(ienc)->iconvName();
+               ifdocstream ifs(bibfile.toFilesystemEncoding().c_str(),
+                       ios_base::in, encoding);
 
                char_type ch;
                VarMap strings;
 
                while (ifs) {
-
                        ifs.get(ch);
                        if (!ifs)
                                break;
@@ -844,18 +840,6 @@ 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,
-       // 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)
 {
        docstring bibfiles = getParam("bibfiles");
@@ -905,10 +889,44 @@ void InsetBibtex::validate(LaTeXFeatures & features) const
 }
 
 
+void InsetBibtex::updateBuffer(ParIterator const &, UpdateType)
+{
+       buffer().registerBibfiles(getBibFiles());
+       // record encoding of bib files for biblatex
+       string const enc = (params()["encoding"] == from_ascii("default")) ?
+                               string() : to_ascii(params()["encoding"]);
+       if (buffer().params().bibEncoding() != enc) {
+               buffer().params().setBibEncoding(enc);
+               buffer().invalidateBibinfoCache();
+       }
+}
+
+
+docstring InsetBibtex::getRefLabel() const
+{
+       if (buffer().masterParams().documentClass().hasLaTeXLayout("chapter"))
+               return buffer().B_("Bibliography");
+       return buffer().B_("References");
+}
+
+
+void InsetBibtex::addToToc(DocIterator const & cpit, bool output_active,
+                          UpdateType, TocBackend & backend) const
+{
+       if (!prefixIs(to_utf8(getParam("options")), "bibtotoc"))
+               return;
+
+       docstring const str = getRefLabel();
+       TocBuilder & b = backend.builder("tableofcontents");
+       b.pushItem(cpit, str, output_active);
+       b.pop();
+}
+
+
 int InsetBibtex::plaintext(odocstringstream & os,
        OutputParams const & op, size_t max_length) const
 {
-       docstring const reflabel = buffer().B_("References");
+       docstring const reflabel = getRefLabel();
 
        // 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