]> git.lyx.org Git - lyx.git/blobdiff - src/Buffer.cpp
Kornel's gcc compile fix.
[lyx.git] / src / Buffer.cpp
index d8296e9795a5721e06dec63ab1f0656d794adcb7..94f46af094bb7b2b7cd3878eb17b03541a20f7cc 100644 (file)
@@ -42,6 +42,7 @@
 #include "Lexer.h"
 #include "LyXAction.h"
 #include "LyX.h"
+#include "LyXFunc.h"
 #include "LyXRC.h"
 #include "LyXVC.h"
 #include "output_docbook.h"
@@ -49,7 +50,6 @@
 #include "output_latex.h"
 #include "output_xhtml.h"
 #include "output_plaintext.h"
-#include "paragraph_funcs.h"
 #include "Paragraph.h"
 #include "ParagraphParameters.h"
 #include "ParIterator.h"
@@ -69,6 +69,7 @@
 
 #include "insets/InsetBibitem.h"
 #include "insets/InsetBibtex.h"
+#include "insets/InsetBranch.h"
 #include "insets/InsetInclude.h"
 #include "insets/InsetText.h"
 
@@ -126,7 +127,7 @@ namespace {
 
 // Do not remove the comment below, so we get merge conflict in
 // independent branches. Instead add your own.
-int const LYX_FORMAT = 361;  // jspitzm: bibliography custom width
+int const LYX_FORMAT = 370; // uwestoehr: option to suppress default date
 
 typedef map<string, bool> DepClean;
 typedef map<docstring, pair<InsetLabel const *, Buffer::References> > RefCache;
@@ -312,7 +313,7 @@ Buffer::~Buffer()
        // GuiView already destroyed
        gui_ = 0;
 
-       if (d->unnamed && d->filename.extension() == "internal") {
+       if (isInternal()) {
                // No need to do additional cleanups for internal buffer.
                delete d;
                return;
@@ -328,6 +329,12 @@ Buffer::~Buffer()
                        theBufferList().releaseChild(this, child);
        }
 
+       if (!isClean()) {
+               docstring msg = _("LyX attempted to close a document that had unsaved changes!\n");
+               msg += emergencyWrite();
+               frontend::Alert::warning(_("Attempting to close changed document!"), msg);
+       }
+               
        // clear references to children in macro tables
        d->children_positions.clear();
        d->position_to_children.clear();
@@ -439,12 +446,29 @@ Undo & Buffer::undo()
 
 string Buffer::latexName(bool const no_path) const
 {
-       FileName latex_name = makeLatexName(d->filename);
+       FileName latex_name =
+               makeLatexName(exportFileName());
        return no_path ? latex_name.onlyFileName()
                : latex_name.absFilename();
 }
 
 
+FileName Buffer::exportFileName() const
+{
+       docstring const branch_suffix =
+               params().branchlist().getFilenameSuffix();
+       if (branch_suffix.empty())
+               return fileName();
+
+       string const name = fileName().onlyFileNameWithoutExt()
+               + to_utf8(branch_suffix);
+       FileName res(fileName().onlyPath().absFilename() + "/" + name);
+       res.changeExtension(fileName().extension());
+
+       return res;
+}
+
+
 string Buffer::logName(LogType * type) const
 {
        string const filename = latexName(false);
@@ -467,14 +491,31 @@ string Buffer::logName(LogType * type) const
                        changeExtension(filename,
                                        formats.extension(bufferFormat()) + ".out"))));
 
-       // If no Latex log or Build log is newer, show Build log
+       // Also consider the master buffer log file
+       FileName masterfname = fname;
+       LogType mtype;
+       if (masterBuffer() != this) {
+               string const mlogfile = masterBuffer()->logName(&mtype);
+               masterfname = FileName(mlogfile);
+       }
 
+       // If no Latex log or Build log is newer, show Build log
        if (bname.exists() &&
-           (!fname.exists() || fname.lastModified() < bname.lastModified())) {
+           ((!fname.exists() && !masterfname.exists())
+            || (fname.lastModified() < bname.lastModified()
+                && masterfname.lastModified() < bname.lastModified()))) {
                LYXERR(Debug::FILES, "Log name calculated as: " << bname);
                if (type)
                        *type = buildlog;
                return bname.absFilename();
+       // If we have a newer master file log or only a master log, show this
+       } else if (fname != masterfname
+                  && (!fname.exists() && (masterfname.exists()
+                  || fname.lastModified() < masterfname.lastModified()))) {
+               LYXERR(Debug::FILES, "Log name calculated as: " << masterfname);
+               if (type)
+                       *type = mtype;
+               return masterfname.absFilename();
        }
        LYXERR(Debug::FILES, "Log name calculated as: " << fname);
        if (type)
