]> git.lyx.org Git - lyx.git/blobdiff - src/buffer.C
Fix natbib bug spotted by JMarc.
[lyx.git] / src / buffer.C
index 335037aa3de68bc79a34249505dec109b7fb2883..6a3c50a5d69ad9b8e3c3961b04405fe98a8279ba 100644 (file)
@@ -20,7 +20,6 @@
 
 #include "buffer.h"
 #include "bufferlist.h"
-#include "counters.h"
 #include "LyXAction.h"
 #include "lyxrc.h"
 #include "lyxlex.h"
@@ -46,6 +45,7 @@
 #include "lyxtextclasslist.h"
 #include "sgml.h"
 #include "paragraph_funcs.h"
+#include "author.h"
 
 #include "frontends/LyXView.h"
 
@@ -76,6 +76,7 @@
 #include "insets/insetoptarg.h"
 #include "insets/insetminipage.h"
 #include "insets/insetfloat.h"
+#include "insets/insetwrap.h"
 #include "insets/insettabular.h"
 #if 0
 #include "insets/insettheorem.h"
 #include "support/FileInfo.h"
 #include "support/lyxmanip.h"
 #include "support/lyxalgo.h" // for lyx::count
+#include "support/lyxtime.h"
 
 #include <boost/bind.hpp>
 #include <boost/tuple/tuple.hpp>
+#include "BoostFormat.h"
 
 #include <fstream>
 #include <iomanip>
@@ -147,14 +150,14 @@ extern BufferList bufferlist;
 
 namespace {
 
-const int LYX_FORMAT = 221;
+const int LYX_FORMAT = 222;
 
 } // namespace anon
 
 Buffer::Buffer(string const & file, bool ronly)
        : niceFile(true), lyx_clean(true), bak_clean(true),
-         unnamed(false), dep_clean(0), read_only(ronly),
-         filename_(file), users(0), ctrs(new Counters)
+         unnamed(false), read_only(ronly),
+         filename_(file), users(0)
 {
        lyxerr[Debug::INFO] << "Buffer::Buffer()" << endl;
        filepath_ = OnlyPath(file);
@@ -164,6 +167,9 @@ Buffer::Buffer(string const & file, bool ronly)
        } else {
                tmppath.erase();
        }
+
+       // set initial author
+       authorlist.record(Author(lyxrc.user_name, lyxrc.user_email)); 
 }
 
 
@@ -199,7 +205,7 @@ string const Buffer::getLatexName(bool no_path) const
 }
 
 
-pair<Buffer::LogType, string> const Buffer::getLogName(void) const
+pair<Buffer::LogType, string> const Buffer::getLogName() const
 {
        string const filename = getLatexName(false);
 
@@ -226,10 +232,10 @@ pair<Buffer::LogType, string> const Buffer::getLogName(void) const
 
        if (b_fi.exist() &&
            (!f_fi.exist() || f_fi.getModificationTime() < b_fi.getModificationTime())) {
-               lyxerr[Debug::FILES] << "Log name calculated as : " << bname << endl;
+               lyxerr[Debug::FILES] << "Log name calculated as: " << bname << endl;
                return make_pair(Buffer::buildlog, bname);
        }
-       lyxerr[Debug::FILES] << "Log name calculated as : " << fname << endl;
+       lyxerr[Debug::FILES] << "Log name calculated as: " << fname << endl;
        return make_pair(Buffer::latexlog, fname);
 }
 
@@ -244,6 +250,12 @@ void Buffer::setReadonly(bool flag)
 }
 
 
+AuthorList & Buffer::authors()
+{
+       return authorlist;
+}
+
+
 /// Update window titles of all users
 // Should work on a list
 void Buffer::updateTitles() const
@@ -281,6 +293,7 @@ string last_inset_read;
 #endif
 int unknown_layouts;
 int unknown_tokens;
+vector<int> author_ids;
 
 } // anon
 
@@ -292,11 +305,12 @@ int unknown_tokens;
 // changed to be public and have one parameter
 // if par = 0 normal behavior
 // else insert behavior
-// Returns false if "\the_end" is not read for formats >= 2.13. (Asger)
+// Returns false if "\the_end" is not read (Asger)
 bool Buffer::readLyXformat2(LyXLex & lex, Paragraph * par)
 {
        unknown_layouts = 0;
        unknown_tokens = 0;
+       author_ids.clear();
 
        int pos = 0;
        Paragraph::depth_type depth = 0;
@@ -338,7 +352,7 @@ bool Buffer::readLyXformat2(LyXLex & lex, Paragraph * par)
                if (token.empty()) continue;
 
                lyxerr[Debug::PARSER] << "Handling token: `"
-                                     << token << "'" << endl;
+                                     << token << '\'' << endl;
 
                the_end_read =
                        parseSingleLyXformat2Token(lex, par, first_par,
@@ -359,8 +373,13 @@ bool Buffer::readLyXformat2(LyXLex & lex, Paragraph * par)
                        s += tostr(unknown_layouts);
                        s += _(" paragraphs");
                }
+#if USE_BOOST_FORMAT
+               Alert::alert(_("Textclass Loading Error!"), s,
+                          boost::io::str(boost::format(_("When reading %1$s")) % fileName()));
+#else
                Alert::alert(_("Textclass Loading Error!"), s,
-                          _("When reading " + fileName()));
+                            _("When reading ") + fileName());
+#endif
        }
 
        if (unknown_tokens > 0) {
@@ -371,14 +390,26 @@ bool Buffer::readLyXformat2(LyXLex & lex, Paragraph * par)
                        s += tostr(unknown_tokens);
                        s += _(" unknown tokens");
                }
