]> git.lyx.org Git - lyx.git/blobdiff - src/buffer.C
fix reading the author field.
[lyx.git] / src / buffer.C
index 708222efaf400dee92b50f1be4b7fc6e3302838a..67127e1ef850efcdf663daf949467057ea5bbc4b 100644 (file)
@@ -20,6 +20,7 @@
 #include "Bullet.h"
 #include "Chktex.h"
 #include "debug.h"
+#include "encoding.h"
 #include "errorlist.h"
 #include "exporter.h"
 #include "format.h"
 #include "insets/insetinclude.h"
 #include "insets/insettext.h"
 
+#include "mathed/math_macrotemplate.h"
+#include "mathed/math_macrotable.h"
+#include "mathed/math_support.h"
+
 #include "frontends/Alert.h"
 
 #include "graphics/Previews.h"
 #include "support/path.h"
 #include "support/textutils.h"
 #include "support/tostr.h"
-#include "support/std_sstream.h"
 
 #include <boost/bind.hpp>
 
+#include <utime.h>
+
 #include <iomanip>
 #include <stack>
+#include <sstream>
 
-#include <utime.h>
 
 using lyx::pos_type;
 using lyx::par_type;
@@ -116,6 +122,7 @@ using std::make_pair;
 
 using std::ifstream;
 using std::ios;
+using std::map;
 using std::ostream;
 using std::ostringstream;
 using std::ofstream;
@@ -130,7 +137,7 @@ extern BufferList bufferlist;
 
 namespace {
 
-const int LYX_FORMAT = 232;
+const int LYX_FORMAT = 236;
 
 } // namespace anon
 
@@ -179,6 +186,9 @@ struct Buffer::Impl
 
        /// our LyXText that should be wrapped in an InsetText
        InsetText inset;
+
+       ///
+       MacroTable macros;
 };
 
 