@@ -653,9 +694,12 @@ bool Buffer::readDocument(Lexer & lex)
                        }
                }
        }
+       
+       // assure we have a default index
+       params().indiceslist().addDefault(B_("Index"));
 
        // read main text
-       bool const res = text().read(*this, lex, errorList, d->inset);
+       bool const res = text().read(lex, errorList, d->inset);
 
        updateMacros();
        updateMacroInstances();
@@ -663,57 +707,6 @@ bool Buffer::readDocument(Lexer & lex)
 }
 
 
-// needed to insert the selection
-void Buffer::insertStringAsLines(ParagraphList & pars,
-       pit_type & pit, pos_type & pos,
-       Font const & fn, docstring const & str, bool autobreakrows)
-{
-       Font font = fn;
-
-       // insert the string, don't insert doublespace
-       bool space_inserted = true;
-       for (docstring::const_iterator cit = str.begin();
-           cit != str.end(); ++cit) {
-               Paragraph & par = pars[pit];
-               if (*cit == '\n') {
-                       if (autobreakrows && (!par.empty() || par.allowEmpty())) {
-                               breakParagraph(params(), pars, pit, pos,
-                                              par.layout().isEnvironment());
-                               ++pit;
-                               pos = 0;
-                               space_inserted = true;
-                       } else {
-                               continue;
-                       }
-                       // do not insert consecutive spaces if !free_spacing
-               } else if ((*cit == ' ' || *cit == '\t') &&
-                          space_inserted && !par.isFreeSpacing()) {
-                       continue;
-               } else if (*cit == '\t') {
-                       if (!par.isFreeSpacing()) {
-                               // tabs are like spaces here
-                               par.insertChar(pos, ' ', font, params().trackChanges);
-                               ++pos;
-                               space_inserted = true;
-                       } else {
-                               par.insertChar(pos, *cit, font, params().trackChanges);
-                               ++pos;
-                               space_inserted = true;
-                       }
-               } else if (!isPrintable(*cit)) {
-                       // Ignore unprintables
-                       continue;
-               } else {
-                       // just insert the character
-                       par.insertChar(pos, *cit, font, params().trackChanges);
-                       ++pos;
-                       space_inserted = (*cit == ' ');
-               }
-
-       }
-}
-
-
 bool Buffer::readString(string const & s)
 {
        params().compressed = false;
@@ -959,6 +952,63 @@ bool Buffer::writeFile(FileName const & fname) const
 }
 
 
