#include "WordLangTuple.h"
#include "WordList.h"
-#include "insets/InsetBibitem.h"
#include "insets/InsetBibtex.h"
#include "insets/InsetBranch.h"
#include "insets/InsetInclude.h"
#include "mathed/MathMacroTemplate.h"
#include "mathed/MathSupport.h"
+#include "graphics/PreviewLoader.h"
+
#include "frontends/alert.h"
#include "frontends/Delegates.h"
#include "frontends/WorkAreaManager.h"
-#include "graphics/Previews.h"
-
#include "support/lassert.h"
#include "support/convert.h"
#include "support/debug.h"
using namespace std;
using namespace lyx::support;
+using namespace lyx::graphics;
namespace lyx {
// Do not remove the comment below, so we get merge conflict in
// independent branches. Instead add your own.
-int const LYX_FORMAT = 410; // rgh: dummy format for list->labeling
+int const LYX_FORMAT = 415; //uwestoehr : support for package undertilde (bug 6622)
typedef map<string, bool> DepClean;
typedef map<docstring, pair<InsetLabel const *, Buffer::References> > RefCache;
~Impl()
{
+ delete preview_loader_;
if (wa_) {
wa_->closeAll();
delete wa_;
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_;
/// our Text that should be wrapped in an InsetText
InsetText * inset;
+ ///
+ PreviewLoader * preview_loader_;
+
/// This is here to force the test to be done whenever parent_buffer
/// is accessed.
Buffer const * parent() const {
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(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)
+ toc_backend(owner), macro_lock(false), timestamp_(0), checksum_(0),
+ wa_(0), gui_(0), undo_(*owner), bibinfo_cache_valid_(false),
+ bibfile_cache_valid_(false), cite_labels_valid_(false),
+ preview_loader_(0), cloned_buffer_(cloned_buffer),
+ 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;
// read main text
bool const res = text().read(lex, errorList, d->inset);
+ // inform parent buffer about local macros
+ if (parent()) {
+ Buffer const * pbuf = parent();
+ UserMacroSet::const_iterator cit = usermacros.begin();
+ UserMacroSet::const_iterator end = usermacros.end();
+ for (; cit != end; ++cit)
+ pbuf->usermacros.insert(*cit);
+ }
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);
}
-void Buffer::updatePreviews() const
+PreviewLoader * Buffer::loader() const
{
- if (graphics::Previews::status() != LyXRC::PREVIEW_OFF)
- thePreviews().generateBufferPreviews(*this);
+ if (lyxrc.preview == LyXRC::PREVIEW_OFF)
+ return 0;
+ if (!d->preview_loader_)
+ d->preview_loader_ = new PreviewLoader(*this);
+ return d->preview_loader_;
}
void Buffer::removePreviews() const
{
- thePreviews().removeLoader(*this);
+ delete d->preview_loader_;
+ d->preview_loader_ = 0;
+}
+
+
+void Buffer::updatePreviews() const
+{
+ PreviewLoader * ploader = loader();
+ if (!ploader)
+ return;
+
+ InsetIterator it = inset_iterator_begin(*d->inset);
+ InsetIterator const end = inset_iterator_end(*d->inset);
+ for (; it != end; ++it)
+ it->addPreview(it, *ploader);
+
+ ploader->startLoading();
}
backupName = FileName(addName(lyxrc.backupdir_path,
mangledName));
}
- // do not copy because of #6587
- if (fileName().moveTo(backupName)) {
- madeBackup = true;
- } else {
+
+ // Except file is symlink do not copy because of #6587.
+ // Hard links have bad luck.
+ if (fileName().isSymLink())
+ madeBackup = fileName().copyTo(backupName);
+ else
+ madeBackup = fileName().moveTo(backupName);
+
+ if (!madeBackup) {
Alert::error(_("Backup failure"),
bformat(_("Cannot create backup file %1$s.\n"
- "Please check whether the directory exists and is writeable."),
+ "Please check whether the directory exists and is writable."),
from_utf8(backupName.absFileName())));
//LYXERR(Debug::DEBUG, "Fs error: " << fe.what());
}
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;
LYXERR0(" " << s);
if (writeFile(FileName(s))) {
markClean();
- user_message += bformat(_(" Saved to %1$s. Phew.\n"), from_utf8(s));
+ user_message += " " + bformat(_("Saved to %1$s. Phew.\n"), from_utf8(s));
return user_message;
} else {
- user_message += _(" Save failed! Trying again...\n");
+ user_message += " " + _("Save failed! Trying again...\n");
}
}
// 2) In HOME directory.
- string s = addName(package().home_dir().absFileName(), absFileName());
+ string s = addName(Package::get_home_dir().absFileName(), absFileName());
s += ".emergency";
lyxerr << ' ' << s << endl;
if (writeFile(FileName(s))) {
markClean();
- user_message += bformat(_(" Saved to %1$s. Phew.\n"), from_utf8(s));
+ user_message += " " + bformat(_("Saved to %1$s. Phew.\n"), from_utf8(s));
return user_message;
}
- user_message += _(" Save failed! Trying yet again...\n");
+ user_message += " " + _("Save failed! Trying yet again...\n");
// 3) In "/tmp" directory.
// MakeAbsPath to prepend the current
lyxerr << ' ' << s << endl;
if (writeFile(FileName(s))) {
markClean();
- user_message += bformat(_(" Saved to %1$s. Phew.\n"), from_utf8(s));
+ user_message += " " + bformat(_("Saved to %1$s. Phew.\n"), from_utf8(s));
return user_message;
}
- user_message += _(" Save failed! Bummer. Document is lost.");
+ user_message += " " + _("Save failed! Bummer. Document is lost.");
// Don't try again.
markClean();
return user_message;
// The top of the file should not be written by params().
// write out a comment in the top of the file
- ofs << "#LyX " << lyx_version
+ ofs << "#LyX " << lyx_version_major << "." << lyx_version_minor
<< " created this file. For more info see http://www.lyx.org/\n"
<< "\\lyxformat " << LYX_FORMAT << "\n"
<< "\\begin_document\n";
{
OutputParams runparams = runparams_in;
+ // This is necessary for LuaTeX/XeTeX with tex fonts.
+ // See FIXME in BufferParams::encoding()
+ if (runparams.isFullUnicode())
+ runparams.encoding = encodings.fromLyXName("utf8-plain");
+
string const encoding = runparams.encoding->iconvName();
LYXERR(Debug::LATEX, "makeLaTeXFile encoding: " << encoding << "...");
ErrorList & errorList = d->errorLists["Export"];
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 {
- d->texrow.reset();
- writeLaTeXSource(ofs, original_path,
+ os.texrow().reset();
+ writeLaTeXSource(os, original_path,
runparams, output_preamble, output_body);
}
catch (EncodingException & e) {
}
-void Buffer::writeLaTeXSource(odocstream & os,
+void Buffer::writeLaTeXSource(otexstream & os,
string const & original_path,
OutputParams const & runparams_in,
bool const output_preamble, bool const output_body) const
"For more info, see http://www.lyx.org/.\n"
"%% Do not edit unless you really know what "
"you are doing.\n";
- d->texrow.newline();
- d->texrow.newline();
}
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.
- updateMacros();
-
- // 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
if (output_preamble) {
if (!runparams.nice) {
// code for usual, NOT nice-latex-file
- os << "\\batchmode\n"; // changed
- // from \nonstopmode
- d->texrow.newline();
+ os << "\\batchmode\n"; // changed from \nonstopmode
}
if (!original_path.empty()) {
// FIXME UNICODE
<< "\\def\\input@path{{"
<< inputpath << "/}}\n"
<< "\\makeatother\n";
- d->texrow.newline();
- d->texrow.newline();
- d->texrow.newline();
}
}
runparams.use_polyglossia = features.usePolyglossia();
// Write the preamble
runparams.use_babel = params().writeLaTeX(os, features,
- d->texrow,
d->filename.onlyPath());
runparams.use_japanese = features.isRequired("japanese");
// make the body.
os << "\\begin{document}\n";
- d->texrow.newline();
// output the parent macros
MacroSet::iterator it = parentMacros.begin();
MacroSet::iterator end = parentMacros.end();
for (; it != end; ++it) {
- int num_lines = (*it)->write(os, true);
- d->texrow.newlines(num_lines);
+ int num_lines = (*it)->write(os.os(), true);
+ os.texrow().newlines(num_lines);
}
} // output_preamble
- d->texrow.start(paragraphs().begin()->id(), 0);
+ os.texrow().start(paragraphs().begin()->id(), 0);
LYXERR(Debug::INFO, "preamble finished, now the body.");
}
// the real stuff
- latexParagraphs(*this, text(), os, d->texrow, runparams);
+ latexParagraphs(*this, text(), os, runparams);
// Restore the parenthood if needed
if (output_preamble)
// add this just in case after all the paragraphs
os << endl;
- d->texrow.newline();
if (output_preamble) {
os << "\\end{document}\n";
- d->texrow.newline();
LYXERR(Debug::LATEX, "makeLaTeXFile...done");
} else {
LYXERR(Debug::LATEX, "LaTeXFile for inclusion made.");
runparams_in.encoding = runparams.encoding;
// Just to be sure. (Asger)
- d->texrow.newline();
+ os.texrow().newline();
//for (int i = 0; i<d->texrow.rows(); i++) {
// int id,pos;
//}
LYXERR(Debug::INFO, "Finished making LaTeX file.");
- LYXERR(Debug::INFO, "Row count was " << d->texrow.rows() - 1 << '.');
-}
-
-
-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;
+ LYXERR(Debug::INFO, "Row count was " << os.texrow().rows() - 1 << '.');
}
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);
void Buffer::makeLyXHTMLFile(FileName const & fname,
- OutputParams const & runparams,
- bool const body_only) const
+ OutputParams const & runparams) const
{
LYXERR(Debug::LATEX, "makeLyXHTMLFile...");
if (!openFileWrite(ofs, fname))
return;
- writeLyXHTMLSource(ofs, runparams, body_only);
+ // make sure we are ready to export
+ // this has to be done before we validate
+ updateBuffer(UpdateMaster, OutputUpdate);
+ updateMacroInstances(OutputUpdate);
+
+ writeLyXHTMLSource(ofs, runparams);
ofs.close();
if (ofs.fail())
{
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)
}
-void Buffer::checkBibInfoCache() const
+void Buffer::checkIfBibInfoCacheIsValid() const
{
// use the master's cache
Buffer const * const tmp = masterBuffer();
if (tmp != this) {
- tmp->checkBibInfoCache();
+ tmp->checkIfBibInfoCacheIsValid();
return;
}
- // this will also reload the cache if it is invalid
- support::FileNameList const & bibfiles_cache = getBibfilesCache();
-
// compare the cached timestamps with the actual ones.
- support::FileNameList::const_iterator ei = bibfiles_cache.begin();
- support::FileNameList::const_iterator en = bibfiles_cache.end();
+ FileNameList const & bibfiles_cache = getBibfilesCache();
+ FileNameList::const_iterator ei = bibfiles_cache.begin();
+ FileNameList::const_iterator en = bibfiles_cache.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->cite_labels_valid_ = false;
d->bibfile_status_[*ei] = lastw;
}
}
-
- // if not valid, then reload the info
- if (!d->bibinfo_cache_valid_) {
- d->bibinfo_.clear();
- fillWithBibKeys(d->bibinfo_);
- d->bibinfo_cache_valid_ = true;
+}
+
+
+void Buffer::reloadBibInfoCache() const
+{
+ // use the master's cache
+ Buffer const * const tmp = masterBuffer();
+ if (tmp != this) {
+ tmp->reloadBibInfoCache();
+ return;
}
+
+ checkIfBibInfoCacheIsValid();
+ if (d->bibinfo_cache_valid_)
+ return;
+
+ d->bibinfo_.clear();
+ collectBibKeys();
+ d->bibinfo_cache_valid_ = true;
}
-void Buffer::fillWithBibKeys(BiblioInfo & keys) const
+void Buffer::collectBibKeys() const
{
for (InsetIterator it = inset_iterator_begin(inset()); it; ++it)
- it->fillWithBibKeys(keys, it);
+ it->collectBibKeys(it);
+}
+
+
+void Buffer::addBiblioInfo(BiblioInfo const & bi) const
+{
+ Buffer const * tmp = masterBuffer();
+ BiblioInfo & masterbi = (tmp == this) ?
+ d->bibinfo_ : tmp->d->bibinfo_;
+ masterbi.mergeBiblioInfo(bi);
+}
+
+
+void Buffer::addBibTeXInfo(docstring const & key, BibTeXInfo const & bi) const
+{
+ Buffer const * tmp = masterBuffer();
+ BiblioInfo & masterbi = (tmp == this) ?
+ d->bibinfo_ : tmp->d->bibinfo_;
+ masterbi[key] = bi;
+}
+
+
+bool Buffer::citeLabelsValid() const
+{
+ return masterBuffer()->d->cite_labels_valid_;
}
}
-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::saveCheckSum() const
{
FileName const & file = d->filename;
+
+ file.refresh();
if (file.exists()) {
d->timestamp_ = file.lastModified();
d->checksum_ = file.checksum();
ListOfBuffers Buffer::allRelatives() const
{
ListOfBuffers lb = masterBuffer()->getDescendents();
- lb.push_front(const_cast<Buffer *>(this));
+ lb.push_front(const_cast<Buffer *>(masterBuffer()));
return lb;
}
{
ListOfBuffers v;
collectChildren(v, false);
+ // Make sure we have not included ourselves.
+ ListOfBuffers::iterator bit = find(v.begin(), v.end(), this);
+ if (bit != v.end()) {
+ LYXERR0("Recursive include detected in `" << fileName() << "'.");
+ v.erase(bit);
+ }
return v;
}
{
ListOfBuffers v;
collectChildren(v, true);
+ // Make sure we have not included ourselves.
+ ListOfBuffers::iterator bit = find(v.begin(), v.end(), this);
+ if (bit != v.end()) {
+ LYXERR0("Recursive include detected in `" << fileName() << "'.");
+ v.erase(bit);
+ }
return v;
}
break;
// scope ends behind pos?
- if (pos < it->second.first) {
+ if (pos < it->second.first
+ && (cloned_buffer_ ||
+ theBufferList().isLoaded(it->second.second))) {
// look for macro in external file
macro_lock = true;
MacroData const * data
}
-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);
}
}
}
{
//FIXME: This does not work for child documents yet.
LASSERT(code == CITE_CODE, /**/);
+
+ reloadBibInfoCache();
+
// Check if the label 'from' appears more than once
- vector<docstring> labels;
- string paramName;
- checkBibInfoCache();
BiblioInfo const & keys = masterBibInfo();
BiblioInfo::const_iterator bit = keys.begin();
BiblioInfo::const_iterator bend = keys.end();
+ vector<docstring> labels;
for (; bit != bend; ++bit)
// FIXME UNICODE
labels.push_back(bit->first);
- paramName = "key";
if (count(labels.begin(), labels.end(), from) > 1)
return;
+ string const paramName = "key";
for (InsetIterator it = inset_iterator_begin(inset()); it; ++it) {
if (it->lyxCode() == code) {
InsetCommand * inset = it->asInsetCommand();
}
-void Buffer::getSourceCode(odocstream & os, pit_type par_begin,
- pit_type par_end, bool full_source) const
+void Buffer::getSourceCode(odocstream & os, string const format,
+ pit_type par_begin, pit_type par_end,
+ bool full_source) const
{
OutputParams runparams(¶ms().encoding());
runparams.nice = true;
- runparams.flavor = params().useNonTeXFonts ?
- OutputParams::XETEX : OutputParams::LATEX;
+ 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
+ else if (runparams.flavor == OutputParams::HTML)
+ writeLyXHTMLSource(os, runparams, false);
+ else {
// latex or literate
- writeLaTeXSource(os, string(), runparams, true, true);
+ otexstream ots(os, d->texrow);
+ writeLaTeXSource(ots, string(), runparams, true, true);
+ }
} else {
runparams.par_begin = par_begin;
runparams.par_end = par_end;
texrow.newline();
texrow.newline();
// output paragraphs
- if (isDocBook())
+ if (params().isDocBook())
docbookParagraphs(text(), *this, os, runparams);
- else
+ else if (runparams.flavor == OutputParams::HTML) {
+ XHTMLStream xs(os);
+ xhtmlParagraphs(text(), *this, xs, runparams);
+ } else {
// latex or literate
- latexParagraphs(*this, text(), os, texrow, runparams);
+ otexstream ots(os, texrow);
+ latexParagraphs(*this, text(), ots, runparams);
+ }
}
}
ErrorList & Buffer::errorList(string const & type) const
{
- static ErrorList emptyErrorList;
- map<string, ErrorList>::iterator it = d->errorLists.find(type);
- if (it == d->errorLists.end())
- return emptyErrorList;
-
- return it->second;
+ return d->errorLists[type];
}
}
-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;
- typedef vector<Format const *> Formats;
- Formats formats = exportableFormats(true);
- if (isDocBook()
- || isLiterate()
- || params().useNonTeXFonts
- || params().encoding().package() == Encoding::japanese) {
- if (formats.empty())
- return string();
- // return the first we find
- return formats.front()->name();
- }
- return lyxrc.default_view_format;
-}
-
-
namespace {
// helper class, to guarantee this gets reset properly
class MarkAsExporting {
void Buffer::setExportStatus(bool e) const
{
d->doing_export = e;
+ ListOfBuffers clist = getDescendents();
+ ListOfBuffers::const_iterator cit = clist.begin();
+ ListOfBuffers::const_iterator const cen = clist.end();
+ for (; cit != cen; ++cit)
+ (*cit)->d->doing_export = e;
}
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
+ converters.buildGraph();
Graph::EdgePath path;
for (vector<string>::const_iterator it = backs.begin();
it != backs.end(); ++it) {
- Graph::EdgePath p = theConverters().getPath(*it, format);
+ Graph::EdgePath p = converters.getPath(*it, format);
if (!p.empty() && (path.empty() || p.size() < path.size())) {
backend_format = *it;
path = p;
}
return false;
}
- runparams.flavor = theConverters().getFlavor(path);
+ runparams.flavor = converters.getFlavor(path);
} else {
backend_format = format;
runparams.flavor = OutputParams::PDFLATEX;
else if (backend_format == "luatex")
runparams.flavor = OutputParams::LUATEX;
+ else if (backend_format == "dviluatex")
+ runparams.flavor = OutputParams::DVILUATEX;
else if (backend_format == "xetex")
runparams.flavor = OutputParams::XETEX;
}
filename = changeExtension(filename,
formats.extension(backend_format));
- // fix macros
- updateMacroInstances();
-
// Plain text backend
if (backend_format == "text") {
runparams.flavor = OutputParams::TEXT;
break;
case BufferParams::LaTeX:
runparams.math_flavor = OutputParams::MathAsLaTeX;
- break;
+ break;
}
-
makeLyXHTMLFile(FileName(filename), runparams);
- } else if (backend_format == "lyx")
+ } 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);
}
// LaTeX backend
else if (backend_format == format) {
runparams.nice = true;
- if (!makeLaTeXFile(FileName(filename), string(), runparams))
+ if (!makeLaTeXFile(FileName(filename), string(), runparams)) {
+ if (d->cloned_buffer_) {
+ d->cloned_buffer_->d->errorLists["Export"] =
+ d->errorLists["Export"];
+ }
return false;
+ }
} else if (!lyxrc.tex_allows_spaces
&& contains(filePath(), ' ')) {
Alert::error(_("File name error"),
return false;
} else {
runparams.nice = false;
- if (!makeLaTeXFile(FileName(filename), filePath(), runparams))
+ if (!makeLaTeXFile(FileName(filename), filePath(), runparams)) {
+ if (d->cloned_buffer_) {
+ d->cloned_buffer_->d->errorLists["Export"] =
+ d->errorLists["Export"];
+ }
return false;
+ }
}
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));
- bool const success = theConverters().convert(this, FileName(filename),
+ bool const success = converters.convert(this, FileName(filename),
tmp_result_file, FileName(absFileName()), backend_format, format,
error_list);
// Emit the signal to show the error list or copy it back to the
- // cloned Buffer so that it cab be emitted afterwards.
+ // cloned Buffer so that it can be emitted afterwards.
if (format != backend_format) {
if (d->cloned_buffer_) {
d->cloned_buffer_->d->errorLists[error_type] =
ListOfBuffers::const_iterator const cen = clist.end();
for (; cit != cen; ++cit) {
if (d->cloned_buffer_) {
+ // Enable reverse search by copying back the
+ // texrow object to the cloned buffer.
+ // FIXME: this is not thread safe.
+ (*cit)->d->cloned_buffer_->d->texrow = (*cit)->d->texrow;
(*cit)->d->cloned_buffer_->d->errorLists[error_type] =
(*cit)->d->errorLists[error_type];
} else
// 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();
- vector<Format const *> result =
- theConverters().getReachable(backs[0], only_viewable, true);
- for (vector<string>::const_iterator it = backs.begin() + 1;
- it != backs.end(); ++it) {
- vector<Format const *> r =
- theConverters().getReachable(*it, only_viewable, false);
- 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");
- 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);
if (success) {
if (isReadonly()) {
Alert::warning(_("File is read-only"),
- bformat(_("An emergency file is succesfully loaded, "
+ bformat(_("An emergency file is successfully loaded, "
"but the original file %1$s is marked read-only. "
"Please make sure to save the document as a different "
"file."), from_utf8(d->filename.absFileName())));
if (ret_llf == ReadSuccess) {
if (isReadonly()) {
Alert::warning(_("File is read-only"),
- bformat(_("A backup file is succesfully loaded, "
+ bformat(_("A backup file is successfully loaded, "
"but the original file %1$s is marked read-only. "
"Please make sure to save the document as a "
"different file."),
void Buffer::bufferErrors(TeXErrors const & terr, ErrorList & errorList) const
{
- TeXErrors::Errors::const_iterator cit = terr.begin();
+ TeXErrors::Errors::const_iterator it = terr.begin();
TeXErrors::Errors::const_iterator end = terr.end();
+ ListOfBuffers clist = getDescendents();
+ ListOfBuffers::const_iterator cen = clist.end();
- for (; cit != end; ++cit) {
+ for (; it != end; ++it) {
int id_start = -1;
int pos_start = -1;
- int errorRow = cit->error_in_line;
- bool found = d->texrow.getIdFromRow(errorRow, id_start,
- pos_start);
+ int errorRow = it->error_in_line;
+ Buffer const * buf = 0;
+ Impl const * p = d;
+ if (it->child_name.empty())
+ p->texrow.getIdFromRow(errorRow, id_start, pos_start);
+ else {
+ // The error occurred in a child
+ ListOfBuffers::const_iterator cit = clist.begin();
+ for (; cit != cen; ++cit) {
+ string const child_name =
+ DocFileName(changeExtension(
+ (*cit)->absFileName(), "tex")).
+ mangledFileName();
+ if (it->child_name != child_name)
+ continue;
+ (*cit)->d->texrow.getIdFromRow(errorRow,
+ id_start, pos_start);
+ if (id_start != -1) {
+ buf = d->cloned_buffer_
+ ? (*cit)->d->cloned_buffer_->d->owner_
+ : (*cit)->d->owner_;
+ p = (*cit)->d;
+ break;
+ }
+ }
+ }
int id_end = -1;
int pos_end = -1;
+ bool found;
do {
++errorRow;
- found = d->texrow.getIdFromRow(errorRow, id_end, pos_end);
+ found = p->texrow.getIdFromRow(errorRow, id_end, pos_end);
} while (found && id_start == id_end && pos_start == pos_end);
- errorList.push_back(ErrorItem(cit->error_desc,
- cit->error_text, id_start, pos_start, pos_end));
+ if (id_start != id_end) {
+ // Next registered position is outside the inset where
+ // the error occurred, so signal end-of-paragraph
+ pos_end = 0;
+ }
+
+ errorList.push_back(ErrorItem(it->error_desc,
+ it->error_text, id_start, pos_start, pos_end, buf));
}
}
// do this only if we are the top-level Buffer
if (master == this)
- checkBibInfoCache();
+ reloadBibInfoCache();
// 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.
// TocBackend update will be done later.
return;
+ d->bibinfo_cache_valid_ = true;
+ d->cite_labels_valid_ = true;
cbuf.tocBackend().update();
if (scope == UpdateMaster)
cbuf.structureChanged();
// Compute the item depth of the paragraph
par.itemdepth = getItemDepth(it);
- if (layout.margintype == MARGIN_MANUAL
- || layout.latextype == LATEX_BIB_ENVIRONMENT) {
+ if (layout.margintype == MARGIN_MANUAL) {
if (par.params().labelWidthString().empty())
par.params().labelWidthString(par.expandLabel(layout, bp));
+ } else if (layout.latextype == LATEX_BIB_ENVIRONMENT) {
+ // we do not need to do anything here, since the empty case is
+ // handled during export.
} else {
par.params().labelWidthString(docstring());
}
switch(layout.labeltype) {
case LABEL_COUNTER:
if (layout.toclevel <= bp.secnumdepth
- && (layout.latextype != LATEX_ENVIRONMENT
- || it.text()->isFirstInSequence(it.pit()))) {
- counters.step(layout.counter, utype);
- par.params().labelString(
- par.expandLabel(layout, bp));
+ && (layout.latextype != LATEX_ENVIRONMENT
+ || it.text()->isFirstInSequence(it.pit()))) {
+ if (counters.hasCounter(layout.counter))
+ counters.step(layout.counter, utype);
+ par.params().labelString(par.expandLabel(layout, bp));
} else
par.params().labelString(docstring());
break;
updateTitles();
markClean();
message(bformat(_("Document %1$s reloaded."), disp_fn));
+ d->undo_.clear();
} else {
message(bformat(_("Could not reload document %1$s."), disp_fn));
}