]> git.lyx.org Git - lyx.git/blobdiff - src/tex2lyx/text.cpp
tex2lyx: normalize bib and bst paths
[lyx.git] / src / tex2lyx / text.cpp
index d3ceb58ffdb369f294e1e854e63ca9d5e62e561a..3844fce398bff7480935b6bd00aed0bf6368992a 100644 (file)
@@ -45,6 +45,14 @@ using namespace lyx::support;
 namespace lyx {
 
 
+namespace {
+
+void output_arguments(ostream &, Parser &, bool, bool, bool, Context &,
+                      Layout::LaTeXArgMap const &);
+
+}
+
+
 void parse_text_in_inset(Parser & p, ostream & os, unsigned flags, bool outer,
                Context const & context, InsetLayout const * layout)
 {
@@ -55,7 +63,13 @@ void parse_text_in_inset(Parser & p, ostream & os, unsigned flags, bool outer,
                newcontext.layout = &context.textclass.plainLayout();
        else
                newcontext.font = context.font;
+       if (layout)
+               output_arguments(os, p, outer, false, false, newcontext,
+                                layout->latexargs());
        parse_text(p, os, flags, outer, newcontext);
+       if (layout)
+               output_arguments(os, p, outer, false, true, newcontext,
+                                layout->postcommandargs());
        newcontext.check_end_layout(os);
 }
 
@@ -110,20 +124,23 @@ string parse_text_snippet(Parser & p, unsigned flags, const bool outer,
        return os.str();
 }
 
+string fboxrule = "";
+string fboxsep = "";
+string shadow_size = "";
 
 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",
- "secref", "subref", "tabref", "thmref", 0 };
+ "secref", "subsecref", "tabref", "thmref", 0 };
 
 char const * const known_refstyle_prefixes[] = { "alg", "chap", "cor",
  "eq", "enu", "fig", "fn", "lem", "par", "part", "prop",
- "sec", "sub", "tab", "thm", 0 };
+ "sec", "subsec", "tab", "thm", 0 };
 
 
 /**
@@ -233,12 +250,22 @@ 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",
+"LyX", "TeX", "LaTeXe",
+"LaTeX", 0};
+
+/// special characters from known_special_chars which may have a \\protect before
+char const * const known_special_protect_chars[] = {"LyX", "TeX",
+"LaTeXe", "LaTeX", 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 ligaturebreak\n",
+"\\SpecialChar breakableslash\n", "~", "^", "\n\\backslash\n",
+"\\SpecialChar LyX\n", "\\SpecialChar TeX\n", "\\SpecialChar LaTeX2e\n",
+"\\SpecialChar LaTeX\n", 0};
 
 /*!
  * Graphics file extensions known by the dvips driver of the graphics package.
@@ -279,12 +306,6 @@ char const * const known_coded_spaces[] = { "space{}", "space{}",
 "hfill{}", "dotfill{}", "hrulefill{}", "leftarrowfill{}", "rightarrowfill{}",
 "upbracefill{}", "downbracefill{}", 0};
 
-/// These are translated by LyX to commands like "\\LyX{}", so we have to put
-/// them in ERT. "LaTeXe" must come before "LaTeX"!
-char const * const known_phrases[] = {"LyX", "TeX", "LaTeXe", "LaTeX", 0};
-char const * const known_coded_phrases[] = {"LyX", "TeX", "LaTeX2e", "LaTeX", 0};
-int const known_phrase_lengths[] = {3, 5, 7, 0};
-
 /// known TIPA combining diacritical marks
 char const * const known_tipa_marks[] = {"textsubwedge", "textsubumlaut",
 "textsubtilde", "textseagull", "textsubbridge", "textinvsubbridge",
@@ -292,7 +313,7 @@ char const * const known_tipa_marks[] = {"textsubwedge", "textsubumlaut",
 "textovercross", "textsubarch", "textsuperimposetilde", "textraising",
 "textlowering", "textadvancing", "textretracting", "textdoublegrave",
 "texthighrise", "textlowrise", "textrisefall", "textsyllabic",
-"textsubring", 0};
+"textsubring", "textsubbar", 0};
 
 /// TIPA tones that need special handling
 char const * const known_tones[] = {"15", "51", "45", "12", "454", 0};
@@ -500,8 +521,8 @@ docstring convert_unicodesymbols(docstring s)
                bool termination;
                docstring rem;
                set<string> req;
-               docstring parsed = encodings.fromLaTeXCommand(s,
-                               Encodings::TEXT_CMD, termination, rem, &req);
+               docstring parsed = normalize_c(encodings.fromLaTeXCommand(s,
+                               Encodings::TEXT_CMD, termination, rem, &req));
                set<string>::const_iterator it = req.begin();
                set<string>::const_iterator en = req.end();
                for (; it != en; ++it)
@@ -559,6 +580,16 @@ void output_ert_inset(ostream & os, string const & s, Context & context)
 }
 
 
+void output_comment(Parser & p, ostream & os, string const & s,
+                    Context & context)
+{
+       if (p.next_token().cat() == catNewline)
+               output_ert_inset(os, '%' + s, context);
+       else
+               output_ert_inset(os, '%' + s + '\n', context);
+}
+
+
 Layout const * findLayout(TextClass const & textclass, string const & name, bool command)
 {
        Layout const * layout = findLayoutWithoutModule(textclass, name, command);
@@ -611,6 +642,55 @@ void skip_spaces_braces(Parser & p, bool keepws = false)
 }
 
 
+void output_arguments(ostream & os, Parser & p, bool outer, bool need_layout, bool post,
+                      Context & context, Layout::LaTeXArgMap const & latexargs)
+{
+       if (need_layout) {
+               context.check_layout(os);
+               need_layout = false;
+       } else
+               need_layout = true;
+       int i = 0;
+       Layout::LaTeXArgMap::const_iterator lait = latexargs.begin();
+       Layout::LaTeXArgMap::const_iterator const laend = latexargs.end();
+       for (; lait != laend; ++lait) {
+               ++i;
+               eat_whitespace(p, os, context, false);
+               if (lait->second.mandatory) {
+                       if (p.next_token().cat() != catBegin)
+                               break;
+                       p.get_token(); // eat '{'
+                       if (need_layout) {
+                               context.check_layout(os);
+                               need_layout = false;
+                       }
+                       begin_inset(os, "Argument ");
+                       if (post)
+                               os << "post:";
+                       os << i << "\nstatus collapsed\n\n";
+                       parse_text_in_inset(p, os, FLAG_BRACE_LAST, outer, context);
+                       end_inset(os);
+               } else {
+                       if (p.next_token().cat() == catEscape ||
+                           p.next_token().character() != '[')
+                               continue;
+                       p.get_token(); // eat '['
+                       if (need_layout) {
+                               context.check_layout(os);
+                               need_layout = false;
+                       }
+                       begin_inset(os, "Argument ");
+                       if (post)
+                               os << "post:";
+                       os << i << "\nstatus collapsed\n\n";
+                       parse_text_in_inset(p, os, FLAG_BRACK_LAST, outer, context);
+                       end_inset(os);
+               }
+               eat_whitespace(p, os, context, false);
+       }
+}
+
+
 void output_command_layout(ostream & os, Parser & p, bool outer,
                           Context & parent_context,
                           Layout const * newlayout)
@@ -634,48 +714,11 @@ void output_command_layout(ostream & os, Parser & p, bool outer,
                context.need_end_deeper = true;
        }
        context.check_deeper(os);
-       context.check_layout(os);
-       // FIXME: Adjust to format 446!
-       // Since format 446, layouts do not require anymore all optional
-       // arguments before the required ones. Needs to be implemented!
-       int optargs = 0;
-       while (optargs < context.layout->optArgs()) {
-               eat_whitespace(p, os, context, false);
-               if (p.next_token().cat() == catEscape ||
-                   p.next_token().character() != '[')
-                       break;
-               p.get_token(); // eat '['
-               // FIXME: Just a workaround. InsetArgument::updateBuffer
-               //        will compute a proper ID for all "999" Arguments
-               //        (which is also what lyx2lyx produces).
-               //        However, tex2lyx should be able to output proper IDs
-               //        itself.
-               begin_inset(os, "Argument 999\n");
-               os << "status collapsed\n\n";
-               parse_text_in_inset(p, os, FLAG_BRACK_LAST, outer, context);
-               end_inset(os);
-               eat_whitespace(p, os, context, false);
-               ++optargs;
-       }
-       int reqargs = 0;
-       while (reqargs < context.layout->requiredArgs()) {
-               eat_whitespace(p, os, context, false);
-               if (p.next_token().cat() != catBegin)
-                       break;
-               p.get_token(); // eat '{'
-               // FIXME: Just a workaround. InsetArgument::updateBuffer
-               //        will compute a proper ID for all "999" Arguments
-               //        (which is also what lyx2lyx produces).
-               //        However, tex2lyx should be able to output proper IDs
-               //        itself.
-               begin_inset(os, "Argument 999\n");
-               os << "status collapsed\n\n";
-               parse_text_in_inset(p, os, FLAG_BRACE_LAST, outer, context);
-               end_inset(os);
-               eat_whitespace(p, os, context, false);
-               ++reqargs;
-       }
+       output_arguments(os, p, outer, true, false, context,
+                        context.layout->latexargs());
        parse_text(p, os, FLAG_ITEM, outer, context);
+       output_arguments(os, p, outer, false, true, context,
+                        context.layout->postcommandargs());
        context.check_end_layout(os);
        if (parent_context.deeper_paragraph) {
                // We must suppress the "end deeper" because we
@@ -802,11 +845,12 @@ bool parse_command(string const & command, Parser & p, ostream & os,
 void parse_box(Parser & p, ostream & os, unsigned outer_flags,
                unsigned inner_flags, bool outer, Context & parent_context,
                string const & outer_type, string const & special,
-               string const & inner_type)
+               string inner_type, string const & frame_color,
+               string const & background_color)
 {
        string position;
        string inner_pos;
-       string hor_pos = "c";
+       string hor_pos = "l";
        // We need to set the height to the LaTeX default of 1\\totalheight
        // for the case when no height argument is given
        string height_value = "1";
@@ -817,6 +861,63 @@ void parse_box(Parser & p, ostream & os, unsigned outer_flags,
        string width_unit;
        string latex_width;
        string width_special = "none";
+       string thickness = "0.4pt";
+       if (!fboxrule.empty())
+               thickness = fboxrule;
+       else
+               thickness = "0.4pt";
+       string separation;
+       if (!fboxsep.empty())
+               separation = fboxsep;
+       else
+               separation = "3pt";
+       string shadowsize;
+       if (!shadow_size.empty())
+               shadowsize = shadow_size;
+       else
+               shadowsize = "4pt";
+       string framecolor = "black";
+       string backgroundcolor = "none";
+       if (!frame_color.empty())
+               framecolor = frame_color;
+       if (!background_color.empty())
+               backgroundcolor = background_color;
+       // if there is a color box around the \begin statements have not yet been parsed
+       // so do this now
+       if (!frame_color.empty() || !background_color.empty()) {
+               eat_whitespace(p, os, parent_context, false);
+               p.get_token().asInput(); // the '{'
+               // parse minipage
+               if (p.next_token().asInput() == "\\begin") {
+                       p.get_token().asInput();
+                       p.getArg('{', '}');
+                       inner_type = "minipage";
+                       inner_flags = FLAG_END;
+                       active_environments.push_back("minipage");
+               }
+               // parse parbox
+               else if (p.next_token().asInput() == "\\parbox") {
+                       p.get_token().asInput();
+                       inner_type = "parbox";
+                       inner_flags = FLAG_ITEM;
+               }
+               // parse makebox
+               else if (p.next_token().asInput() == "\\makebox") {
+                       p.get_token().asInput();
+                       inner_type = "makebox";
+                       inner_flags = FLAG_ITEM;
+               }
+               // in case there is just \colorbox{color}{text}
+               else {
+                       latex_width = "";
+                       inner_type = "makebox";
+                       inner_flags = FLAG_BRACE_LAST;
+                       position = "t";
+                       inner_pos = "t";
+               }
+       }
+       if (!p.hasOpt() && (inner_type == "makebox" || outer_type == "mbox"))
+               hor_pos = "c";
        if (!inner_type.empty() && p.hasOpt()) {
                if (inner_type != "makebox")
                        position = p.getArg('[', ']');
@@ -857,6 +958,9 @@ void parse_box(Parser & p, ostream & os, unsigned outer_flags,
                                        inner_pos = position;
                                }
                        }
+               } else {
+                       if (inner_type == "makebox")
+                               hor_pos = "c";
                }
        }
        if (inner_type.empty()) {
@@ -874,6 +978,9 @@ void parse_box(Parser & p, ostream & os, unsigned outer_flags,
                                             << " for " << outer_type << endl;
                                        hor_pos = "c";
                                }
+                       } else {
+                               if (outer_type == "framebox")
+                                       hor_pos = "c";
                        }
                }
        } else if (inner_type != "makebox")
@@ -904,9 +1011,8 @@ void parse_box(Parser & p, ostream & os, unsigned outer_flags,
        if (!outer_type.empty() && !inner_type.empty() &&
            (inner_flags & FLAG_END))
                active_environments.push_back(inner_type);
-       // LyX can't handle length variables
-       bool use_ert = contains(width_unit, '\\') || contains(height_unit, '\\');
-       if (!use_ert && !outer_type.empty() && !inner_type.empty()) {
+       bool use_ert = false;
+       if (!outer_type.empty() && !inner_type.empty()) {
                // Look whether there is some content after the end of the
                // inner box, but before the end of the outer box.
                // If yes, we need to output ERT.
@@ -925,16 +1031,7 @@ void parse_box(Parser & p, ostream & os, unsigned outer_flags,
                }
                p.popPosition();
        }
-       // if only \makebox{content} was used we can set its width to 1\width
-       // because this identic and also identic to \mbox
-       // this doesn't work for \framebox{content}, thus we have to use ERT for this
-       if (latex_width.empty() && inner_type == "makebox") {
-               width_value = "1";
-               width_unit = "in";
-               width_special = "width";
-       } else if (latex_width.empty() && outer_type == "framebox") {
-               use_ert = true;
-       }
+
        if (use_ert) {
                ostringstream ss;
                if (!outer_type.empty()) {
@@ -990,9 +1087,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 +1101,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" || !frame_color.empty())
                        os << "Boxed\n";
                else if (outer_type == "shadowbox")
                        os << "Shadowbox\n";
@@ -1018,21 +1112,49 @@ 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 if (!frame_color.empty() && inner_type == "makebox")
+                       os << "has_inner_box 0\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";
-               os << "special \"" << width_special << "\"\n";
-               os << "height \"" << height_value << height_unit << "\"\n";
+               if (outer_type == "mbox")
+                       os << "use_makebox 1\n";
+               else if (!frame_color.empty())
+                       os << "use_makebox 0\n";
+               else
+                       os << "use_makebox " << (inner_type == "makebox") << '\n';
+               if (outer_type == "mbox" || (outer_type == "fbox" && inner_type.empty()))
+                       os << "width \"\"\n";
+               // for values like "1.5\width" LyX uses "1.5in" as width ad sets "width" as sepecial
+               else if (contains(width_unit, '\\'))
+                       os << "width \"" << width_value << "in" << "\"\n";
+               else
+                       os << "width \"" << width_value << width_unit << "\"\n";
+               if (contains(width_unit, '\\')) {
+                       width_unit.erase (0,1); // remove the leading '\'
+                       os << "special \"" << width_unit << "\"\n";
+               } else
+                       os << "special \"" << width_special << "\"\n";
+               if (contains(height_unit, '\\'))
+                       os << "height \"" << height_value << "in" << "\"\n";
+               else
+                       os << "height \"" << height_value << height_unit << "\"\n";
                os << "height_special \"" << height_special << "\"\n";
+               os << "thickness \"" << thickness << "\"\n";
+               os << "separation \"" << separation << "\"\n";
+               os << "shadowsize \"" << shadowsize << "\"\n";
+               os << "framecolor \"" << framecolor << "\"\n";
+               os << "backgroundcolor \"" << backgroundcolor << "\"\n";
                os << "status open\n\n";
 
                // Unfortunately we can't use parse_text_in_inset:
@@ -1077,13 +1199,13 @@ void parse_box(Parser & p, ostream & os, unsigned outer_flags,
                // LyX puts a % after the end of the minipage
                if (p.next_token().cat() == catNewline && p.next_token().cs().size() > 1) {
                        // new paragraph
-                       //output_ert_inset(os, "%dummy", parent_context);
+                       //output_comment(p, os, "dummy", parent_context);
                        p.get_token();
                        p.skip_spaces();
                        parent_context.new_paragraph(os);
                }
                else if (p.next_token().cat() == catSpace || p.next_token().cat() == catNewline) {
-                       //output_ert_inset(os, "%dummy", parent_context);
+                       //output_comment(p, os, "dummy", parent_context);
                        p.get_token();
                        p.skip_spaces();
                        // We add a protected space if something real follows
@@ -1094,6 +1216,26 @@ void parse_box(Parser & p, ostream & os, unsigned outer_flags,
                }
 #endif
        }
+       if (inner_type == "minipage" && (!frame_color.empty() || !background_color.empty()))
+               active_environments.pop_back();
+       if (inner_flags != FLAG_BRACE_LAST && (!frame_color.empty() || !background_color.empty())) {
+               // in this case we have to eat the the closing brace of the color box
+               p.get_token().asInput(); // the '}'
+       }
+       if (p.next_token().asInput() == "}") {
+               // in this case we assume that the closing brace is from the box settings
+               // therefore reset these values for the next box
+               fboxrule = "";
+               fboxsep = "";
+               shadow_size = "";
+       }
+
+       // all boxes except of Frameless and Shaded require calc
+       if (!(outer_type.empty() || outer_type == "mbox") &&
+               !((outer_type == "shaded" && inner_type.empty()) ||
+                            (outer_type == "minipage" && inner_type == "shaded") ||
+                            (outer_type == "parbox" && inner_type == "shaded")))
+               preamble.registerAutomaticallyLoadedPackage("calc");
 }
 
 
@@ -1129,7 +1271,7 @@ 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 == "mbox") {
                // These boxes never have an inner box
                ;
        } else if (p.next_token().asInput() == "\\parbox") {
@@ -1155,14 +1297,14 @@ void parse_outer_box(Parser & p, ostream & os, unsigned flags, bool outer,
                        eat_whitespace(p, os, parent_context, false);
                }
                parse_box(p, os, flags, FLAG_END, outer, parent_context,
-                         outer_type, special, inner);
+                         outer_type, special, inner, "", "");
        } else {
                if (inner_flags == FLAG_ITEM) {
                        p.get_token();
                        eat_whitespace(p, os, parent_context, false);
                }
                parse_box(p, os, flags, inner_flags, outer, parent_context,
-                         outer_type, special, inner);
+                         outer_type, special, inner, "", "");
        }
 }
 
@@ -1299,12 +1441,12 @@ void parse_environment(Parser & p, ostream & os, bool outer,
                if (!opt.empty())
                        os << "placement " << opt << '\n';
                if (contains(opt, "H"))
-                       preamble.registerAutomaticallyLoadedPackage("float");
+                       preamble.registerAutomaticallyLoadedPackage("float");
                else {
                        Floating const & fl = parent_context.textclass.floats()
-                               .getType(unstarred_name);
-                       if (!fl.floattype().empty() && fl.usesFloatPkg())
-                               preamble.registerAutomaticallyLoadedPackage("float");
+                                             .getType(unstarred_name);
+                       if (!fl.floattype().empty() && fl.usesFloatPkg())
+                               preamble.registerAutomaticallyLoadedPackage("float");
                }
 
                os << "wide " << convert<string>(is_starred)
@@ -1397,7 +1539,7 @@ void parse_environment(Parser & p, ostream & os, bool outer,
                                        parent_context, name, "shaded");
                else
                        parse_box(p, os, 0, FLAG_END, outer, parent_context,
-                                 "", "", name);
+                                 "", "", name, "", "");
                p.skip_spaces();
        }
 
@@ -1413,15 +1555,17 @@ void parse_environment(Parser & p, ostream & os, bool outer,
                preamble.registerAutomaticallyLoadedPackage("verbatim");
        }
 
-       else if (name == "verbatim") {
+       else if (unstarred_name == "verbatim") {
                // FIXME: this should go in the generic code that
                // handles environments defined in layout file that
                // have "PassThru 1". However, the code over there is
                // already too complicated for my taste.
+               string const ascii_name =
+                       (name == "verbatim*") ? "Verbatim*" : "Verbatim";
                parent_context.new_paragraph(os);
                Context context(true, parent_context.textclass,
-                               &parent_context.textclass[from_ascii("Verbatim")]);
-               string s = p.verbatimEnvironment("verbatim");
+                               &parent_context.textclass[from_ascii(ascii_name)]);
+               string s = p.verbatimEnvironment(name);
                output_ert(os, s, context);
                p.skip_spaces();
        }
@@ -1514,10 +1658,42 @@ 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, "");
                p.skip_spaces();
+               preamble.registerAutomaticallyLoadedPackage("framed");
        }
 
        else if (name == "lstlisting") {
@@ -1588,24 +1764,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:
@@ -1622,60 +1787,16 @@ void parse_environment(Parser & p, ostream & os, bool outer,
                }
                context.check_deeper(os);
                // handle known optional and required arguments
-               // FIXME: Since format 446, layouts do not require anymore all optional
-               // arguments before the required ones. Needs to be implemented!
                // Unfortunately LyX can't handle arguments of list arguments (bug 7468):
                // It is impossible to place anything after the environment name,
                // but before the first \\item.
-               if (context.layout->latextype == LATEX_ENVIRONMENT) {
-                       bool need_layout = true;
-                       int optargs = 0;
-                       while (optargs < context.layout->optArgs()) {
-                               eat_whitespace(p, os, context, false);
-                               if (p.next_token().cat() == catEscape ||
-                                   p.next_token().character() != '[')
-                                       break;
-                               p.get_token(); // eat '['
-                               if (need_layout) {
-                                       context.check_layout(os);
-                                       need_layout = false;
-                               }
-                               // FIXME: Just a workaround. InsetArgument::updateBuffer
-                               //        will compute a proper ID for all "999" Arguments
-                               //        (which is also what lyx2lyx produces).
-                               //        However, tex2lyx should be able to output proper IDs
-                               //        itself.
-                               begin_inset(os, "Argument 999\n");
-                               os << "status collapsed\n\n";
-                               parse_text_in_inset(p, os, FLAG_BRACK_LAST, outer, context);
-                               end_inset(os);
-                               eat_whitespace(p, os, context, false);
-                               ++optargs;
-                       }
-                       int reqargs = 0;
-                       while (reqargs < context.layout->requiredArgs()) {
-                               eat_whitespace(p, os, context, false);
-                               if (p.next_token().cat() != catBegin)
-                                       break;
-                               p.get_token(); // eat '{'
-                               if (need_layout) {
-                                       context.check_layout(os);
-                                       need_layout = false;
-                               }
-                               // FIXME: Just a workaround. InsetArgument::updateBuffer
-                               //        will compute a proper ID for all "999" Arguments
-                               //        (which is also what lyx2lyx produces).
-                               //        However, tex2lyx should be able to output proper IDs
-                               //        itself.
-                               begin_inset(os, "Argument 999\n");
-                               os << "status collapsed\n\n";
-                               parse_text_in_inset(p, os, FLAG_BRACE_LAST, outer, context);
-                               end_inset(os);
-                               eat_whitespace(p, os, context, false);
-                               ++reqargs;
-                       }
-               }
+               if (context.layout->latextype == LATEX_ENVIRONMENT)
+                       output_arguments(os, p, outer, false, false, context,
+                                        context.layout->latexargs());
                parse_text(p, os, FLAG_END, outer, context);
+               if (context.layout->latextype == LATEX_ENVIRONMENT)
+                       output_arguments(os, p, outer, false, true, context,
+                                        context.layout->postcommandargs());
                context.check_end_layout(os);
                if (parent_context.deeper_paragraph) {
                        // We must suppress the "end deeper" because we
@@ -1703,7 +1824,7 @@ void parse_environment(Parser & p, ostream & os, bool outer,
                   << "status collapsed\n";
                if (newinsetlayout->isPassThru()) {
                        string const arg = p.verbatimEnvironment(name);
-                       Context context(true, parent_context.textclass, 
+                       Context context(true, parent_context.textclass,
                                        &parent_context.textclass.plainLayout(),
                                        parent_context.layout);
                        output_ert(os, arg, parent_context);
@@ -1771,7 +1892,7 @@ void parse_comment(Parser & p, ostream & os, Token const & t, Context & context)
        LASSERT(t.cat() == catComment, return);
        if (!t.cs().empty()) {
                context.check_layout(os);
-               output_ert_inset(os, '%' + t.cs(), context);
+               output_comment(p, os, t.cs(), context);
                if (p.next_token().cat() == catNewline) {
                        // A newline after a comment line starts a new
                        // paragraph
@@ -1954,7 +2075,6 @@ void copy_file(FileName const & src, string dstname)
                dst = FileName(dstname);
        else
                dst = makeAbsPath(dstname, absParent);
-       string const absMaster = getMasterFilePath(false);
        FileName const srcpath = src.onlyPath();
        FileName const dstpath = dst.onlyPath();
        if (equivalent(srcpath, dstpath))
@@ -1982,43 +2102,55 @@ void copy_file(FileName const & src, string dstname)
 }
 
 
-/// Parse a NoWeb Chunk section. The initial "<<" is already parsed.
-bool 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)
 {
        // check whether a chunk is possible here.
-       if (!context.new_layout_allowed ||
-           !context.textclass.hasLayout(from_ascii("Chunk"))) {
+       if (!context.textclass.hasInsetLayout(from_ascii("Flex:Chunk"))) {
                return false;
        }
 
        p.pushPosition();
 
        // read the parameters
-       Parser::Arg stuff = p.verbatimStuff(">>=", false);
-       if (!stuff.first) {
+       Parser::Arg const params = p.verbatimStuff(">>=\n", false);
+       if (!params.first) {
                p.popPosition();
                return false;
        }
-       string chunk = "<<" + stuff.second + ">>="
-               + p.verbatimStuff("\n").second + '\n';
 
-       stuff = p.verbatimStuff("\n@");
-       if (!stuff.first) {
+       Parser::Arg const code = p.verbatimStuff("\n@");
+       if (!code.first) {
                p.popPosition();
                return false;
        }
-       chunk += stuff.second + "\n@";
-       string post_chunk = p.verbatimStuff("\n").second + '\n';
+       string const post_chunk = p.verbatimStuff("\n").second + '\n';
        if (post_chunk[0] != ' ' && post_chunk[0] != '\n') {
                p.popPosition();
                return false;
        }
-       chunk += post_chunk;
+       // The last newline read is important for paragraph handling
+       p.putback();
+       p.deparse();
 
-       context.new_paragraph(os);
-       Context newcontext(true, context.textclass,
-               &context.textclass[from_ascii("Chunk")]);
-       output_ert(os, chunk, newcontext);
+       //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;
@@ -2171,8 +2303,6 @@ void parse_text(Parser & p, ostream & os, unsigned flags, bool outer,
        bool const use_natbib = isProvided("natbib");
        bool const use_jurabib = isProvided("jurabib");
        string last_env;
-       while (p.good()) {
-               Token const & t = p.get_token();
 
        // it is impossible to determine the correct encoding for non-CJK Japanese.
        // Therefore write a note at the beginning of the document
@@ -2196,6 +2326,8 @@ void parse_text(Parser & p, ostream & os, unsigned flags, bool outer,
                is_nonCJKJapanese = false;
        }
 
+       while (p.good()) {
+               Token const & t = p.get_token();
 #ifdef FILEDEBUG
                debugToken(cerr, t, flags);
 #endif
@@ -2231,6 +2363,8 @@ void parse_text(Parser & p, ostream & os, unsigned flags, bool outer,
                //
                // cat codes
                //
+               bool const starred = p.next_token().asInput() == "*";
+               string const starredname(starred ? (t.cs() + '*') : t.cs());
                if (t.cat() == catMath) {
                        // we are inside some text mode thingy, so opening new math is allowed
                        context.check_layout(os);
@@ -2294,16 +2428,16 @@ void parse_text(Parser & p, ostream & os, unsigned flags, bool outer,
 
                else if (t.asInput() == "<"
                         && p.next_token().asInput() == "<") {
-                       bool has_noweb = false;
+                       bool has_chunk = false;
                        if (noweb_mode) {
                                p.pushPosition();
                                p.get_token();
-                               has_noweb = parse_noweb(p, os, context);
-                               if (!has_noweb)
+                               has_chunk = parse_chunk(p, os, context);
+                               if (!has_chunk)
                                        p.popPosition();
                        }
 
-                       if (!has_noweb) {
+                       if (!has_chunk) {
                                context.check_layout(os);
                                begin_inset(os, "Quotes ");
                                //FIXME: this is a right danish quote;
@@ -2333,36 +2467,28 @@ void parse_text(Parser & p, ostream & os, unsigned flags, bool outer,
 
                else if (t.cat() == catLetter) {
                        context.check_layout(os);
-                       // Workaround for bug 4752.
-                       // FIXME: This whole code block needs to be removed
-                       //        when the bug is fixed and tex2lyx produces
-                       //        the updated file format.
-                       // The replacement algorithm in LyX is so stupid that
-                       // it even translates a phrase if it is part of a word.
-                       bool handled = false;
-                       for (int const * l = known_phrase_lengths; *l; ++l) {
-                               string phrase = t.cs();
-                               for (int i = 1; i < *l && p.next_token().isAlnumASCII(); ++i)
-                                       phrase += p.get_token().cs();
-                               if (is_known(phrase, known_coded_phrases)) {
-                                       output_ert_inset(os, phrase, context);
-                                       handled = true;
-                                       break;
-                               } else {
-                                       for (size_t i = 1; i < phrase.length(); ++i)
-                                               p.putback();
-                               }
-                       }
-                       if (!handled)
-                               os << t.cs();
+                       os << t.cs();
                }
 
                else if (t.cat() == catOther ||
                               t.cat() == catAlign ||
                               t.cat() == catParameter) {
-                       // This translates "&" to "\\&" which may be wrong...
                        context.check_layout(os);
-                       os << t.cs();
+                       if (t.asInput() == "-" && p.next_token().asInput() == "-" &&
+                           context.merging_hyphens_allowed &&
+                           context.font.family != "ttfamily" &&
+                           !context.layout->pass_thru) {
+                               if (p.next_next_token().asInput() == "-") {
+                                       // --- is emdash
+                                       os << to_utf8(docstring(1, 0x2014));
+                                       p.get_token();
+                               } else
+                                       // -- is endash
+                                       os << to_utf8(docstring(1, 0x2013));
+                               p.get_token();
+                       } else
+                               // This translates "&" to "\\&" which may be wrong...
+                               os << t.cs();
                }
 
                else if (p.isParagraph()) {
@@ -2393,10 +2519,8 @@ void parse_text(Parser & p, ostream & os, unsigned flags, bool outer,
                                // {}
                                Token const prev = p.prev_token();
                                p.get_token();
-                               if (p.next_token().character() == '`' ||
-                                   (prev.character() == '-' &&
-                                    p.next_token().character() == '-'))
-                                       ; // ignore it in {}`` or -{}-
+                               if (p.next_token().character() == '`')
+                                       ; // ignore it in {}``
                                else
                                        output_ert_inset(os, "{}", context);
                        } else if (next.cat() == catEscape &&
@@ -2425,6 +2549,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);
@@ -2523,26 +2653,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")
@@ -2585,11 +2709,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.
@@ -2605,8 +2736,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.
@@ -2708,8 +2838,8 @@ void parse_text(Parser & p, ostream & os, unsigned flags, bool outer,
                        context.check_layout(os);
                        // FIXME: This is a hack to prevent paragraph
                        // deletion if it is empty. Handle this better!
-                       output_ert_inset(os,
-                               "%dummy comment inserted by tex2lyx to "
+                       output_comment(p, os,
+                               "dummy comment inserted by tex2lyx to "
                                "ensure that this paragraph is not empty",
                                context);
                        // Both measures above may generate an additional
@@ -2779,38 +2909,10 @@ void parse_text(Parser & p, ostream & os, unsigned flags, bool outer,
                                preamble.registerAutomaticallyLoadedPackage(*it);
                }
 
-               else if (t.cs() == "caption") {
-                       p.skip_spaces();
-                       context.check_layout(os);
-                       p.skip_spaces();
-                       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
-                       //       (for captions, but also for others)
-                       if (p.next_token().cat() != catEscape &&
-                           p.next_token().character() == '[') {
-                               p.get_token(); // eat '['
-                               begin_inset(os, "Argument 1\n");
-                               os << "status collapsed\n";
-                               parse_text_in_inset(p, os, FLAG_BRACK_LAST, outer, context);
-                               end_inset(os);
-                               eat_whitespace(p, os, context, false);
-                       }
-                       parse_text(p, os, FLAG_ITEM, outer, context);
-                       context.check_end_layout(os);
-                       // We don't need really a new paragraph, but
-                       // we must make sure that the next item gets a \begin_layout.
-                       context.new_paragraph(os);
-                       end_inset(os);
-                       p.skip_spaces();
-                       newcontext.check_end_layout(os);
-               }
-
                else if (t.cs() == "subfloat") {
-                       // the syntax is \subfloat[caption]{content}
+                       // the syntax is \subfloat[list entry][sub caption]{content}
                        // if it is a table of figure depends on the surrounding float
-                       bool has_caption = false;
+                       // FIXME: second optional argument is not parsed
                        p.skip_spaces();
                        // do nothing if there is no outer float
                        if (!float_type.empty()) {
@@ -2822,6 +2924,7 @@ void parse_text(Parser & p, ostream & os, unsigned flags, bool outer,
                                   << "\nstatus collapsed\n\n";
                                // test for caption
                                string caption;
+                               bool has_caption = false;
                                if (p.next_token().cat() != catEscape &&
                                                p.next_token().character() == '[') {
                                                        p.get_token(); // eat '['
@@ -3084,16 +3187,12 @@ void parse_text(Parser & p, ostream & os, unsigned flags, bool outer,
                                preamble.registerAutomaticallyLoadedPackage("listings");
                }
 
-               else if (t.cs() == "listoffigures") {
+               else if (t.cs() == "listoffigures" || t.cs() == "listoftables") {
                        context.check_layout(os);
-                       begin_inset(os, "FloatList figure\n");
-                       end_inset(os);
-                       skip_spaces_braces(p);
-               }
-
-               else if (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);
                }
@@ -3145,7 +3244,7 @@ void parse_text(Parser & p, ostream & os, unsigned flags, bool outer,
                else if (t.cs() == "textcolor") {
                        // scheme is \textcolor{color name}{text}
                        string const color = p.verbatim_item();
-                       // we only support the predefined colors of the color package
+                       // we support the predefined colors of the color  and the xcolor package
                        if (color == "black" || color == "blue" || color == "cyan"
                                || color == "green" || color == "magenta" || color == "red"
                                || color == "white" || color == "yellow") {
@@ -3155,6 +3254,16 @@ void parse_text(Parser & p, ostream & os, unsigned flags, bool outer,
                                        context.check_layout(os);
                                        os << "\n\\color inherit\n";
                                        preamble.registerAutomaticallyLoadedPackage("color");
+                       } else if (color == "brown" || color == "darkgray" || color == "gray"
+                               || color == "lightgray" || color == "lime" || color == "olive"
+                               || color == "orange" || color == "pink" || color == "purple"
+                               || color == "teal" || color == "violet") {
+                                       context.check_layout(os);
+                                       os << "\n\\color " << color << "\n";
+                                       parse_text_snippet(p, os, FLAG_ITEM, outer, context);
+                                       context.check_layout(os);
+                                       os << "\n\\color inherit\n";
+                                       preamble.registerAutomaticallyLoadedPackage("xcolor");
                        } else
                                // for custom defined colors
                                output_ert_inset(os, t.asInput() + "{" + color + "}", context);
@@ -3240,7 +3349,10 @@ void parse_text(Parser & p, ostream & os, unsigned flags, bool outer,
                else if (t.cs() == "textipa") {
                        context.check_layout(os);
                        begin_inset(os, "IPA\n");
+                       bool merging_hyphens_allowed = context.merging_hyphens_allowed;
+                       context.merging_hyphens_allowed = false;
                        parse_text_in_inset(p, os, FLAG_ITEM, outer, context);
+                       context.merging_hyphens_allowed = merging_hyphens_allowed;
                        end_inset(os);
                        preamble.registerAutomaticallyLoadedPackage("tipa");
                        preamble.registerAutomaticallyLoadedPackage("tipx");
@@ -3255,34 +3367,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" ) {
@@ -3304,11 +3393,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);
@@ -3393,54 +3483,13 @@ void parse_text(Parser & p, ostream & os, unsigned flags, bool outer,
                        end_inset(os);
                }
 
-               else if (is_known(t.cs(), known_phrases) ||
-                        (t.cs() == "protect" &&
-                         p.next_token().cat() == catEscape &&
-                         is_known(p.next_token().cs(), known_phrases))) {
-                       // LyX sometimes puts a \protect in front, so we have to ignore it
-                       // FIXME: This needs to be changed when bug 4752 is fixed.
-                       where = is_known(
-                               t.cs() == "protect" ? p.get_token().cs() : t.cs(),
-                               known_phrases);
-                       context.check_layout(os);
-                       os << known_coded_phrases[where - known_phrases];
-                       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]
@@ -3451,6 +3500,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" &&
@@ -3677,7 +3750,8 @@ void parse_text(Parser & p, ostream & os, unsigned flags, bool outer,
                        context.check_layout(os);
                        begin_inset(os, "script ");
                        os << t.cs().substr(4) << '\n';
-                       parse_text_in_inset(p, os, FLAG_ITEM, false, context);
+                       newinsetlayout = findInsetLayout(context.textclass, t.cs(), true);
+                       parse_text_in_inset(p, os, FLAG_ITEM, false, context, newinsetlayout);
                        end_inset(os);
                        if (t.cs() == "textsubscript")
                                preamble.registerAutomaticallyLoadedPackage("subscript");
@@ -3784,7 +3858,7 @@ void parse_text(Parser & p, ostream & os, unsigned flags, bool outer,
                                              context.font.language, lang);
                }
 
-               else if (prefixIs(t.cs(), "text")
+               else if (prefixIs(t.cs(), "text") && preamble.usePolyglossia()
                         && is_known(t.cs().substr(4), preamble.polyglossia_languages)) {
                        // scheme is \textLANGUAGE{text} where LANGUAGE is in polyglossia_languages[]
                        string lang;
@@ -3820,17 +3894,31 @@ void parse_text(Parser & p, ostream & os, unsigned flags, bool outer,
                        p.setEncoding(enc, Encoding::inputenc);
                }
 
-               else if ((where = is_known(t.cs(), known_special_chars))) {
+               else if (is_known(t.cs(), known_special_chars) ||
+                        (t.cs() == "protect" &&
+                         p.next_token().cat() == catEscape &&
+                         is_known(p.next_token().cs(), known_special_protect_chars))) {
+                       // LyX sometimes puts a \protect in front, so we have to ignore it
+                       where = is_known(
+                               t.cs() == "protect" ? p.get_token().cs() : 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() == "protect" && p.next_token().asInput() == "\\nobreakdash" &&
+                         p.next_next_token().asInput() == "-") ||
+                        (t.cs() == "@" && p.next_token().asInput() == ".")) {
+                       // LyX sometimes puts a \protect in front, so we have to ignore it
+                       if (t.cs() == "protect")
+                               p.get_token();
                        context.check_layout(os);
-                       os << "\\SpecialChar \\nobreakdash-\n";
+                       if (t.cs() == "nobreakdash")
+                               os << "\\SpecialChar nobreakdash\n";
+                       else
+                               os << "\\SpecialChar endofsentence\n";
                        p.get_token();
                }
 
@@ -3840,40 +3928,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 softhyphen\n";
+                       else
+                               os << t.cs();
                }
 
                else if (t.cs() == "char") {
@@ -3899,7 +3961,7 @@ void parse_text(Parser & p, ostream & os, unsigned flags, bool outer,
                        string delim = p.get_token().asInput();
                        Parser::Arg arg = p.verbatimStuff(delim);
                        if (arg.first)
-                               output_ert_inset(os, "\\verb" + delim 
+                               output_ert_inset(os, "\\verb" + delim
                                                 + arg.second + delim, context);
                        else
                                cerr << "invalid \\verb command. Skipping" << endl;
@@ -3911,33 +3973,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())
@@ -3993,8 +4028,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;
@@ -4157,7 +4192,7 @@ void parse_text(Parser & p, ostream & os, unsigned flags, bool outer,
                                // \nocite{*} option
                                btprint.clear();
                        }
-                       os << "bibfiles " << '"' << p.verbatim_item() << '"' << "\n";
+                       os << "bibfiles " << '"' << normalize_filename(p.verbatim_item()) << '"' << "\n";
                        // Do we have addcontentsline?
                        if (contentslineContent == "\\refname") {
                                BibOpts = "bibtotoc";
@@ -4167,9 +4202,9 @@ void parse_text(Parser & p, ostream & os, unsigned flags, bool outer,
                        // Do we have a bibliographystyle set?
                        if (!bibliographystyle.empty()) {
                                if (BibOpts.empty())
-                                       BibOpts = bibliographystyle;
+                                       BibOpts = normalize_filename(bibliographystyle);
                                else
-                                       BibOpts = BibOpts + ',' + bibliographystyle;
+                                       BibOpts = BibOpts + ',' + normalize_filename(bibliographystyle);
                                // clear it because each bibtex entry has its style
                                // and we need an empty string to handle \phantomsection
                                bibliographystyle.clear();
@@ -4205,13 +4240,60 @@ void parse_text(Parser & p, ostream & os, unsigned flags, bool outer,
                                                context, "parbox", "shaded");
                        } else
                                parse_box(p, os, 0, FLAG_ITEM, outer, context,
-                                         "", "", t.cs());
+                                         "", "", 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(), "");
 
+               else if (t.cs() == "fcolorbox" || t.cs() == "colorbox") {
+                       string backgroundcolor;
+                       preamble.registerAutomaticallyLoadedPackage("xcolor");
+                       if (t.cs() == "fcolorbox") {
+                               string const framecolor = p.getArg('{', '}');
+                               backgroundcolor = p.getArg('{', '}');
+                               parse_box(p, os, 0, 0, outer, context, "", "", "", framecolor, backgroundcolor);
+                       } else {
+                               backgroundcolor = p.getArg('{', '}');
+                               parse_box(p, os, 0, 0, outer, context, "", "", "", "", backgroundcolor);
+                       }
+               }
+
+               // FIXME: due to the compiler limit of "if" nestings
+               // the code for the alignment was put here
+               // put them in their own if if this is fixed
+               else if (t.cs() == "fboxrule" || t.cs() == "fboxsep"
+                            || t.cs() == "shadowsize"
+                                || t.cs() == "raggedleft" || t.cs() == "centering"
+                        || t.cs() == "raggedright") {
+                       if (t.cs() == "fboxrule")
+                               fboxrule = "";
+                       if (t.cs() == "fboxsep")
+                               fboxsep = "";
+                       if (t.cs() == "shadowsize")
+                               shadow_size = "";
+                       if (t.cs() != "raggedleft" && t.cs() != "centering"
+                        && t.cs() != "raggedright") {
+                               p.skip_spaces(true);
+                               while (p.good() && p.next_token().cat() != catSpace
+                                      && p.next_token().cat() != catNewline
+                                      && p.next_token().cat() != catEscape) {
+                                       if (t.cs() == "fboxrule")
+                                               fboxrule = fboxrule + p.get_token().asInput();
+                                       if (t.cs() == "fboxsep")
+                                               fboxsep = fboxsep + p.get_token().asInput();
+                                       if (t.cs() == "shadowsize")
+                                               shadow_size = shadow_size + p.get_token().asInput();
+                               }
+                       } else {
+                               output_ert_inset(os, t.asInput(), context);
+                       }
+               }
+
+               //\framebox() is part of the picture environment and different from \framebox{}
+               //\framebox{} will be parsed by parse_outer_box
                else if (t.cs() == "framebox") {
                        if (p.next_token().character() == '(') {
                                //the syntax is: \framebox(x,y)[position]{content}
@@ -4223,18 +4305,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);
                        }
                }
 
@@ -4253,7 +4328,7 @@ void parse_text(Parser & p, ostream & os, unsigned flags, bool outer,
                        } else
                                //the syntax is: \makebox[width][position]{content}
                                parse_box(p, os, 0, FLAG_ITEM, outer, context,
-                                         "", "", t.cs());
+                                         "", "", t.cs(), "", "");
                }
 
                else if (t.cs() == "smallskip" ||
@@ -4369,11 +4444,8 @@ void parse_text(Parser & p, ostream & os, unsigned flags, bool outer,
                }
 
                else if (t.cs() == "hspace" || t.cs() == "vspace") {
-                       bool starred = false;
-                       if (p.next_token().asInput() == "*") {
+                       if (starred)
                                p.get_token();
-                               starred = true;
-                       }
                        string name = t.asInput();
                        string const length = p.verbatim_item();
                        string unit;
@@ -4427,13 +4499,41 @@ void parse_text(Parser & p, ostream & os, unsigned flags, bool outer,
                                        case Length::MU:
                                                known_unit = true;
                                                break;
-                                       default:
+                                       default: {
+                                               //unitFromString(unit) fails for relative units like Length::PCW
+                                               // therefore handle them separately
+                                               if (unit == "\\paperwidth" || unit == "\\columnwidth"
+                                                       || unit == "\\textwidth" || unit == "\\linewidth"
+                                                       || unit == "\\textheight" || unit == "\\paperheight")
+                                                       known_unit = true;
                                                break;
+                                                        }
                                        }
                                }
                        }
 
-                       if (t.cs()[0] == 'h' && (known_unit || known_hspace)) {
+                       // check for glue lengths
+                       bool is_gluelength = false;
+                       string gluelength = length;
+                       string::size_type i = length.find(" minus");
+                       if (i == string::npos) {
+                               i = length.find(" plus");
+                               if (i != string::npos)
+                                       is_gluelength = true;
+                       } else
+                               is_gluelength = true;
+                       // if yes transform "9xx minus 8yy plus 7zz"
+                       // to "9xx-8yy+7zz"
+                       if (is_gluelength) {
+                               i = gluelength.find(" minus");
+                               if (i != string::npos)
+                                       gluelength.replace(i, 7, "-");
+                               i = gluelength.find(" plus");
+                               if (i != string::npos)
+                                       gluelength.replace(i, 6, "+");
+                       }
+
+                       if (t.cs()[0] == 'h' && (known_unit || known_hspace || is_gluelength)) {
                                // Literal horizontal length or known variable
                                context.check_layout(os);
                                begin_inset(os, "space ");
@@ -4445,16 +4545,20 @@ void parse_text(Parser & p, ostream & os, unsigned flags, bool outer,
                                        os << unit;
                                os << "}";
                                if (known_unit && !known_hspace)
-                                       os << "\n\\length "
-                                          << translate_len(length);
+                                       os << "\n\\length " << translate_len(length);
+                               if (is_gluelength)
+                                       os << "\n\\length " << gluelength;
                                end_inset(os);
-                       } else if (known_unit || known_vspace) {
+                       } else if (known_unit || known_vspace || is_gluelength) {
                                // Literal vertical length or known variable
                                context.check_layout(os);
                                begin_inset(os, "VSpace ");
-                               if (known_unit)
-                                       os << value;
-                               os << unit;
+                               if (known_vspace)
+                                       os << unit;
+                               if (known_unit && !known_vspace)
+                                       os << translate_len(length);
+                               if (is_gluelength)
+                                       os << gluelength;
                                if (starred)
                                        os << '*';
                                end_inset(os);
@@ -4475,12 +4579,21 @@ void parse_text(Parser & p, ostream & os, unsigned flags, bool outer,
                }
 
                // The single '=' is meant here.
-               else if ((newinsetlayout = findInsetLayout(context.textclass, t.cs(), true))) {
+               else if ((newinsetlayout = findInsetLayout(context.textclass, starredname, true))) {
+                       if (starred)
+                               p.get_token();
                        p.skip_spaces();
                        context.check_layout(os);
-                       begin_inset(os, "Flex ");
-                       os << to_utf8(newinsetlayout->name()) << '\n'
-                          << "status collapsed\n";
+                       docstring const name = newinsetlayout->name();
+                       bool const caption = name.find(from_ascii("Caption:")) == 0;
+                       if (caption) {
+                               begin_inset(os, "Caption ");
+                               os << to_utf8(name.substr(8)) << '\n';
+                       } else {
+                               begin_inset(os, "Flex ");
+                               os << to_utf8(name) << '\n'
+                                  << "status collapsed\n";
+                       }
                        if (newinsetlayout->isPassThru()) {
                                // set catcodes to verbatim early, just in case.
                                p.setCatcodes(VERBATIM_CATCODES);
@@ -4494,8 +4607,9 @@ void parse_text(Parser & p, ostream & os, unsigned flags, bool outer,
                                        newcontext.layout = &context.textclass.plainLayout();
                                output_ert(os, arg, newcontext);
                        } else
-                               
                                parse_text_in_inset(p, os, FLAG_ITEM, false, context, newinsetlayout);
+                       if (caption)
+                               p.skip_spaces();
                        end_inset(os);
                }
 
@@ -4610,15 +4724,13 @@ 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")
+                       // handle the dingbats, cyrillic and greek
+                       if (name == "\\ding" || name == "\\textcyr" ||
+                           (name == "\\textgreek" && !preamble.usePolyglossia()))
                                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 + '}';
@@ -4626,84 +4738,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";
+                       else if (preamble.isPackageUsed("tipa")) {
+                               if (name == "\\textglobfall") {
+                                       name = "End";
                                        skip_braces(p);
-                               }
-                               if (p.next_token().asInput() == "d") {
+                               } 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 = "\\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";
-                                       skip_braces(p);
-                               }
-                               if (p.next_token().asInput() == "j") {
-                                       p.get_token();
-                                       name = "\\texthtbardotlessj";
-                                       skip_braces(p);
-                               }
-                               if (p.next_token().asInput() == "o") {
-                                       p.get_token();
-                                       name = "\\textbullseye";
+                                       name = "\\textsubbar";
+                               } 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
-                       docstring s = encodings.fromLaTeXCommand(from_utf8(name),
-                                       Encodings::TEXT_CMD, termination, rem, &req);
+                       bool termination;
+                       docstring rem;
+                       set<string> req;
+                       docstring s = normalize_c(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)
@@ -4723,14 +4850,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);
                        }
                }