]> git.lyx.org Git - lyx.git/blobdiff - src/buffer.C
Collapse all those LFUN_XYZ_APPLY to a single LFUN_INSET_APPLY.
[lyx.git] / src / buffer.C
index 2197e6e9dfde884d3ea742afbfe3d35363e22cab..24f0dbaa4468e8cf56394cf27036c497931f9f3f 100644 (file)
 
 #include <config.h>
 
-#ifdef __GNUG__
-#pragma implementation
-#endif
-
 #include "buffer.h"
 #include "bufferlist.h"
 #include "LyXAction.h"
@@ -35,7 +31,6 @@
 #include "lyxtext.h"
 #include "gettext.h"
 #include "language.h"
-#include "encoding.h"
 #include "exporter.h"
 #include "Lsstream.h"
 #include "converter.h"
@@ -45,6 +40,7 @@
 #include "lyxtextclasslist.h"
 #include "sgml.h"
 #include "paragraph_funcs.h"
+#include "author.h"
 
 #include "frontends/LyXView.h"
 
@@ -59,7 +55,8 @@
 #include "insets/insetnote.h"
 #include "insets/insetquotes.h"
 #include "insets/insetlatexaccent.h"
-#include "insets/insetbib.h"
+#include "insets/insetbibitem.h"
+#include "insets/insetbibtex.h"
 #include "insets/insetcite.h"
 #include "insets/insetexternal.h"
 #include "insets/insetindex.h"
@@ -96,7 +93,7 @@
 #include "support/lyxlib.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>
@@ -134,8 +131,6 @@ using std::pair;
 using std::make_pair;
 using std::vector;
 using std::map;
-using std::max;
-using std::set;
 using std::stack;
 using std::list;
 using std::for_each;
@@ -148,13 +143,13 @@ 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),
+         unnamed(false), read_only(ronly),
          filename_(file), users(0)
 {
        lyxerr[Debug::INFO] << "Buffer::Buffer()" << endl;
@@ -165,6 +160,9 @@ Buffer::Buffer(string const & file, bool ronly)
        } else {
                tmppath.erase();
        }
+
+       // set initial author
+       authorlist.record(Author(lyxrc.user_name, lyxrc.user_email)); 
 }
 
 
@@ -245,6 +243,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
@@ -282,6 +286,7 @@ string last_inset_read;
 #endif
 int unknown_layouts;
 int unknown_tokens;
+vector<int> author_ids;
 
 } // anon
 
@@ -293,11 +298,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;
@@ -306,11 +312,6 @@ bool Buffer::readLyXformat2(LyXLex & lex, Paragraph * par)
        Paragraph * first_par = 0;
        LyXFont font(LyXFont::ALL_INHERIT, params.language);
 
-#if 0
-       if (file_format < 216 && params.language->lang() == "hebrew")
-               font.setLanguage(default_language);
-#endif
-
        if (!par) {
                par = new Paragraph;
                par->layout(params.getLyXTextClass().defaultLayout());
@@ -390,6 +391,13 @@ bool Buffer::readLyXformat2(LyXLex & lex, Paragraph * par)
 }
 
 
