]> git.lyx.org Git - lyx.git/blobdiff - src/Buffer.cpp
reorder initializers to avoid warning
[lyx.git] / src / Buffer.cpp
index 6ed365c894d5fe4ab30804835380592cf8c4d03e..3632af200c769a9bc53f8b3f1914ca27d26acb15 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 {
 
@@ -127,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 = 412; // edwin: set tabular width
+int const LYX_FORMAT = 413; // rgh: html_css_as_file
 
 typedef map<string, bool> DepClean;
 typedef map<docstring, pair<InsetLabel const *, Buffer::References> > RefCache;
@@ -150,6 +151,7 @@ public:
 
        ~Impl()
        {
+               delete preview_loader_;
                if (wa_) {
                        wa_->closeAll();
                        delete wa_;
@@ -257,12 +259,19 @@ public:
        mutable bool bibfile_cache_valid_;
        /// Cache of timestamps of .bib files
        map<FileName, time_t> bibfile_status_;
+       /// Indicates whether the bibinfo has changed since the last time
+       /// we ran updateBuffer(), i.e., whether citation labels may need
+       /// to be updated.
+       mutable bool cite_labels_valid_;
 
        mutable RefCache ref_cache_;
 
        /// 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 { 
@@ -327,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), 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();
@@ -347,6 +357,7 @@ Buffer::Impl::Impl(Buffer * owner, FileName const & file, bool readonly_,
        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_;
+       cite_labels_valid_ = cloned_buffer_->d->cite_labels_valid_;
 }
 
 
@@ -422,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;
 }
 
 
@@ -597,7 +629,7 @@ string Buffer::logName(LogType * type) const
        FileName const bname(
                addName(path, onlyFileName(
                        changeExtension(filename,
-                                       formats.extension(bufferFormat()) + ".out"))));
+                                       formats.extension(params().bufferFormat()) + ".out"))));
 
        // Also consider the master buffer log file
        FileName masterfname = fname;
@@ -830,7 +862,7 @@ bool Buffer::readDocument(Lexer & lex)
        }
        usermacros.clear();
        updateMacros();
-       updateMacroInstances();
+       updateMacroInstances(InternalUpdate);
        return res;
 }
 
@@ -868,7 +900,12 @@ Buffer::ReadStatus Buffer::readFile(FileName const & fn)
 {
        FileName fname(fn);
        Lexer lex;
-       lex.setFile(fname);
+       if (!lex.setFile(fname)) {
+               Alert::error(_("File Not Found"),
+                       bformat(_("Unable to open file `%1$s'."), 
+                               from_utf8(fn.absFileName())));
+               return ReadFileNotFound;
+       }
 
        int file_format;
        ReadStatus const ret_plf = parseLyXFormat(lex, fn, file_format);
@@ -915,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();
 }
 
 
@@ -1086,6 +1142,11 @@ bool Buffer::save() const
 
 bool Buffer::writeFile(FileName const & fname) const
 {
+       // FIXME Do we need to do these here? I don't think writing
+       // the LyX file depends upon it. (RGH)
+       // updateBuffer();
+       // updateMacroInstances();
+
        if (d->read_only && fname == d->filename)
                return false;
 
@@ -1147,7 +1208,7 @@ docstring Buffer::emergencyWrite()
        }
 
        // 2) In HOME directory.
