X-Git-Url: https://git.lyx.org/gitweb/?a=blobdiff_plain;f=src%2Ftex2lyx%2Ftext.cpp;h=2b5d0acb0bcce21293a0d124c28f565ea8ae7167;hb=55a3dd7b346d29a52ba305a4558e9e380ef50f47;hp=1886c08956895b135828f3336b06389c4a9b3258;hpb=2a216184c406228c665ef489cf454dee5bfaf252;p=lyx.git diff --git a/src/tex2lyx/text.cpp b/src/tex2lyx/text.cpp index 1886c08956..2b5d0acb0b 100644 --- a/src/tex2lyx/text.cpp +++ b/src/tex2lyx/text.cpp @@ -163,7 +163,12 @@ char const * const known_old_font_families[] = { "rm", "sf", "tt", 0}; char const * const known_font_families[] = { "rmfamily", "sffamily", "ttfamily", 0}; -/// the same as known_old_font_families and known_font_families with .lyx names +/// LaTeX names for font family changing commands +char const * const known_text_font_families[] = { "textrm", "textsf", +"texttt", 0}; + +/// The same as known_old_font_families, known_font_families and +/// known_text_font_families with .lyx names char const * const known_coded_font_families[] = { "roman", "sans", "typewriter", 0}; @@ -173,7 +178,11 @@ char const * const known_old_font_series[] = { "bf", 0}; /// LaTeX names for font series char const * const known_font_series[] = { "bfseries", "mdseries", 0}; -/// the same as known_old_font_series and known_font_series with .lyx names +/// LaTeX names for font series changing commands +char const * const known_text_font_series[] = { "textbf", "textmd", 0}; + +/// The same as known_old_font_series, known_font_series and +/// known_text_font_series with .lyx names char const * const known_coded_font_series[] = { "bold", "medium", 0}; /// LaTeX 2.09 names for font shapes @@ -183,10 +192,23 @@ char const * const known_old_font_shapes[] = { "it", "sl", "sc", 0}; char const * const known_font_shapes[] = { "itshape", "slshape", "scshape", "upshape", 0}; -/// the same as known_old_font_shapes and known_font_shapes with .lyx names +/// LaTeX names for font shape changing commands +char const * const known_text_font_shapes[] = { "textit", "textsl", "textsc", +"textup", 0}; + +/// The same as known_old_font_shapes, known_font_shapes and +/// known_text_font_shapes with .lyx names 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}; + +/// the same as known_special_chars with .lyx names +char const * const known_coded_special_chars[] = {"ldots{}", "menuseparator", +"textcompwordmark{}", "slash{}", 0}; + /*! * Graphics file extensions known by the dvips driver of the graphics package. * These extensions are used to complete the filename of an included @@ -433,8 +455,11 @@ docstring convert_unicodesymbols(docstring s) } s = s.substr(i); docstring rem; - docstring parsed = encodings.fromLaTeXCommand(s, rem, - Encodings::TEXT_CMD); + set req; + docstring parsed = encodings.fromLaTeXCommand(s, + Encodings::TEXT_CMD, rem, &req); + for (set::const_iterator it = req.begin(); it != req.end(); it++) + preamble.registerAutomaticallyLoadedPackage(*it); os << parsed; s = rem; if (s.empty() || s[0] != '\\') @@ -674,10 +699,14 @@ void parse_arguments(string const & command, for (size_t i = 0; i < no_arguments; ++i) { switch (template_arguments[i]) { case required: + case req_group: // This argument contains regular LaTeX handle_ert(os, ert + '{', context); eat_whitespace(p, os, context, false); - parse_text(p, os, FLAG_ITEM, outer, context); + if (template_arguments[i] == required) + parse_text(p, os, FLAG_ITEM, outer, context); + else + parse_text_snippet(p, os, FLAG_ITEM, outer, context); ert = "}"; break; case item: @@ -689,11 +718,13 @@ void parse_arguments(string const & command, else ert += p.verbatim_item(); break; + case displaymath: case verbatim: // This argument may contain special characters ert += '{' + p.verbatim_item() + '}'; break; case optional: + case opt_group: // true because we must not eat whitespace // if an optional arg follows we must not strip the // brackets from this one @@ -1157,6 +1188,12 @@ void parse_environment(Parser & p, ostream & os, bool outer, parse_math(p, os, FLAG_END, MATH_MODE); os << "\\end{" << name << "}"; end_inset(os); + if (is_display_math_env(name)) { + // 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, parent_context, false); + } } else if (unstarred_name == "tabular" || name == "longtable") { @@ -1174,6 +1211,8 @@ void parse_environment(Parser & p, ostream & os, bool outer, } else if (parent_context.textclass.floats().typeExist(unstarred_name)) { + eat_whitespace(p, os, parent_context, false); + string const opt = p.hasOpt() ? p.getArg('[', ']') : string(); eat_whitespace(p, os, parent_context, false); parent_context.check_layout(os); begin_inset(os, "Float " + unstarred_name + "\n"); @@ -1185,8 +1224,17 @@ void parse_environment(Parser & p, ostream & os, bool outer, float_type = unstarred_name; else float_type = ""; - if (p.hasOpt()) - os << "placement " << p.getArg('[', ']') << '\n'; + if (!opt.empty()) + os << "placement " << opt << '\n'; + if (contains(opt, "H")) + preamble.registerAutomaticallyLoadedPackage("float"); + else { + Floating const & fl = parent_context.textclass.floats() + .getType(unstarred_name); + if (!fl.floattype().empty() && fl.usesFloatPkg()) + preamble.registerAutomaticallyLoadedPackage("float"); + } + os << "wide " << convert(is_starred) << "\nsideways false" << "\nstatus open\n\n"; @@ -1217,6 +1265,7 @@ void parse_environment(Parser & p, ostream & os, bool outer, // we must make sure that the next item gets a \begin_layout. parent_context.new_paragraph(os); p.skip_spaces(); + preamble.registerAutomaticallyLoadedPackage("rotfloat"); } else if (name == "wrapfigure" || name == "wraptable") { @@ -1249,6 +1298,7 @@ void parse_environment(Parser & p, ostream & os, bool outer, // we must make sure that the next item gets a \begin_layout. parent_context.new_paragraph(os); p.skip_spaces(); + preamble.registerAutomaticallyLoadedPackage("wrapfig"); } else if (name == "minipage") { @@ -1288,6 +1338,7 @@ void parse_environment(Parser & p, ostream & os, bool outer, end_inset(os); p.skip_spaces(); skip_braces(p); // eat {} that might by set by LyX behind comments + preamble.registerAutomaticallyLoadedPackage("verbatim"); } else if (name == "lyxgreyedout") { @@ -1350,12 +1401,16 @@ void parse_environment(Parser & p, ostream & os, bool outer, parent_context.add_extra_stuff("\\align center\n"); else if (name == "singlespace") parent_context.add_extra_stuff("\\paragraph_spacing single\n"); - else if (name == "onehalfspace") + else if (name == "onehalfspace") { parent_context.add_extra_stuff("\\paragraph_spacing onehalf\n"); - else if (name == "doublespace") + preamble.registerAutomaticallyLoadedPackage("setspace"); + } else if (name == "doublespace") { parent_context.add_extra_stuff("\\paragraph_spacing double\n"); - else if (name == "spacing") + preamble.registerAutomaticallyLoadedPackage("setspace"); + } else if (name == "spacing") { parent_context.add_extra_stuff("\\paragraph_spacing other " + p.verbatim_item() + "\n"); + preamble.registerAutomaticallyLoadedPackage("setspace"); + } parse_text(p, os, FLAG_END, outer, parent_context); // Just in case the environment is empty parent_context.extra_stuff.erase(); @@ -1467,6 +1522,9 @@ void parse_environment(Parser & p, ostream & os, bool outer, p.skip_spaces(); if (!title_layout_found) title_layout_found = newlayout->intitle; + set const & req = newlayout->requires(); + for (set::const_iterator it = req.begin(); it != req.end(); it++) + preamble.registerAutomaticallyLoadedPackage(*it); } // The single '=' is meant here. @@ -1849,6 +1907,7 @@ void parse_text(Parser & p, ostream & os, unsigned flags, bool outer, { Layout const * newlayout = 0; InsetLayout const * newinsetlayout = 0; + char const * const * where = 0; // Store the latest bibliographystyle and nocite{*} option // (needed for bibtex inset) string btprint; @@ -1900,7 +1959,8 @@ void parse_text(Parser & p, ostream & os, unsigned flags, bool outer, context.check_layout(os); begin_inset(os, "Formula "); Token const & n = p.get_token(); - if (n.cat() == catMath && outer) { + bool const display(n.cat() == catMath && outer); + if (display) { // TeX's $$...$$ syntax for displayed math os << "\\["; parse_math(p, os, FLAG_SIMPLE, MATH_MODE); @@ -1914,6 +1974,12 @@ void parse_text(Parser & p, ostream & os, unsigned flags, bool outer, os << '$'; } end_inset(os); + if (display) { + // 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.cat() == catSuper || t.cat() == catSub) @@ -2035,8 +2101,10 @@ void parse_text(Parser & p, ostream & os, unsigned flags, bool outer, os << t.cs(); } - else if (t.cat() == catBegin && - p.next_token().cat() == catEnd) { + else if (t.cat() == catBegin) { + Token const next = p.next_token(); + Token const end = p.next_next_token(); + if (next.cat() == catEnd) { // {} Token const prev = p.prev_token(); p.get_token(); @@ -2046,14 +2114,19 @@ void parse_text(Parser & p, ostream & os, unsigned flags, bool outer, ; // ignore it in {}`` or -{}- else handle_ert(os, "{}", context); - - } - - else if (t.cat() == catBegin) { + } else if (next.cat() == catEscape && + is_known(next.cs(), known_quotes) && + end.cat() == catEnd) { + // Something like {\textquoteright} (e.g. + // from writer2latex). LyX writes + // \textquoteright{}, so we may skip the + // braces here for better readability. + parse_text_snippet(p, os, FLAG_BRACE_LAST, + outer, context); + } else { context.check_layout(os); // special handling of font attribute changes Token const prev = p.prev_token(); - Token const next = p.next_token(); TeXFont const oldFont = context.font; if (next.character() == '[' || next.character() == ']' || @@ -2126,6 +2199,7 @@ void parse_text(Parser & p, ostream & os, unsigned flags, bool outer, parse_text_snippet(p, os, FLAG_BRACE_LAST, outer, context); handle_ert(os, "}", context); + } } } @@ -2160,6 +2234,10 @@ void parse_text(Parser & p, ostream & os, unsigned flags, bool outer, parse_math(p, os, FLAG_EQUATION, MATH_MODE); os << "\\]"; 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); } else if (t.cs() == "begin") @@ -2185,7 +2263,8 @@ void parse_text(Parser & p, ostream & os, unsigned flags, bool outer, // FIXME: This swallows comments, but we cannot use // eat_whitespace() since we must not output // anything before the item. - s = p.getArg('[', ']'); + p.skip_spaces(true); + s = p.verbatimOption(); } else p.skip_spaces(false); context.set_item(); @@ -2235,7 +2314,8 @@ void parse_text(Parser & p, ostream & os, unsigned flags, bool outer, else if (t.cs() == "bibitem") { context.set_item(); context.check_layout(os); - string label = convert_command_inset_arg(p.getArg('[', ']')); + eat_whitespace(p, os, context, false); + string label = convert_command_inset_arg(p.verbatimOption()); string key = convert_command_inset_arg(p.verbatim_item()); if (contains(label, '\\') || contains(key, '\\')) { // LyX can't handle LaTeX commands in labels or keys @@ -2250,8 +2330,65 @@ void parse_text(Parser & p, ostream & os, unsigned flags, bool outer, } } - else if (is_macro(p)) - parse_macro(p, os, context); + else if (is_macro(p)) { + // catch the case of \def\inputGnumericTable + bool macro = true; + if (t.cs() == "def") { + Token second = p.next_token(); + if (second.cs() == "inputGnumericTable") { + p.pushPosition(); + p.get_token(); + skip_braces(p); + Token third = p.get_token(); + p.popPosition(); + if (third.cs() == "input") { + p.get_token(); + skip_braces(p); + p.get_token(); + string name = normalize_filename(p.verbatim_item()); + string const path = getMasterFilePath(); + // We want to preserve relative / absolute filenames, + // therefore path is only used for testing + // The file extension is in every case ".tex". + // So we need to remove this extension and check for + // the original one. + name.erase(name.length() - 4, name.length()); + if (!makeAbsPath(name, path).exists()) { + char const * const Gnumeric_formats[] = {"gnumeric" + "ods", "xls", 0}; + string const Gnumeric_name = + find_file(name, path, Gnumeric_formats); + if (!Gnumeric_name.empty()) + name = Gnumeric_name; + } + if (makeAbsPath(name, path).exists()) + fix_relative_filename(name); + else + cerr << "Warning: Could not find file '" + << name << "'." << endl; + context.check_layout(os); + begin_inset(os, "External\n\ttemplate "); + os << "GnumericSpreadsheet\n\tfilename " + << name << "\n"; + end_inset(os); + context.check_layout(os); + macro = false; + // register the packages that are automatically reloaded + // by the Gnumeric template + // Fixme: InsetExternal.cpp should give us that list + preamble.registerAutomaticallyLoadedPackage("array"); + preamble.registerAutomaticallyLoadedPackage("calc"); + preamble.registerAutomaticallyLoadedPackage("color"); + preamble.registerAutomaticallyLoadedPackage("hhline"); + preamble.registerAutomaticallyLoadedPackage("ifthen"); + preamble.registerAutomaticallyLoadedPackage("longtable"); + preamble.registerAutomaticallyLoadedPackage("multirow"); + } + } + } + if (macro) + parse_macro(p, os, context); + } else if (t.cs() == "noindent") { p.skip_spaces(); @@ -2297,6 +2434,10 @@ void parse_text(Parser & p, ostream & os, unsigned flags, bool outer, p.skip_spaces(); if (!title_layout_found) title_layout_found = newlayout->intitle; + set const & req = newlayout->requires(); + for (set::const_iterator it = req.begin(); + it != req.end(); it++) + preamble.registerAutomaticallyLoadedPackage(*it); } else handle_ert(os, "\\date{" + date + '}', context); @@ -2314,6 +2455,9 @@ void parse_text(Parser & p, ostream & os, unsigned flags, bool outer, p.skip_spaces(); if (!title_layout_found) title_layout_found = newlayout->intitle; + set const & req = newlayout->requires(); + for (set::const_iterator it = req.begin(); it != req.end(); it++) + preamble.registerAutomaticallyLoadedPackage(*it); } // Section headings and the like @@ -2324,6 +2468,9 @@ void parse_text(Parser & p, ostream & os, unsigned flags, bool outer, p.skip_spaces(); if (!title_layout_found) title_layout_found = newlayout->intitle; + set const & req = newlayout->requires(); + for (set::const_iterator it = req.begin(); it != req.end(); it++) + preamble.registerAutomaticallyLoadedPackage(*it); } else if (t.cs() == "caption") { @@ -2647,50 +2794,20 @@ void parse_text(Parser & p, ostream & os, unsigned flags, bool outer, handle_ert(os, "\\listof{" + name + "}", context); } - else if (t.cs() == "textrm") - parse_text_attributes(p, os, FLAG_ITEM, outer, - context, "\\family", - context.font.family, "roman"); - - else if (t.cs() == "textsf") - parse_text_attributes(p, os, FLAG_ITEM, outer, - context, "\\family", - context.font.family, "sans"); - - else if (t.cs() == "texttt") - parse_text_attributes(p, os, FLAG_ITEM, outer, - context, "\\family", - context.font.family, "typewriter"); - - else if (t.cs() == "textmd") - parse_text_attributes(p, os, FLAG_ITEM, outer, - context, "\\series", - context.font.series, "medium"); - - else if (t.cs() == "textbf") - parse_text_attributes(p, os, FLAG_ITEM, outer, - context, "\\series", - context.font.series, "bold"); - - else if (t.cs() == "textup") + else if ((where = is_known(t.cs(), known_text_font_families))) parse_text_attributes(p, os, FLAG_ITEM, outer, - context, "\\shape", - context.font.shape, "up"); + context, "\\family", context.font.family, + known_coded_font_families[where - known_text_font_families]); - else if (t.cs() == "textit") + else if ((where = is_known(t.cs(), known_text_font_series))) parse_text_attributes(p, os, FLAG_ITEM, outer, - context, "\\shape", - context.font.shape, "italic"); + context, "\\series", context.font.series, + known_coded_font_series[where - known_text_font_series]); - else if (t.cs() == "textsl") + else if ((where = is_known(t.cs(), known_text_font_shapes))) parse_text_attributes(p, os, FLAG_ITEM, outer, - context, "\\shape", - context.font.shape, "slanted"); - - else if (t.cs() == "textsc") - parse_text_attributes(p, os, FLAG_ITEM, outer, - context, "\\shape", - context.font.shape, "smallcaps"); + context, "\\shape", context.font.shape, + known_coded_font_shapes[where - known_text_font_shapes]); else if (t.cs() == "textnormal" || t.cs() == "normalfont") { context.check_layout(os); @@ -2890,7 +3007,7 @@ void parse_text(Parser & p, ostream & os, unsigned flags, bool outer, 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. - char const * const * where = is_known( + where = is_known( t.cs() == "protect" ? p.get_token().cs() : t.cs(), known_phrases); context.check_layout(os); @@ -2898,18 +3015,19 @@ void parse_text(Parser & p, ostream & os, unsigned flags, bool outer, skip_spaces_braces(p); } - else if (is_known(t.cs(), known_ref_commands)) { + else if ((where = is_known(t.cs(), known_ref_commands))) { string const opt = p.getOpt(); if (opt.empty()) { context.check_layout(os); - char const * const * where = is_known(t.cs(), - known_ref_commands); 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 support optional arguments of ref commands handle_ert(os, t.asInput() + '[' + opt + "]{" + @@ -3062,6 +3180,7 @@ void parse_text(Parser & p, ostream & os, unsigned flags, bool outer, << convert_command_inset_arg(p.verbatim_item()) << "\"\n"; end_inset(os); + preamble.registerAutomaticallyLoadedPackage("nomencl"); } else if (t.cs() == "label") { @@ -3079,6 +3198,9 @@ void parse_text(Parser & p, ostream & os, unsigned flags, bool outer, os << "type \"idx\"\n"; end_inset(os); skip_spaces_braces(p); + preamble.registerAutomaticallyLoadedPackage("makeidx"); + if (preamble.use_indices() == "true") + preamble.registerAutomaticallyLoadedPackage("splitidx"); } else if (t.cs() == "printnomenclature") { @@ -3105,6 +3227,7 @@ void parse_text(Parser & p, ostream & os, unsigned flags, bool outer, os << "width \"" << width << '\"'; end_inset(os); skip_spaces_braces(p); + preamble.registerAutomaticallyLoadedPackage("nomencl"); } else if ((t.cs() == "textsuperscript" || t.cs() == "textsubscript")) { @@ -3117,8 +3240,7 @@ void parse_text(Parser & p, ostream & os, unsigned flags, bool outer, preamble.registerAutomaticallyLoadedPackage("subscript"); } - else if (is_known(t.cs(), known_quotes)) { - char const * const * where = is_known(t.cs(), known_quotes); + else if ((where = is_known(t.cs(), known_quotes))) { context.check_layout(os); begin_inset(os, "Quotes "); os << known_coded_quotes[where - known_quotes]; @@ -3130,9 +3252,8 @@ void parse_text(Parser & p, ostream & os, unsigned flags, bool outer, skip_braces(p); } - else if (is_known(t.cs(), known_sizes) && + else if ((where = is_known(t.cs(), known_sizes)) && context.new_layout_allowed) { - char const * const * where = is_known(t.cs(), known_sizes); context.check_layout(os); TeXFont const oldFont = context.font; context.font.size = known_coded_sizes[where - known_sizes]; @@ -3140,10 +3261,8 @@ void parse_text(Parser & p, ostream & os, unsigned flags, bool outer, eat_whitespace(p, os, context, false); } - else if (is_known(t.cs(), known_font_families) && + else if ((where = is_known(t.cs(), known_font_families)) && context.new_layout_allowed) { - char const * const * where = - is_known(t.cs(), known_font_families); context.check_layout(os); TeXFont const oldFont = context.font; context.font.family = @@ -3152,10 +3271,8 @@ void parse_text(Parser & p, ostream & os, unsigned flags, bool outer, eat_whitespace(p, os, context, false); } - else if (is_known(t.cs(), known_font_series) && + else if ((where = is_known(t.cs(), known_font_series)) && context.new_layout_allowed) { - char const * const * where = - is_known(t.cs(), known_font_series); context.check_layout(os); TeXFont const oldFont = context.font; context.font.series = @@ -3164,10 +3281,8 @@ void parse_text(Parser & p, ostream & os, unsigned flags, bool outer, eat_whitespace(p, os, context, false); } - else if (is_known(t.cs(), known_font_shapes) && + else if ((where = is_known(t.cs(), known_font_shapes)) && context.new_layout_allowed) { - char const * const * where = - is_known(t.cs(), known_font_shapes); context.check_layout(os); TeXFont const oldFont = context.font; context.font.shape = @@ -3175,10 +3290,8 @@ void parse_text(Parser & p, ostream & os, unsigned flags, bool outer, output_font_change(os, oldFont, context.font); eat_whitespace(p, os, context, false); } - else if (is_known(t.cs(), known_old_font_families) && + else if ((where = is_known(t.cs(), known_old_font_families)) && context.new_layout_allowed) { - char const * const * where = - is_known(t.cs(), known_old_font_families); context.check_layout(os); TeXFont const oldFont = context.font; context.font.init(); @@ -3189,10 +3302,8 @@ void parse_text(Parser & p, ostream & os, unsigned flags, bool outer, eat_whitespace(p, os, context, false); } - else if (is_known(t.cs(), known_old_font_series) && + else if ((where = is_known(t.cs(), known_old_font_series)) && context.new_layout_allowed) { - char const * const * where = - is_known(t.cs(), known_old_font_series); context.check_layout(os); TeXFont const oldFont = context.font; context.font.init(); @@ -3203,10 +3314,8 @@ void parse_text(Parser & p, ostream & os, unsigned flags, bool outer, eat_whitespace(p, os, context, false); } - else if (is_known(t.cs(), known_old_font_shapes) && + else if ((where = is_known(t.cs(), known_old_font_shapes)) && context.new_layout_allowed) { - char const * const * where = - is_known(t.cs(), known_old_font_shapes); context.check_layout(os); TeXFont const oldFont = context.font; context.font.init(); @@ -3239,27 +3348,11 @@ void parse_text(Parser & p, ostream & os, unsigned flags, bool outer, p.setEncoding(enc); } - else if (t.cs() == "ldots") { + else if ((where = is_known(t.cs(), known_special_chars))) { context.check_layout(os); - os << "\\SpecialChar \\ldots{}\n"; - skip_spaces_braces(p); - } - - else if (t.cs() == "lyxarrow") { - context.check_layout(os); - os << "\\SpecialChar \\menuseparator\n"; - skip_spaces_braces(p); - } - - else if (t.cs() == "textcompwordmark") { - context.check_layout(os); - os << "\\SpecialChar \\textcompwordmark{}\n"; - skip_spaces_braces(p); - } - - else if (t.cs() == "slash") { - context.check_layout(os); - os << "\\SpecialChar \\slash{}\n"; + os << "\\SpecialChar \\" + << known_coded_special_chars[where - known_special_chars] + << '\n'; skip_spaces_braces(p); } @@ -3351,13 +3444,17 @@ void parse_text(Parser & p, ostream & os, unsigned flags, bool outer, string command = t.asInput() + "{" + trimSpaceAndEol(p.verbatim_item()) + "}"; - docstring s = encodings.fromLaTeXCommand(from_utf8(command), rem); + set req; + docstring s = encodings.fromLaTeXCommand(from_utf8(command), + Encodings::TEXT_CMD | Encodings::MATH_CMD, 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::const_iterator it = req.begin(); it != req.end(); it++) + preamble.registerAutomaticallyLoadedPackage(*it); } else // we did not find a non-ert version handle_ert(os, command, context); @@ -3491,6 +3588,8 @@ void parse_text(Parser & p, ostream & os, unsigned flags, bool outer, begin_command_inset(os, "include", name); os << "preview false\n" "filename \"" << outname << "\"\n"; + if (t.cs() == "verbatiminput") + preamble.registerAutomaticallyLoadedPackage("verbatim"); } end_inset(os); } @@ -3575,17 +3674,30 @@ void parse_text(Parser & p, ostream & os, unsigned flags, bool outer, parse_outer_box(p, os, FLAG_ITEM, outer, context, t.cs(), ""); else if (t.cs() == "framebox") { - string special = p.getFullOpt(); - special += p.getOpt(); - parse_outer_box(p, os, FLAG_ITEM, outer, context, t.cs(), special); + if (p.next_token().character() == '(') { + //the syntax is: \framebox(x,y)[position]{content} + string arg = t.asInput(); + arg += p.getFullParentheseArg(); + arg += p.getFullOpt(); + eat_whitespace(p, os, context, false); + handle_ert(os, arg + '{', context); + eat_whitespace(p, os, context, false); + parse_text(p, os, FLAG_ITEM, outer, context); + handle_ert(os, "}", context); + } else { + string special = p.getFullOpt(); + special += p.getOpt(); + parse_outer_box(p, os, FLAG_ITEM, outer, + context, t.cs(), special); + } } //\makebox() is part of the picture environment and different from \makebox{} //\makebox{} will be parsed by parse_box else if (t.cs() == "makebox") { - string arg = t.asInput(); if (p.next_token().character() == '(') { //the syntax is: \makebox(x,y)[position]{content} + string arg = t.asInput(); arg += p.getFullParentheseArg(); arg += p.getFullOpt(); eat_whitespace(p, os, context, false); @@ -3610,8 +3722,7 @@ void parse_text(Parser & p, ostream & os, unsigned flags, bool outer, skip_spaces_braces(p); } - else if (is_known(t.cs(), known_spaces)) { - char const * const * where = is_known(t.cs(), known_spaces); + else if ((where = is_known(t.cs(), known_spaces))) { context.check_layout(os); begin_inset(os, "space "); os << '\\' << known_coded_spaces[where - known_spaces] @@ -3645,7 +3756,7 @@ void parse_text(Parser & p, ostream & os, unsigned flags, bool outer, t.cs() == "DeclareRobustCommandx" || t.cs() == "newcommand" || t.cs() == "newcommandx" || - t.cs() == "providecommand" || + t.cs() == "providecommand" || t.cs() == "providecommandx" || t.cs() == "renewcommand" || t.cs() == "renewcommandx") { @@ -3829,13 +3940,113 @@ void parse_text(Parser & p, ostream & os, unsigned flags, bool outer, end_inset(os); } + else if (t.cs() == "includepdf") { + p.skip_spaces(); + string const arg = p.getArg('[', ']'); + map opts; + vector keys; + split_map(arg, opts, keys); + string name = normalize_filename(p.verbatim_item()); + string const path = getMasterFilePath(); + // We want to preserve relative / absolute filenames, + // therefore path is only used for testing + if (!makeAbsPath(name, path).exists()) { + // The file extension is probably missing. + // Now try to find it out. + char const * const pdfpages_format[] = {"pdf", 0}; + string const pdftex_name = + find_file(name, path, pdfpages_format); + if (!pdftex_name.empty()) { + name = pdftex_name; + pdflatex = true; + } + } + if (makeAbsPath(name, path).exists()) + fix_relative_filename(name); + else + cerr << "Warning: Could not find file '" + << name << "'." << endl; + // write output + context.check_layout(os); + begin_inset(os, "External\n\ttemplate "); + os << "PDFPages\n\tfilename " + << name << "\n"; + // parse the options + if (opts.find("pages") != opts.end()) + os << "\textra LaTeX \"pages=" + << opts["pages"] << "\"\n"; + if (opts.find("angle") != opts.end()) + os << "\trotateAngle " + << opts["angle"] << '\n'; + if (opts.find("origin") != opts.end()) { + ostringstream ss; + string const opt = opts["origin"]; + if (opt == "tl") ss << "topleft"; + if (opt == "bl") ss << "bottomleft"; + if (opt == "Bl") ss << "baselineleft"; + if (opt == "c") ss << "center"; + if (opt == "tc") ss << "topcenter"; + if (opt == "bc") ss << "bottomcenter"; + if (opt == "Bc") ss << "baselinecenter"; + if (opt == "tr") ss << "topright"; + if (opt == "br") ss << "bottomright"; + if (opt == "Br") ss << "baselineright"; + if (!ss.str().empty()) + os << "\trotateOrigin " << ss.str() << '\n'; + else + cerr << "Warning: Ignoring unknown includegraphics origin argument '" << opt << "'\n"; + } + if (opts.find("width") != opts.end()) + os << "\twidth " + << translate_len(opts["width"]) << '\n'; + if (opts.find("height") != opts.end()) + os << "\theight " + << translate_len(opts["height"]) << '\n'; + if (opts.find("keepaspectratio") != opts.end()) + os << "\tkeepAspectRatio\n"; + end_inset(os); + context.check_layout(os); + } + + else if (t.cs() == "loadgame") { + p.skip_spaces(); + string name = normalize_filename(p.verbatim_item()); + string const path = getMasterFilePath(); + // We want to preserve relative / absolute filenames, + // therefore path is only used for testing + if (!makeAbsPath(name, path).exists()) { + // The file extension is probably missing. + // Now try to find it out. + char const * const lyxskak_format[] = {"fen", 0}; + string const lyxskak_name = + find_file(name, path, lyxskak_format); + if (!lyxskak_name.empty()) + name = lyxskak_name; + } + if (makeAbsPath(name, path).exists()) + fix_relative_filename(name); + else + cerr << "Warning: Could not find file '" + << name << "'." << endl; + context.check_layout(os); + begin_inset(os, "External\n\ttemplate "); + os << "ChessDiagram\n\tfilename " + << name << "\n"; + end_inset(os); + context.check_layout(os); + // after a \loadgame follows a \showboard + if (p.get_token().asInput() == "showboard") + p.get_token(); + } + else { // 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) docstring rem; + set req; docstring s = encodings.fromLaTeXCommand(from_utf8(t.asInput()), - rem, Encodings::TEXT_CMD); + Encodings::TEXT_CMD, rem, &req); if (!s.empty()) { if (!rem.empty()) cerr << "When parsing " << t.cs() @@ -3844,6 +4055,8 @@ void parse_text(Parser & p, ostream & os, unsigned flags, bool outer, context.check_layout(os); os << to_utf8(s); skip_spaces_braces(p); + for (set::const_iterator it = req.begin(); it != req.end(); it++) + preamble.registerAutomaticallyLoadedPackage(*it); } //cerr << "#: " << t << " mode: " << mode << endl; // heuristic: read up to next non-nested space