+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,
@@ -408,7 +416,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") {
@@ -417,11 +425,6 @@ Buffer::parseSingleLyXformat2Token(LyXLex & lex, Paragraph *& par,
                // right values after this tag (Jug 20020420)
                font = LyXFont(LyXFont::ALL_INHERIT, params.language);
 
-#if 0
-               if (file_format < 216 && params.language->lang() == "hebrew")
-                       font.setLanguage(default_language);
-#endif
-
                lex.eatLine();
                string layoutname = lex.getString();
 
@@ -498,6 +501,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]);
@@ -576,9 +581,9 @@ Buffer::parseSingleLyXformat2Token(LyXLex & lex, Paragraph *& par,
                                lex.next();
                                string const next_token = lex.getString();
                                if (next_token == "\\-") {
-                                       par->insertChar(pos, '-', font);
+                                       par->insertChar(pos, '-', font, current_change);
                                } else if (next_token == "~") {
-                                       par->insertChar(pos, ' ', font);
+                                       par->insertChar(pos, ' ', font, current_change);
                                } else {
                                        lex.printError("Token `$$Token' "
                                                       "is in free space "
@@ -589,16 +594,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;
@@ -621,13 +626,13 @@ Buffer::parseSingleLyXformat2Token(LyXLex & lex, Paragraph *& par,
 #if USE_BOOST_FORMAT
                        Alert::alert(_("Textclass error"),
                                boost::io::str(boost::format(_("The document uses an unknown textclass \"%1$s\".")) % lex.getString()),
-                               _("LyX will not be able to produce output correctly."));
+                               _("-- substituting default."));
 #else
                        Alert::alert(
                                _("Textclass error"),
                                _("The document uses an unknown textclass ")
                                + lex.getString(),
-                               _("LyX will not be able to produce output correctly."));
+                               _("-- substituting default."));
 #endif
                        params.textclass = 0;
                }
@@ -641,12 +646,12 @@ Buffer::parseSingleLyXformat2Token(LyXLex & lex, Paragraph *& par,
                        Alert::alert(_("Textclass Loading Error!"),
                                   boost::io::str(boost::format(_("Can't load textclass %1$s")) %
                                   params.getLyXTextClass().name()),
-                                  _("-- substituting default"));
+                                  _("-- substituting default."));
 #else
                        Alert::alert(_("Textclass Loading Error!"),
                                     _("Can't load textclass ")
                                     + params.getLyXTextClass().name(),
-                                    _("-- substituting default"));
+                                    _("-- substituting default."));
 #endif
                        params.textclass = 0;
                }
