I have modified the parser to not drop any spaces anymore. The result is
that the Userguide roundtrip works better. Apart from the preamble, a

diff -u Userguide.tex Userguide-new.tex

shows now almost only real problems. Another benefit is that it is possible
to add support for verbatim and similar environments. A few bugfixes and
enhancements are added, too. The drawback is that we have more calls of
Parser::skip_spaces() now, but some of them will go with the implementation
of Jean-Marcs suggestion to handle \command and
\begin{command}...\end{command} by the same code. Also some comments are
still dropped, but we issue a warning now.
See the Changelog and comments in the source for more details.

For whose who want to test: The attached Userguide.diff removes some
occurences of bug # 1428 from the Userguide.

Comments?

Georg
--- UserGuide.lyx	2003-07-30 13:42:44.000000000 +0200
+++ UserGuide-corrected.lyx	2003-11-01 22:16:51.000000000 +0100
@@ -986,11 +986,7 @@
 \emph on 
 Single click 
 \emph default 
-the
-\emph on 
- 
-\emph default 
-left mouse button to open or close any of these.
+the left mouse button to open or close any of these.
  Also check the appropriate section of this manual for more details.
 \end_deeper 
 \layout Enumerate
@@ -1003,11 +999,7 @@
 \emph on 
 Single click
 \emph default 
- the right mouse button
-\emph on 
- 
-\emph default 
-to open a dialog that will allow you to manipulate the table.
+ the right mouse button to open a dialog that will allow you to manipulate the table.
 \end_deeper 
 \layout Subsection
 
@@ -2115,7 +2107,7 @@
 
 PostScript® is a registered trademark of Adobe Systems Incorporated, and
  is the main page description language in the UN*X world.
- 
+
 \end_inset 
 
  format.
@@ -6324,7 +6316,7 @@
  the body of the item text.
  The body of the text has a larger left margin, which is equal to the default
  label width plus a little extra space.
- 
+
 \layout List
 \labelwidthstring MMMMMM
 
@@ -7720,7 +7712,7 @@
 \family sans 
 Section
 \family default 
- 
+
 \layout Itemize
 
 
@@ -7737,7 +7729,7 @@
 \family sans 
 Paragraph
 \family default 
- 
+
 \layout Itemize
 
 
@@ -8646,7 +8638,7 @@
 \labelwidthstring MMM
 
 #2-b Back to level #2.
- 
+
 \end_deeper 
 \layout List
 \labelwidthstring MMM
@@ -9163,7 +9155,7 @@
 Verse
 \family default 
  environment.
- 
+
 \layout Quotation
 
 We're now ending the 
@@ -9901,10 +9893,8 @@
 Caps
 \family default 
  
-\shape smallcaps 
-This is the Small caps font shape
-\shape default 
 \noun on 
+This is the Small caps font shape
 .
 \end_deeper 
 \layout List
@@ -10383,11 +10373,7 @@
 No\SpecialChar ~
 color
 \family default 
-, which
-\family sans 
- 
-\family default 
-is the standard 
+, which is the standard 
 \begin_inset Quotes eld
 \end_inset 
 
@@ -10577,7 +10563,7 @@
 \end_inset 
 
 .
- 
+
 \layout Enumerate
 
 Next, LaTeX uses the commands in the 
@@ -12954,7 +12940,7 @@
 \family default 
  manually.
  But this is annoying.
- 
+
 \end_inset 
 
  This way you have the full PostScript® and LaTeX power combined except
@@ -15509,8 +15495,6 @@
 \family default 
  example file to see how this works.
 
-\emph on 
- 
 \layout Standard
 
 The check box in the long table options can be used to specify specific
@@ -15787,7 +15771,7 @@
 
 \end_inset 
 
- 
+
 \layout Section
 
 Table of Contents and other Listings
@@ -17432,9 +17416,7 @@
 \begin_inset Formula $\alpha$
 \end_inset 
 
- by typing the following keys: First type
-\family typewriter 
- 
+ by typing the following keys: First type 
 \family sans 
 M-c\SpecialChar ~
 m
@@ -17471,7 +17453,7 @@
 \end_inset 
 
  was right there on the screen.
- 
+
 \layout Standard
 
 The 
@@ -19578,10 +19560,7 @@
 \layout Standard
 
 So in general there is no need to use the option described below, and we
- recommend not using it until the text is
-\emph on 
- 
-\emph default 
+ recommend not using it until the text is 
 finished, and until you have checked in the preview to see if you 
 \emph on 
 really 
@@ -19643,7 +19622,7 @@
 A good documentation should weight no more than 1
 \newline 
 kg.
- 
+
 \layout Standard
 
 Obviously, it would be a good thing to put a protected blank between 
@@ -24769,7 +24748,7 @@
 \begin_deeper 
 \layout Itemize
 
-math mode 
+math mode
 \layout Itemize
 
 tables
@@ -24900,7 +24879,7 @@
 \begin_deeper 
 \layout Itemize
 
-manual fine-tuning 
+manual fine-tuning
 \layout Itemize
 
 using LaTeX from within LyX
? tex2lyx-space.diff
? lib/lyx2lyx/green.lyx
? lib/lyx2lyx/lyx225to221.sh
? lib/lyx2lyx/lyx2lyx-g
? lib/lyx2lyx/lyxconvert_221-g.py
? lib/lyx2lyx/lyxconvert_222.py
? lib/lyx2lyx/lyxconvert_222to221.py
? lib/lyx2lyx/lyxconvert_223to222.py
? lib/lyx2lyx/lyxconvert_224to223.py
? lib/lyx2lyx/lyxconvert_225to224.py
? lib/lyx2lyx/t.fig
? lib/lyx2lyx/text-1.3.lyx
? lib/lyx2lyx/text-1.4.lyx
? lib/lyx2lyx/text-224.lyx
? lib/lyx2lyx/text.lyx
? lib/lyx2lyx/textm-1.4.lyx
? lib/lyx2lyx/textm-221.lyx
? lib/lyx2lyx/textm-222.lyx
? lib/lyx2lyx/textm-223.lyx
? lib/lyx2lyx/textm-224.lyx
? lib/lyx2lyx/xx.lyx
? src/forms.h
? src/tex2lyx-new
? src/tex2lyx-orig
? src/frontends/xforms/forms.h
? src/tex2lyx/UserGuide-1.4-orig.lyx
? src/tex2lyx/UserGuide-1.4-orig.tex
? src/tex2lyx/UserGuide-1.4-orig.toc
? src/tex2lyx/UserGuide-1.4-t2l-lyx.lyx
? src/tex2lyx/UserGuide-1.4-t2l-lyx.tex
? src/tex2lyx/UserGuide-1.4-t2l.lyx
? src/tex2lyx/UserGuide-1.4-t2l.tex
? src/tex2lyx/UserGuide-1.4-t2l.toc
? src/tex2lyx/UserGuide-corrected-1.4-t2l.aux
? src/tex2lyx/UserGuide-corrected-1.4-t2l.dvi
? src/tex2lyx/UserGuide-corrected-1.4-t2l.log
? src/tex2lyx/UserGuide-corrected-1.4-t2l.lyx
? src/tex2lyx/UserGuide-corrected-1.4-t2l.ps
? src/tex2lyx/UserGuide-corrected-1.4-t2l.tex
? src/tex2lyx/UserGuide-corrected-1.4-t2l.toc
? src/tex2lyx/UserGuide-corrected-1.4.aux
? src/tex2lyx/UserGuide-corrected-1.4.dvi
? src/tex2lyx/UserGuide-corrected-1.4.log
? src/tex2lyx/UserGuide-corrected-1.4.lyx
? src/tex2lyx/UserGuide-corrected-1.4.ps
? src/tex2lyx/UserGuide-corrected-1.4.tex
? src/tex2lyx/UserGuide-corrected-1.4.toc
? src/tex2lyx/UserGuide-corrected.lyx
? src/tex2lyx/UserGuide.diff
? src/tex2lyx/UserGuide.lyx
? src/tex2lyx/UserGuide.tex
? src/tex2lyx/convert.sh
? src/tex2lyx/escher-lsd.eps
? src/tex2lyx/lyx
? src/tex2lyx/mobius.eps
? src/tex2lyx/newfile1.lyx
? src/tex2lyx/platypus.eps
? src/tex2lyx/t.diff
Index: lib/symbols
===================================================================
RCS file: /cvs/lyx/lyx-devel/lib/symbols,v
retrieving revision 1.44
diff -u -r1.44 symbols
--- lib/symbols 2003/10/13 09:50:08     1.44
+++ lib/symbols 2003/11/03 09:31:29
@@ -120,6 +120,8 @@
 parbox            parbox      none
 protect           protect     none
 mbox              mbox        forcetext
