partial fix for bug 20

git-svn-id: svn://svn.lyx.org/lyx/lyx-devel/trunk@10356 a592a061-630c-0410-9148-cb99ea01b6c8
This commit is contained in:
Georg Baum 2005-07-26 11:58:43 +00:00
parent db92c134c2
commit 233c69505a
7 changed files with 313 additions and 148 deletions

View File

@ -1,3 +1,7 @@
2005-07-26 Georg Baum <Georg.Baum@post.rwth-aachen.de>
* syntax.default: add \fancyhead and \href
2005-07-25 Georg Baum <Georg.Baum@post.rwth-aachen.de> 2005-07-25 Georg Baum <Georg.Baum@post.rwth-aachen.de>
* configure.m4: fix invocation of tex2lyx again. * configure.m4: fix invocation of tex2lyx again.

View File

@ -125,6 +125,7 @@ $$
\epsfig{} \epsfig{}
\epsfxsize \epsfxsize
\epsfysize \epsfysize
\fancyhead[]{}
\footnote[]{} \footnote[]{}
\footnotesize \footnotesize
\H{} \H{}
@ -445,6 +446,7 @@ $$
\glossaryentry{}{} %only in .glo file (JMarc) \glossaryentry{}{} %only in .glo file (JMarc)
% \graphpaper[](,)(,) %picture % \graphpaper[](,)(,) %picture
\headtoname \headtoname
\href{}{translate} % from the hyperref package
\hspace{} \hspace{}
\hspace*{} \hspace*{}
\hyphenation{} \hyphenation{}

View File

@ -1,3 +1,26 @@
2005-07-26 Georg Baum <Georg.Baum@post.rwth-aachen.de>
* context.[Ch] (~Context): new, warn about ignored extra stuff
* context.[Ch] (operator==, operator!=): new Font comparison operators
* context.C (check_layout): simplify logic
* context.C (dump): output all members
* context.h (new_layout_allowed): new member variable
* text.C (parse_text): remove string wrapper since it can lead to
invalid .lyx files (begin_layout/end_layout trouble)
* text.C (parse_text_snippet): Make sure that we don't create invalid
.lyx files
* text.C (parse_text_snippet): New string wrapper for simple text
* text.C (handle_ert): Always check layout
* text.C (parse_environment): Don't allow font changes in unknown
environments
* text.C (parse_unknown_environment): new, needed for the above
* text.C (parse_environment): Only swallo spaces when we know that it
does not harm
* text.C (parse_comment): Honor context.new_layout_allowed
* text.C (parse_text_attributes): Make sure that we have a valid
layout
* text.C (parse_text): Honor context.new_layout_allowed
2005-07-25 Georg Baum <Georg.Baum@post.rwth-aachen.de> 2005-07-25 Georg Baum <Georg.Baum@post.rwth-aachen.de>
* tex2lyx.C (main): allow specification of output file name * tex2lyx.C (main): allow specification of output file name

View File

