]> git.lyx.org Git - lyx.git/blobdiff - src/Buffer.cpp
InsetTabular.cpp: multirows inherit the width and the alignment from the column;...
[lyx.git] / src / Buffer.cpp
index dad081932be7661be9b8926fcd426e0fb73791b7..5bd73da715315da24f5f00effdb0757f195ba092 100644 (file)
 #include "insets/InsetBibtex.h"
 #include "insets/InsetBranch.h"
 #include "insets/InsetInclude.h"
+#include "insets/InsetTabular.h"
 #include "insets/InsetText.h"
 
+#include "mathed/InsetMathHull.h"
 #include "mathed/MacroTable.h"
 #include "mathed/MathMacroTemplate.h"
 #include "mathed/MathSupport.h"
 #include "support/textutils.h"
 #include "support/types.h"
 
-#include <boost/bind.hpp>
-#include <boost/shared_ptr.hpp>
+#include "support/bind.h"
+#include "support/shared_ptr.h"
 
 #include <algorithm>
 #include <fstream>
@@ -126,7 +128,7 @@ namespace {
 
 // Do not remove the comment below, so we get merge conflict in
 // independent branches. Instead add your own.
-int const LYX_FORMAT = 386; // rgh: LyX version for InsetInfo
+int const LYX_FORMAT = 404; // rgh: refstyle
 
 typedef map<string, bool> DepClean;
 typedef map<docstring, pair<InsetLabel const *, Buffer::References> > RefCache;
@@ -141,7 +143,6 @@ void showPrintError(string const & name)
 
 } // namespace anon
 
-class BufferSet : public std::set<Buffer const *> {};
 
 class Buffer::Impl
 {
@@ -156,7 +157,7 @@ public:
                }
                delete inset;
        }
-
+       
        /// search for macro in local (buffer) table or in children
        MacroData const * getBufferMacro(docstring const & name,
                DocIterator const & pos) const;
@@ -166,8 +167,6 @@ public:
        void updateMacros(DocIterator & it, DocIterator & scope);
        ///
        void setLabel(ParIterator & it, UpdateType utype) const;