+docstring Buffer::emergencyWrite()
+{
+       // No need to save if the buffer has not changed.
+       if (isClean())
+               return docstring();
+
+       string const doc = isUnnamed() ? onlyFilename(absFileName()) : absFileName();
+
+       docstring user_message = bformat(
+               _("LyX: Attempting to save document %1$s\n"), from_utf8(doc));
+
+       // We try to save three places:
+       // 1) Same place as document. Unless it is an unnamed doc.
+       if (!isUnnamed()) {
+               string s = absFileName();
+               s += ".emergency";
+               LYXERR0("  " << s);
+               if (writeFile(FileName(s))) {
+                       markClean();
+                       user_message += bformat(_("  Saved to %1$s. Phew.\n"), from_utf8(s));
+                       return user_message;
+               } else {
+                       user_message += _("  Save failed! Trying again...\n");
+               }
+       }
+
+       // 2) In HOME directory.
+       string s = addName(package().home_dir().absFilename(), absFileName());
+       s += ".emergency";
+       lyxerr << ' ' << s << endl;
+       if (writeFile(FileName(s))) {
+               markClean();
+               user_message += bformat(_("  Saved to %1$s. Phew.\n"), from_utf8(s));
+               return user_message;
+       }
+
+       user_message += _("  Save failed! Trying yet again...\n");
+
+       // 3) In "/tmp" directory.
+       // MakeAbsPath to prepend the current
+       // drive letter on OS/2
+       s = addName(package().temp_dir().absFilename(), absFileName());
+       s += ".emergency";
+       lyxerr << ' ' << s << endl;
+       if (writeFile(FileName(s))) {
+               markClean();
+               user_message += bformat(_("  Saved to %1$s. Phew.\n"), from_utf8(s));
+               return user_message;
+       }
+
+       user_message += _("  Save failed! Bummer. Document is lost.");
+       // Don't try again.
+       markClean();
+       return user_message;
+}
+
+
 bool Buffer::write(ostream & ofs) const
 {
 #ifdef HAVE_LOCALE
@@ -979,7 +1029,7 @@ bool Buffer::write(ostream & ofs) const
        AuthorList::Authors::const_iterator a_it = params().authors().begin();
        AuthorList::Authors::const_iterator a_end = params().authors().end();
        for (; a_it != a_end; ++a_it)
-               a_it->second.setUsed(false);
+               a_it->setUsed(false);
 
        ParIterator const end = const_cast<Buffer *>(this)->par_iterator_end();
        ParIterator it = const_cast<Buffer *>(this)->par_iterator_begin();
@@ -993,7 +1043,7 @@ bool Buffer::write(ostream & ofs) const
 
        // write the text
        ofs << "\n\\begin_body\n";
-       text().write(*this, ofs);
+       text().write(ofs);
        ofs << "\n\\end_body\n";
 
        // Write marker that shows file is complete
@@ -1333,7 +1383,7 @@ void Buffer::writeDocBookSource(odocstream & os, string const & fname,
 
        sgml::openTag(os, top);
        os << '\n';
-       docbookParagraphs(paragraphs(), *this, os, runparams);
+       docbookParagraphs(text(), *this, os, runparams);
        sgml::closeTag(os, top_element);
 }
 
@@ -1391,7 +1441,7 @@ void Buffer::writeLyXHTMLSource(odocstream & os,
        }
 
        params().documentClass().counters().reset();
-       xhtmlParagraphs(paragraphs(), *this, os, runparams);
+       xhtmlParagraphs(text(), *this, os, runparams);
        if (!only_body)
                os << "</body>\n</html>\n";
 }