+#if USE_BOOST_FORMAT
+               Alert::alert(_("Textclass Loading Error!"), s,
+                          boost::io::str(boost::format(_("When reading %1$s")) % fileName()));
+#else
                Alert::alert(_("Textclass Loading Error!"), s,
-                          _("When reading " + fileName()));
+                            _("When reading ") +  fileName());
+#endif
        }
 
        return the_end_read;
 }
 
 
+namespace {
+       // This stuff is, in the traditional LyX terminology, Super UGLY
+       // but this code is too b0rken to admit of a better solution yet
+       Change current_change;
+};
+
 bool
 Buffer::parseSingleLyXformat2Token(LyXLex & lex, Paragraph *& par,
                                   Paragraph *& first_par,
@@ -397,7 +428,7 @@ Buffer::parseSingleLyXformat2Token(LyXLex & lex, Paragraph *& par,
        if (token[0] != '\\') {
                for (string::const_iterator cit = token.begin();
                     cit != token.end(); ++cit) {
-                       par->insertChar(pos, (*cit), font);
+                       par->insertChar(pos, (*cit), font, current_change);
                        ++pos;
                }
        } else if (token == "\\layout") {
@@ -487,6 +518,8 @@ Buffer::parseSingleLyXformat2Token(LyXLex & lex, Paragraph *& par,
                        else {
                                par = new Paragraph(par);
                                par->layout(params.getLyXTextClass().defaultLayout());
+                               if (params.tracking_changes)
+                                       par->trackChanges();
                        }
                        pos = 0;
                        par->layout(params.getLyXTextClass()[layoutname]);
@@ -563,12 +596,11 @@ Buffer::parseSingleLyXformat2Token(LyXLex & lex, Paragraph *& par,
                if (layout->free_spacing || par->isFreeSpacing()) {
                        if (lex.isOK()) {
                                lex.next();
-                               string next_token = lex.getString();
+                               string const next_token = lex.getString();
                                if (next_token == "\\-") {
-                                       par->insertChar(pos, '-', font);
-                               } else if (next_token == "\\protected_separator"
-                                       || next_token == "~") {
-                                       par->insertChar(pos, ' ', font);
+                                       par->insertChar(pos, '-', font, current_change);
+                               } else if (next_token == "~") {
+                                       par->insertChar(pos, ' ', font, current_change);
                                } else {
                                        lex.printError("Token `$$Token' "
                                                       "is in free space "
@@ -579,16 +611,16 @@ Buffer::parseSingleLyXformat2Token(LyXLex & lex, Paragraph *& par,
                } else {
                        Inset * inset = new InsetSpecialChar;
                        inset->read(this, lex);
-                       par->insertInset(pos, inset, font);
+                       par->insertInset(pos, inset, font, current_change);
                }
                ++pos;
        } else if (token == "\\i") {
                Inset * inset = new InsetLatexAccent;
                inset->read(this, lex);
-               par->insertInset(pos, inset, font);
+               par->insertInset(pos, inset, font, current_change);
                ++pos;
        } else if (token == "\\backslash") {
-               par->insertChar(pos, '\\', font);
+               par->insertChar(pos, '\\', font, current_change);
                ++pos;
        } else if (token == "\\begin_deeper") {
                ++depth;
@@ -608,10 +640,17 @@ Buffer::parseSingleLyXformat2Token(LyXLex & lex, Paragraph *& par,
                if (pp.first) {
                        params.textclass = pp.second;
                } else {
-                       Alert::alert(string(_("Textclass error")),
-                               string(_("The document uses an unknown textclass \"")) +
-                               lex.getString() + string("\"."),
-                               string(_("LyX will not be able to produce output correctly.")));
+#if USE_BOOST_FORMAT
+                       Alert::alert(_("Textclass error"),
+                               boost::io::str(boost::format(_("The document uses an unknown textclass \"%1$s\".")) % lex.getString()),
+                               _("-- substituting default."));
+#else
+                       Alert::alert(
+                               _("Textclass error"),
+                               _("The document uses an unknown textclass ")
+                               + lex.getString(),
+                               _("-- substituting default."));
+#endif
                        params.textclass = 0;
                }
                if (!params.getLyXTextClass().load()) {
@@ -620,10 +659,17 @@ Buffer::parseSingleLyXformat2Token(LyXLex & lex, Paragraph *& par,
                        // or stop loading the file.
                        // I can substitute but I don't see how I can
                        // stop loading... ideas??  ARRae980418
+#if USE_BOOST_FORMAT
                        Alert::alert(_("Textclass Loading Error!"),
-                                  string(_("Can't load textclass ")) +
-                                  params.getLyXTextClass().name(),
-                                  _("-- substituting default"));
+                                  boost::io::str(boost::format(_("Can't load textclass %1$s")) %
+                                  params.getLyXTextClass().name()),
+                                  _("-- substituting default."));
+#else
+                       Alert::alert(_("Textclass Loading Error!"),
+                                    _("Can't load textclass ")
+                                    + params.getLyXTextClass().name(),
+                                    _("-- substituting default."));
+#endif
                        params.textclass = 0;
                }
        } else if (token == "\\options") {
@@ -732,6 +778,21 @@ Buffer::parseSingleLyXformat2Token(LyXLex & lex, Paragraph *& par,
        } else if (token == "\\use_numerical_citations") {
                lex.nextToken();
                params.use_numerical_citations = lex.getInteger();
+       } else if (token == "\\tracking_changes") {
+               lex.nextToken();
+               params.tracking_changes = lex.getInteger();
+               // mark the first paragraph
+               if (params.tracking_changes)
+                       par->trackChanges();
+       } else if (token == "\\author") {
+               lex.nextToken();
+               istringstream ss(lex.getString());
+               Author a;
+               ss >> a;
+               int aid(authorlist.record(a)); 
+               lyxerr << "aid is " << aid << endl;
+               lyxerr << "listed aid is " << author_ids.size() << endl;
+               author_ids.push_back(authorlist.record(a));
        } else if (token == "\\paperorientation") {
                int tmpret = lex.findToken(string_orientation);
                if (tmpret == -1)
@@ -905,29 +966,37 @@ Buffer::parseSingleLyXformat2Token(LyXLex & lex, Paragraph *& par,
                par->params().labelWidthString(lex.getString());
                // do not delete this token, it is still needed!
        } else if (token == "\\newline") {
-               par->insertChar(pos, Paragraph::META_NEWLINE, font);
+               par->insertChar(pos, Paragraph::META_NEWLINE, font, current_change);
                ++pos;
        } else if (token == "\\LyXTable") {
                Inset * inset = new InsetTabular(*this);
                inset->read(this, lex);
-               par->insertInset(pos, inset, font);
+               par->insertInset(pos, inset, font, current_change);
                ++pos;
        } else if (token == "\\hfill") {
-               par->insertChar(pos, Paragraph::META_HFILL, font);
-               ++pos;
-       } else if (token == "\\protected_separator") { // obsolete
-               // This is a backward compability thingie. (Lgb)
-               // Remove it later some time...introduced with fileformat
-               // 2.16. (Lgb)
-               LyXLayout_ptr const & layout = par->layout();
-
-               if (layout->free_spacing || par->isFreeSpacing()) {
-                       par->insertChar(pos, ' ', font);
-               } else {
-                       Inset * inset = new InsetSpecialChar(InsetSpecialChar::PROTECTED_SEPARATOR);
-                       par->insertInset(pos, inset, font);
-               }
+               par->insertChar(pos, Paragraph::META_HFILL, font, current_change);
                ++pos;
+       } else if (token == "\\change_unchanged") {
+               // Hack ! Needed for empty paragraphs :/
+               if (!pos)
+                       par->cleanChanges();
+               current_change = Change(Change::UNCHANGED);
+       } else if (token == "\\change_inserted") {
+               lex.nextToken();
+               istringstream istr(lex.getString());
+               int aid;
+               lyx::time_type ct;
+               istr >> aid;
+               istr >> ct;
+               current_change = Change(Change::INSERTED, author_ids[aid], ct);
+       } else if (token == "\\change_deleted") {
+               lex.nextToken();
+               istringstream istr(lex.getString());
+               int aid;
+               lyx::time_type ct;
+               istr >> aid;
+               istr >> ct;
+               current_change = Change(Change::DELETED, author_ids[aid], ct);
        } else if (token == "\\bibitem") {  // ale970302
                if (!par->bibkey) {
                        InsetCommandParams p("bibitem", "dummy");
@@ -940,8 +1009,14 @@ Buffer::parseSingleLyXformat2Token(LyXLex & lex, Paragraph *& par,
                // This should be insurance for the future: (Asger)
                ++unknown_tokens;
                lex.eatLine();
+#if USE_BOOST_FORMAT
+               boost::format fmt(_("Unknown token: %1$s %2$s\n"));
+               fmt % token % lex.text();
+               string const s = fmt.str();
+#else
                string const s = _("Unknown token: ") + token
-                       + " " + lex.text()  + "\n";
+                       + ' ' + lex.text() + '\n';
+#endif
                // we can do this here this way because we're actually reading
                // the buffer and don't care about LyXText right now.
                InsetError * new_inset = new InsetError(s);
@@ -953,6 +1028,7 @@ Buffer::parseSingleLyXformat2Token(LyXLex & lex, Paragraph *& par,
        return the_end_read;
 }
 
+
 // needed to insert the selection
 void Buffer::insertStringAsLines(Paragraph *& par, pos_type & pos,
                                 LyXFont const & fn,string const & str) const
@@ -987,13 +1063,13 @@ void Buffer::insertStringAsLines(Paragraph *& par, pos_type & pos,
                } else if (*cit == '\t') {
                        if (!layout->free_spacing && !par->isFreeSpacing()) {
                                // tabs are like spaces here
-                               par->insertChar(pos, ' ', font);
+                               par->insertChar(pos, ' ', font, current_change);
                                ++pos;
                                space_inserted = true;
                        } else {
                                const pos_type nb = 8 - pos % 8;
                                for (pos_type a = 0; a < nb ; ++a) {
-                                       par->insertChar(pos, ' ', font);
+                                       par->insertChar(pos, ' ', font, current_change);
                                        ++pos;
                                }
                                space_inserted = true;
@@ -1117,6 +1193,10 @@ void Buffer::readInset(LyXLex & lex, Paragraph *& par,
                        lex.next();
                        string tmptok = lex.getString();
                        inset = new InsetFloat(params, tmptok);
+               } else if (tmptok == "Wrap") {
+                       lex.next();
+                       string tmptok = lex.getString();
+                       inset = new InsetWrap(params, tmptok);
 #if 0
                } else if (tmptok == "List") {
                        inset = new InsetList;
@@ -1133,13 +1213,13 @@ void Buffer::readInset(LyXLex & lex, Paragraph *& par,
        }
 
        if (inset) {
-               par->insertInset(pos, inset, font);
+               par->insertInset(pos, inset, font, current_change);
                ++pos;
        }
 }
 
 
-bool Buffer::readFile(LyXLex & lex, Paragraph * par)
+bool Buffer::readFile(LyXLex & lex, string const & filename, Paragraph * par)
 {
        if (lex.isOK()) {
                lex.next();
@@ -1147,20 +1227,21 @@ bool Buffer::readFile(LyXLex & lex, Paragraph * par)
                if (token == "\\lyxformat") { // the first token _must_ be...
                        lex.eatLine();
                        string tmp_format = lex.getString();
-                       //lyxerr << "LyX Format: `" << tmp_format << "'" << endl;
+                       //lyxerr << "LyX Format: `" << tmp_format << '\'' << endl;
                        // if present remove ".," from string.
                        string::size_type dot = tmp_format.find_first_of(".,");
                        //lyxerr << "           dot found at " << dot << endl;
                        if (dot != string::npos)
                                tmp_format.erase(dot, 1);
                        file_format = strToInt(tmp_format);
+                       //lyxerr << "format: " << file_format << endl;
                        if (file_format == LYX_FORMAT) {
                                // current format
                        } else if (file_format > LYX_FORMAT) {
                                // future format
                                Alert::alert(_("Warning!"),
-                                          _("LyX file format is newer that what"),
-                                          _("is supported in this LyX version. Expect some problems."));
+                                       _("The file was created with a newer version of "
+                                       "LyX. This is likely to cause problems."));
 
                        } else if (file_format < LYX_FORMAT) {
                                // old formats
@@ -1169,20 +1250,37 @@ bool Buffer::readFile(LyXLex & lex, Paragraph * par)
                                                   _("Old LyX file format found. "
                                                     "Use LyX 0.10.x to read this!"));
                                        return false;
-                               } else {
-                                       string const command = "lyx2lyx "
-                                               + QuoteName(filename_);
+                               } else if (!filename.empty()) {
+                                       string command =
+                                               LibFileSearch("lyx2lyx", "lyx2lyx");
+                                       if (command.empty()) {
+                                               Alert::alert(_("ERROR!"),
+                                                            _("Can't find conversion script."));
+                                               return false;
+                                       }
+                                       command += " -t"
+                                               +tostr(LYX_FORMAT) + ' '
+                                               + QuoteName(filename);
+                                       lyxerr[Debug::INFO] << "Running '"
+                                                           << command << '\''
+                                                           << endl;
                                        cmd_ret const ret = RunCommand(command);
                                        if (ret.first) {
                                                Alert::alert(_("ERROR!"),
-                                                    _("An error occured while "
-                                                      "running the conversion script."));
+                                                            _("An error occured while "
+                                                              "running the conversion script."));
                                                return false;
                                        }
-                                       istringstream is(ret.second);
+                                       istringstream is(STRCONV(ret.second));
                                        LyXLex tmplex(0, 0);
                                        tmplex.setStream(is);
-                                       return readFile(tmplex);
+                                       return readFile(tmplex, string(), par);
+                               } else {
+                                       // This code is reached if lyx2lyx failed (for
+                                       // some reason) to change the file format of
+                                       // the file.
+                                       lyx::Assert(false);
+                                       return false;
                                }
                        }
                        bool the_end = readLyXformat2(lex, par);
@@ -1316,6 +1414,15 @@ bool Buffer::writeFile(string const & fname) const
        // now write out the buffer paramters.
        params.writeFile(ofs);
 
+       // if we're tracking, list all possible authors
+       if (params.tracking_changes) {
+               AuthorList::Authors::const_iterator it = authorlist.begin();
+               AuthorList::Authors::const_iterator end = authorlist.end();
+               for (; it != end; ++it) {
+                       ofs << "\\author " << it->second << "\n";
+               }
+       }
        Paragraph::depth_type depth = 0;
 
        // this will write out all the paragraphs
@@ -1486,7 +1593,7 @@ string const Buffer::asciiParagraph(Paragraph const & par,
                default:
                {
                        string const parlab = par.params().labelString();
-                       buffer << parlab << " ";
+                       buffer << parlab << ' ';
                        currlinelen += parlab.length() + 1;
                }
                break;
@@ -1581,7 +1688,7 @@ string const Buffer::asciiParagraph(Paragraph const & par,
                }
        }
        buffer << word;
-       return buffer.str().c_str();
+       return STRCONV(buffer.str());
 }
 
 
@@ -1768,7 +1875,7 @@ void Buffer::makeLaTeXFile(ostream & os,
                        options << params.options << ',';
                }
 
-               string strOptions(options.str().c_str());
+               string strOptions(STRCONV(options.str()));
                if (!strOptions.empty()) {
                        strOptions = rtrim(strOptions, ",");
                        os << '[' << strOptions << ']';
@@ -2048,7 +2155,7 @@ void Buffer::makeLaTeXFile(ostream & os,
                        if (!lyxrc.language_global_options
                            && tmp == "\\usepackage{babel}")
                                tmp = string("\\usepackage[") +
-                                       language_options.str().c_str() +
+                                       STRCONV(language_options.str()) +
                                        "]{babel}";
                        preamble += tmp + "\n";
                        preamble += features.getBabelOptions();
@@ -2056,6 +2163,15 @@ void Buffer::makeLaTeXFile(ostream & os,
 
                preamble += "\\makeatother\n";
 
+               // dvipost settings come after everything else
+               if (params.tracking_changes) {
+                       preamble += "\\dvipostlayout\n";
+                       preamble += "\\dvipost{osstart color push Red}\n";
+                       preamble += "\\dvipost{osend color pop}\n";
+                       preamble += "\\dvipost{cbstart color push Blue}\n";
+                       preamble += "\\dvipost{cbend color pop} \n";
+               }
+
                os << preamble;
 
                if (only_preamble)
@@ -2100,8 +2216,9 @@ void Buffer::makeLaTeXFile(ostream & os,
        // Just to be sure. (Asger)
        texrow.newline();
 
-       lyxerr[Debug::INFO] << "Finished making latex file." << endl;
-       lyxerr[Debug::INFO] << "Row count was " << texrow.rows()-1 << "." << endl;
+       lyxerr[Debug::INFO] << "Finished making LaTeX file." << endl;
+       lyxerr[Debug::INFO] << "Row count was " << texrow.rows() - 1
+                           << '.' << endl;
 
        // we want this to be true outside previews (for insetexternal)
        niceFile = true;
@@ -2194,38 +2311,6 @@ bool Buffer::isSGML() const
 }
 
 
-int Buffer::sgmlOpenTag(ostream & os, Paragraph::depth_type depth, bool mixcont,
-                        string const & latexname) const
-{
-       if (!latexname.empty() && latexname != "!-- --") {
-               if (!mixcont)
-                       os << string(" ",depth);
-               os << "<" << latexname << ">";
-       }
-
-       if (!mixcont)
-               os << endl;
-
-       return mixcont?0:1;
-}
-
-
-int Buffer::sgmlCloseTag(ostream & os, Paragraph::depth_type depth, bool mixcont,
-                         string const & latexname) const
-{
-       if (!latexname.empty() && latexname != "!-- --") {
-               if (!mixcont)
-                       os << endl << string(" ",depth);
-               os << "</" << latexname << ">";
-       }
-
-       if (!mixcont)
-               os << endl;
-
-       return mixcont?0:1;
-}
-
-
 void Buffer::makeLinuxDocFile(string const & fname, bool nice, bool body_only)
 {
        ofstream ofs(fname.c_str());
@@ -2262,12 +2347,12 @@ void Buffer::makeLinuxDocFile(string const & fname, bool nice, bool body_only)
                ofs << ">\n\n";
 
                if (params.options.empty())
-                       sgmlOpenTag(ofs, 0, false, top_element);
+                       sgml::openTag(ofs, 0, false, top_element);
                else {
                        string top = top_element;
-                       top += " ";
+                       top += ' ';
                        top += params.options;
-                       sgmlOpenTag(ofs, 0, false, top);
+                       sgml::openTag(ofs, 0, false, top);
                }
        }
 
@@ -2288,7 +2373,7 @@ void Buffer::makeLinuxDocFile(string const & fname, bool nice, bool body_only)
                        Inset::Code lyx_code = inset->lyxCode();
                        if (lyx_code == Inset::TOC_CODE) {
                                string const temp = "toc";
-                               sgmlOpenTag(ofs, depth, false, temp);
+                               sgml::openTag(ofs, depth, false, temp);
 
                                par = par->next();
                                continue;
@@ -2297,7 +2382,7 @@ void Buffer::makeLinuxDocFile(string const & fname, bool nice, bool body_only)
 
                // environment tag closing
                for (; depth > par->params().depth(); --depth) {
-                       sgmlCloseTag(ofs, depth, false, environment_stack[depth]);
+                       sgml::closeTag(ofs, depth, false, environment_stack[depth]);
                        environment_stack[depth].erase();
                }
 
@@ -2306,29 +2391,28 @@ void Buffer::makeLinuxDocFile(string const & fname, bool nice, bool body_only)
                case LATEX_PARAGRAPH:
                        if (depth == par->params().depth()
                           && !environment_stack[depth].empty()) {
-                               sgmlCloseTag(ofs, depth, false, environment_stack[depth]);
+                               sgml::closeTag(ofs, depth, false, environment_stack[depth]);
                                environment_stack[depth].erase();
                                if (depth)
                                        --depth;
                                else
                                        ofs << "</p>";
                        }
-                       sgmlOpenTag(ofs, depth, false, style->latexname());
+                       sgml::openTag(ofs, depth, false, style->latexname());
                        break;
 
                case LATEX_COMMAND:
                        if (depth!= 0)
                                sgmlError(par, 0,
-                                         _("Error : Wrong depth for"
-                                           " LatexType Command.\n"));
+                                         _("Error: Wrong depth for LatexType Command.\n"));
 
                        if (!environment_stack[depth].empty()) {
-                               sgmlCloseTag(ofs, depth, false, environment_stack[depth]);
+                               sgml::closeTag(ofs, depth, false, environment_stack[depth]);
                                ofs << "</p>";
                        }
 
                        environment_stack[depth].erase();
-                       sgmlOpenTag(ofs, depth, false, style->latexname());
+                       sgml::openTag(ofs, depth, false, style->latexname());
                        break;
 
                case LATEX_ENVIRONMENT:
@@ -2338,7 +2422,7 @@ void Buffer::makeLinuxDocFile(string const & fname, bool nice, bool body_only)
 
                        if (depth == par->params().depth()
                            && environment_stack[depth] != latexname) {
-                               sgmlCloseTag(ofs, depth, false,
+                               sgml::closeTag(ofs, depth, false,
                                             environment_stack[depth]);
                                environment_stack[depth].erase();
                        }
@@ -2348,9 +2432,9 @@ void Buffer::makeLinuxDocFile(string const & fname, bool nice, bool body_only)
                        }
                        if (environment_stack[depth] != latexname) {
                                if (depth == 0) {
-                                       sgmlOpenTag(ofs, depth, false, "p");
+                                       sgml::openTag(ofs, depth, false, "p");
                                }
-                               sgmlOpenTag(ofs, depth, false, latexname);
+                               sgml::openTag(ofs, depth, false, latexname);
 
                                if (environment_stack.size() == depth + 1)
                                        environment_stack.push_back("!-- --");
@@ -2367,12 +2451,12 @@ void Buffer::makeLinuxDocFile(string const & fname, bool nice, bool body_only)
                        else
                                item_name = "item";
 
-                       sgmlOpenTag(ofs, depth + 1, false, item_name);
+                       sgml::openTag(ofs, depth + 1, false, item_name);
                }
                break;
 
                default:
-                       sgmlOpenTag(ofs, depth, false, style->latexname());
+                       sgml::openTag(ofs, depth, false, style->latexname());
                        break;
                }
 
@@ -2391,18 +2475,18 @@ void Buffer::makeLinuxDocFile(string const & fname, bool nice, bool body_only)
                                ofs << "]]>";
                        break;
                default:
-                       sgmlCloseTag(ofs, depth, false, style->latexname());
+                       sgml::closeTag(ofs, depth, false, style->latexname());
                        break;
                }
        }
 
        // Close open tags
        for (int i = depth; i >= 0; --i)
-               sgmlCloseTag(ofs, depth, false, environment_stack[i]);
+               sgml::closeTag(ofs, depth, false, environment_stack[i]);
 
        if (!body_only) {
                ofs << "\n\n";
-               sgmlCloseTag(ofs, 0, false, top_element);
+               sgml::closeTag(ofs, 0, false, top_element);
        }
 
        ofs.close();
@@ -2590,7 +2674,7 @@ void Buffer::simpleLinuxDocOnePar(ostream & os,
                while (!tag_state.empty() && tag_close) {
                        PAR_TAG k =  tag_state.top();
                        tag_state.pop();
-                       os << "</" << tag_name(k) << ">";
+                       os << "</" << tag_name(k) << '>';
                        if (tag_close & k)
                                reset(tag_close,k);
                        else
@@ -2600,13 +2684,13 @@ void Buffer::simpleLinuxDocOnePar(ostream & os,
                for(list< PAR_TAG >::const_iterator j = temp.begin();
                    j != temp.end(); ++j) {
                        tag_state.push(*j);
-                       os << "<" << tag_name(*j) << ">";
+                       os << '<' << tag_name(*j) << '>';
                }
 
                for(list< PAR_TAG >::const_iterator j = tag_open.begin();
                    j != tag_open.end(); ++j) {
                        tag_state.push(*j);
-                       os << "<" << tag_name(*j) << ">";
+                       os << '<' << tag_name(*j) << '>';
                }
 
                char c = par->getChar(i);
@@ -2649,7 +2733,7 @@ void Buffer::simpleLinuxDocOnePar(ostream & os,
        }
 
        while (!tag_state.empty()) {
-               os << "</" << tag_name(tag_state.top()) << ">";
+               os << "</" << tag_name(tag_state.top()) << '>';
                tag_state.pop();
        }
 
@@ -2722,13 +2806,13 @@ void Buffer::makeDocBookFile(string const & fname, bool nice, bool only_body)
        string top = top_element;
        top += " lang=\"";
        top += params.language->code();
-       top += "\"";
+       top += '"';
 
        if (!params.options.empty()) {
-               top += " ";
+               top += ' ';
                top += params.options;
        }
-       sgmlOpenTag(ofs, 0, false, top);
+       sgml::openTag(ofs, 0, false, top);
 
        ofs << "<!-- DocBook file was created by " << lyx_docversion
            << "\n  See http://www.lyx.org/ for more information -->\n";
@@ -2758,11 +2842,11 @@ void Buffer::makeDocBookFile(string const & fname, bool nice, bool only_body)
                for (; depth > par->params().depth(); --depth) {
                        if (environment_inner[depth] != "!-- --") {
                                item_name = "listitem";
-                               sgmlCloseTag(ofs, command_depth + depth, false, item_name);
+                               sgml::closeTag(ofs, command_depth + depth, false, item_name);
                                if (environment_inner[depth] == "varlistentry")
-                                       sgmlCloseTag(ofs, depth+command_depth, false, environment_inner[depth]);
+                                       sgml::closeTag(ofs, depth+command_depth, false, environment_inner[depth]);
                        }
-                       sgmlCloseTag(ofs, depth + command_depth, false, environment_stack[depth]);
+                       sgml::closeTag(ofs, depth + command_depth, false, environment_stack[depth]);
                        environment_stack[depth].erase();
                        environment_inner[depth].erase();
                }
@@ -2772,12 +2856,12 @@ void Buffer::makeDocBookFile(string const & fname, bool nice, bool only_body)
                   && !environment_stack[depth].empty()) {
                        if (environment_inner[depth] != "!-- --") {
                                item_name= "listitem";
-                               sgmlCloseTag(ofs, command_depth+depth, false, item_name);
+                               sgml::closeTag(ofs, command_depth+depth, false, item_name);
                                if (environment_inner[depth] == "varlistentry")
-                                       sgmlCloseTag(ofs, depth + command_depth, false, environment_inner[depth]);
+                                       sgml::closeTag(ofs, depth + command_depth, false, environment_inner[depth]);
                        }
 
-                       sgmlCloseTag(ofs, depth + command_depth, false, environment_stack[depth]);
+                       sgml::closeTag(ofs, depth + command_depth, false, environment_stack[depth]);
 
                        environment_stack[depth].erase();
                        environment_inner[depth].erase();
@@ -2786,15 +2870,14 @@ void Buffer::makeDocBookFile(string const & fname, bool nice, bool only_body)
                // Write opening SGML tags.
                switch (style->latextype) {
                case LATEX_PARAGRAPH:
-                       sgmlOpenTag(ofs, depth + command_depth,
+                       sgml::openTag(ofs, depth + command_depth,
                                    false, style->latexname());
                        break;
 
                case LATEX_COMMAND:
                        if (depth != 0)
                                sgmlError(par, 0,
-                                         _("Error : Wrong depth for "
-                                           "LatexType Command.\n"));
+                                         _("Error: Wrong depth for LatexType Command.\n"));
 
                        command_name = style->latexname();
 
@@ -2807,14 +2890,14 @@ void Buffer::makeDocBookFile(string const & fname, bool nice, bool only_body)
                                if (cmd_depth < command_base) {
                                        for (Paragraph::depth_type j = command_depth;
                                             j >= command_base; --j) {
-                                               sgmlCloseTag(ofs, j, false, command_stack[j]);
+                                               sgml::closeTag(ofs, j, false, command_stack[j]);
                                                ofs << endl;
                                        }
                                        command_depth = command_base = cmd_depth;
                                } else if (cmd_depth <= command_depth) {
                                        for (int j = command_depth;
                                             j >= int(cmd_depth); --j) {
-                                               sgmlCloseTag(ofs, j, false, command_stack[j]);
+                                               sgml::closeTag(ofs, j, false, command_stack[j]);
                                                ofs << endl;
                                        }
                                        command_depth = cmd_depth;
@@ -2838,15 +2921,15 @@ void Buffer::makeDocBookFile(string const & fname, bool nice, bool only_body)
                                if (lyx_code == Inset::LABEL_CODE) {
                                        command_name += " id=\"";
                                        command_name += (static_cast<InsetCommand *>(inset))->getContents();
-                                       command_name += "\"";
+                                       command_name += '"';
                                        desc_on = 3;
                                }
                        }
 
-                       sgmlOpenTag(ofs, depth + command_depth, false, command_name);
+                       sgml::openTag(ofs, depth + command_depth, false, command_name);
 
-                       item_name = c_params.empty()?"title":c_params;
-                       sgmlOpenTag(ofs, depth + 1 + command_depth, false, item_name);
+                       item_name = c_params.empty() ? "title" : c_params;
+                       sgml::openTag(ofs, depth + 1 + command_depth, false, item_name);
                        break;
 
                case LATEX_ENVIRONMENT:
@@ -2863,13 +2946,13 @@ void Buffer::makeDocBookFile(string const & fname, bool nice, bool only_body)
                                }
                                environment_stack[depth] = style->latexname();
                                environment_inner[depth] = "!-- --";
-                               sgmlOpenTag(ofs, depth + command_depth, false, environment_stack[depth]);
+                               sgml::openTag(ofs, depth + command_depth, false, environment_stack[depth]);
                        } else {
                                if (environment_inner[depth] != "!-- --") {
                                        item_name= "listitem";
-                                       sgmlCloseTag(ofs, command_depth + depth, false, item_name);
+                                       sgml::closeTag(ofs, command_depth + depth, false, item_name);
                                        if (environment_inner[depth] == "varlistentry")
-                                               sgmlCloseTag(ofs, depth + command_depth, false, environment_inner[depth]);
+                                               sgml::closeTag(ofs, depth + command_depth, false, environment_inner[depth]);
                                }
                        }
 
@@ -2878,7 +2961,7 @@ void Buffer::makeDocBookFile(string const & fname, bool nice, bool only_body)
                                        if (style->latexparam() == "CDATA")
                                                ofs << "<![CDATA[";
                                        else
-                                               sgmlOpenTag(ofs, depth + command_depth, false, style->latexparam());
+                                               sgml::openTag(ofs, depth + command_depth, false, style->latexparam());
                                }
                                break;
                        }
@@ -2886,15 +2969,15 @@ void Buffer::makeDocBookFile(string const & fname, bool nice, bool only_body)
                        desc_on = (style->labeltype == LABEL_MANUAL);
 
                        environment_inner[depth] = desc_on ? "varlistentry" : "listitem";
-                       sgmlOpenTag(ofs, depth + 1 + command_depth,
+                       sgml::openTag(ofs, depth + 1 + command_depth,
                                    false, environment_inner[depth]);
 
                        item_name = desc_on ? "term" : "para";
-                       sgmlOpenTag(ofs, depth + 1 + command_depth,
+                       sgml::openTag(ofs, depth + 1 + command_depth,
                                    false, item_name);
                        break;
                default:
-                       sgmlOpenTag(ofs, depth + command_depth,
+                       sgml::openTag(ofs, depth + command_depth,
                                    false, style->latexname());
                        break;
                }
@@ -2908,7 +2991,7 @@ void Buffer::makeDocBookFile(string const & fname, bool nice, bool only_body)
                switch (style->latextype) {
                case LATEX_COMMAND:
                        end_tag = c_params.empty() ? "title" : c_params;
-                       sgmlCloseTag(ofs, depth + command_depth,
+                       sgml::closeTag(ofs, depth + command_depth,
                                     false, end_tag);
                        break;
                case LATEX_ENVIRONMENT:
@@ -2916,19 +2999,19 @@ void Buffer::makeDocBookFile(string const & fname, bool nice, bool only_body)
                                if (style->latexparam() == "CDATA")
                                        ofs << "]]>";
                                else
-                                       sgmlCloseTag(ofs, depth + command_depth, false, style->latexparam());
+                                       sgml::closeTag(ofs, depth + command_depth, false, style->latexparam());
                        }
                        break;
                case LATEX_ITEM_ENVIRONMENT:
                        if (desc_on == 1) break;
-                       end_tag= "para";
-                       sgmlCloseTag(ofs, depth + 1 + command_depth, false, end_tag);
+                       end_tag = "para";
+                       sgml::closeTag(ofs, depth + 1 + command_depth, false, end_tag);
                        break;
                case LATEX_PARAGRAPH:
-                       sgmlCloseTag(ofs, depth + command_depth, false, style->latexname());
+                       sgml::closeTag(ofs, depth + command_depth, false, style->latexname());
                        break;
                default:
-                       sgmlCloseTag(ofs, depth + command_depth, false, style->latexname());
+                       sgml::closeTag(ofs, depth + command_depth, false, style->latexname());
                        break;
                }
        }
@@ -2938,23 +3021,23 @@ void Buffer::makeDocBookFile(string const & fname, bool nice, bool only_body)
                if (!environment_stack[depth].empty()) {
                        if (environment_inner[depth] != "!-- --") {
                                item_name = "listitem";
-                               sgmlCloseTag(ofs, command_depth + depth, false, item_name);
+                               sgml::closeTag(ofs, command_depth + depth, false, item_name);
                               if (environment_inner[depth] == "varlistentry")
-                                      sgmlCloseTag(ofs, depth + command_depth, false, environment_inner[depth]);
+                                      sgml::closeTag(ofs, depth + command_depth, false, environment_inner[depth]);
                        }
 
-                       sgmlCloseTag(ofs, depth + command_depth, false, environment_stack[depth]);
+                       sgml::closeTag(ofs, depth + command_depth, false, environment_stack[depth]);
                }
        }
 
        for (int j = command_depth; j >= 0 ; --j)
                if (!command_stack[j].empty()) {
-                       sgmlCloseTag(ofs, j, false, command_stack[j]);
+                       sgml::closeTag(ofs, j, false, command_stack[j]);
                        ofs << endl;
                }
 
        ofs << "\n\n";
-       sgmlCloseTag(ofs, 0, false, top_element);
+       sgml::closeTag(ofs, 0, false, top_element);
 
        ofs.close();
        // How to check for successful close
@@ -3106,6 +3189,11 @@ void Buffer::validate(LaTeXFeatures & features) const
 {
        LyXTextClass const & tclass = params.getLyXTextClass();
 
+       if (params.tracking_changes) {
+               features.require("dvipost");
+               features.require("color");
+       }
        // AMS Style is at document level
        if (params.use_amsmath || tclass.provides(LyXTextClass::amsmath))
                features.require("amsmath");
@@ -3143,26 +3231,6 @@ void Buffer::validate(LaTeXFeatures & features) const
 }
 
 
-// This function should be in Buffer because it's a buffer's property (ale)
-string const Buffer::getIncludeonlyList(char delim)
-{
-       string lst;
-       for (inset_iterator it = inset_iterator_begin();
-           it != inset_iterator_end(); ++it) {
-               if (it->lyxCode() == Inset::INCLUDE_CODE) {
-                       InsetInclude & inc = static_cast<InsetInclude &>(*it);
-                       if (inc.isIncludeOnly()) {
-                               if (!lst.empty())
-                                       lst += delim;
-                               lst += inc.getRelFileBaseName();
-                       }
-               }
-       }
-       lyxerr[Debug::INFO] << "Includeonly(" << lst << ')' << endl;
-       return lst;
-}
-
-
 vector<string> const Buffer::getLabelList() const
 {
        /// if this is a child document and the parent is already loaded
@@ -3212,7 +3280,7 @@ vector<pair<string, string> > const Buffer::getBibkeyList() const
 
        if (!keys.empty())
                return keys;
+
        // Might be either using bibtex or a child has bibliography
        for (inset_iterator it = inset_const_iterator_begin();
                it != inset_const_iterator_end(); ++it) {
@@ -3234,34 +3302,16 @@ vector<pair<string, string> > const Buffer::getBibkeyList() const
 
 bool Buffer::isDepClean(string const & name) const
 {
-       DEPCLEAN * item = dep_clean;
-       while (item && item->master != name)
-               item = item->next;
-       if (!item) return true;
-       return item->clean;
+       DepClean::const_iterator it = dep_clean_.find(name);
+       if (it == dep_clean_.end())
+               return true;
+       return it->second;
 }
 
 
 void Buffer::markDepClean(string const & name)
 {
-       if (!dep_clean) {
-               dep_clean = new DEPCLEAN;
-               dep_clean->clean = true;
-               dep_clean->master = name;
-               dep_clean->next = 0;
-       } else {
-               DEPCLEAN * item = dep_clean;
-               while (item && item->master != name)
-                       item = item->next;
-               if (item) {
-                       item->clean = true;
-               } else {
-                       item = new DEPCLEAN;
-                       item->clean = true;
-                       item->master = name;
-                       item->next = 0;
-               }
-       }
+       dep_clean_[name] = true;
 }
 
 
@@ -3331,12 +3381,6 @@ bool Buffer::isMultiLingual()
 }
 
 
-Counters & Buffer::counters() const
-{
-       return *ctrs.get();
-}
-
-
 void Buffer::inset_iterator::setParagraph()
 {
        while (pit != pend) {
@@ -3394,6 +3438,18 @@ ParIterator Buffer::par_iterator_end()
        return ParIterator();
 }
 
+ParConstIterator Buffer::par_iterator_begin() const
+{
+       return ParConstIterator(&*(paragraphs.begin()));
+}
+
+
+ParConstIterator Buffer::par_iterator_end() const
+{
+       return ParConstIterator();
+}
+
+
 
 void Buffer::addUser(BufferView * u)
 {
@@ -3462,10 +3518,12 @@ void Buffer::markDirty()
                updateTitles();
        }
        bak_clean = false;
-       DEPCLEAN * tmp = dep_clean;
-       while (tmp) {
-               tmp->clean = false;
-               tmp = tmp->next;
+
+       DepClean::iterator it = dep_clean_.begin();
+       DepClean::const_iterator const end = dep_clean_.end();
+
+       for (; it != end; ++it) {
+               it->second = false;
        }
 }