]> git.lyx.org Git - features.git/commitdiff
architectural changes to tex2lyx
authorJean-Marc Lasgouttes <lasgouttes@lyx.org>
Mon, 4 Aug 2003 10:26:10 +0000 (10:26 +0000)
committerJean-Marc Lasgouttes <lasgouttes@lyx.org>
Mon, 4 Aug 2003 10:26:10 +0000 (10:26 +0000)
git-svn-id: svn://svn.lyx.org/lyx/lyx-devel/trunk@7494 a592a061-630c-0410-9148-cb99ea01b6c8

src/tex2lyx/ChangeLog
src/tex2lyx/Makefile.am
src/tex2lyx/context.C [new file with mode: 0644]
src/tex2lyx/context.h [new file with mode: 0644]
src/tex2lyx/table.C
src/tex2lyx/test-structure.tex [new file with mode: 0644]
src/tex2lyx/tex2lyx.C
src/tex2lyx/tex2lyx.h
src/tex2lyx/text.C

index 54d77c7ac533b743e94d1248b0124a3ccf1d8294..0775b5c69598890e4dd22e0d03f4e4cb5c7347c4 100644 (file)
@@ -1,3 +1,26 @@
+2003-08-03  Jean-Marc Lasgouttes  <lasgouttes@lyx.org>
+
+       * text.C: update to use Context struct, and more notably:
+       (cap, check_layout, check_end_layout): remove
+       (parse_text_snippet): new thin wrapper around parse_text, used for
+       things like \textrm{...}
+       (parse_environment): remove existing depth handling code, which is
+       handled transparently by the Context struct; make unknown
+       environments work (again?) through ERT
+        
+       * test-structure.tex: new test file, used to try out various
+       layouts combinations
+
+       * tex2lyx.C:
+       * tex2lyx.h:
+       * table.C: update to use Context struct
+       
+       * context.[Ch]: new helper struct which is passed to parse_*
+       functions and handles *_layout and *_deeper tags output
+
+       * Makefile.am (EXTRA_DIST): new file test-structure.tex
+       (tex2lyx_SOURCES): add context.[Ch]
+
 2003-07-30  Angus Leeming  <leeming@lyx.org>
 
        * Makefile.am: Hide the fact that we re-generate those symbolic links
index f773de61868c8639ebee25f8cde8765f881fa443..2a2e1adcebebb2cd0015e804d6540244bf41514a 100644 (file)
@@ -1,6 +1,7 @@
 include $(top_srcdir)/config/common.am
 
 INCLUDES = -I$(srcdir)/../ $(BOOST_INCLUDES)
+EXTRA_DIST = test-structure.tex
 
 #noinst_LTLIBRARIES = libtexparser.la
 #
@@ -27,6 +28,8 @@ linked_files = \
 tex2lyx_SOURCES = \
        $(linked_files) \
        Spacing.h \
+       context.C \
+       context.h \
        gettext.C \
        gettext.h \
        lyxfont.C \
diff --git a/src/tex2lyx/context.C b/src/tex2lyx/context.C
new file mode 100644 (file)
index 0000000..93431ed
--- /dev/null
@@ -0,0 +1,79 @@
+/** A small helper function
+    \author Jean-Marc Lasgouttes (2003)
+ */
+
+#include <iostream>
+
+#include "context.h"
+
+using std::ostream;
+using std::endl;
+
+Context::Context(bool need_layout_,
+                LyXTextClass const & textclass_,
+                LyXLayout_ptr layout_, LyXLayout_ptr parent_layout_)
+       : need_layout(need_layout_),
+         need_end_layout(false), need_end_deeper(false),
+         textclass(textclass_),
+         layout(layout_), parent_layout(parent_layout_)
+{
+       if (!layout.get())
+               layout = textclass.defaultLayout();
+       if (!parent_layout.get())
+               parent_layout = textclass.defaultLayout();
+}
+
+
+void Context::check_end_layout(ostream & os) 
+{
+       if (need_end_layout) {
+               os << "\n\\end_layout\n";
+               need_end_layout = false;
+       }
+       if (need_end_deeper) {
+               os << "\n\\end_deeper\n";
+               need_end_deeper = false;
+       }
+}
+
+
+void Context::check_layout(ostream & os)
+{
+       if (need_layout) {
+               if (parent_layout->isEnvironment()) {
+                       if (need_end_deeper) {
+                               // no need to have \end_deeper \begin_deeper
+// FIXME: This does not work because \par already calls check_end_layout
+                               need_end_deeper = false;
+                               check_end_layout(os);
+                       } else {
+                               check_end_layout(os);
+                               os << "\n\\begin_deeper\n";
+                               need_end_deeper = true;
+                       }
+               } else 
+                       check_end_layout(os);
+               
+               os << "\n\\begin_layout " << layout->name() << "\n\n";
+               need_end_layout = true;
+               need_layout=false;
+               if (!extra_stuff.empty()) {
+                       os << extra_stuff;
+                       extra_stuff.erase();
+               }
+       }
+}
+
+
+void Context::dump(ostream & os, string const & desc) const
+{
+       os << desc <<" [";
+       if (need_layout)
+               os << "need_layout ";
+       if (need_end_layout)
+               os << "need_end_layout ";
+       if (!extra_stuff.empty())
+               os << "extrastuff=[" << extra_stuff << "] ";
+       os << "layout=" << layout->name();
+       os << " parent_layout=" << parent_layout->name() << "]" << endl;
+}
diff --git a/src/tex2lyx/context.h b/src/tex2lyx/context.h
new file mode 100644 (file)
index 0000000..2b5faa8
--- /dev/null
@@ -0,0 +1,43 @@
+// -*- C++ -*-
+#ifndef CONTEXT_H
+#define CONTEXT_H
+
+#include "lyxtextclass.h"
+
+// A helper struct
+struct Context {
+       Context(bool need_layout_,
+               LyXTextClass const & textclass_,
+               LyXLayout_ptr layout_ = LyXLayout_ptr(),
+               LyXLayout_ptr parent_layout_= LyXLayout_ptr());
+
+       // Output a \begin_layout is requested
+       void check_layout(std::ostream & os);
+
+       // Output a \end_layout if needed
+       void check_end_layout(std::ostream & os);
+
+       // dump content on standard error (for debugging purpose)
+       void dump(std::ostream &, std::string const & desc = "context") const;
+
+       // Do we need to output some \begin_layout command before the
+       // next characters?
+       bool need_layout;
+       // Do we need to output some \end_layout command
+       bool need_end_layout;
+       // We may need to add something after this \begin_layout command
+       std::string extra_stuff;
+       // If there has been an \begin_deeper, we'll need a matching
+       // \end_deeper
+       bool need_end_deeper;
+
+       // The textclass of the document. Could actually be a global variable
+       LyXTextClass const & textclass;
+       // The layout of the current paragraph
+       LyXLayout_ptr layout;
+       // The layout of the outer paragraph (for environment layouts)
+       LyXLayout_ptr parent_layout;
+};
+       
+
+#endif
index da29b6b3eabda19e605891cbb5e6a6241efb0d38..ac1b44eddff8ae6a13a0e0cf3238aa7bbc135f9e 100644 (file)
@@ -26,8 +26,6 @@ using std::map;
 
 #include "mathed/math_gridinfo.h"
 
