]> git.lyx.org Git - lyx.git/blobdiff - src/buffer.C
Add a Buffer::fully_loaded member function, returning true only when
[lyx.git] / src / buffer.C
index 3e1841f0e39e2799afde65f34200f37be0277b99..5fa662477800cf598057e9cc4304f2b75faef88e 100644 (file)
  *
  * \author Lars Gullik Bjønnes
  *
- * Full author contact details are available in file CREDITS
+ * Full author contact details are available in file CREDITS.
  */
 
 #include <config.h>
 
 #include "buffer.h"
+
+#include "author.h"
+#include "buffer_funcs.h"
 #include "bufferlist.h"
-#include "LyXAction.h"
-#include "lyxrc.h"
-#include "lyxlex.h"
-#include "tex-strings.h"
-#include "layout.h"
-#include "bufferview_funcs.h"
-#include "lyxfont.h"
-#include "version.h"
-#include "LaTeX.h"
+#include "bufferparams.h"
+#include "Bullet.h"
 #include "Chktex.h"
 #include "debug.h"
-#include "LaTeXFeatures.h"
-#include "lyxtext.h"
-#include "gettext.h"
-#include "language.h"
+#include "errorlist.h"
 #include "exporter.h"
-#include "Lsstream.h"
 #include "format.h"
-#include "BufferView.h"
-#include "ParagraphParameters.h"
+#include "funcrequest.h"
+#include "gettext.h"
 #include "iterators.h"
-#include "lyxtextclasslist.h"
-#include "sgml.h"
-#include "paragraph_funcs.h"
+#include "language.h"
+#include "LaTeX.h"
+#include "LaTeXFeatures.h"
+#include "LyXAction.h"
+#include "lyxlex.h"
+#include "lyxrc.h"
+#include "lyxvc.h"
 #include "messages.h"
-#include "author.h"
-
-#include "frontends/LyXView.h"
-
-#include "mathed/formulamacro.h"
-#include "mathed/formula.h"
+#include "paragraph.h"
+#include "paragraph_funcs.h"
+#include "ParagraphParameters.h"
+#include "sgml.h"
+#include "texrow.h"
+#include "undo.h"
+#include "version.h"
 
-#include "insets/inseterror.h"
 #include "insets/insetbibitem.h"
 #include "insets/insetbibtex.h"
 #include "insets/insetinclude.h"
 #include "insets/insettext.h"
 
-#include "frontends/Dialogs.h"
 #include "frontends/Alert.h"
 
 #include "graphics/Previews.h"
 
-#include "support/textutils.h"
+#include "support/FileInfo.h"
 #include "support/filetools.h"
-#include "support/path.h"
-#include "support/os.h"
+#include "support/gzstream.h"
 #include "support/lyxlib.h"
-#include "support/FileInfo.h"
-#include "support/lyxmanip.h"
-#include "support/lyxtime.h"
+#include "support/os.h"
+#include "support/path.h"
+#include "support/textutils.h"
+#include "support/tostr.h"
 
 #include <boost/bind.hpp>
 #include <boost/tuple/tuple.hpp>
-#include "support/BoostFormat.h"
 
-#include <fstream>
+#include "support/std_sstream.h"
+
 #include <iomanip>
-#include <map>
 #include <stack>
-#include <list>
-#include <algorithm>
 
-#include <cstdlib>
-#include <cmath>
-#include <unistd.h>
-#include <sys/types.h>
 #include <utime.h>
 
 #ifdef HAVE_LOCALE
-#include <locale>
 #endif
 
-#ifndef CXX_GLOBAL_CSTD
-using std::pow;
-#endif
+using lyx::pos_type;
+
+using lyx::support::AddName;
+using lyx::support::ascii_lowercase;
+using lyx::support::atoi;
+using lyx::support::bformat;
+using lyx::support::ChangeExtension;
+using lyx::support::cmd_ret;
+using lyx::support::compare_ascii_no_case;
+using lyx::support::compare_no_case;
+using lyx::support::contains;
+using lyx::support::CreateBufferTmpDir;
+using lyx::support::destroyDir;
+using lyx::support::FileInfo;
+using lyx::support::FileInfo;
+using lyx::support::getExtFromContents;
+using lyx::support::IsDirWriteable;
+using lyx::support::IsFileWriteable;
+using lyx::support::LibFileSearch;
+using lyx::support::ltrim;
+using lyx::support::MakeAbsPath;
+using lyx::support::MakeDisplayPath;
+using lyx::support::MakeLatexName;
+using lyx::support::OnlyFilename;
+using lyx::support::OnlyPath;
+using lyx::support::Path;
+using lyx::support::QuoteName;
+using lyx::support::removeAutosaveFile;
+using lyx::support::rename;
+using lyx::support::RunCommand;
+using lyx::support::split;
+using lyx::support::strToInt;
+using lyx::support::subst;
+using lyx::support::tempName;
+using lyx::support::trim;
+
+namespace os = lyx::support::os;
+
+using std::endl;
+using std::for_each;
+using std::make_pair;
 
-using std::ostream;
-using std::ofstream;
 using std::ifstream;
-using std::fstream;
+using std::list;
 using std::ios;
-using std::setw;
-using std::endl;
+using std::ostream;
+using std::ostringstream;
+using std::ofstream;
 using std::pair;
-using std::make_pair;
-using std::vector;
-using std::map;
 using std::stack;
-using std::list;
-using std::for_each;
+using std::vector;
+using std::string;
 
-using lyx::pos_type;
-using lyx::textclass_type;
 
 // all these externs should eventually be removed.
 extern BufferList bufferlist;
 
 namespace {
 
-const int LYX_FORMAT = 223;
+const int LYX_FORMAT = 225;
+
+bool openFileWrite(ofstream & ofs, string const & fname)
+{
+       ofs.open(fname.c_str());
+       if (!ofs) {
+               string const file = MakeDisplayPath(fname, 50);
+               string text = bformat(_("Could not open the specified "
+                                       "document\n%1$s."), file);
+               Alert::error(_("Could not open file"), text);
+               return false;
+       }
+       return true;
+}
 
 } // namespace anon
 
+
+typedef std::map<string, bool> DepClean;
+
+struct Buffer::Impl
+{
+       Impl(Buffer & parent, string const & file, bool readonly);
+
+       limited_stack<Undo> undostack;
+       limited_stack<Undo> redostack;
+       BufferParams params;
+       ParagraphList paragraphs;
+       LyXVC lyxvc;
+       string temppath;
+       bool nicefile;
+       TexRow texrow;
+
+       /// need to regenerate .tex ?
+       DepClean dep_clean;
+
+       /// is save needed
+       mutable bool lyx_clean;
+
+       /// is autosave needed
+       mutable bool bak_clean;
+
+       /// is this a unnamed file (New...)
+       bool unnamed;
+
+       /// buffer is r/o
+       bool read_only;
+
+       /// name of the file the buffer is associated with.
+       string filename;
+
+       /// The path to the document file.
+       string filepath;
+
+       boost::scoped_ptr<Messages> messages;
+
+       /** set to true only when the file is fully loaded.
+        *  Used to prevent the premature generation of previews
+        *  and by the citation inset.
+        */
+       bool file_fully_loaded;
+};
+
+
+Buffer::Impl::Impl(Buffer & parent, string const & file, bool readonly_)
+       : nicefile(true),
+         lyx_clean(true), bak_clean(true), unnamed(false), read_only(readonly_),
+         filename(file), filepath(OnlyPath(file)), file_fully_loaded(false)
+{
+       lyxvc.buffer(&parent);
+       if (readonly_ || lyxrc.use_tempdir)
+               temppath = CreateBufferTmpDir();
+}
+
+
 Buffer::Buffer(string const & file, bool ronly)
-       : niceFile(true), lyx_clean(true), bak_clean(true),
-         unnamed(false), read_only(ronly),
-         filename_(file), users(0)
+       : pimpl_(new Impl(*this, file, ronly))
 {
        lyxerr[Debug::INFO] << "Buffer::Buffer()" << endl;
-       filepath_ = OnlyPath(file);
-       lyxvc.buffer(this);
-       if (read_only || lyxrc.use_tempdir) {
-               tmppath = CreateBufferTmpDir();
-       } else {
-               tmppath.erase();
-       }
-
-       // set initial author
-       authors().record(Author(lyxrc.user_name, lyxrc.user_email));
 }
 
 
@@ -141,36 +219,114 @@ Buffer::~Buffer()
        // here the buffer should take care that it is
        // saved properly, before it goes into the void.
 