-       ///
-       void collectRelatives(BufferSet & bufs) const;
 
        /** If we have branches that use the file suffix
            feature, return the file name with suffix appended.
@@ -254,7 +253,9 @@ public:
        /// A cache for bibliography info
        mutable BiblioInfo bibinfo_;
        /// whether the bibinfo cache is valid
-       bool bibinfo_cache_valid_;
+       mutable bool bibinfo_cache_valid_;
+       /// whether the bibfile cache is valid
+       mutable bool bibfile_cache_valid_;
        /// Cache of timestamps of .bib files
        map<FileName, time_t> bibfile_status_;
 
@@ -276,18 +277,27 @@ public:
                        parent_buffer = 0;
                return parent_buffer; 
        }
+       
        ///
        void setParent(Buffer const * pb) {
-               if (!cloned_buffer_ 
-                   && parent_buffer && pb && parent_buffer != pb)
+               if (parent_buffer == pb)
+                       // nothing to do
+                       return;
+               if (!cloned_buffer_ && parent_buffer && pb)
                        LYXERR0("Warning: a buffer should not have two parents!");
                parent_buffer = pb;
+               if (!cloned_buffer_ && parent_buffer) {
+                       parent_buffer->invalidateBibfileCache();
+                       parent_buffer->invalidateBibinfoCache();
+               }
        }
 
        /// If non zero, this buffer is a clone of existing buffer \p cloned_buffer_
        /// This one is useful for preview detached in a thread.
        Buffer const * cloned_buffer_;
-
+       /// are we in the process of exporting this buffer?
+       mutable bool doing_export;
+       
 private:
        /// So we can force access via the accessors.
        mutable Buffer const * parent_buffer;
@@ -320,7 +330,8 @@ Buffer::Impl::Impl(Buffer * owner, FileName const & file, bool readonly_,
          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),
-         cloned_buffer_(cloned_buffer), parent_buffer(0)
+               bibfile_cache_valid_(false), cloned_buffer_(cloned_buffer), 
+               doing_export(false), parent_buffer(0)
 {
        if (!cloned_buffer_) {
                temppath = createBufferTmpDir();
@@ -335,6 +346,7 @@ Buffer::Impl::Impl(Buffer * owner, FileName const & file, bool readonly_,
        bibfiles_cache_ = cloned_buffer_->d->bibfiles_cache_;
        bibinfo_ = cloned_buffer_->d->bibinfo_;
        bibinfo_cache_valid_ = cloned_buffer_->d->bibinfo_cache_valid_;
+       bibfile_cache_valid_ = cloned_buffer_->d->bibfile_cache_valid_;
        bibfile_status_ = cloned_buffer_->d->bibfile_status_;
 }
 
@@ -402,8 +414,8 @@ Buffer::~Buffer()
                        from_utf8(d->temppath.absFileName())));
        }
 
-       // Remove any previewed LaTeX snippets associated with this buffer.
-       thePreviews().removeLoader(*this);
+       if (!isClone())
+               removePreviews();
 
        delete d;
 }
@@ -553,7 +565,7 @@ string Buffer::latexName(bool const no_path) const
 FileName Buffer::Impl::exportFileName() const
 {
        docstring const branch_suffix =
-               params.branchlist().getFilenameSuffix();
+               params.branchlist().getFileNameSuffix();
        if (branch_suffix.empty())
                return filename;
 
@@ -673,6 +685,10 @@ int Buffer::readHeader(Lexer & lex)
        params().isfontcolor = false;
        params().notefontcolor = lyx::rgbFromHexName("#cccccc");
        params().boxbgcolor = lyx::rgbFromHexName("#ff0000");
+       params().html_latex_start.clear();
+       params().html_latex_end.clear();
+       params().html_math_img_scale = 1.0;
+       params().output_sync_macro.erase();
 
        for (int i = 0; i < 4; ++i) {
                params().user_defined_bullet(i) = ITEMIZE_DEFAULTS[i];
@@ -737,15 +753,15 @@ bool Buffer::readDocument(Lexer & lex)
        ErrorList & errorList = d->errorLists["Parse"];
        errorList.clear();
 
+       // remove dummy empty par
+       paragraphs().clear();
+
        if (!lex.checkFor("\\begin_document")) {
                docstring const s = _("\\begin_document is missing");
                errorList.push_back(ErrorItem(_("Document header error"),
                        s, -1, 0, 0));
        }
 
-       // we are reading in a brand new document
-       LASSERT(paragraphs().empty(), /**/);
-
        readHeader(lex);
 
        if (params().outputChanges) {
@@ -771,7 +787,7 @@ bool Buffer::readDocument(Lexer & lex)
        if (!params().master.empty()) {
                FileName const master_file = makeAbsPath(params().master,
                           onlyPath(absFileName()));
-               if (isLyXFilename(master_file.absFileName())) {
+               if (isLyXFileName(master_file.absFileName())) {
                        Buffer * master = 
                                checkAndLoadLyXFile(master_file, true);
                        if (master) {
@@ -815,44 +831,65 @@ bool Buffer::readString(string const & s)
 {
        params().compressed = false;
 
-       // remove dummy empty par
-       paragraphs().clear();
        Lexer lex;
        istringstream is(s);
        lex.setStream(is);
-       FileName const name = FileName::tempName("Buffer_readString");
-       switch (readFile(lex, name, true)) {
-       case failure:
-               return false;
-       case wrongversion: {
+       FileName const fn = FileName::tempName("Buffer_readString");
+
+       int file_format;
+       ReadStatus const ret_plf = parseLyXFormat(lex, fn, file_format);
+       if (ret_plf != ReadSuccess)
+               return ret_plf;
+
+       if (file_format != LYX_FORMAT) {
                // We need to call lyx2lyx, so write the input to a file
-               ofstream os(name.toFilesystemEncoding().c_str());
+               ofstream os(fn.toFilesystemEncoding().c_str());
                os << s;
                os.close();
-               return readFile(name);
-       }
-       case success:
-               break;
+               // lyxvc in readFile
+               return readFile(fn) == ReadSuccess;
        }
 
+       if (readDocument(lex))
+               return false;
        return true;
 }
 
 
-bool Buffer::readFile(FileName const & filename)
+Buffer::ReadStatus Buffer::readFile(FileName const & fn)
 {
-       FileName fname(filename);
-
-       params().compressed = fname.isZippedFile();
-
-       // remove dummy empty par
-       paragraphs().clear();
+       FileName fname(fn);
        Lexer lex;
        lex.setFile(fname);
-       if (readFile(lex, fname) != success)
-               return false;
 
-       return true;
+       int file_format;
+       ReadStatus const ret_plf = parseLyXFormat(lex, fn, file_format);
+       if (ret_plf != ReadSuccess)
+               return ret_plf;
+
+       if (file_format != LYX_FORMAT) {
+               FileName tmpFile;
+               ReadStatus const ret_clf = convertLyXFormat(fn, tmpFile, file_format);
+               if (ret_clf != ReadSuccess)
+                       return ret_clf;
+               return readFile(tmpFile);
+       }
+
+       if (readDocument(lex)) {
+               Alert::error(_("Document format failure"),
+                       bformat(_("%1$s ended unexpectedly, which means"
+                               " that it is probably corrupted."),
+                                       from_utf8(fn.absFileName())));
+               return ReadDocumentFailure;
+       }
+
+       d->file_fully_loaded = true;
+       // InsetInfo needs to know if file is under VCS
+       lyxvc().file_found_hook(fn);
+       d->read_only = !fname.isWritable();
+       params().compressed = fname.isZippedFile();
+       saveCheckSum();
+       return ReadSuccess;
 }
 
 
@@ -868,112 +905,100 @@ void Buffer::setFullyLoaded(bool value)
 }
 
 
-Buffer::ReadStatus Buffer::readFile(Lexer & lex, FileName const & filename,
-               bool fromstring)
+void Buffer::updatePreviews() const
 {
-       LASSERT(!filename.empty(), /**/);
+       if (graphics::Previews::status() != LyXRC::PREVIEW_OFF)
+               thePreviews().generateBufferPreviews(*this);
+}
 
-       // the first (non-comment) token _must_ be...
-       if (!lex.checkFor("\\lyxformat")) {
+
+void Buffer::removePreviews() const
+{
+       thePreviews().removeLoader(*this);
+}
+
+
+Buffer::ReadStatus Buffer::parseLyXFormat(Lexer & lex,
+       FileName const & fn, int & file_format) const
+{
+       if(!lex.checkFor("\\lyxformat")) {
                Alert::error(_("Document format failure"),
-                            bformat(_("%1$s is not a readable LyX document."),
-                                      from_utf8(filename.absFileName())));
-               return failure;
-       }
+                       bformat(_("%1$s is not a readable LyX document."),
+                               from_utf8(fn.absFileName())));
+               return ReadNoLyXFormat;
+       }       
 
        string tmp_format;
        lex >> tmp_format;
-       //lyxerr << "LyX Format: `" << tmp_format << '\'' << endl;
-       // if present remove ".," from string.
+
+       // LyX formats 217 and earlier were written as 2.17. This corresponds
+       // to files from LyX versions < 1.1.6.3. We just remove the dot in
+       // these cases. See also: www.lyx.org/trac/changeset/1313.
        size_t dot = tmp_format.find_first_of(".,");
-       //lyxerr << "           dot found at " << dot << endl;
        if (dot != string::npos)
-                       tmp_format.erase(dot, 1);
-       int const file_format = convert<int>(tmp_format);
-       //lyxerr << "format: " << file_format << endl;
-
-       // save timestamp and checksum of the original disk file, making sure
-       // to not overwrite them with those of the file created in the tempdir
-       // when it has to be converted to the current format.
-       if (!d->checksum_) {
-               // Save the timestamp and checksum of disk file. If filename is an
-               // emergency file, save the timestamp and checksum of the original lyx file
-               // because isExternallyModified will check for this file. (BUG4193)
-               string diskfile = filename.absFileName();
-               if (suffixIs(diskfile, ".emergency"))
-                       diskfile = diskfile.substr(0, diskfile.size() - 10);
-               saveCheckSum(FileName(diskfile));
-       }
+               tmp_format.erase(dot, 1);
 
-       if (file_format != LYX_FORMAT) {
+       file_format = convert<int>(tmp_format);
+       return ReadSuccess;
+}
 
-               if (fromstring)
-                       // lyx2lyx would fail
-                       return wrongversion;
-
-               FileName const tmpfile = FileName::tempName("Buffer_readFile");
-               if (tmpfile.empty()) {
-                       Alert::error(_("Conversion failed"),
-                                    bformat(_("%1$s is from a different"
-                                             " version of LyX, but a temporary"
-                                             " file for converting it could"
-                                             " not be created."),
-                                             from_utf8(filename.absFileName())));
-                       return failure;
-               }
-               FileName const lyx2lyx = libFileSearch("lyx2lyx", "lyx2lyx");
-               if (lyx2lyx.empty()) {
-                       Alert::error(_("Conversion script not found"),
-                                    bformat(_("%1$s is from a different"
-                                              " version of LyX, but the"
-                                              " conversion script lyx2lyx"
-                                              " could not be found."),
-                                              from_utf8(filename.absFileName())));
-                       return failure;
-               }
-               ostringstream command;
-               command << os::python()
-                       << ' ' << quoteName(lyx2lyx.toFilesystemEncoding())
-                       << " -t " << convert<string>(LYX_FORMAT)
-                       << " -o " << quoteName(tmpfile.toFilesystemEncoding())
-                       << ' ' << quoteName(filename.toSafeFilesystemEncoding());
-               string const command_str = command.str();
-
-               LYXERR(Debug::INFO, "Running '" << command_str << '\'');
-
-               cmd_ret const ret = runCommand(command_str);
-               if (ret.first != 0) {
-                       if (file_format < LYX_FORMAT)
-                               Alert::error(_("Conversion script failed"),
-                                    bformat(_("%1$s is from an older version"
-                                             " of LyX, but the lyx2lyx script"
-                                             " failed to convert it."),
-                                             from_utf8(filename.absFileName())));
-                       else
-                               Alert::error(_("Conversion script failed"),
-                                    bformat(_("%1$s is from a newer version"
-                                             " of LyX and cannot be converted by the"
-                                                               " lyx2lyx script."),
-                                             from_utf8(filename.absFileName())));
-                       return failure;
-               } else {
-                       bool const ret = readFile(tmpfile);
-                       // Do stuff with tmpfile name and buffer name here.
-                       return ret ? success : failure;
-               }
 
+Buffer::ReadStatus Buffer::convertLyXFormat(FileName const & fn, 
+       FileName & tmpfile, int from_format)
+{
+       tmpfile = FileName::tempName("Buffer_convertLyXFormat");
+       if(tmpfile.empty()) {
+               Alert::error(_("Conversion failed"),
+                       bformat(_("%1$s is from a different"
+                               " version of LyX, but a temporary"
+                               " file for converting it could"
+                               " not be created."),
+                               from_utf8(fn.absFileName())));
+               return LyX2LyXNoTempFile;
        }
 
-       if (readDocument(lex)) {
-               Alert::error(_("Document format failure"),
-                            bformat(_("%1$s ended unexpectedly, which means"
-                                                   " that it is probably corrupted."),
-                                      from_utf8(filename.absFileName())));
-               return failure;
+       FileName const lyx2lyx = libFileSearch("lyx2lyx", "lyx2lyx");
+       if (lyx2lyx.empty()) {
+               Alert::error(_("Conversion script not found"),
+                    bformat(_("%1$s is from a different"
+                              " version of LyX, but the"
+                              " conversion script lyx2lyx"
+                              " could not be found."),
+                              from_utf8(fn.absFileName())));
+               return LyX2LyXNotFound;
        }
 
-       d->file_fully_loaded = true;
-       return success;
+       // Run lyx2lyx:
+       //   $python$ "$lyx2lyx$" -t $LYX_FORMAT$ -o "$tempfile$" "$filetoread$"
+       ostringstream command;
+       command << os::python()
+               << ' ' << quoteName(lyx2lyx.toFilesystemEncoding())
+               << " -t " << convert<string>(LYX_FORMAT)
+               << " -o " << quoteName(tmpfile.toFilesystemEncoding())
+               << ' ' << quoteName(fn.toSafeFilesystemEncoding());
+       string const command_str = command.str();
+
+       LYXERR(Debug::INFO, "Running '" << command_str << '\'');
+
+       cmd_ret const ret = runCommand(command_str);
+       if (ret.first != 0) {
+               if (from_format < LYX_FORMAT) {
+                       Alert::error(_("Conversion script failed"),
+                               bformat(_("%1$s is from an older version"
+                                       " of LyX, but the lyx2lyx script"
+                                       " failed to convert it."),
+                                       from_utf8(fn.absFileName())));
+                       return LyX2LyXOlderFormat;
+               } else {
+                       Alert::error(_("Conversion script failed"),
+                               bformat(_("%1$s is from an newer version"
+                                       " of LyX, but the lyx2lyx script"
+                                       " failed to convert it."),
+                                       from_utf8(fn.absFileName())));
+                       return LyX2LyXNewerFormat;
+               }
+       }
+       return ReadSuccess;
 }
 
 
@@ -1006,6 +1031,7 @@ bool Buffer::save() const
                        backupName = FileName(addName(lyxrc.backupdir_path,
                                                      mangledName));
                }
+               // do not copy because of #6587
                if (fileName().moveTo(backupName)) {
                        madeBackup = true;
                } else {
@@ -1058,7 +1084,7 @@ bool Buffer::writeFile(FileName const & fname) const
        // see bug 6587
        // removeAutosaveFile();
 
-       saveCheckSum(d->filename);
+       saveCheckSum();
        message(str + _(" done."));
 
        return true;
@@ -1564,7 +1590,6 @@ void Buffer::writeLyXHTMLSource(odocstream & os,
        LaTeXFeatures features(*this, params(), runparams);
        validate(features);
        updateBuffer(UpdateMaster, OutputUpdate);
-       checkBibInfoCache();
        d->bibinfo_.makeCitationLabels(*this);
        updateMacros();
        updateMacroInstances();
@@ -1656,7 +1681,7 @@ void Buffer::validate(LaTeXFeatures & features) const
        updateMacros();
 
        for_each(paragraphs().begin(), paragraphs().end(),
-                boost::bind(&Paragraph::validate, _1, boost::ref(features)));
+                bind(&Paragraph::validate, _1, ref(features)));
 
        if (lyxerr.debugging(Debug::LATEX)) {
                features.showStruct();
@@ -1666,10 +1691,9 @@ void Buffer::validate(LaTeXFeatures & features) const
 
 void Buffer::getLabelList(vector<docstring> & list) const
 {
-       // If this is a child document, use the parent's list instead.
-       Buffer const * const pbuf = d->parent();
-       if (pbuf) {
-               pbuf->getLabelList(list);
+       // If this is a child document, use the master's list instead.
+       if (parent()) {
+               masterBuffer()->getLabelList(list);
                return;
        }
 
@@ -1686,54 +1710,71 @@ void Buffer::getLabelList(vector<docstring> & list) const
 
 void Buffer::updateBibfilesCache(UpdateScope scope) const
 {
+       // FIXME This is probably unnecssary, given where we call this.
        // If this is a child document, use the parent's cache instead.
-       Buffer const * const pbuf = d->parent();
-       if (pbuf && scope != UpdateChildOnly) {
-               pbuf->updateBibfilesCache();
+       if (parent() && scope != UpdateChildOnly) {
+               masterBuffer()->updateBibfilesCache();
                return;
        }
 
        d->bibfiles_cache_.clear();
        for (InsetIterator it = inset_iterator_begin(inset()); it; ++it) {
                if (it->lyxCode() == BIBTEX_CODE) {
-                       InsetBibtex const & inset =
-                               static_cast<InsetBibtex const &>(*it);
+                       InsetBibtex const & inset = static_cast<InsetBibtex const &>(*it);
                        support::FileNameList const bibfiles = inset.getBibFiles();
                        d->bibfiles_cache_.insert(d->bibfiles_cache_.end(),
                                bibfiles.begin(),
                                bibfiles.end());
                } else if (it->lyxCode() == INCLUDE_CODE) {
-                       InsetInclude & inset =
-                               static_cast<InsetInclude &>(*it);
-                       inset.updateBibfilesCache();
+                       InsetInclude & inset = static_cast<InsetInclude &>(*it);
+                       Buffer const * const incbuf = inset.getChildBuffer();
+                       if (!incbuf)
+                               continue;
                        support::FileNameList const & bibfiles =
-                                       inset.getBibfilesCache();
-                       d->bibfiles_cache_.insert(d->bibfiles_cache_.end(),
-                               bibfiles.begin(),
-                               bibfiles.end());
+                                       incbuf->getBibfilesCache(UpdateChildOnly);
+                       if (!bibfiles.empty()) {
+                               d->bibfiles_cache_.insert(d->bibfiles_cache_.end(),
+                                       bibfiles.begin(),
+                                       bibfiles.end());
+                       }
                }
        }
-       // the bibinfo cache is now invalid
+       d->bibfile_cache_valid_ = true;
        d->bibinfo_cache_valid_ = false;
 }
 
 
-void Buffer::invalidateBibinfoCache()
+void Buffer::invalidateBibinfoCache() const
 {
        d->bibinfo_cache_valid_ = false;
+       // also invalidate the cache for the parent buffer
+       Buffer const * const pbuf = d->parent();
+       if (pbuf)
+               pbuf->invalidateBibinfoCache();
 }
 
 
-support::FileNameList const & Buffer::getBibfilesCache(UpdateScope scope) const
+void Buffer::invalidateBibfileCache() const
 {
-       // If this is a child document, use the parent's cache instead.
+       d->bibfile_cache_valid_ = false;
+       d->bibinfo_cache_valid_ = false;
+       // also invalidate the cache for the parent buffer
        Buffer const * const pbuf = d->parent();
-       if (pbuf && scope != UpdateChildOnly)
+       if (pbuf)
+               pbuf->invalidateBibfileCache();
+}
+
+
+support::FileNameList 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.
+       Buffer const * const pbuf = masterBuffer();
+       if (pbuf != this && scope != UpdateChildOnly)
                return pbuf->getBibfilesCache();
 
-       // We update the cache when first used instead of at loading time.
-       if (d->bibfiles_cache_.empty())
-               const_cast<Buffer *>(this)->updateBibfilesCache(scope);
+       if (!d->bibfile_cache_valid_)
+               this->updateBibfilesCache(scope);
 
        return d->bibfiles_cache_;
 }
@@ -1741,28 +1782,28 @@ support::FileNameList const & Buffer::getBibfilesCache(UpdateScope scope) const
 
 BiblioInfo const & Buffer::masterBibInfo() const
 {
-       // if this is a child document and the parent is already loaded
-       // use the parent's list instead  [ale990412]
        Buffer const * const tmp = masterBuffer();
-       LASSERT(tmp, /**/);
        if (tmp != this)
                return tmp->masterBibInfo();
-       return localBibInfo();
-}
-
-
-BiblioInfo const & Buffer::localBibInfo() const
-{
        return d->bibinfo_;
 }
 
 
 void Buffer::checkBibInfoCache() const 
 {
-       support::FileNameList const & bibfilesCache = getBibfilesCache();
+       // use the master's cache
+       Buffer const * const tmp = masterBuffer();
+       if (tmp != this) {
+               tmp->checkBibInfoCache();
+               return;
+       }
+
+       // this will also reload the cache if it is invalid 
+       support::FileNameList const & bibfiles_cache = getBibfilesCache();
+       
        // compare the cached timestamps with the actual ones.
-       support::FileNameList::const_iterator ei = bibfilesCache.begin();
-       support::FileNameList::const_iterator en = bibfilesCache.end();
+       support::FileNameList::const_iterator ei = bibfiles_cache.begin();
+       support::FileNameList::const_iterator en = bibfiles_cache.end();
        for (; ei != en; ++ ei) {
                time_t lastw = ei->lastModified();
                time_t prevw = d->bibfile_status_[*ei];
@@ -1771,13 +1812,20 @@ void Buffer::checkBibInfoCache() const
                        d->bibfile_status_[*ei] = lastw;
                }
        }
-
+       
+       // if not valid, then reload the info
        if (!d->bibinfo_cache_valid_) {
                d->bibinfo_.clear();
-               for (InsetIterator it = inset_iterator_begin(inset()); it; ++it)
-                       it->fillWithBibKeys(d->bibinfo_, it);
+               fillWithBibKeys(d->bibinfo_);
                d->bibinfo_cache_valid_ = true;
-       }       
+       }
+}
+
+
+void Buffer::fillWithBibKeys(BiblioInfo & keys) const
+{
+       for (InsetIterator it = inset_iterator_begin(inset()); it; ++it)
+               it->fillWithBibKeys(keys, it);
 }
 
 
@@ -1978,28 +2026,37 @@ void Buffer::dispatch(FuncRequest const & func, DispatchResult & dr)
                break;
 
        case LFUN_BRANCH_ADD: {
-               docstring const branch_name = func.argument();
+               docstring branch_name = func.argument();
                if (branch_name.empty()) {
                        dispatched = false;
                        break;
                }
                BranchList & branch_list = params().branchlist();
-               Branch * branch = branch_list.find(branch_name);
-               if (branch) {
-                       LYXERR0("Branch " << branch_name << " already exists.");
-                       dr.setError(true);
-                       docstring const msg = 
-                               bformat(_("Branch \"%1$s\" already exists."), branch_name);
-                       dr.setMessage(msg);
-               } else {
-                       branch_list.add(branch_name);
-                       branch = branch_list.find(branch_name);
-                       string const x11hexname = X11hexname(branch->color());
-                       docstring const str = branch_name + ' ' + from_ascii(x11hexname);
-                       lyx::dispatch(FuncRequest(LFUN_SET_COLOR, str));        
-                       dr.setError(false);
-                       dr.update(Update::Force);
+               vector<docstring> const branches =
+                       getVectorFromString(branch_name, branch_list.separator());
+               docstring msg;
+               for (vector<docstring>::const_iterator it = branches.begin();
+                    it != branches.end(); ++it) {
+                       branch_name = *it;
+                       Branch * branch = branch_list.find(branch_name);
+                       if (branch) {
+                               LYXERR0("Branch " << branch_name << " already exists.");
+                               dr.setError(true);
+                               if (!msg.empty())
+                                       msg += ("\n");
+                               msg += bformat(_("Branch \"%1$s\" already exists."), branch_name);
+                       } else {
+                               branch_list.add(branch_name);
+                               branch = branch_list.find(branch_name);
+                               string const x11hexname = X11hexname(branch->color());
+                               docstring const str = branch_name + ' ' + from_ascii(x11hexname);
+                               lyx::dispatch(FuncRequest(LFUN_SET_COLOR, str));
+                               dr.setError(false);
+                               dr.screenUpdate(Update::Force);
+                       }
                }
+               if (!msg.empty())
+                       dr.setMessage(msg);
                break;
        }
 
@@ -2022,7 +2079,8 @@ void Buffer::dispatch(FuncRequest const & func, DispatchResult & dr)
                } else {
                        branch->setSelected(func.action() == LFUN_BRANCH_ACTIVATE);
                        dr.setError(false);
-                       dr.update(Update::Force);
+                       dr.screenUpdate(Update::Force);
+                       dr.forceBufferUpdate();
                }
                break;
        }
@@ -2057,8 +2115,10 @@ void Buffer::dispatch(FuncRequest const & func, DispatchResult & dr)
                        }
                }
 
-               if (success)
-                       dr.update(Update::Force);
+               if (success) {
+                       dr.screenUpdate(Update::Force);
+                       dr.forceBufferUpdate();
+               }
                break;
        }
 
@@ -2184,8 +2244,10 @@ void Buffer::dispatch(FuncRequest const & func, DispatchResult & dr)
                Language const * newL = languages.getLanguage(argument);
                if (!newL || oldL == newL)
                        break;
-               if (oldL->rightToLeft() == newL->rightToLeft() && !isMultiLingual())
+               if (oldL->rightToLeft() == newL->rightToLeft() && !isMultiLingual()) {
                        changeLanguage(oldL, newL);
+                       dr.forceBufferUpdate();
+               }
                break;
        }
 
@@ -2237,9 +2299,10 @@ void Buffer::getLanguages(std::set<Language const *> & languages) const
        for (ParConstIterator it = par_iterator_begin(); it != end; ++it)
                it->getLanguages(languages);
        // also children
-       std::vector<Buffer *> clist = getChildren();
-       for (vector<Buffer *>::const_iterator cit = clist.begin();
-            cit != clist.end(); ++cit)
+       ListOfBuffers clist = getDescendents();
+       ListOfBuffers::const_iterator cit = clist.begin();
+       ListOfBuffers::const_iterator const cen = clist.end();
+       for (; cit != cen; ++cit)
                (*cit)->getLanguages(languages);
 }
 
@@ -2319,8 +2382,9 @@ bool Buffer::isExternallyModified(CheckMethod method) const
 }
 
 
