mutable bool bibfile_cache_valid_;
/// Cache of timestamps of .bib files
map<FileName, time_t> bibfile_status_;
+ /// Indicates whether the bibinfo has changed since the last time
+ /// we ran updateBuffer(), i.e., whether citation labels may need
+ /// to be updated.
+ mutable bool cite_labels_valid_;
mutable RefCache ref_cache_;
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), cloned_buffer_(cloned_buffer),
- doing_export(false), parent_buffer(0)
+ bibfile_cache_valid_(false), cite_labels_valid_(false),
+ cloned_buffer_(cloned_buffer), doing_export(false), parent_buffer(0)
{
if (!cloned_buffer_) {
temppath = createBufferTmpDir();
bibinfo_cache_valid_ = cloned_buffer_->d->bibinfo_cache_valid_;
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_;
}
Buffer * Buffer::clone() const
{
+ BufferMap bufmap;
+ masterBuffer()->clone(bufmap);
+ BufferMap::iterator it = bufmap.find(this);
+ LASSERT(it != bufmap.end(), return 0);
+ return it->second;
+}
+
+
+void Buffer::clone(BufferMap & bufmap) const
+{
+ // have we already been cloned?
+ if (bufmap.find(this) != bufmap.end())
+ return;
+
Buffer * buffer_clone = new Buffer(fileName().absFileName(), false, this);
+ bufmap[this] = buffer_clone;
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();
+ Impl::PositionScopeBufferMap::iterator it = d->position_to_children.begin();
+ Impl::PositionScopeBufferMap::iterator end = d->position_to_children.end();
for (; it != end; ++it) {
- DocIterator dit = it->second.clone(buffer_clone);
+ DocIterator dit = it->first.clone(buffer_clone);
dit.setBuffer(buffer_clone);
- Buffer * child = const_cast<Buffer *>(it->first);
- Buffer * child_clone = child->clone();
+ Buffer * child = const_cast<Buffer *>(it->second.second);
+
+ child->clone(bufmap);
+ BufferMap::iterator const bit = bufmap.find(child);
+ LASSERT(bit != bufmap.end(), continue);
+ Buffer * child_clone = bit->second;
+
Inset * inset = dit.nextInset();
LASSERT(inset && inset->lyxCode() == INCLUDE_CODE, continue);
InsetInclude * inset_inc = static_cast<InsetInclude *>(inset);
inset_inc->setChildBuffer(child_clone);
child_clone->d->setParent(buffer_clone);
+ // FIXME Do we need to do this now, or can we wait until we run updateMacros()?
buffer_clone->setChild(dit, child_clone);
}
buffer_clone->d->macro_lock = false;
- return buffer_clone;
+ return;
}
FileName const bname(
addName(path, onlyFileName(
changeExtension(filename,
- formats.extension(bufferFormat()) + ".out"))));
+ formats.extension(params().bufferFormat()) + ".out"))));
// Also consider the master buffer log file
FileName masterfname = fname;
}
usermacros.clear();
updateMacros();
- updateMacroInstances();
+ updateMacroInstances(InternalUpdate);
return res;
}
{
FileName fname(fn);
Lexer lex;
- lex.setFile(fname);
+ if (!lex.setFile(fname)) {
+ Alert::error(_("File Not Found"),
+ bformat(_("Unable to open file `%1$s'."),
+ from_utf8(fn.absFileName())));
+ return ReadFileNotFound;
+ }
int file_format;
ReadStatus const ret_plf = parseLyXFormat(lex, fn, file_format);
bool Buffer::writeFile(FileName const & fname) const
{
+ // FIXME Do we need to do these here? I don't think writing
+ // the LyX file depends upon it. (RGH)
+ // updateBuffer();
+ // updateMacroInstances();
+
if (d->read_only && fname == d->filename)
return false;
errorList.clear();
bool failed_export = false;
otexstream os(ofs, d->texrow);
+
+ // make sure we are ready to export
+ // this needs to be done before we validate
+ // FIXME Do we need to do this all the time? I.e., in children
+ // of a master we are exporting?
+ updateBuffer();
+ updateMacroInstances(OutputUpdate);
+
try {
os.texrow().reset();
writeLaTeXSource(os, original_path,
}
LYXERR(Debug::INFO, "lyx document header finished");
- // Don't move this behind the parent_buffer=0 code below,
- // because then the macros will not get the right "redefinition"
- // flag as they don't see the parent macros which are output before.
- updateBuffer();
-
- // fold macros if possible, still with parent buffer as the
- // macros will be put in the prefix anyway.
- updateMacroInstances();
-
// 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
}
-bool Buffer::isLatex() const
-{
- return params().documentClass().outputType() == LATEX;
-}
-
-
-bool Buffer::isLiterate() const
-{
- return params().documentClass().outputType() == LITERATE;
-}
-
-
-bool Buffer::isDocBook() const
-{
- return params().documentClass().outputType() == DOCBOOK;
-}
-
-
void Buffer::makeDocBookFile(FileName const & fname,
OutputParams const & runparams,
bool const body_only) const
if (!openFileWrite(ofs, fname))
return;
+ // make sure we are ready to export
+ // this needs to be done before we validate
+ updateBuffer();
+ updateMacroInstances(OutputUpdate);
+
writeDocBookSource(ofs, fname.absFileName(), runparams, body_only);
ofs.close();
params().documentClass().counters().reset();
- updateMacros();
-
sgml::openTag(os, top);
os << '\n';
docbookParagraphs(text(), *this, os, runparams);
if (!openFileWrite(ofs, fname))
return;
+ // make sure we are ready to export
+ // this has to be done before we validate
+ updateBuffer(UpdateMaster, OutputUpdate);
+ updateMacroInstances(OutputUpdate);
+
writeLyXHTMLSource(ofs, runparams, body_only);
ofs.close();
{
LaTeXFeatures features(*this, params(), runparams);
validate(features);
- updateBuffer(UpdateMaster, OutputUpdate);
d->bibinfo_.makeCitationLabels(*this);
- updateMacros();
- updateMacroInstances();
if (!only_body) {
os << "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n"
{
params().validate(features);
- updateMacros();
-
for_each(paragraphs().begin(), paragraphs().end(),
bind(&Paragraph::validate, _1, ref(features)));
}
d->bibfile_cache_valid_ = true;
d->bibinfo_cache_valid_ = false;
+ d->cite_labels_valid_ = false;
}
void Buffer::invalidateBibinfoCache() const
{
d->bibinfo_cache_valid_ = false;
+ d->cite_labels_valid_ = false;
// also invalidate the cache for the parent buffer
Buffer const * const pbuf = d->parent();
if (pbuf)
{
d->bibfile_cache_valid_ = false;
d->bibinfo_cache_valid_ = false;
+ d->cite_labels_valid_ = false;
// also invalidate the cache for the parent buffer
Buffer const * const pbuf = d->parent();
if (pbuf)
time_t prevw = d->bibfile_status_[*ei];
if (lastw != prevw) {
d->bibinfo_cache_valid_ = false;
+ d->cite_labels_valid_ = false;
d->bibfile_status_[*ei] = lastw;
}
}
}
+bool Buffer::citeLabelsValid() const
+{
+ return masterBuffer()->d->cite_labels_valid_;
+}
+
+
bool Buffer::isDepClean(string const & name) const
{
DepClean::const_iterator const it = d->dep_clean.find(name);
}
-bool Buffer::isExportableFormat(string const & format) const
-{
- typedef vector<Format const *> 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()) {
case LFUN_BUFFER_EXPORT: {
docstring const arg = cmd.argument();
- enable = arg == "custom" || isExportable(to_utf8(arg));
+ enable = arg == "custom" || params().isExportable(to_utf8(arg));
if (!enable)
flag.message(bformat(
_("Don't know how to export to format: %1$s"), arg));
}
case LFUN_BUFFER_CHKTEX:
- enable = isLatex() && !lyxrc.chktex_command.empty();
+ enable = params().isLatex() && !lyxrc.chktex_command.empty();
break;
case LFUN_BUILD_PROGRAM:
- enable = isExportable("program");
+ enable = params().isExportable("program");
break;
case LFUN_BRANCH_ACTIVATE:
// Execute the command in the background
Systemcall call;
- call.startscript(Systemcall::DontWait, command);
+ call.startscript(Systemcall::DontWait, command, filePath());
break;
}
command2 += quoteName(psname);
// First run dvips.
// If successful, then spool command
- res = one.startscript(Systemcall::Wait, command);
+ res = one.startscript(Systemcall::Wait, command,
+ filePath());
if (res == 0) {
// If there's no GUI, we have to wait on this command. Otherwise,
// file, before it can be printed!!
Systemcall::Starttype stype = use_gui ?
Systemcall::DontWait : Systemcall::Wait;
- res = one.startscript(stype, command2);
+ res = one.startscript(stype, command2,
+ filePath());
}
} else {
// case 2: print directly to a printer
// as above....
Systemcall::Starttype stype = use_gui ?
Systemcall::DontWait : Systemcall::Wait;
- res = one.startscript(stype, command + quoteName(dviname));
+ res = one.startscript(stype, command +
+ quoteName(dviname), filePath());
}
} else {
// as above....
Systemcall::Starttype stype = use_gui ?
Systemcall::DontWait : Systemcall::Wait;
- res = one.startscript(stype, command);
+ res = one.startscript(stype, command, filePath());
}
if (res == 0)
}
-void Buffer::updateMacroInstances() const
+void Buffer::updateMacroInstances(UpdateType utype) const
{
LYXERR(Debug::MACROS, "updateMacroInstances for "
<< d->filename.onlyFileName());
MacroContext mc = MacroContext(this, it);
for (DocIterator::idx_type i = 0; i < n; ++i) {
MathData & data = minset->cell(i);
- data.updateMacros(0, mc);
+ data.updateMacros(0, mc, utype);
}
}
}
{
OutputParams runparams(¶ms().encoding());
runparams.nice = true;
- runparams.flavor = getOutputFlavor(format);
+ runparams.flavor = params().getOutputFlavor(format);
runparams.linelen = lyxrc.plaintext_linelen;
// No side effect of file copying and image conversion
runparams.dryrun = true;
d->texrow.reset();
d->texrow.newline();
d->texrow.newline();
- if (isDocBook())
+ if (params().isDocBook())
writeDocBookSource(os, absFileName(), runparams, false);
else if (runparams.flavor == OutputParams::HTML)
writeLyXHTMLSource(os, runparams, false);
texrow.newline();
texrow.newline();
// output paragraphs
- if (isDocBook())
+ if (params().isDocBook())
docbookParagraphs(text(), *this, os, runparams);
else if (runparams.flavor == OutputParams::HTML) {
XHTMLStream xs(os);
}
-string Buffer::bufferFormat() const
-{
- string format = params().documentClass().outputFormat();
- if (format == "latex") {
- if (params().useNonTeXFonts)
- return "xetex";
- if (params().encoding().package() == Encoding::japanese)
- return "platex";
- }
- return format;
-}
-
-
-string Buffer::getDefaultOutputFormat() const
-{
- if (!params().default_output_format.empty()
- && params().default_output_format != "default")
- return params().default_output_format;
- if (isDocBook()
- || params().useNonTeXFonts
- || params().encoding().package() == Encoding::japanese) {
- vector<Format const *> const formats = exportableFormats(true);
- if (formats.empty())
- return string();
- // return the first we find
- return formats.front()->name();
- }
- return lyxrc.default_view_format;
-}
-
-
-OutputParams::FLAVOR Buffer::getOutputFlavor(string const format) const
-{
- string const dformat = (format.empty() || format == "default") ?
- getDefaultOutputFormat() : format;
- DefaultFlavorCache::const_iterator it =
- default_flavors_.find(dformat);
-
- if (it != default_flavors_.end())
- return it->second;
-
- OutputParams::FLAVOR result = OutputParams::LATEX;
-
- if (dformat == "xhtml")
- result = OutputParams::HTML;
- else {
- // Try to determine flavor of default output format
- vector<string> backs = backends();
- if (find(backs.begin(), backs.end(), dformat) == backs.end()) {
- // Get shortest path to format
- Graph::EdgePath path;
- for (vector<string>::const_iterator it = backs.begin();
- it != backs.end(); ++it) {
- Graph::EdgePath p = theConverters().getPath(*it, dformat);
- if (!p.empty() && (path.empty() || p.size() < path.size())) {
- path = p;
- }
- }
- if (!path.empty())
- result = theConverters().getFlavor(path);
- }
- }
- // cache this flavor
- default_flavors_[dformat] = result;
- return result;
-}
-
-
namespace {
// helper class, to guarantee this gets reset properly
class MarkAsExporting {
runparams.flavor = OutputParams::LATEX;
runparams.linelen = lyxrc.plaintext_linelen;
runparams.includeall = includeall;
- vector<string> backs = backends();
+ vector<string> backs = params().backends();
Converters converters = theConverters();
if (find(backs.begin(), backs.end(), format) == backs.end()) {
// Get shortest path to format
filename = changeExtension(filename,
formats.extension(backend_format));
- // fix macros
- updateMacros();
- updateMacroInstances();
-
// Plain text backend
if (backend_format == "text") {
runparams.flavor = OutputParams::TEXT;
} else if (backend_format == "lyx")
writeFile(FileName(filename));
// Docbook backend
- else if (isDocBook()) {
+ else if (params().isDocBook()) {
runparams.nice = !put_in_tempdir;
makeDocBookFile(FileName(filename), runparams);
}
}
string const error_type = (format == "program")
- ? "Build" : bufferFormat();
+ ? "Build" : params().bufferFormat();
ErrorList & error_list = d->errorLists[error_type];
string const ext = formats.extension(format);
FileName const tmp_result_file(changeExtension(filename, ext));
// 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;
- string const error_type = bufferFormat();
+ string const error_type = params().bufferFormat();
d->cloned_buffer_->d->errorLists[error_type] = d->errorLists[error_type];
}
}
-bool Buffer::isExportable(string const & format) const
-{
- vector<string> backs = backends();
- for (vector<string>::const_iterator it = backs.begin();
- it != backs.end(); ++it)
- if (theConverters().isReachable(*it, format))
- return true;
- return false;
-}
-
-
-vector<Format const *> Buffer::exportableFormats(bool only_viewable) const
-{
- vector<string> const backs = backends();
- set<string> excludes;
- if (params().useNonTeXFonts) {
- excludes.insert("latex");
- excludes.insert("pdflatex");
- }
- vector<Format const *> result =
- theConverters().getReachable(backs[0], only_viewable, true, excludes);
- for (vector<string>::const_iterator it = backs.begin() + 1;
- it != backs.end(); ++it) {
- vector<Format const *> r =
- theConverters().getReachable(*it, only_viewable, false, excludes);
- result.insert(result.end(), r.begin(), r.end());
- }
- return result;
-}
-
-
-vector<string> Buffer::backends() const
-{
- vector<string> v;
- 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("luatex");
- v.push_back("xetex");
- } else if (v.back() == "xetex")
- v.push_back("luatex");
- v.push_back("xhtml");
- v.push_back("text");
- v.push_back("lyx");
- return v;
-}
-
-
Buffer::ReadStatus Buffer::extractFromVC()
{
bool const found = LyXVC::file_not_found_hook(d->filename);
return;
d->bibinfo_cache_valid_ = true;
+ d->cite_labels_valid_ = true;
cbuf.tocBackend().update();
if (scope == UpdateMaster)
cbuf.structureChanged();