-extern bool need_layout;
-
 // filled in preamble.C
 std::map<char, int> special_columns;
 
@@ -284,7 +282,7 @@ void handle_hline_below(RowInfo & ri, vector<CellInfo> & ci)
 
 
 void handle_tabular(Parser & p, ostream & os,
-                   LyXTextClass const & textclass)
+                   Context & context)
 {
        string posopts = p.getOpt();
        if (posopts.size())
@@ -400,7 +398,7 @@ void handle_tabular(Parser & p, ostream & os,
                                cellinfo[row][col].multi     = 1;
                                cellinfo[row][col].align     = t.front().align;
                                ostringstream os;
-                               parse_text_in_inset(p, os, FLAG_ITEM, false, textclass);
+                               parse_text_in_inset(p, os, FLAG_ITEM, false, context);
                                cellinfo[row][col].content   = os.str();
                                cellinfo[row][col].leftline  |= t.front().leftline;
                                cellinfo[row][col].rightline |= t.front().rightline;
@@ -422,7 +420,7 @@ void handle_tabular(Parser & p, ostream & os,
                                cellinfo[row][col].rightline = colinfo[col].rightline;
                                cellinfo[row][col].align = colinfo[col].align;
                                ostringstream os;
-                               parse_text_in_inset(p, os, FLAG_ITEM, false, textclass);
+                               parse_text_in_inset(p, os, FLAG_CELL, false, context);
                                cellinfo[row][col].content   = os.str();
                        }
                }
diff --git a/src/tex2lyx/test-structure.tex b/src/tex2lyx/test-structure.tex
new file mode 100644 (file)
index 0000000..5d6e0fc
--- /dev/null
@@ -0,0 +1,87 @@
+\documentclass{article}
+
+\begin{document}
+
+This document contains all sorts of layouts we are supposed to
+support, along with weird nestings.
+
+
+A normal paragraph
+
+Another one 
+\begin{equation} 
+x = \sin y 
+\end{equation} 
+with maths inside
+
+\begin{quote}
+An environment...
+
+... with two paragraphs
+\end{quote}
+
+\begin{foo}
+an unknown environment
+\end{foo}
+
+
+\section{A section}
+
+\section[Hello!]{A section with optional argument}
+
+\begin{quote}
+An environment
+\end{quote}
+
+\section*{A starred section}
+
+\begin{figure}
+\caption{A figure}
+\end{figure}
+
+A paragraph\footnote{hello} with a footnote and another
+one\footnote{hello 
+
+there} with several paragraphs
+
+some ERT \vspace{1cm} aa
+
+and another paragraph
+
+\begin{center}
+Some centered stuff (does not work)
+\end{center}
+
+\begin{quotation}
+An environment
+
+\section*{with a command inside it}
+\end{quotation}
+
+\begin{quotation}
+An environment
+
+\begin{quotation}
+and the one inside it
+
+actually with several paragraphs
+\end{quotation}
+
+\end{quotation}
+
+We can also nest enumerations (does not work quite yet)
+
+\begin{enumerate}
+\item Item1
+\begin{enumerate}
+\item Item1.a
+\item Item1.b
+\end{enumerate}
+\begin{itemize}
+\item Item1.*
+\item Item1.*
+\end{itemize}
+\item Item2
+\end{enumerate}
+
+\end{document}
index ed941fc739c562be580e2b3a64dd007a1ae74a5e..a2a60e2370fdbdb2a89415f69d13a0d7d595bb98 100644 (file)
@@ -5,6 +5,7 @@
 // {[(
 
 #include "tex2lyx.h"
+#include "context.h"
 
 #include "debug.h"
 #include "lyx_main.h"
@@ -130,8 +131,9 @@ int main(int argc, char * argv[])
        stringstream ss;
        LyXTextClass textclass = parse_preamble(p, ss);
        active_environments.push_back("document");
-       parse_text(p, ss, FLAG_END, true, textclass);
-       check_end_layout(ss);
+       Context context(true, textclass);
+       parse_text(p, ss, FLAG_END, true, context);
+       context.check_end_layout(ss);
        ss << "\n\\end_document\n";
 
        ss.seekg(0);
index d2b296d4719f373485d05d7e4b6101927433b372..74b21e290782aa9b2f64a2c98a0408545914b724 100644 (file)
@@ -1,3 +1,4 @@
+// -*- C++ -*-
 #ifndef TEX2LYX_H
 #define TEX2LYX_H
 
@@ -8,31 +9,32 @@
 #include <string>
 #include <vector>
 
-class LyXTextClass;
+class Context;
 
+/// in preamble.C
 LyXTextClass const parse_preamble(Parser & p, std::ostream & os);
 
+
+/// in text.C
 void parse_text(Parser & p, std::ostream & os, unsigned flags, bool outer,
-               LyXTextClass const & textclass,
-               LyXLayout_ptr layout_ptr = LyXLayout_ptr());
+               Context & context);
+
+//std::string parse_text(Parser & p, unsigned flags, const bool outer,
+//                    Context & context);
 
 void parse_text_in_inset(Parser & p, std::ostream & os, unsigned flags, 
-                        bool outer, LyXTextClass const & textclass, 
-                        LyXLayout_ptr layout = LyXLayout_ptr());
+                        bool outer, Context & context);
 