-void Buffer::saveCheckSum(FileName const & file) const
+void Buffer::saveCheckSum() const
 {
+       FileName const & file = d->filename;
        if (file.exists()) {
                d->timestamp_ = file.lastModified();
                d->checksum_ = file.checksum();
@@ -2341,6 +2405,7 @@ void Buffer::markClean() const
        // if the .lyx file has been saved, we don't need an
        // autosave
        d->bak_clean = true;
+       d->undo_.markDirty();
 }
 
 
@@ -2421,34 +2486,18 @@ Buffer const * Buffer::parent() const
 }
 
 
-void Buffer::Impl::collectRelatives(BufferSet & bufs) const
-{
-       bufs.insert(owner_);
-       if (parent())
-               parent()->d->collectRelatives(bufs);
-
-       // loop over children
-       BufferPositionMap::const_iterator it = children_positions.begin();
-       BufferPositionMap::const_iterator end = children_positions.end();
-       for (; it != end; ++it)
-               bufs.insert(const_cast<Buffer *>(it->first));
-}
-
-
-std::vector<Buffer const *> Buffer::allRelatives() const
+ListOfBuffers Buffer::allRelatives() const
 {
-       BufferSet bufs;
-       d->collectRelatives(bufs);
-       BufferSet::iterator it = bufs.begin();
-       std::vector<Buffer const *> ret;
-       for (; it != bufs.end(); ++it)
-               ret.push_back(*it);
-       return ret;
+       ListOfBuffers lb = masterBuffer()->getDescendents();
+       lb.push_front(const_cast<Buffer *>(this));
+       return lb;
 }
 
 
 Buffer const * Buffer::masterBuffer() const
 {
+       // FIXME Should be make sure we are not in some kind
+       // of recursive include? A -> B -> A will crash this.
        Buffer const * const pbuf = d->parent();
        if (!pbuf)
                return this;
@@ -2473,27 +2522,43 @@ DocIterator Buffer::firstChildPosition(Buffer const * child)
 }
 
 