-       // make sure that views using this buffer
-       // forgets it.
-       if (users)
-               users->buffer(0);
-
-       if (!tmppath.empty() && destroyDir(tmppath) != 0) {
-#if USE_BOOST_FORMAT
-               boost::format fmt = _("Could not remove the temporary directory %1$s");
-               fmt % tmppath;
-               string msg = fmt.str();
-#else
-               string msg = _("Could not remove the temporary directory ") + tmppath;
-#endif
-               Alert::warning(_("Could not remove temporary directory"), msg);
+       closing();
+
+       if (!temppath().empty() && destroyDir(temppath()) != 0) {
+               Alert::warning(_("Could not remove temporary directory"),
+                       bformat(_("Could not remove the temporary directory %1$s"), temppath()));
        }
 
-       paragraphs.clear();
+       paragraphs().clear();
+
+       // Remove any previewed LaTeX snippets associated with this buffer.
+       lyx::graphics::Previews::get().removeLoader(*this);
+}
+
+
+limited_stack<Undo> & Buffer::undostack()
+{
+       return pimpl_->undostack;
+}
+
+
+limited_stack<Undo> const & Buffer::undostack() const
+{
+       return pimpl_->undostack;
+}
+
 
-       // Remove any previewed LaTeX snippets assocoated with this buffer.
-       grfx::Previews::get().removeLoader(this);
+limited_stack<Undo> & Buffer::redostack()
+{
+       return pimpl_->redostack;
+}
+
+
+limited_stack<Undo> const & Buffer::redostack() const
+{
+       return pimpl_->redostack;
+}
+
+
+BufferParams & Buffer::params()
+{
+       return pimpl_->params;
+}
+
+
+BufferParams const & Buffer::params() const
+{
+       return pimpl_->params;
+}
+
+
+ParagraphList & Buffer::paragraphs()
+{
+       return pimpl_->paragraphs;
+}
+
+
+ParagraphList const & Buffer::paragraphs() const
+{
+       return pimpl_->paragraphs;
+}
+
+
+LyXVC & Buffer::lyxvc()
+{
+       return pimpl_->lyxvc;
+}
+
+
+LyXVC const & Buffer::lyxvc() const
+{
+       return pimpl_->lyxvc;
+}
+
+
+string const & Buffer::temppath() const
+{
+       return pimpl_->temppath;
+}
+
+
+bool & Buffer::niceFile()
+{
+       return pimpl_->nicefile;
+}
+
+
+bool Buffer::niceFile() const
+{
+       return pimpl_->nicefile;
+}
+
+
+TexRow & Buffer::texrow()
+{
+       return pimpl_->texrow;
+}
+
+
+TexRow const & Buffer::texrow() const
+{
+       return pimpl_->texrow;
 }
 
 
 string const Buffer::getLatexName(bool no_path) const
 {
        string const name = ChangeExtension(MakeLatexName(fileName()), ".tex");
-       if (no_path)
-               return OnlyFilename(name);
-       else
-               return name;
+       return no_path ? OnlyFilename(name) : name;
 }
 
 
@@ -184,7 +340,7 @@ pair<Buffer::LogType, string> const Buffer::getLogName() const
        string path = OnlyPath(filename);
 
        if (lyxrc.use_tempdir || !IsDirWriteable(path))
