]> git.lyx.org Git - lyx.git/blobdiff - src/insets/InsetBibtex.cpp
Change string
[lyx.git] / src / insets / InsetBibtex.cpp
index a23c8cac4055df9f3760fc53c6127716ac9de028..a74be8e1f0ac9f67d010cf8b827fc5eb4db82d05 100644 (file)
@@ -27,8 +27,8 @@
 #include "frontends/alert.h"
 
 #include "support/debug.h"
-#include "support/ExceptionMessage.h"
 #include "support/docstream.h"
+#include "support/ExceptionMessage.h"
 #include "support/filetools.h"
 #include "support/gettext.h"
 #include "support/lstrings.h"
@@ -36,7 +36,6 @@
 #include "support/Path.h"
 #include "support/textutils.h"
 
-#include <boost/tokenizer.hpp>
 #include <limits>
 
 using namespace std;
@@ -49,26 +48,39 @@ namespace os = support::os;
 
 
 InsetBibtex::InsetBibtex(InsetCommandParams const & p)
-       : InsetCommand(p, "bibtex")
+       : InsetCommand(p, "bibtex"), bibfiles_()
 {}
 
 
-ParamInfo const & InsetBibtex::findInfo(string const & /* cmdName */)
+void InsetBibtex::setBuffer(Buffer & buffer)
 {
-       static ParamInfo param_info_;
-       if (param_info_.empty()) {
-               param_info_.add("options", true);
-               param_info_.add("btprint", true);
-               param_info_.add("bibfiles", false);
-               param_info_.add("embed", false);
+       if (buffer_) {
+               EmbeddedFileList::iterator it = bibfiles_.begin();
+               EmbeddedFileList::iterator it_end = bibfiles_.end();
+               for (; it != it_end; ++it) {
+                       try {
+                               *it = it->copyTo(&buffer);
+                       } catch (ExceptionMessage const & message) {
+                               Alert::error(message.title_, message.details_);
+                               // failed to embed
+                               it->setEmbed(false);
+                       }               
+               }
        }
-       return param_info_;
+       Inset::setBuffer(buffer);
 }
 
 
-Inset * InsetBibtex::clone() const
+ParamInfo const & InsetBibtex::findInfo(string const & /* cmdName */)
 {
-       return new InsetBibtex(*this);
+       static ParamInfo param_info_;
+       if (param_info_.empty()) {
+               param_info_.add("btprint", ParamInfo::LATEX_OPTIONAL);
+               param_info_.add("bibfiles", ParamInfo::LATEX_REQUIRED);
+               param_info_.add("embed", ParamInfo::LYX_INTERNAL);
+               param_info_.add("options", ParamInfo::LYX_INTERNAL);
+       }
+       return param_info_;
 }
 
 
@@ -93,49 +105,9 @@ void InsetBibtex::doDispatch(Cursor & cur, FuncRequest & cmd)
                        break;
                }
                //
-               InsetCommandParams orig = params();
-               // returned "embed" is composed of "true" or "false", which needs to be adjusted
-               string tmp;
-               string emb;
-               
-               string newBibfiles;
-               string newEmbedStatus;
-               
-               string bibfiles = to_utf8(p["bibfiles"]);
-               string embedStatus = to_utf8(p["embed"]);
-               
-               bibfiles = split(bibfiles, tmp, ',');
-               embedStatus = split(embedStatus, emb, ',');
-               while (!tmp.empty()) {
-                       EmbeddedFile file(changeExtension(tmp, "bib"), cur.buffer().filePath());
-                       if (!newBibfiles.empty())
-                               newBibfiles += ",";
-                       newBibfiles += tmp;
-                       if (!newEmbedStatus.empty())
-                               newEmbedStatus += ",";
-                       if (emb == "true")
-                               newEmbedStatus += file.inzipName();
-                       // Get next file name
-                       bibfiles = split(bibfiles, tmp, ',');
-                       embedStatus = split(embedStatus, emb, ',');
-               }
-               LYXERR(Debug::FILES, "Update parameters from " << p["bibfiles"]
-                       << " " << p["embed"] << " to " << newBibfiles << " "
-                       << newEmbedStatus);
-               p["bibfiles"] = from_utf8(newBibfiles);
-               p["embed"] = from_utf8(newEmbedStatus);
-               
-               setParams(p);
-               try {
-                       // test parameter and copy files
-                       getFiles(cur.buffer());
-               } catch (ExceptionMessage const & message) {
-                       Alert::error(message.title_, message.details_);
-                       // do not set parameter if an error happens
-                       setParams(orig);
-                       break;
-               }
-               cur.buffer().updateBibfilesCache();
+               createBibFiles(p["bibfiles"], p["embed"]);
+               updateParam();
+               buffer().updateBibfilesCache();
                break;
        }
 