@@ -383,9 +393,11 @@ void unknownClass(string const & unknown)
 int Buffer::readHeader(LyXLex & lex)
 {
        int unknown_tokens = 0;
+       int line = -1;
+       int begin_header_line = -1;
 
        while (lex.isOK()) {
-               lex.nextToken();
+               lex.next();
                string const token = lex.getString();
 
                if (token.empty())
@@ -394,13 +406,18 @@ int Buffer::readHeader(LyXLex & lex)
                if (token == "\\end_header")
                        break;
 
+               ++line;
+               if (token == "\\begin_header") {
+                       begin_header_line = line;
+                       continue;
+               }
+
                lyxerr[Debug::PARSER] << "Handling header token: `"
                                      << token << '\'' << endl;
 
-
                string unknown = params().readToken(lex, token);
                if (!unknown.empty()) {
-                       if (unknown[0] != '\\') {
+                       if (unknown[0] != '\\' and token == "\\textclass") {
                                unknownClass(unknown);
                        } else {
                                ++unknown_tokens;
@@ -413,6 +430,10 @@ int Buffer::readHeader(LyXLex & lex)
                        }
                }
        }
+       if (begin_header_line) {
+               string const s = _("\\begin_header is missing");
+               error(ErrorItem(_("Header error"), s, -1, 0, 0));
+       }
        return unknown_tokens;
 }
 
@@ -420,8 +441,15 @@ int Buffer::readHeader(LyXLex & lex)
 // Uwe C. Schroeder
 // changed to be public and have one parameter
 // Returns false if "\end_document" is not read (Asger)
-bool Buffer::readBody(LyXLex & lex)
+bool Buffer::readDocument(LyXLex & lex)
 {
+       lex.next();
+       string const token = lex.getString();
+       if (token != "\\begin_document") {
+               string const s = _("\\begin_document is missing");
+               error(ErrorItem(_("Header error"), s, -1, 0, 0));
+       }
+
        if (paragraphs().empty()) {
                readHeader(lex);
                if (!params().getLyXTextClass().load()) {
@@ -456,8 +484,7 @@ void Buffer::insertStringAsLines(ParagraphList & pars,
        pars[par].checkInsertChar(font);
        // insert the string, don't insert doublespace
        bool space_inserted = true;
-       bool autobreakrows = !pars[par].inInset() ||
-               static_cast<InsetText *>(pars[par].inInset())->getAutoBreakRows();
+       bool autobreakrows = pars[par].autoBreakRows();
        for (string::const_iterator cit = str.begin();
            cit != str.end(); ++cit) {
                if (*cit == '\n') {
@@ -572,7 +599,7 @@ bool Buffer::readFile(LyXLex & lex, string const & filename, par_type pit)
                return false;
        }
 
-       lex.eatLine();
+       lex.next();
        string tmp_format = lex.getString();
        //lyxerr << "LyX Format: `" << tmp_format << '\'' << endl;
        // if present remove ".," from string.
@@ -583,13 +610,7 @@ bool Buffer::readFile(LyXLex & lex, string const & filename, par_type pit)
        int file_format = strToInt(tmp_format);
        //lyxerr << "format: " << file_format << endl;
 
-       if (file_format > LYX_FORMAT) {
-               Alert::warning(_("Document format failure"),
-                              bformat(_("%1$s was created with a newer"
-                                        " version of LyX. This is likely to"
-                                        " cause problems."),
-                                        filename));
-       } else if (file_format < LYX_FORMAT) {
+       if (file_format != LYX_FORMAT) {
                string const tmpfile = tempName();
                if (tmpfile.empty()) {
                        Alert::error(_("Conversion failed"),
@@ -633,21 +654,18 @@ bool Buffer::readFile(LyXLex & lex, string const & filename, par_type pit)
 
        }
 
-       bool the_end = readBody(lex);
-       params().setPaperStuff();
-
-#warning Look here!
-#if 0
-       if (token == "\\end_document")
-               the_end_read = true;
-
-       if (!the_end) {
+       if (readDocument(lex)) {
                Alert::error(_("Document format failure"),
                             bformat(_("%1$s ended unexpectedly, which means"
                                       " that it is probably corrupted."),
                                       filename));
        }
-#endif 
+
+       //lyxerr << "removing " << MacroTable::localMacros().size()
+       //      << " temporary macro entries" << endl;
+       //MacroTable::localMacros().clear();
+       params().setPaperStuff();
+
        pimpl_->file_fully_loaded = true;
        return true;
 }
@@ -737,7 +755,7 @@ bool Buffer::writeFile(string const & fname) const
        if (finfo.exist() && !finfo.writable())
                return false;
 
-       bool retval;
+       bool retval = false;
 
        if (params().compressed) {
                gz::ogzstream ofs(fname.c_str());
@@ -770,18 +788,21 @@ bool Buffer::do_writeFile(ostream & ofs) const
        // write out a comment in the top of the file
        ofs << "#LyX " << lyx_version
            << " created this file. For more info see http://www.lyx.org/\n"
-           << "\\lyxformat " << LYX_FORMAT << "\n";
+           << "\\lyxformat " << LYX_FORMAT << "\n"
+           << "\\begin_document\n";
 
        // now write out the buffer parameters.
+       ofs << "\\begin_header\n";
        params().writeFile(ofs);
-
        ofs << "\\end_header\n";
-
+       
        // write the text
+       ofs << "\n\\begin_body\n";
        text().write(*this, ofs);
+       ofs << "\n\\end_body\n";
 
        // Write marker that shows file is complete
-       ofs << "\n\\end_document" << endl;
+       ofs << "\\end_document" << endl;
 
        // Shouldn't really be needed....
        //ofs.close();
@@ -838,6 +859,7 @@ void Buffer::makeLaTeXFile(ostream & os,
        lyxerr[Debug::LATEX] << "  Buffer validation done." << endl;
 
        texrow().reset();
+
        // The starting paragraph of the coming rows is the
        // first paragraph of the document. (Asger)
        texrow().start(paragraphs().begin()->id(), 0);
@@ -1053,7 +1075,18 @@ void Buffer::makeDocBookFile(string const & fname,
        string top_element = tclass.latexname();
 
        if (!only_body) {
-               ofs << subst(tclass.class_header(), "#", top_element);
+               if (runparams.flavor == OutputParams::XML)
+                       ofs << "<?xml version=\"1.0\" encoding=\""
+                           << params().language->encoding()->Name() << "\"?>\n";
+
+               ofs << "<!DOCTYPE " << top_element << " ";
+
+               if (! tclass.class_header().empty()) ofs << tclass.class_header();
+               else if (runparams.flavor == OutputParams::XML)
+                       ofs << "PUBLIC \"-//OASIS//DTD DocBook XML//EN\" "
+                           << "\"http://www.oasis-open.org/docbook/xml/4.2/docbookx.dtd\"";
+               else
+                       ofs << " PUBLIC \"-//OASIS//DTD DocBook V4.2//EN\"";
 
                string preamble = params().preamble;
                string const name = runparams.nice ? ChangeExtension(pimpl_->filename, ".sgml")
@@ -1069,7 +1102,10 @@ void Buffer::makeDocBookFile(string const & fname,
 
        string top = top_element;
        top += " lang=\"";
-       top += params().language->code();
+       if (runparams.flavor == OutputParams::XML)
+               top += params().language->code();
+       else
+               top += params().language->code().substr(0,2);
        top += '"';
 
        if (!params().options.empty()) {
@@ -1078,7 +1114,8 @@ void Buffer::makeDocBookFile(string const & fname,
        }
        sgml::openTag(ofs, 0, false, top);
 
-       ofs << "<!-- SGML/XML file was created by LyX " << lyx_version
+       ofs << "<!-- " << ((runparams.flavor == OutputParams::XML)? "XML" : "SGML")
+           << " file was created by LyX " << lyx_version
            << "\n  See http://www.lyx.org/ for more information -->\n";
 
        params().getLyXTextClass().counters().reset();
@@ -1192,7 +1229,7 @@ void Buffer::getLabelList(std::vector<string> & list) const
                return;
        }
 
-       for (InsetIterator it(inset()); it; ++it)
+       for (InsetIterator it = inset_iterator_begin(inset()); it; ++it)
                it.nextInset()->getLabelList(*this, list);
 }
 
@@ -1210,7 +1247,7 @@ void Buffer::fillWithBibKeys(std::vector<std::pair<string, string> > & keys)
                return;
        }
 
-       for (InsetIterator it(inset()); it; ++it) {
+       for (InsetIterator it = inset_iterator_begin(inset()); it; ++it) {
                if (it->lyxCode() == InsetOld::BIBTEX_CODE) {
                        InsetBibtex const & inset =
                                dynamic_cast<InsetBibtex const &>(*it);
@@ -1304,11 +1341,9 @@ bool Buffer::isMultiLingual() const
 
 ParIterator Buffer::getParFromID(int id) const
 {
-#warning FIXME: const correctness! (Andre)
-       ParIterator it = const_cast<Buffer*>(this)->par_iterator_begin();
-       ParIterator end = const_cast<Buffer*>(this)->par_iterator_end();
+       ParConstIterator it = par_iterator_begin();
+       ParConstIterator end = par_iterator_end();
 
-#warning FIXME, perhaps this func should return a ParIterator? (Lgb)
        if (id < 0) {
                // John says this is called with id == -1 from undo
                lyxerr << "getParFromID(), id: " << id << endl;
@@ -1344,25 +1379,25 @@ bool Buffer::hasParWithID(int id) const
 
 ParIterator Buffer::par_iterator_begin()
 {
-       return ParIterator(inset(), 0);
+       return ::par_iterator_begin(inset());
 }
 
 
 ParIterator Buffer::par_iterator_end()
 {
-       return ParIterator(DocumentIterator());
+       return ::par_iterator_end(inset());
 }
 
 
 ParConstIterator Buffer::par_iterator_begin() const
 {
-       return ParConstIterator(inset(), 0);
+       return ::par_const_iterator_begin(inset());
 }
 
 
 ParConstIterator Buffer::par_iterator_end() const
 {
-       return ParConstIterator(DocumentIterator());
+       return ::par_const_iterator_end(inset());
 }
 
 
@@ -1476,3 +1511,46 @@ Buffer const * Buffer::getMasterBuffer() const
 
        return this;
 }
+
+
+MacroData const & Buffer::getMacro(std::string const & name) const
+{
+       return pimpl_->macros.get(name);
+}
+
+
+bool Buffer::hasMacro(string const & name) const
+{
+       return pimpl_->macros.has(name);
+}
+
+
+void Buffer::insertMacro(string const & name, MacroData const & data)
+{
+       MacroTable::globalMacros().insert(name, data);
+       pimpl_->macros.insert(name, data);
+}
+
+
+void Buffer::buildMacros()
+{
+       // Start with global table.
+       pimpl_->macros = MacroTable::globalMacros();
+
+       // Now add our own.
+       ParagraphList & pars = text().paragraphs();
+       for (size_t i = 0, n = pars.size(); i != n; ++i) {
+               //lyxerr << "searching main par " << i
+               //      << " for macro definitions" << std::endl;
+               InsetList::iterator it = pars[i].insetlist.begin();
+               InsetList::iterator end = pars[i].insetlist.end();
+               for ( ; it != end; ++it) {
+                       //lyxerr << "found inset code " << it->inset->lyxCode() << std::endl;
+                       if (it->inset->lyxCode() == InsetBase::MATHMACRO_CODE) {
+                               MathMacroTemplate & mac
+                                       = static_cast<MathMacroTemplate &>(*it->inset);
+                               insertMacro(mac.name(), mac.asMacroData());
+                       }
+               }
+       }
+}