]> git.lyx.org Git - lyx.git/blobdiff - src/tex2lyx/text.cpp
Let the Foot inset have a different Layout when inside a title
[lyx.git] / src / tex2lyx / text.cpp
index fae7eb16af00769e5d6385b8d5178c6c461d29ea..2c212a425fffbc7afc57b8171e0a591c94baf0fa 100644 (file)
@@ -112,10 +112,10 @@ string parse_text_snippet(Parser & p, unsigned flags, const bool outer,
 
 
 char const * const known_ref_commands[] = { "ref", "pageref", "vref",
- "vpageref", "prettyref", "eqref", 0 };
+ "vpageref", "prettyref", "nameref", "eqref", 0 };
 
 char const * const known_coded_ref_commands[] = { "ref", "pageref", "vref",
- "vpageref", "formatted", "eqref", 0 };
+ "vpageref", "formatted", "nameref", "eqref", 0 };
 
 char const * const known_refstyle_commands[] = { "algref", "chapref", "corref",
  "eqref", "enuref", "figref", "fnref", "lemref", "parref", "partref", "propref",
@@ -233,12 +233,14 @@ char const * const known_coded_font_shapes[] = { "italic", "slanted",
 "smallcaps", "up", 0};
 
 /// Known special characters which need skip_spaces_braces() afterwards
-char const * const known_special_chars[] = {"ldots", "lyxarrow",
-"textcompwordmark", "slash", 0};
+char const * const known_special_chars[] = {"ldots",
+"lyxarrow", "textcompwordmark",
+"slash", "textasciitilde", "textasciicircum", "textbackslash", 0};
 
 /// the same as known_special_chars with .lyx names
-char const * const known_coded_special_chars[] = {"ldots{}", "menuseparator",
-"textcompwordmark{}", "slash{}", 0};
+char const * const known_coded_special_chars[] = {"\\SpecialChar \\ldots{}\n",
+"\\SpecialChar \\menuseparator\n", "\\SpecialChar \\textcompwordmark{}\n",
+"\\SpecialChar \\slash{}\n", "~", "^", "\n\\backslash\n", 0};
 
 /*!
  * Graphics file extensions known by the dvips driver of the graphics package.
@@ -933,7 +935,9 @@ void parse_box(Parser & p, ostream & os, unsigned outer_flags,
                width_unit = "in";
                width_special = "width";
        } else if (latex_width.empty() && outer_type == "framebox") {
-               use_ert = true;
+               width_value.clear();
+               width_unit.clear();
+               width_special = "none";
        }
        if (use_ert) {
                ostringstream ss;
@@ -990,9 +994,6 @@ void parse_box(Parser & p, ostream & os, unsigned outer_flags,
                        if (outer_flags & FLAG_END)
                                output_ert_inset(os, "\\end{" + outer_type + '}',
                                           parent_context);
-                       else if (inner_type.empty() && outer_type == "framebox")
-                               // in this case it is already closed later
-                               ;
                        else
                                output_ert_inset(os, "}", parent_context);
                }
@@ -1007,7 +1008,7 @@ void parse_box(Parser & p, ostream & os, unsigned outer_flags,
                begin_inset(os, "Box ");
                if (outer_type == "framed")
                        os << "Framed\n";
-               else if (outer_type == "framebox")
+               else if (outer_type == "framebox" || outer_type == "fbox")
                        os << "Boxed\n";
                else if (outer_type == "shadowbox")
                        os << "Shadowbox\n";
@@ -1018,18 +1019,27 @@ void parse_box(Parser & p, ostream & os, unsigned outer_flags,
                        preamble.registerAutomaticallyLoadedPackage("color");
                } else if (outer_type == "doublebox")
                        os << "Doublebox\n";
-               else if (outer_type.empty())
+               else if (outer_type.empty() || outer_type == "mbox")
                        os << "Frameless\n";
                else
                        os << outer_type << '\n';
                os << "position \"" << position << "\"\n";
                os << "hor_pos \"" << hor_pos << "\"\n";
-               os << "has_inner_box " << !inner_type.empty() << "\n";
+               if (outer_type == "mbox")
+                       os << "has_inner_box 1\n";
+               else
+                       os << "has_inner_box " << !inner_type.empty() << "\n";
                os << "inner_pos \"" << inner_pos << "\"\n";
                os << "use_parbox " << (inner_type == "parbox" || shadedparbox)
                   << '\n';
-               os << "use_makebox " << (inner_type == "makebox") << '\n';
-               os << "width \"" << width_value << width_unit << "\"\n";
+               if (outer_type == "mbox")
+                       os << "use_makebox 1\n";
+               else
+                       os << "use_makebox " << (inner_type == "makebox") << '\n';
+               if (outer_type == "fbox" || outer_type == "mbox")
+                       os << "width \"\"\n";
+               else
+                       os << "width \"" << width_value << width_unit << "\"\n";
                os << "special \"" << width_special << "\"\n";
                os << "height \"" << height_value << height_unit << "\"\n";
                os << "height_special \"" << height_special << "\"\n";
@@ -1129,7 +1139,8 @@ void parse_outer_box(Parser & p, ostream & os, unsigned flags, bool outer,
                        p.skip_spaces(true);
                }
        }
-       if (outer_type == "shaded") {
+       if (outer_type == "shaded" || outer_type == "fbox"
+               || outer_type == "mbox") {
                // These boxes never have an inner box
                ;
        } else if (p.next_token().asInput() == "\\parbox") {
@@ -1514,6 +1525,37 @@ void parse_environment(Parser & p, ostream & os, bool outer,
                        preamble.registerAutomaticallyLoadedPackage("color");
        }
 
+       else if (name == "btSect") {
+               eat_whitespace(p, os, parent_context, false);
+               parent_context.check_layout(os);
+               begin_command_inset(os, "bibtex", "bibtex");
+               string bibstyle = "plain";
+               if (p.hasOpt()) {
+                       bibstyle = p.getArg('[', ']');
+                       p.skip_spaces(true);
+               }
+               string const bibfile = p.getArg('{', '}');
+               eat_whitespace(p, os, parent_context, false);
+               Token t = p.get_token();
+               if (t.asInput() == "\\btPrintCited") {
+                       p.skip_spaces(true);
+                       os << "btprint " << '"' << "btPrintCited" << '"' << "\n";
+               }
+               if (t.asInput() == "\\btPrintNotCited") {
+                       p.skip_spaces(true);
+                       os << "btprint " << '"' << "btPrintNotCited" << '"' << "\n";
+               }
+               if (t.asInput() == "\\btPrintAll") {
+                       p.skip_spaces(true);
+                       os << "btprint " << '"' << "btPrintAll" << '"' << "\n";
+               }
+               os << "bibfiles " << '"' << bibfile << '"' << "\n";
+               os << "options " << '"' << bibstyle << '"' <<  "\n";
+               parse_text_in_inset(p, os, FLAG_END, outer, parent_context);
+               end_inset(os);
+               p.skip_spaces();
+       }
+
        else if (name == "framed" || name == "shaded") {
                eat_whitespace(p, os, parent_context, false);
                parse_outer_box(p, os, FLAG_END, outer, parent_context, name, "");
@@ -1588,24 +1630,13 @@ void parse_environment(Parser & p, ostream & os, bool outer,
                if (last_env == name) {
                        // we need to output a separator since LyX would export
                        // the two environments as one otherwise (bug 5716)
-                       docstring const sep = from_ascii("--Separator--");
                        TeX2LyXDocClass const & textclass(parent_context.textclass);
-                       if (textclass.hasLayout(sep)) {
-                               Context newcontext(parent_context);
-                               newcontext.layout = &(textclass[sep]);
-                               newcontext.check_layout(os);
-                               newcontext.check_end_layout(os);
-                       } else {
-                               parent_context.check_layout(os);
-                               begin_inset(os, "Note Note\n");
-                               os << "status closed\n";
-                               Context newcontext(true, textclass,
-                                               &(textclass.defaultLayout()));
-                               newcontext.check_layout(os);
-                               newcontext.check_end_layout(os);
-                               end_inset(os);
-                               parent_context.check_end_layout(os);
-                       }
+                       Context newcontext(true, textclass,
+                                       &(textclass.defaultLayout()));
+                       newcontext.check_layout(os);
+                       begin_inset(os, "Separator plain\n");
+                       end_inset(os);
+                       newcontext.check_end_layout(os);
                }
                switch (context.layout->latextype) {
                case  LATEX_LIST_ENVIRONMENT:
@@ -1982,78 +2013,58 @@ void copy_file(FileName const & src, string dstname)
 }
 
 
-/// Parse a NoWeb Chunk section. The initial "<<" is already parsed.
-void parse_noweb(Parser & p, ostream & os, Context & context)
+/// Parse a literate Chunk section. The initial "<<" is already parsed.
+bool parse_chunk(Parser & p, ostream & os, Context & context)
 {
-       // assemble the rest of the keyword
-       string name("<<");
-       bool chunk = false;
-       while (p.good()) {
-               Token const & t = p.get_token();
-               if (t.asInput() == ">" && p.next_token().asInput() == ">") {
-                       name += ">>";
-                       p.get_token();
-                       chunk = (p.good() && p.next_token().asInput() == "=");
-                       if (chunk)
-                               name += p.get_token().asInput();
-                       break;
-               }
-               name += t.asInput();
+       // check whether a chunk is possible here.
+       if (!context.textclass.hasInsetLayout(from_ascii("Flex:Chunk"))) {
+               return false;
        }
 
-       if (!chunk || !context.new_layout_allowed ||
-           !context.textclass.hasLayout(from_ascii("Chunk"))) {
-               cerr << "Warning: Could not interpret '" << name
-                    << "'. Ignoring it." << endl;
-               return;
+       p.pushPosition();
+
+       // read the parameters
+       Parser::Arg const params = p.verbatimStuff(">>=\n", false);
+       if (!params.first) {
+               p.popPosition();
+               return false;
        }
 
-       // We use new_paragraph instead of check_end_layout because the stuff
-       // following the noweb chunk needs to start with a \begin_layout.
-       // This may create a new paragraph even if there was none in the
-       // noweb file, but the alternative is an invalid LyX file. Since
-       // noweb code chunks are implemented with a layout style in LyX they
-       // always must be in an own paragraph.
-       context.new_paragraph(os);
-       Context newcontext(true, context.textclass,
-               &context.textclass[from_ascii("Chunk")]);
-       newcontext.check_layout(os);
-       os << name;
-       while (p.good()) {
-               Token const & t = p.get_token();
-               // We abuse the parser a bit, because this is no TeX syntax
-               // at all.
-               if (t.cat() == catEscape)
-                       os << subst(t.asInput(), "\\", "\n\\backslash\n");
-               else {
-                       ostringstream oss;
-                       Context tmp(false, context.textclass,
-                                   &context.textclass[from_ascii("Chunk")]);
-                       tmp.need_end_layout = true;
-                       tmp.check_layout(oss);
-                       os << subst(t.asInput(), "\n", oss.str());
-               }
-               // The chunk is ended by an @ at the beginning of a line.
-               // After the @ the line may contain a comment and/or
-               // whitespace, but nothing else.
-               if (t.asInput() == "@" && p.prev_token().cat() == catNewline &&
-                   (p.next_token().cat() == catSpace ||
-                    p.next_token().cat() == catNewline ||
-                    p.next_token().cat() == catComment)) {
-                       while (p.good() && p.next_token().cat() == catSpace)
-                               os << p.get_token().asInput();
-                       if (p.next_token().cat() == catComment)
-                               // The comment includes a final '\n'
-                               os << p.get_token().asInput();
-                       else {
-                               if (p.next_token().cat() == catNewline)
-                                       p.get_token();
-                               os << '\n';
-                       }
-                       break;
-               }
+       Parser::Arg const code = p.verbatimStuff("\n@");
+       if (!code.first) {
+               p.popPosition();
+               return false;
        }
-       newcontext.check_end_layout(os);
+       string const post_chunk = p.verbatimStuff("\n").second + '\n';
+       if (post_chunk[0] != ' ' && post_chunk[0] != '\n') {
+               p.popPosition();
+               return false;
+       }
+       // The last newline read is important for paragraph handling
+       p.putback();
+       p.deparse();
+
+       //cerr << "params=[" << params.second << "], code=[" << code.second << "]" <<endl;
+       // We must have a valid layout before outputting the Chunk inset.
+       context.check_layout(os);
+       Context chunkcontext(true, context.textclass);
+       chunkcontext.layout = &context.textclass.plainLayout();
+       begin_inset(os, "Flex Chunk");
+       os << "\nstatus open\n";
+       if (!params.second.empty()) {
+               chunkcontext.check_layout(os);
+               Context paramscontext(true, context.textclass);
+               paramscontext.layout = &context.textclass.plainLayout();
+               begin_inset(os, "Argument 1");
+               os << "\nstatus open\n";
+               output_ert(os, params.second, paramscontext);
+               end_inset(os);
+       }
+       output_ert(os, code.second, chunkcontext);
+       end_inset(os);
+
+       p.dropPosition();
+       return true;
 }
 
 
@@ -2325,18 +2336,26 @@ void parse_text(Parser & p, ostream & os, unsigned flags, bool outer,
                }
 
                else if (t.asInput() == "<"
-                        && p.next_token().asInput() == "<" && noweb_mode) {
-                       p.get_token();
-                       parse_noweb(p, os, context);
-               }
+                        && p.next_token().asInput() == "<") {
+                       bool has_chunk = false;
+                       if (noweb_mode) {
+                               p.pushPosition();
+                               p.get_token();
+                               has_chunk = parse_chunk(p, os, context);
+                               if (!has_chunk)
+                                       p.popPosition();
+                       }
 
-               else if (t.asInput() == "<" && p.next_token().asInput() == "<") {
-                       context.check_layout(os);
-                       begin_inset(os, "Quotes ");
-                       os << "ard";
-                       end_inset(os);
-                       p.get_token();
-                       skip_braces(p);
+                       if (!has_chunk) {
+                               context.check_layout(os);
+                               begin_inset(os, "Quotes ");
+                               //FIXME: this is a right danish quote;
+                               // why not a left french quote?
+                               os << "ard";
+                               end_inset(os);
+                               p.get_token();
+                               skip_braces(p);
+                       }
                }
 
                else if (t.cat() == catSpace || (t.cat() == catNewline && ! p.isParagraph()))
@@ -2449,6 +2468,12 @@ void parse_text(Parser & p, ostream & os, unsigned flags, bool outer,
                                if (!s.empty()) {
                                        context.check_layout(os);
                                        os << to_utf8(s);
+                                       if (!rem.empty())
+                                               output_ert_inset(os,
+                                                       to_utf8(rem), context);
+                                       for (set<string>::const_iterator it = req.begin();
+                                            it != req.end(); ++it)
+                                               preamble.registerAutomaticallyLoadedPackage(*it);
                                } else
                                        // we did not find a non-ert version
                                        output_ert_inset(os, name, context);
@@ -2547,26 +2572,20 @@ void parse_text(Parser & p, ostream & os, unsigned flags, bool outer,
                // control sequences
                //
 
-               else if (t.cs() == "(") {
-                       context.check_layout(os);
-                       begin_inset(os, "Formula");
-                       os << " \\(";
-                       parse_math(p, os, FLAG_SIMPLE2, MATH_MODE);
-                       os << "\\)";
-                       end_inset(os);
-               }
-
-               else if (t.cs() == "[") {
+               else if (t.cs() == "(" || t.cs() == "[") {
+                       bool const simple = t.cs() == "(";
                        context.check_layout(os);
                        begin_inset(os, "Formula");
-                       os << " \\[";
-                       parse_math(p, os, FLAG_EQUATION, MATH_MODE);
-                       os << "\\]";
+                       os << " \\" << t.cs();
+                       parse_math(p, os, simple ? FLAG_SIMPLE2 : FLAG_EQUATION, MATH_MODE);
+                       os << '\\' << (simple ? ')' : ']');
                        end_inset(os);
-                       // Prevent the conversion of a line break to a space
-                       // (bug 7668). This does not change the output, but
-                       // looks ugly in LyX.
-                       eat_whitespace(p, os, context, false);
+                       if (!simple) {
+                               // Prevent the conversion of a line break to a
+                               // space (bug 7668). This does not change the
+                               // output, but looks ugly in LyX.
+                               eat_whitespace(p, os, context, false);
+                       }
                }
 
                else if (t.cs() == "begin")
@@ -2609,11 +2628,18 @@ void parse_text(Parser & p, ostream & os, unsigned flags, bool outer,
                        }
                        if (optarg) {
                                if (context.layout->labeltype != LABEL_MANUAL) {
-                                       // LyX does not support \item[\mybullet]
-                                       // in itemize environments
+                                       // handle option of itemize item
+                                       begin_inset(os, "Argument item:1\n");
+                                       os << "status open\n";
+                                       os << "\n\\begin_layout Plain Layout\n";
                                        Parser p2(s + ']');
                                        os << parse_text_snippet(p2,
                                                FLAG_BRACK_LAST, outer, context);
+                                       // we must not use context.check_end_layout(os)
+                                       // because that would close the outer itemize layout
+                                       os << "\n\\end_layout\n";
+                                       end_inset(os);
+                                       eat_whitespace(p, os, context, false);
                                } else if (!s.empty()) {
                                        // LyX adds braces around the argument,
                                        // so we need to remove them here.
@@ -2629,8 +2655,7 @@ void parse_text(Parser & p, ostream & os, unsigned flags, bool outer,
                                        } else {
                                                Parser p2(s + ']');
                                                os << parse_text_snippet(p2,
-                                                       FLAG_BRACK_LAST,
-                                                       outer, context);
+                                                       FLAG_BRACK_LAST, outer, context);
                                        }
                                        // The space is needed to separate the
                                        // item from the rest of the sentence.
@@ -2804,10 +2829,18 @@ void parse_text(Parser & p, ostream & os, unsigned flags, bool outer,
                }
 
                else if (t.cs() == "caption") {
+                       bool starred = false;
+                       if (p.next_token().asInput() == "*") {
+                               p.get_token();
+                               starred = true;
+                       }
                        p.skip_spaces();
                        context.check_layout(os);
                        p.skip_spaces();
-                       begin_inset(os, "Caption Standard\n");
+                       if (starred)
+                               begin_inset(os, "Caption LongTableNoNumber\n");
+                       else
+                               begin_inset(os, "Caption Standard\n");
                        Context newcontext(true, context.textclass, 0, 0, context.font);
                        newcontext.check_layout(os);
                        // FIXME InsetArgument is now properly implemented in InsetLayout
@@ -3108,16 +3141,12 @@ void parse_text(Parser & p, ostream & os, unsigned flags, bool outer,
                                preamble.registerAutomaticallyLoadedPackage("listings");
                }
 
-               else if (t.cs() == "listoffigures") {
-                       context.check_layout(os);
-                       begin_inset(os, "FloatList figure\n");
-                       end_inset(os);
-                       skip_spaces_braces(p);
-               }
-
-               else if (t.cs() == "listoftables") {
+               else if (t.cs() == "listoffigures" || t.cs() == "listoftables") {
                        context.check_layout(os);
-                       begin_inset(os, "FloatList table\n");
+                       if (t.cs() == "listoffigures")
+                               begin_inset(os, "FloatList figure\n");
+                       else
+                               begin_inset(os, "FloatList table\n");
                        end_inset(os);
                        skip_spaces_braces(p);
                }
@@ -3279,34 +3308,11 @@ void parse_text(Parser & p, ostream & os, unsigned flags, bool outer,
                        p.skip_spaces();
                }
 
-               // the TIPA Combining diacritical marks
-               else if (is_known(t.cs(), known_tipa_marks) || t.cs() == "textvertline") {
-                       preamble.registerAutomaticallyLoadedPackage("tipa");
-                       preamble.registerAutomaticallyLoadedPackage("tipx");
-                       context.check_layout(os);
-                       if (t.cs() == "textvertline") {
-                               os << "|";
-                               skip_braces(p);
-                               continue;
-                       }
-                       // try to see whether the string is in unicodesymbols
-                       bool termination;
-                       docstring rem;
-                       string content = trimSpaceAndEol(p.verbatim_item());
-                       string command = t.asInput() + "{" + content + "}";
-                       set<string> req;
-                       docstring s = encodings.fromLaTeXCommand(from_utf8(command),
-                               Encodings::TEXT_CMD | Encodings::MATH_CMD,
-                               termination, rem, &req);
-                       if (!s.empty()) {
-                               if (!rem.empty())
-                                       cerr << "When parsing " << command
-                                            << ", result is " << to_utf8(s)
-                                            << "+" << to_utf8(rem) << endl;
-                               os << content << to_utf8(s);
-                       } else
-                               // we did not find a non-ert version
-                               output_ert_inset(os, command, context);
+               else if (t.cs() == "textvertline") {
+                       // FIXME: This is not correct, \textvertline is higher than |
+                       os << "|";
+                       skip_braces(p);
+                       continue;
                }
 
                else if (t.cs() == "tone" ) {
@@ -3328,11 +3334,12 @@ void parse_text(Parser & p, ostream & os, unsigned flags, bool outer,
                                Encodings::TEXT_CMD | Encodings::MATH_CMD,
                                termination, rem, &req);
                        if (!s.empty()) {
-                               if (!rem.empty())
-                                       cerr << "When parsing " << command
-                                            << ", result is " << to_utf8(s)
-                                                << "+" << to_utf8(rem) << endl;
                                os << to_utf8(s);
+                               if (!rem.empty())
+                                       output_ert_inset(os, to_utf8(rem), context);
+                               for (set<string>::const_iterator it = req.begin();
+                                    it != req.end(); ++it)
+                                       preamble.registerAutomaticallyLoadedPackage(*it);
                        } else
                                // we did not find a non-ert version
                                output_ert_inset(os, command, context);
@@ -3431,40 +3438,13 @@ void parse_text(Parser & p, ostream & os, unsigned flags, bool outer,
                        skip_spaces_braces(p);
                }
 
-               else if ((where = is_known(t.cs(), known_ref_commands))) {
-                       // \eqref can also occur if refstyle is used
-                       if (t.cs() == "eqref" && preamble.refstyle() == "1") {
-                               context.check_layout(os);
-                               begin_command_inset(os, "ref", "formatted");
-                               os << "reference \"eq:"
-                                  << convert_command_inset_arg(p.verbatim_item())
-                                  << "\"\n";
-                               end_inset(os);
-                               preamble.registerAutomaticallyLoadedPackage("refstyle");
-                       } else {
-                               string const opt = p.getOpt();
-                               if (opt.empty()) {
-                                       context.check_layout(os);
-                                       begin_command_inset(os, "ref",
-                                               known_coded_ref_commands[where - known_ref_commands]);
-                                       os << "reference \""
-                                          << convert_command_inset_arg(p.verbatim_item())
-                                          << "\"\n";
-                                       end_inset(os);
-                                       if (t.cs() == "vref" || t.cs() == "vpageref")
-                                               preamble.registerAutomaticallyLoadedPackage("varioref");
-                               } else {
-                                       // LyX does not yet support optional arguments of ref commands
-                                       output_ert_inset(os, t.asInput() + '[' + opt + "]{" +
-                                              p.verbatim_item() + "}", context);
-                               }
-                       }
-               }
-
-               else if ((where = is_known(t.cs(), known_refstyle_commands))) {
+               // handle refstyle first to catch \eqref which can also occur
+               // without refstyle. Only recognize these commands if
+               // refstyle.sty was found in the preamble (otherwise \eqref
+               // and user defined ref commands could be misdetected).
+               else if ((where = is_known(t.cs(), known_refstyle_commands)) &&
+                        preamble.refstyle()) {
                        context.check_layout(os);
-                       // \eqref can also occur if refstyle is not used
-                       // this case is already handled in the previous else if
                        begin_command_inset(os, "ref", "formatted");
                        os << "reference \"";
                        os << known_refstyle_prefixes[where - known_refstyle_commands]
@@ -3475,6 +3455,30 @@ void parse_text(Parser & p, ostream & os, unsigned flags, bool outer,
                        preamble.registerAutomaticallyLoadedPackage("refstyle");
                }
 
+               // if refstyle is used, we must not convert \prettyref to a
+               // formatted reference, since that would result in a refstyle command.
+               else if ((where = is_known(t.cs(), known_ref_commands)) &&
+                        (t.cs() != "prettyref" || !preamble.refstyle())) {
+                       string const opt = p.getOpt();
+                       if (opt.empty()) {
+                               context.check_layout(os);
+                               begin_command_inset(os, "ref",
+                                       known_coded_ref_commands[where - known_ref_commands]);
+                               os << "reference \""
+                                  << convert_command_inset_arg(p.verbatim_item())
+                                  << "\"\n";
+                               end_inset(os);
+                               if (t.cs() == "vref" || t.cs() == "vpageref")
+                                       preamble.registerAutomaticallyLoadedPackage("varioref");
+                               else if (t.cs() == "prettyref")
+                                       preamble.registerAutomaticallyLoadedPackage("prettyref");
+                       } else {
+                               // LyX does not yet support optional arguments of ref commands
+                               output_ert_inset(os, t.asInput() + '[' + opt + "]{" +
+                                      p.verbatim_item() + '}', context);
+                       }
+               }
+
                else if (use_natbib &&
                         is_known(t.cs(), known_natbib_commands) &&
                         ((t.cs() != "citefullauthor" &&
@@ -3846,16 +3850,15 @@ void parse_text(Parser & p, ostream & os, unsigned flags, bool outer,
 
                else if ((where = is_known(t.cs(), known_special_chars))) {
                        context.check_layout(os);
-                       os << "\\SpecialChar \\"
-                          << known_coded_special_chars[where - known_special_chars]
-                          << '\n';
+                       os << known_coded_special_chars[where - known_special_chars];
                        skip_spaces_braces(p);
                }
 
-               else if (t.cs() == "nobreakdash" && p.next_token().asInput() == "-") {
+               else if ((t.cs() == "nobreakdash" && p.next_token().asInput() == "-") ||
+                        (t.cs() == "@" && p.next_token().asInput() == ".")) {
                        context.check_layout(os);
-                       os << "\\SpecialChar \\nobreakdash-\n";
-                       p.get_token();
+                       os << "\\SpecialChar \\" << t.cs()
+                          << p.get_token().asInput() << '\n';
                }
 
                else if (t.cs() == "textquotedbl") {
@@ -3864,40 +3867,14 @@ void parse_text(Parser & p, ostream & os, unsigned flags, bool outer,
                        skip_braces(p);
                }
 
-               else if (t.cs() == "@" && p.next_token().asInput() == ".") {
-                       context.check_layout(os);
-                       os << "\\SpecialChar \\@.\n";
-                       p.get_token();
-               }
-
-               else if (t.cs() == "-") {
-                       context.check_layout(os);
-                       os << "\\SpecialChar \\-\n";
-               }
-
-               else if (t.cs() == "textasciitilde") {
-                       context.check_layout(os);
-                       os << '~';
-                       skip_spaces_braces(p);
-               }
-
-               else if (t.cs() == "textasciicircum") {
-                       context.check_layout(os);
-                       os << '^';
-                       skip_spaces_braces(p);
-               }
-
-               else if (t.cs() == "textbackslash") {
-                       context.check_layout(os);
-                       os << "\n\\backslash\n";
-                       skip_spaces_braces(p);
-               }
-
                else if (t.cs() == "_" || t.cs() == "&" || t.cs() == "#"
                            || t.cs() == "$" || t.cs() == "{" || t.cs() == "}"
-                           || t.cs() == "%") {
+                           || t.cs() == "%" || t.cs() == "-") {
                        context.check_layout(os);
-                       os << t.cs();
+                       if (t.cs() == "-")
+                               os << "\\SpecialChar \\-\n";
+                       else
+                               os << t.cs();
                }
 
                else if (t.cs() == "char") {
@@ -3921,9 +3898,12 @@ void parse_text(Parser & p, ostream & os, unsigned flags, bool outer,
                        // set catcodes to verbatim early, just in case.
                        p.setCatcodes(VERBATIM_CATCODES);
                        string delim = p.get_token().asInput();
-                       //FIXME: handle error condition
-                       string const arg = p.verbatimStuff(delim).second;
-                       output_ert_inset(os, "\\verb" + delim + arg + delim, context);
+                       Parser::Arg arg = p.verbatimStuff(delim);
+                       if (arg.first)
+                               output_ert_inset(os, "\\verb" + delim 
+                                                + arg.second + delim, context);
+                       else
+                               cerr << "invalid \\verb command. Skipping" << endl;
                }
 
                // Problem: \= creates a tabstop inside the tabbing environment
@@ -3932,33 +3912,6 @@ void parse_text(Parser & p, ostream & os, unsigned flags, bool outer,
                else if (t.cs() == "=" && (flags & FLAG_TABBING))
                        output_ert_inset(os, t.asInput(), context);
 
-               // accents (see Table 6 in Comprehensive LaTeX Symbol List)
-               else if (t.cs().size() == 1
-                        && contains("\"'.=^`bcdHkrtuv~", t.cs())) {
-                       context.check_layout(os);
-                       // try to see whether the string is in unicodesymbols
-                       bool termination;
-                       docstring rem;
-                       string command = t.asInput() + "{"
-                               + trimSpaceAndEol(p.verbatim_item())
-                               + "}";
-                       set<string> req;
-                       docstring s = encodings.fromLaTeXCommand(from_utf8(command),
-                               Encodings::TEXT_CMD | Encodings::MATH_CMD,
-                               termination, rem, &req);
-                       if (!s.empty()) {
-                               if (!rem.empty())
-                                       cerr << "When parsing " << command
-                                            << ", result is " << to_utf8(s)
-                                            << "+" << to_utf8(rem) << endl;
-                               os << to_utf8(s);
-                               for (set<string>::const_iterator it = req.begin(); it != req.end(); ++it)
-                                       preamble.registerAutomaticallyLoadedPackage(*it);
-                       } else
-                               // we did not find a non-ert version
-                               output_ert_inset(os, command, context);
-               }
-
                else if (t.cs() == "\\") {
                        context.check_layout(os);
                        if (p.hasOpt())
@@ -4014,8 +3967,8 @@ void parse_text(Parser & p, ostream & os, unsigned flags, bool outer,
                                string const absfigname =
                                        changeExtension(abstexname, ".fig");
                                fix_child_filename(filename);
-                               string const lyxname =
-                                       changeExtension(filename, ".lyx");
+                               string const lyxname = changeExtension(filename,
+                                       roundtripMode() ? ".lyx.lyx" : ".lyx");
                                string const abslyxname = makeAbsPath(
                                        lyxname, getParentFilePath(false)).absFileName();
                                bool xfig = false;
@@ -4229,7 +4182,8 @@ void parse_text(Parser & p, ostream & os, unsigned flags, bool outer,
                                          "", "", t.cs());
                }
 
-               else if (t.cs() == "ovalbox" || t.cs() == "Ovalbox" ||
+               else if (t.cs() == "fbox" || t.cs() == "mbox" ||
+                            t.cs() == "ovalbox" || t.cs() == "Ovalbox" ||
                         t.cs() == "shadowbox" || t.cs() == "doublebox")
                        parse_outer_box(p, os, FLAG_ITEM, outer, context, t.cs(), "");
 
@@ -4244,18 +4198,11 @@ void parse_text(Parser & p, ostream & os, unsigned flags, bool outer,
                                parse_text(p, os, FLAG_ITEM, outer, context);
                                output_ert_inset(os, "}", context);
                        } else {
+                               //the syntax is: \framebox[width][position]{content}
                                string special = p.getFullOpt();
                                special += p.getOpt();
-                               // LyX does not yet support \framebox without any option
-                               if (!special.empty())
-                                       parse_outer_box(p, os, FLAG_ITEM, outer,
-                                                       context, t.cs(), special);
-                               else {
-                                       eat_whitespace(p, os, context, false);
-                                       output_ert_inset(os, "\\framebox{", context);
-                                       parse_text(p, os, FLAG_ITEM, outer, context);
-                                       output_ert_inset(os, "}", context);
-                               }
+                               parse_outer_box(p, os, FLAG_ITEM, outer,
+                                                   context, t.cs(), special);
                        }
                }
 
@@ -4631,15 +4578,12 @@ void parse_text(Parser & p, ostream & os, unsigned flags, bool outer,
                        // try to see whether the string is in unicodesymbols
                        // Only use text mode commands, since we are in text mode here,
                        // and math commands may be invalid (bug 6797)
-                       bool termination;
-                       docstring rem;
-                       set<string> req;
                        string name = t.asInput();
                        // handle the dingbats and Cyrillic
                        if (name == "\\ding" || name == "\\textcyr")
                                name = name + '{' + p.getArg('{', '}') + '}';
                        // handle the ifsym characters
-                       if (name == "\\textifsymbol") {
+                       else if (name == "\\textifsymbol") {
                                string const optif = p.getFullOpt();
                                string const argif = p.getArg('{', '}');
                                name = name + optif + '{' + argif + '}';
@@ -4647,84 +4591,99 @@ void parse_text(Parser & p, ostream & os, unsigned flags, bool outer,
                        // handle the \ascii characters
                        // the case of \ascii within braces, as LyX outputs it, is already
                        // handled for t.cat() == catBegin
-                       if (name == "\\ascii") {
+                       else if (name == "\\ascii") {
                                // the code is "\asci\xxx"
                                name = "{" + name + p.get_token().asInput() + "}";
                                skip_braces(p);
                        }
                        // handle some TIPA special characters
-                       if (name == "\\textglobfall") {
-                               name = "End";
-                               skip_braces(p);
-                       }
-                       if (name == "\\textdoublevertline") {
-                               name = "\\textbardbl";
-                               skip_braces(p);
-                       }
-                       if (name == "\\!" ) {
-                               if (p.next_token().asInput() == "b") {
-                                       p.get_token();  // eat 'b'
-                                       name = "\\texthtb";
-                                       skip_braces(p);
-                               }
-                               if (p.next_token().asInput() == "d") {
-                                       p.get_token();
-                                       name = "\\texthtd";
-                                       skip_braces(p);
-                               }
-                               if (p.next_token().asInput() == "g") {
-                                       p.get_token();
-                                       name = "\\texthtg";
-                                       skip_braces(p);
-                               }
-                               if (p.next_token().asInput() == "G") {
-                                       p.get_token();
-                                       name = "\\texthtscg";
+                       else if (preamble.isPackageUsed("tipa")) {
+                               if (name == "\\textglobfall") {
+                                       name = "End";
                                        skip_braces(p);
-                               }
-                               if (p.next_token().asInput() == "j") {
-                                       p.get_token();
-                                       name = "\\texthtbardotlessj";
-                                       skip_braces(p);
-                               }
-                               if (p.next_token().asInput() == "o") {
+                               } else if (name == "\\s") {
+                                       // fromLaTeXCommand() does not yet
+                                       // recognize tipa short cuts
+                                       name = "\\textsyllabic";
+                               } else if (name == "\\=" &&
+                                          p.next_token().asInput() == "*") {
+                                       // fromLaTeXCommand() does not yet
+                                       // recognize tipa short cuts
                                        p.get_token();
-                                       name = "\\textbullseye";
+                                       name = "\\b";
+                               } else if (name == "\\textdoublevertline") {
+                                       // FIXME: This is not correct,
+                                       // \textvertline is higher than \textbardbl
+                                       name = "\\textbardbl";
                                        skip_braces(p);
+                               } else if (name == "\\!" ) {
+                                       if (p.next_token().asInput() == "b") {
+                                               p.get_token();  // eat 'b'
+                                               name = "\\texthtb";
+                                               skip_braces(p);
+                                       } else if (p.next_token().asInput() == "d") {
+                                               p.get_token();
+                                               name = "\\texthtd";
+                                               skip_braces(p);
+                                       } else if (p.next_token().asInput() == "g") {
+                                               p.get_token();
+                                               name = "\\texthtg";
+                                               skip_braces(p);
+                                       } else if (p.next_token().asInput() == "G") {
+                                               p.get_token();
+                                               name = "\\texthtscg";
+                                               skip_braces(p);
+                                       } else if (p.next_token().asInput() == "j") {
+                                               p.get_token();
+                                               name = "\\texthtbardotlessj";
+                                               skip_braces(p);
+                                       } else if (p.next_token().asInput() == "o") {
+                                               p.get_token();
+                                               name = "\\textbullseye";
+                                               skip_braces(p);
+                                       }
+                               } else if (name == "\\*" ) {
+                                       if (p.next_token().asInput() == "k") {
+                                               p.get_token();
+                                               name = "\\textturnk";
+                                               skip_braces(p);
+                                       } else if (p.next_token().asInput() == "r") {
+                                               p.get_token();  // eat 'b'
+                                               name = "\\textturnr";
+                                               skip_braces(p);
+                                       } else if (p.next_token().asInput() == "t") {
+                                               p.get_token();
+                                               name = "\\textturnt";
+                                               skip_braces(p);
+                                       } else if (p.next_token().asInput() == "w") {
+                                               p.get_token();
+                                               name = "\\textturnw";
+                                               skip_braces(p);
+                                       }
                                }
                        }
-                       if (name == "\\*" ) {
-                               if (p.next_token().asInput() == "k") {
-                                       p.get_token();
-                                       name = "\\textturnk";
-                                       skip_braces(p);
-                               }
-                               if (p.next_token().asInput() == "r") {
-                                       p.get_token();  // eat 'b'
-                                       name = "\\textturnr";
-                                       skip_braces(p);
-                               }                               
-                               if (p.next_token().asInput() == "t") {
-                                       p.get_token();
-                                       name = "\\textturnt";
-                                       skip_braces(p);
-                               }
-                               if (p.next_token().asInput() == "w") {
-                                       p.get_token();
-                                       name = "\\textturnw";
-                                       skip_braces(p);
-                               }                               
+                       if ((name.size() == 2 &&
+                            contains("\"'.=^`bcdHkrtuv~", name[1]) &&
+                            p.next_token().asInput() != "*") ||
+                           is_known(name.substr(1), known_tipa_marks)) {
+                               // name is a command that corresponds to a
+                               // combining character in unicodesymbols.
+                               // Append the argument, fromLaTeXCommand()
+                               // will either convert it to a single
+                               // character or a combining sequence.
+                               name += '{' + p.verbatim_item() + '}';
                        }
                        // now get the character from unicodesymbols
+                       bool termination;
+                       docstring rem;
+                       set<string> req;
                        docstring s = encodings.fromLaTeXCommand(from_utf8(name),
                                        Encodings::TEXT_CMD, termination, rem, &req);
                        if (!s.empty()) {
-                               if (!rem.empty())
-                                       cerr << "When parsing " << t.cs()
-                                            << ", result is " << to_utf8(s)
-                                            << "+" << to_utf8(rem) << endl;
                                context.check_layout(os);
                                os << to_utf8(s);
+                               if (!rem.empty())
+                                       output_ert_inset(os, to_utf8(rem), context);
                                if (termination)
                                        skip_spaces_braces(p);
                                for (set<string>::const_iterator it = req.begin(); it != req.end(); ++it)
@@ -4744,14 +4703,14 @@ void parse_text(Parser & p, ostream & os, unsigned flags, bool outer,
                        output_ert_inset(os, s + ' ', context);
                        */
                        else {
-                               string name2 = t.asInput();
-                               if (p.next_token().asInput() == "*") {
+                               if (t.asInput() == name &&
+                                   p.next_token().asInput() == "*") {
                                        // Starred commands like \vspace*{}
                                        p.get_token();  // Eat '*'
-                                       name2 += '*';
+                                       name += '*';
                                }
-                               if (!parse_command(name2, p, os, outer, context))
-                                       output_ert_inset(os, name2, context);
+                               if (!parse_command(name, p, os, outer, context))
+                                       output_ert_inset(os, name, context);
                        }
                }