X-Git-Url: https://git.lyx.org/gitweb/?a=blobdiff_plain;f=src%2FBuffer.cpp;h=8c1ea58e4aaef5fa6eed8e94180fa654493a7c2c;hb=fe8c185a6e23b590e084f21ea06ce622ea99820d;hp=1ebe6cffb2a7aaf761e813ba44875b2799f4d9a0;hpb=f5a03ab60186e9c53d50946d859c7c99d6566bb5;p=lyx.git diff --git a/src/Buffer.cpp b/src/Buffer.cpp index 1ebe6cffb2..8c1ea58e4a 100644 --- a/src/Buffer.cpp +++ b/src/Buffer.cpp @@ -126,9 +126,7 @@ namespace os = support::os; namespace { -// Do not remove the comment below, so we get merge conflict in -// independent branches. Instead add your own. -int const LYX_FORMAT = 416; //uwestoehr : support for horizontal spaces (bug 7728) +int const LYX_FORMAT = LYX_FORMAT_LYX; typedef map DepClean; typedef map > RefCache; @@ -144,6 +142,10 @@ void showPrintError(string const & name) } // namespace anon +// A storehouse for the cloned buffers. +list cloned_buffers; + + class Buffer::Impl { public: @@ -158,7 +160,7 @@ public: } delete inset; } - + /// search for macro in local (buffer) table or in children MacroData const * getBufferMacro(docstring const & name, DocIterator const & pos) const; @@ -274,7 +276,7 @@ public: /// This is here to force the test to be done whenever parent_buffer /// is accessed. - Buffer const * parent() const { + Buffer const * parent() const { // if parent_buffer is not loaded, then it has been unloaded, // which means that parent_buffer is an invalid pointer. So we // set it to null in that case. @@ -283,9 +285,9 @@ public: // for the best. if (!cloned_buffer_ && !theBufferList().isLoaded(parent_buffer)) parent_buffer = 0; - return parent_buffer; + return parent_buffer; } - + /// void setParent(Buffer const * pb) { if (parent_buffer == pb) @@ -303,9 +305,11 @@ public: /// 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_; + /// + CloneList * clone_list_; /// are we in the process of exporting this buffer? mutable bool doing_export; - + private: /// So we can force access via the accessors. mutable Buffer const * parent_buffer; @@ -337,9 +341,9 @@ Buffer::Impl::Impl(Buffer * owner, FileName const & file, bool readonly_, : 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), cite_labels_valid_(false), - preview_loader_(0), cloned_buffer_(cloned_buffer), + 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), clone_list_(0), doing_export(false), parent_buffer(0) { if (!cloned_buffer_) { @@ -358,6 +362,7 @@ Buffer::Impl::Impl(Buffer * owner, FileName const & file, bool readonly_, 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_; + unnamed = cloned_buffer_->d->unnamed; } @@ -396,52 +401,85 @@ Buffer::~Buffer() return; } - // 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); - if (d->cloned_buffer_) - delete child; - // The child buffer might have been closed already. - else if (theBufferList().isLoaded(child)) - theBufferList().releaseChild(this, child); - } + if (isClone()) { + // this is in case of recursive includes: we won't try to delete + // ourselves as a child. + d->clone_list_->erase(this); + // 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); + if (d->clone_list_->erase(child)) + delete child; + } + // 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(), /* */); + list::iterator it = + find(cloned_buffers.begin(), cloned_buffers.end(), d->clone_list_); + LASSERT(it != cloned_buffers.end(), /* */); + cloned_buffers.erase(it); + delete d->clone_list_; + } + // FIXME Do we really need to do this right before we delete d? + // clear references to children in macro tables + d->children_positions.clear(); + d->position_to_children.clear(); + } else { + // 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); + if (theBufferList().isLoaded(child)) + 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 (!isClean()) { + docstring msg = _("LyX attempted to close a document that had unsaved changes!\n"); + msg += emergencyWrite(); + Alert::warning(_("Attempting to close changed document!"), msg); + } - 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()))); - } + // FIXME Do we really need to do this right before we delete d? + // clear references to children in macro tables + d->children_positions.clear(); + d->position_to_children.clear(); - if (!isClone()) + if (!d->temppath.destroyDirectory()) { + Alert::warning(_("Could not remove temporary directory"), + bformat(_("Could not remove the temporary directory %1$s"), + from_utf8(d->temppath.absFileName()))); + } removePreviews(); + } delete d; } -Buffer * Buffer::clone() const +Buffer * Buffer::cloneFromMaster() const { BufferMap bufmap; - masterBuffer()->clone(bufmap); - BufferMap::iterator it = bufmap.find(this); - LASSERT(it != bufmap.end(), return 0); - return it->second; + cloned_buffers.push_back(new CloneList()); + CloneList * clones = cloned_buffers.back(); + + masterBuffer()->cloneWithChildren(bufmap, clones); + + // make sure we got cloned + BufferMap::const_iterator bit = bufmap.find(this); + LASSERT(bit != bufmap.end(), return 0); + Buffer * cloned_buffer = bit->second; + + return cloned_buffer; } -void Buffer::clone(BufferMap & bufmap) const +void Buffer::cloneWithChildren(BufferMap & bufmap, CloneList * clones) const { // have we already been cloned? if (bufmap.find(this) != bufmap.end()) @@ -449,6 +487,8 @@ void Buffer::clone(BufferMap & bufmap) const Buffer * buffer_clone = new Buffer(fileName().absFileName(), false, this); 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 @@ -462,7 +502,7 @@ void Buffer::clone(BufferMap & bufmap) const dit.setBuffer(buffer_clone); Buffer * child = const_cast(it->second.second); - child->clone(bufmap); + child->cloneWithChildren(bufmap, clones); BufferMap::iterator const bit = bufmap.find(child); LASSERT(bit != bufmap.end(), continue); Buffer * child_clone = bit->second; @@ -480,6 +520,18 @@ void Buffer::clone(BufferMap & bufmap) const } +Buffer * Buffer::cloneBufferOnly() const { + cloned_buffers.push_back(new CloneList()); + CloneList * clones = cloned_buffers.back(); + Buffer * buffer_clone = new Buffer(fileName().absFileName(), false, this); + 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; +} + + bool Buffer::isClone() const { return d->cloned_buffer_; @@ -713,10 +765,10 @@ int Buffer::readHeader(Lexer & lex) params().indiceslist().clear(); params().backgroundcolor = lyx::rgbFromHexName("#ffffff"); params().isbackgroundcolor = false; - params().fontcolor = lyx::rgbFromHexName("#000000"); + params().fontcolor = RGBColor(0, 0, 0); params().isfontcolor = false; - params().notefontcolor = lyx::rgbFromHexName("#cccccc"); - params().boxbgcolor = lyx::rgbFromHexName("#ff0000"); + params().notefontcolor = RGBColor(0xCC, 0xCC, 0xCC); + params().boxbgcolor = RGBColor(0xFF, 0, 0); params().html_latex_start.clear(); params().html_latex_end.clear(); params().html_math_img_scale = 1.0; @@ -820,7 +872,7 @@ bool Buffer::readDocument(Lexer & lex) FileName const master_file = makeAbsPath(params().master, onlyPath(absFileName())); if (isLyXFileName(master_file.absFileName())) { - Buffer * master = + Buffer * master = checkAndLoadLyXFile(master_file, true); if (master) { // necessary e.g. after a reload @@ -845,7 +897,7 @@ bool Buffer::readDocument(Lexer & lex) } } } - + // assure we have a default index params().indiceslist().addDefault(B_("Index")); @@ -902,7 +954,7 @@ Buffer::ReadStatus Buffer::readFile(FileName const & fn) Lexer lex; if (!lex.setFile(fname)) { Alert::error(_("File Not Found"), - bformat(_("Unable to open file `%1$s'."), + bformat(_("Unable to open file `%1$s'."), from_utf8(fn.absFileName()))); return ReadFileNotFound; } @@ -920,7 +972,7 @@ Buffer::ReadStatus Buffer::readFile(FileName const & fn) return readFile(tmpFile); } - // FIXME: InsetInfo needs to know whether the file is under VCS + // FIXME: InsetInfo needs to know whether the file is under VCS // during the parse process, so this has to be done before. lyxvc().file_found_hook(d->filename); @@ -954,7 +1006,7 @@ void Buffer::setFullyLoaded(bool value) PreviewLoader * Buffer::loader() const { - if (lyxrc.preview == LyXRC::PREVIEW_OFF) + if (!isExporting() && lyxrc.preview == LyXRC::PREVIEW_OFF) return 0; if (!d->preview_loader_) d->preview_loader_ = new PreviewLoader(*this); @@ -992,7 +1044,7 @@ Buffer::ReadStatus Buffer::parseLyXFormat(Lexer & lex, bformat(_("%1$s is not a readable LyX document."), from_utf8(fn.absFileName()))); return ReadNoLyXFormat; - } + } string tmp_format; lex >> tmp_format; @@ -1009,7 +1061,7 @@ Buffer::ReadStatus Buffer::parseLyXFormat(Lexer & lex, } -Buffer::ReadStatus Buffer::convertLyXFormat(FileName const & fn, +Buffer::ReadStatus Buffer::convertLyXFormat(FileName const & fn, FileName & tmpfile, int from_format) { tmpfile = FileName::tempName("Buffer_convertLyXFormat"); @@ -1087,7 +1139,7 @@ bool Buffer::save() const // ask if the disk file has been externally modified (use checksum method) if (fileName().exists() && isExternallyModified(checksum_method)) { - docstring text = + docstring text = bformat(_("Document %1$s has been externally modified. " "Are you sure you want to overwrite this file?"), file); int const ret = Alert::prompt(_("Overwrite modified file?"), @@ -1302,7 +1354,7 @@ bool Buffer::write(ostream & ofs) const bool Buffer::makeLaTeXFile(FileName const & fname, string const & original_path, OutputParams const & runparams_in, - bool output_preamble, bool output_body) const + OutputWhat output) const { OutputParams runparams = runparams_in; @@ -1312,7 +1364,7 @@ bool Buffer::makeLaTeXFile(FileName const & fname, runparams.encoding = encodings.fromLyXName("utf8-plain"); string const encoding = runparams.encoding->iconvName(); - LYXERR(Debug::LATEX, "makeLaTeXFile encoding: " << encoding << "..."); + LYXERR(Debug::LATEX, "makeLaTeXFile encoding: " << encoding << ", fname=" << fname.realPath()); ofdocstream ofs; try { ofs.reset(encoding); } @@ -1341,8 +1393,7 @@ bool Buffer::makeLaTeXFile(FileName const & fname, try { os.texrow().reset(); - writeLaTeXSource(os, original_path, - runparams, output_preamble, output_body); + writeLaTeXSource(os, original_path, runparams, output); } catch (EncodingException & e) { odocstringstream ods; @@ -1387,7 +1438,7 @@ bool Buffer::makeLaTeXFile(FileName const & fname, void Buffer::writeLaTeXSource(otexstream & os, string const & original_path, OutputParams const & runparams_in, - bool const output_preamble, bool const output_body) const + OutputWhat output) const { // The child documents, if any, shall be already loaded at this point. @@ -1402,6 +1453,11 @@ void Buffer::writeLaTeXSource(otexstream & os, validate(features); LYXERR(Debug::LATEX, " Buffer validation done."); + bool const output_preamble = + output == FullSource || output == OnlyPreamble; + bool const output_body = + output == FullSource || output == OnlyBody; + // The starting paragraph of the coming rows is the // first paragraph of the document. (Asger) if (output_preamble && runparams.nice) { @@ -1413,12 +1469,13 @@ void Buffer::writeLaTeXSource(otexstream & os, LYXERR(Debug::INFO, "lyx document header finished"); // 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 - // with either \input or \includegraphics (what figinsets do). - // input@path is set when the actual parameter - // original_path is set. This is done for usual tex-file, but not - // for nice-latex-file. (Matthias 250696) + // usual files have \batchmode and special input@path to allow + // inclusion of figures specified by an explicitly relative path + // (i.e., a path starting with './' or '../') with either \input or + // \includegraphics, as the TEXINPUTS method doesn't work in this case. + // input@path is set when the actual parameter original_path is set. + // This is done for usual tex-file, but not for nice-latex-file. + // (Matthias 250696) // Note that input@path is only needed for something the user does // in the preamble, included .tex files or ERT, files included by // LyX work without it. @@ -1430,7 +1487,7 @@ void Buffer::writeLaTeXSource(otexstream & os, if (!original_path.empty()) { // FIXME UNICODE // We don't know the encoding of inputpath - docstring const inputpath = from_utf8(support::latex_path(original_path)); + docstring const inputpath = from_utf8(original_path); docstring uncodable_glyphs; Encoding const * const enc = runparams.encoding; if (enc) { @@ -1448,18 +1505,41 @@ void Buffer::writeLaTeXSource(otexstream & os, // warn user if we found uncodable glyphs. if (!uncodable_glyphs.empty()) { - frontend::Alert::warning(_("Uncodable character in file path"), - support::bformat(_("The path of your document\n" - "(%1$s)\n" - "contains glyphs that are unknown in the\n" - "current document encoding (namely %2$s).\n" - "This will likely result in incomplete output.\n\n" - "Choose an appropriate document encoding (such as utf8)\n" - "or change the file path name."), inputpath, uncodable_glyphs)); + frontend::Alert::warning( + _("Uncodable character in file path"), + support::bformat( + _("The path of your document\n" + "(%1$s)\n" + "contains glyphs that are unknown " + "in the current document encoding " + "(namely %2$s). This may result in " + "incomplete output, unless " + "TEXINPUTS contains the document " + "directory and you don't use " + "explicitly relative paths (i.e., " + "paths starting with './' or " + "'../') in the preamble or in ERT." + "\n\nIn case of problems, choose " + "an appropriate document encoding\n" + "(such as utf8) or change the " + "file path name."), + inputpath, uncodable_glyphs)); } else { + string docdir = + support::latex_path(original_path); + if (contains(docdir, '#')) { + docdir = subst(docdir, "#", "\\#"); + os << "\\catcode`\\#=11" + "\\def\\#{#}\\catcode`\\#=6\n"; + } + if (contains(docdir, '%')) { + docdir = subst(docdir, "%", "\\%"); + os << "\\catcode`\\%=11" + "\\def\\%{%}\\catcode`\\%=14\n"; + } os << "\\makeatletter\n" << "\\def\\input@path{{" - << inputpath << "/}}\n" + << docdir << "/}}\n" << "\\makeatother\n"; } } @@ -1489,7 +1569,7 @@ void Buffer::writeLaTeXSource(otexstream & os, int num_lines = (*it)->write(os.os(), true); os.texrow().newlines(num_lines); } - + } // output_preamble os.texrow().start(paragraphs().begin()->id(), 0); @@ -1539,7 +1619,7 @@ void Buffer::writeLaTeXSource(otexstream & os, void Buffer::makeDocBookFile(FileName const & fname, OutputParams const & runparams, - bool const body_only) const + OutputWhat output) const { LYXERR(Debug::LATEX, "makeDocBookFile..."); @@ -1552,7 +1632,7 @@ void Buffer::makeDocBookFile(FileName const & fname, updateBuffer(); updateMacroInstances(OutputUpdate); - writeDocBookSource(ofs, fname.absFileName(), runparams, body_only); + writeDocBookSource(ofs, fname.absFileName(), runparams, output); ofs.close(); if (ofs.fail()) @@ -1562,7 +1642,7 @@ void Buffer::makeDocBookFile(FileName const & fname, void Buffer::writeDocBookSource(odocstream & os, string const & fname, OutputParams const & runparams, - bool const only_body) const + OutputWhat output) const { LaTeXFeatures features(*this, params(), runparams); validate(features); @@ -1572,7 +1652,12 @@ void Buffer::writeDocBookSource(odocstream & os, string const & fname, DocumentClass const & tclass = params().documentClass(); string const top_element = tclass.latexname(); - if (!only_body) { + bool const output_preamble = + output == FullSource || output == OnlyPreamble; + bool const output_body = + output == FullSource || output == OnlyBody; + + if (output_preamble) { if (runparams.flavor == OutputParams::XML) os << "\n"; @@ -1607,29 +1692,31 @@ void Buffer::writeDocBookSource(odocstream & os, string const & fname, os << ">\n\n"; } - string top = top_element; - top += " lang=\""; - if (runparams.flavor == OutputParams::XML) - top += params().language->code(); - else - top += params().language->code().substr(0, 2); - top += '"'; + if (output_body) { + string top = top_element; + top += " lang=\""; + if (runparams.flavor == OutputParams::XML) + top += params().language->code(); + else + top += params().language->code().substr(0, 2); + top += '"'; - if (!params().options.empty()) { - top += ' '; - top += params().options; - } + if (!params().options.empty()) { + top += ' '; + top += params().options; + } - os << "\n"; + os << "\n"; - params().documentClass().counters().reset(); + params().documentClass().counters().reset(); - sgml::openTag(os, top); - os << '\n'; - docbookParagraphs(text(), *this, os, runparams); - sgml::closeTag(os, top_element); + sgml::openTag(os, top); + os << '\n'; + docbookParagraphs(text(), *this, os, runparams); + sgml::closeTag(os, top_element); + } } @@ -1647,7 +1734,7 @@ void Buffer::makeLyXHTMLFile(FileName const & fname, updateBuffer(UpdateMaster, OutputUpdate); updateMacroInstances(OutputUpdate); - writeLyXHTMLSource(ofs, runparams); + writeLyXHTMLSource(ofs, runparams, FullSource); ofs.close(); if (ofs.fail()) @@ -1657,13 +1744,18 @@ void Buffer::makeLyXHTMLFile(FileName const & fname, void Buffer::writeLyXHTMLSource(odocstream & os, OutputParams const & runparams, - bool const only_body) const + OutputWhat output) const { LaTeXFeatures features(*this, params(), runparams); validate(features); d->bibinfo_.makeCitationLabels(*this); - if (!only_body) { + bool const output_preamble = + output == FullSource || output == OnlyPreamble; + bool const output_body = + output == FullSource || output == OnlyBody; + + if (output_preamble) { os << "\n" << "\n" // FIXME Language should be set properly. @@ -1675,29 +1767,84 @@ void Buffer::writeLyXHTMLSource(odocstream & os, docstring const & doctitle = features.htmlTitle(); os << "" - << (doctitle.empty() ? from_ascii("LyX Document") : doctitle) + << (doctitle.empty() ? + from_ascii("LyX Document") : + html::htmlize(doctitle, XHTMLStream::ESCAPE_ALL)) << "\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"; + docstring styles = features.getTClassHTMLPreamble(); + if (!styles.empty()) + os << "\n\n" << styles << '\n'; + + styles = from_utf8(features.getPreambleSnippets()); + if (!styles.empty()) + os << "\n\n" << styles << '\n'; + + // we will collect CSS information in a stream, and then output it + // either here, as part of the header, or else in a separate file. + odocstringstream css; + styles = from_utf8(features.getCSSSnippets()); + if (!styles.empty()) + css << "/* LyX Provided Styles */\n" << styles << '\n'; + + styles = features.getTClassHTMLStyles(); + if (!styles.empty()) + css << "/* Layout-provided Styles */\n" << styles << '\n'; + + bool const needfg = params().fontcolor != RGBColor(0, 0, 0); + bool const needbg = params().backgroundcolor != RGBColor(0xFF, 0xFF, 0xFF); + if (needfg || needbg) { + css << "\nbody {\n"; + if (needfg) + css << " color: " + << from_ascii(X11hexname(params().fontcolor)) + << ";\n"; + if (needbg) + css << " background-color: " + << from_ascii(X11hexname(params().backgroundcolor)) + << ";\n"; + css << "}\n"; + } + + docstring const dstyles = css.str(); + if (!dstyles.empty()) { + bool written = false; + if (params().html_css_as_file) { + // open a file for CSS info + ofdocstream ocss; + string const fcssname = addName(temppath(), "docstyle.css"); + FileName const fcssfile = FileName(fcssname); + if (openFileWrite(ocss, fcssfile)) { + ocss << dstyles; + ocss.close(); + written = true; + // write link to header + os << "\n"; + // register file + runparams.exportdata->addExternalFile("xhtml", fcssfile); + } + } + // we are here if the CSS is supposed to be written to the header + // or if we failed to write it to an external file. + if (!written) { + os << "\n"; + } } - os << "\n\n"; + os << "\n"; + } + + if (output_body) { + os << "\n"; + XHTMLStream xs(os); + params().documentClass().counters().reset(); + xhtmlParagraphs(text(), *this, xs, runparams); + os << "\n"; } - XHTMLStream xs(os); - params().documentClass().counters().reset(); - xhtmlParagraphs(text(), *this, xs, runparams); - if (!only_body) - os << "\n\n"; + if (output_preamble) + os << "\n"; } @@ -1934,6 +2081,24 @@ bool Buffer::citeLabelsValid() const } +void Buffer::removeBiblioTempFiles() const +{ + // We remove files that contain LaTeX commands specific to the + // particular bibliographic style being used, in order to avoid + // LaTeX errors when we switch style. + FileName const aux_file(addName(temppath(), changeExtension(latexName(),".aux"))); + FileName const bbl_file(addName(temppath(), changeExtension(latexName(),".bbl"))); + LYXERR(Debug::FILES, "Removing the .aux file " << aux_file); + aux_file.removeFile(); + LYXERR(Debug::FILES, "Removing the .bbl file " << bbl_file); + bbl_file.removeFile(); + // Also for the parent buffer + Buffer const * const pbuf = parent(); + if (pbuf) + pbuf->removeBiblioTempFiles(); +} + + bool Buffer::isDepClean(string const & name) const { DepClean::const_iterator const it = d->dep_clean.find(name); @@ -1977,7 +2142,15 @@ bool Buffer::getStatus(FuncRequest const & cmd, FuncStatus & flag) case LFUN_BUFFER_EXPORT: { docstring const arg = cmd.argument(); - enable = arg == "custom" || params().isExportable(to_utf8(arg)); + 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)); @@ -1992,14 +2165,6 @@ bool Buffer::getStatus(FuncRequest const & cmd, FuncStatus & flag) enable = params().isExportable("program"); break; - case LFUN_BRANCH_ACTIVATE: - case LFUN_BRANCH_DEACTIVATE: { - 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: @@ -2025,7 +2190,7 @@ void Buffer::dispatch(string const & command, DispatchResult & result) // NOTE We can end up here even if we have no GUI, because we are called -// by LyX::exec to handled command-line requests. So we may need to check +// by LyX::exec to handled command-line requests. So we may need to check // whether we have a GUI or not. The boolean use_gui holds this information. void Buffer::dispatch(FuncRequest const & func, DispatchResult & dr) { @@ -2049,16 +2214,16 @@ void Buffer::dispatch(FuncRequest const & func, DispatchResult & dr) break; case LFUN_BUFFER_EXPORT: { - bool success = doExport(argument, false, false); - dr.setError(!success); - if (!success) - dr.setMessage(bformat(_("Error exporting to format: %1$s."), + ExportStatus const status = doExport(argument, false); + dr.setError(status != ExportSuccess); + if (status != ExportSuccess) + dr.setMessage(bformat(_("Error exporting to format: %1$s."), func.argument())); break; } case LFUN_BUILD_PROGRAM: - doExport("program", true, false); + doExport("program", true); break; case LFUN_BUFFER_CHKTEX: @@ -2090,7 +2255,7 @@ void Buffer::dispatch(FuncRequest const & func, DispatchResult & dr) break; } else { - doExport(format_name, true, false, filename); + doExport(format_name, true, filename); } // Substitute $$FName for filename @@ -2151,31 +2316,6 @@ void Buffer::dispatch(FuncRequest const & func, DispatchResult & dr) break; } - case LFUN_BRANCH_ACTIVATE: - case LFUN_BRANCH_DEACTIVATE: { - BranchList & branchList = params().branchlist(); - docstring const branchName = func.argument(); - // the case without a branch name is handled elsewhere - if (branchName.empty()) { - dispatched = false; - break; - } - Branch * branch = branchList.find(branchName); - if (!branch) { - LYXERR0("Branch " << branchName << " does not exist."); - dr.setError(true); - docstring const msg = - bformat(_("Branch \"%1$s\" does not exist."), branchName); - dr.setMessage(msg); - } else { - branch->setSelected(func.action() == LFUN_BRANCH_ACTIVATE); - dr.setError(false); - dr.screenUpdate(Update::Force); - dr.forceBufferUpdate(); - } - break; - } - case LFUN_BRANCHES_RENAME: { if (func.argument().empty()) break; @@ -2215,7 +2355,7 @@ void Buffer::dispatch(FuncRequest const & func, DispatchResult & dr) case LFUN_BUFFER_PRINT: { // we'll assume there's a problem until we succeed - dr.setError(true); + dr.setError(true); string target = func.getArg(0); string target_name = func.getArg(1); string command = func.getArg(2); @@ -2224,23 +2364,20 @@ void Buffer::dispatch(FuncRequest const & func, DispatchResult & dr) || target_name.empty() || command.empty()) { LYXERR0("Unable to parse " << func.argument()); - docstring const msg = + docstring const msg = bformat(_("Unable to parse \"%1$s\""), func.argument()); dr.setMessage(msg); break; } if (target != "printer" && target != "file") { LYXERR0("Unrecognized target \"" << target << '"'); - docstring const msg = + docstring const msg = bformat(_("Unrecognized target \"%1$s\""), from_utf8(target)); dr.setMessage(msg); break; } - bool const update_unincluded = - params().maintain_unincluded_children - && !params().getIncludedChildren().empty(); - if (!doExport("dvi", true, update_unincluded)) { + if (!doExport("dvi", true)) { showPrintError(absFileName()); dr.setMessage(_("Error exporting to DVI.")); break; @@ -2324,7 +2461,7 @@ void Buffer::dispatch(FuncRequest const & func, DispatchResult & dr) res = one.startscript(stype, command, filePath()); } - if (res == 0) + if (res == 0) dr.setError(false); else { dr.setMessage(_("Error running external commands.")); @@ -2608,7 +2745,7 @@ DocIterator Buffer::firstChildPosition(Buffer const * child) bool Buffer::hasChildren() const { - return !d->children_positions.empty(); + return !d->children_positions.empty(); } @@ -2624,7 +2761,7 @@ void Buffer::collectChildren(ListOfBuffers & clist, bool grand_children) const if (bit != clist.end()) continue; clist.push_back(child); - if (grand_children) + if (grand_children) // there might be grandchildren child->collectChildren(clist, true); } @@ -2838,7 +2975,7 @@ void Buffer::Impl::updateMacros(DocIterator & it, DocIterator & scope) it.pop_back(); continue; } - + if (iit->inset->asInsetTabular()) { CursorSlice slice(*iit->inset); size_t const numcells = slice.nargs(); @@ -3122,7 +3259,7 @@ void Buffer::changeRefsIfUnique(docstring const & from, docstring const & to, void Buffer::getSourceCode(odocstream & os, string const format, pit_type par_begin, pit_type par_end, - bool full_source) const + OutputWhat output) const { OutputParams runparams(¶ms().encoding()); runparams.nice = true; @@ -3131,21 +3268,7 @@ void Buffer::getSourceCode(odocstream & os, string const format, // No side effect of file copying and image conversion runparams.dryrun = true; - if (full_source) { - os << "% " << _("Preview source code") << "\n\n"; - d->texrow.reset(); - d->texrow.newline(); - d->texrow.newline(); - if (params().isDocBook()) - writeDocBookSource(os, absFileName(), runparams, false); - else if (runparams.flavor == OutputParams::HTML) - writeLyXHTMLSource(os, runparams, false); - else { - // latex or literate - otexstream ots(os, d->texrow); - writeLaTeXSource(ots, string(), runparams, true, true); - } - } else { + if (output == CurrentParagraph) { runparams.par_begin = par_begin; runparams.par_end = par_end; if (par_begin + 1 == par_end) { @@ -3168,12 +3291,34 @@ void Buffer::getSourceCode(odocstream & os, string const format, docbookParagraphs(text(), *this, os, runparams); else if (runparams.flavor == OutputParams::HTML) { XHTMLStream xs(os); + setMathFlavor(runparams); xhtmlParagraphs(text(), *this, xs, runparams); } else { // latex or literate otexstream ots(os, texrow); latexParagraphs(*this, text(), ots, runparams); } + } else { + os << "% "; + if (output == FullSource) + os << _("Preview source code"); + else if (output == OnlyPreamble) + os << _("Preview preamble"); + else if (output == OnlyBody) + os << _("Preview body"); + os << "\n\n"; + d->texrow.reset(); + d->texrow.newline(); + d->texrow.newline(); + if (params().isDocBook()) + writeDocBookSource(os, absFileName(), runparams, output); + else if (runparams.flavor == OutputParams::HTML) + writeLyXHTMLSource(os, runparams, output); + else { + // latex or literate + otexstream ots(os, d->texrow); + writeLaTeXSource(ots, string(), runparams, output); + } } } @@ -3278,7 +3423,7 @@ private: int AutoSaveBuffer::generateChild() { #if defined(__APPLE__) - /* FIXME fork() is not usable for autosave on Mac OS X 10.6 (snow leopard) + /* 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 @@ -3338,7 +3483,7 @@ FileName Buffer::getEmergencyFileName() const FileName Buffer::getAutosaveFileName() const { // if the document is unnamed try to save in the backup dir, else - // in the default document path, and as a last try in the filePath, + // in the default document path, and as a last try in the filePath, // which will most often be the temporary directory string fpath; if (isUnnamed()) @@ -3371,7 +3516,7 @@ void Buffer::moveAutosaveFile(support::FileName const & oldauto) const } -bool Buffer::autoSave() const +bool Buffer::autoSave() const { Buffer const * buf = d->cloned_buffer_ ? d->cloned_buffer_ : this; if (buf->d->bak_clean || isReadonly()) @@ -3379,7 +3524,7 @@ bool Buffer::autoSave() const message(_("Autosaving current document...")); buf->d->bak_clean = true; - + FileName const fname = getAutosaveFileName(); if (d->cloned_buffer_) { // If this buffer is cloned, we assume that @@ -3393,7 +3538,7 @@ bool Buffer::autoSave() const } // failed to write/rename tmp_ret so try writing direct return writeFile(fname); - } else { + } 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). @@ -3404,28 +3549,27 @@ bool Buffer::autoSave() const } -namespace { - // helper class, to guarantee this gets reset properly - class MarkAsExporting { - public: - MarkAsExporting(Buffer const * buf) : buf_(buf) - { - LASSERT(buf_, /* */); - buf_->setExportStatus(true); - } - ~MarkAsExporting() - { - buf_->setExportStatus(false); - } - private: - Buffer const * const buf_; - }; -} +// 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); + } +private: + Buffer const * const buf_; +}; + void Buffer::setExportStatus(bool e) const { - d->doing_export = e; + d->doing_export = e; ListOfBuffers clist = getDescendents(); ListOfBuffers::const_iterator cit = clist.begin(); ListOfBuffers::const_iterator const cen = clist.end(); @@ -3440,12 +3584,68 @@ bool Buffer::isExporting() const } -bool Buffer::doExport(string const & format, bool put_in_tempdir, +Buffer::ExportStatus Buffer::doExport(string const & target, bool put_in_tempdir) + const +{ + string result_file; + return doExport(target, put_in_tempdir, result_file); +} + +Buffer::ExportStatus Buffer::doExport(string const & target, bool put_in_tempdir, + string & result_file) const +{ + bool const update_unincluded = + params().maintain_unincluded_children + && !params().getIncludedChildren().empty(); + + // (1) export with all included children (omit \includeonly) + if (update_unincluded) { + ExportStatus const status = + doExport(target, put_in_tempdir, true, result_file); + if (status != ExportSuccess) + return status; + } + // (2) export with included children only + return doExport(target, put_in_tempdir, false, result_file); +} + + +void Buffer::setMathFlavor(OutputParams & op) const +{ + switch (params().html_math_output) { + case BufferParams::MathML: + op.math_flavor = OutputParams::MathAsMathML; + break; + case BufferParams::HTML: + op.math_flavor = OutputParams::MathAsHTML; + break; + case BufferParams::Images: + op.math_flavor = OutputParams::MathAsImages; + break; + case BufferParams::LaTeX: + op.math_flavor = OutputParams::MathAsLaTeX; + break; + } +} + + +Buffer::ExportStatus Buffer::doExport(string const & target, bool put_in_tempdir, bool includeall, string & result_file) const { + LYXERR(Debug::FILES, "target=" << target); + OutputParams runparams(¶ms().encoding()); + string format = target; + string dest_filename; + size_t pos = target.find(' '); + if (pos != string::npos) { + dest_filename = target.substr(pos + 1, target.length() - pos - 1); + format = target.substr(0, pos); + runparams.export_folder = FileName(dest_filename).onlyPath().realPath(); + FileName(dest_filename).onlyPath().createPath(); + LYXERR(Debug::FILES, "format=" << format << ", dest_filename=" << dest_filename << ", export_folder=" << runparams.export_folder); + } MarkAsExporting exporting(this); string backend_format; - OutputParams runparams(¶ms().encoding()); runparams.flavor = OutputParams::LATEX; runparams.linelen = lyxrc.plaintext_linelen; runparams.includeall = includeall; @@ -3471,12 +3671,13 @@ bool Buffer::doExport(string const & format, bool put_in_tempdir, _("No information for exporting the format %1$s."), formats.prettyName(format))); } - return false; + return ExportNoPathToFormat; } runparams.flavor = converters.getFlavor(path); } else { backend_format = format; + LYXERR(Debug::FILES, "backend_format=" << backend_format); // FIXME: Don't hardcode format names here, but use a flag if (backend_format == "pdflatex") runparams.flavor = OutputParams::PDFLATEX; @@ -3492,6 +3693,7 @@ bool Buffer::doExport(string const & format, bool put_in_tempdir, filename = addName(temppath(), filename); filename = changeExtension(filename, formats.extension(backend_format)); + LYXERR(Debug::FILES, "filename=" << filename); // Plain text backend if (backend_format == "text") { @@ -3501,20 +3703,7 @@ bool Buffer::doExport(string const & format, bool put_in_tempdir, // HTML backend else if (backend_format == "xhtml") { runparams.flavor = OutputParams::HTML; - switch (params().html_math_output) { - case BufferParams::MathML: - runparams.math_flavor = OutputParams::MathAsMathML; - break; - case BufferParams::HTML: - runparams.math_flavor = OutputParams::MathAsHTML; - break; - case BufferParams::Images: - runparams.math_flavor = OutputParams::MathAsImages; - break; - case BufferParams::LaTeX: - runparams.math_flavor = OutputParams::MathAsLaTeX; - break; - } + setMathFlavor(runparams); makeLyXHTMLFile(FileName(filename), runparams); } else if (backend_format == "lyx") writeFile(FileName(filename)); @@ -3531,13 +3720,13 @@ bool Buffer::doExport(string const & format, bool put_in_tempdir, d->cloned_buffer_->d->errorLists["Export"] = d->errorLists["Export"]; } - return false; + return ExportError; } } else if (!lyxrc.tex_allows_spaces && contains(filePath(), ' ')) { Alert::error(_("File name error"), _("The directory path to the document cannot contain spaces.")); - return false; + return ExportTexPathHasSpaces; } else { runparams.nice = false; if (!makeLaTeXFile(FileName(filename), filePath(), runparams)) { @@ -3545,7 +3734,7 @@ bool Buffer::doExport(string const & format, bool put_in_tempdir, d->cloned_buffer_->d->errorLists["Export"] = d->errorLists["Export"]; } - return false; + return ExportError; } } @@ -3562,9 +3751,9 @@ bool Buffer::doExport(string const & format, bool put_in_tempdir, // cloned Buffer so that it can be emitted afterwards. if (format != backend_format) { if (d->cloned_buffer_) { - d->cloned_buffer_->d->errorLists[error_type] = + d->cloned_buffer_->d->errorLists[error_type] = d->errorLists[error_type]; - } else + } else errors(error_type); // also to the children, in case of master-buffer-view ListOfBuffers clist = getDescendents(); @@ -3576,7 +3765,7 @@ bool Buffer::doExport(string const & format, bool put_in_tempdir, // texrow object to the cloned buffer. // FIXME: this is not thread safe. (*cit)->d->cloned_buffer_->d->texrow = (*cit)->d->texrow; - (*cit)->d->cloned_buffer_->d->errorLists[error_type] = + (*cit)->d->cloned_buffer_->d->errorLists[error_type] = (*cit)->d->errorLists[error_type]; } else (*cit)->errors(error_type, true); @@ -3594,35 +3783,52 @@ bool Buffer::doExport(string const & format, bool put_in_tempdir, } if (!success) - return false; + return ExportConverterError; if (put_in_tempdir) { result_file = tmp_result_file.absFileName(); - return true; + return ExportSuccess; } - result_file = changeExtension(d->exportFileName().absFileName(), ext); + if (dest_filename.empty()) + result_file = changeExtension(d->exportFileName().absFileName(), ext); + else + result_file = dest_filename; // We need to copy referenced files (e. g. included graphics // if format == "dvi") to the result dir. vector const files = runparams.exportdata->externalFiles(format); - string const dest = onlyPath(result_file); + string const dest = runparams.export_folder.empty() ? + onlyPath(result_file) : runparams.export_folder; bool use_force = use_gui ? lyxrc.export_overwrite == ALL_FILES : force_overwrite == ALL_FILES; CopyStatus status = use_force ? FORCE : SUCCESS; - + vector::const_iterator it = files.begin(); vector::const_iterator const en = files.end(); for (; it != en && status != CANCEL; ++it) { string const fmt = formats.getFormatFromFile(it->sourceName); + string fixedName = it->exportName; + if (!runparams.export_folder.empty()) { + // Relative pathnames starting with ../ will be sanitized + // if exporting to a different folder + while (fixedName.substr(0, 3) == "../") + fixedName = fixedName.substr(3, fixedName.length() - 3); + } + FileName fixedFileName = makeAbsPath(fixedName, dest); + fixedFileName.onlyPath().createPath(); status = copyFile(fmt, it->sourceName, - makeAbsPath(it->exportName, dest), - it->exportName, status == FORCE); + fixedFileName, + it->exportName, status == FORCE, + runparams.export_folder.empty()); } if (status == CANCEL) { message(_("Document export cancelled.")); - } else if (tmp_result_file.exists()) { + return ExportCancel; + } + + if (tmp_result_file.exists()) { // Finally copy the main file use_force = use_gui ? lyxrc.export_overwrite != NO_FILES : force_overwrite != NO_FILES; @@ -3631,43 +3837,50 @@ bool Buffer::doExport(string const & format, bool put_in_tempdir, status = copyFile(format, tmp_result_file, FileName(result_file), result_file, status == FORCE); - message(bformat(_("Document exported as %1$s " - "to file `%2$s'"), - formats.prettyName(format), - makeDisplayPath(result_file))); + if (status == CANCEL) { + message(_("Document export cancelled.")); + return ExportCancel; + } else { + message(bformat(_("Document exported as %1$s " + "to file `%2$s'"), + formats.prettyName(format), + makeDisplayPath(result_file))); + } } else { // This must be a dummy converter like fax (bug 1888) message(bformat(_("Document exported as %1$s"), formats.prettyName(format))); } - return true; + return ExportSuccess; } -bool Buffer::doExport(string const & format, bool put_in_tempdir, - bool includeall) const +Buffer::ExportStatus Buffer::preview(string const & format) const { - string result_file; - // (1) export with all included children (omit \includeonly) - if (includeall && !doExport(format, put_in_tempdir, true, result_file)) - return false; - // (2) export with included children only - return doExport(format, put_in_tempdir, false, result_file); + bool const update_unincluded = + params().maintain_unincluded_children + && !params().getIncludedChildren().empty(); + return preview(format, update_unincluded); } - -bool Buffer::preview(string const & format, bool includeall) const +Buffer::ExportStatus Buffer::preview(string const & format, bool includeall) const { MarkAsExporting exporting(this); string result_file; // (1) export with all included children (omit \includeonly) - if (includeall && !doExport(format, true, true)) - return false; + if (includeall) { + ExportStatus const status = doExport(format, true, true, result_file); + if (status != ExportSuccess) + return status; + } // (2) export with included children only - if (!doExport(format, true, false, result_file)) - return false; - return formats.view(*this, FileName(result_file), format); + ExportStatus const status = doExport(format, true, false, result_file); + if (status != ExportSuccess) + return status; + if (!formats.view(*this, FileName(result_file), format)) + return PreviewError; + return PreviewSuccess; } @@ -3685,14 +3898,14 @@ Buffer::ReadStatus Buffer::extractFromVC() Buffer::ReadStatus Buffer::loadEmergency() { FileName const emergencyFile = getEmergencyFileName(); - if (!emergencyFile.exists() + if (!emergencyFile.exists() || emergencyFile.lastModified() <= d->filename.lastModified()) return ReadFileNotFound; docstring const file = makeDisplayPath(d->filename.absFileName(), 20); docstring const text = bformat(_("An emergency save of the document " "%1$s exists.\n\nRecover emergency save?"), file); - + int const load_emerg = Alert::prompt(_("Load emergency save?"), text, 0, 2, _("&Recover"), _("&Load Original"), _("&Cancel")); @@ -3717,7 +3930,7 @@ Buffer::ReadStatus Buffer::loadEmergency() str += "\n\n" + bformat(_("Remove emergency file now?\n(%1$s)"), makeDisplayPath(emergencyFile.absFileName())); - int const del_emerg = + int const del_emerg = Alert::prompt(_("Delete emergency file?"), str, 1, 1, _("&Remove"), _("&Keep")); if (del_emerg == 0) { @@ -3749,16 +3962,16 @@ Buffer::ReadStatus Buffer::loadAutosave() { // Now check if autosave file is newer. FileName const autosaveFile = getAutosaveFileName(); - if (!autosaveFile.exists() - || autosaveFile.lastModified() <= d->filename.lastModified()) + if (!autosaveFile.exists() + || autosaveFile.lastModified() <= d->filename.lastModified()) return ReadFileNotFound; docstring const file = makeDisplayPath(d->filename.absFileName(), 20); - docstring const text = bformat(_("The backup of the document %1$s " + docstring const text = bformat(_("The backup of the document %1$s " "is newer.\n\nLoad the backup instead?"), file); int const ret = Alert::prompt(_("Load backup?"), text, 0, 2, _("&Load backup"), _("Load &original"), _("&Cancel")); - + switch (ret) { case 0: { @@ -3770,7 +3983,7 @@ Buffer::ReadStatus Buffer::loadAutosave() bformat(_("A backup file is successfully loaded, " "but the original file %1$s is marked read-only. " "Please make sure to save the document as a " - "different file."), + "different file."), from_utf8(d->filename.absFileName()))); } markDirty(); @@ -3800,7 +4013,7 @@ Buffer::ReadStatus Buffer::loadLyXFile() ReadStatus const ret_re = loadEmergency(); if (ret_re == ReadSuccess || ret_re == ReadCancel) return ret_re; - + ReadStatus const ret_ra = loadAutosave(); if (ret_ra == ReadSuccess || ret_ra == ReadCancel) return ret_ra; @@ -3873,7 +4086,7 @@ void Buffer::bufferErrors(TeXErrors const & terr, ErrorList & errorList) const void Buffer::setBuffersForInsets() const { - inset().setBuffer(const_cast(*this)); + inset().setBuffer(const_cast(*this)); } @@ -3882,7 +4095,7 @@ void Buffer::updateBuffer(UpdateScope scope, UpdateType utype) const // Use the master text class also for child documents Buffer const * const master = masterBuffer(); DocumentClass const & textclass = master->params().documentClass(); - + // do this only if we are the top-level Buffer if (master == this) reloadBibInfoCache(); @@ -3896,7 +4109,7 @@ void Buffer::updateBuffer(UpdateScope scope, UpdateType utype) const if (master != this) { bufToUpdate.insert(this); master->updateBuffer(UpdateMaster, utype); - // Do this here in case the master has no gui associated with it. Then, + // 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->d->gui_) structureChanged(); @@ -4113,13 +4326,13 @@ void Buffer::Impl::setLabel(ParIterator & it, UpdateType utype) const if (counters.hasCounter(from_utf8(type))) { string const & lang = par.getParLanguage(bp)->code(); counters.step(from_utf8(type), utype); - full_label = bformat(from_ascii("%1$s %2$s:"), - name, + full_label = bformat(from_ascii("%1$s %2$s:"), + name, counters.theCounter(from_utf8(type), lang)); } else - full_label = bformat(from_ascii("%1$s #:"), name); + full_label = bformat(from_ascii("%1$s #:"), name); } - par.params().labelString(full_label); + par.params().labelString(full_label); break; } @@ -4130,7 +4343,7 @@ void Buffer::Impl::setLabel(ParIterator & it, UpdateType utype) const case LABEL_MANUAL: case LABEL_TOP_ENVIRONMENT: case LABEL_CENTERED_TOP_ENVIRONMENT: - case LABEL_STATIC: + case LABEL_STATIC: case LABEL_BIBLIO: par.params().labelString(par.expandLabel(layout, bp)); break; @@ -4160,7 +4373,7 @@ void Buffer::updateBuffer(ParIterator & parit, UpdateType utype) const masterBuffer()->params().documentClass().counters(). setActiveLayout(parit->layout()); } - + // set the counter for this paragraph d->setLabel(parit, utype); @@ -4182,8 +4395,9 @@ int Buffer::spellCheck(DocIterator & from, DocIterator & to, WordLangTuple wl; suggestions.clear(); word_lang = WordLangTuple(); + bool const to_end = to.empty(); + DocIterator const end = to_end ? doc_iterator_end(this) : to; // 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()) { @@ -4191,8 +4405,8 @@ int Buffer::spellCheck(DocIterator & from, DocIterator & to, 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) + // when leaving the mathed) LyX will crash later otherwise. + if (from.atEnd() || (!to_end && from >= end)) break; to = from; from.paragraph().spellCheck(); @@ -4232,7 +4446,7 @@ Buffer::ReadStatus Buffer::reload() d->undo_.clear(); } else { message(bformat(_("Could not reload document %1$s."), disp_fn)); - } + } setBusy(false); removePreviews(); updatePreviews();