]> git.lyx.org Git - lyx.git/blobdiff - src/tex2lyx/text.cpp
Some more oxygen svg icon fixes
[lyx.git] / src / tex2lyx / text.cpp
index 7bb0a3fe309a401c4ff6b1b1d9f392f6e0a109a0..68f4ec9dd051086b5beec66cee8d68240fef63b0 100644 (file)
@@ -47,7 +47,7 @@ namespace lyx {
 
 namespace {
 
-void output_arguments(ostream &, Parser &, bool, Context &,
+void output_arguments(ostream &, Parser &, bool, bool, bool, Context &,
                       Layout::LaTeXArgMap const &);
 
 }
@@ -64,8 +64,12 @@ void parse_text_in_inset(Parser & p, ostream & os, unsigned flags, bool outer,
        else
                newcontext.font = context.font;
        if (layout)
-               output_arguments(os, p, outer, newcontext, layout->latexargs());
+               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);
 }
 
@@ -245,12 +249,20 @@ char const * const known_coded_font_shapes[] = { "italic", "slanted",
 /// Known special characters which need skip_spaces_braces() afterwards
 char const * const known_special_chars[] = {"ldots",
 "lyxarrow", "textcompwordmark",
-"slash", "textasciitilde", "textasciicircum", "textbackslash", 0};
+"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[] = {"\\SpecialChar \\ldots{}\n",
 "\\SpecialChar \\menuseparator\n", "\\SpecialChar \\textcompwordmark{}\n",
-"\\SpecialChar \\slash{}\n", "~", "^", "\n\\backslash\n", 0};
+"\\SpecialChar \\slash{}\n", "~", "^", "\n\\backslash\n",
+"\\SpecialChar \\LyX\n", "\\SpecialChar \\TeX\n", "\\SpecialChar \\LaTeXe\n",
+"\\SpecialChar \\LaTeX\n", 0};
 
 /*!
  * Graphics file extensions known by the dvips driver of the graphics package.
@@ -291,12 +303,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",
@@ -623,10 +629,14 @@ void skip_spaces_braces(Parser & p, bool keepws = false)
 }
 
 
-void output_arguments(ostream & os, Parser & p, bool outer, Context & context,
-                      Layout::LaTeXArgMap const & latexargs)
+void output_arguments(ostream & os, Parser & p, bool outer, bool need_layout, bool post,
+                      Context & context, Layout::LaTeXArgMap const & latexargs)
 {
-       context.check_layout(os);
+       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();
@@ -637,7 +647,13 @@ void output_arguments(ostream & os, Parser & p, bool outer, Context & context,
                        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);
@@ -646,7 +662,13 @@ void output_arguments(ostream & os, Parser & p, bool outer, Context & context,
                            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);
@@ -679,8 +701,11 @@ void output_command_layout(ostream & os, Parser & p, bool outer,
                context.need_end_deeper = true;
        }
        context.check_deeper(os);
-       output_arguments(os, p, outer, context, context.layout->latexargs());
+       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
@@ -1656,60 +1681,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
@@ -2381,36 +2362,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()) {
@@ -2441,10 +2414,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 &&
@@ -2834,8 +2805,9 @@ void parse_text(Parser & p, ostream & os, unsigned flags, bool outer,
                }
 
                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
+                       // FIXME: second optional argument is not parsed
                        bool has_caption = false;
                        p.skip_spaces();
                        // do nothing if there is no outer float
@@ -3262,7 +3234,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");
@@ -3393,20 +3368,6 @@ 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);
-               }
-
                // 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
@@ -3674,7 +3635,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");
@@ -3781,7 +3743,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;
@@ -3817,14 +3779,26 @@ 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 << known_coded_special_chars[where - known_special_chars];
                        skip_spaces_braces(p);
                }
 
                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 \\" << t.cs()
                           << p.get_token().asInput() << '\n';
@@ -4587,8 +4561,9 @@ void parse_text(Parser & p, ostream & os, unsigned flags, bool outer,
                        // Only use text mode commands, since we are in text mode here,
                        // and math commands may be invalid (bug 6797)
                        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
                        else if (name == "\\textifsymbol") {