@@ -756,6 +761,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)
@@ -903,7 +923,8 @@ Buffer::parseSingleLyXformat2Token(LyXLex & lex, Paragraph *& par,
                params.float_placement = lex.getString();
        } else if (token == "\\align") {
                int tmpret = lex.findToken(string_align);
-               if (tmpret == -1) ++tmpret;
+               if (tmpret == -1)
+                       ++tmpret;
                int const tmpret2 = int(pow(2.0, tmpret));
                par->params().align(LyXAlignment(tmpret2));
        } else if (token == "\\added_space_top") {
@@ -929,22 +950,43 @@ 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 == "\\bibitem") {  // ale970302
+               InsetCommandParams p("bibitem", "dummy");
+               InsetBibitem * inset = new InsetBibitem(p);
+               inset->read(this, lex);
+               par->insertInset(pos, inset, font, current_change);
                ++pos;
        } else if (token == "\\hfill") {
-               par->insertChar(pos, Paragraph::META_HFILL, font);
+               par->insertChar(pos, Paragraph::META_HFILL, font, current_change);
                ++pos;
-       } else if (token == "\\bibitem") {  // ale970302
-               if (!par->bibkey) {
-                       InsetCommandParams p("bibitem", "dummy");
-                       par->bibkey = new InsetBibKey(p);
-               }
-               par->bibkey->read(this, lex);
+       } 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 == "\\the_end") {
                the_end_read = true;
        } else {
@@ -1005,13 +1047,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;
@@ -1058,7 +1100,7 @@ void Buffer::readInset(LyXLex & lex, Paragraph *& par,
                        inset = new InsetCitation(inscmd);
                } else if (cmdName == "bibitem") {
                        lex.printError("Wrong place for bibitem");
-                       inset = new InsetBibKey(inscmd);
+                       inset = new InsetBibitem(inscmd);
                } else if (cmdName == "BibTeX") {
                        inset = new InsetBibtex(inscmd);
                } else if (cmdName == "index") {
@@ -1155,7 +1197,7 @@ void Buffer::readInset(LyXLex & lex, Paragraph *& par,
        }
 
        if (inset) {
-               par->insertInset(pos, inset, font);
+               par->insertInset(pos, inset, font, current_change);
                ++pos;
        }
 }
@@ -1182,7 +1224,7 @@ bool Buffer::readFile(LyXLex & lex, string const & filename, Paragraph * par)
                        } else if (file_format > LYX_FORMAT) {
                                // future format
                                Alert::alert(_("Warning!"),
-                                       _("The file was created with a newer version of"
+                                       _("The file was created with a newer version of "
                                        "LyX. This is likely to cause problems."));
 
                        } else if (file_format < LYX_FORMAT) {
@@ -1216,7 +1258,7 @@ bool Buffer::readFile(LyXLex & lex, string const & filename, Paragraph * par)
                                        istringstream is(STRCONV(ret.second));
                                        LyXLex tmplex(0, 0);
                                        tmplex.setStream(is);
-                                       return readFile(tmplex, string());
+                                       return readFile(tmplex, string(), par);
                                } else {
                                        // This code is reached if lyx2lyx failed (for
                                        // some reason) to change the file format of
@@ -1228,12 +1270,6 @@ bool Buffer::readFile(LyXLex & lex, string const & filename, Paragraph * par)
                        bool the_end = readLyXformat2(lex, par);
                        params.setPaperStuff();
 
-#if 0
-                       // the_end was added in 213
-                       if (file_format < 213)
-                               the_end = true;
-#endif
-
                        if (!the_end) {
                                Alert::alert(_("Warning!"),
                                           _("Reading of document is not complete"),
@@ -1356,6 +1392,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
@@ -1542,7 +1587,7 @@ string const Buffer::asciiParagraph(Paragraph const & par,
 
        // this is to change the linebreak to do it by word a bit more
        // intelligent hopefully! (only in the case where we have a
-       // max linelenght!) (Jug)
+       // max linelength!) (Jug)
 
        string word;
 
@@ -1648,8 +1693,6 @@ void Buffer::writeFileAscii(ostream & os, int linelen)
 }
 
 
-bool use_babel;
-
 
 void Buffer::makeLaTeXFile(string const & fname,
                           string const & original_path,
@@ -1724,379 +1767,8 @@ void Buffer::makeLaTeXFile(ostream & os,
                        texrow.newline();
                }
 
-               os << "\\documentclass";
-
-               LyXTextClass const & tclass = params.getLyXTextClass();
-
-               ostringstream options; // the document class options.
-
-               if (tokenPos(tclass.opt_fontsize(),
-                            '|', params.fontsize) >= 0) {
-                       // only write if existing in list (and not default)
-                       options << params.fontsize << "pt,";
-               }
-
-
-               if (!params.use_geometry &&
-                   (params.paperpackage == BufferParams::PACKAGE_NONE)) {
-                       switch (params.papersize) {
-                       case BufferParams::PAPER_A4PAPER:
-                               options << "a4paper,";
-                               break;
-                       case BufferParams::PAPER_USLETTER:
-                               options << "letterpaper,";
-                               break;
-                       case BufferParams::PAPER_A5PAPER:
-                               options << "a5paper,";
-                               break;
-                       case BufferParams::PAPER_B5PAPER:
-                               options << "b5paper,";
-                               break;
-                       case BufferParams::PAPER_EXECUTIVEPAPER:
-                               options << "executivepaper,";
-                               break;
-                       case BufferParams::PAPER_LEGALPAPER:
-                               options << "legalpaper,";
-                               break;
-                       }
-               }
-
-               // if needed
-               if (params.sides != tclass.sides()) {
-                       switch (params.sides) {
-                       case LyXTextClass::OneSide:
-                               options << "oneside,";
-                               break;
-                       case LyXTextClass::TwoSides:
-                               options << "twoside,";
-                               break;
-                       }
-               }
-
-               // if needed
-               if (params.columns != tclass.columns()) {
-                       if (params.columns == 2)
-                               options << "twocolumn,";
-                       else
-                               options << "onecolumn,";
-               }
-
-               if (!params.use_geometry
-                   && params.orientation == BufferParams::ORIENTATION_LANDSCAPE)
-                       options << "landscape,";
-
-               // language should be a parameter to \documentclass
-               use_babel = false;
-               ostringstream language_options;
-               if (params.language->babel() == "hebrew"
-                   && default_language->babel() != "hebrew")
-                        // This seems necessary
-                       features.useLanguage(default_language);
-
-               if (lyxrc.language_use_babel ||
-                   params.language->lang() != lyxrc.default_language ||
-                   features.hasLanguages()) {
-                       use_babel = true;
-                       language_options << features.getLanguages();
-                       language_options << params.language->babel();
-                       if (lyxrc.language_global_options)
-                               options << language_options.str() << ',';
-               }
-
-               // the user-defined options
-               if (!params.options.empty()) {
-                       options << params.options << ',';
-               }
-
-               string strOptions(STRCONV(options.str()));
-               if (!strOptions.empty()) {
-                       strOptions = rtrim(strOptions, ",");
-                       os << '[' << strOptions << ']';
-               }
-
-               os << '{' << tclass.latexname() << "}\n";
-               texrow.newline();
-               // end of \documentclass defs
-
-               // font selection must be done before loading fontenc.sty
-               // The ae package is not needed when using OT1 font encoding.
-               if (params.fonts != "default" &&
-                   (params.fonts != "ae" || lyxrc.fontenc != "default")) {
-                       os << "\\usepackage{" << params.fonts << "}\n";
-                       texrow.newline();
-                       if (params.fonts == "ae") {
-                               os << "\\usepackage{aecompl}\n";
-                               texrow.newline();
-                       }
-               }
-               // this one is not per buffer
-               if (lyxrc.fontenc != "default") {
-                       os << "\\usepackage[" << lyxrc.fontenc
-                           << "]{fontenc}\n";
-                       texrow.newline();
-               }
-
-               if (params.inputenc == "auto") {
-                       string const doc_encoding =
-                               params.language->encoding()->LatexName();
-
-                       // Create a list with all the input encodings used
-                       // in the document
-                       set<string> encodings = features.getEncodingSet(doc_encoding);
-
-                       os << "\\usepackage[";
-                       std::copy(encodings.begin(), encodings.end(),
-                                 std::ostream_iterator<string>(os, ","));
-                       os << doc_encoding << "]{inputenc}\n";
-                       texrow.newline();
-               } else if (params.inputenc != "default") {
-                       os << "\\usepackage[" << params.inputenc
-                           << "]{inputenc}\n";
-                       texrow.newline();
-               }
-
-               // At the very beginning the text parameters.
-               if (params.paperpackage != BufferParams::PACKAGE_NONE) {
-                       switch (params.paperpackage) {
-                       case BufferParams::PACKAGE_A4:
-                               os << "\\usepackage{a4}\n";
-                               texrow.newline();
-                               break;
-                       case BufferParams::PACKAGE_A4WIDE:
-                               os << "\\usepackage{a4wide}\n";
-                               texrow.newline();
-                               break;
-                       case BufferParams::PACKAGE_WIDEMARGINSA4:
-                               os << "\\usepackage[widemargins]{a4}\n";
-                               texrow.newline();
-                               break;
-                       }
-               }
-               if (params.use_geometry) {
-                       os << "\\usepackage{geometry}\n";
-                       texrow.newline();
-                       os << "\\geometry{verbose";
-                       if (params.orientation == BufferParams::ORIENTATION_LANDSCAPE)
-                               os << ",landscape";
-                       switch (params.papersize2) {
-                       case BufferParams::VM_PAPER_CUSTOM:
-                               if (!params.paperwidth.empty())
-                                       os << ",paperwidth="
-                                           << params.paperwidth;
-                               if (!params.paperheight.empty())
-                                       os << ",paperheight="
-                                           << params.paperheight;
-                               break;
-                       case BufferParams::VM_PAPER_USLETTER:
-                               os << ",letterpaper";
-                               break;
-                       case BufferParams::VM_PAPER_USLEGAL:
-                               os << ",legalpaper";
-                               break;
-                       case BufferParams::VM_PAPER_USEXECUTIVE:
-                               os << ",executivepaper";
-                               break;
-                       case BufferParams::VM_PAPER_A3:
-                               os << ",a3paper";
-                               break;
-                       case BufferParams::VM_PAPER_A4:
-                               os << ",a4paper";
-                               break;
-                       case BufferParams::VM_PAPER_A5:
-                               os << ",a5paper";
-                               break;
-                       case BufferParams::VM_PAPER_B3:
-                               os << ",b3paper";
-                               break;
-                       case BufferParams::VM_PAPER_B4:
-                               os << ",b4paper";
-                               break;
-                       case BufferParams::VM_PAPER_B5:
-                               os << ",b5paper";
-                               break;
-                       default:
-                               // default papersize ie BufferParams::VM_PAPER_DEFAULT
-                               switch (lyxrc.default_papersize) {
-                               case BufferParams::PAPER_DEFAULT: // keep compiler happy
-                               case BufferParams::PAPER_USLETTER:
-                                       os << ",letterpaper";
-                                       break;
-                               case BufferParams::PAPER_LEGALPAPER:
-                                       os << ",legalpaper";
-                                       break;
-                               case BufferParams::PAPER_EXECUTIVEPAPER:
-                                       os << ",executivepaper";
-                                       break;
-                               case BufferParams::PAPER_A3PAPER:
-                                       os << ",a3paper";
-                                       break;
-                               case BufferParams::PAPER_A4PAPER:
-                                       os << ",a4paper";
-                                       break;
-                               case BufferParams::PAPER_A5PAPER:
-                                       os << ",a5paper";
-                                       break;
-                               case BufferParams::PAPER_B5PAPER:
-                                       os << ",b5paper";
-                                       break;
-                               }
-                       }
-                       if (!params.topmargin.empty())
-                               os << ",tmargin=" << params.topmargin;
-                       if (!params.bottommargin.empty())
-                               os << ",bmargin=" << params.bottommargin;
-                       if (!params.leftmargin.empty())
-                               os << ",lmargin=" << params.leftmargin;
-                       if (!params.rightmargin.empty())
-                               os << ",rmargin=" << params.rightmargin;
-                       if (!params.headheight.empty())
-                               os << ",headheight=" << params.headheight;
-                       if (!params.headsep.empty())
-                               os << ",headsep=" << params.headsep;
-                       if (!params.footskip.empty())
-                               os << ",footskip=" << params.footskip;
-                       os << "}\n";
-                       texrow.newline();
-               }
-
-               if (tokenPos(tclass.opt_pagestyle(),
-                            '|', params.pagestyle) >= 0) {
-                       if (params.pagestyle == "fancy") {
-                               os << "\\usepackage{fancyhdr}\n";
-                               texrow.newline();
-                       }
-                       os << "\\pagestyle{" << params.pagestyle << "}\n";
-                       texrow.newline();
-               }
-
-               if (params.secnumdepth != tclass.secnumdepth()) {
-                       os << "\\setcounter{secnumdepth}{"
-                           << params.secnumdepth
-                           << "}\n";
-                       texrow.newline();
-               }
-               if (params.tocdepth != tclass.tocdepth()) {
-                       os << "\\setcounter{tocdepth}{"
-                           << params.tocdepth
-                           << "}\n";
-                       texrow.newline();
-               }
-
-               if (params.paragraph_separation) {
-                       switch (params.defskip.kind()) {
-                       case VSpace::SMALLSKIP:
-                               os << "\\setlength\\parskip{\\smallskipamount}\n";
-                               break;
-                       case VSpace::MEDSKIP:
-                               os << "\\setlength\\parskip{\\medskipamount}\n";
-                               break;
-                       case VSpace::BIGSKIP:
-                               os << "\\setlength\\parskip{\\bigskipamount}\n";
-                               break;
-                       case VSpace::LENGTH:
-                               os << "\\setlength\\parskip{"
-                                   << params.defskip.length().asLatexString()
-                                   << "}\n";
-                               break;
-                       default: // should never happen // Then delete it.
-                               os << "\\setlength\\parskip{\\medskipamount}\n";
-                               break;
-                       }
-                       texrow.newline();
-
-                       os << "\\setlength\\parindent{0pt}\n";
-                       texrow.newline();
-               }
-
-               // Now insert the LyX specific LaTeX commands...
-
-               // The optional packages;
-               string preamble(features.getPackages());
-
-               // this might be useful...
-               preamble += "\n\\makeatletter\n";
-
-               // Some macros LyX will need
-               string tmppreamble(features.getMacros());
-
-               if (!tmppreamble.empty()) {
-                       preamble += "\n%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% "
-                               "LyX specific LaTeX commands.\n"
-                               + tmppreamble + '\n';
-               }
-
-               // the text class specific preamble
-               tmppreamble = features.getTClassPreamble();
-               if (!tmppreamble.empty()) {
-                       preamble += "%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% "
-                               "Textclass specific LaTeX commands.\n"
-                               + tmppreamble + '\n';
-               }
-
-               /* the user-defined preamble */
-               if (!params.preamble.empty()) {
-                       preamble += "%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% "
-                               "User specified LaTeX commands.\n"
-                               + params.preamble + '\n';
-               }
-
-               // Itemize bullet settings need to be last in case the user
-               // defines their own bullets that use a package included
-               // in the user-defined preamble -- ARRae
-               // Actually it has to be done much later than that
-               // since some packages like frenchb make modifications
-               // at \begin{document} time -- JMarc
-               string bullets_def;
-               for (int i = 0; i < 4; ++i) {
-                       if (params.user_defined_bullets[i] != ITEMIZE_DEFAULTS[i]) {
-                               if (bullets_def.empty())
-                                       bullets_def="\\AtBeginDocument{\n";
-                               bullets_def += "  \\renewcommand{\\labelitemi";
-                               switch (i) {
-                               // `i' is one less than the item to modify
-                               case 0:
-                                       break;
-                               case 1:
-                                       bullets_def += 'i';
-                                       break;
-                               case 2:
-                                       bullets_def += "ii";
-                                       break;
-                               case 3:
-                                       bullets_def += 'v';
-                                       break;
-                               }
-                               bullets_def += "}{" +
-                                 params.user_defined_bullets[i].getText()
-                                 + "}\n";
-                       }
-               }
-
-               if (!bullets_def.empty())
-                 preamble += bullets_def + "}\n\n";
-
-               int const nlines =
-                       int(lyx::count(preamble.begin(), preamble.end(), '\n'));
-               for (int j = 0; j != nlines; ++j) {
-                       texrow.newline();
-               }
-
-               // We try to load babel late, in case it interferes
-               // with other packages.
-               if (use_babel) {
-                       string tmp = lyxrc.language_package;
-                       if (!lyxrc.language_global_options
-                           && tmp == "\\usepackage{babel}")
-                               tmp = string("\\usepackage[") +
-                                       STRCONV(language_options.str()) +
-                                       "]{babel}";
-                       preamble += tmp + "\n";
-                       preamble += features.getBabelOptions();
-               }
-
-               preamble += "\\makeatother\n";
-
-               os << preamble;
+               // Write the preamble
+               params.writeLaTeX(os, features, texrow);
 
                if (only_preamble)
                        return;
@@ -2158,6 +1830,7 @@ void Buffer::latexParagraphs(ostream & ofs, Paragraph * par,
 {
        bool was_title = false;
        bool already_title = false;
+       LyXTextClass const & tclass = params.getLyXTextClass();
 
        // if only_body
        while (par != endpar) {
@@ -2174,10 +1847,24 @@ void Buffer::latexParagraphs(ostream & ofs, Paragraph * par,
                                        lyxerr <<"Error in latexParagraphs: You"
                                                " should not mix title layouts"
                                                " with normal ones." << endl;
-                               } else
+                               } else if (!was_title) {
                                        was_title = true;
+                                       if (tclass.titletype() == TITLE_ENVIRONMENT) {
+                                               ofs << "\\begin{"
+                                                   << tclass.titlename()
+                                                   << "}\n";
+                                               texrow.newline();
+                                       }
+                               }
                        } else if (was_title && !already_title) {
-                               ofs << "\\maketitle\n";
+                               if (tclass.titletype() == TITLE_ENVIRONMENT) {
+                                       ofs << "\\end{" << tclass.titlename()
+                                           << "}\n";
+                               }
+                               else {
+                                       ofs << "\\" << tclass.titlename()
+                                           << "\n";
+                               }
                                texrow.newline();
                                already_title = true;
                                was_title = false;
@@ -2196,7 +1883,14 @@ void Buffer::latexParagraphs(ostream & ofs, Paragraph * par,
        }
        // It might be that we only have a title in this document
        if (was_title && !already_title) {
-               ofs << "\\maketitle\n";
+               if (tclass.titletype() == TITLE_ENVIRONMENT) {
+                       ofs << "\\end{" << tclass.titlename()
+                           << "}\n";
+               }
+               else {
+                       ofs << "\\" << tclass.titlename()
+                           << "\n";
+                               }
                texrow.newline();
        }
 }
@@ -2341,6 +2035,7 @@ void Buffer::makeLinuxDocFile(string const & fname, bool nice, bool body_only)
 
                case LATEX_ENVIRONMENT:
                case LATEX_ITEM_ENVIRONMENT:
+               case LATEX_BIB_ENVIRONMENT:
                {
                        string const & latexname = style->latexname();
 
@@ -2395,6 +2090,7 @@ void Buffer::makeLinuxDocFile(string const & fname, bool nice, bool body_only)
                        break;
                case LATEX_ENVIRONMENT:
                case LATEX_ITEM_ENVIRONMENT:
+               case LATEX_BIB_ENVIRONMENT:
                        if (style->latexparam() == "CDATA")
                                ofs << "]]>";
                        break;
@@ -3064,7 +2760,7 @@ int Buffer::runChktex()
 {
        if (!users->text) return 0;
 
-       users->owner()->prohibitInput();
+       users->owner()->busy(true);
 
        // get LaTeX-Filename
        string const name = getLatexName();
@@ -3103,7 +2799,7 @@ int Buffer::runChktex()
                users->repaint();
                users->fitCursor();
        }
-       users->owner()->allowInput();
+       users->owner()->busy(false);
 
        return res;
 }
@@ -3113,6 +2809,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");
@@ -3172,83 +2873,48 @@ vector<string> const Buffer::getLabelList() const
 
 
 // This is also a buffer property (ale)
-vector<pair<string, string> > const Buffer::getBibkeyList() const
+void Buffer::fillWithBibKeys(vector<pair<string, string> > & keys) const
 {
-       typedef pair<string, string> StringPair;
        /// if this is a child document and the parent is already loaded
-       /// Use the parent's list instead  [ale990412]
+       /// use the parent's list instead  [ale990412]
        if (!params.parentname.empty() && bufferlist.exists(params.parentname)) {
                Buffer const * tmp = bufferlist.getBuffer(params.parentname);
-               if (tmp)
-                       return tmp->getBibkeyList();
-       }
-
-       vector<StringPair> keys;
-       ParagraphList::iterator pit = paragraphs.begin();
-       ParagraphList::iterator pend = paragraphs.end();
-       for (; pit != pend; ++pit) {
-               if (pit->bibkey) {
-                       string const key = pit->bibkey->getContents();
-                       string const opt = pit->bibkey->getOptions();
-                       string const ref = pit->asString(this, false);
-                       string const info = opt + "TheBibliographyRef" + ref;
-
-                       keys.push_back(StringPair(key, info));
+               if (tmp) {
+                       tmp->fillWithBibKeys(keys);
+                       return;
                }
        }
 
-       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) {
-               // Search for Bibtex or Include inset
-               if (it->lyxCode() == Inset::BIBTEX_CODE) {
-                       vector<StringPair> tmp =
-                               static_cast<InsetBibtex &>(*it).getKeys(this);
-                       keys.insert(keys.end(), tmp.begin(), tmp.end());
-               } else if (it->lyxCode() == Inset::INCLUDE_CODE) {
-                       vector<StringPair> const tmp =
-                               static_cast<InsetInclude &>(*it).getKeys();
-                       keys.insert(keys.end(), tmp.begin(), tmp.end());
+               if (it->lyxCode() == Inset::BIBTEX_CODE)
+                       static_cast<InsetBibtex &>(*it).fillWithBibKeys(this, keys);
+               else if (it->lyxCode() == Inset::INCLUDE_CODE)
+                       static_cast<InsetInclude &>(*it).fillWithBibKeys(keys);
+               else if (it->lyxCode() == Inset::BIBITEM_CODE) {
+                       InsetBibitem & bib = static_cast<InsetBibitem &>(*it);
+                       string const key = bib.getContents();
+                       string const opt = bib.getOptions();
+                       string const ref; // = pit->asString(this, false);
+                       string const info = opt + "TheBibliographyRef" + ref;
+                       keys.push_back(pair<string, string>(key, info));
                }
        }
-
-       return keys;
 }
 
 
 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;
 }
 
 
@@ -3348,18 +3014,21 @@ Paragraph * Buffer::getParFromID(int id) const
 {
        if (id < 0)
                return 0;
+       // why should we allow < 0 ??
+       //lyx::Assert(id >= 0);
+
+       ParConstIterator it(par_iterator_begin());
+       ParConstIterator end(par_iterator_end());
 
-       ParagraphList::iterator it = paragraphs.begin();
-       ParagraphList::iterator end = paragraphs.end();
        for (; it != end; ++it) {
-               if (it->id() == id) {
-                       return &*it;
-               }
-               Paragraph * tmp = it->getParFromID(id);
-               if (tmp) {
-                       return tmp;
+               // go on then, show me how to remove
+               // the cast
+               if ((*it)->id() == id) {
+                       return const_cast<Paragraph*>(*it);
                }
        }
+
        return 0;
 }
 
@@ -3455,10 +3124,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;
        }
 }