]> git.lyx.org Git - lyx.git/blobdiff - src/Buffer.cpp
Fix glitch in drawing fractions
[lyx.git] / src / Buffer.cpp
index f2dbb88840024f27885c694f39bfd7de7f0a9bce..517cd129523157368686a376b2d9b62d851567b6 100644 (file)
@@ -79,6 +79,7 @@
 #include "mathed/MathMacroTemplate.h"
 #include "mathed/MathSupport.h"
 
+#include "graphics/GraphicsCache.h"
 #include "graphics/PreviewLoader.h"
 
 #include "frontends/alert.h"
@@ -277,7 +278,7 @@ public:
 
        /// A cache for the bibfiles (including bibfiles of loaded child
        /// documents), needed for appropriate update of natbib labels.
-       mutable support::FileNameList bibfiles_cache_;
+       mutable support::FileNamePairList bibfiles_cache_;
 
        // FIXME The caching mechanism could be improved. At present, we have a
        // cache for each Buffer, that caches all the bibliography info for that
@@ -421,8 +422,8 @@ Buffer::Impl::Impl(Buffer * owner, FileName const & file, bool readonly_,
          ignore_parent(false),  toc_backend(owner), macro_lock(false), timestamp_(0),
          checksum_(0), wa_(0),  gui_(0), undo_(*owner), bibinfo_cache_valid_(false),
          bibfile_cache_valid_(false), cite_labels_valid_(false), preview_error_(false),
-         inset(0), preview_loader_(0), cloned_buffer_(cloned_buffer), clone_list_(0),
-         doing_export(false), parent_buffer(0),
+         inset(0), preview_loader_(0), cloned_buffer_(cloned_buffer),
+         clone_list_(0), doing_export(false), parent_buffer(0),
          word_count_(0), char_count_(0), blank_count_(0)
 {
        if (!cloned_buffer_) {
@@ -911,6 +912,9 @@ int Buffer::readHeader(Lexer & lex)
        params().output_sync_macro.erase();
        params().setLocalLayout(docstring(), false);
        params().setLocalLayout(docstring(), true);
+       params().biblio_opts.erase();
+       params().biblatex_bibstyle.erase();
+       params().biblatex_citestyle.erase();
 
        for (int i = 0; i < 4; ++i) {
                params().user_defined_bullet(i) = ITEMIZE_DEFAULTS[i];
@@ -1874,7 +1878,15 @@ void Buffer::writeLaTeXSource(otexstream & os,
                // Write the preamble
                runparams.use_babel = params().writeLaTeX(os, features,
                                                          d->filename.onlyPath());
-               
+
+               // Biblatex bibliographies are loaded here
+               if (params().useBiblatex()) {
+                       vector<docstring> const bibfiles =
+                               prepareBibFilePaths(runparams, getBibfilesCache(), true);
+                       for (docstring const & file: bibfiles)
+                               os << "\\addbibresource{" << file << "}\n";
+               }
+
                if (!runparams.dryrun && features.hasPolyglossiaExclusiveLanguages()
                    && !features.hasOnlyPolyglossiaLanguages()) {
                        docstring blangs;
@@ -2022,7 +2034,7 @@ void Buffer::writeDocBookSource(odocstream & os, string const & fname,
                if (! tclass.class_header().empty())
                        os << from_ascii(tclass.class_header());
                else if (runparams.flavor == OutputParams::XML)
-                       os << "PUBLIC \"-//OASIS//DTD DocBook XML//EN\" "
+                       os << "PUBLIC \"-//OASIS//DTD DocBook XML V4.2//EN\" "
                            << "\"http://www.oasis-open.org/docbook/xml/4.2/docbookx.dtd\"";
                else
                        os << " PUBLIC \"-//OASIS//DTD DocBook V4.2//EN\"";
@@ -2301,7 +2313,7 @@ void Buffer::updateBibfilesCache(UpdateScope scope) const
        for (InsetIterator it = inset_iterator_begin(inset()); it; ++it) {
                if (it->lyxCode() == BIBTEX_CODE) {
                        InsetBibtex const & inset = static_cast<InsetBibtex const &>(*it);
-                       support::FileNameList const bibfiles = inset.getBibFiles();
+                       support::FileNamePairList const bibfiles = inset.getBibFiles();
                        d->bibfiles_cache_.insert(d->bibfiles_cache_.end(),
                                bibfiles.begin(),
                                bibfiles.end());
@@ -2310,7 +2322,7 @@ void Buffer::updateBibfilesCache(UpdateScope scope) const
                        Buffer const * const incbuf = inset.getChildBuffer();
                        if (!incbuf)
                                continue;
-                       support::FileNameList const & bibfiles =
+                       support::FileNamePairList const & bibfiles =
                                        incbuf->getBibfilesCache(UpdateChildOnly);
                        if (!bibfiles.empty()) {
                                d->bibfiles_cache_.insert(d->bibfiles_cache_.end(),
@@ -2348,7 +2360,7 @@ void Buffer::invalidateBibfileCache() const
 }
 
 
-support::FileNameList const & Buffer::getBibfilesCache(UpdateScope scope) const
+support::FileNamePairList const & Buffer::getBibfilesCache(UpdateScope scope) const
 {
        // FIXME This is probably unnecessary, given where we call this.
        // If this is a child document, use the master's cache instead.
@@ -2382,16 +2394,17 @@ void Buffer::checkIfBibInfoCacheIsValid() const
        }
 
        // compare the cached timestamps with the actual ones.
-       FileNameList const & bibfiles_cache = getBibfilesCache();
-       FileNameList::const_iterator ei = bibfiles_cache.begin();
-       FileNameList::const_iterator en = bibfiles_cache.end();
+       FileNamePairList const & bibfiles_cache = getBibfilesCache();
+       FileNamePairList::const_iterator ei = bibfiles_cache.begin();
+       FileNamePairList::const_iterator en = bibfiles_cache.end();
        for (; ei != en; ++ ei) {
-               time_t lastw = ei->lastModified();
-               time_t prevw = d->bibfile_status_[*ei];
+               FileName const fn = ei->second;
+               time_t lastw = fn.lastModified();
+               time_t prevw = d->bibfile_status_[fn];
                if (lastw != prevw) {
                        d->bibinfo_cache_valid_ = false;
                        d->cite_labels_valid_ = false;
-                       d->bibfile_status_[*ei] = lastw;
+                       d->bibfile_status_[fn] = lastw;
                }
        }
 }
@@ -3102,6 +3115,114 @@ DocFileName Buffer::getReferencedFileName(string const & fn) const
 }
 
 
+string const Buffer::prepareFileNameForLaTeX(string const & name,
+                                            string const & ext, bool nice) const
+{
+       string const fname = makeAbsPath(name, filePath()).absFileName();
+       if (FileName::isAbsolute(name) || !FileName(fname + ext).isReadableFile())
+               return name;
+       if (!nice)
+               return fname;
+
+       // FIXME UNICODE
+       return to_utf8(makeRelPath(from_utf8(fname),
+               from_utf8(masterBuffer()->filePath())));
+}
+
+
+vector<docstring> const Buffer::prepareBibFilePaths(OutputParams const & runparams,
+                                               FileNamePairList const bibfilelist,
+                                               bool const add_extension) const
+{
+       // 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<docstring> res;
+
+       // determine the export format
+       string const tex_format = flavor2format(runparams.flavor);
+
+       // check for spaces in paths
+       bool found_space = false;
+
+       FileNamePairList::const_iterator it = bibfilelist.begin();
+       FileNamePairList::const_iterator en = bibfilelist.end();
+       for (; it != en; ++it) {
+               string utf8input = to_utf8(it->first);
+               string database =
+                       prepareFileNameForLaTeX(utf8input, ".bib", runparams.nice);
+               FileName const try_in_file =
+                       makeAbsPath(database + ".bib", 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",
+                                       masterBuffer()->temppath());
+                       bool const success = in_file.copyTo(out_file);
+                       if (!success) {
+                               LYXERR0("Failed to copy '" << in_file
+                                      << "' to '" << out_file << "'");
+                       }
+               } else if (!runparams.inComment && runparams.nice && not_from_texmf) {
+                       runparams.exportdata->addExternalFile(tex_format, try_in_file, database + ".bib");
+                       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 (add_extension)
+                       database += ".bib";
+
+               // FIXME UNICODE
+               docstring const path = from_utf8(latex_path(database));
+
+               if (contains(path, ' '))
+                       found_space = true;
+
+               if (find(res.begin(), res.end(), path) == res.end())
+                       res.push_back(path);
+       }
+
+       // Check if there are spaces in the path and warn BibTeX users, if so.
+       // (biber can cope with such paths)
+       if (!prefixIs(runparams.bibtex_command, "biber")) {
+               // Post this warning only once.
+               static bool warned_about_spaces = false;
+               if (!warned_about_spaces &&
+                   runparams.nice && found_space) {
+                       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."));
+               }
+       }
+
+       return res;
+}
+
+
+
 string Buffer::layoutPos() const
 {
        return d->layout_position;
@@ -3555,7 +3676,7 @@ void Buffer::updateMacroInstances(UpdateType utype) const
                MacroContext mc = MacroContext(this, it);
                for (DocIterator::idx_type i = 0; i < n; ++i) {
                        MathData & data = minset->cell(i);
-                       data.updateMacros(0, mc, utype);
+                       data.updateMacros(0, mc, utype, 0);
                }
        }
 }
@@ -3753,7 +3874,7 @@ unique_ptr<TexRow> Buffer::getSourceCode(odocstream & os, string const & format,
                        // in order to know if we should output polyglossia
                        // macros (instead of babel macros)
                        LaTeXFeatures features(*this, params(), runparams);
-                       params().validate(features);
+                       validate(features);
                        runparams.use_polyglossia = features.usePolyglossia();
                        // latex or literate
                        otexstream ots(os);