+# this is not perfect, a real inset would be better
+intertext         mbox        forcetext
 newcommand        newcommand  none
 label             label       none
 left              left        none
Index: lib/reLyX/syntax.default
===================================================================
RCS file: /cvs/lyx/lyx-devel/lib/reLyX/syntax.default,v
retrieving revision 1.7
diff -u -r1.7 syntax.default
--- lib/reLyX/syntax.default    2003/02/11 13:32:13     1.7
+++ lib/reLyX/syntax.default    2003/11/03 09:31:34
@@ -661,6 +661,7 @@
 % the whole document will be copied in TeX mode!
 slide
 titlepage
+psfrags
 \end{reLyXre}
 
 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
Index: po/POTFILES.in
===================================================================
RCS file: /cvs/lyx/lyx-devel/po/POTFILES.in,v
retrieving revision 1.364
diff -u -r1.364 POTFILES.in
--- po/POTFILES.in      2003/10/29 13:24:53     1.364
+++ po/POTFILES.in      2003/11/03 09:31:34
@@ -195,6 +195,7 @@
 src/paragraph_funcs.C
 src/rowpainter.C
 src/support/path_defines.C
+src/tex2lyx-new/lengthcommon.C
 src/text.C
 src/text2.C
 src/text3.C
Index: src/lyxfunc.C
===================================================================
RCS file: /cvs/lyx/lyx-devel/src/lyxfunc.C,v
retrieving revision 1.530
diff -u -r1.530 lyxfunc.C
--- src/lyxfunc.C       2003/11/01 15:45:14     1.530
+++ src/lyxfunc.C       2003/11/03 09:31:39
@@ -1521,10 +1521,15 @@
                setMessage(N_("Opening child document ") +
                           MakeDisplayPath(filename) + "...");
                view()->savePosition(0);
+               string const parentfilename = owner->buffer()->fileName();
                if (bufferlist.exists(filename))
                        view()->buffer(bufferlist.getBuffer(filename));
                else
                        view()->loadLyXFile(filename);
+               // Set the parent name of the child document.
+               // This makes insertion of citations and references in the child work,
+               // when the target is in the parent or another child document.
+               owner->buffer()->setParentName(parentfilename);
                break;
        }
 
Index: src/insets/insetminipage.C
===================================================================
RCS file: /cvs/lyx/lyx-devel/src/insets/insetminipage.C,v
retrieving revision 1.102
diff -u -r1.102 insetminipage.C
--- src/insets/insetminipage.C  2003/11/01 15:45:16     1.102
+++ src/insets/insetminipage.C  2003/11/03 09:31:44
@@ -107,6 +107,8 @@
 
                params_.pos   = params.pos;
                params_.width = params.width;
+               params_.inner_pos = params.inner_pos;
+               params_.height = params.height;
 
                /* FIXME: I refuse to believe we have to live
                 * with ugliness like this ... */
@@ -256,8 +258,30 @@
                s_pos += 'b';
                break;
        }
-       os << "\\begin{minipage}[" << s_pos << "]{"
-          << params_.width.asLatexString() << "}%\n";
+       string s_inner_pos;
+       switch (params_.inner_pos) {
+       case inner_top:
+               s_inner_pos += 't';
+               break;
+       case inner_center:
+               s_inner_pos += 'c';
+               break;
+       case inner_bottom:
+               s_inner_pos += 'b';
+               break;
+       case inner_stretch:
+               s_inner_pos += 's';
+               break;
+       }
+       os << "\\begin{minipage}[" << s_pos << "]";
+       if(params_.height.value() != 0) {
+               // 0 was the default value before the height was accessible
+               os << '[' << params_.height.asLatexString() << ']';
+               if(params_.inner_pos != inner_center)
+                       // inner_center was the default value before inner_pos was 
accessible
+                       os << '[' << s_inner_pos << ']';
+       }
+       os << '{' << params_.width.asLatexString() << "}%\n";
 
        int i = inset.latex(buf, os, runparams);
 
Index: src/mathed/math_gridinset.C
===================================================================
RCS file: /cvs/lyx/lyx-devel/src/mathed/math_gridinset.C,v
retrieving revision 1.131
diff -u -r1.131 math_gridinset.C
--- src/mathed/math_gridinset.C 2003/11/01 15:45:19     1.131
+++ src/mathed/math_gridinset.C 2003/11/03 09:31:47
@@ -217,6 +217,24 @@
                        colinfo_[col].align_ = c;
                        ++col;
                        colinfo_[col].lines_ = 0;
+                } else if (c == '@' && it + 1 != hh.end() && *(it + 1) == '{') {
+                       lyxerr << "unknown column separator: '" << c;
+                       int brace_open = 0, brace_close = 0;
+                       for (++it; it != hh.end(); ++it) {
+                               c = *it;
+                               if(c == '{') {
+                                       ++brace_open;
+                               } else if(c == '}') {
+                                       ++brace_close;
+                               }
+                               lyxerr << c;
+                               if(brace_open > 0 && brace_open == brace_close) {
+                                       ++it;
+                                       break;
+                               }
+                       }
+                       --it;
+                       lyxerr << "'\n";
                } else {
                        lyxerr << "unknown column separator: '" << c << "'" << endl;
                }
Index: src/tex2lyx/ChangeLog
===================================================================
RCS file: /cvs/lyx/lyx-devel/src/tex2lyx/ChangeLog,v
retrieving revision 1.40
diff -u -r1.40 ChangeLog
--- src/tex2lyx/ChangeLog       2003/10/23 11:46:33     1.40
+++ src/tex2lyx/ChangeLog       2003/11/03 09:31:49
@@ -1,3 +1,27 @@
+2003-11-03  Georg Baum  <[EMAIL PROTECTED]>
+
+       * math.C:
+       * table.C:
+       * text.C:
+       * context.[Ch]: New functions Context::set_item(),
+       Context::new_paragraph(ostream & os) and Context::atParagraphStart()
+       to make Context usage more explicit
+       * texparser.[Ch]: Rework Parser::tokenize (see comment in texparser.h)
+       * table.C:
+       * math.C:
+       * texparser.C: Don't silently drop comments
+       * texparser.C: Token::asInput() does not append a space anymore
+       * texparser.[Ch]: Renamed Parser::prev_token() to Parser::curr_token().
+       New function Parser::prev_token() returns now really the previous token
+       * Context.[Ch]:
+       * text.C: Convert known vspaces at paragraph start to \\added_space_top
+       * preamble.C: Don't put out newlines twice.
+       * text.C: Fix minipage position bug
+       * text.C: Fix \labelwidthstring bug
+       * text.C: Recognize alignment environments
+       * text.C: Fix a few cases of incorrect context usage, resulting
+       in missing or superflous \begin_layout / \end_laout lines.
+
 2003-10-23  Georg Baum  <[EMAIL PROTECTED]>
 
        * math.C:
