]> git.lyx.org Git - lyx.git/blobdiff - src/insets/InsetBibtex.cpp
Cocoa based Qt-4.6 needs to paint every character separately to match metrics computa...
[lyx.git] / src / insets / InsetBibtex.cpp
index b932f9173773c06a67831e15ca929a44cde8d5d4..c54abb7624c240d37e294596e8866fd47c74e13a 100644 (file)
 
 #include "InsetBibtex.h"
 
+#include "BiblioInfo.h"
 #include "Buffer.h"
 #include "BufferParams.h"
+#include "Cursor.h"
 #include "DispatchResult.h"
 #include "Encoding.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 "TextClass.h"
 
 #include "frontends/alert.h"
@@ -31,6 +35,7 @@
 #include "support/debug.h"
 #include "support/docstream.h"
 #include "support/ExceptionMessage.h"
+#include "support/FileNameList.h"
 #include "support/filetools.h"
 #include "support/gettext.h"
 #include "support/lstrings.h"
@@ -50,16 +55,16 @@ namespace os = support::os;
 
 
 InsetBibtex::InsetBibtex(Buffer * buf, InsetCommandParams const & p)
-       : InsetCommand(buf, p, "bibtex")
+       : InsetCommand(buf, p)
 {
-       buffer_->invalidateBibinfoCache();
+       buffer().invalidateBibinfoCache();
 }
 
 
 InsetBibtex::~InsetBibtex()
 {
        if (isBufferLoaded())
-               buffer_->invalidateBibinfoCache();
+               buffer().invalidateBibfileCache();
 }
 
 
@@ -86,22 +91,23 @@ void InsetBibtex::doDispatch(Cursor & cur, FuncRequest & cmd)
        case LFUN_INSET_MODIFY: {
                InsetCommandParams p(BIBTEX_CODE);
                try {
-                       if (!InsetCommand::string2params("bibtex", 
-                                       to_utf8(cmd.argument()), p)) {
-                               cur.noUpdate();
+                       if (!InsetCommand::string2params(to_utf8(cmd.argument()), p)) {
+                               cur.noScreenUpdate();
                                break;
                        }
                } catch (ExceptionMessage const & message) {
                        if (message.type_ == WarningException) {
                                Alert::warning(message.title_, message.details_);
-                               cur.noUpdate();
+                               cur.noScreenUpdate();
                        } else 
                                throw message;
                        break;
                }
-               //
+
+               cur.recordUndo();
                setParams(p);
-               buffer().updateBibfilesCache();
+               buffer().invalidateBibfileCache();
+               cur.forceBufferUpdate();
                break;
        }
 
@@ -148,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 bibfile = getBibTeXPath(*it, buffer());
+               FileName const bibfile = getBibTeXPath(*it, buffer());
                formats.edit(buffer(), bibfile,
                     formats.getFormatFromFile(bibfile));
        }
@@ -229,7 +235,7 @@ static string normalizeName(Buffer const & buffer,
 }
 
 
-int InsetBibtex::latex(odocstream & os, OutputParams const & runparams) const
+void InsetBibtex::latex(otexstream & os, OutputParams const & runparams) const
 {
        // the sequence of the commands:
        // 1. \bibliographystyle{style}
@@ -279,12 +285,20 @@ int InsetBibtex::latex(odocstream & os, OutputParams const & runparams) const
                                       << "' to '" << out_file << "'"
                                       << endl;
                        }
-               } else if (!runparams.inComment && runparams.nice && not_from_texmf &&
-                          !isValidLaTeXFilename(database)) {
+               } else if (!runparams.inComment && runparams.nice && not_from_texmf) {
+                       if (!isValidLaTeXFileName(database)) {
                                frontend::Alert::warning(_("Invalid filename"),
-                                                        _("The following filename is likely to cause trouble "
-                                                          "when running the exported file through LaTeX: ") +
-                                                           from_utf8(database));
+                                        _("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)
@@ -314,9 +328,6 @@ 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 = 
@@ -344,7 +355,6 @@ int InsetBibtex::latex(odocstream & os, OutputParams const & runparams) const
                os << "\\bibliographystyle{"
                   << from_utf8(latex_path(normalizeName(buffer(), runparams, base, ".bst")))
                   << "}\n";
-               nlines += 1;
        }
 
        // Post this warning only once.
@@ -364,21 +374,16 @@ int InsetBibtex::latex(odocstream & os, OutputParams const & runparams) const
                        btprint = from_ascii("btPrintCited");
                os << "\\" << btprint << "\n"
                   << "\\end{btSect}\n";
-               nlines += 3;
        }
 
        // bibtotoc-Option
        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";
-                       }
+               // 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"))
+               else if (buffer().params().documentClass().hasLaTeXLayout("section"))
                        os << "\\addcontentsline{toc}{section}{\\refname}";
        }
 