-               path = tmppath;
+               path = temppath();
 
        string const fname = AddName(path,
                                     OnlyFilename(ChangeExtension(filename,
@@ -211,43 +367,18 @@ pair<Buffer::LogType, string> const Buffer::getLogName() const
 
 void Buffer::setReadonly(bool flag)
 {
-       if (read_only != flag) {
-               read_only = flag;
-               updateTitles();
-               users->owner()->getDialogs().updateBufferDependent(false);
+       if (pimpl_->read_only != flag) {
+               pimpl_->read_only = flag;
+               readonly(flag);
        }
 }
 
 
-AuthorList & Buffer::authors()
-{
-       return params.authorlist;
-}
-
-
-/// Update window titles of all users
-// Should work on a list
-void Buffer::updateTitles() const
-{
-       if (users)
-               users->owner()->updateWindowTitle();
-}
-
-
-/// Reset autosave timer of all users
-// Should work on a list
-void Buffer::resetAutosaveTimers() const
-{
-       if (users)
-               users->owner()->resetAutosaveTimer();
-}
-
-
 void Buffer::setFileName(string const & newfile)
 {
-       filename_ = MakeAbsPath(newfile);
-       filepath_ = OnlyPath(filename_);
-       setReadonly(IsFileWriteable(filename_) == 0);
+       pimpl_->filename = MakeAbsPath(newfile);
+       pimpl_->filepath = OnlyPath(pimpl_->filename);
+       setReadonly(IsFileWriteable(pimpl_->filename) == 0);
        updateTitles();
 }
 
@@ -257,16 +388,9 @@ namespace {
 
 void unknownClass(string const & unknown)
 {
-       string msg =
-#if USE_BOOST_FORMAT
-               boost::io::str(boost::format(
-                       _("Using the default document class, because the "
-                       " class %1$s is unknown.")) % unknown);
-#else
-               _("Using the default document class, because the "
-               " class ") + unknown + (" is unknown.");
-#endif
-       Alert::warning(_("Unknown document class"), msg);
+       Alert::warning(_("Unknown document class"),
+               bformat(_("Using the default document class, because the "
+                       "class %1$s is unknown."), unknown));
 }
 
 } // anon
@@ -288,12 +412,19 @@ int Buffer::readHeader(LyXLex & lex)
                lyxerr[Debug::PARSER] << "Handling header token: `"
                                      << token << '\'' << endl;
 
-               string unknown = params.readToken(lex, token);
+
+               string unknown = params().readToken(lex, token);
                if (!unknown.empty()) {
                        if (unknown[0] != '\\') {
                                unknownClass(unknown);
                        } else {
                                ++unknown_tokens;
+                               string const s = bformat(_("Unknown token: "
+                                                          "%1$s %2$s\n"),
+                                                        token,
+                                                        lex.getString());
+                               error(ErrorItem(_("Header error"), s,
+                                               -1, 0, 0));
                        }
                }
        }
@@ -308,35 +439,22 @@ int Buffer::readHeader(LyXLex & lex)
 // changed to be public and have one parameter
 // if par = 0 normal behavior
 // else insert behavior
-// Returns false if "\the_end" is not read (Asger)
+// Returns false if "\end_document" is not read (Asger)
 bool Buffer::readBody(LyXLex & lex, ParagraphList::iterator pit)
 {
-       int unknown_tokens = 0;
-
        Paragraph::depth_type depth = 0;
        bool the_end_read = false;
 
-       if (paragraphs.empty()) {
-               unknown_tokens += readHeader(lex);
-
-               if (!params.getLyXTextClass().load()) {
-                       string theclass = params.getLyXTextClass().name();
-                       string msg =
-#if USE_BOOST_FORMAT
-                               boost::io::str(boost::format(
-                                       _("Using the default document class, because the "
-                                       " class %1$s could not be loaded.")) % theclass);
-#else
-                               _("Using the default document class, because the "
-                               " class ") + theclass + (" could not be loaded.");
-#endif
-                       Alert::error(_("Can't load document class"), msg);
-                       params.textclass = 0;
+       if (paragraphs().empty()) {
+               readHeader(lex);
+               if (!params().getLyXTextClass().load()) {
+                       string theclass = params().getLyXTextClass().name();
+                       Alert::error(_("Can't load document class"), bformat(
+                                       "Using the default document class, because the "
+                                       " class %1$s could not be loaded.", theclass));
+                       params().textclass = 0;
                }
        } else {
-               // We are inserting into an existing document
-               users->text->breakParagraph(paragraphs);
-
                // We don't want to adopt the parameters from the
                // document we insert, so read them into a temporary buffer
                // and then discard it
@@ -355,70 +473,45 @@ bool Buffer::readBody(LyXLex & lex, ParagraphList::iterator pit)
                lyxerr[Debug::PARSER] << "Handling token: `"
                                      << token << '\'' << endl;
 
-               if (token == "\\the_end") {
+               if (token == "\\end_document") {
                        the_end_read = true;
                        continue;
                }
 
-               unknown_tokens += readParagraph(lex, token, paragraphs, pit, depth);
-       }
-
-
-       if (unknown_tokens > 0) {
-#if USE_BOOST_FORMAT
-               string s;
-               if (unknown_tokens == 1) {
-                       boost::format fmt(_("Encountered one unknown token when reading the document %1$s."));
-                       fmt % fileName();
-                       s = fmt.str();
-               } else {
-                       boost::format fmt(_("Encountered %1$s unknown tokens when reading the document %2$s."));
-                       fmt % tostr(unknown_tokens);
-                       fmt % fileName();
-                       s = fmt.str();
-               }
-#else
-               string s = _("Encountered ");
-               if (unknown_tokens == 1) {
-                       s += _("one unknown token");
-               } else {
-                       s += tostr(unknown_tokens);
-                       s += _(" unknown tokens");
-               }
-               Alert::warning(_("Document format failure"), s);
-#endif
+               readParagraph(lex, token, paragraphs(), pit, depth);
        }
 
        return the_end_read;
 }
 
 
-int
-Buffer::readParagraph(LyXLex & lex, string const & token,
-                     ParagraphList & pars, ParagraphList::iterator & pit,
-                     Paragraph::depth_type & depth)
+int Buffer::readParagraph(LyXLex & lex, string const & token,
+                         ParagraphList & pars, ParagraphList::iterator & pit,
+                         lyx::depth_type & depth)
 {
        static Change current_change;
        int unknown = 0;
 
-       if (token == "\\layout") {
+       if (token == "\\begin_layout") {
                lex.pushToken(token);
 
-               Paragraph * par = new Paragraph();
-               par->params().depth(depth);
-               if (params.tracking_changes)
-                       par->trackChanges();
-               LyXFont f(LyXFont::ALL_INHERIT, params.language);
-               par->setFont(0, f);
-
-               // FIXME: goddamn InsetTabular makes us pass a Buffer
-               // not BufferParams
-               unknown += ::readParagraph(*this, *par, lex);
+               Paragraph par;
+               par.params().depth(depth);
+               if (params().tracking_changes)
+                       par.trackChanges();
+               LyXFont f(LyXFont::ALL_INHERIT, params().language);
+               par.setFont(0, f);
 
                // insert after
                if (pit != pars.end())
                        ++pit;
+
                pit = pars.insert(pit, par);
+
+               // FIXME: goddamn InsetTabular makes us pass a Buffer
+               // not BufferParams
+               ::readParagraph(*this, *pit, lex);
+
        } else if (token == "\\begin_deeper") {
                ++depth;
        } else if (token == "\\end_deeper") {
@@ -450,8 +543,8 @@ void Buffer::insertStringAsLines(ParagraphList::iterator & par, pos_type & pos,
        for(string::const_iterator cit = str.begin();
            cit != str.end(); ++cit) {
                if (*cit == '\n') {
-                       if (autobreakrows && (!par->empty() || layout->keepempty)) {
-                               breakParagraph(params, paragraphs, par, pos,
+                       if (autobreakrows && (!par->empty() || par->allowEmpty())) {
+                               breakParagraph(params(), paragraphs(), par, pos,
                                               layout->isEnvironment());
                                ++par;
                                pos = 0;
@@ -461,12 +554,10 @@ void Buffer::insertStringAsLines(ParagraphList::iterator & par, pos_type & pos,
                        }
                        // do not insert consecutive spaces if !free_spacing
                } else if ((*cit == ' ' || *cit == '\t') &&
-                          space_inserted && !layout->free_spacing &&
-                                  !par->isFreeSpacing())
-               {
+                          space_inserted && !par->isFreeSpacing()) {
                        continue;
                } else if (*cit == '\t') {
-                       if (!layout->free_spacing && !par->isFreeSpacing()) {
+                       if (!par->isFreeSpacing()) {
                                // tabs are like spaces here
                                par->insertChar(pos, ' ', font);
                                ++pos;
@@ -493,26 +584,48 @@ void Buffer::insertStringAsLines(ParagraphList::iterator & par, pos_type & pos,
 }
 
 
-bool Buffer::readFile(LyXLex & lex, string const & filename)
+bool Buffer::readFile(string const & filename)
 {
-       bool ret = readFile(lex, filename, paragraphs.begin());
+       // Check if the file is compressed.
+       string const format = getExtFromContents(filename);
+       if (format == "gzip" || format == "zip" || format == "compress") {
+               params().compressed = true;
+       }
+
+       bool ret = readFile(filename, paragraphs().begin());
 
        // After we have read a file, we must ensure that the buffer
        // language is set and used in the gui.
        // If you know of a better place to put this, please tell me. (Lgb)
-       updateDocLang(params.language);
+       updateDocLang(params().language);
 
        return ret;
 }
 
 
-// FIXME: all the below Alerts should give the filename..
+bool Buffer::readFile(string const & filename, ParagraphList::iterator pit)
+{
+       LyXLex lex(0, 0);
+       lex.setFile(filename);
+
+       return readFile(lex, filename, pit);
+}
+
+
+bool Buffer::fully_loaded() const
+{
+       return pimpl_->file_fully_loaded;
+}
+
+
 bool Buffer::readFile(LyXLex & lex, string const & filename,
                      ParagraphList::iterator pit)
 {
+       BOOST_ASSERT(!filename.empty());
+
        if (!lex.isOK()) {
                Alert::error(_("Document could not be read"),
-                       _("The specified document could not be read."));
+                            bformat(_("%1$s could not be read."), filename));
                return false;
        }
 
@@ -521,14 +634,17 @@ bool Buffer::readFile(LyXLex & lex, string const & filename,
 
        if (!lex.isOK()) {
                Alert::error(_("Document could not be read"),
-                       _("The specified document could not be read."));
+                            bformat(_("%1$s could not be read."), filename));
                return false;
        }
 
        // the first token _must_ be...
        if (token != "\\lyxformat") {
+               lyxerr << "Token: " << token << endl;
+
                Alert::error(_("Document format failure"),
-                       _("The specified document is not a LyX document."));
+                            bformat(_("%1$s is not a LyX document."),
+                                      filename));
                return false;
        }
 
@@ -540,65 +656,60 @@ bool Buffer::readFile(LyXLex & lex, string const & filename,
        //lyxerr << "           dot found at " << dot << endl;
        if (dot != string::npos)
                        tmp_format.erase(dot, 1);
-       file_format = strToInt(tmp_format);
+       int file_format = strToInt(tmp_format);
        //lyxerr << "format: " << file_format << endl;
-       if (file_format == LYX_FORMAT) {
-               // current format
-       } else if (file_format > LYX_FORMAT) {
+
+       if (file_format > LYX_FORMAT) {
                Alert::warning(_("Document format failure"),
-                       _("This document was created with a newer version of "
-                       "LyX. This is likely to cause problems."));
+                              bformat(_("%1$s was created with a newer"
+                                        " version of LyX. This is likely to"
+                                        " cause problems."),
+                                        filename));
        } else if (file_format < LYX_FORMAT) {
-               // old formats
-               if (file_format < 200) {
-                       Alert::error(_("Document format failure"),
-                               _("This LyX document is too old to be read "
-                               "by this version of LyX. Try LyX 0.10."));
+               string const tmpfile = tempName();
+               string command = LibFileSearch("lyx2lyx", "lyx2lyx");
+               if (command.empty()) {
+                       Alert::error(_("Conversion script not found"),
+                                    bformat(_("%1$s is from an earlier"
+                                              " version of LyX, but the"
+                                              " conversion script lyx2lyx"
+                                              " could not be found."),
+                                              filename));
                        return false;
-               } else if (!filename.empty()) {
-                       string command =
-                               LibFileSearch("lyx2lyx", "lyx2lyx");
-                       if (command.empty()) {
-                               Alert::error(_("Conversion script not found"),
-                                       _("The document is from an earlier version "
-                                         "of LyX, but the conversion script lyx2lyx "
-                                         "could not be found."));
-                               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::error(_("Conversion script failed"),
-                                       _("The document is from an earlier version "
-                                         "of LyX, but the lyx2lyx script failed "
-                                         "to convert it."));
-                               return false;
-                       }
-                       istringstream is(STRCONV(ret.second));
-                       LyXLex tmplex(0, 0);
-                       tmplex.setStream(is);
-                       return readFile(tmplex, string(), pit);
-               } else {
-                       // This code is reached if lyx2lyx failed (for
-                       // some reason) to change the file format of
-                       // the file.
-                       lyx::Assert(false);
+               }
+               command += " -t"
+                       + tostr(LYX_FORMAT)
+                       + " -o " + tmpfile + ' '
+                       + QuoteName(filename);
+               lyxerr[Debug::INFO] << "Running '"
+                                   << command << '\''
+                                   << endl;
+               cmd_ret const ret = RunCommand(command);
+               if (ret.first != 0) {
+                       Alert::error(_("Conversion script failed"),
+                                    bformat(_("%1$s is from an earlier version"
+                                             " of LyX, but the lyx2lyx script"
+                                             " failed to convert it."),
+                                             filename));
                        return false;
+               } else {
+                       bool ret = readFile(tmpfile, pit);
+                       // Do stuff with tmpfile name and buffer name here.
+                       return ret;
                }
+
        }
+
        bool the_end = readBody(lex, pit);
-       params.setPaperStuff();
+       params().setPaperStuff();
 
        if (!the_end) {
                Alert::error(_("Document format failure"),
-                       _("The document ended unexpectedly, which means "
-                         "that it is probably corrupted."));
+                            bformat(_("%1$s ended unexpectedly, which means"
+                                      " that it is probably corrupted."),
+                                      filename));
        }
+       pimpl_->file_fully_loaded = true;
        return true;
 }
 
@@ -671,7 +782,7 @@ bool Buffer::save() const
        } else {
                // Saving failed, so backup is not backup
                if (lyxrc.make_backup) {
-                       lyx::rename(s, fileName());
+                       rename(s, fileName());
                }
                return false;
        }
@@ -681,7 +792,7 @@ bool Buffer::save() const
 
 bool Buffer::writeFile(string const & fname) const
 {
-       if (read_only && (fname == fileName())) {
+       if (pimpl_->read_only && (fname == fileName())) {
                return false;
        }
 
@@ -690,25 +801,45 @@ bool Buffer::writeFile(string const & fname) const
                return false;
        }
 
-       ofstream ofs(fname.c_str());
-       if (!ofs) {
-               return false;
+       bool retval;
+
+       if (params().compressed) {
+               gz::ogzstream ofs(fname.c_str());
+
+               if (!ofs)
+                       return false;
+
+               retval = do_writeFile(ofs);
+
+       } else {
+               ofstream ofs(fname.c_str());
+               if (!ofs)
+                       return false;
+
+               retval = do_writeFile(ofs);
        }
 
+       return retval;
+}
+
+
+bool Buffer::do_writeFile(ostream & ofs) const
+{
+
 #ifdef HAVE_LOCALE
        // Use the standard "C" locale for file output.
        ofs.imbue(std::locale::classic());
 #endif
 
-       // The top of the file should not be written by params.
+       // The top of the file should not be written by params().
 
        // write out a comment in the top of the file
-       ofs << '#' << lyx_docversion
+       ofs << "#LyX " << lyx_version
            << " created this file. For more info see http://www.lyx.org/\n"
            << "\\lyxformat " << LYX_FORMAT << "\n";
 
        // now write out the buffer paramters.
-       params.writeFile(ofs);
+       params().writeFile(ofs);
 
        ofs << "\\end_header\n";
 
@@ -716,15 +847,16 @@ bool Buffer::writeFile(string const & fname) const
 
        // this will write out all the paragraphs
        // using recursive descent.
-       ParagraphList::iterator pit = paragraphs.begin();
-       ParagraphList::iterator pend = paragraphs.end();
+       ParagraphList::const_iterator pit = paragraphs().begin();
+       ParagraphList::const_iterator pend = paragraphs().end();
        for (; pit != pend; ++pit)
-               pit->write(this, ofs, params, depth);
+               pit->write(*this, ofs, params(), depth);
 
        // Write marker that shows file is complete
-       ofs << "\n\\the_end" << endl;
+       ofs << "\n\\end_document" << endl;
 
-       ofs.close();
+       // Shouldn't really be needed....
+       //ofs.close();
 
        // how to check if close went ok?
        // Following is an attempt... (BE 20001011)
@@ -769,27 +901,10 @@ string const Buffer::asciiParagraph(Paragraph const & par,
                                    bool noparbreak) const
 {
        ostringstream buffer;
-       Paragraph::depth_type depth = 0;
        int ltype = 0;
        Paragraph::depth_type ltype_depth = 0;
        bool ref_printed = false;
-//     if (!par->previous()) {
-#if 0
-       // begins or ends a deeper area ?
-       if (depth != par->params().depth()) {
-               if (par->params().depth() > depth) {
-                       while (par->params().depth() > depth) {
-                               ++depth;
-                       }
-               } else {
-                       while (par->params().depth() < depth) {
-                               --depth;
-                       }
-               }
-       }
-#else
-       depth = par.params().depth();
-#endif
+       Paragraph::depth_type depth = par.params().depth();
 
        // First write the layout
        string const & tmp = par.layout()->name();
@@ -900,18 +1015,18 @@ string const Buffer::asciiParagraph(Paragraph const & par,
        string word;
 
        for (pos_type i = 0; i < par.size(); ++i) {
-               char c = par.getUChar(params, i);
+               char c = par.getUChar(params(), i);
                switch (c) {
                case Paragraph::META_INSET:
                {
-                       Inset const * inset = par.getInset(i);
+                       InsetOld const * inset = par.getInset(i);
                        if (inset) {
                                if (linelen > 0) {
                                        buffer << word;
                                        currlinelen += word.length();
                                        word.erase();
                                }
-                               if (inset->ascii(this, buffer, linelen)) {
+                               if (inset->ascii(*this, buffer, linelen)) {
                                        // to be sure it breaks paragraph
                                        currlinelen += linelen;
                                }
@@ -955,34 +1070,23 @@ string const Buffer::asciiParagraph(Paragraph const & par,
                }
        }
        buffer << word;
-       return STRCONV(buffer.str());
+       return buffer.str();
 }
 
 
 void Buffer::writeFileAscii(string const & fname, int linelen)
 {
-       ofstream ofs(fname.c_str());
-       if (!ofs) {
-               string const file = MakeDisplayPath(fname, 50);
-#if USE_BOOST_FORMAT
-               boost::format fmt(_("Could not save the document\n%1$s."));
-               fmt % file;
-               string text = fmt.str();
-#else
-               string text = _("Could not save the document\n");
-               text += file + ".";
-#endif
-               Alert::error(_("Could not save document"), text);
+       ofstream ofs;
+       if (!::openFileWrite(ofs, fname))
                return;
-       }
        writeFileAscii(ofs, linelen);
 }
 
 
 void Buffer::writeFileAscii(ostream & os, int linelen)
 {
-       ParagraphList::iterator beg = paragraphs.begin();
-       ParagraphList::iterator end = paragraphs.end();
+       ParagraphList::iterator beg = paragraphs().begin();
+       ParagraphList::iterator end = paragraphs().end();
        ParagraphList::iterator it = beg;
        for (; it != end; ++it) {
                os << asciiParagraph(*it, linelen, it == beg);
@@ -991,29 +1095,19 @@ void Buffer::writeFileAscii(ostream & os, int linelen)
 }
 
 
-
 void Buffer::makeLaTeXFile(string const & fname,
                           string const & original_path,
-                          bool nice, bool only_body, bool only_preamble)
+                          LatexRunParams const & runparams,
+                          bool output_preamble, bool output_body)
 {
        lyxerr[Debug::LATEX] << "makeLaTeXFile..." << endl;
 
-       ofstream ofs(fname.c_str());
-       if (!ofs) {
-               string const file = MakeDisplayPath(fname, 50);
-#if USE_BOOST_FORMAT
-               boost::format fmt(_("Could not open the specified document\n%1$s."));
-               fmt % file;
-               string text = fmt.str();
-#else
-               string text = _("Could not open the specified document\n");
-               text += file + ".";
-#endif
-               Alert::error(_("Could not open file"), text);
+       ofstream ofs;
+       if (!::openFileWrite(ofs, fname))
                return;
-       }
 
-       makeLaTeXFile(ofs, original_path, nice, only_body, only_preamble);
+       makeLaTeXFile(ofs, original_path,
+                     runparams, output_preamble, output_body);
 
        ofs.close();
        if (ofs.fail()) {
@@ -1024,28 +1118,30 @@ void Buffer::makeLaTeXFile(string const & fname,
 
 void Buffer::makeLaTeXFile(ostream & os,
                           string const & original_path,
-                          bool nice, bool only_body, bool only_preamble)
+                          LatexRunParams const & runparams_in,
+                          bool output_preamble, bool output_body)
 {
-       niceFile = nice; // this will be used by Insetincludes.
+       LatexRunParams runparams = runparams_in;
+       niceFile() = runparams.nice; // this will be used by Insetincludes.
 
        // validate the buffer.
        lyxerr[Debug::LATEX] << "  Validating buffer..." << endl;
-       LaTeXFeatures features(params);
+       LaTeXFeatures features(*this, params());
        validate(features);
        lyxerr[Debug::LATEX] << "  Buffer validation done." << endl;
 
-       texrow.reset();
+       texrow().reset();
        // The starting paragraph of the coming rows is the
        // first paragraph of the document. (Asger)
-       texrow.start(&*(paragraphs.begin()), 0);
+       texrow().start(paragraphs().begin()->id(), 0);
 
-       if (!only_body && nice) {
-               os << "%% " << lyx_docversion << " created this file.  "
+       if (output_preamble && runparams.nice) {
+               os << "%% LyX " << lyx_version << " created this file.  "
                        "For more info, see http://www.lyx.org/.\n"
                        "%% Do not edit unless you really know what "
                        "you are doing.\n";
-               texrow.newline();
-               texrow.newline();
+               texrow().newline();
+               texrow().newline();
        }
        lyxerr[Debug::INFO] << "lyx header finished" << endl;
        // There are a few differences between nice LaTeX and usual files:
@@ -1055,12 +1151,12 @@ void Buffer::makeLaTeXFile(ostream & os,
        // input@path is set when the actual parameter
        // original_path is set. This is done for usual tex-file, but not
        // for nice-latex-file. (Matthias 250696)
-       if (!only_body) {
-               if (!nice) {
+       if (output_preamble) {
+               if (!runparams.nice) {
                        // code for usual, NOT nice-latex-file
                        os << "\\batchmode\n"; // changed
                        // from \nonstopmode
-                       texrow.newline();
+                       texrow().newline();
                }
                if (!original_path.empty()) {
                        string inputpath = os::external_path(original_path);
@@ -1069,46 +1165,46 @@ void Buffer::makeLaTeXFile(ostream & os,
                            << "\\def\\input@path{{"
                            << inputpath << "/}}\n"
                            << "\\makeatother\n";
-                       texrow.newline();
-                       texrow.newline();
-                       texrow.newline();
+                       texrow().newline();
+                       texrow().newline();
+                       texrow().newline();
                }
 
                // Write the preamble
-               params.writeLaTeX(os, features, texrow);
+               runparams.use_babel = params().writeLaTeX(os, features, texrow());
 
-               if (only_preamble)
+               if (!output_body)
                        return;
 
                // make the body.
                os << "\\begin{document}\n";
-               texrow.newline();
-       } // only_body
+               texrow().newline();
+       } // output_preamble
        lyxerr[Debug::INFO] << "preamble finished, now the body." << endl;
 
        if (!lyxrc.language_auto_begin) {
                os << subst(lyxrc.language_command_begin, "$$lang",
-                            params.language->babel())
+                            params().language->babel())
                    << endl;
-               texrow.newline();
+               texrow().newline();
        }
 
-       latexParagraphs(this, paragraphs, paragraphs.begin(), paragraphs.end(), os, texrow);
+       latexParagraphs(*this, paragraphs(), os, texrow(), runparams);
 
        // add this just in case after all the paragraphs
        os << endl;
-       texrow.newline();
+       texrow().newline();
 
        if (!lyxrc.language_auto_end) {
                os << subst(lyxrc.language_command_end, "$$lang",
-                            params.language->babel())
+                            params().language->babel())
                    << endl;
-               texrow.newline();
+               texrow().newline();
        }
 
-       if (!only_body) {
+       if (output_preamble) {
                os << "\\end{document}\n";
-               texrow.newline();
+               texrow().newline();
 
                lyxerr[Debug::LATEX] << "makeLaTeXFile...done" << endl;
        } else {
@@ -1117,44 +1213,44 @@ void Buffer::makeLaTeXFile(ostream & os,
        }
 
        // Just to be sure. (Asger)
-       texrow.newline();
+       texrow().newline();
 
        lyxerr[Debug::INFO] << "Finished making LaTeX file." << endl;
-       lyxerr[Debug::INFO] << "Row count was " << texrow.rows() - 1
+       lyxerr[Debug::INFO] << "Row count was " << texrow().rows() - 1
                            << '.' << endl;
 
        // we want this to be true outside previews (for insetexternal)
-       niceFile = true;
+       niceFile() = true;
 }
 
 
 bool Buffer::isLatex() const
 {
-       return params.getLyXTextClass().outputType() == LATEX;
+       return params().getLyXTextClass().outputType() == LATEX;
 }
 
 
 bool Buffer::isLinuxDoc() const
 {
-       return params.getLyXTextClass().outputType() == LINUXDOC;
+       return params().getLyXTextClass().outputType() == LINUXDOC;
 }
 
 
 bool Buffer::isLiterate() const
 {
-       return params.getLyXTextClass().outputType() == LITERATE;
+       return params().getLyXTextClass().outputType() == LITERATE;
 }
 
 
 bool Buffer::isDocBook() const
 {
-       return params.getLyXTextClass().outputType() == DOCBOOK;
+       return params().getLyXTextClass().outputType() == DOCBOOK;
 }
 
 
 bool Buffer::isSGML() const
 {
-       LyXTextClass const & tclass = params.getLyXTextClass();
+       LyXTextClass const & tclass = params().getLyXTextClass();
 
        return tclass.outputType() == LINUXDOC ||
               tclass.outputType() == DOCBOOK;
@@ -1163,39 +1259,27 @@ bool Buffer::isSGML() const
 
 void Buffer::makeLinuxDocFile(string const & fname, bool nice, bool body_only)
 {
-       ofstream ofs(fname.c_str());
-
-       if (!ofs) {
-               string const file = MakeDisplayPath(fname, 50);
-#if USE_BOOST_FORMAT
-               boost::format fmt(_("Could not save the specified document\n%1$s.\n"));
-               fmt % file;
-               string text = fmt.str();
-#else
-               string text = _("Could not save the specified document\n");
-               text += file + _(".\n");
-#endif
-               Alert::error(_("Could not save document"), text);
+       ofstream ofs;
+       if (!::openFileWrite(ofs, fname))
                return;
-       }
 
-       niceFile = nice; // this will be used by included files.
+       niceFile() = nice; // this will be used by included files.
 
-       LaTeXFeatures features(params);
+       LaTeXFeatures features(*this, params());
 
        validate(features);
 
-       texrow.reset();
+       texrow().reset();
 
-       LyXTextClass const & tclass = params.getLyXTextClass();
+       LyXTextClass const & tclass = params().getLyXTextClass();
 
        string top_element = tclass.latexname();
 
        if (!body_only) {
                ofs << "<!doctype linuxdoc system";
 
-               string preamble = params.preamble;
-               const string name = nice ? ChangeExtension(filename_, ".sgml")
+               string preamble = params().preamble;
+               string const name = nice ? ChangeExtension(pimpl_->filename, ".sgml")
                         : fname;
                preamble += features.getIncludedFiles(name);
                preamble += features.getLyXSGMLEntities();
@@ -1205,17 +1289,17 @@ void Buffer::makeLinuxDocFile(string const & fname, bool nice, bool body_only)
                }
                ofs << ">\n\n";
 
-               if (params.options.empty())
+               if (params().options.empty())
                        sgml::openTag(ofs, 0, false, top_element);
                else {
                        string top = top_element;
                        top += ' ';
-                       top += params.options;
+                       top += params().options;
                        sgml::openTag(ofs, 0, false, top);
                }
        }
 
-       ofs << "<!-- "  << lyx_docversion
+       ofs << "<!-- LyX "  << lyx_version
            << " created this file. For more info see http://www.lyx.org/"
            << " -->\n";
 
@@ -1223,15 +1307,15 @@ void Buffer::makeLinuxDocFile(string const & fname, bool nice, bool body_only)
        string item_name;
        vector<string> environment_stack(5);
 
-       ParagraphList::iterator pit = paragraphs.begin();
-       ParagraphList::iterator pend = paragraphs.end();
+       ParagraphList::iterator pit = paragraphs().begin();
+       ParagraphList::iterator pend = paragraphs().end();
        for (; pit != pend; ++pit) {
                LyXLayout_ptr const & style = pit->layout();
                // treat <toc> as a special case for compatibility with old code
                if (pit->isInset(0)) {
-                       Inset * inset = pit->getInset(0);
-                       Inset::Code lyx_code = inset->lyxCode();
-                       if (lyx_code == Inset::TOC_CODE) {
+                       InsetOld * inset = pit->getInset(0);
+                       InsetOld::Code lyx_code = inset->lyxCode();
+                       if (lyx_code == InsetOld::TOC_CODE) {
                                string const temp = "toc";
                                sgml::openTag(ofs, depth, false, temp);
                                continue;
@@ -1261,8 +1345,7 @@ void Buffer::makeLinuxDocFile(string const & fname, bool nice, bool body_only)
 
                case LATEX_COMMAND:
                        if (depth != 0)
-                               sgmlError(&*pit, 0,
-                                         _("Error: Wrong depth for LatexType Command.\n"));
+                               error(ErrorItem(_("Error:"), _("Wrong depth for LatexType Command.\n"), pit->id(), 0, pit->size()));
 
                        if (!environment_stack[depth].empty()) {
                                sgml::closeTag(ofs, depth, false, environment_stack[depth]);
@@ -1319,7 +1402,7 @@ void Buffer::makeLinuxDocFile(string const & fname, bool nice, bool body_only)
                        break;
                }
 
-               simpleLinuxDocOnePar(ofs, &*pit, depth);
+               simpleLinuxDocOnePar(ofs, pit, depth);
 
                ofs << "\n";
                // write closing SGML tags
@@ -1351,7 +1434,7 @@ void Buffer::makeLinuxDocFile(string const & fname, bool nice, bool body_only)
        // How to check for successful close
 
        // we want this to be true outside previews (for insetexternal)
-       niceFile = true;
+       niceFile() = true;
 }
 
 
@@ -1412,8 +1495,8 @@ void reset(PAR_TAG & p1, PAR_TAG const & p2)
 
 // Handle internal paragraph parsing -- layout already processed.
 void Buffer::simpleLinuxDocOnePar(ostream & os,
-       Paragraph * par,
-       Paragraph::depth_type /*depth*/)
+       ParagraphList::iterator par,
+       lyx::depth_type /*depth*/) const
 {
        LyXLayout_ptr const & style = par->layout();
 
@@ -1442,7 +1525,7 @@ void Buffer::simpleLinuxDocOnePar(ostream & os,
                PAR_TAG tag_close = NONE;
                list < PAR_TAG > tag_open;
 
-               LyXFont const font = par->getFont(params, i, outerFont(par, paragraphs));
+               LyXFont const font = par->getFont(params(), i, outerFont(par, paragraphs()));
 
                if (font_old.family() != font.family()) {
                        switch (family_type) {
@@ -1554,8 +1637,8 @@ void Buffer::simpleLinuxDocOnePar(ostream & os,
                char c = par->getChar(i);
 
                if (c == Paragraph::META_INSET) {
-                       Inset * inset = par->getInset(i);
-                       inset->linuxdoc(this, os);
+                       InsetOld * inset = par->getInset(i);
+                       inset->linuxdoc(*this, os);
                        font_old = font;
                        continue;
                }
@@ -1569,7 +1652,7 @@ void Buffer::simpleLinuxDocOnePar(ostream & os,
                        bool ws;
                        string str;
                        boost::tie(ws, str) = sgml::escapeChar(c);
-                       if (ws && !style->free_spacing && !par->isFreeSpacing()) {
+                       if (ws && !par->isFreeSpacing()) {
                                // in freespacing mode, spaces are
                                // non-breaking characters
                                if (desc_on) {// if char is ' ' then...
@@ -1604,60 +1687,28 @@ void Buffer::simpleLinuxDocOnePar(ostream & os,
 }
 
 
-// Print an error message.
-void Buffer::sgmlError(ParagraphList::iterator /*par*/, int /*pos*/,
-       string const & /*message*/) const
-{
-#ifdef WITH_WARNINGS
-#warning This is wrong we cannot insert an inset like this!!!
-       // I guess this was Jose' so I explain you more or less why this
-       // is wrong. This way you insert something in the paragraph and
-       // don't tell it to LyXText (row rebreaking and undo handling!!!)
-       // I deactivate this code, have a look at BufferView::insertErrors
-       // how you should do this correctly! (Jug 20020315)
-#endif
-#if 0
-       // insert an error marker in text
-       InsetError * new_inset = new InsetError(message);
-       par->insertInset(pos, new_inset, LyXFont(LyXFont::ALL_INHERIT,
-                        params.language));
-#endif
-}
-
-
 void Buffer::makeDocBookFile(string const & fname, bool nice, bool only_body)
 {
-       ofstream ofs(fname.c_str());
-       if (!ofs) {
-               string const file = MakeDisplayPath(fname, 50);
-#if USE_BOOST_FORMAT
-               boost::format fmt(_("Could not save the specified document\n%1$s.\n"));
-               fmt % file;
-               string text = fmt.str();
-#else
-               string text = _("Could not save the specified document\n");
-               text += file + _(".\n");
-#endif
-               Alert::error(_("Could not save document"), text);
+       ofstream ofs;
+       if (!::openFileWrite(ofs, fname))
                return;
-       }
 
-       niceFile = nice; // this will be used by Insetincludes.
+       niceFile() = nice; // this will be used by Insetincludes.
 
-       LaTeXFeatures features(params);
+       LaTeXFeatures features(*this, params());
        validate(features);
 
-       texrow.reset();
+       texrow().reset();
 
-       LyXTextClass const & tclass = params.getLyXTextClass();
+       LyXTextClass const & tclass = params().getLyXTextClass();
        string top_element = tclass.latexname();
 
        if (!only_body) {
                ofs << "<!DOCTYPE " << top_element
                    << "  PUBLIC \"-//OASIS//DTD DocBook V4.1//EN\"";
 
-               string preamble = params.preamble;
-               const string name = nice ? ChangeExtension(filename_, ".sgml")
+               string preamble = params().preamble;
+               string const name = nice ? ChangeExtension(pimpl_->filename, ".sgml")
                         : fname;
                preamble += features.getIncludedFiles(name);
                preamble += features.getLyXSGMLEntities();
@@ -1670,16 +1721,16 @@ void Buffer::makeDocBookFile(string const & fname, bool nice, bool only_body)
 
        string top = top_element;
        top += " lang=\"";
-       top += params.language->code();
+       top += params().language->code();
        top += '"';
 
-       if (!params.options.empty()) {
+       if (!params().options.empty()) {
                top += ' ';
-               top += params.options;
+               top += params().options;
        }
        sgml::openTag(ofs, 0, false, top);
 
-       ofs << "<!-- DocBook file was created by " << lyx_docversion
+       ofs << "<!-- DocBook file was created by LyX " << lyx_version
            << "\n  See http://www.lyx.org/ for more information -->\n";
 
        vector<string> environment_stack(10);
@@ -1695,8 +1746,8 @@ void Buffer::makeDocBookFile(string const & fname, bool nice, bool only_body)
        string item_name;
        string command_name;
 
-       ParagraphList::iterator par = paragraphs.begin();
-       ParagraphList::iterator pend = paragraphs.end();
+       ParagraphList::iterator par = paragraphs().begin();
+       ParagraphList::iterator pend = paragraphs().end();
 
        for (; par != pend; ++par) {
                string sgmlparam;
@@ -1708,7 +1759,7 @@ void Buffer::makeDocBookFile(string const & fname, bool nice, bool only_body)
 
                // environment tag closing
                for (; depth > par->params().depth(); --depth) {
-                       if (environment_inner[depth] != "!-- --") {
+                       if (environment_inner[depth] != "!-- --" && !environment_inner[depth].empty()) {
                                item_name = "listitem";
                                sgml::closeTag(ofs, command_depth + depth, false, item_name);
                                if (environment_inner[depth] == "varlistentry")
@@ -1744,15 +1795,14 @@ void Buffer::makeDocBookFile(string const & fname, bool nice, bool only_body)
 
                case LATEX_COMMAND:
                        if (depth != 0)
-                               sgmlError(par, 0,
-                                         _("Error: Wrong depth for LatexType Command.\n"));
+                               error(ErrorItem(_("Error"), _("Wrong depth for LatexType Command."), par->id(), 0, par->size()));
 
                        command_name = style->latexname();
 
                        sgmlparam = style->latexparam();
                        c_params = split(sgmlparam, c_depth,'|');
 
-                       cmd_depth = lyx::atoi(c_depth);
+                       cmd_depth = atoi(c_depth);
 
                        if (command_flag) {
                                if (cmd_depth < command_base) {
@@ -1784,9 +1834,9 @@ void Buffer::makeDocBookFile(string const & fname, bool nice, bool only_body)
                        // This is a hack while paragraphs can't have
                        // attributes, like id in this case.
                        if (par->isInset(0)) {
-                               Inset * inset = par->getInset(0);
-                               Inset::Code lyx_code = inset->lyxCode();
-                               if (lyx_code == Inset::LABEL_CODE) {
+                               InsetOld * inset = par->getInset(0);
+                               InsetOld::Code lyx_code = inset->lyxCode();
+                               if (lyx_code == InsetOld::LABEL_CODE) {
                                        command_name += " id=\"";
                                        command_name += (static_cast<InsetCommand *>(inset))->getContents();
                                        command_name += '"';
@@ -1910,13 +1960,13 @@ void Buffer::makeDocBookFile(string const & fname, bool nice, bool only_body)
        // How to check for successful close
 
        // we want this to be true outside previews (for insetexternal)
-       niceFile = true;
+       niceFile() = true;
 }
 
 
 void Buffer::simpleDocBookOnePar(ostream & os,
                                 ParagraphList::iterator par, int & desc_on,
-                                Paragraph::depth_type depth) const
+                                lyx::depth_type depth) const
 {
        bool emph_flag = false;
 
@@ -1930,7 +1980,7 @@ void Buffer::simpleDocBookOnePar(ostream & os,
 
        // parsing main loop
        for (pos_type i = 0; i < par->size(); ++i) {
-               LyXFont font = par->getFont(params, i, outerFont(par, paragraphs));
+               LyXFont font = par->getFont(params(), i, outerFont(par, paragraphs()));
 
                // handle <emphasis> tag
                if (font_old.emph() != font.emph()) {
@@ -1953,12 +2003,12 @@ void Buffer::simpleDocBookOnePar(ostream & os,
 
 
                if (par->isInset(i)) {
-                       Inset * inset = par->getInset(i);
+                       InsetOld * inset = par->getInset(i);
                        // don't print the inset in position 0 if desc_on == 3 (label)
                        if (i || desc_on != 3) {
                                if (style->latexparam() == "CDATA")
                                        os << "]]>";
-                               inset->docbook(this, os, false);
+                               inset->docbook(*this, os, false);
                                if (style->latexparam() == "CDATA")
                                        os << "<![CDATA[";
                        }
@@ -1970,9 +2020,9 @@ void Buffer::simpleDocBookOnePar(ostream & os,
 
                        if (style->pass_thru) {
                                os << c;
-                       } else if (style->free_spacing || par->isFreeSpacing() || c != ' ') {
+                       } else if (par->isFreeSpacing() || c != ' ') {
                                        os << str;
-                       } else if (desc_on ==1) {
+                       } else if (desc_on == 1) {
                                ++char_line_count;
                                os << "\n</term><listitem><para>";
                                desc_on = 2;
@@ -2005,9 +2055,7 @@ void Buffer::simpleDocBookOnePar(ostream & os,
 // Other flags: -wall -v0 -x
 int Buffer::runChktex()
 {
-       if (!users->text) return 0;
-
-       users->owner()->busy(true);
+       busy(true);
 
        // get LaTeX-Filename
        string const name = getLatexName();
@@ -2015,17 +2063,17 @@ int Buffer::runChktex()
 
        string const org_path = path;
        if (lyxrc.use_tempdir || !IsDirWriteable(path)) {
-               path = tmppath;
+               path = temppath();
        }
 
        Path p(path); // path to LaTeX file
-       users->owner()->message(_("Running chktex..."));
-
-       // Remove all error insets
-       bool const removedErrorInsets = users->removeAutoInsets();
+       message(_("Running chktex..."));
 
        // Generate the LaTeX file if neccessary
-       makeLaTeXFile(name, org_path, false);
+       LatexRunParams runparams;
+       runparams.flavor = LatexRunParams::LATEX;
+       runparams.nice = false;
+       makeLaTeXFile(name, org_path, runparams);
 
        TeXErrors terr;
        Chktex chktex(lyxrc.chktex_command, name, filePath());
@@ -2033,20 +2081,13 @@ int Buffer::runChktex()
 
        if (res == -1) {
                Alert::error(_("chktex failure"),
-                       _("Could not run chktex successfully."));
+                            _("Could not run chktex successfully."));
        } else if (res > 0) {
                // Insert all errors as errors boxes
-               users->insertErrors(terr);
+               bufferErrors(*this, terr);
        }
 
-       // if we removed error insets before we ran chktex or if we inserted
-       // error insets after we ran chktex, this must be run:
-       if (removedErrorInsets || res) {
-#warning repaint needed here, or do you mean update() ?
-               users->repaint();
-               users->fitCursor();
-       }
-       users->owner()->busy(false);
+       busy(false);
 
        return res;
 }
@@ -2054,29 +2095,29 @@ int Buffer::runChktex()
 
 void Buffer::validate(LaTeXFeatures & features) const
 {
-       LyXTextClass const & tclass = params.getLyXTextClass();
+       LyXTextClass const & tclass = params().getLyXTextClass();
 
-       if (params.tracking_changes) {
+       if (params().tracking_changes) {
                features.require("dvipost");
                features.require("color");
        }
 
        // AMS Style is at document level
-       if (params.use_amsmath == BufferParams::AMS_ON
+       if (params().use_amsmath == BufferParams::AMS_ON
            || tclass.provides(LyXTextClass::amsmath))
                features.require("amsmath");
 
-       for_each(paragraphs.begin(), paragraphs.end(),
+       for_each(paragraphs().begin(), paragraphs().end(),
                 boost::bind(&Paragraph::validate, _1, boost::ref(features)));
 
        // the bullet shapes are buffer level not paragraph level
        // so they are tested here
        for (int i = 0; i < 4; ++i) {
-               if (params.user_defined_bullets[i] != ITEMIZE_DEFAULTS[i]) {
-                       int const font = params.user_defined_bullets[i].getFont();
+               if (params().user_defined_bullet(i) != ITEMIZE_DEFAULTS[i]) {
+                       int const font = params().user_defined_bullet(i).getFont();
                        if (font == 0) {
-                               int const c = params
-                                       .user_defined_bullets[i]
+                               int const c = params()
+                                       .user_defined_bullet(i)
                                        .getCharacter();
                                if (c == 16
                                   || c == 17
@@ -2099,34 +2140,34 @@ void Buffer::validate(LaTeXFeatures & features) const
 }
 
 
-vector<string> const Buffer::getLabelList() const
+void Buffer::getLabelList(std::vector<string> & list) const
 {
        /// if this is a child document and the parent is already loaded
        /// Use the parent's list instead  [ale990407]
-       if (!params.parentname.empty()
-           && bufferlist.exists(params.parentname)) {
-               Buffer const * tmp = bufferlist.getBuffer(params.parentname);
-               if (tmp)
-                       return tmp->getLabelList();
+       if (!params().parentname.empty()
+           && bufferlist.exists(params().parentname)) {
+               Buffer const * tmp = bufferlist.getBuffer(params().parentname);
+               if (tmp) {
+                       tmp->getLabelList(list);
+                       return;
+               }
        }
 
-       vector<string> label_list;
        for (inset_iterator it = inset_const_iterator_begin();
             it != inset_const_iterator_end(); ++it) {
-               vector<string> const l = it->getLabelList();
-               label_list.insert(label_list.end(), l.begin(), l.end());
+               it->getLabelList(*this, list);
        }
-       return label_list;
 }
 
 
 // This is also a buffer property (ale)
-void Buffer::fillWithBibKeys(vector<pair<string, string> > & keys) const
+void Buffer::fillWithBibKeys(std::vector<std::pair<string, string> > & keys) const
 {
        /// if this is a child document and the parent is already loaded
        /// use the parent's list instead  [ale990412]
-       if (!params.parentname.empty() && bufferlist.exists(params.parentname)) {
-               Buffer const * tmp = bufferlist.getBuffer(params.parentname);
+       if (!params().parentname.empty() &&
+           bufferlist.exists(params().parentname)) {
+               Buffer const * tmp = bufferlist.getBuffer(params().parentname);
                if (tmp) {
                        tmp->fillWithBibKeys(keys);
                        return;
@@ -2135,14 +2176,19 @@ void Buffer::fillWithBibKeys(vector<pair<string, string> > & keys) const
 
        for (inset_iterator it = inset_const_iterator_begin();
                it != inset_const_iterator_end(); ++it) {
-               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();
+               if (it->lyxCode() == InsetOld::BIBTEX_CODE) {
+                       InsetBibtex const & inset =
+                               dynamic_cast<InsetBibtex const &>(*it);
+                       inset.fillWithBibKeys(*this, keys);
+               } else if (it->lyxCode() == InsetOld::INCLUDE_CODE) {
+                       InsetInclude const & inset =
+                               dynamic_cast<InsetInclude const &>(*it);
+                       inset.fillWithBibKeys(*this, keys);
+               } else if (it->lyxCode() == InsetOld::BIBITEM_CODE) {
+                       InsetBibitem const & inset =
+                               dynamic_cast<InsetBibitem const &>(*it);
+                       string const key = inset.getContents();
+                       string const opt = inset.getOptions();
                        string const ref; // = pit->asString(this, false);
                        string const info = opt + "TheBibliographyRef" + ref;
                        keys.push_back(pair<string, string>(key, info));
@@ -2153,8 +2199,8 @@ void Buffer::fillWithBibKeys(vector<pair<string, string> > & keys) const
 
 bool Buffer::isDepClean(string const & name) const
 {
-       DepClean::const_iterator it = dep_clean_.find(name);
-       if (it == dep_clean_.end())
+       DepClean::const_iterator it = pimpl_->dep_clean.find(name);
+       if (it == pimpl_->dep_clean.end())
                return true;
        return it->second;
 }
@@ -2162,28 +2208,23 @@ bool Buffer::isDepClean(string const & name) const
 
 void Buffer::markDepClean(string const & name)
 {
-       dep_clean_[name] = true;
+       pimpl_->dep_clean[name] = true;
 }
 
 
 bool Buffer::dispatch(string const & command, bool * result)
 {
-       // Split command string into command and argument
-       string cmd;
-       string line = ltrim(command);
-       string const arg = trim(split(line, cmd, ' '));
-
-       return dispatch(lyxaction.LookupFunc(cmd), arg, result);
+       return dispatch(lyxaction.lookupFunc(command), result);
 }
 
 
-bool Buffer::dispatch(int action, string const & argument, bool * result)
+bool Buffer::dispatch(FuncRequest const & func, bool * result)
 {
        bool dispatched = true;
 
-       switch (action) {
+       switch (func.action) {
                case LFUN_EXPORT: {
-                       bool const tmp = Exporter::Export(this, argument, false);
+                       bool const tmp = Exporter::Export(this, func.argument, false);
                        if (result)
                                *result = tmp;
                        break;
@@ -2196,22 +2237,6 @@ bool Buffer::dispatch(int action, string const & argument, bool * result)
 }
 
 
-void Buffer::resizeInsets(BufferView * bv)
-{
-       /// then remove all LyXText in text-insets
-       for_each(paragraphs.begin(), paragraphs.end(),
-                boost::bind(&Paragraph::resizeInsetsLyXText, _1, bv));
-}
-
-
-void Buffer::redraw()
-{
-#warning repaint needed here, or do you mean update() ?
-       users->repaint();
-       users->fitCursor();
-}
-
-
 void Buffer::changeLanguage(Language const * from, Language const * to)
 {
        lyxerr << "Changing Language!" << endl;
@@ -2221,13 +2246,13 @@ void Buffer::changeLanguage(Language const * from, Language const * to)
 
        ParIterator end = par_iterator_end();
        for (ParIterator it = par_iterator_begin(); it != end; ++it)
-               (*it)->changeLanguage(params, from, to);
+               it->changeLanguage(params(), from, to);
 }
 
 
 void Buffer::updateDocLang(Language const * nlang)
 {
-       messages_.reset(new Messages(nlang->code()));
+       pimpl_->messages.reset(new Messages(nlang->code()));
 }
 
 
@@ -2235,7 +2260,7 @@ bool Buffer::isMultiLingual()
 {
        ParIterator end = par_iterator_end();
        for (ParIterator it = par_iterator_begin(); it != end; ++it)
-               if ((*it)->isMultiLingual(params))
+               if (it->isMultiLingual(params()))
                        return true;
 
        return false;
@@ -2253,14 +2278,14 @@ void Buffer::inset_iterator::setParagraph()
 }
 
 
-Inset * Buffer::getInsetFromID(int id_arg) const
+InsetOld * Buffer::getInsetFromID(int id_arg) const
 {
        for (inset_iterator it = inset_const_iterator_begin();
                 it != inset_const_iterator_end(); ++it)
        {
                if (it->id() == id_arg)
                        return &(*it);
-               Inset * in = it->getInsetFromID(id_arg);
+               InsetOld * in = it->getInsetFromID(id_arg);
                if (in)
                        return in;
        }
@@ -2268,77 +2293,82 @@ Inset * Buffer::getInsetFromID(int id_arg) const
 }
 
 
-ParagraphList::iterator Buffer::getParFromID(int id) const
+ParIterator Buffer::getParFromID(int id) const
 {
 #warning FIXME: const correctness! (Andre)
-       ParIterator it(const_cast<Buffer*>(this)->par_iterator_begin());
-       ParIterator end(const_cast<Buffer*>(this)->par_iterator_end());
+       ParIterator it = const_cast<Buffer*>(this)->par_iterator_begin();
+       ParIterator end = const_cast<Buffer*>(this)->par_iterator_end();
 
 #warning FIXME, perhaps this func should return a ParIterator? (Lgb)
        if (id < 0) {
                // John says this is called with id == -1 from undo
                lyxerr << "getParFromID(), id: " << id << endl;
-               return 0;
+               return end;
        }
 
-       for (; it != end; ++it) {
-               // go on then, show me how to remove
-               // the cast
-               if ((*it)->id() == id) {
-                       return *it;
-               }
-       }
+       for (; it != end; ++it)
+               if (it->id() == id)
+                       return it;
 
-       return 0;
+       return end;
 }
 
 
-ParIterator Buffer::par_iterator_begin()
+bool Buffer::hasParWithID(int id) const
 {
-       return ParIterator(&*(paragraphs.begin()));
-}
+       ParConstIterator it = par_iterator_begin();
+       ParConstIterator end = par_iterator_end();
+
+       if (id < 0) {
+               // John says this is called with id == -1 from undo
+               lyxerr << "hasParWithID(), id: " << id << endl;
+               return 0;
+       }
 
+       for (; it != end; ++it)
+               if (it->id() == id)
+                       return true;
 
-ParIterator Buffer::par_iterator_end()
-{
-       return ParIterator();
+       return false;
 }
 
-ParConstIterator Buffer::par_iterator_begin() const
+
+ParIterator Buffer::par_iterator_begin()
 {
-       return ParConstIterator(&*(paragraphs.begin()));
+       return ParIterator(paragraphs().begin(), paragraphs());
 }
 
 
-ParConstIterator Buffer::par_iterator_end() const
+ParIterator Buffer::par_iterator_end()
 {
-       return ParConstIterator();
+       return ParIterator(paragraphs().end(), paragraphs());
 }
 
 
-
-void Buffer::addUser(BufferView * u)
+ParConstIterator Buffer::par_iterator_begin() const
 {
-       users = u;
+       ParagraphList const & pars = paragraphs();
+       return ParConstIterator(const_cast<ParagraphList&>(pars).begin(), pars);
 }
 
 
-void Buffer::delUser(BufferView *)
+ParConstIterator Buffer::par_iterator_end() const
 {
-       users = 0;
+       ParagraphList const & pars = paragraphs();
+       return ParConstIterator(const_cast<ParagraphList&>(pars).end(), pars);
 }
 
 
 Language const * Buffer::getLanguage() const
 {
-       return params.language;
+       return params().language;
 }
 
 
 string const Buffer::B_(string const & l10n) const
 {
-       if (messages_.get()) {
-               return messages_->get(l10n);
+       if (pimpl_->messages.get()) {
+               return pimpl_->messages->get(l10n);
        }
 
        return _(l10n);
@@ -2347,56 +2377,56 @@ string const Buffer::B_(string const & l10n) const
 
 bool Buffer::isClean() const
 {
-       return lyx_clean;
+       return pimpl_->lyx_clean;
 }
 
 
 bool Buffer::isBakClean() const
 {
-       return bak_clean;
+       return pimpl_->bak_clean;
 }
 
 
 void Buffer::markClean() const
 {
-       if (!lyx_clean) {
-               lyx_clean = true;
+       if (!pimpl_->lyx_clean) {
+               pimpl_->lyx_clean = true;
                updateTitles();
        }
        // if the .lyx file has been saved, we don't need an
        // autosave
-       bak_clean = true;
+       pimpl_->bak_clean = true;
 }
 
 
 void Buffer::markBakClean()
 {
-       bak_clean = true;
+       pimpl_->bak_clean = true;
 }
 
 
 void Buffer::setUnnamed(bool flag)
 {
-       unnamed = flag;
+       pimpl_->unnamed = flag;
 }
 
 
 bool Buffer::isUnnamed()
 {
-       return unnamed;
+       return pimpl_->unnamed;
 }
 
 
 void Buffer::markDirty()
 {
-       if (lyx_clean) {
-               lyx_clean = false;
+       if (pimpl_->lyx_clean) {
+               pimpl_->lyx_clean = false;
                updateTitles();
        }
-       bak_clean = false;
+       pimpl_->bak_clean = false;
 
-       DepClean::iterator it = dep_clean_.begin();
-       DepClean::const_iterator const end = dep_clean_.end();
+       DepClean::iterator it = pimpl_->dep_clean.begin();
+       DepClean::const_iterator const end = pimpl_->dep_clean.end();
 
        for (; it != end; ++it) {
                it->second = false;
@@ -2406,36 +2436,30 @@ void Buffer::markDirty()
 
 string const & Buffer::fileName() const
 {
-       return filename_;
+       return pimpl_->filename;
 }
 
 
 string const & Buffer::filePath() const
 {
-       return filepath_;
+       return pimpl_->filepath;
 }
 
 
 bool Buffer::isReadonly() const
 {
-       return read_only;
-}
-
-
-BufferView * Buffer::getUser() const
-{
-       return users;
+       return pimpl_->read_only;
 }
 
 
 void Buffer::setParentName(string const & name)
 {
-       params.parentname = name;
+       params().parentname = name;
 }
 
 
 Buffer::inset_iterator::inset_iterator()
-       : pit(0), pend(0)
+       : pit(), pend()
 {}
 
 
@@ -2446,6 +2470,32 @@ Buffer::inset_iterator::inset_iterator(base_type p, base_type e)
 }
 
 
+Buffer::inset_iterator Buffer::inset_iterator_begin()
+{
+       return inset_iterator(paragraphs().begin(), paragraphs().end());
+}
+
+
+Buffer::inset_iterator Buffer::inset_iterator_end()
+{
+       return inset_iterator(paragraphs().end(), paragraphs().end());
+}
+
+
+Buffer::inset_iterator Buffer::inset_const_iterator_begin() const
+{
+       ParagraphList & pars = const_cast<ParagraphList&>(paragraphs());
+       return inset_iterator(pars.begin(), pars.end());
+}
+
+
+Buffer::inset_iterator Buffer::inset_const_iterator_end() const
+{
+       ParagraphList & pars = const_cast<ParagraphList&>(paragraphs());
+       return inset_iterator(pars.end(), pars.end());
+}
+
+
 Buffer::inset_iterator & Buffer::inset_iterator::operator++()
 {
        if (pit != pend) {
@@ -2469,25 +2519,25 @@ Buffer::inset_iterator Buffer::inset_iterator::operator++(int)
 
 Buffer::inset_iterator::reference Buffer::inset_iterator::operator*()
 {
-       return *it.getInset();
+       return *it->inset;
 }
 
 
 Buffer::inset_iterator::pointer Buffer::inset_iterator::operator->()
 {
-       return it.getInset();
+       return it->inset;
 }
 
 
-Paragraph * Buffer::inset_iterator::getPar()
+ParagraphList::iterator Buffer::inset_iterator::getPar() const
 {
-       return &(*pit);
+       return pit;
 }
 
 
 lyx::pos_type Buffer::inset_iterator::getPos() const
 {
-       return it.getPos();
+       return it->pos;
 }