Index: src/tex2lyx/context.C
===================================================================
RCS file: /cvs/lyx/lyx-devel/src/tex2lyx/context.C,v
retrieving revision 1.7
diff -u -r1.7 context.C
--- src/tex2lyx/context.C       2003/10/06 15:43:21     1.7
+++ src/tex2lyx/context.C       2003/11/03 09:31:49
@@ -23,7 +23,7 @@
 
 void begin_layout(ostream & os, LyXLayout_ptr layout)
 {
-       os << "\n\\begin_layout " << layout->name() << "\n\n";
+       os << "\n\\begin_layout " << layout->name() << "\n";
 }
 
 
@@ -94,11 +94,12 @@
                        begin_layout(os, layout);
                        need_layout=false;
                        need_end_layout = true;
-                       if (!extra_stuff.empty()) {
-                               os << extra_stuff;
-                               extra_stuff.erase();
-                       }
                }
+               if (!extra_stuff.empty()) {
+                       os << extra_stuff;
+                       extra_stuff.erase();
+               }
+               os << "\n";
        }
 }
 
@@ -140,6 +141,20 @@
 }
 
 
+void Context::set_item()
+{
+       need_layout = true;
+       has_item = true;
+}
+
+
+void Context::new_paragraph(ostream & os)
+{
+       check_end_layout(os);
+       need_layout = true;
+}
+
+
 void Context::dump(ostream & os, string const & desc) const
 {
        os << "\n" << desc <<" [";
@@ -147,6 +162,12 @@
                os << "need_layout ";
        if (need_end_layout)
                os << "need_end_layout ";
+       if (need_end_deeper)
+               os << "need_end_deeper ";
+       if (has_item)
+               os << "has_item ";
+       if (deeper_paragraph)
+               os << "deeper_paragraph ";
        if (!extra_stuff.empty())
                os << "extrastuff=[" << extra_stuff << "] ";
        os << "layout=" << layout->name();
Index: src/tex2lyx/context.h
===================================================================
RCS file: /cvs/lyx/lyx-devel/src/tex2lyx/context.h,v
retrieving revision 1.7
diff -u -r1.7 context.h
--- src/tex2lyx/context.h       2003/09/09 18:27:24     1.7
+++ src/tex2lyx/context.h       2003/11/03 09:31:49
@@ -37,6 +37,15 @@
        // description \c desc.
        void dump(std::ostream &, std::string const & desc = "context") const;
 
+       /// Are we just beginning a new paragraph?
+       bool atParagraphStart() const { return need_layout; }
+
+       /// Begin an item in a list environment
+       void set_item();
+
+       /// Start a new paragraph
+       void new_paragraph(std::ostream & os);
+
        // Do we need to output some \begin_layout command before the
        // next characters?
        bool need_layout;
Index: src/tex2lyx/math.C
===================================================================
RCS file: /cvs/lyx/lyx-devel/src/tex2lyx/math.C,v
retrieving revision 1.11
diff -u -r1.11 math.C
--- src/tex2lyx/math.C  2003/10/23 11:46:33     1.11
+++ src/tex2lyx/math.C  2003/11/03 09:31:50
@@ -99,8 +99,10 @@
                        }
                }
 
+               else if (t.cat() == catSpace)
+                       os << ' ';
+
                else if (t.cat() == catLetter ||
-                              t.cat() == catSpace ||
                               t.cat() == catSuper ||
                               t.cat() == catSub ||
                               t.cat() == catOther ||
@@ -110,8 +112,7 @@
                        os << t.character();
 
                else if (t.cat() == catNewline) {
-                       //if (p.next_token().cat() == catNewline) {
-                       //      p.get_token();
+                       //if (t.cs.size() > 1) {
                        //      handle_par(os);
                        //} else {
                                os << "\n "; // note the space
@@ -130,8 +131,13 @@
                        os << "unexpected '}' in math\n";
                }
 
-               else if (t.cat() == catComment)
-                       handle_comment(p);
+               else if (t.cat() == catComment) {
+                       if (t.cs().size())
+                               cerr << "Ignoring comment: " << t.asInput();
+                       else
+                               // "%\n" combination
+                               p.skip_spaces();
+               }
 
                //
                // control sequences
Index: src/tex2lyx/preamble.C
===================================================================
RCS file: /cvs/lyx/lyx-devel/src/tex2lyx/preamble.C,v
retrieving revision 1.16
diff -u -r1.16 preamble.C
--- src/tex2lyx/preamble.C      2003/10/23 11:46:33     1.16
+++ src/tex2lyx/preamble.C      2003/11/03 09:31:50
@@ -176,6 +176,21 @@
        h_preamble.str("");
 }
 
+/*!
+ * Swallows up to \param number newlines.
+ * Swallows all newlines if \param number is 0.
+ */
+void swallow_newlines(Parser & p, ostream & os, size_t number)
+{
+       if (p.next_token().cat() != catNewline)
+               return;
+       Token const & t = p.get_token();
+       if (number == 0)
+               return;
+       for(size_t i = number; i < t.cs().size(); ++i)
+               os << '\n';
+}
+
 } // anonymous namespace
 
 LyXTextClass const parse_preamble(Parser & p, ostream & os, string const & forceclass)
