X-Git-Url: https://git.lyx.org/gitweb/?a=blobdiff_plain;f=src%2FBuffer.cpp;h=bd7305701785929e0afe9bc9cb65aa89cb375e28;hb=f503ce67fc2d2f945a519a277c479a769c0d522c;hp=b3137ad4b73cc1ea091b14259b298c9daeba7381;hpb=2b9e44cb0110201ca4d6320266e6550160ee99b3;p=lyx.git diff --git a/src/Buffer.cpp b/src/Buffer.cpp index b3137ad4b7..bd73057017 100644 --- a/src/Buffer.cpp +++ b/src/Buffer.cpp @@ -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" @@ -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 = 369; // vfr: add author ids to list of authors +int const LYX_FORMAT = 374; // rgheck: HTML output options typedef map DepClean; typedef map > RefCache; @@ -146,7 +147,7 @@ class BufferSet : public std::set {}; class Buffer::Impl { public: - Impl(Buffer & parent, FileName const & file, bool readonly); + Impl(Buffer & parent, FileName const & file, bool readonly, Buffer const * cloned_buffer); ~Impl() { @@ -252,10 +253,20 @@ public: return parent_buffer; } /// - void setParent(Buffer const * pb) { parent_buffer = pb; } + void setParent(Buffer const * pb) { + if (parent_buffer && pb && parent_buffer != pb) + LYXERR0("Warning: a buffer should not have two parents!"); + parent_buffer = pb; + } + + /// If non zero, this buffer is a clone of existing buffer \p cloned_buffer_ + /// This one is useful for preview detached in a thread. + Buffer const * cloned_buffer_; + private: /// So we can force access via the accessors. mutable Buffer const * parent_buffer; + }; @@ -278,26 +289,36 @@ static FileName createBufferTmpDir() } -Buffer::Impl::Impl(Buffer & parent, FileName const & file, bool readonly_) +Buffer::Impl::Impl(Buffer & parent, FileName const & file, bool readonly_, + Buffer const * cloned_buffer) : lyx_clean(true), bak_clean(true), unnamed(false), read_only(readonly_), filename(file), file_fully_loaded(false), toc_backend(&parent), macro_lock(false), timestamp_(0), checksum_(0), wa_(0), undo_(parent), bibinfoCacheValid_(false), - parent_buffer(0) + cloned_buffer_(cloned_buffer), parent_buffer(0) { - temppath = createBufferTmpDir(); - lyxvc.setBuffer(&parent); - if (use_gui) - wa_ = new frontend::WorkAreaManager; + if (!cloned_buffer_) { + temppath = createBufferTmpDir(); + lyxvc.setBuffer(&parent); + if (use_gui) + wa_ = new frontend::WorkAreaManager; + return; + } + temppath = cloned_buffer_->d->temppath; + file_fully_loaded = true; + params = cloned_buffer_->d->params; } -Buffer::Buffer(string const & file, bool readonly) - : d(new Impl(*this, FileName(file), readonly)), gui_(0) +Buffer::Buffer(string const & file, bool readonly, Buffer const * cloned_buffer) + : d(new Impl(*this, FileName(file), readonly, cloned_buffer)), gui_(0) { LYXERR(Debug::INFO, "Buffer::Buffer()"); - - d->inset = new InsetText(*this); + if (cloned_buffer) { + d->inset = static_cast(cloned_buffer->d->inset->clone()); + d->inset->setBuffer(*this); + } else + d->inset = new InsetText(this); d->inset->setAutoBreakRows(true); d->inset->getText(0)->setMacrocontextPosition(par_iterator_begin()); } @@ -312,7 +333,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,11 +349,17 @@ Buffer::~Buffer() theBufferList().releaseChild(this, child); } + if (!isClean()) { + docstring msg = _("LyX attempted to close a document that had unsaved changes!\n"); + msg += emergencyWrite(); + Alert::warning(_("Attempting to close changed document!"), msg); + } + // clear references to children in macro tables d->children_positions.clear(); d->position_to_children.clear(); - if (!d->temppath.destroyDirectory()) { + if (!d->cloned_buffer_ && !d->temppath.destroyDirectory()) { Alert::warning(_("Could not remove temporary directory"), bformat(_("Could not remove the temporary directory %1$s"), from_utf8(d->temppath.absFilename()))); @@ -345,6 +372,18 @@ Buffer::~Buffer() } +Buffer * Buffer::clone() const +{ + return new Buffer(fileName().absFilename(), false, this); +} + + +bool Buffer::isClone() const +{ + return d->cloned_buffer_; +} + + void Buffer::changed() const { if (d->wa_) @@ -687,10 +726,14 @@ bool Buffer::readDocument(Lexer & lex) } } } + + // assure we have a default index + params().indiceslist().addDefault(B_("Index")); // read main text bool const res = text().read(lex, errorList, d->inset); + usermacros.clear(); updateMacros(); updateMacroInstances(); return res; @@ -942,6 +985,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 @@ -1316,7 +1416,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); } @@ -1325,7 +1425,7 @@ void Buffer::makeLyXHTMLFile(FileName const & fname, OutputParams const & runparams, bool const body_only) const { - LYXERR(Debug::LATEX, "makeLYXHTMLFile..."); + LYXERR(Debug::LATEX, "makeLyXHTMLFile..."); ofdocstream ofs; if (!openFileWrite(ofs, fname)) @@ -1345,14 +1445,15 @@ void Buffer::writeLyXHTMLSource(odocstream & os, { LaTeXFeatures features(*this, params(), runparams); validate(features); + updateLabels(UpdateMaster, true); d->texrow.reset(); if (!only_body) { - os << "\n"; + os << "\n"; + os << "\n"; // FIXME Language should be set properly. - os << "\n"; + os << "\n"; // FIXME Header os << "\n"; // FIXME Presumably need to set this right @@ -1360,21 +1461,24 @@ void Buffer::writeLyXHTMLSource(odocstream & os, // FIXME Get this during validation? What about other meta-data? os << "TBA\n"; - os << features.getTClassHTMLPreamble(); - - os << '\n'; + os << "\n\n" + << features.getTClassHTMLPreamble() + << "\n\n" + << from_utf8(features.getPreambleSnippets()); + os << "\n\n"; docstring const styleinfo = features.getTClassHTMLStyles(); if (!styleinfo.empty()) { - os << "\n"; + os << "\n"; } os << "\n\n"; } + XHTMLStream xs(os); params().documentClass().counters().reset(); - xhtmlParagraphs(paragraphs(), *this, os, runparams); + xhtmlParagraphs(text(), *this, xs, runparams); if (!only_body) os << "\n\n"; } @@ -1565,25 +1669,69 @@ void Buffer::markDepClean(string const & name) } +bool Buffer::isExportableFormat(string const & format) const +{ + typedef vector 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()) { + // 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_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)); + enable = !branchName.empty() && branchList.find(branchName); break; } @@ -1591,12 +1739,16 @@ bool Buffer::getStatus(FuncRequest const & cmd, FuncStatus & flag) 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; } @@ -1612,12 +1764,27 @@ 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); + bool success = doExport(argument, false); dr.setError(success); if (!success) dr.setMessage(bformat(_("Error exporting to format: %1$s."), @@ -1625,22 +1792,84 @@ void Buffer::dispatch(FuncRequest const & func, DispatchResult & dr) 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()) { + docstring const branch_name = func.argument(); + if (branch_name.empty()) { dispatched = false; break; } - Branch * branch = branchList.find(branchName); + BranchList & branch_list = params().branchlist(); + Branch * branch = branch_list.find(branch_name); if (branch) { - LYXERR0("Branch " << branchName << " does already exist."); + LYXERR0("Branch " << branch_name << " already exists."); dr.setError(true); docstring const msg = - bformat(_("Branch \"%1$s\" does already exist."), branchName); + bformat(_("Branch \"%1$s\" already exists."), branch_name); dr.setMessage(msg); } else { - branchList.add(branchName); + branch_list.add(branch_name); + branch = branch_list.find(branch_name); + string const x11hexname = X11hexname(branch->color()); + docstring const str = branch_name + ' ' + from_ascii(x11hexname); + lyx::dispatch(FuncRequest(LFUN_SET_COLOR, str)); dr.setError(false); dr.update(Update::Force); } @@ -1820,11 +2049,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(); } @@ -1974,7 +2214,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) { @@ -2081,22 +2331,30 @@ DocIterator Buffer::firstChildPosition(Buffer const * child) } -std::vector Buffer::getChildren() const +void Buffer::getChildren(std::vector & clist, bool grand_children) const { - std::vector clist; // loop over children Impl::BufferPositionMap::iterator it = d->children_positions.begin(); Impl::BufferPositionMap::iterator end = d->children_positions.end(); for (; it != end; ++it) { Buffer * child = const_cast(it->first); clist.push_back(child); - // there might be grandchildren - std::vector glist = child->getChildren(); - for (vector::const_iterator git = glist.begin(); - git != glist.end(); ++git) - clist.push_back(*git); + if (grand_children) { + // there might be grandchildren + std::vector glist = child->getChildren(); + for (vector::const_iterator git = glist.begin(); + git != glist.end(); ++git) + clist.push_back(*git); + } } - return clist; +} + + +std::vector Buffer::getChildren(bool grand_children) const +{ + std::vector v; + getChildren(v, grand_children); + return v; } @@ -2307,7 +2565,7 @@ void Buffer::updateMacros(DocIterator & it, DocIterator & scope) const // get macro data MathMacroTemplate & macroTemplate = static_cast(*iit->inset); - MacroContext mc(*this, it); + MacroContext mc(this, it); macroTemplate.updateToContext(mc); // valid? @@ -2319,8 +2577,10 @@ void Buffer::updateMacros(DocIterator & it, DocIterator & scope) const continue; // register macro + // FIXME (Abdel), I don't understandt why we pass 'it' here + // instead of 'macroTemplate' defined above... is this correct? d->macros[macroTemplate.name()][it] = - Impl::ScopeMacro(scope, MacroData(*this, it)); + Impl::ScopeMacro(scope, MacroData(const_cast(this), it)); } // next paragraph @@ -2387,20 +2647,17 @@ void Buffer::updateMacroInstances() const LYXERR(Debug::MACROS, "updateMacroInstances for " << d->filename.onlyFileName()); DocIterator it = doc_iterator_begin(this); - DocIterator end = doc_iterator_end(this); - for (; it != end; it.forwardPos()) { - // look for MathData cells in InsetMathNest insets - Inset * inset = it.nextInset(); - if (!inset) - continue; - - InsetMath * minset = inset->asInsetMath(); + it.forwardInset(); + DocIterator const end = doc_iterator_end(this); + for (; it != end; it.forwardInset()) { + // look for MathData cells in InsetMathNest insets + InsetMath * minset = it.nextInset()->asInsetMath(); if (!minset) continue; // update macro in all cells of the InsetMathNest DocIterator::idx_type n = minset->nargs(); - MacroContext mc = MacroContext(*this, it); + MacroContext mc = MacroContext(this, it); for (DocIterator::idx_type i = 0; i < n; ++i) { MathData & data = minset->cell(i); data.updateMacros(0, mc); @@ -2580,7 +2837,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); @@ -2699,6 +2956,15 @@ private: int AutoSaveBuffer::generateChild() { +#if defined(__APPLE__) + /* FIXME fork() is not usable for autosave on Mac OS X 10.6 (snow leopard) + * We should use something else like threads. + * + * Since I do not know how to determine at run time what is the OS X + * version, I just disable forking altogether for now (JMarc) + */ + pid_t const pid = -1; +#else // tmp_ret will be located (usually) in /tmp // will that be a problem? // Note that this calls ForkedCalls::fork(), so it's @@ -2708,6 +2974,7 @@ int AutoSaveBuffer::generateChild() // you should set pid to -1, and comment out the fork. if (pid != 0 && pid != -1) return pid; +#endif // pid = -1 signifies that lyx was unable // to fork. But we will do the save @@ -2846,14 +3113,18 @@ bool Buffer::doExport(string const & format, bool put_in_tempdir, path = p; } } - if (!path.empty()) - runparams.flavor = theConverters().getFlavor(path); - else { - Alert::error(_("Couldn't export file"), - bformat(_("No information for exporting the format %1$s."), - formats.prettyName(format))); + if (path.empty()) { + if (!put_in_tempdir) { + // Only show this alert if this is an export to a non-temporary + // file (not for previewing). + Alert::error(_("Couldn't export file"), bformat( + _("No information for exporting the format %1$s."), + formats.prettyName(format))); + } return false; } + runparams.flavor = theConverters().getFlavor(path); + } else { backend_format = format; // FIXME: Don't hardcode format names here, but use a flag @@ -2870,12 +3141,15 @@ bool Buffer::doExport(string const & format, bool put_in_tempdir, updateMacroInstances(); // Plain text backend - if (backend_format == "text") + if (backend_format == "text") { + runparams.flavor = OutputParams::TEXT; writePlaintextFile(*this, FileName(filename), runparams); - // no backend - else if (backend_format == "xhtml") + } + // HTML backend + else if (backend_format == "xhtml") { + runparams.flavor = OutputParams::HTML; makeLyXHTMLFile(FileName(filename), runparams); - else if (backend_format == "lyx") + } else if (backend_format == "lyx") writeFile(FileName(filename)); // Docbook backend else if (isDocBook()) { @@ -2987,7 +3261,7 @@ bool Buffer::isExportable(string const & format) const vector Buffer::exportableFormats(bool only_viewable) const { - vector backs = backends(); + vector const backs = backends(); vector result = theConverters().getReachable(backs[0], only_viewable, true); for (vector::const_iterator it = backs.begin() + 1; @@ -3003,14 +3277,12 @@ vector Buffer::exportableFormats(bool only_viewable) const vector Buffer::backends() const { vector v; - if (params().baseClass()->isTeXClassAvailable()) { - 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("text"); + 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("xhtml"); + v.push_back("text"); v.push_back("lyx"); return v; } @@ -3040,11 +3312,33 @@ 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" + bformat(_("Remove emergency file now?\n(%1$s)"), + from_utf8(e.absFilename())); + + if (!Alert::prompt(_("Delete emergency file?"), str, 1, 1, + _("&Remove"), _("&Keep it"))) { + e.removeFile(); + if (res == success) + Alert::warning(_("Emergency file deleted"), + _("Do not forget to save your file now!"), true); + } + return res; + } case 1: + if (!Alert::prompt(_("Delete emergency file?"), + _("Remove emergency file now?"), 1, 1, + _("&Remove"), _("&Keep it"))) + e.removeFile(); break; default: return false; @@ -3142,7 +3436,7 @@ void Buffer::setBuffersForInsets() const } -void Buffer::updateLabels(UpdateScope scope) const +void Buffer::updateLabels(UpdateScope scope, bool out) const { // Use the master text class also for child documents Buffer const * const master = masterBuffer(); @@ -3156,7 +3450,7 @@ void Buffer::updateLabels(UpdateScope scope) const // If this is a child document start with the master if (master != this) { bufToUpdate.insert(this); - master->updateLabels(); + master->updateLabels(UpdateMaster, out); // 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_) @@ -3184,7 +3478,7 @@ void Buffer::updateLabels(UpdateScope scope) const // do the real work ParIterator parit = cbuf.par_iterator_begin(); - updateLabels(parit); + updateLabels(parit, out); if (master != this) // TocBackend update will be done later. @@ -3266,9 +3560,9 @@ static bool needEnumCounterReset(ParIterator const & it) // set the label of a paragraph. This includes the counters. -static void setLabel(Buffer const & buf, ParIterator & it) +void Buffer::setLabel(ParIterator & it) const { - BufferParams const & bp = buf.masterBuffer()->params(); + BufferParams const & bp = this->masterBuffer()->params(); DocumentClass const & textclass = bp.documentClass(); Paragraph & par = it.paragraph(); Layout const & layout = par.layout(); @@ -3276,7 +3570,7 @@ static void setLabel(Buffer const & buf, ParIterator & it) if (par.params().startOfAppendix()) { // FIXME: only the counter corresponding to toplevel - // sectionning should be reset + // sectioning should be reset counters.reset(); counters.appendix(true); } @@ -3297,7 +3591,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)); @@ -3364,9 +3658,9 @@ static void setLabel(Buffer const & buf, ParIterator & it) string const & type = counters.current_float(); docstring full_label; if (type.empty()) - full_label = buf.B_("Senseless!!! "); + full_label = this->B_("Senseless!!! "); else { - docstring name = buf.B_(textclass.floats().getType(type).name()); + docstring name = this->B_(textclass.floats().getType(type).name()); if (counters.hasCounter(from_utf8(type))) { string const & lang = par.getParLanguage(bp)->code(); counters.step(from_utf8(type)); @@ -3395,7 +3689,7 @@ static void setLabel(Buffer const & buf, ParIterator & it) } -void Buffer::updateLabels(ParIterator & parit) const +void Buffer::updateLabels(ParIterator & parit, bool out) const { LASSERT(parit.pit() == 0, /**/); @@ -3413,14 +3707,14 @@ void Buffer::updateLabels(ParIterator & parit) const maxdepth = parit->getMaxDepthAfter(); // set the counter for this paragraph - setLabel(*this, parit); + setLabel(parit); // Now the insets InsetList::const_iterator iit = parit->insetList().begin(); InsetList::const_iterator end = parit->insetList().end(); for (; iit != end; ++iit) { parit.pos() = iit->pos; - iit->inset->updateLabels(parit); + iit->inset->updateLabels(parit, out); } } } @@ -3437,15 +3731,26 @@ int Buffer::spellCheck(DocIterator & from, DocIterator & to, 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(); + while (from.inMathed()) { + from.pop_back(); + from.pos()++; + } + // If from is at the end of the document (which is possible + // when leaving the mathed) LyX will crash later. + if (from == end) + break; to = from; if (from.paragraph().spellCheck(from.pos(), to.pos(), wl, suggestions)) { word_lang = wl; break; } - from = to; - ++progress; + + // Do not increase progress when from == to, otherwise the word + // count will be wrong. + if (from != to) { + from = to; + ++progress; + } } return progress; }