X-Git-Url: https://git.lyx.org/gitweb/?a=blobdiff_plain;f=src%2FBuffer.cpp;h=1b52e248d9d5cf2d01a48b5b5add6109d5d6c89d;hb=489b80aef4d7904d667aeb06a32f2cc4ecbb75fa;hp=fbf288db42bd8ffca05cf3cd3b49f299586f681d;hpb=7a7ab8f14b4d297d52cc1c01e0e057f3768df29c;p=lyx.git diff --git a/src/Buffer.cpp b/src/Buffer.cpp index fbf288db42..1b52e248d9 100644 --- a/src/Buffer.cpp +++ b/src/Buffer.cpp @@ -147,7 +147,7 @@ class BufferSet : public std::set {}; class Buffer::Impl { public: - Impl(Buffer & parent, FileName const & file, bool readonly, Buffer const * cloned_buffer); + Impl(Buffer * owner, FileName const & file, bool readonly, Buffer const * cloned_buffer); ~Impl() { @@ -158,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; @@ -197,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; @@ -218,6 +238,8 @@ public: /// frontend::WorkAreaManager * wa_; + /// + frontend::GuiBufferDelegate * gui_; /// Undo undo_; @@ -248,7 +270,10 @@ 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; } @@ -289,17 +314,17 @@ static FileName createBufferTmpDir() } -Buffer::Impl::Impl(Buffer & parent, FileName const & file, bool readonly_, +Buffer::Impl::Impl(Buffer * owner, FileName const & file, bool readonly_, Buffer const * cloned_buffer) - : lyx_clean(true), bak_clean(true), unnamed(false), + : 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), bibinfo_cache_valid_(false), + 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(&parent); + lyxvc.setBuffer(owner_); if (use_gui) wa_ = new frontend::WorkAreaManager; return; @@ -315,7 +340,7 @@ Buffer::Impl::Impl(Buffer & parent, FileName const & file, bool readonly_, Buffer::Buffer(string const & file, bool readonly, Buffer const * cloned_buffer) - : d(new Impl(*this, FileName(file), readonly, cloned_buffer)), gui_(0) + : d(new Impl(this, FileName(file), readonly, cloned_buffer)) { LYXERR(Debug::INFO, "Buffer::Buffer()"); if (cloned_buffer) { @@ -341,7 +366,7 @@ Buffer::~Buffer() // saved properly, before it goes into the void. // GuiView already destroyed - gui_ = 0; + d->gui_ = 0; if (isInternal()) { // No need to do additional cleanups for internal buffer. @@ -407,6 +432,7 @@ Buffer * Buffer::clone() const child_clone->d->setParent(buffer_clone); buffer_clone->setChild(dit, child_clone); } + buffer_clone->d->macro_lock = false; return buffer_clone; } @@ -518,23 +544,23 @@ void Buffer::setChild(DocIterator const & dit, Buffer * child) 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; } @@ -599,7 +625,7 @@ void Buffer::setReadonly(bool const flag) { if (d->read_only != flag) { d->read_only = flag; - setReadOnly(flag); + changed(false); } } @@ -912,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); @@ -1487,21 +1520,21 @@ void Buffer::writeLyXHTMLSource(odocstream & os, { LaTeXFeatures features(*this, params(), runparams); validate(features); - updateLabels(UpdateMaster, true); + updateLabels(UpdateMaster, OutputUpdate); checkBibInfoCache(); d->bibinfo_.makeCitationLabels(*this); + updateMacros(); + updateMacroInstances(); if (!only_body) { os << "\n"; os << "\n"; // FIXME Language should be set properly. os << "\n"; - // FIXME Header 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.htmlTitle() << "\n"; os << "\n\n" << features.getTClassHTMLPreamble() @@ -1671,7 +1704,6 @@ BiblioInfo const & Buffer::masterBibInfo() const BiblioInfo const & Buffer::localBibInfo() const { - checkBibInfoCache(); return d->bibinfo_; } @@ -2204,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(), /**/); @@ -2245,12 +2271,6 @@ void Buffer::markClean() const } -void Buffer::markBakClean() const -{ - d->bak_clean = true; -} - - void Buffer::setUnnamed(bool flag) { d->unnamed = flag; @@ -2328,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)); } @@ -2345,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) @@ -2408,12 +2428,12 @@ std::vector Buffer::getChildren(bool grand_children) const 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(); @@ -2422,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); @@ -2432,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) { @@ -2463,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; @@ -2477,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; @@ -2489,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; } @@ -2506,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; @@ -2554,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) { @@ -2591,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; } @@ -2614,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? @@ -2628,8 +2647,8 @@ void Buffer::updateMacros(DocIterator & it, DocIterator & scope) const // register macro // FIXME (Abdel), I don't understandt why we pass 'it' here // instead of 'macroTemplate' defined above... is this correct? - d->macros[macroTemplate.name()][it] = - Impl::ScopeMacro(scope, MacroData(const_cast(this), it)); + macros[macroTemplate.name()][it] = + Impl::ScopeMacro(scope, MacroData(const_cast(owner_), it)); } // next paragraph @@ -2658,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); } @@ -2822,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(); @@ -2908,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); } @@ -2957,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; } @@ -3093,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; @@ -3104,7 +3117,8 @@ void Buffer::autoSave() const AutoSaveBuffer autosave(*this, getAutosaveFilename()); autosave.start(); - markBakClean(); + d->bak_clean = true; + resetAutosaveTimers(); } @@ -3255,20 +3269,23 @@ bool Buffer::doExport(string const & format, bool put_in_tempdir, 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()) { @@ -3489,11 +3506,15 @@ void Buffer::setBuffersForInsets() const } -void Buffer::updateLabels(UpdateScope scope, bool out) 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. @@ -3503,10 +3524,10 @@ void Buffer::updateLabels(UpdateScope scope, bool out) const // If this is a child document start with the master if (master != this) { bufToUpdate.insert(this); - master->updateLabels(UpdateMaster, out); + 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)? @@ -3531,7 +3552,7 @@ void Buffer::updateLabels(UpdateScope scope, bool out) const // do the real work ParIterator parit = cbuf.par_iterator_begin(); - updateLabels(parit, out); + updateLabels(parit, utype); if (master != this) // TocBackend update will be done later. @@ -3613,9 +3634,9 @@ static bool needEnumCounterReset(ParIterator const & it) // set the label of a paragraph. This includes the counters. -void Buffer::setLabel(ParIterator & it) const +void Buffer::Impl::setLabel(ParIterator & it, UpdateType utype) const { - BufferParams const & bp = this->masterBuffer()->params(); + BufferParams const & bp = owner_->masterBuffer()->params(); DocumentClass const & textclass = bp.documentClass(); Paragraph & par = it.paragraph(); Layout const & layout = par.layout(); @@ -3645,7 +3666,7 @@ void Buffer::setLabel(ParIterator & it) const 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 @@ -3699,7 +3720,7 @@ void Buffer::setLabel(ParIterator & it) const // 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)); @@ -3711,12 +3732,12 @@ void Buffer::setLabel(ParIterator & it) const string const & type = counters.current_float(); docstring full_label; if (type.empty()) - full_label = this->B_("Senseless!!! "); + full_label = owner_->B_("Senseless!!! "); else { - docstring name = this->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)); @@ -3742,7 +3763,7 @@ void Buffer::setLabel(ParIterator & it) const } -void Buffer::updateLabels(ParIterator & parit, bool out) const +void Buffer::updateLabels(ParIterator & parit, UpdateType utype) const { LASSERT(parit.pit() == 0, /**/); @@ -3759,15 +3780,23 @@ void Buffer::updateLabels(ParIterator & parit, bool out) 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(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, out); + iit->inset->updateLabels(parit, utype); } } }