@@ -188,7 +203,7 @@
        while (p.good()) {
                Token const & t = p.get_token();
 
-               if (t.cs() == "documentclass") {
+               if (t.cat() == catEscape && t.cs() == "documentclass") {
                        is_full_document = true;
                        break;
                }
@@ -206,7 +221,6 @@
                // cat codes
                //
                if (t.cat() == catLetter ||
-                         t.cat() == catSpace ||
                          t.cat() == catSuper ||
                          t.cat() == catSub ||
                          t.cat() == catOther ||
@@ -215,24 +229,28 @@
                          t.cat() == catBegin ||
                          t.cat() == catEnd ||
                          t.cat() == catAlign ||
-                         t.cat() == catNewline ||
                          t.cat() == catParameter)
                h_preamble << t.character();
 
+               else if (t.cat() == catSpace || t.cat() == catNewline)
+                       h_preamble << t.asInput();
+
                else if (t.cat() == catComment)
-                       handle_comment(p);
+                       h_preamble << t.asInput();
 
-               else if (t.cs() == "pagestyle")
+               else if (t.cs() == "pagestyle") {
                        h_paperpagestyle = p.verbatim_item();
+                       swallow_newlines(p, h_preamble, 1);
+               }
 
                else if (t.cs() == "makeatletter") {
                        p.setCatCode('@', catLetter);
-                       h_preamble << "\\makeatletter\n";
+                       h_preamble << "\\makeatletter";
                }
 
                else if (t.cs() == "makeatother") {
                        p.setCatCode('@', catOther);
-                       h_preamble << "\\makeatother\n";
+                       h_preamble << "\\makeatother";
                }
 
                else if (t.cs() == "newcommand" || t.cs() == "renewcommand"
@@ -246,25 +264,27 @@
                        string const opts = p.getOpt();
                        string const body = p.verbatim_item();
                        // only non-lyxspecific stuff
-                       if (name != "\\noun "
-                                 && name != "\\tabularnewline "
-                           && name != "\\LyX "
-                                 && name != "\\lyxline "
-                                 && name != "\\lyxaddress "
-                                 && name != "\\lyxrightaddress "
-                                 && name != "\\boldsymbol "
-                                 && name != "\\lyxarrow ") {
+                       if (   name != "\\noun"
+                           && name != "\\tabularnewline"
+                           && name != "\\LyX"
+                           && name != "\\lyxline"
+                           && name != "\\lyxaddress"
+                           && name != "\\lyxrightaddress"
+                           && name != "\\boldsymbol"
+                           && name != "\\lyxarrow") {
                                ostringstream ss;
                                ss << '\\' << t.cs();
                                if (star)
                                        ss << '*';
-                               ss << '{' << name << '}' << opts << '{' << body << 
"}\n";
+                               ss << '{' << name << '}' << opts << '{' << body << "}";
                                h_preamble << ss.str();
 /*
                                ostream & out = in_preamble ? h_preamble : os;
                                out << "\\" << t.cs() << "{" << name << "}"
-                                   << opts << "{" << body << "}\n";
+                                   << opts << "{" << body << "}";
 */
+                       } else {
+                               swallow_newlines(p, h_preamble, 0);
                        }
                }
 
@@ -276,6 +296,7 @@
                        h_quotes_language = h_language;
                        h_options = join(opts, ",");
                        h_textclass = p.getArg('{', '}');
+                       swallow_newlines(p, h_preamble, 1);
                }
 
                else if (t.cs() == "usepackage") {
@@ -291,6 +312,7 @@
                        } else {
                                handle_package(name, options);
                        }
+                       swallow_newlines(p, h_preamble, 1);
                }
 
                else if (t.cs() == "newenvironment") {
@@ -301,17 +323,18 @@
                        ss << p.getOpt();
                        ss << '{' << p.verbatim_item() << '}';
                        ss << '{' << p.verbatim_item() << '}';
-                       ss << '\n';
                        if (name != "lyxcode" && name != "lyxlist"
                                        && name != "lyxrightadress" && name != 
"lyxaddress")
                                h_preamble << ss.str();
+                       else
+                               swallow_newlines(p, h_preamble, 0);
                }
 
                else if (t.cs() == "def") {
                        string name = p.get_token().cs();
                        while (p.next_token().cat() != catBegin)
                                name += p.get_token().asString();
-                       h_preamble << "\\def\\" << name << '{' << p.verbatim_item() << 
"}\n";
+                       h_preamble << "\\def\\" << name << '{' << p.verbatim_item() << 
"}";
                }
 
                else if (t.cs() == "newcolumntype") {
@@ -328,34 +351,36 @@
                        h_preamble << "\\newcolumntype{" << name << "}";
                        if (nargs)
                                h_preamble << "[" << nargs << "]";
-                       h_preamble << "{" << p.verbatim_item() << "}\n";
+                       h_preamble << "{" << p.verbatim_item() << "}";
                }
 
                else if (t.cs() == "setcounter") {
                        string const name = p.getArg('{', '}');
                        string const content = p.getArg('{', '}');
-                       if (name == "secnumdepth")
+                       if (name == "secnumdepth") {
                                h_secnumdepth = content;
-                       else if (name == "tocdepth")
+                               swallow_newlines(p, h_preamble, 1);
+                       } else if (name == "tocdepth") {
                                h_tocdepth = content;
-                       else
-                               h_preamble << "\\setcounter{" << name << "}{" << 
content << "}\n";
+                               swallow_newlines(p, h_preamble, 1);
+                       } else
+                               h_preamble << "\\setcounter{" << name << "}{" << 
content << "}";
                }
 
                else if (t.cs() == "setlength") {
                        string const name = p.verbatim_item();
                        string const content = p.verbatim_item();
-                       if (name == "parskip")
+                       // Is this correct?
+                       if (name == "parskip") {
                                h_paragraph_separation = "skip";
-                       else if (name == "parindent")
+                               swallow_newlines(p, h_preamble, 1);
+                       } else if (name == "parindent") {
                                h_paragraph_separation = "skip";
-                       else
-                               h_preamble << "\\setlength{" << name << "}{" << 
content << "}\n";
+                               swallow_newlines(p, h_preamble, 1);
+                       } else
+                               h_preamble << "\\setlength{" << name << "}{" << 
content << "}";
                }
 
-               else if (t.cs() == "par")
-                       h_preamble << '\n';
-
                else if (t.cs() == "begin") {
                        string const name = p.getArg('{', '}');
                        if (name == "document")
@@ -364,8 +389,9 @@
                }
 
                else if (t.cs().size())
-                       h_preamble << '\\' << t.cs() << ' ';
+                       h_preamble << '\\' << t.cs();
        }
+       p.skip_spaces();
 
        // Force textclass if the user wanted it
        if (forceclass.size()) {
Index: src/tex2lyx/table.C
===================================================================
RCS file: /cvs/lyx/lyx-devel/src/tex2lyx/table.C,v
retrieving revision 1.22
diff -u -r1.22 table.C
--- src/tex2lyx/table.C 2003/10/29 19:19:27     1.22
+++ src/tex2lyx/table.C 2003/11/03 09:31:52
@@ -192,13 +192,14 @@
                        }
                }
 
+               else if (t.cat() == catSpace || t.cat() == catNewline)
+                               os << t.cs();
+
                else if (t.cat() == catLetter ||
-                              t.cat() == catSpace ||
                               t.cat() == catSuper ||
                               t.cat() == catSub ||
                               t.cat() == catOther ||
                               t.cat() == catActive ||
-                              t.cat() == catNewline ||
                               t.cat() == catParameter)
                        os << t.character();
 
