LyXVC lyxvc;
FileName temppath;
mutable TexRow texrow;
- Buffer const * parent_buffer;
/// need to regenerate .tex?
DepClean dep_clean;
/// our Text that should be wrapped in an InsetText
InsetText * inset;
+
+ /// This is here to force the test to be done whenever parent_buffer
+ /// is accessed.
+ 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.
+ if (!theBufferList().isLoaded(parent_buffer))
+ parent_buffer = 0;
+ return parent_buffer;
+ }
+ ///
+ void setParent(Buffer const * pb) { parent_buffer = pb; }
+private:
+ /// So we can force access via the accessors.
+ mutable Buffer const * parent_buffer;
};
Buffer::Impl::Impl(Buffer & parent, FileName const & file, bool readonly_)
- : parent_buffer(0), lyx_clean(true), bak_clean(true), unnamed(false),
+ : 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)
+ checksum_(0), wa_(0), undo_(parent), bibinfoCacheValid_(false),
+ parent_buffer(0)
{
temppath = createBufferTmpDir();
lyxvc.setBuffer(&parent);
Buffer * master =
checkAndLoadLyXFile(master_file, true);
if (master) {
+ // necessary e.g. after a reload
+ // to re-register the child (bug 5873)
+ // FIXME: clean up updateMacros (here, only
+ // child registering is needed).
+ master->updateMacros();
// set master as master buffer, but only
// if we are a real child
if (master->isChild(this))
else if (master->isFullyLoaded())
LYXERR0("The master '"
<< params().master
- << "' assigned to this document '"
+ << "' assigned to this document ("
<< absFileName()
- << "' does not include "
+ << ") does not include "
"this document. Ignoring the master assignment.");
}
}
bformat(_("%1$s is from a different"
" version of LyX, but a temporary"
" file for converting it could"
- " not be created."),
+ " not be created."),
from_utf8(filename.absFilename())));
return failure;
}
bformat(_("%1$s is from a different"
" version of LyX, but the"
" conversion script lyx2lyx"
- " could not be found."),
+ " could not be found."),
from_utf8(filename.absFilename())));
return failure;
}
Alert::error(_("Conversion script failed"),
bformat(_("%1$s is from a different version"
" of LyX, but the lyx2lyx script"
- " failed to convert it."),
+ " failed to convert it."),
from_utf8(filename.absFilename())));
return failure;
} else {
// This happens for example if only a child document is printed.
Buffer const * save_parent = 0;
if (output_preamble) {
- save_parent = d->parent_buffer;
- d->parent_buffer = 0;
+ save_parent = d->parent();
+ d->setParent(0);
}
// the real stuff
// Restore the parenthood if needed
if (output_preamble)
- d->parent_buffer = save_parent;
+ d->setParent(save_parent);
// add this just in case after all the paragraphs
os << endl;
void Buffer::getLabelList(vector<docstring> & list) const
{
// If this is a child document, use the parent's list instead.
- if (d->parent_buffer) {
- d->parent_buffer->getLabelList(list);
+ Buffer const * const pbuf = d->parent();
+ if (pbuf) {
+ pbuf->getLabelList(list);
return;
}
}
-void Buffer::updateBibfilesCache() const
+void Buffer::updateBibfilesCache(UpdateScope scope) const
{
// If this is a child document, use the parent's cache instead.
- if (d->parent_buffer) {
- d->parent_buffer->updateBibfilesCache();
+ Buffer const * const pbuf = d->parent();
+ if (pbuf && scope != UpdateChildOnly) {
+ pbuf->updateBibfilesCache();
return;
}
static_cast<InsetInclude &>(*it);
inset.updateBibfilesCache();
support::FileNameList const & bibfiles =
- inset.getBibfilesCache(*this);
+ inset.getBibfilesCache();
d->bibfilesCache_.insert(d->bibfilesCache_.end(),
bibfiles.begin(),
bibfiles.end());
}
-support::FileNameList const & Buffer::getBibfilesCache() const
+support::FileNameList const & Buffer::getBibfilesCache(UpdateScope scope) const
{
// If this is a child document, use the parent's cache instead.
- if (d->parent_buffer)
- return d->parent_buffer->getBibfilesCache();
+ Buffer const * const pbuf = d->parent();
+ if (pbuf && scope != UpdateChildOnly)
+ return pbuf->getBibfilesCache();
// We update the cache when first used instead of at loading time.
if (d->bibfilesCache_.empty())
- const_cast<Buffer *>(this)->updateBibfilesCache();
+ const_cast<Buffer *>(this)->updateBibfilesCache(scope);
return d->bibfilesCache_;
}
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.");
void Buffer::setParent(Buffer const * buffer)
{
// Avoids recursive include.
- d->parent_buffer = buffer == this ? 0 : buffer;
+ d->setParent(buffer == this ? 0 : buffer);
updateMacros();
}
Buffer const * Buffer::parent() const
{
- return d->parent_buffer;
+ return d->parent();
}
Buffer const * Buffer::masterBuffer() const
{
- if (!d->parent_buffer)
+ Buffer const * const pbuf = d->parent();
+ if (!pbuf)
return this;
- return d->parent_buffer->masterBuffer();
+ return pbuf->masterBuffer();
}
}
+std::vector<Buffer *> Buffer::getChildren() const
+{
+ std::vector<Buffer *> 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<Buffer *>(it->first);
+ clist.push_back(child);
+ // there might be grandchildren
+ std::vector<Buffer *> glist = child->getChildren();
+ for (vector<Buffer *>::const_iterator git = glist.begin();
+ git != glist.end(); ++git)
+ clist.push_back(*git);
+ }
+ return clist;
+}
+
+
template<typename M>
typename M::iterator greatest_below(M & m, typename M::key_type const & x)
{
return data;
// If there is a master buffer, query that
- if (d->parent_buffer) {
+ Buffer const * const pbuf = d->parent();
+ if (pbuf) {
d->macro_lock = true;
- MacroData const * macro = d->parent_buffer->getMacro(
+ MacroData const * macro = pbuf->getMacro(
name, *this, false);
d->macro_lock = false;
if (macro)
// is it a nested text inset?
if (iit->inset->asInsetText()) {
// Inset needs its own scope?
- InsetText const * itext
- = iit->inset->asInsetText();
+ InsetText const * itext = iit->inset->asInsetText();
bool newScope = itext->isMacroScope();
// scope which ends just behind the inset
// is it an external file?
if (iit->inset->lyxCode() == INCLUDE_CODE) {
// get buffer of external file
- InsetInclude const & inset
- = static_cast<InsetInclude const &>(*iit->inset);
+ InsetInclude const & inset =
+ static_cast<InsetInclude const &>(*iit->inset);
d->macro_lock = true;
- Buffer * child = inset.loadIfNeeded(*this);
+ Buffer * child = inset.getChildBuffer();
d->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 (d->children_positions.find(child) ==
+ d->children_positions.end())
+ d->children_positions[child] = it;
// register child with its scope
d->position_to_children[it] = Impl::ScopeBuffer(scope, child);
continue;
// get macro data
- MathMacroTemplate & macroTemplate
- = static_cast<MathMacroTemplate &>(*iit->inset);
+ MathMacroTemplate & macroTemplate =
+ static_cast<MathMacroTemplate &>(*iit->inset);
MacroContext mc(*this, it);
macroTemplate.updateToContext(mc);
it->first->listMacroNames(macros);
// call parent
- if (d->parent_buffer)
- d->parent_buffer->listMacroNames(macros);
+ Buffer const * const pbuf = d->parent();
+ if (pbuf)
+ pbuf->listMacroNames(macros);
d->macro_lock = false;
}
void Buffer::listParentMacros(MacroSet & macros, LaTeXFeatures & features) const
{
- if (!d->parent_buffer)
+ Buffer const * const pbuf = d->parent();
+ if (!pbuf)
return;
MacroNameSet names;
- d->parent_buffer->listMacroNames(names);
+ pbuf->listMacroNames(names);
// resolve macros
MacroNameSet::iterator it = names.begin();
for (; it != end; ++it) {
// defined?
MacroData const * data =
- d->parent_buffer->getMacro(*it, *this, false);
+ pbuf->getMacro(*it, *this, false);
if (data) {
macros.insert(data);
Buffer::References & Buffer::references(docstring const & label)
{
- if (d->parent_buffer)
+ if (d->parent())
return const_cast<Buffer *>(masterBuffer())->references(label);
RefCache::iterator it = d->ref_cache_.find(label);
void Buffer::clearReferenceCache() const
{
- if (!d->parent_buffer)
+ if (!d->parent())
d->ref_cache_.clear();
}
}
-void Buffer::updateLabels(bool childonly) const
+void Buffer::setBuffersForInsets() const
+{
+ inset().setBuffer(const_cast<Buffer &>(*this));
+}
+
+
+void Buffer::updateLabels(UpdateScope scope) const
{
// Use the master text class also for child documents
Buffer const * const master = masterBuffer();
// master comes back we can see which of them were actually seen (i.e.
// via an InsetInclude). The remaining ones in the set need still be updated.
static std::set<Buffer const *> bufToUpdate;
- if (!childonly) {
+ if (scope == UpdateMaster) {
// If this is a child document start with the master
if (master != this) {
bufToUpdate.insert(this);
- master->updateLabels(false);
+ master->updateLabels();
// 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_)
// update all caches
clearReferenceCache();
- inset().setBuffer(const_cast<Buffer &>(*this));
updateMacros();
Buffer & cbuf = const_cast<Buffer &>(*this);
return;
cbuf.tocBackend().update();
- if (!childonly)
+ if (scope == UpdateMaster)
cbuf.structureChanged();
}
}
}
+
+bool Buffer::nextWord(DocIterator & from, DocIterator & to,
+ docstring & word) const
+{
+ bool inword = false;
+ bool ignoreword = false;
+ string lang_code;
+ to = from;
+
+ while (to.depth()) {
+ if (isLetter(to)) {
+ if (!inword) {
+ inword = true;
+ ignoreword = false;
+ from = to;
+ word.clear();
+ lang_code = to.paragraph().getFontSettings(params(),
+ to.pos()).language()->code();
+ }
+ // Insets like optional hyphens and ligature
+ // break are part of a word.
+ if (!to.paragraph().isInset(to.pos())) {
+ char_type const c = to.paragraph().getChar(to.pos());
+ word += c;
+ if (isDigit(c))
+ ignoreword = true;
+ }
+ } else { // !isLetter(cur)
+ if (inword && !word.empty() && !ignoreword)
+ return true;
+ inword = false;
+ }
+ to.forwardPos();
+ }
+
+ return false;
+}
+
} // namespace lyx