]> git.lyx.org Git - lyx.git/blobdiff - src/Buffer.cpp
Add check for recursive includes.
[lyx.git] / src / Buffer.cpp
index ea1168b6846bc75757703f6cdd94ef772741ef7f..6c3841ba638ee1941effd418265a999564c4107f 100644 (file)
 #include "mathed/MathMacroTemplate.h"
 #include "mathed/MathSupport.h"
 
+#include "graphics/PreviewLoader.h"
+
 #include "frontends/alert.h"
 #include "frontends/Delegates.h"
 #include "frontends/WorkAreaManager.h"
 
-#include "graphics/Previews.h"
-
 #include "support/lassert.h"
 #include "support/convert.h"
 #include "support/debug.h"
 
 using namespace std;
 using namespace lyx::support;
+using namespace lyx::graphics;
 
 namespace lyx {
 
@@ -150,6 +151,7 @@ public:
 
        ~Impl()
        {
+               delete preview_loader_;
                if (wa_) {
                        wa_->closeAll();
                        delete wa_;
@@ -267,6 +269,9 @@ public:
        /// our Text that should be wrapped in an InsetText
        InsetText * inset;
 
+       ///
+       PreviewLoader * preview_loader_;
+
        /// This is here to force the test to be done whenever parent_buffer
        /// is accessed.
        Buffer const * parent() const { 
@@ -331,10 +336,11 @@ Buffer::Impl::Impl(Buffer * owner, FileName const & file, bool readonly_,
        Buffer const * cloned_buffer)
        : owner_(owner), lyx_clean(true), bak_clean(true), unnamed(false),
          read_only(readonly_), filename(file), file_fully_loaded(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),
-         cloned_buffer_(cloned_buffer), doing_export(false), parent_buffer(0)
+         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_loader_(0), cloned_buffer_(cloned_buffer),
+         doing_export(false), parent_buffer(0)
 {
        if (!cloned_buffer_) {
                temppath = createBufferTmpDir();
@@ -427,29 +433,50 @@ Buffer::~Buffer()
 
 Buffer * Buffer::clone() const
 {
+       BufferMap bufmap;
+       masterBuffer()->clone(bufmap);
+       BufferMap::iterator it = bufmap.find(this);
+       LASSERT(it != bufmap.end(), return 0);
+       return it->second;
+}
+
+
+void Buffer::clone(BufferMap & bufmap) const
+{
+       // have we already been cloned?
+       if (bufmap.find(this) != bufmap.end())
+               return;
+
        Buffer * buffer_clone = new Buffer(fileName().absFileName(), false, this);
+       bufmap[this] = buffer_clone;
        buffer_clone->d->macro_lock = true;
        buffer_clone->d->children_positions.clear();
        // FIXME (Abdel 09/01/2010): this is too complicated. The whole children_positions and
        // math macro caches need to be rethought and simplified.
        // I am not sure wether we should handle Buffer cloning here or in BufferList.
        // Right now BufferList knows nothing about buffer clones.
-       Impl::BufferPositionMap::iterator it = d->children_positions.begin();
-       Impl::BufferPositionMap::iterator end = d->children_positions.end();
+       Impl::PositionScopeBufferMap::iterator it = d->position_to_children.begin();
+       Impl::PositionScopeBufferMap::iterator end = d->position_to_children.end();
        for (; it != end; ++it) {
-               DocIterator dit = it->second.clone(buffer_clone);
+               DocIterator dit = it->first.clone(buffer_clone);
                dit.setBuffer(buffer_clone);
-               Buffer * child = const_cast<Buffer *>(it->first);
-               Buffer * child_clone = child->clone();
+               Buffer * child = const_cast<Buffer *>(it->second.second);
+
+               child->clone(bufmap);
+               BufferMap::iterator const bit = bufmap.find(child);
+               LASSERT(bit != bufmap.end(), continue);
+               Buffer * child_clone = bit->second;
+
                Inset * inset = dit.nextInset();
                LASSERT(inset && inset->lyxCode() == INCLUDE_CODE, continue);
                InsetInclude * inset_inc = static_cast<InsetInclude *>(inset);
                inset_inc->setChildBuffer(child_clone);
                child_clone->d->setParent(buffer_clone);
+               // FIXME Do we need to do this now, or can we wait until we run updateMacros()?
                buffer_clone->setChild(dit, child_clone);
        }
        buffer_clone->d->macro_lock = false;
-       return buffer_clone;
+       return;
 }
 
 
@@ -925,16 +952,35 @@ void Buffer::setFullyLoaded(bool value)
 }
 
 
-void Buffer::updatePreviews() const
+PreviewLoader * Buffer::loader() const
 {
-       if (graphics::Previews::status() != LyXRC::PREVIEW_OFF)
-               thePreviews().generateBufferPreviews(*this);
+       if (lyxrc.preview == LyXRC::PREVIEW_OFF)
+               return 0;
+       if (!d->preview_loader_)
+               d->preview_loader_ = new PreviewLoader(*this);
+       return d->preview_loader_;
 }
 
 
 void Buffer::removePreviews() const
 {
-       thePreviews().removeLoader(*this);
+       delete d->preview_loader_;
+       d->preview_loader_ = 0;
+}
+
+
+void Buffer::updatePreviews() const
+{
+       PreviewLoader * ploader = loader();
+       if (!ploader)
+               return;
+
+       InsetIterator it = inset_iterator_begin(*d->inset);
+       InsetIterator const end = inset_iterator_end(*d->inset);
+       for (; it != end; ++it)
+               it->addPreview(it, *ploader);
+
+       ploader->startLoading();
 }
 
 
@@ -1588,8 +1634,7 @@ void Buffer::writeDocBookSource(odocstream & os, string const & fname,
 
 
 void Buffer::makeLyXHTMLFile(FileName const & fname,
-                             OutputParams const & runparams,
-                             bool const body_only) const
+                             OutputParams const & runparams) const
 {
        LYXERR(Debug::LATEX, "makeLyXHTMLFile...");
 
@@ -1602,7 +1647,7 @@ void Buffer::makeLyXHTMLFile(FileName const & fname,
        updateBuffer(UpdateMaster, OutputUpdate);
        updateMacroInstances(OutputUpdate);
 
-       writeLyXHTMLSource(ofs, runparams, body_only);
+       writeLyXHTMLSource(ofs, runparams);
 
        ofs.close();
        if (ofs.fail())
@@ -2595,6 +2640,12 @@ void Buffer::collectChildren(ListOfBuffers & clist, bool grand_children) const
                        // there might be grandchildren
                        child->collectChildren(clist, true);
        }
+       // Make sure we have not included ourselves.
+       ListOfBuffers::iterator bit = find(clist.begin(), clist.end(), this);
+       if (bit != clist.end()) {
+               LYXERR0("Recursive include detected in `" << fileName() << "'.");
+               clist.erase(bit);
+       }
 }
 
 
@@ -3135,12 +3186,7 @@ void Buffer::getSourceCode(odocstream & os, string const format,
 
 ErrorList & Buffer::errorList(string const & type) const
 {
-       static ErrorList emptyErrorList;
-       map<string, ErrorList>::iterator it = d->errorLists.find(type);
-       if (it == d->errorLists.end())
-               return emptyErrorList;
-
-       return it->second;
+       return d->errorLists[type];
 }
 
 
@@ -3984,10 +4030,12 @@ void Buffer::Impl::setLabel(ParIterator & it, UpdateType utype) const
        // Compute the item depth of the paragraph
        par.itemdepth = getItemDepth(it);
 
-       if (layout.margintype == MARGIN_MANUAL
-           || layout.latextype == LATEX_BIB_ENVIRONMENT) {
+       if (layout.margintype == MARGIN_MANUAL) {
                if (par.params().labelWidthString().empty())
                        par.params().labelWidthString(par.expandLabel(layout, bp));
+       } else if (layout.latextype == LATEX_BIB_ENVIRONMENT) {
+               // we do not need to do anything here, since the empty case is
+               // handled during export.
        } else {
                par.params().labelWidthString(docstring());
        }