#include "ParagraphParameters.h"
#include "ParIterator.h"
#include "PDFOptions.h"
-#include "Session.h"
#include "sgml.h"
#include "TexRow.h"
#include "TexStream.h"
namespace {
-int const LYX_FORMAT = 317; // Uwe Stöhr: float placement support for wrap floats
+int const LYX_FORMAT = 325;
typedef map<string, bool> DepClean;
typedef map<docstring, pair<InsetLabel const *, Buffer::References> > RefCache;
typedef pair<DocIterator, MacroData> ScopeMacro;
typedef map<DocIterator, ScopeMacro> PositionScopeMacroMap;
typedef map<docstring, PositionScopeMacroMap> NamePositionScopeMacroMap;
+ /// 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;
typedef map<Buffer const * const, DocIterator> BufferPositionMap;
typedef pair<DocIterator, Buffer const *> ScopeBuffer;
typedef map<DocIterator, ScopeBuffer> PositionScopeBufferMap;
+ /// position of children buffers in this buffer
BufferPositionMap children_positions;
+ /// map from children inclusion positions to their scope and their buffer
PositionScopeBufferMap position_to_children;
/// Container for all sort of Buffer dependant errors.
LYXERR(Debug::PARSER, "Handling document header token: `"
<< token << '\'');
- string unknown = params().readToken(lex, token, d->filename.onlyPath());
+ string unknown = params().readToken(lex, token, d->filename.onlyPath(),
+ d->temppath);
if (!unknown.empty()) {
if (unknown[0] != '\\' && token == "\\textclass") {
Alert::warning(_("Unknown document class"),
// read main text
bool const res = text().read(*this, lex, errorList, &(d->inset));
+ // Enable embeded files, which will set temp path and move
+ // inconsistent inzip files if needed.
+ try {
+ embeddedFiles().validate(*this);
+ embeddedFiles().enable(params().embedded, *this, false);
+ } catch (ExceptionMessage const & message) {
+ Alert::error(message.title_, message.details_);
+ Alert::warning(_("Failed to read embedded files"),
+ _("Due to most likely a bug, LyX failed to locate all embedded "
+ "file. If you unzip the LyX file, you should be able to see and "
+ "open content.lyx which is your main text. You may also be able "
+ "to recover some embedded files. Please report this bug to the "
+ "lyx-devel mailing list."));
+ return false;
+ }
+
updateMacros();
updateMacroInstances();
return res;
}
if (!retval) {
- message(str + _(" could not write file!."));
+ message(str + _(" could not write file!"));
return false;
}
removeAutosaveFile(d->filename.absFilename());
if (params().embedded) {
- message(str + _(" writing embedded files!."));
+ message(str + _(" writing embedded files."));
// if embedding is enabled, write file.lyx and all the embedded files
// to the zip file fname.
if (!d->embedded_files.writeFile(fname, *this)) {
- message(str + _(" could not write embedded files!."));
+ message(str + _(" could not write embedded files!"));
return false;
}
}
d->texrow.newline();
}
LYXERR(Debug::INFO, "lyx document header finished");
+
+ // Don't move this behind the parent_buffer=0 code below,
+ // because then the macros will not get the right "redefinition"
+ // flag as they don't see the parent macros which are output before.
+ updateMacros();
+
+ // fold macros if possible, still with parent buffer as the
+ // macros will be put in the prefix anyway.
+ updateMacroInstances();
+
// There are a few differences between nice LaTeX and usual files:
// usual is \batchmode and has a
// special input@path to allow the including of figures
d->texrow.newline();
}
+ // get parent macros (if this buffer has a parent) which will be
+ // written at the document begin further down.
+ MacroSet parentMacros;
+ listParentMacros(parentMacros, features);
+
// Write the preamble
runparams.use_babel = params().writeLaTeX(os, features, d->texrow);
// make the body.
os << "\\begin{document}\n";
d->texrow.newline();
+
+ // output the parent macros
+ MacroSet::iterator it = parentMacros.begin();
+ MacroSet::iterator end = parentMacros.end();
+ for (; it != end; ++it)
+ (*it)->write(os, true);
} // output_preamble
d->texrow.start(paragraphs().begin()->id(), 0);
LYXERR(Debug::INFO, "preamble finished, now the body.");
- // Don't move this behind the parent_buffer=0 code below,
- // because then the macros will not get the right "redefinition"
- // flag as they don't see the parent macros which are output before.
- updateMacros();
-
- // fold macros if possible, still with parent buffer as the
- // macros will be put in the prefix anyway.
- updateMacroInstances();
-
// if we are doing a real file with body, even if this is the
// child of some other buffer, let's cut the link here.
// This happens for example if only a child document is printed.
Buffer const * save_parent = 0;
if (output_preamble) {
- // output the macros visible for this buffer
- writeParentMacros(os);
-
save_parent = d->parent_buffer;
d->parent_buffer = 0;
}
latexParagraphs(*this, text(), os, d->texrow, runparams);
// Restore the parenthood if needed
- if (output_preamble) {
+ if (output_preamble)
d->parent_buffer = save_parent;
- // restore macros with correct parent buffer (especially
- // important for the redefinition flag which depends on the
- // parent)
- updateMacros();
- }
-
// add this just in case after all the paragraphs
os << endl;
d->texrow.newline();
if (it->lyxCode() == BIBTEX_CODE) {
InsetBibtex const & inset =
static_cast<InsetBibtex const &>(*it);
- EmbeddedFileList const bibfiles = inset.embeddedFiles();
+ EmbeddedFileList const bibfiles = inset.getBibFiles();
d->bibfilesCache_.insert(d->bibfilesCache_.end(),
bibfiles.begin(),
bibfiles.end());
}
-void Buffer::updateEnvironmentMacros(DocIterator & it, pit_type lastpit,
- DocIterator & scope) const
+void Buffer::updateMacros(DocIterator & it, DocIterator & scope) const
{
- Paragraph & par = it.paragraph();
- depth_type depth = par.params().depth();
- Length const & leftIndent = par.params().leftIndent();
+ pit_type lastpit = it.lastpit();
// look for macros in each paragraph
while (it.pit() <= lastpit) {
Paragraph & par = it.paragraph();
- // increased depth?
- if ((par.params().depth() > depth
- || par.params().leftIndent() != leftIndent)
- && par.layout().isEnvironment()) {
- updateBlockMacros(it, scope);
- continue;
- }
-
// iterate over the insets of the current paragraph
InsetList const & insets = par.insetList();
InsetList::const_iterator iit = insets.begin();
// collect macros in inset
it.push_back(CursorSlice(*iit->inset));
- updateInsetMacros(it, newScope ? insetScope : scope);
+ updateMacros(it, newScope ? insetScope : scope);
it.pop_back();
continue;
}
}
-void Buffer::updateBlockMacros(DocIterator & it, DocIterator & scope) const
-{
- Paragraph & par = it.paragraph();
-
- // set scope for macros in this paragraph:
- // * either the "old" outer scope
- // * or the scope ending after the environment
- if (par.layout().isEnvironment()) {
- // find end of environment block,
- DocIterator envEnd = it;
- pit_type n = it.lastpit() + 1;
- depth_type depth = par.params().depth();
- Length const & length = par.params().leftIndent();
- // looping through the paragraph, basically until
- // the layout changes or the depth gets smaller.
- // (the logic of output_latex.cpp's TeXEnvironment)
- do {
- envEnd.pit()++;
- if (envEnd.pit() == n)
- break;
- } while (par.layout() == envEnd.paragraph().layout()
- || depth < envEnd.paragraph().params().depth()
- || length != envEnd.paragraph().params().leftIndent());
-
- // collect macros from environment block
- updateEnvironmentMacros(it, envEnd.pit() - 1, envEnd);
- } else {
- // collect macros from paragraph
- updateEnvironmentMacros(it, it.pit(), scope);
- }
-}
-
-
-void Buffer::updateInsetMacros(DocIterator & it, DocIterator & scope) const
-{
- // look for macros in each paragraph
- pit_type n = it.lastpit() + 1;
- while (it.pit() < n)
- updateBlockMacros(it, scope);
-}
-
-
void Buffer::updateMacros() const
{
if (d->macro_lock)
DocIterator it = par_iterator_begin();
DocIterator outerScope = it;
outerScope.pit() = outerScope.lastpit() + 2;
- updateInsetMacros(it, outerScope);
+ updateMacros(it, outerScope);
}
}
-void Buffer::writeParentMacros(odocstream & os) const
+void Buffer::listParentMacros(MacroSet & macros, LaTeXFeatures & features) const
{
if (!d->parent_buffer)
return;
-
- // collect macro names
+
MacroNameSet names;
d->parent_buffer->listMacroNames(names);
-
- // resolve and output them
+
+ // resolve macros
MacroNameSet::iterator it = names.begin();
MacroNameSet::iterator end = names.end();
for (; it != end; ++it) {
// defined?
MacroData const * data =
d->parent_buffer->getMacro(*it, *this, false);
- if (data)
- data->write(os, true);
+ if (data) {
+ macros.insert(data);
+
+ // we cannot access the original MathMacroTemplate anymore
+ // here to calls validate method. So we do its work here manually.
+ // FIXME: somehow make the template accessible here.
+ if (data->optionals() > 0)
+ features.require("xargs");
+ }
}
}