-       string s = addName(package().home_dir().absFileName(), absFileName());
+       string s = addName(Package::get_home_dir().absFileName(), absFileName());
        s += ".emergency";
        lyxerr << ' ' << s << endl;
        if (writeFile(FileName(s))) {
@@ -1270,6 +1331,14 @@ bool Buffer::makeLaTeXFile(FileName const & fname,
        errorList.clear();
        bool failed_export = false;
        otexstream os(ofs, d->texrow);
+
+       // make sure we are ready to export
+       // this needs to be done before we validate
+       // FIXME Do we need to do this all the time? I.e., in children
+       // of a master we are exporting?
+       updateBuffer();
+       updateMacroInstances(OutputUpdate);
+
        try {
                os.texrow().reset();
                writeLaTeXSource(os, original_path,
@@ -1343,15 +1412,6 @@ void Buffer::writeLaTeXSource(otexstream & os,
        }
        LYXERR(Debug::INFO, "lyx document header finished");
 
-       // Don't move this behind the parent_buffer=0 code below,
-       // because then the macros will not get the right "redefinition"
-       // flag as they don't see the parent macros which are output before.
-       updateMacros();
-
-       // fold macros if possible, still with parent buffer as the
-       // macros will be put in the prefix anyway.
-       updateMacroInstances();
-
        // There are a few differences between nice LaTeX and usual files:
        // usual is \batchmode and has a
        // special input@path to allow the including of figures
@@ -1477,24 +1537,6 @@ void Buffer::writeLaTeXSource(otexstream & os,
 }
 
 
-bool Buffer::isLatex() const
-{
-       return params().documentClass().outputType() == LATEX;
-}
-
-
-bool Buffer::isLiterate() const
-{
-       return params().documentClass().outputType() == LITERATE;
-}
-
-
-bool Buffer::isDocBook() const
-{
-       return params().documentClass().outputType() == DOCBOOK;
-}
-
-
 void Buffer::makeDocBookFile(FileName const & fname,
                              OutputParams const & runparams,
                              bool const body_only) const
@@ -1505,6 +1547,11 @@ void Buffer::makeDocBookFile(FileName const & fname,
        if (!openFileWrite(ofs, fname))
                return;
 
+       // make sure we are ready to export
+       // this needs to be done before we validate
+       updateBuffer();
+       updateMacroInstances(OutputUpdate);
+
        writeDocBookSource(ofs, fname.absFileName(), runparams, body_only);
 
        ofs.close();
@@ -1579,8 +1626,6 @@ void Buffer::writeDocBookSource(odocstream & os, string const & fname,
 
        params().documentClass().counters().reset();
 
-       updateMacros();
-
        sgml::openTag(os, top);
        os << '\n';
        docbookParagraphs(text(), *this, os, runparams);
@@ -1589,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...");
 
@@ -1598,7 +1642,12 @@ void Buffer::makeLyXHTMLFile(FileName const & fname,
        if (!openFileWrite(ofs, fname))
                return;
 
-       writeLyXHTMLSource(ofs, runparams, body_only);
+       // make sure we are ready to export
+       // this has to be done before we validate
+       updateBuffer(UpdateMaster, OutputUpdate);
+       updateMacroInstances(OutputUpdate);
+
+       writeLyXHTMLSource(ofs, runparams);
 
        ofs.close();
        if (ofs.fail())
@@ -1612,10 +1661,7 @@ void Buffer::writeLyXHTMLSource(odocstream & os,
 {
        LaTeXFeatures features(*this, params(), runparams);
        validate(features);
-       updateBuffer(UpdateMaster, OutputUpdate);
        d->bibinfo_.makeCitationLabels(*this);
-       updateMacros();
-       updateMacroInstances();
 
        if (!only_body) {
                os << "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n"
@@ -1701,8 +1747,6 @@ void Buffer::validate(LaTeXFeatures & features) const
 {
        params().validate(features);
 
-       updateMacros();
-
        for_each(paragraphs().begin(), paragraphs().end(),
                 bind(&Paragraph::validate, _1, ref(features)));
 
@@ -1764,12 +1808,14 @@ void Buffer::updateBibfilesCache(UpdateScope scope) const
        }
        d->bibfile_cache_valid_ = true;
        d->bibinfo_cache_valid_ = false;
+       d->cite_labels_valid_ = false;
 }
 
 
 void Buffer::invalidateBibinfoCache() const
 {
        d->bibinfo_cache_valid_ = false;
+       d->cite_labels_valid_ = false;
        // also invalidate the cache for the parent buffer
        Buffer const * const pbuf = d->parent();
        if (pbuf)
@@ -1781,6 +1827,7 @@ void Buffer::invalidateBibfileCache() const
 {
        d->bibfile_cache_valid_ = false;
        d->bibinfo_cache_valid_ = false;
+       d->cite_labels_valid_ = false;
        // also invalidate the cache for the parent buffer
        Buffer const * const pbuf = d->parent();
        if (pbuf)
@@ -1830,6 +1877,7 @@ void Buffer::checkIfBibInfoCacheIsValid() const
                time_t prevw = d->bibfile_status_[*ei];
                if (lastw != prevw) {
                        d->bibinfo_cache_valid_ = false;
+                       d->cite_labels_valid_ = false;
                        d->bibfile_status_[*ei] = lastw;
                }
        }
@@ -1880,6 +1928,12 @@ void Buffer::addBibTeXInfo(docstring const & key, BibTeXInfo const & bi) const
 }
 
 
+bool Buffer::citeLabelsValid() const
+{
+       return masterBuffer()->d->cite_labels_valid_;
+}
+
+
 bool Buffer::isDepClean(string const & name) const
 {
        DepClean::const_iterator const it = d->dep_clean.find(name);
@@ -1895,21 +1949,6 @@ void Buffer::markDepClean(string const & name)
 }
 
 
-bool Buffer::isExportableFormat(string const & format) const
-{
-               typedef vector<Format const *> Formats;
-               Formats formats;
-               formats = exportableFormats(true);
-               Formats::const_iterator fit = formats.begin();
-               Formats::const_iterator end = formats.end();
-               for (; fit != end ; ++fit) {
-                       if ((*fit)->name() == format)
-                               return true;
-               }
-               return false;
-}
-
-
 bool Buffer::getStatus(FuncRequest const & cmd, FuncStatus & flag)
 {
        if (isInternal()) {
@@ -1938,7 +1977,7 @@ bool Buffer::getStatus(FuncRequest const & cmd, FuncStatus & flag)
 
                case LFUN_BUFFER_EXPORT: {
                        docstring const arg = cmd.argument();
-                       enable = arg == "custom" || isExportable(to_utf8(arg));
+                       enable = arg == "custom" || params().isExportable(to_utf8(arg));
                        if (!enable)
                                flag.message(bformat(
                                        _("Don't know how to export to format: %1$s"), arg));
@@ -1946,11 +1985,11 @@ bool Buffer::getStatus(FuncRequest const & cmd, FuncStatus & flag)
                }
 
                case LFUN_BUFFER_CHKTEX:
-                       enable = isLatex() && !lyxrc.chktex_command.empty();
+                       enable = params().isLatex() && !lyxrc.chktex_command.empty();
                        break;
 
                case LFUN_BUILD_PROGRAM:
-                       enable = isExportable("program");
+                       enable = params().isExportable("program");
                        break;
 
                case LFUN_BRANCH_ACTIVATE: 
@@ -2061,7 +2100,7 @@ void Buffer::dispatch(FuncRequest const & func, DispatchResult & dr)
 
                // Execute the command in the background
                Systemcall call;
-               call.startscript(Systemcall::DontWait, command);
+               call.startscript(Systemcall::DontWait, command, filePath());
                break;
        }
 
@@ -2239,7 +2278,8 @@ void Buffer::dispatch(FuncRequest const & func, DispatchResult & dr)
                                command2 += quoteName(psname);
                                // First run dvips.
                                // If successful, then spool command
-                               res = one.startscript(Systemcall::Wait, command);
+                               res = one.startscript(Systemcall::Wait, command,
+                                                     filePath());
 
                                if (res == 0) {
                                        // If there's no GUI, we have to wait on this command. Otherwise,
@@ -2247,7 +2287,8 @@ void Buffer::dispatch(FuncRequest const & func, DispatchResult & dr)
                                        // file, before it can be printed!!
                                        Systemcall::Starttype stype = use_gui ?
                                                Systemcall::DontWait : Systemcall::Wait;
-                                       res = one.startscript(stype, command2);
+                                       res = one.startscript(stype, command2,
+                                                             filePath());
                                }
                        } else {
                                // case 2: print directly to a printer
@@ -2256,7 +2297,8 @@ void Buffer::dispatch(FuncRequest const & func, DispatchResult & dr)
                                // as above....
                                Systemcall::Starttype stype = use_gui ?
                                        Systemcall::DontWait : Systemcall::Wait;
-                               res = one.startscript(stype, command + quoteName(dviname));
+                               res = one.startscript(stype, command +
+                                               quoteName(dviname), filePath());
                        }
 
                } else {
@@ -2279,7 +2321,7 @@ void Buffer::dispatch(FuncRequest const & func, DispatchResult & dr)
                        // as above....
                        Systemcall::Starttype stype = use_gui ?
                                Systemcall::DontWait : Systemcall::Wait;
-                       res = one.startscript(stype, command);
+                       res = one.startscript(stype, command, filePath());
                }
 
                if (res == 0) 
@@ -2437,6 +2479,8 @@ bool Buffer::isExternallyModified(CheckMethod method) const
 void Buffer::saveCheckSum() const
 {
        FileName const & file = d->filename;
+
+       file.refresh();
        if (file.exists()) {
                d->timestamp_ = file.lastModified();
                d->checksum_ = file.checksum();
@@ -2541,7 +2585,7 @@ Buffer const * Buffer::parent() const
 ListOfBuffers Buffer::allRelatives() const
 {
        ListOfBuffers lb = masterBuffer()->getDescendents();
-       lb.push_front(const_cast<Buffer *>(this));
+       lb.push_front(const_cast<Buffer *>(masterBuffer()));
        return lb;
 }
 
@@ -2918,7 +2962,7 @@ void Buffer::getUsedBranches(std::list<docstring> & result, bool const from_mast
 }
 
 
-void Buffer::updateMacroInstances() const
+void Buffer::updateMacroInstances(UpdateType utype) const
 {
        LYXERR(Debug::MACROS, "updateMacroInstances for "
                << d->filename.onlyFileName());
@@ -2936,7 +2980,7 @@ void Buffer::updateMacroInstances() const
                MacroContext mc = MacroContext(this, it);
                for (DocIterator::idx_type i = 0; i < n; ++i) {
                        MathData & data = minset->cell(i);
-                       data.updateMacros(0, mc);
+                       data.updateMacros(0, mc, utype);
                }
        }
 }
@@ -3082,7 +3126,7 @@ void Buffer::getSourceCode(odocstream & os, string const format,
 {
        OutputParams runparams(&params().encoding());
        runparams.nice = true;
-       runparams.flavor = getOutputFlavor(format);
+       runparams.flavor = params().getOutputFlavor(format);
        runparams.linelen = lyxrc.plaintext_linelen;
        // No side effect of file copying and image conversion
        runparams.dryrun = true;
@@ -3092,7 +3136,7 @@ void Buffer::getSourceCode(odocstream & os, string const format,
                d->texrow.reset();
                d->texrow.newline();
                d->texrow.newline();
-               if (isDocBook())
+               if (params().isDocBook())
                        writeDocBookSource(os, absFileName(), runparams, false);
                else if (runparams.flavor == OutputParams::HTML)
                        writeLyXHTMLSource(os, runparams, false);
@@ -3120,7 +3164,7 @@ void Buffer::getSourceCode(odocstream & os, string const format,
                texrow.newline();
                texrow.newline();
                // output paragraphs
-               if (isDocBook())
+               if (params().isDocBook())
                        docbookParagraphs(text(), *this, os, runparams);
                else if (runparams.flavor == OutputParams::HTML) {
                        XHTMLStream xs(os);
@@ -3136,12 +3180,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];
 }
 
 
@@ -3365,74 +3404,6 @@ bool Buffer::autoSave() const
 }
 
 
-string Buffer::bufferFormat() const
-{
-       string format = params().documentClass().outputFormat();
-       if (format == "latex") {
-               if (params().useNonTeXFonts)
-                       return "xetex";
-               if (params().encoding().package() == Encoding::japanese)
-                       return "platex";
-       }
-       return format;
-}
-
-
-string Buffer::getDefaultOutputFormat() const
-{
-       if (!params().default_output_format.empty()
-           && params().default_output_format != "default")
-               return params().default_output_format;
-       if (isDocBook()
-           || params().useNonTeXFonts
-           || params().encoding().package() == Encoding::japanese) {
-               vector<Format const *> const formats = exportableFormats(true);
-               if (formats.empty())
-                       return string();
-               // return the first we find
-               return formats.front()->name();
-       }
-       return lyxrc.default_view_format;
-}
-
-
-OutputParams::FLAVOR Buffer::getOutputFlavor(string const format) const
-{
-       string const dformat = (format.empty() || format == "default") ?
-               getDefaultOutputFormat() : format;
-       DefaultFlavorCache::const_iterator it =
-               default_flavors_.find(dformat);
-
-       if (it != default_flavors_.end())
-               return it->second;
-
-       OutputParams::FLAVOR result = OutputParams::LATEX;
-       
-       if (dformat == "xhtml")
-               result = OutputParams::HTML;
-       else {
-               // Try to determine flavor of default output format
-               vector<string> backs = backends();
-               if (find(backs.begin(), backs.end(), dformat) == backs.end()) {
-                       // Get shortest path to format
-                       Graph::EdgePath path;
-                       for (vector<string>::const_iterator it = backs.begin();
-                           it != backs.end(); ++it) {
-                               Graph::EdgePath p = theConverters().getPath(*it, dformat);
-                               if (!p.empty() && (path.empty() || p.size() < path.size())) {
-                                       path = p;
-                               }
-                       }
-                       if (!path.empty())
-                               result = theConverters().getFlavor(path);
-               }
-       }
-       // cache this flavor
-       default_flavors_[dformat] = result;
-       return result;
-}
-
-
 namespace {
        // helper class, to guarantee this gets reset properly
        class MarkAsExporting   {
@@ -3455,6 +3426,11 @@ namespace {
 void Buffer::setExportStatus(bool e) const
 {
        d->doing_export = e;    
+       ListOfBuffers clist = getDescendents();
+       ListOfBuffers::const_iterator cit = clist.begin();
+       ListOfBuffers::const_iterator const cen = clist.end();
+       for (; cit != cen; ++cit)
+               (*cit)->d->doing_export = e;
 }
 
 
@@ -3473,7 +3449,7 @@ bool Buffer::doExport(string const & format, bool put_in_tempdir,
        runparams.flavor = OutputParams::LATEX;
        runparams.linelen = lyxrc.plaintext_linelen;
        runparams.includeall = includeall;
-       vector<string> backs = backends();
+       vector<string> backs = params().backends();
        Converters converters = theConverters();
        if (find(backs.begin(), backs.end(), format) == backs.end()) {
                // Get shortest path to format
@@ -3515,9 +3491,6 @@ bool Buffer::doExport(string const & format, bool put_in_tempdir,
        filename = changeExtension(filename,
                                   formats.extension(backend_format));
 
-       // fix macros
-       updateMacroInstances();
-
        // Plain text backend
        if (backend_format == "text") {
                runparams.flavor = OutputParams::TEXT;
@@ -3544,15 +3517,20 @@ bool Buffer::doExport(string const & format, bool put_in_tempdir,
        } else if (backend_format == "lyx")
                writeFile(FileName(filename));
        // Docbook backend
-       else if (isDocBook()) {
+       else if (params().isDocBook()) {
                runparams.nice = !put_in_tempdir;
                makeDocBookFile(FileName(filename), runparams);
        }
        // LaTeX backend
        else if (backend_format == format) {
                runparams.nice = true;
-               if (!makeLaTeXFile(FileName(filename), string(), runparams))
+               if (!makeLaTeXFile(FileName(filename), string(), runparams)) {
+                       if (d->cloned_buffer_) {
+                               d->cloned_buffer_->d->errorLists["Export"] =
+                                       d->errorLists["Export"];
+                       }
                        return false;
+               }
        } else if (!lyxrc.tex_allows_spaces
                   && contains(filePath(), ' ')) {
                Alert::error(_("File name error"),
@@ -3560,12 +3538,17 @@ bool Buffer::doExport(string const & format, bool put_in_tempdir,
                return false;
        } else {
                runparams.nice = false;
-               if (!makeLaTeXFile(FileName(filename), filePath(), runparams))
+               if (!makeLaTeXFile(FileName(filename), filePath(), runparams)) {
+                       if (d->cloned_buffer_) {
+                               d->cloned_buffer_->d->errorLists["Export"] =
+                                       d->errorLists["Export"];
+                       }
                        return false;
+               }
        }
 
        string const error_type = (format == "program")
-               ? "Build" : bufferFormat();
+               ? "Build" : params().bufferFormat();
        ErrorList & error_list = d->errorLists[error_type];
        string const ext = formats.extension(format);
        FileName const tmp_result_file(changeExtension(filename, ext));
@@ -3604,7 +3587,7 @@ bool Buffer::doExport(string const & format, bool put_in_tempdir,
                // FIXME: There is a possibility of concurrent access to texrow
                // here from the main GUI thread that should be securized.
                d->cloned_buffer_->d->texrow = d->texrow;
-               string const error_type = bufferFormat();
+               string const error_type = params().bufferFormat();
                d->cloned_buffer_->d->errorLists[error_type] = d->errorLists[error_type];
        }
 
@@ -3686,50 +3669,6 @@ bool Buffer::preview(string const & format, bool includeall) const
 }
 
 
-bool Buffer::isExportable(string const & format) const
-{
-       vector<string> backs = backends();
-       for (vector<string>::const_iterator it = backs.begin();
-            it != backs.end(); ++it)
-               if (theConverters().isReachable(*it, format))
-                       return true;
-       return false;
-}
-
-
-vector<Format const *> Buffer::exportableFormats(bool only_viewable) const
-{
-       vector<string> const backs = backends();
-       vector<Format const *> result =
-               theConverters().getReachable(backs[0], only_viewable, true);
-       for (vector<string>::const_iterator it = backs.begin() + 1;
-            it != backs.end(); ++it) {
-               vector<Format const *>  r =
-                       theConverters().getReachable(*it, only_viewable, false);
-               result.insert(result.end(), r.begin(), r.end());
-       }
-       return result;
-}
-
-
-vector<string> Buffer::backends() const
-{
-       vector<string> v;
-       v.push_back(bufferFormat());
-       // FIXME: Don't hardcode format names here, but use a flag
-       if (v.back() == "latex") {
-               v.push_back("pdflatex");
-               v.push_back("luatex");
-               v.push_back("xetex");
-       } else if (v.back() == "xetex")
-               v.push_back("luatex");
-       v.push_back("xhtml");
-       v.push_back("text");
-       v.push_back("lyx");
-       return v;
-}
-
-
 Buffer::ReadStatus Buffer::extractFromVC()
 {
        bool const found = LyXVC::file_not_found_hook(d->filename);
@@ -3876,24 +3815,56 @@ Buffer::ReadStatus Buffer::loadThisLyXFile(FileName const & fn)
 
 void Buffer::bufferErrors(TeXErrors const & terr, ErrorList & errorList) const
 {
-       TeXErrors::Errors::const_iterator cit = terr.begin();
+       TeXErrors::Errors::const_iterator it = terr.begin();
        TeXErrors::Errors::const_iterator end = terr.end();
+       ListOfBuffers clist = getDescendents();
+       ListOfBuffers::const_iterator cen = clist.end();
 
-       for (; cit != end; ++cit) {
+       for (; it != end; ++it) {
                int id_start = -1;
                int pos_start = -1;
-               int errorRow = cit->error_in_line;
-               bool found = d->texrow.getIdFromRow(errorRow, id_start,
-                                                      pos_start);
+               int errorRow = it->error_in_line;
+               Buffer const * buf = 0;
+               Impl const * p = d;
+               if (it->child_name.empty())
+                   p->texrow.getIdFromRow(errorRow, id_start, pos_start);
+               else {
+                       // The error occurred in a child
+                       ListOfBuffers::const_iterator cit = clist.begin();
+                       for (; cit != cen; ++cit) {
+                               string const child_name =
+                                       DocFileName(changeExtension(
+                                               (*cit)->absFileName(), "tex")).
+                                                       mangledFileName();
+                               if (it->child_name != child_name)
+                                       continue;
+                               (*cit)->d->texrow.getIdFromRow(errorRow,
+                                                       id_start, pos_start);
+                               if (id_start != -1) {
+                                       buf = d->cloned_buffer_
+                                               ? (*cit)->d->cloned_buffer_->d->owner_
+                                               : (*cit)->d->owner_;
+                                       p = (*cit)->d;
+                                       break;
+                               }
+                       }
+               }
                int id_end = -1;
                int pos_end = -1;
+               bool found;
                do {
                        ++errorRow;
-                       found = d->texrow.getIdFromRow(errorRow, id_end, pos_end);
+                       found = p->texrow.getIdFromRow(errorRow, id_end, pos_end);
                } while (found && id_start == id_end && pos_start == pos_end);
 
-               errorList.push_back(ErrorItem(cit->error_desc,
-                       cit->error_text, id_start, pos_start, pos_end));
+               if (id_start != id_end) {
+                       // Next registered position is outside the inset where
+                       // the error occurred, so signal end-of-paragraph
+                       pos_end = 0;
+               }
+
+               errorList.push_back(ErrorItem(it->error_desc,
+                       it->error_text, id_start, pos_start, pos_end, buf));
        }
 }
 
@@ -3957,6 +3928,7 @@ void Buffer::updateBuffer(UpdateScope scope, UpdateType utype) const
                return;
 
        d->bibinfo_cache_valid_ = true;
+       d->cite_labels_valid_ = true;
        cbuf.tocBackend().update();
        if (scope == UpdateMaster)
                cbuf.structureChanged();
@@ -4052,10 +4024,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());
        }