namespace {
-// Do not remove the comment below, so we get merge conflict in
-// independent branches. Instead add your own.
-int const LYX_FORMAT = 416; //uwestoehr : support for horizontal spaces (bug 7728)
+int const LYX_FORMAT = LYX_FORMAT_LYX;
typedef map<string, bool> DepClean;
typedef map<docstring, pair<InsetLabel const *, Buffer::References> > RefCache;
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;
}
Impl::BufferPositionMap::iterator end = d->children_positions.end();
for (; it != end; ++it) {
Buffer * child = const_cast<Buffer *>(it->first);
- if (d->cloned_buffer_)
+ if (isClone())
delete child;
// The child buffer might have been closed already.
else if (theBufferList().isLoaded(child))
PreviewLoader * Buffer::loader() const
{
- if (lyxrc.preview == LyXRC::PREVIEW_OFF)
+ if (!isExporting() && lyxrc.preview == LyXRC::PREVIEW_OFF)
return 0;
if (!d->preview_loader_)
d->preview_loader_ = new PreviewLoader(*this);
bool Buffer::makeLaTeXFile(FileName const & fname,
+ string const & original_path,
OutputParams const & runparams_in,
- bool output_preamble, bool output_body) const
+ OutputWhat output) const
{
OutputParams runparams = runparams_in;
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); }
try {
os.texrow().reset();
- writeLaTeXSource(os, runparams, output_preamble, output_body);
+ writeLaTeXSource(os, original_path, runparams, output);
}
catch (EncodingException & e) {
odocstringstream ods;
void Buffer::writeLaTeXSource(otexstream & os,
+ string const & original_path,
OutputParams const & runparams_in,
- bool const output_preamble, bool const output_body) const
+ OutputWhat output) const
{
// The child documents, if any, shall be already loaded at this point.
validate(features);
LYXERR(Debug::LATEX, " Buffer validation done.");
+ bool const output_preamble =
+ output == FullSource || output == OnlyPreamble;
+ bool const output_body =
+ output == FullSource || output == OnlyBody;
+
// The starting paragraph of the coming rows is the
// first paragraph of the document. (Asger)
if (output_preamble && runparams.nice) {
}
LYXERR(Debug::INFO, "lyx document header finished");
- // With respect to nice LaTeX, usual files have \batchmode
+ // There are a few differences between nice LaTeX and usual files:
+ // 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 (output_preamble) {
if (!runparams.nice) {
// code for usual, NOT nice-latex-file
os << "\\batchmode\n"; // changed from \nonstopmode
}
+ if (!original_path.empty()) {
+ // FIXME UNICODE
+ // We don't know the encoding of inputpath
+ docstring const inputpath = from_utf8(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 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{{"
+ << docdir << "/}}\n"
+ << "\\makeatother\n";
+ }
+ }
// get parent macros (if this buffer has a parent) which will be
// written at the document begin further down.
void Buffer::makeDocBookFile(FileName const & fname,
OutputParams const & runparams,
- bool const body_only) const
+ OutputWhat output) const
{
LYXERR(Debug::LATEX, "makeDocBookFile...");
updateBuffer();
updateMacroInstances(OutputUpdate);
- writeDocBookSource(ofs, fname.absFileName(), runparams, body_only);
+ writeDocBookSource(ofs, fname.absFileName(), runparams, output);
ofs.close();
if (ofs.fail())
void Buffer::writeDocBookSource(odocstream & os, string const & fname,
OutputParams const & runparams,
- bool const only_body) const
+ OutputWhat output) const
{
LaTeXFeatures features(*this, params(), runparams);
validate(features);
DocumentClass const & tclass = params().documentClass();
string const top_element = tclass.latexname();
- if (!only_body) {
+ bool const output_preamble =
+ output == FullSource || output == OnlyPreamble;
+ bool const output_body =
+ output == FullSource || output == OnlyBody;
+
+ if (output_preamble) {
if (runparams.flavor == OutputParams::XML)
os << "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n";
os << ">\n\n";
}
- string top = top_element;
- top += " lang=\"";
- if (runparams.flavor == OutputParams::XML)
- top += params().language->code();
- else
- top += params().language->code().substr(0, 2);
- top += '"';
-
- if (!params().options.empty()) {
- top += ' ';
- top += params().options;
+ if (output_body) {
+ string top = top_element;
+ top += " lang=\"";
+ if (runparams.flavor == OutputParams::XML)
+ top += params().language->code();
+ else
+ top += params().language->code().substr(0, 2);
+ top += '"';
+
+ if (!params().options.empty()) {
+ top += ' ';
+ top += params().options;
+ }
+
+ os << "<!-- " << ((runparams.flavor == OutputParams::XML)? "XML" : "SGML")
+ << " file was created by LyX " << lyx_version
+ << "\n See http://www.lyx.org/ for more information -->\n";
+
+ params().documentClass().counters().reset();
+
+ sgml::openTag(os, top);
+ os << '\n';
+ docbookParagraphs(text(), *this, os, runparams);
+ sgml::closeTag(os, top_element);
}
-
- os << "<!-- " << ((runparams.flavor == OutputParams::XML)? "XML" : "SGML")
- << " file was created by LyX " << lyx_version
- << "\n See http://www.lyx.org/ for more information -->\n";
-
- params().documentClass().counters().reset();
-
- sgml::openTag(os, top);
- os << '\n';
- docbookParagraphs(text(), *this, os, runparams);
- sgml::closeTag(os, top_element);
}
updateBuffer(UpdateMaster, OutputUpdate);
updateMacroInstances(OutputUpdate);
- writeLyXHTMLSource(ofs, runparams);
+ writeLyXHTMLSource(ofs, runparams, FullSource);
ofs.close();
if (ofs.fail())
void Buffer::writeLyXHTMLSource(odocstream & os,
OutputParams const & runparams,
- bool const only_body) const
+ OutputWhat output) const
{
LaTeXFeatures features(*this, params(), runparams);
validate(features);
d->bibinfo_.makeCitationLabels(*this);
- if (!only_body) {
+ bool const output_preamble =
+ output == FullSource || output == OnlyPreamble;
+ bool const output_body =
+ output == FullSource || output == OnlyBody;
+
+ if (output_preamble) {
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.
docstring const & doctitle = features.htmlTitle();
os << "<title>"
- << (doctitle.empty() ? from_ascii("LyX Document") : doctitle)
+ << (doctitle.empty() ?
+ from_ascii("LyX Document") :
+ html::htmlize(doctitle, XHTMLStream::ESCAPE_ALL))
<< "</title>\n";
os << "\n<!-- Text Class Preamble -->\n"
<< ";\n";
os << "}\n</style>\n";
}
- os << "</head>\n<body>\n";
+ os << "</head>\n";
+ }
+
+ if (output_body) {
+ os << "<body>\n";
+ XHTMLStream xs(os);
+ params().documentClass().counters().reset();
+ xhtmlParagraphs(text(), *this, xs, runparams);
+ os << "</body>\n";
}
- XHTMLStream xs(os);
- params().documentClass().counters().reset();
- xhtmlParagraphs(text(), *this, xs, runparams);
- if (!only_body)
- os << "</body>\n</html>\n";
+ if (output_preamble)
+ os << "</html>\n";
}
// get LaTeX-Filename
FileName const path(temppath());
string const name = addName(path.absFileName(), latexName());
+ string const org_path = filePath();
PathChanger p(path); // path to LaTeX file
message(_("Running chktex..."));
runparams.flavor = OutputParams::LATEX;
runparams.nice = false;
runparams.linelen = lyxrc.plaintext_linelen;
- makeLaTeXFile(FileName(name), runparams);
+ makeLaTeXFile(FileName(name), org_path, runparams);
TeXErrors terr;
Chktex chktex(lyxrc.chktex_command, onlyFileName(name), filePath());
break;
case LFUN_BUFFER_EXPORT: {
- bool success = doExport(argument, false, false);
- dr.setError(!success);
- if (!success)
+ ExportStatus const status = doExport(argument, false);
+ dr.setError(status != ExportSuccess);
+ if (status != ExportSuccess)
dr.setMessage(bformat(_("Error exporting to format: %1$s."),
func.argument()));
break;
}
case LFUN_BUILD_PROGRAM:
- doExport("program", true, false);
+ doExport("program", true);
break;
case LFUN_BUFFER_CHKTEX:
break;
} else {
- doExport(format_name, true, false, filename);
+ doExport(format_name, true, filename);
}
// Substitute $$FName for filename
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;
void Buffer::getSourceCode(odocstream & os, string const format,
pit_type par_begin, pit_type par_end,
- bool full_source) const
+ OutputWhat output) const
{
OutputParams runparams(¶ms().encoding());
runparams.nice = true;
// No side effect of file copying and image conversion
runparams.dryrun = true;
- if (full_source) {
- os << "% " << _("Preview source code") << "\n\n";
- d->texrow.reset();
- d->texrow.newline();
- d->texrow.newline();
- if (params().isDocBook())
- writeDocBookSource(os, absFileName(), runparams, false);
- else if (runparams.flavor == OutputParams::HTML)
- writeLyXHTMLSource(os, runparams, false);
- else {
- // latex or literate
- otexstream ots(os, d->texrow);
- writeLaTeXSource(ots, runparams, true, true);
- }
- } else {
+ if (output == CurrentParagraph) {
runparams.par_begin = par_begin;
runparams.par_end = par_end;
if (par_begin + 1 == par_end) {
otexstream ots(os, texrow);
latexParagraphs(*this, text(), ots, runparams);
}
+ } else {
+ os << "% ";
+ if (output == FullSource)
+ os << _("Preview source code");
+ else if (output == OnlyPreamble)
+ os << _("Preview preamble");
+ else if (output == OnlyBody)
+ os << _("Preview body");
+ os << "\n\n";
+ d->texrow.reset();
+ d->texrow.newline();
+ d->texrow.newline();
+ if (params().isDocBook())
+ writeDocBookSource(os, absFileName(), runparams, output);
+ else if (runparams.flavor == OutputParams::HTML)
+ writeLyXHTMLSource(os, runparams, output);
+ else {
+ // latex or literate
+ otexstream ots(os, d->texrow);
+ writeLaTeXSource(ots, string(), runparams, output);
+ }
}
}
}
-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_;
- };
-}
+// helper class, to guarantee this gets reset properly
+class Buffer::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
}
-bool Buffer::doExport(string const & target, bool put_in_tempdir,
+Buffer::ExportStatus Buffer::doExport(string const & target, bool put_in_tempdir)
+ const
+{
+ string result_file;
+ return doExport(target, put_in_tempdir, result_file);
+}
+
+Buffer::ExportStatus Buffer::doExport(string const & target, bool put_in_tempdir,
+ string & result_file) const
+{
+ bool const update_unincluded =
+ params().maintain_unincluded_children
+ && !params().getIncludedChildren().empty();
+
+ // (1) export with all included children (omit \includeonly)
+ if (update_unincluded) {
+ ExportStatus const status =
+ doExport(target, put_in_tempdir, true, result_file);
+ if (status != ExportSuccess)
+ return status;
+ }
+ // (2) export with included children only
+ return doExport(target, put_in_tempdir, false, result_file);
+}
+
+
+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 filename;
+ string dest_filename;
size_t pos = target.find(' ');
if (pos != string::npos) {
- filename = target.substr(pos + 1, target.length() - pos - 1);
+ dest_filename = target.substr(pos + 1, target.length() - pos - 1);
format = target.substr(0, pos);
- runparams.export_folder = FileName(filename).onlyPath().realPath();
- FileName(filename).onlyPath().createPath();
+ 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;
_("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;
runparams.flavor = OutputParams::XETEX;
}
- if (filename.empty()) {
- filename = latexName(false);
- filename = addName(temppath(), filename);
- filename = changeExtension(filename,
- formats.extension(backend_format));
- }
+ string filename = latexName(false);
+ filename = addName(temppath(), filename);
+ filename = changeExtension(filename,
+ formats.extension(backend_format));
+ LYXERR(Debug::FILES, "filename=" << filename);
// Plain text backend
if (backend_format == "text") {
// LaTeX backend
else if (backend_format == format) {
runparams.nice = true;
- if (!makeLaTeXFile(FileName(filename), runparams)) {
+ if (!makeLaTeXFile(FileName(filename), string(), runparams)) {
if (d->cloned_buffer_) {
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), runparams)) {
+ if (!makeLaTeXFile(FileName(filename), filePath(), runparams)) {
if (d->cloned_buffer_) {
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 =
if (status == CANCEL) {
message(_("Document export cancelled."));
- } else if (tmp_result_file.exists()) {
+ return ExportCancel;
+ }
+
+ if (tmp_result_file.exists()) {
// Finally copy the main file
use_force = use_gui ? lyxrc.export_overwrite != NO_FILES
: force_overwrite != NO_FILES;
status = copyFile(format, tmp_result_file,
FileName(result_file), result_file,
status == FORCE);
- message(bformat(_("Document exported as %1$s "
- "to file `%2$s'"),
- formats.prettyName(format),
- makeDisplayPath(result_file)));
+ if (status == CANCEL) {
+ message(_("Document export cancelled."));
+ return ExportCancel;
+ } else {
+ message(bformat(_("Document exported as %1$s "
+ "to file `%2$s'"),
+ formats.prettyName(format),
+ makeDisplayPath(result_file)));
+ }
} else {
// This must be a dummy converter like fax (bug 1888)
message(bformat(_("Document exported as %1$s"),
formats.prettyName(format)));
}
- return true;
+ return ExportSuccess;
}
-bool Buffer::doExport(string const & target, bool put_in_tempdir,
- bool includeall) const
+Buffer::ExportStatus Buffer::preview(string const & format) const
{
- string result_file;
- // (1) export with all included children (omit \includeonly)
- if (includeall && !doExport(target, put_in_tempdir, true, result_file))
- return false;
- // (2) export with included children only
- return doExport(target, put_in_tempdir, false, result_file);
+ bool const update_unincluded =
+ params().maintain_unincluded_children
+ && !params().getIncludedChildren().empty();
+ return preview(format, update_unincluded);
}
-
-bool Buffer::preview(string const & format, bool includeall) const
+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, result_file);
+ 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;
}
}
// If from is at the end of the document (which is possible
// when leaving the mathed) LyX will crash later otherwise.
- if (from.atEnd() || !to_end && from >= end)
+ if (from.atEnd() || (!to_end && from >= end))
break;
to = from;
from.paragraph().spellCheck();