-void parse_table(Parser & p, std::ostream & os, unsigned flags);
 
+/// in math.C
 void parse_math(Parser & p, std::ostream & os, unsigned flags, mode_type mode);
 
-void handle_tabular(Parser & p, std::ostream & os,
-                   LyXTextClass const & textclass);
 
-// Helper
-std::string parse_text(Parser & p, unsigned flags, const bool outer,
-                      LyXTextClass const & textclass, 
-                      LyXLayout_ptr layout_ptr = LyXLayout_ptr());
+/// in table.C
+void handle_tabular(Parser & p, std::ostream & os, Context & context);
+
 
-void check_end_layout(std::ostream & os);
+/// in tex2lyx.C
 void handle_comment(Parser & p);
 std::string const trim(std::string const & a, char const * p = " \t\n\r");
 
index 06da035ca57b2cb14f71522727e0d2ddb0d23900..28e53c184c3134043f0d4dd17686343299748e88 100644 (file)
@@ -7,8 +7,8 @@
 #include <config.h>
 
 #include "tex2lyx.h"
+#include "context.h"
 #include "FloatList.h"
-#include "lyxtextclass.h"
 #include "support/lstrings.h"
 #include "support/tostr.h"
 
@@ -28,19 +28,34 @@ using std::vector;
 using lyx::support::rtrim;
 using lyx::support::suffixIs;
 
-// Do we need to output some \begin_layout command before the next characters?
-bool need_layout = true;
-// We may need to add something after this \begin_layout command
-string extra_stuff;
-// Do we need to output some \end_layout command 
-bool need_end_layout = false;
 
-void check_end_layout(ostream & os) 
+// thin wrapper around parse_text using a string
+string parse_text(Parser & p, unsigned flags, const bool outer,
+                 Context & context)
 {
-       if (need_end_layout) {
-               os << "\n\\end_layout\n";
-               need_end_layout = false;
-       }
+       ostringstream os;
+       parse_text(p, os, flags, outer, context);
+       return os.str();
+}
+
+// parses a subdocument, usually useful in insets (whence the name)
+void parse_text_in_inset(Parser & p, ostream & os, unsigned flags, bool outer,
+               Context & context)
+{
+       Context newcontext(true, context.textclass);
+       parse_text(p, os, flags, outer, newcontext);
+       newcontext.check_end_layout(os);
+}
+
+
+// parses a paragraph snippet, useful for example for \emph{...}
+void parse_text_snippet(Parser & p, ostream & os, unsigned flags, bool outer,
+               Context & context)
+{
+       Context newcontext(false, context.textclass);
+       parse_text(p, os, flags, outer, newcontext);
+       // should not be needed
+       newcontext.check_end_layout(os);
 }
 
 
