}
+string const fromPolyglossiaEnvironment(string const s)
+{
+ // Since \arabic is taken by the LaTeX kernel,
+ // the Arabic polyglossia environment is upcased
+ if (s == "Arabic")
+ return "arabic";
+ else
+ return s;
+}
+
+
+string uncapitalize(string const s)
+{
+ docstring in = from_ascii(s);
+ char_type t = lowercase(s[0]);
+ in[0] = t;
+ return to_ascii(in);
+}
+
+
+bool isCapitalized(string const s)
+{
+ docstring in = from_ascii(s);
+ char_type t = uppercase(s[0]);
+ in[0] = t;
+ return to_ascii(in) == s;
+}
+
+
} // namespace
if (specialfont)
parent_context.new_layout_allowed = false;
output_ert_inset(os, "\\begin{" + name + "}", parent_context);
+ // Try to handle options: Look if we have optional arguments,
+ // and if so, put the brackets in ERT.
+ while (p.hasOpt()) {
+ p.get_token(); // eat '['
+ output_ert_inset(os, "[", parent_context);
+ os << parse_text_snippet(p, FLAG_BRACK_LAST, outer, parent_context);
+ output_ert_inset(os, "]", parent_context);
+ }
parse_text_snippet(p, os, flags, outer, parent_context);
output_ert_inset(os, "\\end{" + name + "}", parent_context);
if (specialfont)
break;
}
- if (is_known(name, preamble.polyglossia_languages)) {
+ // We need to use fromPolyglossiaEnvironment die to Arabic > arabic
+ if (is_known(fromPolyglossiaEnvironment(name), preamble.polyglossia_languages)) {
// We must begin a new paragraph if not already done
if (! parent_context.atParagraphStart()) {
parent_context.check_end_layout(os);
}
// save the language in the context so that it is
// handled by parse_text
- parent_context.font.language = preamble.polyglossia2lyx(name);
+ parent_context.font.language =
+ preamble.polyglossia2lyx(fromPolyglossiaEnvironment(name));
parse_text(p, os, FLAG_END, outer, parent_context);
// Just in case the environment is empty
parent_context.extra_stuff.erase();
break;
}
- // This is only attempted at landscape environments that consists only
+ // This is only attempted at turn environments that consist only
+ // of a tabular (this is how tables in LyX, modulo longtables, are rotated).
+ // Thus we will fall through in other cases.
+ if (name == "turn") {
+ // We check if the next thing is a tabular[*|x]
+ p.pushPosition();
+ p.getArg('{', '}');// eat turn argument
+ bool found_end = false;
+ bool only_table = false;
+ bool end_table = false;
+ p.get_token();
+ p.get_token();
+ string envname = p.getArg('{', '}');
+ if (rtrim(envname, "*") == "tabular" || envname == "tabularx") {
+ // Now we check if the table is the only content
+ // of the turn environment
+ string const tenv = envname;
+ while (!found_end && !end_table && p.good()) {
+ envname = p.next_token().cat() == catBegin
+ ? p.getArg('{', '}') : string();
+ Token const & t = p.get_token();
+ p.skip_spaces();
+ end_table = t.asInput() != "\\end"
+ && envname == tenv;
+ found_end = t.asInput() == "\\end"
+ && envname == "turn";
+ }
+ if (end_table) {
+ p.get_token();
+ envname = p.getArg('{', '}');
+ only_table = p.next_next_token().asInput() == "\\end"
+ && envname == "turn";
+ }
+ if (only_table) {
+ p.popPosition();
+ string const angle = p.getArg('{', '}');
+ p.skip_spaces();
+ int const save_tablerotation = parent_context.tablerotation;
+ parent_context.tablerotation = convert<int>(angle);
+ parse_text(p, os, FLAG_END, outer, parent_context);
+ parent_context.tablerotation = save_tablerotation;
+ p.skip_spaces();
+ break;
+ }
+ // fall through
+ }
+ // fall through
+ p.popPosition();
+ }
+
+ // This is only attempted at landscape environments that consist only
// of a longtable (this is how longtables in LyX are rotated by 90 degs).
// Other landscape environment is handled via the landscape module, thus
// we will fall through in that case.
p.get_token();
p.get_token();
string envname = p.getArg('{', '}');
- if (envname == "longtable") {
+ if (envname == "longtable" || envname == "xltabular") {
// Now we check if the longtable is the only content
// of the landscape environment
+ string const ltenv = envname;
while (!found_end && !end_longtable && p.good()) {
envname = p.next_token().cat() == catBegin
? p.getArg('{', '}') : string();
Token const & t = p.get_token();
p.skip_spaces();
end_longtable = t.asInput() != "\\end"
- && envname == "longtable";
+ && envname == ltenv;
found_end = t.asInput() == "\\end"
&& envname == "landscape";
}
if (only_longtable) {
p.popPosition();
p.skip_spaces();
- bool const save_rotlongtable = parent_context.rotlongtable;
- parent_context.rotlongtable = true;
+ int const save_tablerotation = parent_context.tablerotation;
+ parent_context.tablerotation = 90;
parse_text(p, os, FLAG_END, outer, parent_context);
- parent_context.rotlongtable = save_rotlongtable;
+ parent_context.tablerotation = save_tablerotation;
p.skip_spaces();
break;
}
}
switch (context.layout->latextype) {
case LATEX_LIST_ENVIRONMENT:
+ context.in_list_preamble =
+ !context.layout->listpreamble().empty()
+ && p.hasListPreamble(context.layout->itemcommand());
context.add_par_extra_stuff("\\labelwidthstring "
+ p.verbatim_item() + '\n');
p.skip_spaces();
output_arguments(os, p, outer, false, string(), context,
context.layout->latexargs());
else if (context.layout->latextype == LATEX_ITEM_ENVIRONMENT) {
+ context.in_list_preamble =
+ !context.layout->listpreamble().empty()
+ && p.hasListPreamble(context.layout->itemcommand());
ostringstream oss;
output_arguments(oss, p, outer, false, string(), context,
context.layout->latexargs());
context.list_extra_stuff = oss.str();
}
+ if (context.in_list_preamble) {
+ // Collect the stuff between \begin and first \item
+ context.list_preamble =
+ parse_text_snippet(p, FLAG_END, outer, context);
+ context.in_list_preamble = false;
+ }
parse_text(p, os, FLAG_END, outer, context);
if (context.layout->latextype == LATEX_ENVIRONMENT)
output_arguments(os, p, outer, false, "post", context,
p.skip_spaces();
if (!preamble.titleLayoutFound())
preamble.titleLayoutFound(newlayout->intitle);
- set<string> const & req = newlayout->requires();
+ set<string> const & req = newlayout->required();
set<string>::const_iterator it = req.begin();
set<string>::const_iterator en = req.end();
for (; it != en; ++it)
debugToken(cerr, t, flags);
#endif
+ if (context.in_list_preamble
+ && p.next_token().cs() == context.layout->itemcommand()) {
+ // We are parsing a list preamble. End before first \item.
+ flags |= FLAG_LEAVE;
+ context.in_list_preamble = false;
+ }
+
if (flags & FLAG_ITEM) {
if (t.cat() == catSpace)
continue;
if (context.layout->labeltype != LABEL_MANUAL)
output_arguments(os, p, outer, false, "item", context,
context.layout->itemargs());
+ if (!context.list_preamble.empty()) {
+ // We have a list preamble. Output it here.
+ begin_inset(os, "Argument listpreamble:1");
+ os << "\nstatus collapsed\n\n"
+ << "\\begin_layout Plain Layout\n\n"
+ << rtrim(context.list_preamble)
+ << "\n\\end_layout";
+ end_inset(os);
+ context.list_preamble.clear();
+ }
if (!context.list_extra_stuff.empty()) {
os << context.list_extra_stuff;
context.list_extra_stuff.clear();
parse_text_snippet(p, os, FLAG_ITEM, outer, context);
if (!preamble.titleLayoutFound())
preamble.titleLayoutFound(newlayout->intitle);
- set<string> const & req = newlayout->requires();
+ set<string> const & req = newlayout->required();
set<string>::const_iterator it = req.begin();
set<string>::const_iterator en = req.end();
for (; it != en; ++it)
p.skip_spaces();
if (!preamble.titleLayoutFound())
preamble.titleLayoutFound(newlayout->intitle);
- set<string> const & req = newlayout->requires();
+ set<string> const & req = newlayout->required();
for (set<string>::const_iterator it = req.begin(); it != req.end(); ++it)
preamble.registerAutomaticallyLoadedPackage(*it);
continue;
}
-
// Starred section headings
// Must attempt to parse "Section*" before "Section".
if ((p.next_token().asInput() == "*") &&
p.skip_spaces();
if (!preamble.titleLayoutFound())
preamble.titleLayoutFound(newlayout->intitle);
- set<string> const & req = newlayout->requires();
+ set<string> const & req = newlayout->required();
for (set<string>::const_iterator it = req.begin(); it != req.end(); ++it)
preamble.registerAutomaticallyLoadedPackage(*it);
continue;
p.skip_spaces();
if (!preamble.titleLayoutFound())
preamble.titleLayoutFound(newlayout->intitle);
- set<string> const & req = newlayout->requires();
+ set<string> const & req = newlayout->required();
for (set<string>::const_iterator it = req.begin(); it != req.end(); ++it)
preamble.registerAutomaticallyLoadedPackage(*it);
continue;
if (opts.find("width") != opts.end())
os << "\twidth "
<< translate_len(opts["width"]) << '\n';
- if (opts.find("height") != opts.end())
+ if (opts.find("totalheight") != opts.end())
os << "\theight "
- << translate_len(opts["height"]) << '\n';
+ << translate_len(opts["totalheight"]) << '\n';
if (opts.find("scale") != opts.end()) {
istringstream iss(opts["scale"]);
double val;
vector<string>::const_iterator s =
find(keys.begin(), keys.end(), "width");
if (s == keys.end())
- s = find(keys.begin(), keys.end(), "height");
+ s = find(keys.begin(), keys.end(), "totalheight");
if (s == keys.end())
s = find(keys.begin(), keys.end(), "scale");
if (s != keys.end() && distance(s, a) > 0)
special << "trim,";
if (opts.find("viewport") != opts.end())
special << "viewport=" << opts["viewport"] << ',';
- if (opts.find("totalheight") != opts.end())
- special << "totalheight=" << opts["totalheight"] << ',';
+ if (opts.find("height") != opts.end())
+ special << "height=" << opts["height"] << ',';
if (opts.find("type") != opts.end())
special << "type=" << opts["type"] << ',';
if (opts.find("ext") != opts.end())
if (t.cs() == "listof") {
p.skip_spaces(true);
- string const name = p.get_token().cs();
+ string const name = p.verbatim_item();
if (context.textclass.floats().typeExist(name)) {
context.check_layout(os);
begin_inset(os, "FloatList ");
os << name << "\n";
end_inset(os);
- p.get_token(); // swallow second arg
+ p.verbatim_item(); // swallow second arg
} else
output_ert_inset(os, "\\listof{" + name + "}", context);
continue;
}
+ if (t.cs() == "theendnotes"
+ || (t.cs() == "printendnotes"
+ && p.next_token().asInput() != "*"
+ && !p.hasOpt())) {
+ context.check_layout(os);
+ begin_inset(os, "FloatList endnote\n");
+ end_inset(os);
+ skip_spaces_braces(p);
+ continue;
+ }
+
if ((where = is_known(t.cs(), known_text_font_families))) {
parse_text_attributes(p, os, FLAG_ITEM, outer,
context, "\\family", context.font.family,
continue;
}
- if (t.cs() == "lyxadded" || t.cs() == "lyxdeleted") {
+ if (t.cs() == "lyxadded" || t.cs() == "lyxdeleted" || t.cs() == "lyxobjdeleted"
+ || t.cs() == "lyxdisplayobjdeleted" || t.cs() == "lyxudisplayobjdeleted") {
context.check_layout(os);
+ string initials;
+ if (p.hasOpt()) {
+ initials = p.getArg('[', ']');
+ }
string name = p.getArg('{', '}');
string localtime = p.getArg('{', '}');
- preamble.registerAuthor(name);
+ preamble.registerAuthor(name, initials);
Author const & author = preamble.getAuthor(name);
// from_asctime_utc() will fail if LyX decides to output the
// time in the text language.
os << "\n\\change_deleted ";
os << author.bufferId() << ' ' << ptime << '\n';
parse_text_snippet(p, os, FLAG_ITEM, outer, context);
- bool dvipost = LaTeXPackages::isAvailable("dvipost");
bool xcolorulem = LaTeXPackages::isAvailable("ulem") &&
LaTeXPackages::isAvailable("xcolor");
// No need to test for luatex, since luatex comes in
preamble.registerAutomaticallyLoadedPackage("pdfcolmk");
}
} else {
- if (dvipost) {
- preamble.registerAutomaticallyLoadedPackage("dvipost");
- } else if (xcolorulem) {
+ if (xcolorulem) {
preamble.registerAutomaticallyLoadedPackage("ulem");
preamble.registerAutomaticallyLoadedPackage("xcolor");
}
continue;
}
- // handle refstyle first to catch \eqref which can also occur
- // without refstyle. Only recognize these commands if
+ // Handle refstyle first in order to to catch \eqref, because this
+ // 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).
- if ((where = is_known(t.cs(), known_refstyle_commands))
+ // We uncapitalize the input in order to catch capitalized commands
+ // such as \Eqref.
+ if ((where = is_known(uncapitalize(t.cs()), known_refstyle_commands))
&& preamble.refstyle()) {
+ string const cap = isCapitalized(t.cs()) ? "true" : "false";
+ string plural = "false";
+ // Catch the plural option [s]
+ if (p.hasOpt()) {
+ string const opt = p.getOpt();
+ if (opt == "[s]")
+ plural = "true";
+ else {
+ // LyX does not yet support other optional arguments of ref commands
+ output_ert_inset(os, t.asInput() + opt + "{" +
+ p.verbatim_item() + '}', context);
+ continue;
+ }
+ }
context.check_layout(os);
begin_command_inset(os, "ref", "formatted");
os << "reference \"";
os << known_refstyle_prefixes[where - known_refstyle_commands]
<< ":";
- os << convert_literate_command_inset_arg(p.verbatim_item())
+ os << convert_literate_command_inset_arg(p.getArg('{', '}'))
<< "\"\n";
- os << "plural \"false\"\n";
- os << "caps \"false\"\n";
+ os << "plural \"" << plural << "\"\n";
+ os << "caps \"" << cap << "\"\n";
os << "noprefix \"false\"\n";
end_inset(os);
preamble.registerAutomaticallyLoadedPackage("refstyle");
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);
+ output_ert_inset(os, t.asInput() + opt + "{" +
+ p.verbatim_item() + '}', context);
}
continue;
}
}
string keys, pretextlist, posttextlist;
if (qualified) {
- map<string, string> pres, posts, preslit, postslit;
+ vector<pair<string, string>> pres, posts, preslit, postslit;
vector<string> lkeys;
// text before the citation
string lbefore, lbeforelit;
// text after the citation
string lafter, lafterlit;
- string lkey;
+ string lkey;
pair<bool, string> laft, lbef;
while (true) {
get_cite_arguments(p, true, lbefore, lafter);
laft = convert_latexed_command_inset_arg(lafter);
literal |= !laft.first;
lafter = laft.second;
- lafterlit = subst(lbefore, "\n", " ");
+ lafterlit = subst(lafter, "\n", " ");
}
if (!lbefore.empty()) {
lbefore.erase(0, 1);
lkey = p.getArg('{', '}');
if (lkey.empty())
break;
- if (!lbefore.empty()) {
- pres.insert(make_pair(lkey, lbefore));
- preslit.insert(make_pair(lkey, lbeforelit));
- }
- if (!lafter.empty()) {
- posts.insert(make_pair(lkey, lafter));
- postslit.insert(make_pair(lkey, lafterlit));
- }
+ pres.push_back(make_pair(lkey, lbefore));
+ preslit.push_back(make_pair(lkey, lbeforelit));
+ posts.push_back(make_pair(lkey, lafter));
+ postslit.push_back(make_pair(lkey, lafterlit));
lkeys.push_back(lkey);
}
keys = convert_literate_command_inset_arg(getStringFromVector(lkeys));
for (auto const & ptl : pres) {
if (!pretextlist.empty())
pretextlist += '\t';
- pretextlist += ptl.first + " " + ptl.second;
+ pretextlist += ptl.first;
+ if (!ptl.second.empty())
+ pretextlist += " " + ptl.second;
}
for (auto const & potl : posts) {
if (!posttextlist.empty())
posttextlist += '\t';
- posttextlist += potl.first + " " + potl.second;
+ posttextlist += potl.first;
+ if (!potl.second.empty())
+ posttextlist += " " + potl.second;
}
} else
keys = convert_literate_command_inset_arg(p.verbatim_item());
} else
os << "encoding " << '"' << enc->name() << '"' << "\n";
}
+ string bibfileencs;
+ for (auto const & bf : preamble.biblatex_encodings) {
+ if (!bibfileencs.empty())
+ bibfileencs += "\t";
+ bibfileencs += bf;
+ }
+ if (!bibfileencs.empty())
+ os << "file_encodings " << '"' << bibfileencs << '"' << "\n";
end_inset(os);
need_commentbib = false;
continue;
p.get_token(); // Eat '*'
name += '*';
}
- if (!parse_command(name, p, os, outer, context))
+ if (!parse_command(name, p, os, outer, context)) {
output_ert_inset(os, name, context);
+ // Try to handle options of unknown commands:
+ // Look if we have optional arguments,
+ // and if so, put the brackets in ERT.
+ while (p.hasOpt()) {
+ p.get_token(); // eat '['
+ output_ert_inset(os, "[", context);
+ os << parse_text_snippet(p, FLAG_BRACK_LAST, outer, context);
+ output_ert_inset(os, "]", context);
+ }
+ }
}
}
}
}
if (!bibfiles.empty())
os << "bibfiles " << '"' << bibfiles << '"' << "\n";
+ string bibfileencs;
+ for (auto const & bf : preamble.biblatex_encodings) {
+ if (!bibfileencs.empty())
+ bibfileencs += "\t";
+ bibfileencs += bf;
+ }
+ if (!bibfileencs.empty())
+ os << "file_encodings " << '"' << bibfileencs << '"' << "\n";
end_inset(os);// Bibtex
os << "\\end_layout\n";
end_inset(os);// Note