@@ -146,16 +118,14 @@ void InsetBibtex::doDispatch(Cursor & cur, FuncRequest & cmd)
 }
 
 
-docstring const InsetBibtex::getScreenLabel(Buffer const &) const
+docstring InsetBibtex::screenLabel() const
 {
        return _("BibTeX Generated Bibliography");
 }
 
 
-namespace {
-
-string normalizeName(Buffer const & buffer, OutputParams const & runparams,
-                     string const & name, string const & ext)
+static string normalizeName(Buffer const & buffer,
+       OutputParams const & runparams, string const & name, string const & ext)
 {
        string const fname = makeAbsPath(name, buffer.filePath()).absFilename();
        if (FileName(name).isAbsolute() || !FileName(fname + ext).isReadableFile())
@@ -168,11 +138,8 @@ string normalizeName(Buffer const & buffer, OutputParams const & runparams,
                                         from_utf8(buffer.masterBuffer()->filePath())));
 }
 
-}
-
 
-int InsetBibtex::latex(Buffer const & buffer, odocstream & os,
-                      OutputParams const & runparams) const
+int InsetBibtex::latex(odocstream & os, OutputParams const & runparams) const
 {
        // the sequence of the commands:
        // 1. \bibliographystyle{style}
@@ -194,15 +161,15 @@ int InsetBibtex::latex(Buffer const & buffer, odocstream & os,
        // use such filenames.)
        // Otherwise, store the (maybe absolute) path to the original,
        // unmangled database name.
-       EmbeddedFileList const bibs = getFiles(buffer);
-       EmbeddedFileList::const_iterator it = bibs.begin();
-       EmbeddedFileList::const_iterator it_end = bibs.end();
+       EmbeddedFileList::const_iterator it = bibfiles_.begin();
+       EmbeddedFileList::const_iterator it_end = bibfiles_.end();
        odocstringstream dbs;
        for (; it != it_end; ++it) {
                string utf8input = removeExtension(it->availableFile().absFilename());
                string database =
-                       normalizeName(buffer, runparams, utf8input, ".bib");
-               FileName const try_in_file(makeAbsPath(database + ".bib", buffer.filePath()));
+                       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 &&
@@ -212,7 +179,7 @@ int InsetBibtex::latex(Buffer const & buffer, odocstream & os,
                        DocFileName const in_file = DocFileName(try_in_file);
                        database = removeExtension(in_file.mangledFilename());
                        FileName const out_file = makeAbsPath(database + ".bib",
-                                       buffer.masterBuffer()->temppath());
+                                       buffer().masterBuffer()->temppath());
 
                        bool const success = in_file.copyTo(out_file);
                        if (!success) {
@@ -228,7 +195,7 @@ int InsetBibtex::latex(Buffer const & buffer, odocstream & os,
                                                            from_utf8(database));
                }
 
-               if (it != bibs.begin())
+               if (it != bibfiles_.begin())
                        dbs << ',';
                // FIXME UNICODE
                dbs << from_utf8(latex_path(database));
@@ -259,8 +226,9 @@ int InsetBibtex::latex(Buffer const & buffer, odocstream & os,
        int nlines = 0;
 
        if (!style.empty()) {
-               string base = normalizeName(buffer, runparams, style, ".bst");
-               FileName const try_in_file(makeAbsPath(base + ".bst", buffer.filePath()));
+               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.
@@ -271,8 +239,8 @@ int InsetBibtex::latex(Buffer const & buffer, odocstream & os,
                        // 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()));
+                       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
@@ -282,7 +250,7 @@ int InsetBibtex::latex(Buffer const & buffer, odocstream & os,
                }
                // FIXME UNICODE
                os << "\\bibliographystyle{"
-                  << from_utf8(latex_path(normalizeName(buffer, runparams, base, ".bst")))
+                  << from_utf8(latex_path(normalizeName(buffer(), runparams, base, ".bst")))
                   << "}\n";
                nlines += 1;
        }
@@ -296,7 +264,7 @@ int InsetBibtex::latex(Buffer const & buffer, odocstream & os,
                                              "BibTeX will be unable to find it."));
        }
 
-       if (!db_out.empty() && buffer.params().use_bibtopic){
+       if (!db_out.empty() && buffer().params().use_bibtopic) {
                os << "\\begin{btSect}{" << db_out << "}\n";
                docstring btprint = getParam("btprint");
                if (btprint.empty())
@@ -308,31 +276,21 @@ int InsetBibtex::latex(Buffer const & buffer, odocstream & os,
        }
 
        // bibtotoc-Option
-       if (!bibtotoc.empty() && !buffer.params().use_bibtopic) {
-               // maybe a problem when a textclass has no "art" as
-               // part of its name, because it's than book.
-               // For the "official" lyx-layouts it's no problem to support
-               // all well
-               if (!contains(buffer.params().textClass().name(),
-                             "art")) {
-                       if (buffer.params().sides == OneSide) {
+       if (!bibtotoc.empty() && !buffer().params().use_bibtopic) {
+               if (buffer().params().documentClass().hasLaTeXLayout("chapter")) {
+                       if (buffer().params().sides == OneSide) {
                                // oneside
                                os << "\\clearpage";
                        } else {
                                // twoside
                                os << "\\cleardoublepage";
                        }
-
-                       // bookclass
                        os << "\\addcontentsline{toc}{chapter}{\\bibname}";
-
-               } else {
-                       // article class
+               } else if (buffer().params().documentClass().hasLaTeXLayout("section"))
                        os << "\\addcontentsline{toc}{section}{\\refname}";
-               }
        }
 
-       if (!db_out.empty() && !buffer.params().use_bibtopic){
+       if (!db_out.empty() && !buffer().params().use_bibtopic) {
                docstring btprint = getParam("btprint");
                if (btprint == "btPrintAll") {
                        os << "\\nocite{*}\n";
@@ -346,46 +304,9 @@ int InsetBibtex::latex(Buffer const & buffer, odocstream & os,
 }
 
 
-EmbeddedFileList const InsetBibtex::getFiles(Buffer const & buffer) const
+EmbeddedFileList InsetBibtex::embeddedFiles() const
 {
-       FileName path(buffer.filePath());
-       PathChanger p(path);
-
-       EmbeddedFileList vec;
-
-       string tmp;
-       string emb;
-       // FIXME UNICODE
-       string bibfiles = to_utf8(getParam("bibfiles"));
-       string embedStatus = to_utf8(getParam("embed"));
-       bibfiles = split(bibfiles, tmp, ',');
-       embedStatus = split(embedStatus, emb, ',');
-       while (!tmp.empty()) {
-               if (!emb.empty()) {
-                       EmbeddedFile file(changeExtension(tmp, "bib"), buffer.filePath());
-                       // If the file structure is correct, this should not fail.
-                       file.setEmbed(true);
-                       file.enable(buffer.embedded(), &buffer);
-                       vec.push_back(file);
-               } else {
-                       // this includes the cases when the embed parameter is empty
-                       FileName const file = findtexfile(changeExtension(tmp, "bib"), "bib");
-
-                       // If we didn't find a matching file name just fail silently
-                       if (!file.empty()) {
-                               EmbeddedFile efile = EmbeddedFile(file.absFilename(), buffer.filePath());
-                               efile.setEmbed(false);
-                               efile.enable(buffer.embedded(), &buffer);
-                               vec.push_back(efile);
-                       }
-               }
-
-               // Get next file name
-               bibfiles = split(bibfiles, tmp, ',');
-               embedStatus = split(embedStatus, emb, ',');
-       }
-
-       return vec;
+       return bibfiles_;
 }
 
 namespace {
@@ -627,10 +548,10 @@ namespace {
 
 
 // This method returns a comma separated list of Bibtex entries
-void InsetBibtex::fillWithBibKeys(Buffer const & buffer,
-               BiblioInfo & keylist, InsetIterator const & /*di*/) const
+void InsetBibtex::fillWithBibKeys(BiblioInfo & keylist,
+       InsetIterator const & /*di*/) const
 {
-       EmbeddedFileList const files = getFiles(buffer);
+       EmbeddedFileList const files = embeddedFiles();
        for (vector<EmbeddedFile>::const_iterator it = files.begin();
             it != files.end(); ++ it) {
                // This bibtex parser is a first step to parse bibtex files
@@ -653,8 +574,7 @@ void InsetBibtex::fillWithBibKeys(Buffer const & buffer,
                // 8bit clean bibtex forks exist.
                
                idocfstream ifs(it->availableFile().toFilesystemEncoding().c_str(),
-                       ios_base::in,
-                       buffer.params().encoding().iconvName());
+                       ios_base::in, buffer().params().encoding().iconvName());
 
                char_type ch;
                VarMap strings;
@@ -786,36 +706,35 @@ void InsetBibtex::fillWithBibKeys(Buffer const & buffer,
 
 bool InsetBibtex::addDatabase(string const & db)
 {
-       // FIXME UNICODE
-       string bibfiles(to_utf8(getParam("bibfiles")));
-       if (tokenPos(bibfiles, ',', db) == -1) {
-               if (!bibfiles.empty())
-                       bibfiles += ',';
-               setParam("bibfiles", from_utf8(bibfiles + db));
-               return true;
-       }
-       return false;
+       EmbeddedFile file(changeExtension(db, "bib"), buffer().filePath());
+       
+       // only compare filename
+       EmbeddedFileList::iterator it = bibfiles_.begin();
+       EmbeddedFileList::iterator it_end = bibfiles_.end();
+       for (; it != it_end; ++it)
+               if (it->absFilename() == file.absFilename())
+                       return false;
+       
+       bibfiles_.push_back(file);
+       updateParam();
+       return true;
 }
 
 
 bool InsetBibtex::delDatabase(string const & db)
 {
-       // FIXME UNICODE
-       string bibfiles(to_utf8(getParam("bibfiles")));
-       if (contains(bibfiles, db)) {
-               int const n = tokenPos(bibfiles, ',', db);
-               string bd = db;
-               if (n > 0) {
-                       // this is not the first database
-                       string tmp = ',' + bd;
-                       setParam("bibfiles", from_utf8(subst(bibfiles, tmp, string())));
-               } else if (n == 0)
-                       // this is the first (or only) database
-                       setParam("bibfiles", from_utf8(split(bibfiles, bd, ',')));
-               else
-                       return false;
-       }
-       return true;
+       EmbeddedFile file(changeExtension(db, "bib"), buffer().filePath());
+       
+       // only compare filename
+       EmbeddedFileList::iterator it = bibfiles_.begin();
+       EmbeddedFileList::iterator it_end = bibfiles_.end();
+       for (; it != it_end; ++it)
+               if (it->absFilename() == file.absFilename()) {
+                       bibfiles_.erase(it);
+                       updateParam();
+                       return true;
+               }
+       return false;
 }
 
 
@@ -826,35 +745,51 @@ void InsetBibtex::validate(LaTeXFeatures & features) const
 }
 
 
-void InsetBibtex::registerEmbeddedFiles(Buffer const & buffer, EmbeddedFileList & files) const
+void InsetBibtex::createBibFiles(docstring const & bibParam,
+       docstring const & embedParam) const
 {
-       EmbeddedFileList const dbs = getFiles(buffer);
-       for (vector<EmbeddedFile>::const_iterator it = dbs.begin();
-               it != dbs.end(); ++ it)
-               files.registerFile(*it, this, buffer);          
+       bibfiles_.clear();
+       
+       string tmp;
+       string emb;
+       
+       string bibfiles = to_utf8(bibParam);
+       string embedStatus = to_utf8(embedParam);
+       
+       LYXERR(Debug::FILES, "Create bib files from parameters "
+               << bibfiles << " and " << embedStatus);
+
+       bibfiles = split(bibfiles, tmp, ',');
+       embedStatus = split(embedStatus, emb, ',');
+       
+       while (!tmp.empty()) {
+               EmbeddedFile file(changeExtension(tmp, "bib"), buffer().filePath());
+               
+               file.setInzipName(emb);
+               file.setEmbed(!emb.empty());
+               file.enable(buffer().embedded(), &buffer(), false);
+               bibfiles_.push_back(file);
+               // Get next file name
+               bibfiles = split(bibfiles, tmp, ',');
+               embedStatus = split(embedStatus, emb, ',');
+       }
 }
 
 
-void InsetBibtex::updateEmbeddedFile(Buffer const & buf, EmbeddedFile const & file)
+void InsetBibtex::updateParam()
 {
-       // look for the item and update status
        docstring bibfiles;
        docstring embed;
 
        bool first = true;
-       EmbeddedFileList dbs = getFiles(buf);
-       for (EmbeddedFileList::iterator it = dbs.begin();
-               it != dbs.end(); ++ it) {
-               // update from file
-               if (it->absFilename() == file.absFilename())
-                       it->setEmbed(file.embedded());
-               // write parameter string
+       for (EmbeddedFileList::iterator it = bibfiles_.begin();
+               it != bibfiles_.end(); ++it) {
                if (!first) {
                        bibfiles += ',';
                        embed += ',';
                } else
                        first = false;
-               bibfiles += from_utf8(it->outputFilename(buf.filePath()));
+               bibfiles += from_utf8(it->outputFilename(buffer().filePath()));
                if (it->embedded())
                        embed += from_utf8(it->inzipName());
        }
@@ -863,4 +798,28 @@ void InsetBibtex::updateEmbeddedFile(Buffer const & buf, EmbeddedFile const & fi
 }
 
 
+void InsetBibtex::registerEmbeddedFiles(EmbeddedFileList & files) const
+{
+       if (bibfiles_.empty())
+               createBibFiles(params()["bibfiles"], params()["embed"]);
+
+       EmbeddedFileList::const_iterator it = bibfiles_.begin();
+       EmbeddedFileList::const_iterator it_end = bibfiles_.end();
+       for (; it != it_end; ++it)
+               files.registerFile(*it, this, buffer());
+}
+
+
+void InsetBibtex::updateEmbeddedFile(EmbeddedFile const & file)
+{
+       // look for the item and update status
+       for (EmbeddedFileList::iterator it = bibfiles_.begin();
+               it != bibfiles_.end(); ++it)
+               if (it->absFilename() == file.absFilename())
+                       *it = file;
+       
+       updateParam();
+}
+
+
 } // namespace lyx