@@ -1584,34 +1634,90 @@ void Buffer::markDepClean(string const & name)
 
 bool Buffer::getStatus(FuncRequest const & cmd, FuncStatus & flag)
 {
+       if (isInternal()) {
+               // FIXME? if there is an Buffer LFUN that can be dispatched even
+               // if internal, put a switch '(cmd.action)' here.
+               return false;
+       }
+
+       bool enable = true;
+
        switch (cmd.action) {
+
+               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_EXPORT_CUSTOM:
+                       // FIXME: Nothing to check here?
+                       break;
+
                case LFUN_BUFFER_EXPORT: {
                        docstring const arg = cmd.argument();
-                       bool enable = arg == "custom" || isExportable(to_utf8(arg));
+                       enable = arg == "custom" || isExportable(to_utf8(arg));
                        if (!enable)
                                flag.message(bformat(
                                        _("Don't know how to export to format: %1$s"), arg));
-                       flag.setEnabled(enable);
                        break;
                }
 
+               case LFUN_MASTER_BUFFER_UPDATE:
+               case LFUN_MASTER_BUFFER_VIEW: 
+                       enable = parent() != 0;
+                       break;
+               case LFUN_BUFFER_UPDATE:
+               case LFUN_BUFFER_VIEW: {
+                       string format = to_utf8(cmd.argument());
+                       if (cmd.argument().empty())
+                               format = getDefaultOutputFormat();
+                       typedef vector<Format const *> Formats;
+                       Formats formats;
+                       formats = exportableFormats(true);
+                       Formats::const_iterator fit = formats.begin();
+                       Formats::const_iterator end = formats.end();
+                       enable = false;
+                       for (; fit != end ; ++fit) {
+                               if ((*fit)->name() == format)
+                                       enable = true;
+                       }
+                       break;
+               }
+               case LFUN_BUFFER_CHKTEX:
+                       enable = isLatex() && !lyxrc.chktex_command.empty();
+                       break;
+
+               case LFUN_BUILD_PROGRAM:
+                       enable = isExportable("program");
+                       break;
+
                case LFUN_BRANCH_ACTIVATE: 
                case LFUN_BRANCH_DEACTIVATE: {
-               BranchList const & branchList = params().branchlist();
-               docstring const branchName = cmd.argument();
-               flag.setEnabled(!branchName.empty()
-                               && branchList.find(branchName));
+                       BranchList const & branchList = params().branchlist();
+                       docstring const branchName = cmd.argument();
+                       enable = !branchName.empty() && branchList.find(branchName);
                        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!
-                       flag.setEnabled(true);
+                       break;
+
+               case LFUN_BUFFER_LANGUAGE:
+                       enable = !isReadonly();
                        break;
 
                default:
                        return false;
        }
+       flag.setEnabled(enable);
        return true;
 }
 
@@ -1627,12 +1733,32 @@ void Buffer::dispatch(string const & command, DispatchResult & result)
 // whether we have a GUI or not. The boolean use_gui holds this information.
 void Buffer::dispatch(FuncRequest const & func, DispatchResult & dr)
 {
+       if (isInternal()) {
+               // FIXME? if there is an Buffer LFUN that can be dispatched even
+               // if internal, put a switch '(cmd.action)' here.
+               dr.dispatched(false);
+               return;
+       }
+       string const argument = to_utf8(func.argument());
        // We'll set this back to false if need be.
        bool dispatched = true;
+       undo().beginUndoGroup();
 
        switch (func.action) {
+       case LFUN_BUFFER_TOGGLE_READ_ONLY:
+               if (lyxvc().inUse())
+                       lyxvc().toggleReadOnly();
+               else
+                       setReadonly(!isReadonly());
+               break;
+
        case LFUN_BUFFER_EXPORT: {
-               bool success = doExport(to_utf8(func.argument()), false);
+               if (argument == "custom") {
+                       lyx::dispatch(FuncRequest(LFUN_DIALOG_SHOW, "sendto"));
+                       break;
+               }
+               doExport(argument, false);
+               bool success = doExport(argument, false);
                dr.setError(success);
                if (!success)
                        dr.setMessage(bformat(_("Error exporting to format: %1$s."), 
@@ -1640,6 +1766,118 @@ void Buffer::dispatch(FuncRequest const & func, DispatchResult & dr)
                break;
        }
 
+       case LFUN_BUFFER_UPDATE: {
+               string format = argument;
+               if (argument.empty())
+                       format = getDefaultOutputFormat();
+               doExport(format, true);
+               break;
+       }
+
+       case LFUN_BUFFER_VIEW: {
+               string format = argument;
+               if (argument.empty())
+                       format = getDefaultOutputFormat();
+               preview(format);
+               break;
+       }
+
+       case LFUN_MASTER_BUFFER_UPDATE: {
+               string format = argument;
+               if (argument.empty())
+                       format = masterBuffer()->getDefaultOutputFormat();
+               masterBuffer()->doExport(format, true);
+               break;
+       }
+
+       case LFUN_MASTER_BUFFER_VIEW: {
+               string format = argument;
+               if (argument.empty())
+                       format = masterBuffer()->getDefaultOutputFormat();
+               masterBuffer()->preview(format);
+               break;
+       }
+
+       case LFUN_BUILD_PROGRAM:
+               doExport("program", true);
+               break;
+
+       case LFUN_BUFFER_CHKTEX:
+               runChktex();
+               break;
+
+       case LFUN_BUFFER_EXPORT_CUSTOM: {
+               string format_name;
+               string command = split(argument, format_name, ' ');
+               Format const * format = formats.getFormat(format_name);
+               if (!format) {
+                       lyxerr << "Format \"" << format_name
+                               << "\" not recognized!"
+                               << endl;
+                       break;
+               }
+
+               // The name of the file created by the conversion process
+               string filename;
+
+               // Output to filename
+               if (format->name() == "lyx") {
+                       string const latexname = latexName(false);
+                       filename = changeExtension(latexname,
+                               format->extension());
+                       filename = addName(temppath(), filename);
+
+                       if (!writeFile(FileName(filename)))
+                               break;
+
+               } else {
+                       doExport(format_name, true, filename);
+               }
+
+               // Substitute $$FName for filename
+               if (!contains(command, "$$FName"))
+                       command = "( " + command + " ) < $$FName";
+               command = subst(command, "$$FName", filename);
+
+               // Execute the command in the background
+               Systemcall call;
+               call.startscript(Systemcall::DontWait, command);
+               break;
+       }
+
+       // FIXME: There is need for a command-line import.
+       /*
+       case LFUN_BUFFER_IMPORT:
+               doImport(argument);
+               break;
+       */
+
+       case LFUN_BUFFER_AUTO_SAVE:
+               autoSave();
+               break;
+
+       case LFUN_BRANCH_ADD: {
+               BranchList & branchList = params().branchlist();
+               docstring const branchName = func.argument();
+               if (branchName.empty()) {
+                       dispatched = false;
+                       break;
+               }
+               Branch * branch = branchList.find(branchName);
+               if (branch) {
+                       LYXERR0("Branch " << branchName << " does already exist.");
+                       dr.setError(true);
+                       docstring const msg = 
+                               bformat(_("Branch \"%1$s\" does already exist."), branchName);
+                       dr.setMessage(msg);
+               } else {
+                       branchList.add(branchName);
+                       dr.setError(false);
+                       dr.update(Update::Force);
+               }
+               break;
+       }
+
        case LFUN_BRANCH_ACTIVATE:
        case LFUN_BRANCH_DEACTIVATE: {
                BranchList & branchList = params().branchlist();
@@ -1664,6 +1902,41 @@ void Buffer::dispatch(FuncRequest const & func, DispatchResult & dr)
                break;
        }
 
+       case LFUN_BRANCHES_RENAME: {
+               if (func.argument().empty())
+                       break;
+
+               docstring const oldname = from_utf8(func.getArg(0));
+               docstring const newname = from_utf8(func.getArg(1));
+               InsetIterator it  = inset_iterator_begin(inset());
+               InsetIterator const end = inset_iterator_end(inset());
+               bool success = false;
+               for (; it != end; ++it) {
+                       if (it->lyxCode() == BRANCH_CODE) {
+                               InsetBranch & ins = static_cast<InsetBranch &>(*it);
+                               if (ins.branch() == oldname) {
+                                       undo().recordUndo(it);
+                                       ins.rename(newname);
+                                       success = true;
+                                       continue;
+                               }
+                       }
+                       if (it->lyxCode() == INCLUDE_CODE) {
+                               // get buffer of external file
+                               InsetInclude const & ins =
+                                       static_cast<InsetInclude const &>(*it);
+                               Buffer * child = ins.getChildBuffer();
+                               if (!child)
+                                       continue;
+                               child->dispatch(func, dr);
+                       }
+               }
+
+               if (success)
+                       dr.update(Update::Force);
+               break;
+       }
+
        case LFUN_BUFFER_PRINT: {
                // we'll assume there's a problem until we succeed
                dr.setError(true); 
@@ -1778,11 +2051,22 @@ void Buffer::dispatch(FuncRequest const & func, DispatchResult & dr)
                break;
        }
 
+       case LFUN_BUFFER_LANGUAGE: {
+               Language const * oldL = params().language;
+               Language const * newL = languages.getLanguage(argument);
+               if (!newL || oldL == newL)
+                       break;
+               if (oldL->rightToLeft() == newL->rightToLeft() && !isMultiLingual())
+                       changeLanguage(oldL, newL);
+               break;
+       }
+
        default:
                dispatched = false;
                break;
        }
        dr.dispatched(dispatched);
+       undo().endUndoGroup();
 }
 
 
@@ -1932,7 +2216,17 @@ bool Buffer::isUnnamed() const
 }
 
 
-// FIXME: this function should be moved to buffer_pimpl.C
+/// \note
+/// Don't check unnamed, here: isInternal() is used in
+/// newBuffer(), where the unnamed flag has not been set by anyone
+/// yet. Also, for an internal buffer, there should be no need for
+/// retrieving fileName() nor for checking if it is unnamed or not.
+bool Buffer::isInternal() const
+{
+       return fileName().extension() == "internal";
+}
+
+
 void Buffer::markDirty()
 {
        if (d->lyx_clean) {
@@ -2311,6 +2605,35 @@ void Buffer::updateMacros() const
 }
 
 
+void Buffer::getUsedBranches(std::list<docstring> & result, bool const from_master) const
+{
+       InsetIterator it  = inset_iterator_begin(inset());
+       InsetIterator const end = inset_iterator_end(inset());
+       for (; it != end; ++it) {
+               if (it->lyxCode() == BRANCH_CODE) {
+                       InsetBranch & br = static_cast<InsetBranch &>(*it);
+                       docstring const name = br.branch();
+                       if (!from_master && !params().branchlist().find(name))
+                               result.push_back(name);
+                       else if (from_master && !masterBuffer()->params().branchlist().find(name))
+                               result.push_back(name);
+                       continue;
+               }
+               if (it->lyxCode() == INCLUDE_CODE) {
+                       // get buffer of external file
+                       InsetInclude const & ins =
+                               static_cast<InsetInclude const &>(*it);
+                       Buffer * child = ins.getChildBuffer();
+                       if (!child)
+                               continue;
+                       child->getUsedBranches(result, true);
+               }
+       }
+       // remove duplicates
+       result.unique();
+}
+
+
 void Buffer::updateMacroInstances() const
 {
        LYXERR(Debug::MACROS, "updateMacroInstances for "
@@ -2509,7 +2832,7 @@ void Buffer::getSourceCode(odocstream & os, pit_type par_begin,
                texrow.newline();
                // output paragraphs
                if (isDocBook())
-                       docbookParagraphs(paragraphs(), *this, os, runparams);
+                       docbookParagraphs(text(), *this, os, runparams);
                else 
                        // latex or literate
                        latexParagraphs(*this, text(), os, texrow, runparams);
@@ -2543,10 +2866,10 @@ void Buffer::structureChanged() const
 }
 
 
-void Buffer::errors(string const & err) const
+void Buffer::errors(string const & err, bool from_master) const
 {
        if (gui_)
-               gui_->errors(err);
+               gui_->errors(err, from_master);
 }
 
 
@@ -2836,8 +3159,14 @@ bool Buffer::doExport(string const & format, bool put_in_tempdir,
                tmp_result_file, FileName(absFileName()), backend_format, format,
                error_list);
        // Emit the signal to show the error list.
-       if (format != backend_format)
+       if (format != backend_format) {
                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)
+                       (*cit)->errors(error_type, true);
+       }
        if (!success)
                return false;
 
@@ -2846,7 +3175,7 @@ bool Buffer::doExport(string const & format, bool put_in_tempdir,
                return true;
        }
 
-       result_file = changeExtension(absFileName(), ext);
+       result_file = changeExtension(exportFileName().absFilename(), ext);
        // We need to copy referenced files (e. g. included graphics
        // if format == "dvi") to the result dir.
        vector<ExportedFile> const files =
@@ -2963,11 +3292,32 @@ bool Buffer::readFileHelper(FileName const & s)
                                      _("&Recover"),  _("&Load Original"),
                                      _("&Cancel")))
                {
-               case 0:
+               case 0: {
                        // the file is not saved if we load the emergency file.
                        markDirty();
-                       return readFile(e);
+                       docstring str;
+                       bool res;
+
+                       if ((res = readFile(e)) == success)
+                               str = _("Document was successfully recovered.");
+                       else
+                               str = _("Document was NOT successfully recovered.");
+                       str += "\n\n" + _("Remove emergency file now?");
+
+                       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;
@@ -3083,7 +3433,7 @@ void Buffer::updateLabels(UpdateScope scope) const
                        // Do this here in case the master has no gui associated with it. Then, 
                        // the TocModel is not updated and TocModel::toc_ is invalid (bug 5699).
                        if (!master->gui_)
-                               structureChanged();     
+                               structureChanged();
 
                        // was buf referenced from the master (i.e. not in bufToUpdate anymore)?
                        if (bufToUpdate.find(this) == bufToUpdate.end())
@@ -3211,7 +3561,7 @@ static void setLabel(Buffer const & buf, ParIterator & it)
        if (layout.margintype == MARGIN_MANUAL
            || layout.latextype == LATEX_BIB_ENVIRONMENT) {
                if (par.params().labelWidthString().empty())
-                       par.params().labelWidthString(par.translateIfPossible(layout.labelstring(), bp));
+                       par.params().labelWidthString(par.expandLabel(layout, bp));
        } else {
                par.params().labelWidthString(docstring());
        }
@@ -3220,7 +3570,7 @@ static void setLabel(Buffer const & buf, ParIterator & it)
        case LABEL_COUNTER:
                if (layout.toclevel <= bp.secnumdepth
                    && (layout.latextype != LATEX_ENVIRONMENT
-                       || isFirstInSequence(it.pit(), it.plist()))) {
+                       || it.text()->isFirstInSequence(it.pit()))) {
                        counters.step(layout.counter);
                        par.params().labelString(
                                par.expandLabel(layout, bp));
@@ -3277,7 +3627,8 @@ static void setLabel(Buffer const & buf, ParIterator & it)
                        counters.reset(enumcounter);
                counters.step(enumcounter);
 
-               par.params().labelString(counters.theCounter(enumcounter));
+               string const & lang = par.getParLanguage(bp)->code();
+               par.params().labelString(counters.theCounter(enumcounter, lang));
 
                break;
        }
@@ -3290,10 +3641,11 @@ static void setLabel(Buffer const & buf, ParIterator & it)
                else {
                        docstring name = buf.B_(textclass.floats().getType(type).name());
                        if (counters.hasCounter(from_utf8(type))) {
+                               string const & lang = par.getParLanguage(bp)->code();
                                counters.step(from_utf8(type));
                                full_label = bformat(from_ascii("%1$s %2$s:"), 
                                                     name, 
-                                                    counters.theCounter(from_utf8(type)));
+                                                    counters.theCounter(from_utf8(type), lang));
                        } else
                                full_label = bformat(from_ascii("%1$s #:"), name);      
                }
@@ -3310,8 +3662,7 @@ static void setLabel(Buffer const & buf, ParIterator & it)
        case LABEL_CENTERED_TOP_ENVIRONMENT:
        case LABEL_STATIC:      
        case LABEL_BIBLIO:
-               par.params().labelString(
-                       par.translateIfPossible(layout.labelstring(), bp));
+               par.params().labelString(par.expandLabel(layout, bp));
                break;
        }
 }
