#include "Lexer.h"
#include "LyXAction.h"
#include "LyX.h"
-#include "LyXFunc.h"
#include "LyXRC.h"
#include "LyXVC.h"
#include "output_docbook.h"
#include "insets/InsetInclude.h"
#include "insets/InsetText.h"
+#include "mathed/InsetMathHull.h"
#include "mathed/MacroTable.h"
#include "mathed/MathMacroTemplate.h"
#include "mathed/MathSupport.h"
#include "support/textutils.h"
#include "support/types.h"
-#include <boost/bind.hpp>
-#include <boost/shared_ptr.hpp>
+#include "support/bind.h"
+#include "support/shared_ptr.h"
#include <algorithm>
#include <fstream>
// Do not remove the comment below, so we get merge conflict in
// independent branches. Instead add your own.
-int const LYX_FORMAT = 375; // jspitzm: includeonly support
+int const LYX_FORMAT = 400; // uwestoehr: support for \rule
typedef map<string, bool> DepClean;
typedef map<docstring, pair<InsetLabel const *, Buffer::References> > RefCache;
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()
{
}
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;
/// 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<Buffer const * const, DocIterator> BufferPositionMap;
///
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
/// A cache for bibliography info
mutable BiblioInfo bibinfo_;
/// whether the bibinfo cache is valid
- bool bibinfoCacheValid_;
+ mutable bool bibinfo_cache_valid_;
+ /// whether the bibfile cache is valid
+ mutable bool bibfile_cache_valid_;
/// Cache of timestamps of .bib files
- map<FileName, time_t> bibfileStatus_;
+ map<FileName, time_t> bibfile_status_;
mutable RefCache ref_cache_;
// 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) {
- if (parent_buffer && pb && parent_buffer != pb)
+ if (parent_buffer == pb)
+ // nothing to do
+ return;
+ if (!cloned_buffer_ && parent_buffer && pb)
LYXERR0("Warning: a buffer should not have two parents!");
parent_buffer = pb;
+ if (!cloned_buffer_ && parent_buffer) {
+ parent_buffer->invalidateBibfileCache();
+ parent_buffer->invalidateBibinfoCache();
+ }
}
/// 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_;
-
+ /// are we in the process of exporting this buffer?
+ mutable bool doing_export;
+
private:
/// So we can force access via the accessors.
mutable Buffer const * parent_buffer;
// We are in our own directory. Why bother to mangle name?
// In fact I wrote this code to circumvent a problematic behaviour
// (bug?) of EMX mkstemp().
- FileName tmpfl(package().temp_dir().absFilename() + "/lyx_tmpbuf" +
+ FileName tmpfl(package().temp_dir().absFileName() + "/lyx_tmpbuf" +
convert<string>(count++));
if (!tmpfl.createDirectory(0777)) {
throw ExceptionMessage(WarningException, _("Disk Error: "), bformat(
_("LyX could not create the temporary directory '%1$s' (Disk is full maybe?)"),
- from_utf8(tmpfl.absFilename())));
+ from_utf8(tmpfl.absFileName())));
}
return tmpfl;
}
-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), bibinfoCacheValid_(false),
- cloned_buffer_(cloned_buffer), 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), cloned_buffer_(cloned_buffer),
+ doing_export(false), parent_buffer(0)
{
if (!cloned_buffer_) {
temppath = createBufferTmpDir();
- lyxvc.setBuffer(&parent);
+ 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_cache_valid_ = cloned_buffer_->d->bibfile_cache_valid_;
+ bibfile_status_ = cloned_buffer_->d->bibfile_status_;
}
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) {
// 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.
Impl::BufferPositionMap::iterator end = d->children_positions.end();
for (; it != end; ++it) {
Buffer * child = const_cast<Buffer *>(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 (!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())));
+ from_utf8(d->temppath.absFileName())));
}
// Remove any previewed LaTeX snippets associated with this buffer.
- thePreviews().removeLoader(*this);
+ if (!isClone())
+ thePreviews().removeLoader(*this);
delete d;
}
Buffer * Buffer::clone() const
{
- // FIXME for asynchronous export and preview: We must also clone all
- // the child buffers!
- return new Buffer(fileName().absFilename(), false, this);
+ 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<Buffer *>(it->first);
+ Buffer * child_clone = child->clone();
+ 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);
+ buffer_clone->setChild(dit, child_clone);
+ }
+ buffer_clone->d->macro_lock = false;
+ return buffer_clone;
}
string const Buffer::temppath() const
{
- return d->temppath.absFilename();
+ return d->temppath.absFileName();
}
}
+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();
+ : 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;
}
string const path = temppath();
FileName const fname(addName(temppath(),
- onlyFilename(changeExtension(filename,
+ onlyFileName(changeExtension(filename,
".log"))));
// FIXME: how do we know this is the name of the build log?
FileName const bname(
- addName(path, onlyFilename(
+ addName(path, onlyFileName(
changeExtension(filename,
formats.extension(bufferFormat()) + ".out"))));
LYXERR(Debug::FILES, "Log name calculated as: " << bname);
if (type)
*type = buildlog;
- return bname.absFilename();
+ return bname.absFileName();
// If we have a newer master file log or only a master log, show this
} else if (fname != masterfname
&& (!fname.exists() && (masterfname.exists()
LYXERR(Debug::FILES, "Log name calculated as: " << masterfname);
if (type)
*type = mtype;
- return masterfname.absFilename();
+ return masterfname.absFileName();
}
LYXERR(Debug::FILES, "Log name calculated as: " << fname);
if (type)
*type = latexlog;
- return fname.absFilename();
+ return fname.absFileName();
}
{
if (d->read_only != flag) {
d->read_only = flag;
- setReadOnly(flag);
+ changed(false);
}
}
params().pdfoptions().clear();
params().indiceslist().clear();
params().backgroundcolor = lyx::rgbFromHexName("#ffffff");
+ params().isbackgroundcolor = false;
+ params().fontcolor = lyx::rgbFromHexName("#000000");
+ params().isfontcolor = false;
+ params().notefontcolor = lyx::rgbFromHexName("#cccccc");
+ params().boxbgcolor = lyx::rgbFromHexName("#ff0000");
+ params().html_latex_start.clear();
+ params().html_latex_end.clear();
+ params().html_math_img_scale = 1.0;
+ params().output_sync_macro.erase();
for (int i = 0; i < 4; ++i) {
params().user_defined_bullet(i) = ITEMIZE_DEFAULTS[i];
if (!params().master.empty()) {
FileName const master_file = makeAbsPath(params().master,
onlyPath(absFileName()));
- if (isLyXFilename(master_file.absFilename())) {
+ if (isLyXFileName(master_file.absFileName())) {
Buffer * master =
checkAndLoadLyXFile(master_file, true);
if (master) {
if (!lex.checkFor("\\lyxformat")) {
Alert::error(_("Document format failure"),
bformat(_("%1$s is not a readable LyX document."),
- from_utf8(filename.absFilename())));
+ from_utf8(filename.absFileName())));
return failure;
}
// Save the timestamp and checksum of disk file. If filename is an
// emergency file, save the timestamp and checksum of the original lyx file
// because isExternallyModified will check for this file. (BUG4193)
- string diskfile = filename.absFilename();
+ string diskfile = filename.absFileName();
if (suffixIs(diskfile, ".emergency"))
diskfile = diskfile.substr(0, diskfile.size() - 10);
saveCheckSum(FileName(diskfile));
" version of LyX, but a temporary"
" file for converting it could"
" not be created."),
- from_utf8(filename.absFilename())));
+ from_utf8(filename.absFileName())));
return failure;
}
FileName const lyx2lyx = libFileSearch("lyx2lyx", "lyx2lyx");
" version of LyX, but the"
" conversion script lyx2lyx"
" could not be found."),
- from_utf8(filename.absFilename())));
+ from_utf8(filename.absFileName())));
return failure;
}
ostringstream command;
<< ' ' << quoteName(lyx2lyx.toFilesystemEncoding())
<< " -t " << convert<string>(LYX_FORMAT)
<< " -o " << quoteName(tmpfile.toFilesystemEncoding())
- << ' ' << quoteName(filename.toFilesystemEncoding());
+ << ' ' << quoteName(filename.toSafeFilesystemEncoding());
string const command_str = command.str();
LYXERR(Debug::INFO, "Running '" << command_str << '\'');
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())));
+ 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);
Alert::error(_("Document format failure"),
bformat(_("%1$s ended unexpectedly, which means"
" that it is probably corrupted."),
- from_utf8(filename.absFilename())));
+ from_utf8(filename.absFileName())));
+ return failure;
}
d->file_fully_loaded = true;
}
-// Should probably be moved to somewhere else: BufferView? LyXView?
+// Should probably be moved to somewhere else: BufferView? GuiView?
bool Buffer::save() const
{
+ // ask if the disk file has been externally modified (use checksum method)
+ if (fileName().exists() && isExternallyModified(checksum_method)) {
+ docstring const file = makeDisplayPath(absFileName(), 20);
+ docstring text = bformat(_("Document %1$s has been externally modified. Are you sure "
+ "you want to overwrite this file?"), file);
+ int const ret = Alert::prompt(_("Overwrite modified file?"),
+ text, 1, 1, _("&Overwrite"), _("&Cancel"));
+ if (ret == 1)
+ return false;
+ }
+
// We don't need autosaves in the immediate future. (Asger)
resetAutosaveTimers();
- string const encodedFilename = d->filename.toFilesystemEncoding();
-
FileName backupName;
bool madeBackup = false;
backupName = FileName(absFileName() + '~');
if (!lyxrc.backupdir_path.empty()) {
string const mangledName =
- subst(subst(backupName.absFilename(), '/', '!'), ':', '!');
+ subst(subst(backupName.absFileName(), '/', '!'), ':', '!');
backupName = FileName(addName(lyxrc.backupdir_path,
mangledName));
}
- if (fileName().copyTo(backupName)) {
+ // do not copy because of #6587
+ if (fileName().moveTo(backupName)) {
madeBackup = true;
} else {
Alert::error(_("Backup failure"),
bformat(_("Cannot create backup file %1$s.\n"
"Please check whether the directory exists and is writeable."),
- from_utf8(backupName.absFilename())));
+ from_utf8(backupName.absFileName())));
//LYXERR(Debug::DEBUG, "Fs error: " << fe.what());
}
}
- // ask if the disk file has been externally modified (use checksum method)
- if (fileName().exists() && isExternallyModified(checksum_method)) {
- docstring const file = makeDisplayPath(absFileName(), 20);
- docstring text = bformat(_("Document %1$s has been externally modified. Are you sure "
- "you want to overwrite this file?"), file);
- int const ret = Alert::prompt(_("Overwrite modified file?"),
- text, 1, 1, _("&Overwrite"), _("&Cancel"));
- if (ret == 1)
- return false;
- }
-
if (writeFile(d->filename)) {
markClean();
return true;
bool retval = false;
docstring const str = bformat(_("Saving document %1$s..."),
- makeDisplayPath(fname.absFilename()));
+ makeDisplayPath(fname.absFileName()));
message(str);
+ string const encoded_fname = fname.toSafeFilesystemEncoding(os::CREATE);
+
if (params().compressed) {
- gz::ogzstream ofs(fname.toFilesystemEncoding().c_str(), ios::out|ios::trunc);
+ gz::ogzstream ofs(encoded_fname.c_str(), ios::out|ios::trunc);
retval = ofs && write(ofs);
} else {
- ofstream ofs(fname.toFilesystemEncoding().c_str(), ios::out|ios::trunc);
+ ofstream ofs(encoded_fname.c_str(), ios::out|ios::trunc);
retval = ofs && write(ofs);
}
return false;
}
- removeAutosaveFile();
+ // see bug 6587
+ // removeAutosaveFile();
saveCheckSum(d->filename);
message(str + _(" done."));
if (isClean())
return docstring();
- string const doc = isUnnamed() ? onlyFilename(absFileName()) : absFileName();
+ string const doc = isUnnamed() ? onlyFileName(absFileName()) : absFileName();
docstring user_message = bformat(
_("LyX: Attempting to save document %1$s\n"), from_utf8(doc));
}
// 2) In HOME directory.
- string s = addName(package().home_dir().absFilename(), absFileName());
+ string s = addName(package().home_dir().absFileName(), absFileName());
s += ".emergency";
lyxerr << ' ' << s << endl;
if (writeFile(FileName(s))) {
// 3) In "/tmp" directory.
// MakeAbsPath to prepend the current
// drive letter on OS/2
- s = addName(package().temp_dir().absFilename(), absFileName());
+ s = addName(package().temp_dir().absFileName(), absFileName());
s += ".emergency";
lyxerr << ' ' << s << endl;
if (writeFile(FileName(s))) {
if (!original_path.empty()) {
// FIXME UNICODE
// We don't know the encoding of inputpath
- docstring const inputpath = from_utf8(latex_path(original_path));
- os << "\\makeatletter\n"
- << "\\def\\input@path{{"
- << inputpath << "/}}\n"
- << "\\makeatother\n";
- d->texrow.newline();
- d->texrow.newline();
- d->texrow.newline();
+ docstring const inputpath = from_utf8(support::latex_path(original_path));
+ docstring uncodable_glyphs;
+ Encoding const * const enc = runparams.encoding;
+ if (enc) {
+ for (size_t n = 0; n < inputpath.size(); ++n) {
+ docstring const glyph =
+ docstring(1, inputpath[n]);
+ if (enc->latexChar(inputpath[n], true) != glyph) {
+ LYXERR0("Uncodable character '"
+ << glyph
+ << "' in input path!");
+ uncodable_glyphs += glyph;
+ }
+ }
+ }
+
+ // warn user if we found uncodable glyphs.
+ if (!uncodable_glyphs.empty()) {
+ frontend::Alert::warning(_("Uncodable character in file path"),
+ support::bformat(_("The path of your document\n"
+ "(%1$s)\n"
+ "contains glyphs that are unknown in the\n"
+ "current document encoding (namely %2$s).\n"
+ "This will likely result in incomplete output.\n\n"
+ "Choose an appropriate document encoding (such as utf8)\n"
+ "or change the file path name."), inputpath, uncodable_glyphs));
+ } else {
+ os << "\\makeatletter\n"
+ << "\\def\\input@path{{"
+ << inputpath << "/}}\n"
+ << "\\makeatother\n";
+ d->texrow.newline();
+ d->texrow.newline();
+ d->texrow.newline();
+ }
}
// get parent macros (if this buffer has a parent) which will be
// output the parent macros
MacroSet::iterator it = parentMacros.begin();
MacroSet::iterator end = parentMacros.end();
- for (; it != end; ++it)
- (*it)->write(os, true);
+ for (; it != end; ++it) {
+ int num_lines = (*it)->write(os, true);
+ d->texrow.newlines(num_lines);
+ }
+
} // output_preamble
d->texrow.start(paragraphs().begin()->id(), 0);
// Just to be sure. (Asger)
d->texrow.newline();
+ //for (int i = 0; i<d->texrow.rows(); i++) {
+ // int id,pos;
+ // if (d->texrow.getIdFromRow(i+1,id,pos) && id>0)
+ // lyxerr << i+1 << ":" << id << ":" << getParFromID(id).paragraph().asString()<<"\n";
+ //}
+
LYXERR(Debug::INFO, "Finished making LaTeX file.");
LYXERR(Debug::INFO, "Row count was " << d->texrow.rows() - 1 << '.');
}
if (!openFileWrite(ofs, fname))
return;
- writeDocBookSource(ofs, fname.absFilename(), runparams, body_only);
+ writeDocBookSource(ofs, fname.absFileName(), runparams, body_only);
ofs.close();
if (ofs.fail())
{
LaTeXFeatures features(*this, params(), runparams);
validate(features);
- updateLabels(UpdateMaster, true);
-
- d->texrow.reset();
+ updateBuffer(UpdateMaster, OutputUpdate);
+ d->bibinfo_.makeCitationLabels(*this);
+ updateMacros();
+ updateMacroInstances();
if (!only_body) {
- os << "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n";
- os << "<!DOCTYPE html PUBLIC \"-//W3C//DTD XHTML 1.1 plus MathML 2.0//EN\" \"http://www.w3.org/TR/MathML2/dtd/xhtml-math11-f.dtd\">\n";
- // FIXME Language should be set properly.
- os << "<html xmlns=\"http://www.w3.org/1999/xhtml\">\n";
- // FIXME Header
- os << "<head>\n";
- // FIXME Presumably need to set this right
- os << "<meta http-equiv=\"Content-type\" content=\"text/html;charset=UTF-8\" />\n";
- // FIXME Get this during validation? What about other meta-data?
- os << "<title>TBA</title>\n";
+ os << "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n"
+ << "<!DOCTYPE html PUBLIC \"-//W3C//DTD XHTML 1.1 plus MathML 2.0//EN\" \"http://www.w3.org/TR/MathML2/dtd/xhtml-math11-f.dtd\">\n"
+ // FIXME Language should be set properly.
+ << "<html xmlns=\"http://www.w3.org/1999/xhtml\">\n"
+ << "<head>\n"
+ << "<meta name=\"GENERATOR\" content=\"" << PACKAGE_STRING << "\" />\n"
+ // FIXME Presumably need to set this right
+ << "<meta http-equiv=\"Content-type\" content=\"text/html;charset=UTF-8\" />\n";
+
+ docstring const & doctitle = features.htmlTitle();
+ os << "<title>"
+ << (doctitle.empty() ? from_ascii("LyX Document") : doctitle)
+ << "</title>\n";
os << "\n<!-- Text Class Preamble -->\n"
- << features.getTClassHTMLPreamble()
- << "\n<!-- Premable Snippets -->\n"
- << from_utf8(features.getPreambleSnippets());
+ << features.getTClassHTMLPreamble()
+ << "\n<!-- Premable Snippets -->\n"
+ << from_utf8(features.getPreambleSnippets());
os << "\n<!-- Layout-provided Styles -->\n";
docstring const styleinfo = features.getTClassHTMLStyles();
// get LaTeX-Filename
FileName const path(temppath());
- string const name = addName(path.absFilename(), latexName());
+ string const name = addName(path.absFileName(), latexName());
string const org_path = filePath();
PathChanger p(path); // path to LaTeX file
OutputParams runparams(¶ms().encoding());
runparams.flavor = OutputParams::LATEX;
runparams.nice = false;
+ runparams.linelen = lyxrc.plaintext_linelen;
makeLaTeXFile(FileName(name), org_path, runparams);
TeXErrors terr;
- Chktex chktex(lyxrc.chktex_command, onlyFilename(name), filePath());
+ Chktex chktex(lyxrc.chktex_command, onlyFileName(name), filePath());
int const res = chktex.run(terr); // run chktex
if (res == -1) {
updateMacros();
for_each(paragraphs().begin(), paragraphs().end(),
- boost::bind(&Paragraph::validate, _1, boost::ref(features)));
+ bind(&Paragraph::validate, _1, ref(features)));
if (lyxerr.debugging(Debug::LATEX)) {
features.showStruct();
void Buffer::updateBibfilesCache(UpdateScope scope) const
{
+ // FIXME This is probably unnecssary, given where we call this.
// If this is a child document, use the parent's cache instead.
Buffer const * const pbuf = d->parent();
if (pbuf && scope != UpdateChildOnly) {
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<InsetBibtex const &>(*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) {
InsetInclude & inset =
static_cast<InsetInclude &>(*it);
- inset.updateBibfilesCache();
+ Buffer const * const incbuf = inset.getChildBuffer();
+ if (!incbuf)
+ continue;
support::FileNameList const & bibfiles =
- inset.getBibfilesCache();
- d->bibfilesCache_.insert(d->bibfilesCache_.end(),
- bibfiles.begin(),
- bibfiles.end());
+ incbuf->getBibfilesCache(UpdateChildOnly);
+ if (!bibfiles.empty()) {
+ d->bibfiles_cache_.insert(d->bibfiles_cache_.end(),
+ bibfiles.begin(),
+ bibfiles.end());
+ }
}
}
- // the bibinfo cache is now invalid
- d->bibinfoCacheValid_ = false;
+ d->bibfile_cache_valid_ = true;
+ d->bibinfo_cache_valid_ = false;
+}
+
+
+void Buffer::invalidateBibinfoCache() const
+{
+ d->bibinfo_cache_valid_ = false;
+ // also invalidate the cache for the parent buffer
+ Buffer const * const pbuf = d->parent();
+ if (pbuf)
+ pbuf->invalidateBibinfoCache();
}
-void Buffer::invalidateBibinfoCache()
+void Buffer::invalidateBibfileCache() const
{
- d->bibinfoCacheValid_ = false;
+ d->bibfile_cache_valid_ = false;
+ d->bibinfo_cache_valid_ = false;
+ // also invalidate the cache for the parent buffer
+ Buffer const * const pbuf = d->parent();
+ if (pbuf)
+ pbuf->invalidateBibfileCache();
}
support::FileNameList const & Buffer::getBibfilesCache(UpdateScope scope) const
{
- // If this is a child document, use the parent's cache instead.
- Buffer const * const pbuf = d->parent();
- if (pbuf && scope != UpdateChildOnly)
+ // FIXME This is probably unnecessary, given where we call this.
+ // If this is a child document, use the master's cache instead.
+ Buffer const * const pbuf = masterBuffer();
+ if (pbuf != this && 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(scope);
+ if (!d->bibfile_cache_valid_)
+ this->updateBibfilesCache(scope);
- return d->bibfilesCache_;
+ return d->bibfiles_cache_;
}
BiblioInfo const & Buffer::masterBibInfo() const
{
- // if this is a child document and the parent is already loaded
- // use the parent's list instead [ale990412]
Buffer const * const tmp = masterBuffer();
- LASSERT(tmp, /**/);
if (tmp != this)
return tmp->masterBibInfo();
- return localBibInfo();
+ return d->bibinfo_;
}
-BiblioInfo const & Buffer::localBibInfo() const
+void Buffer::checkBibInfoCache() 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;
- }
- }
+ // use the master's cache
+ Buffer const * const tmp = masterBuffer();
+ if (tmp != this) {
+ tmp->checkBibInfoCache();
+ return;
}
- if (!d->bibinfoCacheValid_) {
+ // 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();
+ 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 not valid, then reload the info
+ 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;
+ fillWithBibKeys(d->bibinfo_);
+ d->bibinfo_cache_valid_ = true;
}
- return d->bibinfo_;
+}
+
+
+void Buffer::fillWithBibKeys(BiblioInfo & keys) const
+{
+ for (InsetIterator it = inset_iterator_begin(inset()); it; ++it)
+ it->fillWithBibKeys(keys, it);
}
bool enable = true;
- switch (cmd.action) {
+ switch (cmd.action()) {
case LFUN_BUFFER_TOGGLE_READ_ONLY:
flag.setOnOff(isReadonly());
{
if (isInternal()) {
// FIXME? if there is an Buffer LFUN that can be dispatched even
- // if internal, put a switch '(cmd.action)' here.
+ // if internal, put a switch '(cmd.action())' here.
dr.dispatched(false);
return;
}
bool dispatched = true;
undo().beginUndoGroup();
- switch (func.action) {
+ switch (func.action()) {
case LFUN_BUFFER_TOGGLE_READ_ONLY:
if (lyxvc().inUse())
lyxvc().toggleReadOnly();
break;
case LFUN_BUFFER_EXPORT: {
- bool success = doExport(argument, false);
- dr.setError(success);
+ bool success = doExport(argument, false, false);
+ dr.setError(!success);
if (!success)
dr.setMessage(bformat(_("Error exporting to format: %1$s."),
func.argument()));
}
case LFUN_BUILD_PROGRAM:
- doExport("program", true);
+ doExport("program", true, false);
break;
case LFUN_BUFFER_CHKTEX:
break;
} else {
- doExport(format_name, true, filename);
+ doExport(format_name, true, false, filename);
}
// Substitute $$FName for filename
break;
case LFUN_BRANCH_ADD: {
- docstring const branch_name = func.argument();
+ docstring branch_name = func.argument();
if (branch_name.empty()) {
dispatched = false;
break;
}
BranchList & branch_list = params().branchlist();
- Branch * branch = branch_list.find(branch_name);
- if (branch) {
- LYXERR0("Branch " << branch_name << " already exists.");
- dr.setError(true);
- docstring const msg =
- bformat(_("Branch \"%1$s\" already exists."), branch_name);
- dr.setMessage(msg);
- } else {
- 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);
+ vector<docstring> const branches =
+ getVectorFromString(branch_name, branch_list.separator());
+ docstring msg;
+ for (vector<docstring>::const_iterator it = branches.begin();
+ it != branches.end(); ++it) {
+ branch_name = *it;
+ Branch * branch = branch_list.find(branch_name);
+ if (branch) {
+ LYXERR0("Branch " << branch_name << " already exists.");
+ dr.setError(true);
+ if (!msg.empty())
+ msg += ("\n");
+ msg += bformat(_("Branch \"%1$s\" already exists."), branch_name);
+ } else {
+ 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);
+ }
}
+ if (!msg.empty())
+ dr.setMessage(msg);
break;
}
bformat(_("Branch \"%1$s\" does not exist."), branchName);
dr.setMessage(msg);
} else {
- branch->setSelected(func.action == LFUN_BRANCH_ACTIVATE);
+ branch->setSelected(func.action() == LFUN_BRANCH_ACTIVATE);
dr.setError(false);
dr.update(Update::Force);
+ dr.forceBufferUpdate();
}
break;
}
}
}
- if (success)
+ if (success) {
dr.update(Update::Force);
+ dr.forceBufferUpdate();
+ }
break;
}
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;
docstring text = bformat(
_("The file %1$s already exists.\n\n"
"Do you want to overwrite that file?"),
- makeDisplayPath(filename.absFilename()));
+ makeDisplayPath(filename.absFileName()));
if (Alert::prompt(_("Overwrite file?"),
text, 0, 1, _("&Overwrite"), _("&Cancel")) != 0)
break;
Language const * newL = languages.getLanguage(argument);
if (!newL || oldL == newL)
break;
- if (oldL->rightToLeft() == newL->rightToLeft() && !isMultiLingual())
+ if (oldL->rightToLeft() == newL->rightToLeft() && !isMultiLingual()) {
changeLanguage(oldL, newL);
+ dr.forceBufferUpdate();
+ }
break;
}
}
+std::set<Language const *> Buffer::getLanguages() const
+{
+ std::set<Language const *> languages;
+ getLanguages(languages);
+ return languages;
+}
+
+
+void Buffer::getLanguages(std::set<Language const *> & languages) const
+{
+ ParConstIterator end = par_iterator_end();
+ // add the buffer language, even if it's not actively used
+ languages.insert(language());
+ // iterate over the paragraphs
+ for (ParConstIterator it = par_iterator_begin(); it != end; ++it)
+ it->getLanguages(languages);
+ // also children
+ std::vector<Buffer *> clist = getChildren();
+ for (vector<Buffer *>::const_iterator cit = clist.begin();
+ cit != clist.end(); ++cit)
+ (*cit)->getLanguages(languages);
+}
+
+
DocIterator Buffer::getParFromID(int const id) const
{
Buffer * buf = const_cast<Buffer *>(this);
}
-bool Buffer::isBakClean() const
-{
- return d->bak_clean;
-}
-
-
bool Buffer::isExternallyModified(CheckMethod method) const
{
LASSERT(d->filename.exists(), /**/);
// if the .lyx file has been saved, we don't need an
// autosave
d->bak_clean = true;
-}
-
-
-void Buffer::markBakClean() const
-{
- d->bak_clean = true;
+ d->undo_.markDirty();
}
string Buffer::absFileName() const
{
- return d->filename.absFilename();
+ return d->filename.absFileName();
}
string Buffer::filePath() const
{
- return d->filename.onlyPath().absFilename() + "/";
+ return d->filename.onlyPath().absFileName() + "/";
}
}
-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<Buffer *>(it->first));
}
std::vector<Buffer const *> Buffer::allRelatives() const
{
BufferSet bufs;
- collectRelatives(bufs);
+ d->collectRelatives(bufs);
BufferSet::iterator it = bufs.begin();
std::vector<Buffer const *> ret;
for (; it != bufs.end(); ++it)
clist.push_back(child);
if (grand_children) {
// 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);
+ vector<Buffer *> glist = child->getChildren();
+ clist.insert(clist.end(), glist.begin(), glist.end());
}
}
}
-std::vector<Buffer *> Buffer::getChildren(bool grand_children) const
+vector<Buffer *> Buffer::getChildren(bool grand_children) const
{
- std::vector<Buffer *> v;
+ vector<Buffer *> v;
getChildren(v, grand_children);
return v;
}
template<typename M>
-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();
}
-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);
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) {
}
// 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;
// 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;
}
// try previous file if there is one
- if (it == d->position_to_children.begin())
+ if (it == position_to_children.begin())
break;
--it;
}
return 0;
// query buffer macros
- MacroData const * data = getBufferMacro(name, pos);
+ MacroData const * data = d->getBufferMacro(name, pos);
if (data != 0)
return data;
}
-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) {
// get buffer of external file
InsetInclude const & inset =
static_cast<InsetInclude const &>(*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;
}
+ if (doing_export && iit->inset->asInsetMath()) {
+ InsetMath * im = static_cast<InsetMath *>(iit->inset);
+ if (im->asHullInset()) {
+ InsetMathHull * hull = static_cast<InsetMathHull *>(im);
+ hull->recordLocation(it);
+ }
+ }
+
if (iit->inset->lyxCode() != MATHMACRO_CODE)
continue;
// get macro data
MathMacroTemplate & macroTemplate =
static_cast<MathMacroTemplate &>(*iit->inset);
- MacroContext mc(this, it);
+ MacroContext mc(owner_, it);
macroTemplate.updateToContext(mc);
// valid?
// 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<Buffer *>(this), it));
+ macros[macroTemplate.name()][it] =
+ Impl::ScopeMacro(scope, MacroData(const_cast<Buffer *>(owner_), it));
}
// next paragraph
DocIterator it = par_iterator_begin();
DocIterator outerScope = it;
outerScope.pit() = outerScope.lastpit() + 2;
- updateMacros(it, outerScope);
+ d->updateMacros(it, outerScope);
}
// 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();
ErrorList & Buffer::errorList(string const & type) const
{
static ErrorList emptyErrorList;
- map<string, ErrorList>::iterator I = d->errorLists.find(type);
- if (I == d->errorLists.end())
+ map<string, ErrorList>::iterator it = d->errorLists.find(type);
+ if (it == d->errorLists.end())
return emptyErrorList;
- return I->second;
+ return it->second;
}
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);
}
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;
}
AutoSaveBuffer(Buffer const & buffer, FileName const & fname)
: buffer_(buffer), fname_(fname) {}
///
- virtual boost::shared_ptr<ForkedProcess> clone() const
+ virtual shared_ptr<ForkedProcess> clone() const
{
- return boost::shared_ptr<ForkedProcess>(new AutoSaveBuffer(*this));
+ return shared_ptr<ForkedProcess>(new AutoSaveBuffer(*this));
}
///
int start()
{
command_ = to_utf8(bformat(_("Auto-saving %1$s"),
- from_utf8(fname_.absFilename())));
+ from_utf8(fname_.absFileName())));
return run(DontWait);
}
private:
} // namespace anon
-FileName Buffer::getAutosaveFilename() const
+FileName Buffer::getAutosaveFileName() const
{
// if the document is unnamed try to save in the backup dir, else
// in the default document path, and as a last try in the filePath,
void Buffer::removeAutosaveFile() const
{
- FileName const f = getAutosaveFilename();
+ FileName const f = getAutosaveFileName();
if (f.exists())
f.removeFile();
}
void Buffer::moveAutosaveFile(support::FileName const & oldauto) const
{
- FileName const newauto = getAutosaveFilename();
- if (!(oldauto == newauto || oldauto.moveTo(newauto)))
- LYXERR0("Unable to remove autosave file `" << oldauto << "'!");
+ FileName const newauto = getAutosaveFileName();
+ oldauto.refresh();
+ if (newauto != oldauto && oldauto.exists())
+ if (!oldauto.moveTo(newauto))
+ LYXERR0("Unable to move autosave file `" << oldauto << "'!");
}
// 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;
// emit message signal.
message(_("Autosaving current document..."));
- AutoSaveBuffer autosave(*this, getAutosaveFilename());
+ AutoSaveBuffer autosave(*this, getAutosaveFileName());
autosave.start();
- markBakClean();
+ d->bak_clean = true;
+
resetAutosaveTimers();
}
}
+namespace {
+ // helper class, to guarantee this gets reset properly
+ class MarkAsExporting {
+ public:
+ MarkAsExporting(Buffer const * buf) : buf_(buf)
+ {
+ LASSERT(buf_, /* */);
+ buf_->setExportStatus(true);
+ }
+ ~MarkAsExporting()
+ {
+ buf_->setExportStatus(false);
+ }
+ private:
+ Buffer const * const buf_;
+ };
+}
+
+
+void Buffer::setExportStatus(bool e) const
+{
+ d->doing_export = e;
+}
+
+
+bool Buffer::isExporting() const
+{
+ return d->doing_export;
+}
+
bool Buffer::doExport(string const & format, bool put_in_tempdir,
- string & result_file) const
+ bool includeall, string & result_file) const
{
+ MarkAsExporting exporting(this);
string backend_format;
OutputParams runparams(¶ms().encoding());
runparams.flavor = OutputParams::LATEX;
runparams.linelen = lyxrc.plaintext_linelen;
+ runparams.includeall = includeall;
vector<string> backs = backends();
if (find(backs.begin(), backs.end(), format) == backs.end()) {
// Get shortest path to format
// HTML backend
else if (backend_format == "xhtml") {
runparams.flavor = OutputParams::HTML;
+ switch (params().html_math_output) {
+ case BufferParams::MathML:
+ runparams.math_flavor = OutputParams::MathAsMathML;
+ break;
+ case BufferParams::HTML:
+ runparams.math_flavor = OutputParams::MathAsHTML;
+ break;
+ case BufferParams::Images:
+ runparams.math_flavor = OutputParams::MathAsImages;
+ break;
+ case BufferParams::LaTeX:
+ runparams.math_flavor = OutputParams::MathAsLaTeX;
+ break;
+ }
+
makeLyXHTMLFile(FileName(filename), runparams);
} else if (backend_format == "lyx")
writeFile(FileName(filename));
bool const success = theConverters().convert(this, FileName(filename),
tmp_result_file, FileName(absFileName()), backend_format, format,
error_list);
- // Emit the signal to show the 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.
if (format != backend_format) {
- errors(error_type);
+ if (d->cloned_buffer_) {
+ d->cloned_buffer_->d->errorLists[error_type] =
+ d->errorLists[error_type];
+ } else
+ errors(error_type);
// also to the children, in case of master-buffer-view
std::vector<Buffer *> clist = getChildren();
for (vector<Buffer *>::const_iterator cit = clist.begin();
- cit != clist.end(); ++cit)
- (*cit)->errors(error_type, true);
+ cit != clist.end(); ++cit) {
+ if (d->cloned_buffer_) {
+ (*cit)->d->cloned_buffer_->d->errorLists[error_type] =
+ (*cit)->d->errorLists[error_type];
+ } else
+ (*cit)->errors(error_type, true);
+ }
}
- if (!success)
- return false;
if (d->cloned_buffer_) {
// Enable reverse dvi or pdf to work by copying back the texrow
// 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();
+ d->cloned_buffer_->d->errorLists[error_type] = d->errorLists[error_type];
}
+ if (!success)
+ return false;
+
if (put_in_tempdir) {
- result_file = tmp_result_file.absFilename();
+ 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<ExportedFile> const files =
runparams.exportdata->externalFiles(format);
string const dest = onlyPath(result_file);
- CopyStatus status = SUCCESS;
- for (vector<ExportedFile>::const_iterator it = files.begin();
- it != files.end() && status != CANCEL; ++it) {
+ bool use_force = use_gui ? lyxrc.export_overwrite == ALL_FILES
+ : force_overwrite == ALL_FILES;
+ CopyStatus status = use_force ? FORCE : SUCCESS;
+
+ vector<ExportedFile>::const_iterator it = files.begin();
+ vector<ExportedFile>::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()) {
// Finally copy the main file
+ use_force = use_gui ? lyxrc.export_overwrite != NO_FILES
+ : force_overwrite != NO_FILES;
+ if (status == SUCCESS && use_force)
+ status = FORCE;
status = copyFile(format, tmp_result_file,
FileName(result_file), result_file,
status == FORCE);
}
-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
{
+ MarkAsExporting exporting(this);
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);
}
{
// File information about normal file
if (!s.exists()) {
- docstring const file = makeDisplayPath(s.absFilename(), 50);
+ docstring const file = makeDisplayPath(s.absFileName(), 50);
docstring text = bformat(_("The specified document\n%1$s"
"\ncould not be read."), file);
Alert::error(_("Could not read document"), text);
}
// Check if emergency save file exists and is newer.
- FileName const e(s.absFilename() + ".emergency");
+ FileName const e(s.absFileName() + ".emergency");
if (e.exists() && s.exists() && e.lastModified() > s.lastModified()) {
- docstring const file = makeDisplayPath(s.absFilename(), 20);
+ docstring const file = makeDisplayPath(s.absFileName(), 20);
docstring const text =
bformat(_("An emergency save of the document "
"%1$s exists.\n\n"
else
str = _("Document was NOT successfully recovered.");
str += "\n\n" + bformat(_("Remove emergency file now?\n(%1$s)"),
- from_utf8(e.absFilename()));
+ makeDisplayPath(e.absFileName()));
if (!Alert::prompt(_("Delete emergency file?"), str, 1, 1,
_("&Remove"), _("&Keep it"))) {
}
// Now check if autosave file is newer.
- FileName const a(onlyPath(s.absFilename()) + '#' + onlyFilename(s.absFilename()) + '#');
+ FileName const a(onlyPath(s.absFileName()) + '#' + onlyFileName(s.absFileName()) + '#');
if (a.exists() && s.exists() && a.lastModified() > s.lastModified()) {
- docstring const file = makeDisplayPath(s.absFilename(), 20);
+ docstring const file = makeDisplayPath(s.absFileName(), 20);
docstring const text =
bformat(_("The backup of the document "
"%1$s is newer.\n\nLoad the "
bool Buffer::loadLyXFile(FileName const & s)
{
- if (s.isReadableFile()) {
+ // 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()){
+ // InsetInfo needs to know if file is under VCS
+ lyxvc().file_found_hook(s);
if (readFileHelper(s)) {
- lyxvc().file_found_hook(s);
- if (!s.isWritable())
- setReadonly(true);
+ d->read_only = !s.isWritable();
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);
- }
- }
}
return false;
}
}
-void Buffer::updateLabels(UpdateScope scope, bool out) const
+void Buffer::updateBuffer(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 (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.
// If this is a child document start with the master
if (master != this) {
bufToUpdate.insert(this);
- master->updateLabels(UpdateMaster, out);
+ master->updateBuffer(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)?
// do the real work
ParIterator parit = cbuf.par_iterator_begin();
- updateLabels(parit, out);
+ updateBuffer(parit, utype);
if (master != this)
// TocBackend update will be done later.
// 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();
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
// 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));
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));
}
-void Buffer::updateLabels(ParIterator & parit, bool out) const
+void Buffer::updateBuffer(ParIterator & parit, UpdateType utype) const
{
LASSERT(parit.pit() == 0, /**/);
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->updateBuffer(parit, utype);
}
}
}
if (from == end)
break;
to = from;
- if (from.paragraph().spellCheck(from.pos(), to.pos(), wl, suggestions)) {
+ from.paragraph().spellCheck();
+ SpellChecker::Result res = from.paragraph().spellCheck(from.pos(), to.pos(), wl, suggestions);
+ if (SpellChecker::misspelled(res)) {
word_lang = wl;
break;
}
bool Buffer::reload()
{
setBusy(true);
+ // c.f. bug 6587
+ removeAutosaveFile();
// e.g., read-only status could have changed due to version control
d->filename.refresh();
- docstring const disp_fn = makeDisplayPath(d->filename.absFilename());
+ docstring const disp_fn = makeDisplayPath(d->filename.absFileName());
bool const success = loadLyXFile(d->filename);
if (success) {
- updateLabels();
+ updateBuffer();
changed(true);
- errors("Parse");
+ updateTitles();
+ markClean();
message(bformat(_("Document %1$s reloaded."), disp_fn));
} else {
message(bformat(_("Could not reload document %1$s."), disp_fn));
}
setBusy(false);
+ thePreviews().removeLoader(*this);
+ if (graphics::Previews::status() != LyXRC::PREVIEW_OFF)
+ thePreviews().generateBufferPreviews(*this);
+ errors("Parse");
return success;
}
+// FIXME We could do better here, but it is complicated. What would be
+// nice is to offer either (a) to save the child buffer to an appropriate
+// location, so that it would "move with the master", or else (b) to update
+// the InsetInclude so that it pointed to the same file. But (a) is a bit
+// complicated, because the code for this lives in GuiView.
+void Buffer::checkChildBuffers()
+{
+ Impl::BufferPositionMap::iterator it = d->children_positions.begin();
+ Impl::BufferPositionMap::iterator const en = d->children_positions.end();
+ for (; it != en; ++it) {
+ DocIterator dit = it->second;
+ Buffer * cbuf = const_cast<Buffer *>(it->first);
+ if (!cbuf || !theBufferList().isLoaded(cbuf))
+ continue;
+ Inset * inset = dit.nextInset();
+ LASSERT(inset && inset->lyxCode() == INCLUDE_CODE, continue);
+ InsetInclude * inset_inc = static_cast<InsetInclude *>(inset);
+ docstring const & incfile = inset_inc->getParam("filename");
+ string oldloc = cbuf->absFileName();
+ string newloc = makeAbsPath(to_utf8(incfile),
+ onlyPath(absFileName())).absFileName();
+ if (oldloc == newloc)
+ continue;
+ // the location of the child file is incorrect.
+ Alert::warning(_("Included File Invalid"),
+ bformat(_("Saving this document to a new location has made the file:\n"
+ " %1$s\n"
+ "inaccessible. You will need to update the included filename."),
+ from_utf8(oldloc)));
+ cbuf->setParent(0);
+ inset_inc->setChildBuffer(0);
+ }
+ // invalidate cache of children
+ d->children_positions.clear();
+ d->position_to_children.clear();
+}
+
} // namespace lyx