@@ -216,6 +217,7 @@
 
                else if (t.cat() == catAlign) {
                        os << TAB;
+                       p.skip_spaces();
                }
 
                else if (t.cs() == "tabularnewline" || t.cs() == "\\") {
@@ -232,7 +234,7 @@
                        hlines += "\\cline{" + p.verbatim_item() + '}';
 
                else if (t.cat() == catComment)
-                       handle_comment(p);
+                       os << t.asInput();
 
                else if (t.cs() == "(") {
                        os << "\\(";
Index: src/tex2lyx/tex2lyx.C
===================================================================
RCS file: /cvs/lyx/lyx-devel/src/tex2lyx/tex2lyx.C,v
retrieving revision 1.52
diff -u -r1.52 tex2lyx.C
--- src/tex2lyx/tex2lyx.C       2003/10/23 11:46:33     1.52
+++ src/tex2lyx/tex2lyx.C       2003/11/03 09:31:52
@@ -52,19 +52,6 @@
 // Hacks to allow the thing to link in the lyxlayout stuff
 LyXErr lyxerr(std::cerr.rdbuf());
 
-void handle_comment(Parser & p)
-{
-       string s;
-       while (p.good()) {
-               Token const & t = p.get_token();
-               if (t.cat() == catNewline)
-                       break;
-               s += t.asString();
-       }
-       //cerr << "comment: " << s << "\n";
-       p.skip_spaces();
-}
-
 
 string const trim(string const & a, char const * p)
 {
@@ -238,6 +225,13 @@
        active_environments.pop_back();
        ss.seekg(0);
        os << ss.str();
+#ifdef TEST_PARSER
+       p.reset();
+       ofstream parsertest("parsertest.tex");
+       while (p.good())
+               parsertest << p.get_token().asInput();
+       // <origfile> and parsertest.tex should now have identical content
+#endif
 }
 
 
Index: src/tex2lyx/tex2lyx.h
===================================================================
RCS file: /cvs/lyx/lyx-devel/src/tex2lyx/tex2lyx.h,v
retrieving revision 1.11
diff -u -r1.11 tex2lyx.h
--- src/tex2lyx/tex2lyx.h       2003/10/23 11:46:33     1.11
+++ src/tex2lyx/tex2lyx.h       2003/11/03 09:31:52
@@ -46,7 +46,6 @@
 
 
 /// in tex2lyx.C
-void handle_comment(Parser & p);
 std::string const trim(std::string const & a, char const * p = " \t\n\r");
 
 void split(std::string const & s, std::vector<std::string> & result,
Index: src/tex2lyx/texparser.C
===================================================================
RCS file: /cvs/lyx/lyx-devel/src/tex2lyx/texparser.C,v
retrieving revision 1.22
diff -u -r1.22 texparser.C
--- src/tex2lyx/texparser.C     2003/10/23 11:46:33     1.22
+++ src/tex2lyx/texparser.C     2003/11/03 09:31:53
@@ -28,17 +28,6 @@
 
 CatCode theCatcode[256];
 
-void skipSpaceTokens(istream & is, char c)
-{
-       // skip trailing spaces
-       while (catcode(c) == catSpace || catcode(c) == catNewline)
-               if (!is.get(c))
-                       break;
-       //cerr << "putting back: " << c << "\n";
-       is.putback(c);
-}
-
-
 void catInit()
 {
        fill(theCatcode, theCatcode + 256, catOther);
@@ -95,12 +84,16 @@
 
 ostream & operator<<(ostream & os, Token const & t)
 {
-       if (t.cs().size())
+       if (t.cat() == catComment)
+               os << '%' << t.cs() << '\n';
+       else if (t.cat() == catSpace)
+               os << t.cs();
+       else if (t.cat() == catEscape)
                os << '\\' << t.cs() << ' ';
        else if (t.cat() == catLetter)
                os << t.character();
        else if (t.cat() == catNewline)
-               os << "[\\n," << t.cat() << "]\n";
+               os << "[" << t.cs().size() << "\\n," << t.cat() << "]\n";
        else
                os << '[' << t.character() << ',' << t.cat() << ']';
        return os;
@@ -115,7 +108,11 @@
 
 string Token::asInput() const
 {
-       return char_ ? string(1, char_) : '\\' + cs_ + ' ';
+       if (cat_ == catComment)
+               return '%' + cs_ + '\n';
+       if (cat_ == catSpace || cat_ == catNewline)
+               return cs_;
+       return char_ ? string(1, char_) : '\\' + cs_;
 }
 
 
@@ -154,6 +151,13 @@
 Token const & Parser::prev_token() const
 {
        static const Token dummy;
+       return pos_ > 1 ? tokens_[pos_ - 2] : dummy;
+}
+
+
+Token const & Parser::curr_token() const
+{
+       static const Token dummy;
        return pos_ > 0 ? tokens_[pos_ - 1] : dummy;
 }
 
@@ -173,20 +177,41 @@
 }
 
 
-void Parser::skip_spaces()
+void Parser::skip_spaces(bool skip_comments)
 {
-       while (1) {
-               if (next_token().cat() == catSpace || next_token().cat() == catNewline)
+       // We just silently return if we have no more tokens.
+       // skip_spaces() should be callable at any time,
+       // the caller must check p::good() anyway.
+       while (good()) {
+               if ( next_token().cat() == catSpace ||
+                   (next_token().cat() == catNewline && next_token().cs().size() == 
1) ||
+                    next_token().cat() == catComment && next_token().cs().empty())
                        get_token();
-               else if (next_token().cat() == catComment)
-                       while (next_token().cat() != catNewline)
-                               get_token();
+               else if (skip_comments && next_token().cat() == catComment)
+                       cerr << "  Ignoring comment: " << get_token().asInput();
                else
                        break;
        }
 }
 
 
+void Parser::unskip_spaces(bool skip_comments)
+{
+       while (pos_ > 0) {
+               if ( curr_token().cat() == catSpace ||
+                   (curr_token().cat() == catNewline && curr_token().cs().size() == 
1))
+                       putback();
+               else if (skip_comments && curr_token().cat() == catComment) {
+                       // TODO: Get rid of this
+                       cerr << "Unignoring comment: " << curr_token().asInput();
+                       putback();
+               }
+               else
+                       break;
+       }
+}
+
+
 void Parser::putback()
 {
        --pos_;
@@ -209,7 +234,12 @@
 
 string Parser::getArg(char left, char right)
 {
-       skip_spaces();
+       skip_spaces(true);
+
+       // This is needed if a partial file ends with a command without arguments,
+       // e. g. \medskip
+       if (! good())
+               return string();
 
        string result;
        char c = getChar();
@@ -217,8 +247,17 @@
        if (c != left)
                putback();
        else
-               while ((c = getChar()) != right && good())
-                       result += c;
+               while ((c = getChar()) != right && good()) {
+                       // Ignore comments
+                       if (curr_token().cat() == catComment) {
+                               if (curr_token().cs().size())
+                                       cerr << "Ignoring comment: " << 
curr_token().asInput();
+                       }
+                       else if (curr_token().cat() == catSpace || curr_token().cat() 
== catNewline)
+                               result += curr_token().cs();
+                       else
+                               result += c;
+               }
 
        return result;
 }
@@ -245,34 +284,39 @@
                //cerr << "reading c: " << c << "\n";
 
                switch (catcode(c)) {
+                       case catSpace: {
+                               string s(1, c);
+                               while (is.get(c) && catcode(c) == catSpace)
+                                       s += c;
+                               if (catcode(c) != catSpace)
+                                       is.putback(c);
+                               push_back(Token(s, catSpace));
+                               break;
+                       }
+
                        case catNewline: {
                                ++lineno_;
-                               is.get(c);
-                               if (catcode(c) == catNewline) {
-                                       //do {
-                                               is.get(c);
-                                       //} while (catcode(c) == catNewline);
-                                       push_back(Token("par"));
-                               } else {
-                                       push_back(Token('\n', catNewline));
+                               string s(1, c);
+                               while (is.get(c) && catcode(c) == catNewline) {
+                                       ++lineno_;
+                                       s += c;
                                }
-                               is.putback(c);
+                               if (catcode(c) != catNewline)
+                                       is.putback(c);
+                               push_back(Token(s, catNewline));
                                break;
                        }
 
                        case catComment: {
-                               push_back(Token(c, catComment));
+                               // We don't treat "%\n" combinations here specially 
because
+                               // we want to preserve them in the preamble
+                               string s;
                                while (is.get(c) && catcode(c) != catNewline)
-                                       push_back(Token(c, catLetter));
-                               push_back(Token(c, catNewline));
+                                       s += c;
+                               // Note: The '%' at the beginning and the '\n' at the 
end
+                               // of the comment are not stored.
                                ++lineno_;
-                               is.get(c);
-                               if (catcode(c) == catNewline) {
-                                       push_back(Token("par"));
-                                       ++lineno_;
-                               } else {
-                                       is.putback(c);
-                               }
+                               push_back(Token(s, catComment));
                                break;
                        }
 
@@ -286,18 +330,11 @@
                                                // collect letters
                                                while (is.get(c) && catcode(c) == 
catLetter)
                                                        s += c;
-                                               skipSpaceTokens(is, c);
+                                               if (catcode(c) != catLetter)
+                                                       is.putback(c);
                                        }
-                                       push_back(Token(s));
+                                       push_back(Token(s, catEscape));
                                }
-                               break;
-                       }
-
-                       case catSuper:
-                       case catSub: {
-                               push_back(Token(c, catcode(c)));
-                               is.get(c);
-                               skipSpaceTokens(is, c);
                                break;
                        }
 
Index: src/tex2lyx/texparser.h
===================================================================
RCS file: /cvs/lyx/lyx-devel/src/tex2lyx/texparser.h,v
retrieving revision 1.15
diff -u -r1.15 texparser.h
--- src/tex2lyx/texparser.h     2003/10/23 11:46:33     1.15
+++ src/tex2lyx/texparser.h     2003/11/03 09:31:53
@@ -75,7 +75,7 @@
        ///
        Token(char c, CatCode cat) : cs_(), char_(c), cat_(cat) {}
        ///
-       Token(std::string const & cs) : cs_(cs), char_(0), cat_(catIgnore) {}
+       Token(std::string const & cs, CatCode cat) : cs_(cs), char_(0), cat_(cat) {}
 
        ///
        std::string const & cs() const { return cs_; }
@@ -100,9 +100,16 @@
 std::ostream & operator<<(std::ostream & os, Token const & t);
 
 
-//
-// Actual parser class
-//
+/*!
+ * Actual parser class
+ *
+ * The parser parses every character of the inputstream into a token
+ * and classifies the token.
+ * The following transformations are done:
+ * - Consecutive spaces are combined into one single token with CatCode catSpace
+ * - Consecutive newlines are combined into one single token with CatCode catSpace
+ * - Comments and %\n combinations are parsed into one token with CatCode catComment
+ */
 
 class Parser {
 
@@ -136,11 +143,15 @@
        ///
        Token const & prev_token() const;
        ///
-       Token const & next_token() const;
+       Token const & curr_token() const;
        ///
+       Token const & next_token() const;
+       /// Make the next token current and return that.
        Token const & get_token();
-       /// skips spaces if any
-       void skip_spaces();
+       /// skips spaces (and comments if \param skip_comments is true)
+       void skip_spaces(bool skip_comments = false);
+       /// puts back spaces (and comments if \param skip_comments is true)
+       void unskip_spaces(bool skip_comments = false);
        ///
        void lex(std::string const & s);
        ///
@@ -156,7 +167,7 @@
        ///
        CatCode getCatCode(char c) const;
 
-//private:
+private:
        ///
        int lineno_;
        ///
Index: src/tex2lyx/text.C
===================================================================
RCS file: /cvs/lyx/lyx-devel/src/tex2lyx/text.C,v
retrieving revision 1.25
diff -u -r1.25 text.C
--- src/tex2lyx/text.C  2003/10/23 11:46:33     1.25
+++ src/tex2lyx/text.C  2003/11/03 09:31:58
@@ -170,8 +170,30 @@
 }
 
 
-void handle_ert(ostream & os, string const & s, Context const & context)
+void handle_ert(ostream & os, string const & s, Context & context, bool check_layout 
= true)
 {
+       if (check_layout) {
+               // We must have a valid layout before outputting the ERT inset.
+               context.check_layout(os);
+       }
+       Context newcontext(true, context.textclass);
+       begin_inset(os, "ERT");
+       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;
+       }
+       newcontext.check_end_layout(os);
+       end_inset(os);
+}
+
+
+void handle_comment(ostream & os, string const & s, Context & context)
+{
+       // TODO: Handle this better
        Context newcontext(true, context.textclass);
        begin_inset(os, "ERT");
        os << "\nstatus Collapsed\n";
@@ -182,6 +204,8 @@
                else
                        os << *it;
        }
+       // make sure that our comment is the last thing on the line
+       os << "\n\\newline";
        newcontext.check_end_layout(os);
        end_inset(os);
 }
@@ -217,10 +241,11 @@
        context.check_deeper(os);
        context.check_layout(os);
        if (context.layout->optionalargs > 0) {
+               p.skip_spaces();
                if (p.next_token().character() == '[') {
                        p.get_token(); // eat '['
                        begin_inset(os, "OptArg\n");
-                       os << "collapsed true\n";
+                       os << "collapsed true\n\n";
                        parse_text_in_inset(p, os, FLAG_BRACK_LAST, outer, context);
                        end_inset(os);
                }
@@ -228,9 +253,57 @@
        parse_text_snippet(p, os, FLAG_ITEM, outer, context);
        context.check_end_layout(os);
        context.check_end_deeper(os);
+       // We don't need really a new paragraph, but
+       // we must make sure that the next item gets a \begin_layout.
+       parent_context.new_paragraph(os);
 }
 
 
+/*!
+ * Output a space if necessary.
+ * This function gets called for every whitespace token.
+ *
+ * We suppress as many spaces as possible. This has two effects:
+ * - Reimporting LyX generated LaTeX files changes almost no whitespace
+ * - Superflous whitespace from non LyX generated LaTeX files is removed.
+ *
+ * The consequence is that the logic inside the function is
+ * complicated, but that's the price...
+ *
+ * We have three cases here:
+ * - A space must be suppressed. Example: The lyxcode case below
+ * - A space may be suppressed. Example: Spaces before "\par"
+ * - A space must not be suppressed. Example: A space between two words
+ */
+void check_space(Parser const & p, ostream & os, Context & context)
+{
+       Token const next = p.next_token();
+       Token const curr = p.curr_token();
+       Token const prev = p.prev_token();
+       string const name = next.cs();
+       if (next.cat() == catSpace ||
+           next.cat() == catComment ||
+           (next.cat() == catNewline && next.cs().size() == 1) ||
+           next.cs() == "par" ||
+           next.cs() == "item" ||
+           (next.cs() == "end" && (context.layout->latextype == 
LATEX_ITEM_ENVIRONMENT ||
+                                   context.layout->latextype == 
LATEX_LIST_ENVIRONMENT ||
+                                   active_environment() == "quotation" ||
+                                   active_environment() == "quote" ||
+                                   active_environment() == "verse" ||
+                                   // LyX emits a newline before \end{lyxcode}.
+                                   // This newline must be ignored,
+                                   // otherwise LyX will add an additional protected 
space.
+                                   (active_environment() == "lyxcode" && curr.cat() 
== catNewline))) ||
+           // Or should we make a negative list? The alignment environments like 
center would be included
+           prev.cs() == "]" ||
+           prev.cs() == "\\") {
+               return;
+       }
+       context.check_layout(os);
+       os << ' ';
+}
+
 void parse_environment(Parser & p, ostream & os, bool outer,
                       Context & parent_context)
 {
@@ -239,6 +312,8 @@
        const bool is_starred = suffixIs(name, '*');
        string const unstarred_name = rtrim(name, "*");
        active_environments.push_back(name);
+       p.skip_spaces();
+
        if (is_math_env(name)) {
                parent_context.check_layout(os);
                begin_inset(os, "Formula ");
@@ -262,13 +337,15 @@
                        os << "placement " << p.getArg('[', ']') << '\n';
                }
                os << "wide " << tostr(is_starred)
-                  << "\ncollapsed false\n";
+                  << "\ncollapsed false\n\n";
                parse_text_in_inset(p, os, FLAG_END, outer, parent_context);
                end_inset(os);
+               // We don't need really a new paragraph, but
+               // we must make sure that the next item gets a \begin_layout.
+               parent_context.new_paragraph(os);
        }
 
        else if (name == "minipage") {
-               parent_context.check_layout(os);
                string position = "1";
                string inner_pos = "0";
                string height = "0pt";
@@ -293,8 +370,8 @@
                                if (p.next_token().asInput() == "[") {
                                        latex_inner_pos = p.getArg('[', ']');
                                        switch(latex_inner_pos[0]) {
-                                       case 't': inner_pos = "0"; break;
-                                       case 'c': inner_pos = "1"; break;
+                                       case 'c': inner_pos = "0"; break;
+                                       case 't': inner_pos = "1"; break;
                                        case 'b': inner_pos = "2"; break;
                                        case 's': inner_pos = "3"; break;
                                        default:
@@ -318,11 +395,11 @@
                                ss << '[' << latex_inner_pos << ']';
                        ss << "{" << width << "}";
                        handle_ert(os, ss.str(), parent_context);
-                       parent_context.check_end_layout(os);
-                       parent_context.need_layout = true;
+                       parent_context.new_paragraph(os);
                        parse_text_in_inset(p, os, FLAG_END, outer, parent_context);
                        handle_ert(os, "\\end{minipage}", parent_context);
                } else {
+                       parent_context.check_layout(os);
                        begin_inset(os, "Minipage\n");
                        os << "position " << position << '\n';
                        os << "inner_position " << inner_pos << '\n';
@@ -332,11 +409,27 @@
                        parse_text_in_inset(p, os, FLAG_END, outer, parent_context);
                        end_inset(os);
                }
-
        }
 
-       else if (name == "center") {
+       // Alignment settings
+       else if (name == "center" || name == "flushleft" || name == "flushright" ||
+                name == "centering" || name == "raggedright" || name == "raggedleft") 
{
+               // We must begin a new paragraph if not already done
+               if (! parent_context.atParagraphStart()) {
+                       parent_context.check_end_layout(os);
+                       parent_context.new_paragraph(os);
+               }
+               if (name == "flushleft" || name == "raggedright")
+                       parent_context.extra_stuff += "\\align left ";
+               else if (name == "flushright" || name == "raggedleft")
+                       parent_context.extra_stuff += "\\align right ";
+               else
+                       parent_context.extra_stuff += "\\align center ";
                parse_text(p, os, FLAG_END, outer, parent_context);
+               // Just in case the environment is empty ..
+               parent_context.extra_stuff.erase();
+               // We must begin a new paragraph to reset the alignment
+               parent_context.new_paragraph(os);
        }
 
        // The single '=' is meant here.
@@ -360,6 +453,7 @@
                parse_text(p, os, FLAG_END, outer, context);
                context.check_end_layout(os);
                context.check_end_deeper(os);
+               parent_context.new_paragraph(os);
        }
 
        else if (name == "appendix") {
@@ -383,19 +477,20 @@
 
        else if (name == "tabbing") {
                // We need to remember that we have to handle '\=' specially
-               parent_context.check_layout(os);
                handle_ert(os, "\\begin{" + name + "}", parent_context);
                parse_text_snippet(p, os, FLAG_END | FLAG_TABBING, outer, 
parent_context);
                handle_ert(os, "\\end{" + name + "}", parent_context);
        }
 
        else {
-               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);
        }
+
        active_environments.pop_back();
+       if (name != "math")
+               p.skip_spaces();
 }
 
 } // anonymous namespace
@@ -485,9 +580,10 @@
                        skip_braces(p);
                }
 
+               else if (t.cat() == catSpace || (t.cat() == catNewline && 
t.cs().size() == 1))
+                       check_space(p, os, context);
 
                else if (t.cat() == catLetter ||
-                              t.cat() == catSpace ||
                               t.cat() == catOther ||
                               t.cat() == catAlign ||
                               t.cat() == catParameter) {
@@ -495,16 +591,9 @@
                        os << t.character();
                }
 
-               else if (t.cat() == catNewline) {
-                       if (p.next_token().cat() == catNewline) {
-                               // this should have been be done by
-                               // the parser already
-                               cerr << "what are we doing here?" << endl;
-                               p.get_token();
-                               context.need_layout = true;
-                       } else {
-                               os << " "; // note the space
-                       }
+               else if (t.cat() == catNewline || (t.cat() == catEscape && t.cs() == 
"par")) {
+                       p.skip_spaces();
+                       context.new_paragraph(os);
                }
 
                else if (t.cat() == catActive) {
@@ -519,20 +608,19 @@
                }
 
                else if (t.cat() == catBegin) {
-// FIXME???
                        // special handling of size changes
                        context.check_layout(os);
                        bool const is_size = is_known(p.next_token().cs(), 
known_sizes);
-                       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  {}``
+                       Token const prev = p.prev_token();
+                       string const s = parse_text(p, FLAG_BRACE_LAST, outer, 
context);
+                       if (s.empty() && (p.next_token().character() == '`' ||
+                                         (prev.character() == '-' && 
p.next_token().character())))
+                               ; // ignore it in {}`` or -{}-
                        else if (is_size || s == "[" || s == "]" || s == "*")
                                os << s;
                        else {
-                               handle_ert(os, "{", context);
+                               handle_ert(os, "{", context, false);
+                               // s will end the current layout and begin a new one 
if necessary
                                os << s;
                                handle_ert(os, "}", context);
                        }
@@ -540,15 +628,26 @@
 
                else if (t.cat() == catEnd) {
                        if (flags & FLAG_BRACE_LAST) {
-                               context.check_end_layout(os);
                                return;
                        }
                        cerr << "stray '}' in text\n";
                        handle_ert(os, "}", context);
                }
 
-               else if (t.cat() == catComment)
-                       handle_comment(p);
+               else if (t.cat() == catComment) {
+                       context.check_layout(os);
+                       if (t.cs().size()) {
+                               handle_comment(os, '%' + t.cs(), context);
+                               if (p.next_token().cat() == catNewline) {
+                                       // A newline after a comment line starts a new 
paragraph
+                                       context.new_paragraph(os);
+                                       p.skip_spaces();
+                               }
+                       } else {
+                               // "%\n" combination
+                               p.skip_spaces();
+                       }
+               }
 
                //
                // control sequences
@@ -588,8 +687,7 @@
                }
 
                else if (t.cs() == "item") {
-                       // should be done automatically by Parser::tokenize
-                       //p.skip_spaces();
+                       p.skip_spaces();
                        string s;
                        bool optarg = false;
                        if (p.next_token().character() == '[') {
@@ -598,11 +696,10 @@
                                s = parse_text(p, FLAG_BRACK_LAST, outer, newcontext);
                                optarg = true;
                        }
-                       context.need_layout = true;
-                       context.has_item = true;
+                       context.set_item();
                        context.check_layout(os);
                        if (optarg) {
-                               if (active_environment() == "itemize") {
+                               if (context.layout->labeltype != LABEL_MANUAL) {
                                        // lyx does not support \item[\mybullet] in 
itemize environments
                                        handle_ert(os, "[", context);
                                        os << s;
@@ -610,13 +707,13 @@
                                } else if (s.size()) {
                                        // The space is needed to separate the item 
from the rest of the sentence.
                                        os << s << ' ';
+                                       p.skip_spaces();
                                }
                        }
                }
 
                else if (t.cs() == "bibitem") {
-                       context.need_layout = true;
-                       context.has_item = true;
+                       context.set_item();
                        context.check_layout(os);
                        os << "\\bibitem ";
                        os << p.getOpt();
@@ -624,6 +721,7 @@
                }
 
                else if (t.cs() == "def") {
+                       p.skip_spaces();
                        context.check_layout(os);
                        string name = p.get_token().cs();
                        while (p.next_token().cat() != catBegin)
@@ -631,20 +729,14 @@
                        handle_ert(os, "\\def\\" + name + '{' + p.verbatim_item() + 
'}', context);
                }
 
-               else if (t.cs() == "par") {
+               else if (t.cs() == "noindent") {
                        p.skip_spaces();
-                       context.check_end_layout(os);
-                       context.need_layout = true;
+                       context.extra_stuff += "\\noindent ";
                }
 
                else if (t.cs() == "appendix") {
-                       context.check_end_layout(os);
-                       Context newcontext(true, context.textclass, context.layout,
-                                       context.layout);
-                       newcontext.check_layout(os);
-                       os << "\\start_of_appendix\n";
-                       parse_text(p, os, FLAG_END, outer, newcontext);
-                       newcontext.check_end_layout(os);
+                       p.skip_spaces();
+                       context.extra_stuff += "\\start_of_appendix ";
                }
 
                // Must attempt to parse "Section*" before "Section".
@@ -655,12 +747,14 @@
                         newlayout->isCommand()) {
                        p.get_token();
                        output_command_layout(os, p, outer, context, newlayout);
+                       p.skip_spaces();
                }
 
                // The single '=' is meant here.
                else if ((newlayout = findLayout(context.textclass, t.cs())).get() &&
                         newlayout->isCommand()) {
                        output_command_layout(os, p, outer, context, newlayout);
+                       p.skip_spaces();
                }
 
                else if (t.cs() == "includegraphics") {
@@ -763,22 +857,25 @@
                }
 
                else if (t.cs() == "footnote") {
+                       p.skip_spaces();
                        context.check_layout(os);
                        begin_inset(os, "Foot\n");
-                       os << "collapsed true\n";
+                       os << "collapsed true\n\n";
                        parse_text_in_inset(p, os, FLAG_ITEM, false, context);
                        end_inset(os);
                }
 
                else if (t.cs() == "marginpar") {
+                       p.skip_spaces();
                        context.check_layout(os);
                        begin_inset(os, "Marginal\n");
-                       os << "collapsed true\n";
+                       os << "collapsed true\n\n";
                        parse_text_in_inset(p, os, FLAG_ITEM, false, context);
                        end_inset(os);
                }
 
                else if (t.cs() == "ensuremath") {
+                       p.skip_spaces();
                        context.check_layout(os);
                        Context newcontext(false, context.textclass);
                        string s = parse_text(p, FLAG_ITEM, false, newcontext);
@@ -793,12 +890,16 @@
                        context.check_layout(os);
                        os << "\n\\hfill\n";
                        skip_braces(p);
+                       p.skip_spaces();
                }
 
-               else if (t.cs() == "makeindex" || t.cs() == "maketitle")
+               else if (t.cs() == "makeindex" || t.cs() == "maketitle") {
+                       p.skip_spaces();
                        skip_braces(p); // swallow this
+               }
 
                else if (t.cs() == "tableofcontents") {
+                       p.skip_spaces();
                        context.check_layout(os);
                        begin_inset(os, "LatexCommand \\tableofcontents\n");
                        end_inset(os);
@@ -806,6 +907,7 @@
                }
 
                else if (t.cs() == "listoffigures") {
+                       p.skip_spaces();
                        context.check_layout(os);
                        begin_inset(os, "FloatList figure\n");
                        end_inset(os);
@@ -813,6 +915,7 @@
                }
 
                else if (t.cs() == "listoftables") {
+                       p.skip_spaces();
                        context.check_layout(os);
                        begin_inset(os, "FloatList table\n");
                        end_inset(os);
@@ -820,6 +923,7 @@
                }
 
                else if (t.cs() == "listof") {
+                       p.skip_spaces(true);
                        string const name = p.get_token().asString();
                        if (context.textclass.floats().typeExist(name)) {
                                context.check_layout(os);
@@ -906,6 +1010,7 @@
 
                else if (is_known(t.cs(), known_quotes)) {
                        char const ** where = is_known(t.cs(), known_quotes);
+                       context.check_layout(os);
                        begin_inset(os, "Quotes ");
                        os << known_coded_quotes[where - known_quotes];
                        end_inset(os);
@@ -916,6 +1021,7 @@
                        char const ** where = is_known(t.cs(), known_sizes);
                        context.check_layout(os);
                        os << "\n\\size " << known_coded_sizes[where - known_sizes] << 
"\n";
+                       p.skip_spaces();
                }
 
                else if (t.cs() == "LyX" || t.cs() == "TeX"
@@ -1096,6 +1202,35 @@
                        end_inset(os);
                }
 
+               else if ( t.cs() == "smallskip" ||
+                         t.cs() == "medskip" ||
+                         t.cs() == "bigskip" ||
+                         t.cs() == "vfill" ||
+                        (t.cs() == "vspace" && p.next_token().asInput() != "*")) {
+                       string arg;
+                       if (t.cs() == "vspace")
+                               arg = p.getArg('{', '}');
+                       else
+                               arg = t.cs();
+                       // We may only add the vspace to the current context if the
+                       // current paragraph is not empty.
+                       if (context.atParagraphStart()
+                           && (p.next_token().cat() != catNewline || 
p.next_token().cs().size() == 1)
+                           && (! (p.next_token().cat() == catEscape && 
p.next_token().cs() == "end"))
+                           && (! (p.next_token().cat() == catEscape && 
p.next_token().cs() == "par"))) {
+                               context.extra_stuff += "\\added_space_top " + arg + " 
";
+                               p.skip_spaces();
+                       } else {
+                               if (t.cs() == "vspace")
+                                       handle_ert(os, t.asInput() + '{' + arg + '}', 
context);
+                               else
+                                       handle_ert(os, t.asInput(), context);
+                       }
+                       // Would be nice to recognize added_space_bottom too...
+                       // At the moment this is parsed as added_space_top of the
+                       // next paragraph.
+               }
+
                else if (t.cs() == "psfrag") {
                        // psfrag{ps-text}[ps-pos][tex-pos]{tex-text}
                        // TODO: Generalize this!
@@ -1103,7 +1238,6 @@
                        arguments += '}';
                        arguments += p.getOpt();
                        arguments += p.getOpt();
-                       p.skip_spaces();
                        handle_ert(os, "\\psfrag{" + arguments, context);
                }
 
@@ -1122,7 +1256,13 @@
                        handle_ert(os, s + ' ', context);
                        */
                        context.check_layout(os);
-                       handle_ert(os, t.asInput() + ' ', context);
+                       string name = t.asInput();
+                       if (p.next_token().asInput() == "*") {
+                               // Starred commands like \vspace*{}
+                               p.get_token();                          // Eat '*'
+                               name += '*';
+                       }
+                       handle_ert(os, name, context);
                }
 
                if (flags & FLAG_LEAVE) {

Reply via email to