-void Buffer::getChildren(std::vector<Buffer *> & clist, bool grand_children) const
+bool Buffer::hasChildren() const
+{
+       return !d->children_positions.empty();  
+}
+
+
+void Buffer::collectChildren(ListOfBuffers & clist, bool grand_children) const
 {
        // loop over children
        Impl::BufferPositionMap::iterator it = d->children_positions.begin();
        Impl::BufferPositionMap::iterator end = d->children_positions.end();
        for (; it != end; ++it) {
                Buffer * child = const_cast<Buffer *>(it->first);
+               // No duplicates
+               ListOfBuffers::const_iterator bit = find(clist.begin(), clist.end(), child);
+               if (bit != clist.end())
+                       continue;
                clist.push_back(child);
-               if (grand_children) {
+               if (grand_children) 
                        // there might be grandchildren
-                       vector<Buffer *> glist = child->getChildren();
-                       clist.insert(clist.end(), glist.begin(), glist.end());
-               }
+                       child->collectChildren(clist, true);
        }
 }
 
 
-vector<Buffer *> Buffer::getChildren(bool grand_children) const
+ListOfBuffers Buffer::getChildren() const
+{
+       ListOfBuffers v;
+       collectChildren(v, false);
+       return v;
+}
+
+
+ListOfBuffers Buffer::getDescendents() const
 {
-       vector<Buffer *> v;
-       getChildren(v, grand_children);
+       ListOfBuffers v;
+       collectChildren(v, true);
        return v;
 }
 