@@ -386,13 +391,9 @@ int InsetBibtex::latex(odocstream & os, OutputParams const & runparams) const
                docstring btprint = getParam("btprint");
                if (btprint == "btPrintAll") {
                        os << "\\nocite{*}\n";
-                       nlines += 1;
                }
                os << "\\bibliography{" << db_out << "}\n";
-               nlines += 1;
        }
-
-       return nlines;
 }
 
 
@@ -473,7 +474,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;
@@ -546,13 +547,13 @@ namespace {
                                return false;
 
                        // check for field type
-                       if (isDigit(ch)) {
+                       if (isDigitASCII(ch)) {
 
                                // read integer value
                                do {
                                        val += ch;
                                        ifs.get(ch);
-                               } while (ifs && isDigit(ch));
+                               } while (ifs && isDigitASCII(ch));
 
                                if (!ifs)
                                        return false;
@@ -601,16 +602,19 @@ namespace {
                                                        break;
                                                case '}':
                                                        --nestLevel;
-                                                       if (nestLevel < 0) return false;
+                                                       if (nestLevel < 0) 
+                                                               return false;
                                                        break;
                                        }
 
-                                       ifs.get(ch);
+                                       if (ifs)
+                                               ifs.get(ch);
                                }
 
                                if (!ifs)
                                        return false;
 
+                               // FIXME Why is this here?
                                ifs.get(ch);
 
                                if (!ifs)
@@ -657,9 +661,13 @@ namespace {
 }
 
 
-// This method returns a comma separated list of Bibtex entries
-void InsetBibtex::fillWithBibKeys(BiblioInfo & keylist,
-       InsetIterator const & /*di*/) const
+void InsetBibtex::collectBibKeys(InsetIterator const & /*di*/) const
+{
+       parseBibTeXFiles();
+}
+
+
+void InsetBibtex::parseBibTeXFiles() const
 {
        // This bibtex parser is a first step to parse bibtex files
        // more precisely.
@@ -679,6 +687,9 @@ void InsetBibtex::fillWithBibKeys(BiblioInfo & keylist,
        // 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::FileNameList const files = getBibFiles();
        support::FileNameList::const_iterator it = files.begin();
        support::FileNameList::const_iterator en = files.end();
@@ -701,12 +712,12 @@ void InsetBibtex::fillWithBibKeys(BiblioInfo & keylist,
                        docstring entryType;
 
                        if (!readTypeOrKey(entryType, ifs, from_ascii("{("), docstring(), makeLowerCase)) {
-                               lyxerr << "InsetBibtex::fillWithBibKeys: Error reading entry type." << std::endl;
+                               lyxerr << "BibTeX Parser: Error reading entry type." << std::endl;
                                continue;
                        }
 
                        if (!ifs) {
-                               lyxerr << "InsetBibtex::fillWithBibKeys: Unexpected end of file." << std::endl;
+                               lyxerr << "BibTeX Parser: Unexpected end of file." << std::endl;
                                continue;
                        }
 
@@ -717,12 +728,12 @@ void InsetBibtex::fillWithBibKeys(BiblioInfo & keylist,
 
                        ifs.get(ch);
                        if (!ifs) {
-                               lyxerr << "InsetBibtex::fillWithBibKeys: Unexpected end of file." << std::endl;
+                               lyxerr << "BibTeX Parser: Unexpected end of file." << std::endl;
                                break;
                        }
 
                        if ((ch != '(') && (ch != '{')) {
-                               lyxerr << "InsetBibtex::fillWithBibKeys: Invalid entry delimiter." << std::endl;
+                               lyxerr << "BibTeX Parser: Invalid entry delimiter." << std::endl;
                                ifs.putback(ch);
                                continue;
                        }
@@ -736,25 +747,25 @@ void InsetBibtex::fillWithBibKeys(BiblioInfo & keylist,
                                docstring value;
 
                                if (!readTypeOrKey(name, ifs, from_ascii("="), from_ascii("#{}(),"), makeLowerCase)) {
-                                       lyxerr << "InsetBibtex::fillWithBibKeys: Error reading string name." << std::endl;
+                                       lyxerr << "BibTeX Parser: Error reading string name." << std::endl;
                                        continue;
                                }
 
                                if (!ifs) {
-                                       lyxerr << "InsetBibtex::fillWithBibKeys: Unexpected end of file." << std::endl;
+                                       lyxerr << "BibTeX Parser: Unexpected end of file." << std::endl;
                                        continue;
                                }
 
                                // next char must be an equal sign
                                ifs.get(ch);
                                if (!ifs || ch != '=') {
-                                       lyxerr << "InsetBibtex::fillWithBibKeys: No `=' after string name: " << 
+                                       lyxerr << "BibTeX Parser: No `=' after string name: " << 
                                                        name << "." << std::endl;
                                        continue;
                                }
 
                                if (!readValue(value, ifs, strings)) {
-                                       lyxerr << "InsetBibtex::fillWithBibKeys: Unable to read value for string: " << 
+                                       lyxerr << "BibTeX Parser: Unable to read value for string: " << 
                                                        name << "." << std::endl;
                                        continue;
                                }
@@ -768,7 +779,7 @@ void InsetBibtex::fillWithBibKeys(BiblioInfo & keylist,
                                docstring value;
 
                                if (!readValue(value, ifs, strings)) {
-                                       lyxerr << "InsetBibtex::fillWithBibKeys: Unable to read preamble value." << std::endl;
+                                       lyxerr << "BibTeX Parser: Unable to read preamble value." << std::endl;
                                        continue;
                                }
 
@@ -778,13 +789,13 @@ void InsetBibtex::fillWithBibKeys(BiblioInfo & keylist,
                                docstring key;
 
                                if (!readTypeOrKey(key, ifs, from_ascii(","), from_ascii("}"), keepCase)) {
-                                       lyxerr << "InsetBibtex::fillWithBibKeys: Unable to read key for entry type:" << 
+                                       lyxerr << "BibTeX Parser: Unable to read key for entry type:" << 
                                                        entryType << "." << std::endl;
                                        continue;
                                }
 
                                if (!ifs) {
-                                       lyxerr << "InsetBibtex::fillWithBibKeys: Unexpected end of file." << std::endl;
+                                       lyxerr << "BibTeX Parser: Unexpected end of file." << std::endl;
                                        continue;
                                }
 
@@ -796,10 +807,8 @@ void InsetBibtex::fillWithBibKeys(BiblioInfo & keylist,
                                // all items must be separated by a comma. If
                                // it is missing the scanning of this entry is
                                // stopped and the next is searched.
-                               docstring fields;
                                docstring name;
                                docstring value;
-                               docstring commaNewline;
                                docstring data;
                                BibTeXInfo keyvalmap(key, entryType);
                                
@@ -813,13 +822,14 @@ void InsetBibtex::fillWithBibKeys(BiblioInfo & keylist,
                                                break;
 
                                        // next char must be an equal sign
+                                       // FIXME Whitespace??
                                        ifs.get(ch);
                                        if (!ifs) {
-                                               lyxerr << "InsetBibtex::fillWithBibKeys: Unexpected end of file." << std::endl;
+                                               lyxerr << "BibTeX Parser: Unexpected end of file." << std::endl;
                                                break;
                                        }
                                        if (ch != '=') {
-                                               lyxerr << "InsetBibtex::fillWithBibKeys: Missing `=' after field name: " <<
+                                               lyxerr << "BibTeX Parser: Missing `=' after field name: " <<
                                                                name << ", for key: " << key << "." << std::endl;
                                                ifs.putback(ch);
                                                break;
@@ -827,7 +837,7 @@ void InsetBibtex::fillWithBibKeys(BiblioInfo & keylist,
 
                                        // read field value
                                        if (!readValue(value, ifs, strings)) {
-                                               lyxerr << "InsetBibtex::fillWithBibKeys: Unable to read value for field: " <<
+                                               lyxerr << "BibTeX Parser: Unable to read value for field: " <<
                                                                name << ", for key: " << key << "." << std::endl;
                                                break;
                                        }
@@ -845,6 +855,8 @@ void InsetBibtex::fillWithBibKeys(BiblioInfo & keylist,
                        } //< else (citation entry)
                } //< searching '@'
        } //< for loop over files
+
+       buffer().addBiblioInfo(keylist);
 }
 
 
@@ -919,8 +931,13 @@ docstring InsetBibtex::xhtml(XHTMLStream & xs, OutputParams const &) const
        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());
+               
        xs << html::StartTag("h2", "class='bibtex'")
-               << _("References")
+               << reflabel
                << html::EndTag("h2")
                << html::StartTag("div", "class='bibtex'");
 
@@ -960,17 +977,18 @@ docstring InsetBibtex::xhtml(XHTMLStream & xs, OutputParams const &) const
                // 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'") 
-                       << bibinfo.getInfo(entry.key(), buffer(), true)
-                       << html::EndTag("span")
-                       << html::EndTag("div");
-               xs.cr();
+                  << XHTMLStream::ESCAPE_AND
+                  << bibinfo.getInfo(entry.key(), buffer(), true)
+                  << html::EndTag("span")
+                  << html::EndTag("div")
+                  << html::CR();
        }
        xs << html::EndTag("div");
        return docstring();
 }
 
 
-docstring InsetBibtex::contextMenu(BufferView const &, int, int) const
+docstring InsetBibtex::contextMenuName() const
 {
        return from_ascii("context-bibtex");
 }