@ -51,6 +51,17 @@ void end_deeper(ostream & os)
} }
bool operator==(Font const & f1, Font const & f2)
{
return
f1.size == f2.size &&
f1.family == f2.family &&
f1.series == f2.series &&
f1.shape == f2.shape;
}
void output_font_change(ostream & os, Font const & oldfont, void output_font_change(ostream & os, Font const & oldfont,
Font const & newfont) Font const & newfont)
{ {
@ -75,7 +86,7 @@ Context::Context(bool need_layout_,
: need_layout(need_layout_), : need_layout(need_layout_),
need_end_layout(false), need_end_deeper(false), need_end_layout(false), need_end_deeper(false),
has_item(false), deeper_paragraph(false), has_item(false), deeper_paragraph(false),
textclass(textclass_), new_layout_allowed(true), textclass(textclass_),
layout(layout_), parent_layout(parent_layout_), layout(layout_), parent_layout(parent_layout_),
font(font_) font(font_)
{ {
@ -86,6 +97,14 @@ Context::Context(bool need_layout_,
} }
Context::~Context()
{
if (!extra_stuff.empty())
std::cerr << "Bug: Ignoring extra stuff '" << extra_stuff
<< '\'' << std::endl;
}
void Context::check_layout(ostream & os) void Context::check_layout(ostream & os)
{ {
if (need_layout) { if (need_layout) {
@ -104,8 +123,6 @@ void Context::check_layout(ostream & os)
} }
begin_layout(os, layout, font, normalfont); begin_layout(os, layout, font, normalfont);
has_item = false; has_item = false;
need_layout=false;
need_end_layout = true;
} else { } else {
// a standard paragraph in an // a standard paragraph in an
// enumeration. We have to recognize // enumeration. We have to recognize
@ -114,16 +131,15 @@ void Context::check_layout(ostream & os)
begin_deeper(os); begin_deeper(os);
begin_layout(os, textclass.defaultLayout(), begin_layout(os, textclass.defaultLayout(),
font, normalfont); font, normalfont);
need_layout=false;
need_end_layout = true;
deeper_paragraph = true; deeper_paragraph = true;
} }
need_layout = false;
} else { } else {
// No list-like environment // No list-like environment
begin_layout(os, layout, font, normalfont); begin_layout(os, layout, font, normalfont);
need_layout=false; need_layout=false;
need_end_layout = true;
} }
need_end_layout = true;
if (!extra_stuff.empty()) { if (!extra_stuff.empty()) {
os << extra_stuff; os << extra_stuff;
extra_stuff.erase(); extra_stuff.erase();
@ -206,8 +222,13 @@ void Context::dump(ostream & os, string const & desc) const
os << "has_item "; os << "has_item ";
if (deeper_paragraph) if (deeper_paragraph)
os << "deeper_paragraph "; os << "deeper_paragraph ";
if (new_layout_allowed)
os << "new_layout_allowed ";
if (!extra_stuff.empty()) if (!extra_stuff.empty())
os << "extrastuff=[" << extra_stuff << "] "; os << "extrastuff=[" << extra_stuff << "] ";
os << "layout=" << layout->name(); os << "textclass=" << textclass.name()
os << " parent_layout=" << parent_layout->name() << "]" << endl; << " layout=" << layout->name()
<< " parent_layout=" << parent_layout->name() << "] font=["
<< font.size << ' ' << font.family << ' ' << font.series << ' '
<< font.shape << ']' << endl;
} }

View File

@ -45,12 +45,32 @@ public:
}; };
bool operator==(Font const &, Font const &);
inline bool operator!=(Font const & f1, Font const & f2)
{
return !operator==(f1, f2);
}
/// Output changed font parameters if \p oldfont and \p newfont differ /// Output changed font parameters if \p oldfont and \p newfont differ
void output_font_change(std::ostream & os, Font const & oldfont, void output_font_change(std::ostream & os, Font const & oldfont,
Font const & newfont); Font const & newfont);
// A helper struct /*!
* A helper struct.
*
* Every bit of text has a corresponding context.
* Usage: Parsing begins with a global context. A new context is opened for
* every new LaTeX group, e.g. at the beginning of a new environment.
* The old context is used again after the group is closed.
*
* Since not all paragraph parameters in LyX have the same scoping as their
* LaTeX counterpart we may have to transfer context properties (e. g. the
* font) from and to the parent context.
*/
class Context { class Context {
public: public:
Context(bool need_layout_, Context(bool need_layout_,
@ -58,6 +78,7 @@ public:
LyXLayout_ptr layout_ = LyXLayout_ptr(), LyXLayout_ptr layout_ = LyXLayout_ptr(),
LyXLayout_ptr parent_layout_= LyXLayout_ptr(), LyXLayout_ptr parent_layout_= LyXLayout_ptr(),
Font font_ = Font()); Font font_ = Font());
~Context();
/// Output a \\begin_layout if requested /// Output a \\begin_layout if requested
void check_layout(std::ostream & os); void check_layout(std::ostream & os);
@ -97,13 +118,21 @@ public:
/// If there has been an \\begin_deeper, we'll need a matching /// If there has been an \\begin_deeper, we'll need a matching
/// \\end_deeper /// \\end_deeper
bool need_end_deeper; bool need_end_deeper;
/// If we are in an itemize-like environment, we need an \\item /// If we are in an itemize-like environment, we need an \item
/// for each paragraph, otherwise this has to be a deeper /// for each paragraph, otherwise this has to be a deeper
/// paragraph. /// paragraph.
bool has_item; bool has_item;
/// we are handling a standard paragraph in an itemize-like /// we are handling a standard paragraph in an itemize-like
/// environment /// environment
bool deeper_paragraph; bool deeper_paragraph;
/*!
* Inside of unknown environments we may not allow font and layout
* changes.
* Otherwise things like
* \\large\\begin{foo}\\huge bar\\end{foo}
* would not work.
*/
bool new_layout_allowed;
/// The textclass of the document. Could actually be a global variable /// The textclass of the document. Could actually be a global variable
LyXTextClass const & textclass; LyXTextClass const & textclass;

View File

@ -34,12 +34,15 @@ extern std::map<std::string, std::vector<std::string> > used_packages;
void parse_text(Parser & p, std::ostream & os, unsigned flags, bool outer, void parse_text(Parser & p, std::ostream & os, unsigned flags, bool outer,
Context & context); Context & context);
//std::string parse_text(Parser & p, unsigned flags, const bool outer, /*!
// Context & context); * Parses a subdocument, usually useful in insets (whence the name).
*
/// parses a subdocument, usually useful in insets (whence the name) * It ignores \c context.need_layout and \c context.need_end_layout and
* starts and ends always a new layout.
* Therefore this may only be used to parse text in insets or table cells.
*/
void parse_text_in_inset(Parser & p, std::ostream & os, unsigned flags, void parse_text_in_inset(Parser & p, std::ostream & os, unsigned flags,
bool outer, Context & context); bool outer, Context const & context);
/// in math.C /// in math.C

View File

@ -50,18 +50,8 @@ using std::vector;
namespace fs = boost::filesystem; namespace fs = boost::filesystem;
/// thin wrapper around parse_text using a string
string parse_text(Parser & p, unsigned flags, const bool outer,
Context & context)
{
ostringstream os;
parse_text(p, os, flags, outer, context);
return os.str();
}
void parse_text_in_inset(Parser & p, ostream & os, unsigned flags, bool outer, void parse_text_in_inset(Parser & p, ostream & os, unsigned flags, bool outer,
Context & context) Context const & context)
{ {
Context newcontext(true, context.textclass); Context newcontext(true, context.textclass);
newcontext.font = context.font; newcontext.font = context.font;
@ -70,19 +60,45 @@ void parse_text_in_inset(Parser & p, ostream & os, unsigned flags, bool outer,
} }
namespace {
/// parses a paragraph snippet, useful for example for \\emph{...} /// parses a paragraph snippet, useful for example for \\emph{...}
void parse_text_snippet(Parser & p, ostream & os, unsigned flags, bool outer, void parse_text_snippet(Parser & p, ostream & os, unsigned flags, bool outer,
Context & context) Context & context)
{ {
Context newcontext(false, context.textclass); Context newcontext(context);
newcontext.font = context.font; // Don't inherit the extra stuff
newcontext.extra_stuff.clear();
parse_text(p, os, flags, outer, newcontext); parse_text(p, os, flags, outer, newcontext);
// should not be needed // Make sure that we don't create invalid .lyx files
newcontext.check_end_layout(os); context.need_layout = newcontext.need_layout;
context.need_end_layout = newcontext.need_end_layout;
} }
namespace { /*!
* Thin wrapper around parse_text_snippet() using a string.
*
* We completely ignore \c context.need_layout and \c context.need_end_layout,
* because our return value is not used directly (otherwise the stream version
* of parse_text_snippet() could be used). That means that the caller needs
* to do layout management manually.
* This is intended to parse text that does not create any layout changes.
*/
string parse_text_snippet(Parser & p, unsigned flags, const bool outer,
Context & context)
{
Context newcontext(context);
newcontext.need_layout = false;
newcontext.need_end_layout = false;
newcontext.new_layout_allowed = false;
// Avoid warning by Context::~Context()
newcontext.extra_stuff.clear();
ostringstream os;
parse_text_snippet(p, os, flags, outer, newcontext);
return os.str();
}
char const * const known_latex_commands[] = { "ref", "cite", "label", "index", char const * const known_latex_commands[] = { "ref", "cite", "label", "index",
"printindex", "pageref", "url", "vref", "vpageref", "prettyref", "eqref", 0 }; "printindex", "pageref", "url", "vref", "vpageref", "prettyref", "eqref", 0 };
@ -356,14 +372,10 @@ void skip_braces(Parser & p)
} }
void handle_ert(ostream & os, string const & s, Context & context)
void handle_ert(ostream & os, string const & s, Context & context,
bool check_layout = true)
{ {
if (check_layout) { // We must have a valid layout before outputting the ERT inset.
// We must have a valid layout before outputting the ERT inset. context.check_layout(os);
context.check_layout(os);
}
Context newcontext(true, context.textclass); Context newcontext(true, context.textclass);
begin_inset(os, "ERT"); begin_inset(os, "ERT");
os << "\nstatus collapsed\n"; os << "\nstatus collapsed\n";
@ -655,14 +667,40 @@ void parse_box(Parser & p, ostream & os, unsigned flags, bool outer,
} }
/// parse an unknown environment
void parse_unknown_environment(Parser & p, string const & name, ostream & os,
unsigned flags, bool outer,
Context & parent_context)
{
if (name == "tabbing")
// We need to remember that we have to handle '\=' specially
flags |= FLAG_TABBING;
// We need to translate font changes and paragraphs inside the
// environment to ERT if we have a non standard font.
// Otherwise things like
// \large\begin{foo}\huge bar\end{foo}
// will not work.
bool const specialfont =
(parent_context.font != parent_context.normalfont);
bool const new_layout_allowed = parent_context.new_layout_allowed;
if (specialfont)
parent_context.new_layout_allowed = false;
handle_ert(os, "\\begin{" + name + "}", parent_context);
parse_text_snippet(p, os, flags, outer, parent_context);
handle_ert(os, "\\end{" + name + "}", parent_context);
if (specialfont)
parent_context.new_layout_allowed = new_layout_allowed;
}
void parse_environment(Parser & p, ostream & os, bool outer, void parse_environment(Parser & p, ostream & os, bool outer,
Context & parent_context) Context & parent_context)
{ {
LyXLayout_ptr newlayout; LyXLayout_ptr newlayout;
string const name = p.getArg('{', '}'); string const name = p.getArg('{', '}');
const bool is_starred = suffixIs(name, '*'); const bool is_starred = suffixIs(name, '*');
string const unstarred_name = rtrim(name, "*"); string const unstarred_name = rtrim(name, "*");
eat_whitespace(p, os, parent_context, false);
active_environments.push_back(name); active_environments.push_back(name);
if (is_math_env(name)) { if (is_math_env(name)) {
@ -675,13 +713,16 @@ void parse_environment(Parser & p, ostream & os, bool outer,
} }
else if (name == "tabular" || name == "longtable") { else if (name == "tabular" || name == "longtable") {
eat_whitespace(p, os, parent_context, false);
parent_context.check_layout(os); parent_context.check_layout(os);
begin_inset(os, "Tabular "); begin_inset(os, "Tabular ");
handle_tabular(p, os, name == "longtable", parent_context); handle_tabular(p, os, name == "longtable", parent_context);
end_inset(os); end_inset(os);
p.skip_spaces();
} }
else if (parent_context.textclass.floats().typeExist(unstarred_name)) { else if (parent_context.textclass.floats().typeExist(unstarred_name)) {
eat_whitespace(p, os, parent_context, false);
parent_context.check_layout(os); parent_context.check_layout(os);
begin_inset(os, "Float " + unstarred_name + "\n"); begin_inset(os, "Float " + unstarred_name + "\n");
if (p.next_token().asInput() == "[") { if (p.next_token().asInput() == "[") {
@ -695,14 +736,43 @@ void parse_environment(Parser & p, ostream & os, bool outer,
// We don't need really a new paragraph, but // We don't need really a new paragraph, but
// we must make sure that the next item gets a \begin_layout. // we must make sure that the next item gets a \begin_layout.
parent_context.new_paragraph(os); parent_context.new_paragraph(os);
p.skip_spaces();
} }
else if (name == "minipage") else if (name == "minipage") {
eat_whitespace(p, os, parent_context, false);
parse_box(p, os, FLAG_END, outer, parent_context, false); parse_box(p, os, FLAG_END, outer, parent_context, false);
p.skip_spaces();
}
else if (name == "comment") {
eat_whitespace(p, os, parent_context, false);
parent_context.check_layout(os);
begin_inset(os, "Note Comment\n");
os << "status open\n";
parse_text_in_inset(p, os, FLAG_END, outer, parent_context);
end_inset(os);
p.skip_spaces();
}
else if (name == "lyxgreyedout") {
eat_whitespace(p, os, parent_context, false);
parent_context.check_layout(os);
begin_inset(os, "Note Greyedout\n");
os << "status open\n";
parse_text_in_inset(p, os, FLAG_END, outer, parent_context);
end_inset(os);
p.skip_spaces();
}
else if (!parent_context.new_layout_allowed)
parse_unknown_environment(p, name, os, FLAG_END, outer,
parent_context);
// Alignment settings // Alignment settings
else if (name == "center" || name == "flushleft" || name == "flushright" || else if (name == "center" || name == "flushleft" || name == "flushright" ||
name == "centering" || name == "raggedright" || name == "raggedleft") { name == "centering" || name == "raggedright" || name == "raggedleft") {
eat_whitespace(p, os, parent_context, false);
// We must begin a new paragraph if not already done // We must begin a new paragraph if not already done
if (! parent_context.atParagraphStart()) { if (! parent_context.atParagraphStart()) {
parent_context.check_end_layout(os); parent_context.check_end_layout(os);
@ -719,11 +789,13 @@ void parse_environment(Parser & p, ostream & os, bool outer,
parent_context.extra_stuff.erase(); parent_context.extra_stuff.erase();
// We must begin a new paragraph to reset the alignment // We must begin a new paragraph to reset the alignment
parent_context.new_paragraph(os); parent_context.new_paragraph(os);
p.skip_spaces();
} }
// The single '=' is meant here. // The single '=' is meant here.
else if ((newlayout = findLayout(parent_context.textclass, name)).get() && else if ((newlayout = findLayout(parent_context.textclass, name)).get() &&
newlayout->isEnvironment()) { newlayout->isEnvironment()) {
eat_whitespace(p, os, parent_context, false);
Context context(true, parent_context.textclass, newlayout, Context context(true, parent_context.textclass, newlayout,
parent_context.layout, parent_context.font); parent_context.layout, parent_context.font);
if (parent_context.deeper_paragraph) { if (parent_context.deeper_paragraph) {
@ -756,10 +828,12 @@ void parse_environment(Parser & p, ostream & os, bool outer,
} }
context.check_end_deeper(os); context.check_end_deeper(os);
parent_context.new_paragraph(os); parent_context.new_paragraph(os);
p.skip_spaces();
} }
else if (name == "appendix") { else if (name == "appendix") {
// This is no good latex style, but it works and is used in some documents... // This is no good latex style, but it works and is used in some documents...
eat_whitespace(p, os, parent_context, false);
parent_context.check_end_layout(os); parent_context.check_end_layout(os);
Context context(true, parent_context.textclass, parent_context.layout, Context context(true, parent_context.textclass, parent_context.layout,
parent_context.layout, parent_context.font); parent_context.layout, parent_context.font);
@ -767,34 +841,7 @@ void parse_environment(Parser & p, ostream & os, bool outer,
os << "\\start_of_appendix\n"; os << "\\start_of_appendix\n";
parse_text(p, os, FLAG_END, outer, context); parse_text(p, os, FLAG_END, outer, context);
context.check_end_layout(os); context.check_end_layout(os);
} p.skip_spaces();
else if (name == "comment") {
parent_context.check_layout(os);
begin_inset(os, "Note Comment\n");
os << "status open\n";
parse_text_in_inset(p, os, FLAG_END, outer, parent_context);
end_inset(os);
}
else if (name == "lyxgreyedout") {
parent_context.check_layout(os);
begin_inset(os, "Note Greyedout\n");
os << "status open\n";
parse_text_in_inset(p, os, FLAG_END, outer, parent_context);
end_inset(os);
}
else if (name == "tabbing") {
// We need to remember that we have to handle '\=' specially
handle_ert(os, "\\begin{" + name + "}", parent_context);
// FIXME: Try whether parse_text instead of parse_text_snippet
// works. Then no manual layout checking would be needed.
parent_context.check_end_layout(os);
parse_text_snippet(p, os, FLAG_END | FLAG_TABBING, outer,
parent_context);
parent_context.need_layout = true;
handle_ert(os, "\\end{" + name + "}", parent_context);
} }
else if (known_environments.find(name) != known_environments.end()) { else if (known_environments.find(name) != known_environments.end()) {
@ -808,36 +855,31 @@ void parse_environment(Parser & p, ostream & os, bool outer,
arguments.back(); arguments.back();
if (!arguments.empty()) if (!arguments.empty())
arguments.pop_back(); arguments.pop_back();
// See comment in parse_unknown_environment()
bool const specialfont =
(parent_context.font != parent_context.normalfont);
bool const new_layout_allowed =
parent_context.new_layout_allowed;
if (specialfont)
parent_context.new_layout_allowed = false;
parse_arguments("\\begin{" + name + "}", arguments, p, os, parse_arguments("\\begin{" + name + "}", arguments, p, os,
outer, parent_context); outer, parent_context);
if (contents == verbatim) if (contents == verbatim)
handle_ert(os, p.verbatimEnvironment(name), handle_ert(os, p.verbatimEnvironment(name),
parent_context); parent_context);
else { else
// FIXME: Try whether parse_text instead of
// parse_text_snippet works. Then no manual layout
// checking would be needed.
parent_context.check_end_layout(os);
parse_text_snippet(p, os, FLAG_END, outer, parse_text_snippet(p, os, FLAG_END, outer,
parent_context); parent_context);
parent_context.need_layout = true;
}
handle_ert(os, "\\end{" + name + "}", parent_context); handle_ert(os, "\\end{" + name + "}", parent_context);
if (specialfont)
parent_context.new_layout_allowed = new_layout_allowed;
} }
else { else
handle_ert(os, "\\begin{" + name + "}", parent_context); parse_unknown_environment(p, name, os, FLAG_END, outer,
// FIXME: Try whether parse_text instead of parse_text_snippet parent_context);
// works. Then no manual layout checking would be needed.
parent_context.check_end_layout(os);
parse_text_snippet(p, os, FLAG_END, outer, parent_context);
parent_context.need_layout = true;
handle_ert(os, "\\end{" + name + "}", parent_context);
}
active_environments.pop_back(); active_environments.pop_back();
if (name != "math")
p.skip_spaces();
} }
@ -851,11 +893,13 @@ void parse_comment(Parser & p, ostream & os, Token const & t, Context & context)
if (p.next_token().cat() == catNewline) { if (p.next_token().cat() == catNewline) {
// A newline after a comment line starts a new // A newline after a comment line starts a new
// paragraph // paragraph
if(!context.atParagraphStart()) { if (context.new_layout_allowed) {
// Only start a new paragraph if not already if(!context.atParagraphStart())
// done (we might get called recursively) // Only start a new paragraph if not already
context.new_paragraph(os); // done (we might get called recursively)
} context.new_paragraph(os);
} else
handle_ert(os, "\n", context);
eat_whitespace(p, os, context, true); eat_whitespace(p, os, context, true);
} }
} else { } else {
@ -899,12 +943,13 @@ void parse_text_attributes(Parser & p, ostream & os, unsigned flags, bool outer,
string & currentvalue, string const & newvalue) string & currentvalue, string const & newvalue)
{ {
context.check_layout(os); context.check_layout(os);
string oldvalue = currentvalue; string const oldvalue = currentvalue;
currentvalue = newvalue; currentvalue = newvalue;
os << '\n' << attribute << ' ' << newvalue << "\n"; os << '\n' << attribute << ' ' << newvalue << "\n";
parse_text_snippet(p, os, flags, outer, context); parse_text_snippet(p, os, flags, outer, context);
currentvalue = oldvalue; context.check_layout(os);
os << '\n' << attribute << ' ' << oldvalue << "\n"; os << '\n' << attribute << ' ' << oldvalue << "\n";
currentvalue = oldvalue;
} }
@ -1061,7 +1106,10 @@ void parse_text(Parser & p, ostream & os, unsigned flags, bool outer,
} }
else if (p.isParagraph()) { else if (p.isParagraph()) {
context.new_paragraph(os); if (context.new_layout_allowed)
context.new_paragraph(os);
else
handle_ert(os, "\\par ", context);
eat_whitespace(p, os, context, true); eat_whitespace(p, os, context, true);
} }
@ -1076,55 +1124,85 @@ void parse_text(Parser & p, ostream & os, unsigned flags, bool outer,
os << t.character(); os << t.character();
} }
else if (t.cat() == catBegin &&
p.next_token().cat() == catEnd) {
// {}
Token const prev = p.prev_token();
p.get_token();
if (p.next_token().character() == '`' ||
(prev.character() == '-' &&
p.next_token().character() == '-'))
; // ignore it in {}`` or -{}-
else
handle_ert(os, "{}", context);
}
else if (t.cat() == catBegin) { else if (t.cat() == catBegin) {
context.check_layout(os); context.check_layout(os);
// special handling of font attribute changes // special handling of font attribute changes
Token const prev = p.prev_token(); Token const prev = p.prev_token();
Token const next = p.next_token(); Token const next = p.next_token();
Font const oldFont = context.font; Font const oldFont = context.font;
string const s = parse_text(p, FLAG_BRACE_LAST, outer, if (next.character() == '[' ||
context); next.character() == ']' ||
context.font = oldFont; next.character() == '*') {
if (s.empty() && (p.next_token().character() == '`' || p.get_token();
(prev.character() == '-' && if (p.next_token().cat() == catEnd) {
p.next_token().character() == '-'))) os << next.character();
; // ignore it in {}`` or -{}- p.get_token();
else if (s == "[" || s == "]" || s == "*") } else {
os << s; p.putback();
else if (is_known(next.cs(), known_sizes)) { handle_ert(os, "{", context);
// s will change the size, so we must reset parse_text_snippet(p, os,
// it here FLAG_BRACE_LAST,
os << s; outer, context);
handle_ert(os, "}", context);
}
} else if (! context.new_layout_allowed) {
handle_ert(os, "{", context);
parse_text_snippet(p, os, FLAG_BRACE_LAST,
outer, context);
handle_ert(os, "}", context);
} else if (is_known(next.cs(), known_sizes)) {
// next will change the size, so we must
// reset it here
parse_text_snippet(p, os, FLAG_BRACE_LAST,
outer, context);
if (!context.atParagraphStart()) if (!context.atParagraphStart())
os << "\n\\size " os << "\n\\size "
<< context.font.size << "\n"; << context.font.size << "\n";
} else if (is_known(next.cs(), known_font_families)) { } else if (is_known(next.cs(), known_font_families)) {
// s will change the font family, so we must // next will change the font family, so we
// reset it here // must reset it here
os << s; parse_text_snippet(p, os, FLAG_BRACE_LAST,
outer, context);
if (!context.atParagraphStart()) if (!context.atParagraphStart())
os << "\n\\family " os << "\n\\family "
<< context.font.family << "\n"; << context.font.family << "\n";
} else if (is_known(next.cs(), known_font_series)) { } else if (is_known(next.cs(), known_font_series)) {
// s will change the font series, so we must // next will change the font series, so we
// reset it here // must reset it here
os << s; parse_text_snippet(p, os, FLAG_BRACE_LAST,
outer, context);
if (!context.atParagraphStart()) if (!context.atParagraphStart())
os << "\n\\series " os << "\n\\series "
<< context.font.series << "\n"; << context.font.series << "\n";
} else if (is_known(next.cs(), known_font_shapes)) { } else if (is_known(next.cs(), known_font_shapes)) {
// s will change the font shape, so we must // next will change the font shape, so we
// reset it here // must reset it here
os << s; parse_text_snippet(p, os, FLAG_BRACE_LAST,
outer, context);
if (!context.atParagraphStart()) if (!context.atParagraphStart())
os << "\n\\shape " os << "\n\\shape "
<< context.font.shape << "\n"; << context.font.shape << "\n";
} else if (is_known(next.cs(), known_old_font_families) || } else if (is_known(next.cs(), known_old_font_families) ||
is_known(next.cs(), known_old_font_series) || is_known(next.cs(), known_old_font_series) ||
is_known(next.cs(), known_old_font_shapes)) { is_known(next.cs(), known_old_font_shapes)) {
// s will change the font family, series // next will change the font family, series
// and shape, so we must reset it here // and shape, so we must reset it here
os << s; parse_text_snippet(p, os, FLAG_BRACE_LAST,
outer, context);
if (!context.atParagraphStart()) if (!context.atParagraphStart())
os << "\n\\family " os << "\n\\family "
<< context.font.family << context.font.family
@ -1133,10 +1211,9 @@ void parse_text(Parser & p, ostream & os, unsigned flags, bool outer,
<< "\n\\shape " << "\n\\shape "
<< context.font.shape << "\n"; << context.font.shape << "\n";
} else { } else {
handle_ert(os, "{", context, false); handle_ert(os, "{", context);
// s will end the current layout and begin a parse_text_snippet(p, os, FLAG_BRACE_LAST,
// new one if necessary outer, context);
os << s;
handle_ert(os, "}", context); handle_ert(os, "}", context);
} }
} }
@ -1195,9 +1272,8 @@ void parse_text(Parser & p, ostream & os, unsigned flags, bool outer,
bool optarg = false; bool optarg = false;
if (p.next_token().character() == '[') { if (p.next_token().character() == '[') {
p.get_token(); // eat '[' p.get_token(); // eat '['
Context newcontext(false, context.textclass); s = parse_text_snippet(p, FLAG_BRACK_LAST,
newcontext.font = context.font; outer, context);
s = parse_text(p, FLAG_BRACK_LAST, outer, newcontext);
optarg = true; optarg = true;
} }
context.set_item(); context.set_item();
@ -1265,6 +1341,7 @@ void parse_text(Parser & p, ostream & os, unsigned flags, bool outer,
// Must attempt to parse "Section*" before "Section". // Must attempt to parse "Section*" before "Section".
else if ((p.next_token().asInput() == "*") && else if ((p.next_token().asInput() == "*") &&
context.new_layout_allowed &&
// The single '=' is meant here. // The single '=' is meant here.
(newlayout = findLayout(context.textclass, (newlayout = findLayout(context.textclass,
t.cs() + '*')).get() && t.cs() + '*')).get() &&
@ -1275,7 +1352,8 @@ void parse_text(Parser & p, ostream & os, unsigned flags, bool outer,
} }
// The single '=' is meant here. // The single '=' is meant here.
else if ((newlayout = findLayout(context.textclass, t.cs())).get() && else if (context.new_layout_allowed &&
(newlayout = findLayout(context.textclass, t.cs())).get() &&
newlayout->isCommand()) { newlayout->isCommand()) {
output_command_layout(os, p, outer, context, newlayout); output_command_layout(os, p, outer, context, newlayout);
p.skip_spaces(); p.skip_spaces();
@ -1446,9 +1524,7 @@ void parse_text(Parser & p, ostream & os, unsigned flags, bool outer,
else if (t.cs() == "ensuremath") { else if (t.cs() == "ensuremath") {
p.skip_spaces(); p.skip_spaces();
context.check_layout(os); context.check_layout(os);
Context newcontext(false, context.textclass); string const s = p.verbatim_item();
newcontext.font = context.font;
string s = parse_text(p, FLAG_ITEM, false, newcontext);
if (s == "±" || s == "³" || s == "²" || s == "µ") if (s == "±" || s == "³" || s == "²" || s == "µ")
os << s; os << s;
else else
@ -1575,6 +1651,7 @@ void parse_text(Parser & p, ostream & os, unsigned flags, bool outer,
context.check_layout(os); context.check_layout(os);
os << "\n\\bar under\n"; os << "\n\\bar under\n";
parse_text_snippet(p, os, FLAG_ITEM, outer, context); parse_text_snippet(p, os, FLAG_ITEM, outer, context);
context.check_layout(os);
os << "\n\\bar default\n"; os << "\n\\bar default\n";
} }
@ -1582,6 +1659,7 @@ void parse_text(Parser & p, ostream & os, unsigned flags, bool outer,
context.check_layout(os); context.check_layout(os);
os << "\n\\" << t.cs() << " on\n"; os << "\n\\" << t.cs() << " on\n";
parse_text_snippet(p, os, FLAG_ITEM, outer, context); parse_text_snippet(p, os, FLAG_ITEM, outer, context);
context.check_layout(os);
os << "\n\\" << t.cs() << " default\n"; os << "\n\\" << t.cs() << " default\n";
} }
@ -1699,7 +1777,8 @@ void parse_text(Parser & p, ostream & os, unsigned flags, bool outer,
skip_braces(p); skip_braces(p);
} }
else if (is_known(t.cs(), known_sizes)) { else if (is_known(t.cs(), known_sizes) &&
context.new_layout_allowed) {
char const * const * where = is_known(t.cs(), known_sizes); char const * const * where = is_known(t.cs(), known_sizes);
context.check_layout(os); context.check_layout(os);
Font const oldFont = context.font; Font const oldFont = context.font;
@ -1708,7 +1787,8 @@ void parse_text(Parser & p, ostream & os, unsigned flags, bool outer,
eat_whitespace(p, os, context, false); eat_whitespace(p, os, context, false);
} }
else if (is_known(t.cs(), known_font_families)) { else if (is_known(t.cs(), known_font_families) &&
context.new_layout_allowed) {
char const * const * where = char const * const * where =
is_known(t.cs(), known_font_families); is_known(t.cs(), known_font_families);
context.check_layout(os); context.check_layout(os);
@ -1719,7 +1799,8 @@ void parse_text(Parser & p, ostream & os, unsigned flags, bool outer,
eat_whitespace(p, os, context, false); eat_whitespace(p, os, context, false);
} }
else if (is_known(t.cs(), known_font_series)) { else if (is_known(t.cs(), known_font_series) &&
context.new_layout_allowed) {
char const * const * where = char const * const * where =
is_known(t.cs(), known_font_series); is_known(t.cs(), known_font_series);
context.check_layout(os); context.check_layout(os);
@ -1730,7 +1811,8 @@ void parse_text(Parser & p, ostream & os, unsigned flags, bool outer,
eat_whitespace(p, os, context, false); eat_whitespace(p, os, context, false);
} }
else if (is_known(t.cs(), known_font_shapes)) { else if (is_known(t.cs(), known_font_shapes) &&
context.new_layout_allowed) {
char const * const * where = char const * const * where =
is_known(t.cs(), known_font_shapes); is_known(t.cs(), known_font_shapes);
context.check_layout(os); context.check_layout(os);
@ -1740,7 +1822,8 @@ void parse_text(Parser & p, ostream & os, unsigned flags, bool outer,
output_font_change(os, oldFont, context.font); output_font_change(os, oldFont, context.font);
eat_whitespace(p, os, context, false); eat_whitespace(p, os, context, false);
} }
else if (is_known(t.cs(), known_old_font_families)) { else if (is_known(t.cs(), known_old_font_families) &&
context.new_layout_allowed) {
char const * const * where = char const * const * where =
is_known(t.cs(), known_old_font_families); is_known(t.cs(), known_old_font_families);
context.check_layout(os); context.check_layout(os);
@ -1753,7 +1836,8 @@ void parse_text(Parser & p, ostream & os, unsigned flags, bool outer,
eat_whitespace(p, os, context, false); eat_whitespace(p, os, context, false);
} }
else if (is_known(t.cs(), known_old_font_series)) { else if (is_known(t.cs(), known_old_font_series) &&
context.new_layout_allowed) {
char const * const * where = char const * const * where =
is_known(t.cs(), known_old_font_series); is_known(t.cs(), known_old_font_series);
context.check_layout(os); context.check_layout(os);
@ -1766,7 +1850,8 @@ void parse_text(Parser & p, ostream & os, unsigned flags, bool outer,
eat_whitespace(p, os, context, false); eat_whitespace(p, os, context, false);
} }
else if (is_known(t.cs(), known_old_font_shapes)) { else if (is_known(t.cs(), known_old_font_shapes) &&
context.new_layout_allowed) {
char const * const * where = char const * const * where =
is_known(t.cs(), known_old_font_shapes); is_known(t.cs(), known_old_font_shapes);
context.check_layout(os); context.check_layout(os);
@ -1885,7 +1970,8 @@ void parse_text(Parser & p, ostream & os, unsigned flags, bool outer,
// we need the trim as the LyX parser chokes on such spaces // we need the trim as the LyX parser chokes on such spaces
context.check_layout(os); context.check_layout(os);
os << "\n\\i \\" << t.cs() << "{" os << "\n\\i \\" << t.cs() << "{"
<< trim(parse_text(p, FLAG_ITEM, outer, context), " ") << "}\n"; << trim(parse_text_snippet(p, FLAG_ITEM, outer, context), " ")
<< "}\n";
} }
else if (t.cs() == "ss") { else if (t.cs() == "ss") {
@ -1959,15 +2045,6 @@ void parse_text(Parser & p, ostream & os, unsigned flags, bool outer,
end_inset(os); end_inset(os);
} }
else if (t.cs() == "fancyhead") {
context.check_layout(os);
ostringstream ss;
ss << "\\fancyhead";
ss << p.getOpt();
ss << '{' << p.verbatim_item() << "}\n";
handle_ert(os, ss.str(), context);
}
else if (t.cs() == "bibliographystyle") { else if (t.cs() == "bibliographystyle") {
// store new bibliographystyle // store new bibliographystyle
bibliographystyle = p.verbatim_item(); bibliographystyle = p.verbatim_item();
@ -2002,6 +2079,13 @@ void parse_text(Parser & p, ostream & os, unsigned flags, bool outer,
skip_braces(p); skip_braces(p);
} }
else if (t.cs() == "newpage") {
context.check_layout(os);
// FIXME: what about \\clearpage and \\pagebreak?
os << "\n\\newpage\n";
skip_braces(p); // eat {}
}
else if (t.cs() == "newcommand" || else if (t.cs() == "newcommand" ||
t.cs() == "providecommand" || t.cs() == "providecommand" ||
t.cs() == "renewcommand") { t.cs() == "renewcommand") {
@ -2134,5 +2218,4 @@ void parse_text(Parser & p, ostream & os, unsigned flags, bool outer,
} }
} }
// }]) // }])