@@ -2675,6 +2740,17 @@ void Buffer::Impl::updateMacros(DocIterator & it, DocIterator & scope)
                                it.pop_back();
                                continue;
                        }
+                       
+                       if (iit->inset->asInsetTabular()) {
+                               CursorSlice slice(*iit->inset);
+                               size_t const numcells = slice.nargs();
+                               for (; slice.idx() < numcells; slice.forwardIdx()) {
+                                       it.push_back(slice);
+                                       updateMacros(it, scope);
+                                       it.pop_back();
+                               }
+                               continue;
+                       }
 
                        // is it an external file?
                        if (iit->inset->lyxCode() == INCLUDE_CODE) {
@@ -2698,12 +2774,19 @@ void Buffer::Impl::updateMacros(DocIterator & it, DocIterator & scope)
                                continue;
                        }
 
+                       InsetMath * im = iit->inset->asInsetMath();
+                       if (doing_export && im)  {
+                               InsetMathHull * hull = im->asHullInset();
+                               if (hull)
+                                       hull->recordLocation(it);
+                       }
+
                        if (iit->inset->lyxCode() != MATHMACRO_CODE)
                                continue;
 
                        // get macro data
                        MathMacroTemplate & macroTemplate =
-                               static_cast<MathMacroTemplate &>(*iit->inset);
+                               *iit->inset->asInsetMath()->asMacroTemplate();
                        MacroContext mc(owner_, it);
                        macroTemplate.updateToContext(mc);
 
