]> git.lyx.org Git - lyx.git/blobdiff - src/Buffer.cpp
Natbib authoryear uses (Ref1; Ref2) by default.
[lyx.git] / src / Buffer.cpp
index 3561c45bcc8d884c29d79e93a4bfd81764f6d072..43b5ecd792f76065950c61e4439f156426260392 100644 (file)
@@ -25,6 +25,7 @@
 #include "Converter.h"
 #include "Counters.h"
 #include "Cursor.h"
+#include "CutAndPaste.h"
 #include "DispatchResult.h"
 #include "DocIterator.h"
 #include "Encoding.h"
 #include "support/lyxalgo.h"
 #include "support/os.h"
 #include "support/Package.h"
-#include "support/Path.h"
+#include "support/PathChanger.h"
 #include "support/Systemcall.h"
+#include "support/TempFile.h"
 #include "support/textutils.h"
 #include "support/types.h"
 
 #include <map>
 #include <set>
 #include <sstream>
-#include <stack>
 #include <vector>
 
 using namespace std;
@@ -283,7 +284,8 @@ public:
 
        /// This is here to force the test to be done whenever parent_buffer
        /// is accessed.
-       Buffer const * parent() const {
+       Buffer const * parent() const
+       {
                // ignore_parent temporarily "orphans" a buffer
                // (e.g. if a child is compiled standalone)
                if (ignore_parent)
@@ -300,7 +302,8 @@ public:
        }
 
        ///
-       void setParent(Buffer const * pb) {
+       void setParent(Buffer const * pb)
+       {
                if (parent_buffer == pb)
                        // nothing to do
                        return;
@@ -325,10 +328,14 @@ public:
        /// \p from initial position
        /// \p to points to the end position
        void updateStatistics(DocIterator & from, DocIterator & to,
-                                                 bool skipNoOutput = true);
+                             bool skipNoOutput = true);
        /// statistics accessor functions
-       int wordCount() const { return word_count_; }
-       int charCount(bool with_blanks) const {
+       int wordCount() const
+       {
+               return word_count_;
+       }
+       int charCount(bool with_blanks) const
+       {
                return char_count_
                + (with_blanks ? blank_count_ : 0);
        }
@@ -445,13 +452,17 @@ Buffer::~Buffer()
                // if we're the master buffer, then we should get rid of the list
                // of clones
                if (!parent()) {
-                       // if this is not empty, we have leaked something. worse, one of the
-                       // children still has a reference to this list.
-                       LASSERT(d->clone_list_->empty(), /* */);
+                       // If this is not empty, we have leaked something. Worse, one of the
+                       // children still has a reference to this list. But we will try to
+                       // continue, rather than shut down.
+                       LATTEST(d->clone_list_->empty());
                        list<CloneList *>::iterator it =
                                find(cloned_buffers.begin(), cloned_buffers.end(), d->clone_list_);
-                       LASSERT(it != cloned_buffers.end(), /* */);
-                       cloned_buffers.erase(it);
+                       if (it == cloned_buffers.end()) {
+                               // We will leak in this case, but it is safe to continue.
+                               LATTEST(false);
+                       } else
+                               cloned_buffers.erase(it);
                        delete d->clone_list_;
                }
                // FIXME Do we really need to do this right before we delete d?
@@ -494,7 +505,7 @@ Buffer::~Buffer()
 Buffer * Buffer::cloneFromMaster() const
 {
        BufferMap bufmap;
-       cloned_buffers.push_back(new CloneList());
+       cloned_buffers.push_back(new CloneList);
        CloneList * clones = cloned_buffers.back();
 
        masterBuffer()->cloneWithChildren(bufmap, clones);
@@ -515,11 +526,21 @@ void Buffer::cloneWithChildren(BufferMap & bufmap, CloneList * clones) const
                return;
 
        Buffer * buffer_clone = new Buffer(fileName().absFileName(), false, this);
+
+       // The clone needs its own DocumentClass, since running updateBuffer() will
+       // modify it, and we would otherwise be sharing it with the original Buffer.
+       buffer_clone->params().makeDocumentClass();
+       ErrorList el;
+       cap::switchBetweenClasses(
+                       params().documentClassPtr(), buffer_clone->params().documentClassPtr(),
+                       static_cast<InsetText &>(buffer_clone->inset()), el);
+
        bufmap[this] = buffer_clone;
        clones->insert(buffer_clone);
        buffer_clone->d->clone_list_ = clones;
        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.
@@ -550,11 +571,21 @@ void Buffer::cloneWithChildren(BufferMap & bufmap, CloneList * clones) const
 
 
 Buffer * Buffer::cloneBufferOnly() const {
-       cloned_buffers.push_back(new CloneList());
+       cloned_buffers.push_back(new CloneList);
        CloneList * clones = cloned_buffers.back();
        Buffer * buffer_clone = new Buffer(fileName().absFileName(), false, this);
+
+       // The clone needs its own DocumentClass, since running updateBuffer() will
+       // modify it, and we would otherwise be sharing it with the original Buffer.
+       buffer_clone->params().makeDocumentClass();
+       ErrorList el;
+       cap::switchBetweenClasses(
+                       params().documentClassPtr(), buffer_clone->params().documentClassPtr(),
+                       static_cast<InsetText &>(buffer_clone->inset()), el);
+
        clones->insert(buffer_clone);
        buffer_clone->d->clone_list_ = clones;
+
        // we won't be cloning the children
        buffer_clone->d->children_positions.clear();
        return buffer_clone;
@@ -576,7 +607,7 @@ void Buffer::changed(bool update_metrics) const
 
 frontend::WorkAreaManager & Buffer::workAreaManager() const
 {
-       LASSERT(d->wa_, /**/);
+       LBUFERR(d->wa_);
        return *d->wa_;
 }
 
@@ -756,7 +787,10 @@ void Buffer::setReadonly(bool const flag)
 
 void Buffer::setFileName(FileName const & fname)
 {
+       bool const changed = fname != d->filename;
        d->filename = fname;
+       if (changed)
+               lyxvc().file_found_hook(fname);
        setReadonly(d->filename.isReadOnly());
        saveCheckSum();
        updateTitles();
@@ -949,6 +983,49 @@ bool Buffer::readDocument(Lexer & lex)
 }
 
 
+bool Buffer::importString(string const & format, docstring const & contents, ErrorList & errorList)
+{
+       Format const * fmt = formats.getFormat(format);
+       if (!fmt)
+               return false;
+       // It is important to use the correct extension here, since some
+       // converters create a wrong output file otherwise (e.g. html2latex)
+       TempFile const tempfile("Buffer_importStringXXXXXX." + fmt->extension());
+       FileName const name(tempfile.name());
+       ofdocstream os(name.toFilesystemEncoding().c_str());
+       bool const success = (os << contents);
+       os.close();
+
+       bool converted = false;
+       if (success) {
+               params().compressed = false;
+
+               // remove dummy empty par
+               paragraphs().clear();
+
+               converted = importFile(format, name, errorList);
+       }
+
+       if (name.exists())
+               name.removeFile();
+       return converted;
+}
+
+
+bool Buffer::importFile(string const & format, FileName const & name, ErrorList & errorList)
+{
+       if (!theConverters().isReachable(format, "lyx"))
+               return false;
+
+       TempFile const tempfile("Buffer_importFileXXXXXX.lyx");
+       FileName const lyx(tempfile.name());
+       if (theConverters().convert(0, name, lyx, name, format, "lyx", errorList))
+               return readFile(lyx) == ReadSuccess;
+
+       return false;
+}
+
+
 bool Buffer::readString(string const & s)
 {
        params().compressed = false;
@@ -959,22 +1036,23 @@ bool Buffer::readString(string const & s)
        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;
+       bool success = parseLyXFormat(lex, fn, file_format) == ReadSuccess;
 
-       if (file_format != LYX_FORMAT) {
+       if (success && file_format != LYX_FORMAT) {
                // We need to call lyx2lyx, so write the input to a file
                ofstream os(fn.toFilesystemEncoding().c_str());
                os << s;
                os.close();
                // lyxvc in readFile
-               return readFile(fn) == ReadSuccess;
+               if (readFile(fn) != ReadSuccess)
+                       success = false;
        }
-
-       if (readDocument(lex))
-               return false;
-       return true;
+       else if (success)
+               if (readDocument(lex))
+                       success = false;
+       if (fn.exists())
+               fn.removeFile();
+       return success;
 }
 
 
@@ -1094,7 +1172,7 @@ Buffer::ReadStatus Buffer::parseLyXFormat(Lexer & lex,
 Buffer::ReadStatus Buffer::convertLyXFormat(FileName const & fn,
        FileName & tmpfile, int from_format)
 {
-       tmpfile = FileName::tempName("Buffer_convertLyXFormat");
+       tmpfile = FileName::tempName("Buffer_convertLyXFormatXXXXXX.lyx");
        if(tmpfile.empty()) {
                Alert::error(_("Conversion failed"),
                        bformat(_("%1$s is from a different"
@@ -1224,11 +1302,6 @@ 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;
 
@@ -1592,8 +1665,12 @@ void Buffer::writeLaTeXSource(otexstream & os,
 
                runparams.use_japanese = features.isRequired("japanese");
 
-               if (!output_body)
+               if (!output_body) {
+                       // Restore the parenthood if needed
+                       if (!runparams.is_child)
+                               d->ignore_parent = false;
                        return;
+               }
 
                // make the body.
                os << "\\begin{document}\n";
@@ -1867,7 +1944,9 @@ void Buffer::writeLyXHTMLSource(odocstream & os,
                if (output_body_tag)
                        os << "<body>\n";
                XHTMLStream xs(os);
-               params().documentClass().counters().reset();
+               if (output != IncludedFile)
+                       // if we're an included file, the counters are in the master.
+                       params().documentClass().counters().reset();
                xhtmlParagraphs(text(), *this, xs, runparams);
                if (output_body_tag)
                        os << "</body>\n";
@@ -1906,7 +1985,7 @@ int Buffer::runChktex()
        if (res == -1) {
                Alert::error(_("chktex failure"),
                             _("Could not run chktex successfully."));
-       } else if (res > 0) {
+       } else {
                ErrorList & errlist = d->errorLists["ChkTeX"];
                errlist.clear();
                bufferErrors(terr, errlist);
@@ -2109,6 +2188,13 @@ void Buffer::addBibTeXInfo(docstring const & key, BibTeXInfo const & bi) const
 }
 
 
+void Buffer::makeCitationLabels() const
+{
+       Buffer const * const master = masterBuffer();
+       return d->bibinfo_.makeCitationLabels(*master);
+}
+
+
 bool Buffer::citeLabelsValid() const
 {
        return masterBuffer()->d->cite_labels_valid_;
@@ -2160,57 +2246,70 @@ bool Buffer::getStatus(FuncRequest const & cmd, FuncStatus & flag)
 
        switch (cmd.action()) {
 
-               case LFUN_BUFFER_TOGGLE_READ_ONLY:
-                       flag.setOnOff(isReadonly());
-                       break;
+       case LFUN_BUFFER_TOGGLE_READ_ONLY:
+               flag.setOnOff(isReadonly());
+               break;
 
                // FIXME: There is need for a command-line import.
                //case LFUN_BUFFER_IMPORT:
 
-               case LFUN_BUFFER_AUTO_SAVE:
-                       break;
+       case LFUN_BUFFER_AUTO_SAVE:
+               break;
 
-               case LFUN_BUFFER_EXPORT_CUSTOM:
-                       // FIXME: Nothing to check here?
-                       break;
+       case LFUN_BUFFER_EXPORT_CUSTOM:
+               // FIXME: Nothing to check here?
+               break;
 
-               case LFUN_BUFFER_EXPORT: {
-                       docstring const arg = cmd.argument();
-                       if (arg == "custom") {
-                               enable = true;
-                               break;
-                       }
-                       string format = to_utf8(arg);
-                       size_t pos = format.find(' ');
-                       if (pos != string::npos)
-                               format = format.substr(0, pos);
-                       enable = params().isExportable(format);
-                       if (!enable)
-                               flag.message(bformat(
-                                       _("Don't know how to export to format: %1$s"), arg));
+       case LFUN_BUFFER_EXPORT: {
+               docstring const arg = cmd.argument();
+               if (arg == "custom") {
+                       enable = true;
                        break;
                }
+               string format = to_utf8(arg);
+               size_t pos = format.find(' ');
+               if (pos != string::npos)
+                       format = format.substr(0, pos);
+               enable = params().isExportable(format);
+               if (!enable)
+                       flag.message(bformat(
+                                            _("Don't know how to export to format: %1$s"), arg));
+               break;
+       }
 
-               case LFUN_BUFFER_CHKTEX:
-                       enable = params().isLatex() && !lyxrc.chktex_command.empty();
-                       break;
+       case LFUN_BUFFER_CHKTEX:
+               enable = params().isLatex() && !lyxrc.chktex_command.empty();
+               break;
 
-               case LFUN_BUILD_PROGRAM:
-                       enable = params().isExportable("program");
-                       break;
+       case LFUN_BUILD_PROGRAM:
+               enable = params().isExportable("program");
+               break;
 
-               case LFUN_BRANCH_ADD:
-               case LFUN_BRANCHES_RENAME:
-               case LFUN_BUFFER_PRINT:
-                       // if no Buffer is present, then of course we won't be called!
-                       break;
+       case LFUN_BRANCH_ACTIVATE:
+       case LFUN_BRANCH_DEACTIVATE:
+       case LFUN_BRANCH_MASTER_ACTIVATE:
+       case LFUN_BRANCH_MASTER_DEACTIVATE: {
+               bool const master = (cmd.action() == LFUN_BRANCH_MASTER_ACTIVATE
+                                    || cmd.action() == LFUN_BRANCH_MASTER_DEACTIVATE);
+               BranchList const & branchList = master ? masterBuffer()->params().branchlist()
+                       : params().branchlist();
+               docstring const branchName = cmd.argument();
+               flag.setEnabled(!branchName.empty() && branchList.find(branchName));
+               break;
+       }
 
-               case LFUN_BUFFER_LANGUAGE:
-                       enable = !isReadonly();
-                       break;
+       case LFUN_BRANCH_ADD:
+       case LFUN_BRANCHES_RENAME:
+       case LFUN_BUFFER_PRINT:
+               // if no Buffer is present, then of course we won't be called!
+               break;
 
-               default:
-                       return false;
+       case LFUN_BUFFER_LANGUAGE:
+               enable = !isReadonly();
+               break;
+
+       default:
+               return false;
        }
        flag.setEnabled(enable);
        return true;
@@ -2241,8 +2340,11 @@ void Buffer::dispatch(FuncRequest const & func, DispatchResult & dr)
 
        switch (func.action()) {
        case LFUN_BUFFER_TOGGLE_READ_ONLY:
-               if (lyxvc().inUse())
-                       lyxvc().toggleReadOnly();
+               if (lyxvc().inUse()) {
+                       string log = lyxvc().toggleReadOnly();
+                       if (!log.empty())
+                               dr.setMessage(log);
+               }
                else
                        setReadonly(!isReadonly());
                break;
@@ -2315,6 +2417,42 @@ void Buffer::dispatch(FuncRequest const & func, DispatchResult & dr)
                resetAutosaveTimers();
                break;
 
+       case LFUN_BRANCH_ACTIVATE:
+       case LFUN_BRANCH_DEACTIVATE:
+       case LFUN_BRANCH_MASTER_ACTIVATE:
+       case LFUN_BRANCH_MASTER_DEACTIVATE: {
+               bool const master = (func.action() == LFUN_BRANCH_MASTER_ACTIVATE
+                                    || func.action() == LFUN_BRANCH_MASTER_DEACTIVATE);
+               Buffer * buf = master ? const_cast<Buffer *>(masterBuffer())
+                                     : this;
+
+               docstring const branch_name = func.argument();
+               // the case without a branch name is handled elsewhere
+               if (branch_name.empty()) {
+                       dispatched = false;
+                       break;
+               }
+               Branch * branch = buf->params().branchlist().find(branch_name);
+               if (!branch) {
+                       LYXERR0("Branch " << branch_name << " does not exist.");
+                       dr.setError(true);
+                       docstring const msg =
+                               bformat(_("Branch \"%1$s\" does not exist."), branch_name);
+                       dr.setMessage(msg);
+                       break;
+               }
+               bool const activate = (func.action() == LFUN_BRANCH_ACTIVATE
+                                      || func.action() == LFUN_BRANCH_MASTER_ACTIVATE);
+               if (branch->isSelected() != activate) {
+                       buf->undo().recordUndoFullDocument(CursorData());
+                       branch->setSelected(activate);
+                       dr.setError(false);
+                       dr.screenUpdate(Update::Force);
+                       dr.forceBufferUpdate();
+               }
+               break;
+       }
+
        case LFUN_BRANCH_ADD: {
                docstring branch_name = func.argument();
                if (branch_name.empty()) {
@@ -2515,8 +2653,8 @@ void Buffer::dispatch(FuncRequest const & func, DispatchResult & dr)
 
 void Buffer::changeLanguage(Language const * from, Language const * to)
 {
-       LASSERT(from, /**/);
-       LASSERT(to, /**/);
+       LASSERT(from, return);
+       LASSERT(to, return);
 
        for_each(par_iterator_begin(),
                 par_iterator_end(),
@@ -2627,7 +2765,7 @@ bool Buffer::isClean() const
 
 bool Buffer::isExternallyModified(CheckMethod method) const
 {
-       LASSERT(d->filename.exists(), /**/);
+       LASSERT(d->filename.exists(), return false);
        // if method == timestamp, check timestamp before checksum
        return (method == checksum_method
                || d->timestamp_ != d->filename.lastModified())
@@ -2723,11 +2861,12 @@ string Buffer::absFileName() const
 
 string Buffer::filePath() const
 {
-       int last = d->filename.onlyPath().absFileName().length() - 1;
+       string const abs = d->filename.onlyPath().absFileName();
+       if (abs.empty())
+               return abs;
+       int last = abs.length() - 1;
 
-       return d->filename.onlyPath().absFileName()[last] == '/'
-               ? d->filename.onlyPath().absFileName()
-               : d->filename.onlyPath().absFileName() + "/";
+       return abs[last] == '/' ? abs : abs + '/';
 }
 
 
@@ -3224,10 +3363,10 @@ void Buffer::listParentMacros(MacroSet & macros, LaTeXFeatures & features) const
 }
 
 
-Buffer::References & Buffer::references(docstring const & label)
+Buffer::References & Buffer::getReferenceCache(docstring const & label)
 {
        if (d->parent())
-               return const_cast<Buffer *>(masterBuffer())->references(label);
+               return const_cast<Buffer *>(masterBuffer())->getReferenceCache(label);
 
        RefCache::iterator it = d->ref_cache_.find(label);
        if (it != d->ref_cache_.end())
@@ -3243,7 +3382,14 @@ Buffer::References & Buffer::references(docstring const & label)
 
 Buffer::References const & Buffer::references(docstring const & label) const
 {
-       return const_cast<Buffer *>(this)->references(label);
+       return const_cast<Buffer *>(this)->getReferenceCache(label);
+}
+
+
+void Buffer::addReference(docstring const & label, Inset * inset, ParIterator it)
+{
+       References & refs = getReferenceCache(label);
+       refs.push_back(make_pair(inset, it));
 }
 
 
@@ -3266,12 +3412,9 @@ void Buffer::clearReferenceCache() const
 }
 
 
-void Buffer::changeRefsIfUnique(docstring const & from, docstring const & to,
-       InsetCode code)
+void Buffer::changeRefsIfUnique(docstring const & from, docstring const & to)
 {
        //FIXME: This does not work for child documents yet.
-       LASSERT(code == CITE_CODE, /**/);
-
        reloadBibInfoCache();
 
        // Check if the label 'from' appears more than once
@@ -3289,14 +3432,12 @@ void Buffer::changeRefsIfUnique(docstring const & from, docstring const & to,
 
        string const paramName = "key";
        for (InsetIterator it = inset_iterator_begin(inset()); it; ++it) {
-               if (it->lyxCode() == code) {
-                       InsetCommand * inset = it->asInsetCommand();
-                       if (!inset)
-                               continue;
-                       docstring const oldValue = inset->getParam(paramName);
-                       if (oldValue == from)
-                               inset->setParam(paramName, to);
-               }
+               if (it->lyxCode() != CITE_CODE) 
+                       continue;
+               InsetCommand * inset = it->asInsetCommand();
+               docstring const oldValue = inset->getParam(paramName);
+               if (oldValue == from)
+                       inset->setParam(paramName, to);
        }
 }
 
@@ -3616,45 +3757,20 @@ bool Buffer::autoSave() const
        buf->d->bak_clean = true;
 
        FileName const fname = getAutosaveFileName();
-       if (d->cloned_buffer_) {
-               // If this buffer is cloned, we assume that
-               // we are running in a separate thread already.
-               FileName const tmp_ret = FileName::tempName("lyxauto");
-               if (!tmp_ret.empty()) {
-                       writeFile(tmp_ret);
-                       // assume successful write of tmp_ret
-                       if (tmp_ret.moveTo(fname))
-                               return true;
-               }
-               // failed to write/rename tmp_ret so try writing direct
-               return writeFile(fname);
-       } else {
-               /// This function is deprecated as the frontend needs to take care
-               /// of cloning the buffer and autosaving it in another thread. It
-               /// is still here to allow (QT_VERSION < 0x040400).
-               AutoSaveBuffer autosave(*this, fname);
-               autosave.start();
-               return true;
-       }
-}
+       LASSERT(d->cloned_buffer_, return false);
 
-
-// helper class, to guarantee this gets reset properly
-class Buffer::MarkAsExporting {
-public:
-       MarkAsExporting(Buffer const * buf) : buf_(buf)
-       {
-               LASSERT(buf_, /* */);
-               buf_->setExportStatus(true);
-       }
-       ~MarkAsExporting()
-       {
-               buf_->setExportStatus(false);
+       // If this buffer is cloned, we assume that
+       // we are running in a separate thread already.
+       FileName const tmp_ret = FileName::tempName("lyxauto");
+       if (!tmp_ret.empty()) {
+               writeFile(tmp_ret);
+               // assume successful write of tmp_ret
+               if (tmp_ret.moveTo(fname))
+                       return true;
        }
-private:
-       Buffer const * const buf_;
-};
-
+       // failed to write/rename tmp_ret so try writing direct
+       return writeFile(fname);
+}
 
 
 void Buffer::setExportStatus(bool e) const
@@ -4019,6 +4135,7 @@ Buffer::ReadStatus Buffer::loadEmergency()
                                        "file."), from_utf8(d->filename.absFileName())));
                        }
                        markDirty();
+                       lyxvc().file_found_hook(d->filename);
                        str = _("Document was successfully recovered.");
                } else
                        str = _("Document was NOT successfully recovered.");
@@ -4082,6 +4199,7 @@ Buffer::ReadStatus Buffer::loadAutosave()
                                        from_utf8(d->filename.absFileName())));
                        }
                        markDirty();
+                       lyxvc().file_found_hook(d->filename);
                        return ReadSuccess;
                }
                return ReadAutosaveFailure;
@@ -4187,6 +4305,8 @@ void Buffer::setBuffersForInsets() const
 
 void Buffer::updateBuffer(UpdateScope scope, UpdateType utype) const
 {
+       LBUFERR(!text().paragraphs().empty());
+
        // Use the master text class also for child documents
        Buffer const * const master = masterBuffer();
        DocumentClass const & textclass = master->params().documentClass();
@@ -4227,8 +4347,6 @@ void Buffer::updateBuffer(UpdateScope scope, UpdateType utype) const
 
        Buffer & cbuf = const_cast<Buffer &>(*this);
 
-       LASSERT(!text().paragraphs().empty(), /**/);
-
        // do the real work
        ParIterator parit = cbuf.par_iterator_begin();
        updateBuffer(parit, utype);
@@ -4239,7 +4357,7 @@ void Buffer::updateBuffer(UpdateScope scope, UpdateType utype) const
 
        d->bibinfo_cache_valid_ = true;
        d->cite_labels_valid_ = true;
-       cbuf.tocBackend().update();
+       cbuf.tocBackend().update(utype == OutputUpdate);
        if (scope == UpdateMaster)
                cbuf.structureChanged();
 }
@@ -4300,7 +4418,7 @@ static depth_type getItemDepth(ParIterator const & it)
 static bool needEnumCounterReset(ParIterator const & it)
 {
        Paragraph const & par = *it;
-       LASSERT(par.layout().labeltype == LABEL_ENUMERATE, /**/);
+       LASSERT(par.layout().labeltype == LABEL_ENUMERATE, return false);
        depth_type const cur_depth = par.getDepth();
        ParIterator prev_it = it;
        while (prev_it.pit()) {
@@ -4347,17 +4465,6 @@ void Buffer::Impl::setLabel(ParIterator & it, UpdateType utype) const
        }
 
        switch(layout.labeltype) {
-       case LABEL_COUNTER:
-               if (layout.toclevel <= bp.secnumdepth
-                     && (layout.latextype != LATEX_ENVIRONMENT
-                         || it.text()->isFirstInSequence(it.pit()))) {
-                       if (counters.hasCounter(layout.counter))
-                               counters.step(layout.counter, utype);
-                       par.params().labelString(par.expandLabel(layout, bp));
-               } else
-                       par.params().labelString(docstring());
-               break;
-
        case LABEL_ITEMIZE: {
                // At some point of time we should do something more
                // clever here, like:
@@ -4437,19 +4544,34 @@ void Buffer::Impl::setLabel(ParIterator & it, UpdateType utype) const
                par.params().labelString(docstring());
                break;
 
+       case LABEL_ABOVE:
+       case LABEL_CENTERED:
+       case LABEL_STATIC: {
+               docstring const & lcounter = layout.counter;
+               if (!lcounter.empty()) {
+                       if (layout.toclevel <= bp.secnumdepth
+                                               && (layout.latextype != LATEX_ENVIRONMENT
+                                       || it.text()->isFirstInSequence(it.pit()))) {
+                               if (counters.hasCounter(lcounter))
+                                       counters.step(lcounter, utype);
+                               par.params().labelString(par.expandLabel(layout, bp));
+                       } else
+                               par.params().labelString(docstring());
+               } else
+                       par.params().labelString(par.expandLabel(layout, bp));
+               break;
+       }
+
        case LABEL_MANUAL:
-       case LABEL_TOP_ENVIRONMENT:
-       case LABEL_CENTERED_TOP_ENVIRONMENT:
-       case LABEL_STATIC:
        case LABEL_BIBLIO:
                par.params().labelString(par.expandLabel(layout, bp));
-               break;
        }
 }
 
 
 void Buffer::updateBuffer(ParIterator & parit, UpdateType utype) const
 {
+       // LASSERT: Is it safe to continue here, or should we just return?
        LASSERT(parit.pit() == 0, /**/);
 
        // Set the position of the text in the buffer to be able