@@ -3348,77 +3699,27 @@ void Buffer::updateLabels(ParIterator & parit) const
 }
 
 
-bool Buffer::nextWord(DocIterator & from, DocIterator & to,
-       docstring & word) const
-{
-       bool inword = false;
-       bool ignoreword = false;
-       string lang_code;
-       // Go backward a bit if needed in order to return the word currently
-       // pointed by 'from'.
-       while (from && from.pos() && isLetter(from))
-               from.backwardPos();
-       // OK, we start from here.
-       to = from;
-       while (to.depth()) {
-               if (isLetter(to)) {
-                       if (!inword) {
-                               inword = true;
-                               ignoreword = false;
-                               from = to;
-                               word.clear();
-                               lang_code = to.paragraph().getFontSettings(params(),
-                                       to.pos()).language()->code();
-                       }
-                       // Insets like optional hyphens and ligature
-                       // break are part of a word.
-                       if (!to.paragraph().isInset(to.pos())) {
-                               char_type const c = to.paragraph().getChar(to.pos());
-                               word += c;
-                               if (isDigit(c))
-                                       ignoreword = true;
-                       }
-               } else { // !isLetter(cur)
-                       if (inword && !word.empty() && !ignoreword)
-                               return true;
-                       inword = false;
-               }
-               to.forwardPos();
-       }
-       from = to;
-       word.clear();
-       return false;
-}
-
-
 int Buffer::spellCheck(DocIterator & from, DocIterator & to,
        WordLangTuple & word_lang, docstring_list & suggestions) const
 {
        int progress = 0;
-       SpellChecker::Result res = SpellChecker::OK;
-       SpellChecker * speller = theSpellChecker();
+       WordLangTuple wl;
        suggestions.clear();
-       docstring word;
-       while (nextWord(from, to, word)) {
-               ++progress;
-               string lang_code = lyxrc.spellchecker_use_alt_lang
-                     ? lyxrc.spellchecker_alt_lang
-                     : from.paragraph().getFontSettings(params(), from.pos()).language()->code();
-               WordLangTuple wl(word, lang_code);
-               res = speller->check(wl);
-               // ... just bail out if the spellchecker reports an error.
-               if (!speller->error().empty()) {
-                       throw ExceptionMessage(WarningException,
-                               _("The spellchecker has failed."), speller->error());
-               }
-               if (res != SpellChecker::OK && res != SpellChecker::IGNORED_WORD) {
+       word_lang = WordLangTuple();
+       // OK, we start from here.
+       DocIterator const end = doc_iterator_end(this);
+       for (; from != end; from.forwardPos()) {
+               // We are only interested in text so remove the math CursorSlice.
+               while (from.inMathed())
+                       from.forwardInset();
+               to = from;
+               if (from.paragraph().spellCheck(from.pos(), to.pos(), wl, suggestions)) {
                        word_lang = wl;
                        break;
                }
                from = to;
+               ++progress;
        }
-       while (!(word = speller->nextMiss()).empty())
-               suggestions.push_back(word);
        return progress;
 }