@@ -2927,10 +3010,12 @@ void Buffer::changeRefsIfUnique(docstring const & from, docstring const & to,
 
        for (InsetIterator it = inset_iterator_begin(inset()); it; ++it) {
                if (it->lyxCode() == code) {
-                       InsetCommand & inset = static_cast<InsetCommand &>(*it);
-                       docstring const oldValue = inset.getParam(paramName);
+                       InsetCommand * inset = it->asInsetCommand();
+                       if (!inset)
+                               continue;
+                       docstring const oldValue = inset->getParam(paramName);
                        if (oldValue == from)
-                               inset.setParam(paramName, to);
+                               inset->setParam(paramName, to);
                }
        }
 }
@@ -3067,9 +3152,9 @@ public:
        AutoSaveBuffer(Buffer const & buffer, FileName const & fname)
                : buffer_(buffer), fname_(fname) {}
        ///
-       virtual boost::shared_ptr<ForkedProcess> clone() const
+       virtual shared_ptr<ForkedProcess> clone() const
        {
-               return boost::shared_ptr<ForkedProcess>(new AutoSaveBuffer(*this));
+               return shared_ptr<ForkedProcess>(new AutoSaveBuffer(*this));
        }
        ///
        int start()
@@ -3141,7 +3226,19 @@ int AutoSaveBuffer::generateChild()
 } // namespace anon
 
 
-FileName Buffer::getAutosaveFilename() const
+FileName Buffer::getEmergencyFileName() const
+{
+       return getEmergencyFileNameFor(d->filename);
+}
+
+
+FileName Buffer::getEmergencyFileNameFor(FileName const & fn) const
+{
+       return FileName(fn.absFileName() + ".emergency");
+}
+
+
+FileName Buffer::getAutosaveFileName() const
 {
        // if the document is unnamed try to save in the backup dir, else
        // in the default document path, and as a last try in the filePath, 
@@ -3153,14 +3250,21 @@ FileName Buffer::getAutosaveFilename() const
        if (!isUnnamed() || fpath.empty() || !FileName(fpath).exists())
                fpath = filePath();
 
-       string const fname = "#" + d->filename.onlyFileName() + "#";
-       return makeAbsPath(fname, fpath);
+       string const fname = d->filename.onlyFileName();
+       return getAutosaveFileNameFor(makeAbsPath(fname, fpath));
+}
+
+
+FileName Buffer::getAutosaveFileNameFor(FileName const & fn) const
+{
+       string const fname = "#" + onlyFileName(fn.absFileName()) + "#";
+       return FileName(onlyPath(fn.absFileName()) + fname);
 }
 
 
 void Buffer::removeAutosaveFile() const
 {
-       FileName const f = getAutosaveFilename();
+       FileName const f = getAutosaveFileName();
        if (f.exists())
                f.removeFile();
 }
@@ -3168,7 +3272,7 @@ void Buffer::removeAutosaveFile() const
 
 void Buffer::moveAutosaveFile(support::FileName const & oldauto) const
 {
-       FileName const newauto = getAutosaveFilename();
+       FileName const newauto = getAutosaveFileName();
        oldauto.refresh();
        if (newauto != oldauto && oldauto.exists())
                if (!oldauto.moveTo(newauto))
@@ -3187,7 +3291,7 @@ void Buffer::autoSave() const
 
        // emit message signal.
        message(_("Autosaving current document..."));
-       AutoSaveBuffer autosave(*this, getAutosaveFilename());
+       AutoSaveBuffer autosave(*this, getAutosaveFileName());
        autosave.start();
 
        d->bak_clean = true;
@@ -3229,10 +3333,41 @@ string Buffer::getDefaultOutputFormat() const
 }
 
 
