]> git.lyx.org Git - lyx.git/blobdiff - src/Buffer.cpp
this we don't need anymore
[lyx.git] / src / Buffer.cpp
index 3f079a69d96b806cf6b6fe9b56019c9b28864c85..d6fdee79b1e6be755d81a32d2f88fa1885f1cd74 100644 (file)
@@ -51,7 +51,6 @@
 #include "ParagraphParameters.h"
 #include "ParIterator.h"
 #include "PDFOptions.h"
-#include "Session.h"
 #include "sgml.h"
 #include "TexRow.h"
 #include "TexStream.h"
@@ -78,6 +77,7 @@
 
 #include "graphics/Previews.h"
 
+#include "support/assert.h"
 #include "support/convert.h"
 #include "support/debug.h"
 #include "support/ExceptionMessage.h"
@@ -117,7 +117,7 @@ namespace os = support::os;
 
 namespace {
 
-int const LYX_FORMAT = 318;
+int const LYX_FORMAT = 328;
 
 typedef map<string, bool> DepClean;
 typedef map<docstring, pair<InsetLabel const *, Buffer::References> > RefCache;
@@ -215,6 +215,7 @@ public:
        InsetText inset;
 };
 
+
 /// Creates the per buffer temporary directory
 static FileName createBufferTmpDir()
 {
@@ -295,7 +296,7 @@ void Buffer::changed() const
 
 frontend::WorkAreaManager & Buffer::workAreaManager() const
 {
-       BOOST_ASSERT(d->wa_);
+       LASSERT(d->wa_, /**/);
        return *d->wa_;
 }
 
@@ -484,8 +485,8 @@ int Buffer::readHeader(Lexer & lex)
        ErrorList & errorList = d->errorLists["Parse"];
 
        while (lex.isOK()) {
-               lex.next();
-               string const token = lex.getString();
+               string token;
+               lex >> token;
 
                if (token.empty())
                        continue;
@@ -502,7 +503,8 @@ int Buffer::readHeader(Lexer & lex)
                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"),
@@ -539,16 +541,14 @@ bool Buffer::readDocument(Lexer & lex)
        ErrorList & errorList = d->errorLists["Parse"];
        errorList.clear();
 
-       lex.next();
-       string const token = lex.getString();
-       if (token != "\\begin_document") {
+       if (!lex.checkFor("\\begin_document")) {
                docstring const s = _("\\begin_document is missing");
                errorList.push_back(ErrorItem(_("Document header error"),
                        s, -1, 0, 0));
        }
 
        // we are reading in a brand new document
-       BOOST_ASSERT(paragraphs().empty());
+       LASSERT(paragraphs().empty(), /**/);
 
        readHeader(lex);
 
@@ -577,7 +577,19 @@ bool Buffer::readDocument(Lexer & lex)
 
        // Enable embeded files, which will set temp path and move
        // inconsistent inzip files if needed.
-       embeddedFiles().enable(params().embedded, *this, false);
+       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();
@@ -645,7 +657,7 @@ bool Buffer::readString(string const & s)
 
        // remove dummy empty par
        paragraphs().clear();
-       Lexer lex(0, 0);
+       Lexer lex;
        istringstream is(s);
        lex.setStream(is);
        FileName const name = FileName::tempName();
@@ -693,7 +705,7 @@ bool Buffer::readFile(FileName const & filename)
 
        // remove dummy empty par
        paragraphs().clear();
-       Lexer lex(0, 0);
+       Lexer lex;
        lex.setFile(fname);
        if (readFile(lex, fname) != success)
                return false;
@@ -717,38 +729,21 @@ void Buffer::setFullyLoaded(bool value)
 Buffer::ReadStatus Buffer::readFile(Lexer & lex, FileName const & filename,
                bool fromstring)
 {
-       BOOST_ASSERT(!filename.empty());
-
-       if (!lex.isOK()) {
-               Alert::error(_("Document could not be read"),
-                            bformat(_("%1$s could not be read."), from_utf8(filename.absFilename())));
-               return failure;
-       }
-
-       lex.next();
-       string const token = lex.getString();
-
-       if (!lex) {
-               Alert::error(_("Document could not be read"),
-                            bformat(_("%1$s could not be read."), from_utf8(filename.absFilename())));
-               return failure;
-       }
-
-       // the first token _must_ be...
-       if (token != "\\lyxformat") {
-               lyxerr << "Token: " << token << endl;
+       LASSERT(!filename.empty(), /**/);
 
+       // the first (non-comment) token _must_ be...
+       if (!lex.checkFor("\\lyxformat")) {
                Alert::error(_("Document format failure"),
-                            bformat(_("%1$s is not a LyX document."),
+                            bformat(_("%1$s is not a readable LyX document."),
                                       from_utf8(filename.absFilename())));
                return failure;
        }
 
-       lex.next();
-       string tmp_format = lex.getString();
+       string tmp_format;
+       lex >> tmp_format;
        //lyxerr << "LyX Format: `" << tmp_format << '\'' << endl;
        // if present remove ".," from string.
-       string::size_type dot = tmp_format.find_first_of(".,");
+       size_t dot = tmp_format.find_first_of(".,");
        //lyxerr << "           dot found at " << dot << endl;
        if (dot != string::npos)
                        tmp_format.erase(dot, 1);
@@ -913,18 +908,18 @@ bool Buffer::writeFile(FileName const & fname) const
        }
 
        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;
                }
        }
@@ -1091,6 +1086,16 @@ void Buffer::writeLaTeXSource(odocstream & os,
                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
@@ -1121,6 +1126,11 @@ void Buffer::writeLaTeXSource(odocstream & os,
                        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);
 
@@ -1130,29 +1140,23 @@ void Buffer::writeLaTeXSource(odocstream & os,
                // 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;
        }
@@ -1161,15 +1165,9 @@ void Buffer::writeLaTeXSource(odocstream & os,
        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();
@@ -1390,7 +1388,7 @@ void Buffer::updateBibfilesCache() const
                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());
@@ -1464,8 +1462,8 @@ bool Buffer::dispatch(FuncRequest const & func, bool * result)
 
 void Buffer::changeLanguage(Language const * from, Language const * to)
 {
-       BOOST_ASSERT(from);
-       BOOST_ASSERT(to);
+       LASSERT(from, /**/);
+       LASSERT(to, /**/);
 
        for_each(par_iterator_begin(),
                 par_iterator_end(),
@@ -1556,7 +1554,7 @@ bool Buffer::isBakClean() const
 
 bool Buffer::isExternallyModified(CheckMethod method) const
 {
-       BOOST_ASSERT(d->filename.exists());
+       LASSERT(d->filename.exists(), /**/);
        // if method == timestamp, check timestamp before checksum
        return (method == checksum_method 
                || d->timestamp_ != d->filename.lastModified())
@@ -1979,24 +1977,30 @@ void Buffer::listMacroNames(MacroNameSet & macros) const
 }
 
 
-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");
+               }
        }
 }
 
@@ -2047,7 +2051,7 @@ void Buffer::changeRefsIfUnique(docstring const & from, docstring const & to,
        InsetCode code)
 {
        //FIXME: This does not work for child documents yet.
-       BOOST_ASSERT(code == CITE_CODE);
+       LASSERT(code == CITE_CODE, /**/);
        // Check if the label 'from' appears more than once
        vector<docstring> labels;
        string paramName;