@@ -63,14 +78,6 @@ char const * known_sizes[] = { "tiny", "scriptsize", "footnotesize",
 char const * known_coded_sizes[] = { "tiny", "scriptsize", "footnotesize",
 "small", "normal", "large", "larger", "largest",  "huge", "giant", 0};
 
-string cap(string s)
-{
-       if (s.size())
-               s[0] = toupper(s[0]);
-       return s;
-}
-
-
 // splits "x=z, y=b" into a map
 map<string, string> split_map(string const & s)
 {
@@ -87,21 +94,6 @@ map<string, string> split_map(string const & s)
 }
 
 
-void check_layout(ostream & os, LyXLayout_ptr layout)
-{
-       if (need_layout) {
-               check_end_layout(os);
-               os << "\n\\begin_layout " << layout->name() << "\n\n";
-               need_end_layout = true;
-               need_layout=false;
-               if (!extra_stuff.empty()) {
-                       os << extra_stuff;
-                       extra_stuff.erase();
-               }
-       }
-}
-
-
 void begin_inset(ostream & os, string const & name)
 {
        os << "\n\\begin_inset " << name;
@@ -127,18 +119,19 @@ void skip_braces(Parser & p)
 }
 
 
-void handle_ert(ostream & os, string const & s)
+void handle_ert(ostream & os, string const & s, Context const & context)
 {
+       Context newcontext(true, context.textclass);
        begin_inset(os, "ERT");
-       os << "\nstatus Collapsed\n\n\\begin_layout Standard\n\n";
+       os << "\nstatus Collapsed\n";
+       newcontext.check_layout(os);
        for (string::const_iterator it = s.begin(), et = s.end(); it != et; ++it) {
                if (*it == '\\')
                        os << "\n\\backslash \n";
                else
                        os << *it;
        }
-       need_end_layout = true;
-       check_end_layout(os);
+       newcontext.check_end_layout(os);
        end_inset(os);
 }
 
@@ -163,73 +156,75 @@ LyXLayout_ptr findLayout(LyXTextClass const & textclass,
 }
 
 
-void output_command_layout(ostream & os, LyXLayout_ptr const & layout,
-                 Parser & p, bool outer, LyXTextClass const & textclass)
+void output_command_layout(ostream & os, Parser & p, bool outer,
+                          Context & parent_context,
+                          LyXLayout_ptr newlayout)
 {
-       need_layout = true;
-       check_layout(os, layout);
-       if (layout->optionalargs > 0) {
+//     parent_context.dump(os, "#parent_context before output_command_layout");
+       parent_context.check_end_layout(os);
+       Context context(true, parent_context.textclass, newlayout,
+                       parent_context.layout);
+       context.check_layout(os);
+       if (context.layout->optionalargs > 0) {
                string s; 
                if (p.next_token().character() == '[') {
                        p.get_token(); // eat '['
                        begin_inset(os, "OptArg\n");
                        os << "collapsed true\n";
-                       parse_text_in_inset(p, os, FLAG_BRACK_LAST, outer, textclass);
+                       parse_text_in_inset(p, os, FLAG_BRACK_LAST, outer, context);
                        end_inset(os);
                }
        }
-       parse_text(p, os, FLAG_ITEM, outer, textclass, layout);
-       need_layout = true;
+       parse_text_snippet(p, os, FLAG_ITEM, outer, context);
+       context.check_end_layout(os);   
+//     context.dump(os, "#context after output_command_layout");
+//     parent_context.dump(os, "#parent_context after output_command_layout");
 }
 
 
-} // anonymous namespace
-
-
 void parse_environment(Parser & p, ostream & os, bool outer,
-                      LyXTextClass const & textclass, LyXLayout_ptr layout)
+                      Context & parent_context)
 {
+//     parent_context.dump(os, "#parent_context before parse_environment");
        LyXLayout_ptr newlayout;
        string const name = p.getArg('{', '}');
        const bool is_starred = suffixIs(name, '*');
        string const unstarred_name = rtrim(name, "*");
        active_environments.push_back(name);
        if (is_math_env(name)) {
-               check_layout(os, layout);
+               parent_context.check_layout(os);
                begin_inset(os, "Formula ");
                os << "\\begin{" << name << "}";
                parse_math(p, os, FLAG_END, MATH_MODE);
                os << "\\end{" << name << "}";
                end_inset(os);
        } else if (name == "tabular") {
-               check_layout(os, layout);
+               parent_context.check_layout(os);
                begin_inset(os, "Tabular ");
-               handle_tabular(p, os, textclass);
+               handle_tabular(p, os, parent_context);
                end_inset(os);
-       } else if (textclass.floats().typeExist(unstarred_name)) {
-               check_layout(os, layout);
+       } else if (parent_context.textclass.floats().typeExist(unstarred_name)) {
+               parent_context.check_layout(os);
                begin_inset(os, "Float " + unstarred_name + "\n");
                if (p.next_token().asInput() == "[") {
                        os << "placement " << p.getArg('[', ']') << '\n';
                }
                os << "wide " << tostr(is_starred)
                   << "\ncollapsed false\n";
-               parse_text_in_inset(p, os, FLAG_END, outer, textclass);
+               parse_text_in_inset(p, os, FLAG_END, outer, parent_context);
                        end_inset(os);
        } else if (name == "center") {
-               parse_text(p, os, FLAG_END, outer, textclass);
+               parse_text(p, os, FLAG_END, outer, parent_context);
                // The single '=' is meant here.
-       } else if ((newlayout = findLayout(textclass, name)).get() &&
+       } else if ((newlayout = findLayout(parent_context.textclass, name)).get() &&
                   newlayout->isEnvironment()) {
-               size_t const n = active_environments.size();
-               string const s = active_environments[n - 2];
-               bool const deeper = s == "enumerate" || s == "itemize"
-                       || s == "lyxlist";
-               if (deeper)
-                       os << "\n\\begin_deeper";
-               switch (newlayout->latextype) {
+               Context context(true, parent_context.textclass, newlayout,
+                               parent_context.layout);
+               parent_context.check_end_layout(os);
+//             context.dump(os, "#context in parse_environment");
+               switch (context.layout->latextype) {
                case  LATEX_LIST_ENVIRONMENT:
-                       extra_stuff = "\\labelwidthstring "
+                       context.extra_stuff = "\\labelwidthstring "
                                + p.verbatim_item() + '\n';
                        break;
                case  LATEX_BIB_ENVIRONMENT:
@@ -238,24 +233,26 @@ void parse_environment(Parser & p, ostream & os, bool outer,
                default:
                        break;
                }
-               need_layout = true;
-               parse_text(p, os, FLAG_END, outer, textclass, newlayout);
-               check_end_layout(os);
-               if (deeper)
-                       os << "\n\\end_deeper\n";
-               need_layout = true;
+               //context.check_layout(os);
+               parse_text(p, os, FLAG_END, outer, context);
+//             context.dump(os, "#context after parse_environment");
+               context.check_end_layout(os);
        } else {
-               cerr << "why are we here?" << endl;
-               parse_text(p, os, FLAG_END, outer, textclass);
+               parent_context.check_layout(os);
+               handle_ert(os, "\\begin{" + name + "}", parent_context);
+               parse_text_snippet(p, os, FLAG_END, outer, parent_context);
+               handle_ert(os, "\\end{" + name + "}", parent_context);
        }
 }
 
+} // anonymous namespace
+
+
+
 
 void parse_text(Parser & p, ostream & os, unsigned flags, bool outer,
-               LyXTextClass const & textclass, LyXLayout_ptr layout)
+               Context & context)
 {
-       if (!layout.get())
-               layout = textclass.defaultLayout();
        LyXLayout_ptr newlayout;
        while (p.good()) {
                Token const & t = p.get_token();
@@ -288,7 +285,7 @@ void parse_text(Parser & p, ostream & os, unsigned flags, bool outer,
                //
                if (t.cat() == catMath) {
                        // we are inside some text mode thingy, so opening new math is allowed
-                       check_layout(os, layout);
+                       context.check_layout(os);
                        begin_inset(os, "Formula ");
                        Token const & n = p.get_token();
                        if (n.cat() == catMath && outer) {
@@ -316,7 +313,7 @@ void parse_text(Parser & p, ostream & os, unsigned flags, bool outer,
                // quote...)
                else if (t.asInput() == "`" 
                         && p.next_token().asInput() == "`") {
-                       check_layout(os, layout);
+                       context.check_layout(os);
                        begin_inset(os, "Quotes ");
                        os << "eld";
                        end_inset(os);
@@ -325,7 +322,7 @@ void parse_text(Parser & p, ostream & os, unsigned flags, bool outer,
                }       
                else if (t.asInput() == "'" 
                         && p.next_token().asInput() == "'") {
-                       check_layout(os, layout);
+                       context.check_layout(os);
                        begin_inset(os, "Quotes ");
                        os << "erd";
                        end_inset(os);
@@ -339,23 +336,25 @@ void parse_text(Parser & p, ostream & os, unsigned flags, bool outer,
                               t.cat() == catOther ||
                               t.cat() == catAlign ||
                               t.cat() == catParameter) {
-                       check_layout(os, layout);
+                       context.check_layout(os);
                        os << t.character();
                }
 
                else if (t.cat() == catNewline) {
                        if (p.next_token().cat() == catNewline) {
                                p.get_token();
-                               need_layout = true;
+                               context.need_layout = true;
+                               // this should be done by the parser already
+                               cerr << "what are we doing here?" << endl;
                        } else {
                                os << " "; // note the space
                        }
                }
 
                else if (t.cat() == catActive) {
-                       check_layout(os, layout);
+                       context.check_layout(os);
                        if (t.character() == '~') {
-                               if (layout->free_spacing)
+                               if (context.layout->free_spacing)
                                        os << ' ';
                                else 
                                        os << "\\InsetSpace ~\n";
@@ -366,29 +365,30 @@ void parse_text(Parser & p, ostream & os, unsigned flags, bool outer,
                else if (t.cat() == catBegin) {
 // FIXME??? 
                        // special handling of size changes
-                       check_layout(os, layout);
+                       context.check_layout(os);
                        bool const is_size = is_known(p.next_token().cs(), known_sizes);
-                       need_end_layout = false;
-                       string const s = parse_text(p, FLAG_BRACE_LAST, outer, textclass, layout);
-                       need_end_layout = true;
+                       Context newcontext(false, context.textclass);
+//                     need_end_layout = false;
+                       string const s = parse_text(p, FLAG_BRACE_LAST, outer, newcontext);
+//                     need_end_layout = true;
                        if (s.empty() && p.next_token().character() == '`')
                                ; // ignore it in  {}``
                        else if (is_size || s == "[" || s == "]" || s == "*")
                                os << s;
                        else {
-                               handle_ert(os, "{");
+                               handle_ert(os, "{", context);
                                os << s;
-                               handle_ert(os, "}");
+                               handle_ert(os, "}", context);
                        }
                }
 
                else if (t.cat() == catEnd) {
                        if (flags & FLAG_BRACE_LAST) {
-                               check_end_layout(os);
+                               context.check_end_layout(os);
                                return;
                        }
                        cerr << "stray '}' in text\n";
-                       handle_ert(os, "}");
+                       handle_ert(os, "}", context);
                }
 
                else if (t.cat() == catComment)
@@ -399,7 +399,7 @@ void parse_text(Parser & p, ostream & os, unsigned flags, bool outer,
                //
 
                else if (t.cs() == "(") {
-                       check_layout(os, layout);
+                       context.check_layout(os);
                        begin_inset(os, "Formula");
                        os << " \\(";
                        parse_math(p, os, FLAG_SIMPLE2, MATH_MODE);
@@ -408,7 +408,7 @@ void parse_text(Parser & p, ostream & os, unsigned flags, bool outer,
                }
 
                else if (t.cs() == "[") {
-                       check_layout(os, layout);
+                       context.check_layout(os);
                        begin_inset(os, "Formula");
                        os << " \\[";
                        parse_math(p, os, FLAG_EQUATION, MATH_MODE);
@@ -417,7 +417,7 @@ void parse_text(Parser & p, ostream & os, unsigned flags, bool outer,
                }
 
                else if (t.cs() == "begin")
-                       parse_environment(p, os, outer, textclass, layout);
+                       parse_environment(p, os, outer, context);
 
                else if (t.cs() == "end") {
                        if (flags & FLAG_END) {
@@ -427,6 +427,7 @@ void parse_text(Parser & p, ostream & os, unsigned flags, bool outer,
                                        cerr << "\\end{" + name + "} does not match \\begin{"
                                                + active_environment() + "}\n";
                                active_environments.pop_back();
+                               context.check_end_layout(os);
                                return;
                        }
                        p.error("found 'end' unexpectedly");
@@ -438,10 +439,11 @@ void parse_text(Parser & p, ostream & os, unsigned flags, bool outer,
                        string s; 
                        if (p.next_token().character() == '[') {
                                p.get_token(); // eat '['
-                               s = parse_text(p, FLAG_BRACK_LAST, outer, textclass, layout);
+                               Context newcontext(false, context.textclass);
+                               s = parse_text(p, FLAG_BRACK_LAST, outer, newcontext);
                        }
-                       need_layout = true;
-                       check_layout(os, layout);
+                       context.need_layout = true;
+                       context.check_layout(os);
                        if (s.size())
                                os << s << ' ';
                }
@@ -450,12 +452,13 @@ void parse_text(Parser & p, ostream & os, unsigned flags, bool outer,
                        string name = p.get_token().cs();
                        while (p.next_token().cat() != catBegin)
                                name += p.get_token().asString();
-                       handle_ert(os, "\\def\\" + name + '{' + p.verbatim_item() + '}');
+                       handle_ert(os, "\\def\\" + name + '{' + p.verbatim_item() + '}', context);
                }
 
                else if (t.cs() == "par") {
                        p.skip_spaces();
-                       need_layout = true;
+                       context.check_end_layout(os);
+                       context.need_layout = true;
 //                     if (p.next_token().cs() != "\\begin")
 //                             handle_par(os);
                        //cerr << "next token: '" << p.next_token().cs() << "'\n";
@@ -464,24 +467,24 @@ void parse_text(Parser & p, ostream & os, unsigned flags, bool outer,
                // Must attempt to parse "Section*" before "Section".
                else if ((p.next_token().asInput() == "*") &&
                         // The single '=' is meant here.
-                        (newlayout = findLayout(textclass,
+                        (newlayout = findLayout(context.textclass,
                                                 t.cs() + '*')).get() &&
                         newlayout->isCommand()) {
                        p.get_token();
-                       output_command_layout(os, newlayout, p, outer, textclass);
+                       output_command_layout(os, p, outer, context, newlayout);
                }
 
                // The single '=' is meant here.
-               else if ((newlayout = findLayout(textclass, t.cs())).get() &&
+               else if ((newlayout = findLayout(context.textclass, t.cs())).get() &&
                         newlayout->isCommand()) {
-                       output_command_layout(os, newlayout, p, outer, textclass);
+                       output_command_layout(os, p, outer, context, newlayout);
                }
 
                else if (t.cs() == "includegraphics") {
                        map<string, string> opts = split_map(p.getArg('[', ']'));
                        string name = p.verbatim_item();
                        
-                       check_layout(os, layout);
+                       context.check_layout(os);
                        begin_inset(os, "Graphics ");
                        os << "\n\tfilename " << name << '\n';
                        if (opts.find("width") != opts.end())
@@ -492,34 +495,34 @@ void parse_text(Parser & p, ostream & os, unsigned flags, bool outer,
                }
                
                else if (t.cs() == "footnote") {
-                       check_layout(os, layout);
+                       context.check_layout(os);
                        begin_inset(os, "Foot\n");
                        os << "collapsed true\n";
-                       parse_text_in_inset(p, os, FLAG_ITEM, false, textclass);
+                       parse_text_in_inset(p, os, FLAG_ITEM, false, context);
                        end_inset(os);
                }
 
-               else if (t.cs() == "ensuremath") {
-                       check_layout(os, layout);
-                       string s = parse_text(p, FLAG_ITEM, false, textclass);
-                       if (s == "±" || s == "³" || s == "²" || s == "µ")
-                               os << s;
-                       else
-                               handle_ert(os, "\\ensuremath{" + s + "}");
-               }
-
                else if (t.cs() == "marginpar") {
-                       check_layout(os, layout);
+                       context.check_layout(os);
                        begin_inset(os, "Marginal\n");
                        os << "collapsed true\n";
-                       need_layout = true;
-                       parse_text(p, os, FLAG_ITEM, false, textclass);
+                       parse_text_in_inset(p, os, FLAG_ITEM, false, context);
                        end_inset(os);
-                       need_end_layout = true;
+               }
+
+               else if (t.cs() == "ensuremath") {
+                       context.check_layout(os);
+                       Context newcontext(false, context.textclass);
+                       string s = parse_text(p, FLAG_ITEM, false, newcontext);
+                       if (s == "±" || s == "³" || s == "²" || s == "µ")
+                               os << s;
+                       else
+                               handle_ert(os, "\\ensuremath{" + s + "}",
+                                          context);
                }
 
                else if (t.cs() == "hfill") {
-                       check_layout(os, layout);
+                       context.check_layout(os);
                        os << "\n\\hfill\n";
                        skip_braces(p);
                }
@@ -528,7 +531,7 @@ void parse_text(Parser & p, ostream & os, unsigned flags, bool outer,
                        skip_braces(p); // swallow this
 
                else if (t.cs() == "tableofcontents") {
-                       check_layout(os, layout);
+                       context.check_layout(os);
                        begin_inset(os, "LatexCommand ");
                        os << '\\' << t.cs() << "{}\n";
                        end_inset(os);
@@ -537,70 +540,70 @@ void parse_text(Parser & p, ostream & os, unsigned flags, bool outer,
 
 
                else if (t.cs() == "textrm") {
-                       check_layout(os, layout);
+                       context.check_layout(os);
                        os << "\n\\family roman \n";
-                       parse_text(p, os, FLAG_ITEM, outer, textclass);
+                       parse_text_snippet(p, os, FLAG_ITEM, outer, context);
                        os << "\n\\family default \n";
                }
 
                else if (t.cs() == "textsf") {
-                       check_layout(os, layout);
+                       context.check_layout(os);
                        os << "\n\\family sans \n";
-                       parse_text(p, os, FLAG_ITEM, outer, textclass);
+                       parse_text_snippet(p, os, FLAG_ITEM, outer, context);
                        os << "\n\\family default \n";
                }
 
                else if (t.cs() == "texttt") {
-                       check_layout(os, layout);
+                       context.check_layout(os);
                        os << "\n\\family typewriter \n";
-                       parse_text(p, os, FLAG_ITEM, outer, textclass);
+                       parse_text_snippet(p, os, FLAG_ITEM, outer, context);
                        os << "\n\\family default \n";
                }
 
                else if (t.cs() == "textit") {
-                       check_layout(os, layout);
+                       context.check_layout(os);
                        os << "\n\\shape italic \n";
-                       parse_text(p, os, FLAG_ITEM, outer, textclass);
+                       parse_text_snippet(p, os, FLAG_ITEM, outer, context);
                        os << "\n\\shape default \n";
                }
 
                else if (t.cs() == "textsc") {
-                       check_layout(os, layout);
+                       context.check_layout(os);
                        os << "\n\\noun on \n";
-                       parse_text(p, os, FLAG_ITEM, outer, textclass);
+                       parse_text_snippet(p, os, FLAG_ITEM, outer, context);
                        os << "\n\\noun default \n";
                }
 
                else if (t.cs() == "textbf") {
-                       check_layout(os, layout);
+                       context.check_layout(os);
                        os << "\n\\series bold \n";
-                       parse_text(p, os, FLAG_ITEM, outer, textclass);
+                       parse_text_snippet(p, os, FLAG_ITEM, outer, context);
                        os << "\n\\series default \n";
                }
 
                else if (t.cs() == "underbar") {
-                       check_layout(os, layout);
+                       context.check_layout(os);
                        os << "\n\\bar under \n";
-                       parse_text(p, os, FLAG_ITEM, outer, textclass);
+                       parse_text_snippet(p, os, FLAG_ITEM, outer, context);
                        os << "\n\\bar default \n";
                }
 
                else if (t.cs() == "emph" || t.cs() == "noun") {
-                       check_layout(os, layout);
+                       context.check_layout(os);
                        os << "\n\\" << t.cs() << " on \n";
-                       parse_text(p, os, FLAG_ITEM, outer, textclass);
+                       parse_text_snippet(p, os, FLAG_ITEM, outer, context);
                        os << "\n\\" << t.cs() << " default \n";
                }
 
                else if (t.cs() == "bibitem") {
-                       check_layout(os, layout);
+                       context.check_layout(os);
                        os << "\\bibitem ";
                        os << p.getOpt();
                        os << '{' << p.verbatim_item() << '}' << "\n";
                }
 
                else if (is_known(t.cs(), known_latex_commands)) {
-                       check_layout(os, layout);
+                       context.check_layout(os);
                        begin_inset(os, "LatexCommand ");
                        os << '\\' << t.cs();
                        os << p.getOpt();
@@ -619,66 +622,66 @@ void parse_text(Parser & p, ostream & os, unsigned flags, bool outer,
 
                else if (is_known(t.cs(), known_sizes)) {
                        char const ** where = is_known(t.cs(), known_sizes);
-                       check_layout(os, layout);
+                       context.check_layout(os);
                        os << "\n\\size " << known_coded_sizes[where - known_sizes] << "\n";
                }
 
                else if (t.cs() == "LyX" || t.cs() == "TeX" 
                         || t.cs() == "LaTeX") {
-                       check_layout(os, layout);
+                       context.check_layout(os);
                        os << t.cs();
                        skip_braces(p); // eat {}
                }
 
                else if (t.cs() == "LaTeXe") {
-                       check_layout(os, layout);
+                       context.check_layout(os);
                        os << "LaTeX2e";
                        skip_braces(p); // eat {}
                }
 
                else if (t.cs() == "ldots") {
-                       check_layout(os, layout);
+                       context.check_layout(os);
                        skip_braces(p);
                        os << "\\SpecialChar \\ldots{}\n";
                }
 
                else if (t.cs() == "lyxarrow") {
-                       check_layout(os, layout);
+                       context.check_layout(os);
                        os << "\\SpecialChar \\menuseparator\n";
                        skip_braces(p);
                }
 
                else if (t.cs() == "ldots") {
-                       check_layout(os, layout);
+                       context.check_layout(os);
                        os << "\\SpecialChar \\ldots{}\n";
                        skip_braces(p);
                }
 
                else if (t.cs() == "@" && p.next_token().asInput() == ".") {
-                       check_layout(os, layout);
+                       context.check_layout(os);
                        os << "\\SpecialChar \\@.\n";
                        p.get_token();
                }
 
                else if (t.cs() == "-") {
-                       check_layout(os, layout);
+                       context.check_layout(os);
                        os << "\\SpecialChar \\-\n";
                }
 
                else if (t.cs() == "textasciitilde") {
-                       check_layout(os, layout);
+                       context.check_layout(os);
                        os << '~';
                        skip_braces(p);
                }
 
                else if (t.cs() == "textasciicircum") {
-                       check_layout(os, layout);
+                       context.check_layout(os);
                        os << '^';
                        skip_braces(p);
                }
 
                else if (t.cs() == "textbackslash") {
-                       check_layout(os, layout);
+                       context.check_layout(os);
                        os << "\n\\backslash \n";
                        skip_braces(p);
                }
@@ -686,12 +689,12 @@ void parse_text(Parser & p, ostream & os, unsigned flags, bool outer,
                else if (t.cs() == "_" || t.cs() == "&" || t.cs() == "#" 
                            || t.cs() == "$" || t.cs() == "{" || t.cs() == "}" 
                            || t.cs() == "%") {
-                       check_layout(os, layout);
+                       context.check_layout(os);
                        os << t.cs();
                }
 
                else if (t.cs() == "char") {
-                       check_layout(os, layout);
+                       context.check_layout(os);
                        if (p.next_token().character() == '`') {
                                p.get_token();
                                if (p.next_token().cs() == "\"") {
@@ -699,15 +702,15 @@ void parse_text(Parser & p, ostream & os, unsigned flags, bool outer,
                                        os << '"';
                                        skip_braces(p);
                                } else {
-                                       handle_ert(os, "\\char`");
+                                       handle_ert(os, "\\char`", context);
                                }
                        } else {
-                               handle_ert(os, "\\char");
+                               handle_ert(os, "\\char", context);
                        }
                }
 
                else if (t.cs() == "\"") {
-                       check_layout(os, layout);
+                       context.check_layout(os);
                        string const name = p.verbatim_item();
                             if (name == "a") os << 'ä';
                        else if (name == "o") os << 'ö';
@@ -715,43 +718,44 @@ void parse_text(Parser & p, ostream & os, unsigned flags, bool outer,
                        else if (name == "A") os << 'Ä';
                        else if (name == "O") os << 'Ö';
                        else if (name == "U") os << 'Ü';
-                       else handle_ert(os, "\"{" + name + "}");
+                       else handle_ert(os, "\"{" + name + "}", context);
                }
 
                else if (t.cs() == "=" || t.cs() == "H" || t.cs() == "c"
                      || t.cs() == "^" || t.cs() == "'" || t.cs() == "~") {
                        // we need the trim as the LyX parser chokes on such spaces
-                       check_layout(os, layout);
+                       context.check_layout(os);
                        os << "\n\\i \\" << t.cs() << "{"
-                          << trim(parse_text(p, FLAG_ITEM, outer, textclass), " ") << "}\n";
+                          << trim(parse_text(p, FLAG_ITEM, outer, context), " ") << "}\n";
                }
 
                else if (t.cs() == "ss") {
-                       check_layout(os, layout);
+                       context.check_layout(os);
                        os << "ß";
                }
 
                else if (t.cs() == "i" || t.cs() == "j") {
-                       check_layout(os, layout);
+                       context.check_layout(os);
                        os << "\\" << t.cs() << ' ';
                }
 
                else if (t.cs() == "\\") {
-                       check_layout(os, layout);
+                       context.check_layout(os);
                        os << "\n\\newline \n";
                }
        
                else if (t.cs() == "input") {
-                       check_layout(os, layout);
-                       handle_ert(os, "\\input{" + p.verbatim_item() + "}\n");
+                       context.check_layout(os);
+                       handle_ert(os, "\\input{" + p.verbatim_item() + "}\n",
+                                  context);
                }
                else if (t.cs() == "fancyhead") {
-                       check_layout(os, layout);
+                       context.check_layout(os);
                        ostringstream ss;
                        ss << "\\fancyhead";
                        ss << p.getOpt();
                        ss << '{' << p.verbatim_item() << "}\n";
-                       handle_ert(os, ss.str());
+                       handle_ert(os, ss.str(), context);
                }
 
                else {
@@ -766,10 +770,10 @@ void parse_text(Parser & p, ostream & os, unsigned flags, bool outer,
                                z = p.verbatim_item();
                        }
                        cerr << "found ERT: " << s << endl;
-                       handle_ert(os, s + ' ');
+                       handle_ert(os, s + ' ', context);
                        */
-                       check_layout(os, layout);
-                       handle_ert(os, t.asInput() + ' ');
+                       context.check_layout(os);
+                       handle_ert(os, t.asInput() + ' ', context);
                }
 
                if (flags & FLAG_LEAVE) {
@@ -780,22 +784,4 @@ void parse_text(Parser & p, ostream & os, unsigned flags, bool outer,
 }
 
 
-string parse_text(Parser & p, unsigned flags, const bool outer,
-                 LyXTextClass const & textclass,
-                 LyXLayout_ptr layout)
-{
-       ostringstream os;
-       parse_text(p, os, flags, outer, textclass, layout);
-       return os.str();
-}
-
-void parse_text_in_inset(Parser & p, ostream & os, unsigned flags, bool outer,
-               LyXTextClass const & textclass, LyXLayout_ptr layout)
-{
-               need_layout = true;
-               need_end_layout = false;
-               parse_text(p, os, flags, outer, textclass, layout);
-               check_end_layout(os);
-               need_end_layout = true;
-}
 // }])