X-Git-Url: https://git.lyx.org/gitweb/?a=blobdiff_plain;f=src%2FBuffer.cpp;h=1b52e248d9d5cf2d01a48b5b5add6109d5d6c89d;hb=489b80aef4d7904d667aeb06a32f2cc4ecbb75fa;hp=22970694c6e9359eb694db5a921b6e306763f8f5;hpb=74cd0fab481562ca233f2cf678d4fb4a7999ef84;p=lyx.git diff --git a/src/Buffer.cpp b/src/Buffer.cpp index 22970694c6..1b52e248d9 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 = 370; // uwestoehr: option to suppress default date +int const LYX_FORMAT = 376; // jspitzm: support for unincluded file maintenance 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 * owner, FileName const & file, bool readonly, Buffer const * cloned_buffer); ~Impl() { @@ -157,6 +158,25 @@ public: delete inset; } + /// search for macro in local (buffer) table or in children + MacroData const * getBufferMacro(docstring const & name, + DocIterator const & pos) const; + + /// Update macro table starting with position of it \param it in some + /// text inset. + void updateMacros(DocIterator & it, DocIterator & scope); + /// + void setLabel(ParIterator & it, UpdateType utype) const; + /// + void collectRelatives(BufferSet & bufs) const; + + /** If we have branches that use the file suffix + feature, return the file name with suffix appended. + */ + support::FileName exportFileName() const; + + Buffer * owner_; + BufferParams params; LyXVC lyxvc; FileName temppath; @@ -196,7 +216,8 @@ public: /// map from the macro name to the position map, /// which maps the macro definition position to the scope and the MacroData. NamePositionScopeMacroMap macros; - bool macro_lock; + /// This seem to change the way Buffer::getMacro() works + mutable bool macro_lock; /// positions of child buffers in the buffer typedef map BufferPositionMap; @@ -217,13 +238,15 @@ public: /// frontend::WorkAreaManager * wa_; + /// + frontend::GuiBufferDelegate * gui_; /// Undo undo_; /// A cache for the bibfiles (including bibfiles of loaded child /// documents), needed for appropriate update of natbib labels. - mutable support::FileNameList bibfilesCache_; + mutable support::FileNameList bibfiles_cache_; // FIXME The caching mechanism could be improved. At present, we have a // cache for each Buffer, that caches all the bibliography info for that @@ -232,9 +255,9 @@ public: /// A cache for bibliography info mutable BiblioInfo bibinfo_; /// whether the bibinfo cache is valid - bool bibinfoCacheValid_; + bool bibinfo_cache_valid_; /// Cache of timestamps of .bib files - map bibfileStatus_; + map bibfile_status_; mutable RefCache ref_cache_; @@ -247,15 +270,28 @@ public: // 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. - if (!theBufferList().isLoaded(parent_buffer)) + // however, the BufferList doesn't know about cloned buffers, so + // they will always be regarded as unloaded. in that case, we hope + // for the best. + if (!cloned_buffer_ && !theBufferList().isLoaded(parent_buffer)) parent_buffer = 0; 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 +314,46 @@ static FileName createBufferTmpDir() } -Buffer::Impl::Impl(Buffer & parent, FileName const & file, bool readonly_) - : lyx_clean(true), bak_clean(true), unnamed(false), +Buffer::Impl::Impl(Buffer * owner, FileName const & file, bool readonly_, + Buffer const * cloned_buffer) + : owner_(owner), lyx_clean(true), bak_clean(true), unnamed(false), read_only(readonly_), filename(file), file_fully_loaded(false), - toc_backend(&parent), macro_lock(false), timestamp_(0), - checksum_(0), wa_(0), undo_(parent), bibinfoCacheValid_(false), - parent_buffer(0) -{ - temppath = createBufferTmpDir(); - lyxvc.setBuffer(&parent); - if (use_gui) - wa_ = new frontend::WorkAreaManager; + toc_backend(owner), macro_lock(false), timestamp_(0), + checksum_(0), wa_(0), gui_(0), undo_(*owner), bibinfo_cache_valid_(false), + cloned_buffer_(cloned_buffer), parent_buffer(0) +{ + if (!cloned_buffer_) { + temppath = createBufferTmpDir(); + lyxvc.setBuffer(owner_); + if (use_gui) + wa_ = new frontend::WorkAreaManager; + return; + } + temppath = cloned_buffer_->d->temppath; + file_fully_loaded = true; + params = cloned_buffer_->d->params; + bibfiles_cache_ = cloned_buffer_->d->bibfiles_cache_; + bibinfo_ = cloned_buffer_->d->bibinfo_; + bibinfo_cache_valid_ = cloned_buffer_->d->bibinfo_cache_valid_; + bibfile_status_ = cloned_buffer_->d->bibfile_status_; } -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)) { LYXERR(Debug::INFO, "Buffer::Buffer()"); - - d->inset = new InsetText(*this); + if (cloned_buffer) { + d->inset = new InsetText(*cloned_buffer->d->inset); + d->inset->setBuffer(*this); + // FIXME: optimize this loop somewhat, maybe by creating a new + // general recursive Inset::setId(). + DocIterator it = doc_iterator_begin(this); + DocIterator cloned_it = doc_iterator_begin(cloned_buffer); + for (; !it.atEnd(); it.forwardPar(), cloned_it.forwardPar()) + it.paragraph().setId(cloned_it.paragraph().id()); + } else + d->inset = new InsetText(this); d->inset->setAutoBreakRows(true); d->inset->getText(0)->setMacrocontextPosition(par_iterator_begin()); } @@ -310,9 +366,9 @@ Buffer::~Buffer() // saved properly, before it goes into the void. // GuiView already destroyed - gui_ = 0; + d->gui_ = 0; - if (d->unnamed && d->filename.extension() == "internal") { + if (isInternal()) { // No need to do additional cleanups for internal buffer. delete d; return; @@ -323,22 +379,24 @@ Buffer::~Buffer() 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. - if (theBufferList().isLoaded(child)) + else 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(); - frontend::Alert::warning(_("Attempting to close changed document!"), msg); + 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()))); @@ -351,10 +409,44 @@ Buffer::~Buffer() } -void Buffer::changed() const +Buffer * Buffer::clone() const +{ + Buffer * buffer_clone = new Buffer(fileName().absFilename(), false, this); + buffer_clone->d->macro_lock = true; + buffer_clone->d->children_positions.clear(); + // FIXME (Abdel 09/01/2010): this is too complicated. The whole children_positions and + // math macro caches need to be rethought and simplified. + // I am not sure wether we should handle Buffer cloning here or in BufferList. + // Right now BufferList knows nothing about buffer clones. + Impl::BufferPositionMap::iterator it = d->children_positions.begin(); + Impl::BufferPositionMap::iterator end = d->children_positions.end(); + for (; it != end; ++it) { + DocIterator dit = it->second.clone(buffer_clone); + dit.setBuffer(buffer_clone); + Buffer * child = const_cast(it->first); + Buffer * child_clone = child->clone(); + Inset * inset = dit.nextInset(); + LASSERT(inset && inset->lyxCode() == INCLUDE_CODE, continue); + InsetInclude * inset_inc = static_cast(inset); + inset_inc->setChildBuffer(child_clone); + child_clone->d->setParent(buffer_clone); + buffer_clone->setChild(dit, child_clone); + } + buffer_clone->d->macro_lock = false; + return buffer_clone; +} + + +bool Buffer::isClone() const +{ + return d->cloned_buffer_; +} + + +void Buffer::changed(bool update_metrics) const { if (d->wa_) - d->wa_->redrawAll(); + d->wa_->redrawAll(update_metrics); } @@ -443,26 +535,32 @@ Undo & Buffer::undo() } +void Buffer::setChild(DocIterator const & dit, Buffer * child) +{ + d->children_positions[child] = dit; +} + + string Buffer::latexName(bool const no_path) const { FileName latex_name = - makeLatexName(exportFileName()); + makeLatexName(d->exportFileName()); return no_path ? latex_name.onlyFileName() : latex_name.absFilename(); } -FileName Buffer::exportFileName() const +FileName Buffer::Impl::exportFileName() const { docstring const branch_suffix = - params().branchlist().getFilenameSuffix(); + params.branchlist().getFilenameSuffix(); if (branch_suffix.empty()) - return fileName(); + return filename; - string const name = fileName().onlyFileNameWithoutExt() + string const name = filename.onlyFileNameWithoutExt() + to_utf8(branch_suffix); - FileName res(fileName().onlyPath().absFilename() + "/" + name); - res.changeExtension(fileName().extension()); + FileName res(filename.onlyPath().absFilename() + "/" + name); + res.changeExtension(filename.extension()); return res; } @@ -527,7 +625,7 @@ void Buffer::setReadonly(bool const flag) { if (d->read_only != flag) { d->read_only = flag; - setReadOnly(flag); + changed(false); } } @@ -566,6 +664,7 @@ int Buffer::readHeader(Lexer & lex) params().listings_params.clear(); params().clearLayoutModules(); params().clearRemovedModules(); + params().clearIncludedChildren(); params().pdfoptions().clear(); params().indiceslist().clear(); params().backgroundcolor = lyx::rgbFromHexName("#ffffff"); @@ -700,6 +799,7 @@ bool Buffer::readDocument(Lexer & lex) // read main text bool const res = text().read(lex, errorList, d->inset); + usermacros.clear(); updateMacros(); updateMacroInstances(); return res; @@ -838,11 +938,18 @@ Buffer::ReadStatus Buffer::readFile(Lexer & lex, FileName const & filename, cmd_ret const ret = runCommand(command_str); if (ret.first != 0) { - Alert::error(_("Conversion script failed"), - bformat(_("%1$s is from a different version" + if (file_format < LYX_FORMAT) + Alert::error(_("Conversion script failed"), + bformat(_("%1$s is from an older version" " of LyX, but the lyx2lyx script" " failed to convert it."), from_utf8(filename.absFilename()))); + else + Alert::error(_("Conversion script failed"), + bformat(_("%1$s is from a newer version" + " of LyX and cannot be converted by the" + " lyx2lyx script."), + from_utf8(filename.absFilename()))); return failure; } else { bool const ret = readFile(tmpfile); @@ -1217,7 +1324,9 @@ void Buffer::writeLaTeXSource(odocstream & os, listParentMacros(parentMacros, features); // Write the preamble - runparams.use_babel = params().writeLaTeX(os, features, d->texrow); + runparams.use_babel = params().writeLaTeX(os, features, + d->texrow, + d->filename.onlyPath()); runparams.use_japanese = features.isRequired("japanese"); @@ -1391,7 +1500,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)) @@ -1411,36 +1520,40 @@ void Buffer::writeLyXHTMLSource(odocstream & os, { LaTeXFeatures features(*this, params(), runparams); validate(features); - - d->texrow.reset(); + updateLabels(UpdateMaster, OutputUpdate); + checkBibInfoCache(); + d->bibinfo_.makeCitationLabels(*this); + updateMacros(); + updateMacroInstances(); if (!only_body) { - os << "\n"; + os << "\n"; + os << "\n"; // FIXME Language should be set properly. - os << "\n"; - // FIXME Header + os << "\n"; os << "\n"; // FIXME Presumably need to set this right os << "\n"; - // FIXME Get this during validation? What about other meta-data? - os << "TBA\n"; - - os << features.getTClassHTMLPreamble(); + os << "" << features.htmlTitle() << "\n"; - 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(text(), *this, os, runparams); + xhtmlParagraphs(text(), *this, xs, runparams); if (!only_body) os << "\n\n"; } @@ -1531,13 +1644,13 @@ void Buffer::updateBibfilesCache(UpdateScope scope) const return; } - d->bibfilesCache_.clear(); + d->bibfiles_cache_.clear(); for (InsetIterator it = inset_iterator_begin(inset()); it; ++it) { if (it->lyxCode() == BIBTEX_CODE) { InsetBibtex const & inset = static_cast(*it); support::FileNameList const bibfiles = inset.getBibFiles(); - d->bibfilesCache_.insert(d->bibfilesCache_.end(), + d->bibfiles_cache_.insert(d->bibfiles_cache_.end(), bibfiles.begin(), bibfiles.end()); } else if (it->lyxCode() == INCLUDE_CODE) { @@ -1546,19 +1659,19 @@ void Buffer::updateBibfilesCache(UpdateScope scope) const inset.updateBibfilesCache(); support::FileNameList const & bibfiles = inset.getBibfilesCache(); - d->bibfilesCache_.insert(d->bibfilesCache_.end(), + d->bibfiles_cache_.insert(d->bibfiles_cache_.end(), bibfiles.begin(), bibfiles.end()); } } // the bibinfo cache is now invalid - d->bibinfoCacheValid_ = false; + d->bibinfo_cache_valid_ = false; } void Buffer::invalidateBibinfoCache() { - d->bibinfoCacheValid_ = false; + d->bibinfo_cache_valid_ = false; } @@ -1570,10 +1683,10 @@ support::FileNameList const & Buffer::getBibfilesCache(UpdateScope scope) const return pbuf->getBibfilesCache(); // We update the cache when first used instead of at loading time. - if (d->bibfilesCache_.empty()) + if (d->bibfiles_cache_.empty()) const_cast(this)->updateBibfilesCache(scope); - return d->bibfilesCache_; + return d->bibfiles_cache_; } @@ -1591,28 +1704,31 @@ BiblioInfo const & Buffer::masterBibInfo() const BiblioInfo const & Buffer::localBibInfo() const { - if (d->bibinfoCacheValid_) { - support::FileNameList const & bibfilesCache = getBibfilesCache(); - // compare the cached timestamps with the actual ones. - support::FileNameList::const_iterator ei = bibfilesCache.begin(); - support::FileNameList::const_iterator en = bibfilesCache.end(); - for (; ei != en; ++ ei) { - time_t lastw = ei->lastModified(); - if (lastw != d->bibfileStatus_[*ei]) { - d->bibinfoCacheValid_ = false; - d->bibfileStatus_[*ei] = lastw; - break; - } + return d->bibinfo_; +} + + +void Buffer::checkBibInfoCache() const +{ + support::FileNameList const & bibfilesCache = getBibfilesCache(); + // compare the cached timestamps with the actual ones. + support::FileNameList::const_iterator ei = bibfilesCache.begin(); + support::FileNameList::const_iterator en = bibfilesCache.end(); + for (; ei != en; ++ ei) { + time_t lastw = ei->lastModified(); + time_t prevw = d->bibfile_status_[*ei]; + if (lastw != prevw) { + d->bibinfo_cache_valid_ = false; + d->bibfile_status_[*ei] = lastw; } } - if (!d->bibinfoCacheValid_) { + if (!d->bibinfo_cache_valid_) { d->bibinfo_.clear(); for (InsetIterator it = inset_iterator_begin(inset()); it; ++it) it->fillWithBibKeys(d->bibinfo_, it); - d->bibinfoCacheValid_ = true; - } - return d->bibinfo_; + d->bibinfo_cache_valid_ = true; + } } @@ -1631,25 +1747,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; } @@ -1657,12 +1817,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; } @@ -1678,12 +1842,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, false); dr.setError(success); if (!success) dr.setMessage(bformat(_("Error exporting to format: %1$s."), @@ -1691,22 +1870,84 @@ void Buffer::dispatch(FuncRequest const & func, DispatchResult & dr) break; } + case LFUN_BUILD_PROGRAM: + doExport("program", true, false); + 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, false, 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); } @@ -1796,7 +2037,10 @@ void Buffer::dispatch(FuncRequest const & func, DispatchResult & dr) break; } - if (!doExport("dvi", true)) { + bool const update_unincluded = + params().maintain_unincluded_children + && !params().getIncludedChildren().empty(); + if (!doExport("dvi", true, update_unincluded)) { showPrintError(absFileName()); dr.setMessage(_("Error exporting to DVI.")); break; @@ -1886,11 +2130,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(); } @@ -1981,12 +2236,6 @@ bool Buffer::isClean() const } -bool Buffer::isBakClean() const -{ - return d->bak_clean; -} - - bool Buffer::isExternallyModified(CheckMethod method) const { LASSERT(d->filename.exists(), /**/); @@ -2022,12 +2271,6 @@ void Buffer::markClean() const } -void Buffer::markBakClean() const -{ - d->bak_clean = true; -} - - void Buffer::setUnnamed(bool flag) { d->unnamed = flag; @@ -2040,7 +2283,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) { @@ -2095,15 +2348,15 @@ Buffer const * Buffer::parent() const } -void Buffer::collectRelatives(BufferSet & bufs) const +void Buffer::Impl::collectRelatives(BufferSet & bufs) const { - bufs.insert(this); + bufs.insert(owner_); if (parent()) - parent()->collectRelatives(bufs); + parent()->d->collectRelatives(bufs); // loop over children - Impl::BufferPositionMap::iterator it = d->children_positions.begin(); - Impl::BufferPositionMap::iterator end = d->children_positions.end(); + BufferPositionMap::const_iterator it = children_positions.begin(); + BufferPositionMap::const_iterator end = children_positions.end(); for (; it != end; ++it) bufs.insert(const_cast(it->first)); } @@ -2112,7 +2365,7 @@ void Buffer::collectRelatives(BufferSet & bufs) const std::vector Buffer::allRelatives() const { BufferSet bufs; - collectRelatives(bufs); + d->collectRelatives(bufs); BufferSet::iterator it = bufs.begin(); std::vector ret; for (; it != bufs.end(); ++it) @@ -2147,32 +2400,40 @@ 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; } template -typename M::iterator greatest_below(M & m, typename M::key_type const & x) +typename M::const_iterator greatest_below(M & m, typename M::key_type const & x) { if (m.empty()) return m.end(); - typename M::iterator it = m.lower_bound(x); + typename M::const_iterator it = m.lower_bound(x); if (it == m.begin()) return m.end(); @@ -2181,7 +2442,7 @@ typename M::iterator greatest_below(M & m, typename M::key_type const & x) } -MacroData const * Buffer::getBufferMacro(docstring const & name, +MacroData const * Buffer::Impl::getBufferMacro(docstring const & name, DocIterator const & pos) const { LYXERR(Debug::MACROS, "Searching for " << to_ascii(name) << " at " << pos); @@ -2191,15 +2452,14 @@ MacroData const * Buffer::getBufferMacro(docstring const & name, return 0; // we haven't found anything yet - DocIterator bestPos = par_iterator_begin(); + DocIterator bestPos = owner_->par_iterator_begin(); MacroData const * bestData = 0; // find macro definitions for name - Impl::NamePositionScopeMacroMap::iterator nameIt - = d->macros.find(name); - if (nameIt != d->macros.end()) { + NamePositionScopeMacroMap::const_iterator nameIt = macros.find(name); + if (nameIt != macros.end()) { // find last definition in front of pos or at pos itself - Impl::PositionScopeMacroMap::const_iterator it + PositionScopeMacroMap::const_iterator it = greatest_below(nameIt->second, pos); if (it != nameIt->second.end()) { while (true) { @@ -2222,9 +2482,9 @@ MacroData const * Buffer::getBufferMacro(docstring const & name, } // find macros in included files - Impl::PositionScopeBufferMap::const_iterator it - = greatest_below(d->position_to_children, pos); - if (it == d->position_to_children.end()) + PositionScopeBufferMap::const_iterator it + = greatest_below(position_to_children, pos); + if (it == position_to_children.end()) // no children before return bestData; @@ -2236,10 +2496,10 @@ MacroData const * Buffer::getBufferMacro(docstring const & name, // scope ends behind pos? if (pos < it->second.first) { // look for macro in external file - d->macro_lock = true; + macro_lock = true; MacroData const * data - = it->second.second->getMacro(name, false); - d->macro_lock = false; + = it->second.second->getMacro(name, false); + macro_lock = false; if (data) { bestPos = it->first; bestData = data; @@ -2248,7 +2508,7 @@ MacroData const * Buffer::getBufferMacro(docstring const & name, } // try previous file if there is one - if (it == d->position_to_children.begin()) + if (it == position_to_children.begin()) break; --it; } @@ -2265,7 +2525,7 @@ MacroData const * Buffer::getMacro(docstring const & name, return 0; // query buffer macros - MacroData const * data = getBufferMacro(name, pos); + MacroData const * data = d->getBufferMacro(name, pos); if (data != 0) return data; @@ -2313,9 +2573,9 @@ MacroData const * Buffer::getMacro(docstring const & name, } -void Buffer::updateMacros(DocIterator & it, DocIterator & scope) const +void Buffer::Impl::updateMacros(DocIterator & it, DocIterator & scope) { - pit_type lastpit = it.lastpit(); + pit_type const lastpit = it.lastpit(); // look for macros in each paragraph while (it.pit() <= lastpit) { @@ -2350,20 +2610,20 @@ void Buffer::updateMacros(DocIterator & it, DocIterator & scope) const // get buffer of external file InsetInclude const & inset = static_cast(*iit->inset); - d->macro_lock = true; + macro_lock = true; Buffer * child = inset.getChildBuffer(); - d->macro_lock = false; + macro_lock = false; if (!child) continue; // register its position, but only when it is // included first in the buffer - if (d->children_positions.find(child) == - d->children_positions.end()) - d->children_positions[child] = it; + if (children_positions.find(child) == + children_positions.end()) + children_positions[child] = it; // register child with its scope - d->position_to_children[it] = Impl::ScopeBuffer(scope, child); + position_to_children[it] = Impl::ScopeBuffer(scope, child); continue; } @@ -2373,7 +2633,7 @@ void Buffer::updateMacros(DocIterator & it, DocIterator & scope) const // get macro data MathMacroTemplate & macroTemplate = static_cast(*iit->inset); - MacroContext mc(*this, it); + MacroContext mc(owner_, it); macroTemplate.updateToContext(mc); // valid? @@ -2385,8 +2645,10 @@ void Buffer::updateMacros(DocIterator & it, DocIterator & scope) const continue; // register macro - d->macros[macroTemplate.name()][it] = - Impl::ScopeMacro(scope, MacroData(*this, it)); + // FIXME (Abdel), I don't understandt why we pass 'it' here + // instead of 'macroTemplate' defined above... is this correct? + macros[macroTemplate.name()][it] = + Impl::ScopeMacro(scope, MacroData(const_cast(owner_), it)); } // next paragraph @@ -2415,7 +2677,7 @@ void Buffer::updateMacros() const DocIterator it = par_iterator_begin(); DocIterator outerScope = it; outerScope.pit() = outerScope.lastpit() + 2; - updateMacros(it, outerScope); + d->updateMacros(it, outerScope); } @@ -2453,20 +2715,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); @@ -2582,6 +2841,7 @@ void Buffer::changeRefsIfUnique(docstring const & from, docstring const & to, // Check if the label 'from' appears more than once vector labels; string paramName; + checkBibInfoCache(); BiblioInfo const & keys = masterBibInfo(); BiblioInfo::const_iterator bit = keys.begin(); BiblioInfo::const_iterator bend = keys.end(); @@ -2668,43 +2928,36 @@ ErrorList & Buffer::errorList(string const & type) const void Buffer::updateTocItem(std::string const & type, DocIterator const & dit) const { - if (gui_) - gui_->updateTocItem(type, dit); + if (d->gui_) + d->gui_->updateTocItem(type, dit); } void Buffer::structureChanged() const { - if (gui_) - gui_->structureChanged(); + if (d->gui_) + d->gui_->structureChanged(); } void Buffer::errors(string const & err, bool from_master) const { - if (gui_) - gui_->errors(err, from_master); + if (d->gui_) + d->gui_->errors(err, from_master); } void Buffer::message(docstring const & msg) const { - if (gui_) - gui_->message(msg); + if (d->gui_) + d->gui_->message(msg); } void Buffer::setBusy(bool on) const { - if (gui_) - gui_->setBusy(on); -} - - -void Buffer::setReadOnly(bool on) const -{ - if (d->wa_) - d->wa_->setReadOnly(on); + if (d->gui_) + d->gui_->setBusy(on); } @@ -2717,20 +2970,20 @@ void Buffer::updateTitles() const void Buffer::resetAutosaveTimers() const { - if (gui_) - gui_->resetAutosaveTimers(); + if (d->gui_) + d->gui_->resetAutosaveTimers(); } bool Buffer::hasGuiDelegate() const { - return gui_; + return d->gui_; } void Buffer::setGuiDelegate(frontend::GuiBufferDelegate * gui) { - gui_ = gui; + d->gui_ = gui; } @@ -2765,6 +3018,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 @@ -2774,6 +3036,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 @@ -2843,7 +3106,7 @@ void Buffer::moveAutosaveFile(support::FileName const & oldauto) const // Perfect target for a thread... void Buffer::autoSave() const { - if (isBakClean() || isReadonly()) { + if (d->bak_clean || isReadonly()) { // We don't save now, but we'll try again later resetAutosaveTimers(); return; @@ -2854,7 +3117,8 @@ void Buffer::autoSave() const AutoSaveBuffer autosave(*this, getAutosaveFilename()); autosave.start(); - markBakClean(); + d->bak_clean = true; + resetAutosaveTimers(); } @@ -2894,12 +3158,13 @@ string Buffer::getDefaultOutputFormat() const bool Buffer::doExport(string const & format, bool put_in_tempdir, - string & result_file) const + bool includeall, string & result_file) const { string backend_format; OutputParams runparams(¶ms().encoding()); runparams.flavor = OutputParams::LATEX; runparams.linelen = lyxrc.plaintext_linelen; + runparams.includeall = includeall; vector backs = backends(); if (find(backs.begin(), backs.end(), format) == backs.end()) { // Get shortest path to format @@ -2912,14 +3177,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 @@ -2936,12 +3205,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()) { @@ -2984,25 +3256,36 @@ bool Buffer::doExport(string const & format, bool put_in_tempdir, if (!success) return false; + if (d->cloned_buffer_) { + // Enable reverse dvi or pdf to work by copying back the texrow + // object to the cloned buffer. + // FIXME: There is a possibility of concurrent access to texrow + // here from the main GUI thread that should be securized. + d->cloned_buffer_->d->texrow = d->texrow; + } + if (put_in_tempdir) { result_file = tmp_result_file.absFilename(); return true; } - result_file = changeExtension(exportFileName().absFilename(), ext); + result_file = changeExtension(d->exportFileName().absFilename(), ext); // 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); CopyStatus status = SUCCESS; - for (vector::const_iterator it = files.begin(); - it != files.end() && status != CANCEL; ++it) { + + 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); status = copyFile(fmt, it->sourceName, makeAbsPath(it->exportName, dest), it->exportName, status == FORCE); } + if (status == CANCEL) { message(_("Document export cancelled.")); } else if (tmp_result_file.exists()) { @@ -3024,17 +3307,26 @@ bool Buffer::doExport(string const & format, bool put_in_tempdir, } -bool Buffer::doExport(string const & format, bool put_in_tempdir) const +bool Buffer::doExport(string const & format, bool put_in_tempdir, + bool includeall) const { string result_file; - return doExport(format, put_in_tempdir, 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 Buffer::preview(string const & format) const +bool Buffer::preview(string const & format, bool includeall) const { string result_file; - if (!doExport(format, true, result_file)) + // (1) export with all included children (omit \includeonly) + if (includeall && !doExport(format, true, true)) + return false; + // (2) export with included children only + if (!doExport(format, true, false, result_file)) return false; return formats.view(*this, FileName(result_file), format); } @@ -3053,7 +3345,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; @@ -3069,14 +3361,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; } @@ -3116,7 +3406,8 @@ bool Buffer::readFileHelper(FileName const & s) str = _("Document was successfully recovered."); else str = _("Document was NOT successfully recovered."); - str += "\n\n" + _("Remove emergency file now?"); + 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"))) { @@ -3169,31 +3460,17 @@ bool Buffer::readFileHelper(FileName const & s) bool Buffer::loadLyXFile(FileName const & s) { - if (s.isReadableFile()) { - if (readFileHelper(s)) { - lyxvc().file_found_hook(s); - if (!s.isWritable()) - setReadonly(true); - return true; - } - } else { - docstring const file = makeDisplayPath(s.absFilename(), 20); - // Here we probably should run - if (LyXVC::file_not_found_hook(s)) { - docstring const text = - bformat(_("Do you want to retrieve the document" - " %1$s from version control?"), file); - int const ret = Alert::prompt(_("Retrieve from version control?"), - text, 0, 1, _("&Retrieve"), _("&Cancel")); - - if (ret == 0) { - // How can we know _how_ to do the checkout? - // With the current VC support it has to be, - // a RCS file since CVS do not have special ,v files. - RCS::retrieve(s); - return loadLyXFile(s); - } - } + // If the file is not readable, we try to + // retrieve the file from version control. + if (!s.isReadableFile() + && !LyXVC::file_not_found_hook(s)) + return false; + + if (s.isReadableFile() + && readFileHelper(s)) { + lyxvc().file_found_hook(s); + setReadonly(!s.isWritable()); + return true; } return false; } @@ -3229,11 +3506,15 @@ void Buffer::setBuffersForInsets() const } -void Buffer::updateLabels(UpdateScope scope) const +void Buffer::updateLabels(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 (scope != UpdateMaster || master == this) + checkBibInfoCache(); // keep the buffers to be children in this set. If the call from the // master comes back we can see which of them were actually seen (i.e. @@ -3243,10 +3524,10 @@ 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, utype); // 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_) + if (!master->d->gui_) structureChanged(); // was buf referenced from the master (i.e. not in bufToUpdate anymore)? @@ -3271,7 +3552,7 @@ void Buffer::updateLabels(UpdateScope scope) const // do the real work ParIterator parit = cbuf.par_iterator_begin(); - updateLabels(parit); + updateLabels(parit, utype); if (master != this) // TocBackend update will be done later. @@ -3353,9 +3634,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::Impl::setLabel(ParIterator & it, UpdateType utype) const { - BufferParams const & bp = buf.masterBuffer()->params(); + BufferParams const & bp = owner_->masterBuffer()->params(); DocumentClass const & textclass = bp.documentClass(); Paragraph & par = it.paragraph(); Layout const & layout = par.layout(); @@ -3363,7 +3644,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); } @@ -3385,7 +3666,7 @@ static void setLabel(Buffer const & buf, ParIterator & it) if (layout.toclevel <= bp.secnumdepth && (layout.latextype != LATEX_ENVIRONMENT || it.text()->isFirstInSequence(it.pit()))) { - counters.step(layout.counter); + counters.step(layout.counter, utype); par.params().labelString( par.expandLabel(layout, bp)); } else @@ -3439,7 +3720,7 @@ static void setLabel(Buffer const & buf, ParIterator & it) // Maybe we have to reset the enumeration counter. if (needEnumCounterReset(it)) counters.reset(enumcounter); - counters.step(enumcounter); + counters.step(enumcounter, utype); string const & lang = par.getParLanguage(bp)->code(); par.params().labelString(counters.theCounter(enumcounter, lang)); @@ -3451,12 +3732,12 @@ 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 = owner_->B_("Senseless!!! "); else { - docstring name = buf.B_(textclass.floats().getType(type).name()); + docstring name = owner_->B_(textclass.floats().getType(type).name()); if (counters.hasCounter(from_utf8(type))) { string const & lang = par.getParLanguage(bp)->code(); - counters.step(from_utf8(type)); + counters.step(from_utf8(type), utype); full_label = bformat(from_ascii("%1$s %2$s:"), name, counters.theCounter(from_utf8(type), lang)); @@ -3482,7 +3763,7 @@ static void setLabel(Buffer const & buf, ParIterator & it) } -void Buffer::updateLabels(ParIterator & parit) const +void Buffer::updateLabels(ParIterator & parit, UpdateType utype) const { LASSERT(parit.pit() == 0, /**/); @@ -3499,15 +3780,23 @@ void Buffer::updateLabels(ParIterator & parit) const parit->params().depth(min(parit->params().depth(), maxdepth)); maxdepth = parit->getMaxDepthAfter(); + if (utype == OutputUpdate) { + // track the active counters + // we have to do this for the master buffer, since the local + // buffer isn't tracking anything. + masterBuffer()->params().documentClass().counters(). + setActiveLayout(parit->layout()); + } + // set the counter for this paragraph - setLabel(*this, parit); + d->setLabel(parit, utype); - // Now the insets + // 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, utype); } } } @@ -3524,17 +3813,51 @@ 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; } + +bool Buffer::reload() +{ + setBusy(true); + // e.g., read-only status could have changed due to version control + d->filename.refresh(); + docstring const disp_fn = makeDisplayPath(d->filename.absFilename()); + + bool const success = loadLyXFile(d->filename); + if (success) { + updateLabels(); + changed(true); + markClean(); + message(bformat(_("Document %1$s reloaded."), disp_fn)); + } else { + message(bformat(_("Could not reload document %1$s."), disp_fn)); + } + setBusy(false); + errors("Parse"); + return success; +} + + } // namespace lyx