+namespace {
+       // helper class, to guarantee this gets reset properly
+       class MarkAsExporting   {
+       public:
+               MarkAsExporting(Buffer const * buf) : buf_(buf) 
+               {
+                       LASSERT(buf_, /* */);
+                       buf_->setExportStatus(true);
+               }
+               ~MarkAsExporting() 
+               {
+                       buf_->setExportStatus(false);
+               }
+       private:
+               Buffer const * const buf_;
+       };
+}
+
+
+void Buffer::setExportStatus(bool e) const
+{
+       d->doing_export = e;    
+}
+
+
+bool Buffer::isExporting() const
+{
+       return d->doing_export;
+}
+
 
 bool Buffer::doExport(string const & format, bool put_in_tempdir,
        bool includeall, string & result_file) const
 {
+       MarkAsExporting exporting(this);
        string backend_format;
        OutputParams runparams(&params().encoding());
        runparams.flavor = OutputParams::LATEX;
@@ -3342,9 +3477,10 @@ bool Buffer::doExport(string const & format, bool put_in_tempdir,
                } else 
                        errors(error_type);
                // also to the children, in case of master-buffer-view
-               std::vector<Buffer *> clist = getChildren();
-               for (vector<Buffer *>::const_iterator cit = clist.begin();
-                       cit != clist.end(); ++cit) {
+               ListOfBuffers clist = getDescendents();
+               ListOfBuffers::const_iterator cit = clist.begin();
+               ListOfBuffers::const_iterator const cen = clist.end();
+               for (; cit != cen; ++cit) {
                        if (d->cloned_buffer_) {
                                (*cit)->d->cloned_buffer_->d->errorLists[error_type] = 
                                        (*cit)->d->errorLists[error_type];
@@ -3429,6 +3565,7 @@ bool Buffer::doExport(string const & format, bool put_in_tempdir,
 
 bool Buffer::preview(string const & format, bool includeall) const
 {
+       MarkAsExporting exporting(this);
        string result_file;
        // (1) export with all included children (omit \includeonly)
        if (includeall && !doExport(format, true, true))
@@ -3480,109 +3617,132 @@ vector<string> Buffer::backends() const
 }
 
 
-bool Buffer::readFileHelper(FileName const & s)
+Buffer::ReadStatus Buffer::extractFromVC(FileName const & fn)
 {
-       // File information about normal file
-       if (!s.exists()) {
-               docstring const file = makeDisplayPath(s.absFileName(), 50);
-               docstring text = bformat(_("The specified document\n%1$s"
-                                                    "\ncould not be read."), file);
-               Alert::error(_("Could not read document"), text);
-               return false;
-       }
+       bool const found = LyXVC::file_not_found_hook(fn);
+       if (!found)
+               return ReadFileNotFound;
+       if (!fn.isReadableFile())
+               return ReadVCError;
+       return ReadSuccess;
+}
 
-       // Check if emergency save file exists and is newer.
-       FileName const e(s.absFileName() + ".emergency");
 
-       if (e.exists() && s.exists() && e.lastModified() > s.lastModified()) {
-               docstring const file = makeDisplayPath(s.absFileName(), 20);
-               docstring const text =
-                       bformat(_("An emergency save of the document "
-                                 "%1$s exists.\n\n"
-                                              "Recover emergency save?"), file);
-               switch (Alert::prompt(_("Load emergency save?"), text, 0, 2,
-                                     _("&Recover"),  _("&Load Original"),
-                                     _("&Cancel")))
-               {
-               case 0: {
-                       // the file is not saved if we load the emergency file.
+Buffer::ReadStatus Buffer::loadEmergency(FileName const & fn)
+{
+       FileName const emergencyFile = getEmergencyFileNameFor(fn);
+       if (!emergencyFile.exists() 
+                 || emergencyFile.lastModified() <= fn.lastModified())
+               return ReadFileNotFound;
+
+       docstring const file = makeDisplayPath(fn.absFileName(), 20);
+       docstring const text = bformat(_("An emergency save of the document "
+               "%1$s exists.\n\nRecover emergency save?"), file);
+       
+       int const load_emerg = Alert::prompt(_("Load emergency save?"), text,
+               0, 2, _("&Recover"), _("&Load Original"), _("&Cancel"));
+
+       switch (load_emerg)
+       {
+       case 0: {
+               docstring str;
+               ReadStatus const ret_llf = loadThisLyXFile(emergencyFile);
+               bool const success = (ret_llf == ReadSuccess);
+               if (success) {
                        markDirty();
-                       docstring str;
-                       bool res;
-
-                       if ((res = readFile(e)) == success)
-                               str = _("Document was successfully recovered.");
-                       else
-                               str = _("Document was NOT successfully recovered.");
-                       str += "\n\n" + bformat(_("Remove emergency file now?\n(%1$s)"),
-                                               makeDisplayPath(e.absFileName()));
-
-                       if (!Alert::prompt(_("Delete emergency file?"), str, 1, 1,
-                                       _("&Remove"), _("&Keep it"))) {
-                               e.removeFile();
-                               if (res == success)
-                                       Alert::warning(_("Emergency file deleted"),
-                                               _("Do not forget to save your file now!"), true);
-                               }
-                       return res;
-               }
-               case 1:
-                       if (!Alert::prompt(_("Delete emergency file?"),
-                                       _("Remove emergency file now?"), 1, 1,
-                                       _("&Remove"), _("&Keep it")))
-                               e.removeFile();
-                       break;
-               default:
-                       return false;
-               }
+                       str = _("Document was successfully recovered.");
+               } else
+                       str = _("Document was NOT successfully recovered.");
+               str += "\n\n" + bformat(_("Remove emergency file now?\n(%1$s)"),
+                                       makeDisplayPath(emergencyFile.absFileName()));
+
+               int const del_emerg = 
+                       Alert::prompt(_("Delete emergency file?"), str, 1, 1,
+                               _("&Remove"), _("&Keep"));
+               if (del_emerg == 0) {
+                       emergencyFile.removeFile();
+                       if (success)
+                               Alert::warning(_("Emergency file deleted"),
+                                       _("Do not forget to save your file now!"), true);
+                       }
+               return success ? ReadSuccess : ReadEmergencyFailure;
+       }
+       case 1: {
+               int const del_emerg =
+                       Alert::prompt(_("Delete emergency file?"),
+                               _("Remove emergency file now?"), 1, 1,
+                               _("&Remove"), _("&Keep"));
+               if (del_emerg == 0)
+                       emergencyFile.removeFile();
+               return ReadOriginal;
        }
 
+       default:
+               break;
+       }
+       return ReadCancel;
+}
+
+
+Buffer::ReadStatus Buffer::loadAutosave(FileName const & fn)
+{
        // Now check if autosave file is newer.
-       FileName const a(onlyPath(s.absFileName()) + '#' + onlyFileName(s.absFileName()) + '#');
-
-       if (a.exists() && s.exists() && a.lastModified() > s.lastModified()) {
-               docstring const file = makeDisplayPath(s.absFileName(), 20);
-               docstring const text =
-                       bformat(_("The backup of the document "
-                                 "%1$s is newer.\n\nLoad the "
-                                              "backup instead?"), file);
-               switch (Alert::prompt(_("Load backup?"), text, 0, 2,
-                                     _("&Load backup"), _("Load &original"),
-                                     _("&Cancel") ))
-               {
-               case 0:
-                       // the file is not saved if we load the autosave file.
+       FileName const autosaveFile = getAutosaveFileNameFor(fn);
+       if (!autosaveFile.exists() 
+                 || autosaveFile.lastModified() <= fn.lastModified()) 
+               return ReadFileNotFound;
+
+       docstring const file = makeDisplayPath(fn.absFileName(), 20);
+       docstring const text = bformat(_("The backup of the document %1$s " 
+               "is newer.\n\nLoad the backup instead?"), file);
+       int const ret = Alert::prompt(_("Load backup?"), text, 0, 2,
+               _("&Load backup"), _("Load &original"), _("&Cancel"));
+       
+       switch (ret)
+       {
+       case 0: {
+               ReadStatus const ret_llf = loadThisLyXFile(autosaveFile);
+               // the file is not saved if we load the autosave file.
+               if (ret_llf == ReadSuccess) {
                        markDirty();
-                       return readFile(a);
-               case 1:
-                       // Here we delete the autosave
-                       a.removeFile();
-                       break;
-               default:
-                       return false;
+                       return ReadSuccess;
                }
+               return ReadAutosaveFailure;
        }
-       return readFile(s);
+       case 1:
+               // Here we delete the autosave
+               autosaveFile.removeFile();
+               return ReadOriginal;
+       default:
+               break;
+       }
+       return ReadCancel;
 }
 
 
-bool Buffer::loadLyXFile(FileName const & s)
+Buffer::ReadStatus Buffer::loadLyXFile(FileName const & fn)
 {
-       // If the file is not readable, we try to
-       // retrieve the file from version control.
-       if (!s.isReadableFile()
-                 && !LyXVC::file_not_found_hook(s))
-               return false;
-       
-       if (s.isReadableFile()){
-               // InsetInfo needs to know if file is under VCS
-               lyxvc().file_found_hook(s);
-               if (readFileHelper(s)) {
-                       d->read_only = !s.isWritable();
-                       return true;
-               }
+       if (!fn.isReadableFile()) {
+               ReadStatus const ret_rvc = extractFromVC(fn);
+               if (ret_rvc != ReadSuccess)
+                       return ret_rvc;
        }
-       return false;
+
+       ReadStatus const ret_re = loadEmergency(fn);
+       if (ret_re == ReadSuccess || ret_re == ReadCancel)
+               return ret_re;
+       
+       ReadStatus const ret_ra = loadAutosave(fn);
+       if (ret_ra == ReadSuccess || ret_ra == ReadCancel)
+               return ret_ra;
+
+       return loadThisLyXFile(fn);
+}
+
+
+Buffer::ReadStatus Buffer::loadThisLyXFile(FileName const & fn)
+{
+       return readFile(fn);
 }
 
 
@@ -3623,7 +3783,7 @@ void Buffer::updateBuffer(UpdateScope scope, UpdateType utype) const
        DocumentClass const & textclass = master->params().documentClass();
        
        // do this only if we are the top-level Buffer
-       if (scope != UpdateMaster || master == this)
+       if (master == this)
                checkBibInfoCache();
 
        // keep the buffers to be children in this set. If the call from the
@@ -3877,10 +4037,8 @@ void Buffer::updateBuffer(ParIterator & parit, UpdateType utype) const
 {
        LASSERT(parit.pit() == 0, /**/);
 
-       // set the position of the text in the buffer to be able
-       // to resolve macros in it. This has nothing to do with
-       // labels, but by putting it here we avoid implementing
-       // a whole bunch of traversal routines just for this call.
+       // Set the position of the text in the buffer to be able
+       // to resolve macros in it.
        parit.text()->setMacrocontextPosition(parit);
 
        depth_type maxdepth = 0;
@@ -3932,7 +4090,9 @@ int Buffer::spellCheck(DocIterator & from, DocIterator & to,
                if (from == end)
                        break;
                to = from;
-               if (from.paragraph().spellCheck(from.pos(), to.pos(), wl, suggestions)) {
+               from.paragraph().spellCheck();
+               SpellChecker::Result res = from.paragraph().spellCheck(from.pos(), to.pos(), wl, suggestions);
+               if (SpellChecker::misspelled(res)) {
                        word_lang = wl;
                        break;
                }
@@ -3948,7 +4108,7 @@ int Buffer::spellCheck(DocIterator & from, DocIterator & to,
 }
 
 
-bool Buffer::reload()
+Buffer::ReadStatus Buffer::reload()
 {
        setBusy(true);
        // c.f. bug 6587
@@ -3957,21 +4117,21 @@ bool Buffer::reload()
        d->filename.refresh();
        docstring const disp_fn = makeDisplayPath(d->filename.absFileName());
 
-       bool const success = loadLyXFile(d->filename);
-       if (success) {
+       ReadStatus const status = loadLyXFile(d->filename);
+       if (status == ReadSuccess) {
                updateBuffer();
                changed(true);
+               updateTitles();
                markClean();
                message(bformat(_("Document %1$s reloaded."), disp_fn));
        } else {
                message(bformat(_("Could not reload document %1$s."), disp_fn));
        }       
        setBusy(false);
-       thePreviews().removeLoader(*this);
-       if (graphics::Previews::status() != LyXRC::PREVIEW_OFF)
-               thePreviews().generateBufferPreviews(*this);
+       removePreviews();
+       updatePreviews();
        errors("Parse");
-       return success;
+       return status;
 }