#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 {
namespace {
-// Do not remove the comment below, so we get merge conflict in
-// independent branches. Instead add your own.
-int const LYX_FORMAT = 413; // rgh: html_css_as_file
+int const LYX_FORMAT = LYX_FORMAT_LYX;
typedef map<string, bool> DepClean;
typedef map<docstring, pair<InsetLabel const *, Buffer::References> > RefCache;
~Impl()
{
+ delete preview_loader_;
if (wa_) {
wa_->closeAll();
delete wa_;
/// 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), cite_labels_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();
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_;
+ unnamed = cloned_buffer_->d->unnamed;
}
// 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 = const_cast<Buffer *>(it->second.second);
child->clone(bufmap);
- BufferMap::iterator it = bufmap.find(child);
- LASSERT(it != bufmap.end(), continue);
- Buffer * child_clone = it->second;
+ 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;
params().indiceslist().clear();
params().backgroundcolor = lyx::rgbFromHexName("#ffffff");
params().isbackgroundcolor = false;
- params().fontcolor = lyx::rgbFromHexName("#000000");
+ params().fontcolor = RGBColor(0, 0, 0);
params().isfontcolor = false;
- params().notefontcolor = lyx::rgbFromHexName("#cccccc");
- params().boxbgcolor = lyx::rgbFromHexName("#ff0000");
+ params().notefontcolor = RGBColor(0xCC, 0xCC, 0xCC);
+ params().boxbgcolor = RGBColor(0xFF, 0, 0);
params().html_latex_start.clear();
params().html_latex_end.clear();
params().html_math_img_scale = 1.0;
}
-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();
}
runparams.encoding = encodings.fromLyXName("utf8-plain");
string const encoding = runparams.encoding->iconvName();
- LYXERR(Debug::LATEX, "makeLaTeXFile encoding: " << encoding << "...");
+ LYXERR(Debug::LATEX, "makeLaTeXFile encoding: " << encoding << ", fname=" << fname.realPath());
ofdocstream ofs;
try { ofs.reset(encoding); }
LYXERR(Debug::INFO, "lyx document header finished");
// 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
- // with either \input or \includegraphics (what figinsets do).
- // input@path is set when the actual parameter
- // original_path is set. This is done for usual tex-file, but not
- // for nice-latex-file. (Matthias 250696)
+ // usual files have \batchmode and special input@path to allow
+ // inclusion of figures specified by an explicitly relative path
+ // (i.e., a path starting with './' or '../') with either \input or
+ // \includegraphics, as the TEXINPUTS method doesn't work in this case.
+ // input@path is set when the actual parameter original_path is set.
+ // This is done for usual tex-file, but not for nice-latex-file.
+ // (Matthias 250696)
// Note that input@path is only needed for something the user does
// in the preamble, included .tex files or ERT, files included by
// LyX work without it.
if (!original_path.empty()) {
// FIXME UNICODE
// We don't know the encoding of inputpath
- docstring const inputpath = from_utf8(support::latex_path(original_path));
+ docstring const inputpath = from_utf8(original_path);
docstring uncodable_glyphs;
Encoding const * const enc = runparams.encoding;
if (enc) {
// 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));
+ 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 current document encoding "
+ "(namely %2$s). This may result in "
+ "incomplete output, unless "
+ "TEXINPUTS contains the document "
+ "directory and you don't use "
+ "explicitly relative paths (i.e., "
+ "paths starting with './' or "
+ "'../') in the preamble or in ERT."
+ "\n\nIn case of problems, choose "
+ "an appropriate document encoding\n"
+ "(such as utf8) or change the "
+ "file path name."),
+ inputpath, uncodable_glyphs));
} else {
+ string docdir =
+ support::latex_path(original_path);
+ if (contains(docdir, '#')) {
+ docdir = subst(docdir, "#", "\\#");
+ os << "\\catcode`\\#=11"
+ "\\def\\#{#}\\catcode`\\#=6\n";
+ }
+ if (contains(docdir, '%')) {
+ docdir = subst(docdir, "%", "\\%");
+ os << "\\catcode`\\%=11"
+ "\\def\\%{%}\\catcode`\\%=14\n";
+ }
os << "\\makeatletter\n"
<< "\\def\\input@path{{"
- << inputpath << "/}}\n"
+ << docdir << "/}}\n"
<< "\\makeatother\n";
}
}
void Buffer::makeLyXHTMLFile(FileName const & fname,
- OutputParams const & runparams,
- bool const body_only) const
+ OutputParams const & runparams) const
{
LYXERR(Debug::LATEX, "makeLyXHTMLFile...");
updateBuffer(UpdateMaster, OutputUpdate);
updateMacroInstances(OutputUpdate);
- writeLyXHTMLSource(ofs, runparams, body_only);
+ writeLyXHTMLSource(ofs, runparams);
ofs.close();
if (ofs.fail())
<< styleinfo
<< "</style>\n";
}
+
+ bool const needfg = params().fontcolor != RGBColor(0, 0, 0);
+ bool const needbg = params().backgroundcolor != RGBColor(0xFF, 0xFF, 0xFF);
+ if (needfg || needbg) {
+ os << "<style type='text/css'>\nbody {\n";
+ if (needfg)
+ os << " color: "
+ << from_ascii(X11hexname(params().fontcolor))
+ << ";\n";
+ if (needbg)
+ os << " background-color: "
+ << from_ascii(X11hexname(params().backgroundcolor))
+ << ";\n";
+ os << "}\n</style>\n";
+ }
os << "</head>\n<body>\n";
}
case LFUN_BUFFER_EXPORT: {
docstring const arg = cmd.argument();
- enable = arg == "custom" || params().isExportable(to_utf8(arg));
+ if (arg == "custom") {
+ enable = true;
+ break;
+ }
+ string format = to_utf8(arg);
+ size_t pos = format.find(' ');
+ if (pos != string::npos)
+ format = format.substr(0, pos);
+ enable = params().isExportable(format);
if (!enable)
flag.message(bformat(
_("Don't know how to export to format: %1$s"), arg));
break;
case LFUN_BUFFER_EXPORT: {
- bool success = doExport(argument, false, false);
- dr.setError(!success);
- if (!success)
+ ExportStatus const status = doExport(argument, false, false);
+ dr.setError(status != ExportSuccess);
+ if (status != ExportSuccess)
dr.setMessage(bformat(_("Error exporting to format: %1$s."),
func.argument()));
break;
break;
}
- bool const update_unincluded =
- params().maintain_unincluded_children
- && !params().getIncludedChildren().empty();
- if (!doExport("dvi", true, update_unincluded)) {
+ if (!doExport("dvi", true)) {
showPrintError(absFileName());
dr.setMessage(_("Error exporting to DVI."));
break;
break;
}
- case LFUN_BUFFER_LANGUAGE: {
- Language const * oldL = params().language;
- Language const * newL = languages.getLanguage(argument);
- if (!newL || oldL == newL)
- break;
- if (oldL->rightToLeft() == newL->rightToLeft() && !isMultiLingual()) {
- changeLanguage(oldL, newL);
- dr.forceBufferUpdate();
- }
- break;
- }
-
default:
dispatched = false;
break;
{
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;
}
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];
}
}
-bool Buffer::doExport(string const & format, bool put_in_tempdir,
+Buffer::ExportStatus Buffer::doExport(string const & target, bool put_in_tempdir) const
+{
+ bool const update_unincluded =
+ params().maintain_unincluded_children
+ && !params().getIncludedChildren().empty();
+ return doExport(target, put_in_tempdir, update_unincluded);
+}
+
+
+Buffer::ExportStatus Buffer::doExport(string const & target, bool put_in_tempdir,
bool includeall, string & result_file) const
{
+ LYXERR(Debug::FILES, "target=" << target);
+ OutputParams runparams(¶ms().encoding());
+ string format = target;
+ string dest_filename;
+ size_t pos = target.find(' ');
+ if (pos != string::npos) {
+ dest_filename = target.substr(pos + 1, target.length() - pos - 1);
+ format = target.substr(0, pos);
+ runparams.export_folder = FileName(dest_filename).onlyPath().realPath();
+ FileName(dest_filename).onlyPath().createPath();
+ LYXERR(Debug::FILES, "format=" << format << ", dest_filename=" << dest_filename << ", export_folder=" << runparams.export_folder);
+ }
MarkAsExporting exporting(this);
string backend_format;
- OutputParams runparams(¶ms().encoding());
runparams.flavor = OutputParams::LATEX;
runparams.linelen = lyxrc.plaintext_linelen;
runparams.includeall = includeall;
_("No information for exporting the format %1$s."),
formats.prettyName(format)));
}
- return false;
+ return ExportNoPathToFormat;
}
runparams.flavor = converters.getFlavor(path);
} else {
backend_format = format;
+ LYXERR(Debug::FILES, "backend_format=" << backend_format);
// FIXME: Don't hardcode format names here, but use a flag
if (backend_format == "pdflatex")
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 = addName(temppath(), filename);
filename = changeExtension(filename,
formats.extension(backend_format));
+ LYXERR(Debug::FILES, "filename=" << filename);
// Plain text backend
if (backend_format == "text") {
d->cloned_buffer_->d->errorLists["Export"] =
d->errorLists["Export"];
}
- return false;
+ return ExportError;
}
} else if (!lyxrc.tex_allows_spaces
&& contains(filePath(), ' ')) {
Alert::error(_("File name error"),
_("The directory path to the document cannot contain spaces."));
- return false;
+ return ExportTexPathHasSpaces;
} else {
runparams.nice = false;
if (!makeLaTeXFile(FileName(filename), filePath(), runparams)) {
d->cloned_buffer_->d->errorLists["Export"] =
d->errorLists["Export"];
}
- return false;
+ return ExportError;
}
}
}
if (!success)
- return false;
+ return ExportConverterError;
if (put_in_tempdir) {
result_file = tmp_result_file.absFileName();
- return true;
+ return ExportSuccess;
}
- result_file = changeExtension(d->exportFileName().absFileName(), ext);
+ if (dest_filename.empty())
+ result_file = changeExtension(d->exportFileName().absFileName(), ext);
+ else
+ result_file = dest_filename;
// 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);
+ string const dest = runparams.export_folder.empty() ?
+ onlyPath(result_file) : runparams.export_folder;
bool use_force = use_gui ? lyxrc.export_overwrite == ALL_FILES
: force_overwrite == ALL_FILES;
CopyStatus status = use_force ? FORCE : SUCCESS;
vector<ExportedFile>::const_iterator const en = files.end();
for (; it != en && status != CANCEL; ++it) {
string const fmt = formats.getFormatFromFile(it->sourceName);
+ string fixedName = it->exportName;
+ if (!runparams.export_folder.empty()) {
+ // Relative pathnames starting with ../ will be sanitized
+ // if exporting to a different folder
+ while (fixedName.substr(0, 3) == "../")
+ fixedName = fixedName.substr(3, fixedName.length() - 3);
+ }
+ FileName fixedFileName = makeAbsPath(fixedName, dest);
+ fixedFileName.onlyPath().createPath();
status = copyFile(fmt, it->sourceName,
- makeAbsPath(it->exportName, dest),
- it->exportName, status == FORCE);
+ fixedFileName,
+ it->exportName, status == FORCE,
+ runparams.export_folder.empty());
}
if (status == CANCEL) {
formats.prettyName(format)));
}
- return true;
+ return ExportSuccess;
}
-bool Buffer::doExport(string const & format, bool put_in_tempdir,
- bool includeall) const
+Buffer::ExportStatus Buffer::doExport(string const & target, bool put_in_tempdir,
+ bool includeall) const
{
string result_file;
// (1) export with all included children (omit \includeonly)
- if (includeall && !doExport(format, put_in_tempdir, true, result_file))
- return false;
+ if (includeall) {
+ ExportStatus const status =
+ doExport(target, put_in_tempdir, true, result_file);
+ if (status != ExportSuccess)
+ return status;
+ }
// (2) export with included children only
- return doExport(format, put_in_tempdir, false, result_file);
+ return doExport(target, put_in_tempdir, false, result_file);
}
-bool Buffer::preview(string const & format, bool includeall) const
+Buffer::ExportStatus Buffer::preview(string const & format) const
+{
+ bool const update_unincluded =
+ params().maintain_unincluded_children
+ && !params().getIncludedChildren().empty();
+ return preview(format, update_unincluded);
+}
+
+Buffer::ExportStatus Buffer::preview(string const & format, bool includeall) const
{
MarkAsExporting exporting(this);
string result_file;
// (1) export with all included children (omit \includeonly)
- if (includeall && !doExport(format, true, true))
- return false;
+ if (includeall) {
+ ExportStatus const status = doExport(format, true, true);
+ if (status != ExportSuccess)
+ return status;
+ }
// (2) export with included children only
- if (!doExport(format, true, false, result_file))
- return false;
- return formats.view(*this, FileName(result_file), format);
+ ExportStatus const status = doExport(format, true, false, result_file);
+ if (status != ExportSuccess)
+ return status;
+ if (!formats.view(*this, FileName(result_file), format))
+ return PreviewError;
+ return PreviewSuccess;
}
// 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());
}
WordLangTuple wl;
suggestions.clear();
word_lang = WordLangTuple();
+ bool const to_end = to.empty();
+ DocIterator const end = to_end ? doc_iterator_end(this) : to;
// OK, we start from here.
- DocIterator const end = doc_iterator_end(this);
for (; from != end; from.forwardPos()) {
// We are only interested in text so remove the math CursorSlice.
while (from.inMathed()) {
from.pos()++;
}
// If from is at the end of the document (which is possible
- // when leaving the mathed) LyX will crash later.
- if (from == end)
+ // when leaving the mathed) LyX will crash later otherwise.
+ if (from.atEnd() || (!to_end && from >= end))
break;
to = from;
from.paragraph().spellCheck();