while (p.good()) {
Token const & t = p.get_token();
- if (t.cs() == "documentclass") {
+ if (t.cat() == catEscape && t.cs() == "documentclass") {
is_full_document = true;
break;
}
// cat codes
//
if (t.cat() == catLetter ||
- t.cat() == catSpace ||
t.cat() == catSuper ||
t.cat() == catSub ||
t.cat() == catOther ||
t.cat() == catBegin ||
t.cat() == catEnd ||
t.cat() == catAlign ||
- t.cat() == catNewline ||
t.cat() == catParameter)
h_preamble << t.character();
+ else if (t.cat() == catSpace || t.cat() == catNewline)
+ h_preamble << t.asInput();
+
else if (t.cat() == catComment)
- handle_comment(p);
+ h_preamble << t.asInput();
else if (t.cs() == "pagestyle")
h_paperpagestyle = p.verbatim_item();
else if (t.cs() == "makeatletter") {
p.setCatCode('@', catLetter);
- h_preamble << "\\makeatletter\n";
+ h_preamble << "\\makeatletter";
}
else if (t.cs() == "makeatother") {
p.setCatCode('@', catOther);
- h_preamble << "\\makeatother\n";
+ h_preamble << "\\makeatother";
}
else if (t.cs() == "newcommand" || t.cs() == "renewcommand"
string const opts = p.getOpt();
string const body = p.verbatim_item();
// only non-lyxspecific stuff
- if (name != "\\noun "
- && name != "\\tabularnewline "
- && name != "\\LyX "
- && name != "\\lyxline "
- && name != "\\lyxaddress "
- && name != "\\lyxrightaddress "
- && name != "\\boldsymbol "
- && name != "\\lyxarrow ") {
+ if ( name != "\\noun"
+ && name != "\\tabularnewline"
+ && name != "\\LyX"
+ && name != "\\lyxline"
+ && name != "\\lyxaddress"
+ && name != "\\lyxrightaddress"
+ && name != "\\boldsymbol"
+ && name != "\\lyxarrow") {
ostringstream ss;
ss << '\\' << t.cs();
if (star)
ss << '*';
- ss << '{' << name << '}' << opts << '{' << body << "}\n";
+ ss << '{' << name << '}' << opts << '{' << body << "}";
h_preamble << ss.str();
/*
ostream & out = in_preamble ? h_preamble : os;
out << "\\" << t.cs() << "{" << name << "}"
- << opts << "{" << body << "}\n";
+ << opts << "{" << body << "}";
*/
}
}
ss << p.getOpt();
ss << '{' << p.verbatim_item() << '}';
ss << '{' << p.verbatim_item() << '}';
- ss << '\n';
if (name != "lyxcode" && name != "lyxlist"
&& name != "lyxrightadress" && name != "lyxaddress")
h_preamble << ss.str();
string name = p.get_token().cs();
while (p.next_token().cat() != catBegin)
name += p.get_token().asString();
- h_preamble << "\\def\\" << name << '{' << p.verbatim_item() << "}\n";
+ h_preamble << "\\def\\" << name << '{' << p.verbatim_item() << "}";
}
else if (t.cs() == "newcolumntype") {
h_preamble << "\\newcolumntype{" << name << "}";
if (nargs)
h_preamble << "[" << nargs << "]";
- h_preamble << "{" << p.verbatim_item() << "}\n";
+ h_preamble << "{" << p.verbatim_item() << "}";
}
else if (t.cs() == "setcounter") {
else if (name == "tocdepth")
h_tocdepth = content;
else
- h_preamble << "\\setcounter{" << name << "}{" << content << "}\n";
+ h_preamble << "\\setcounter{" << name << "}{" << content << "}";
}
else if (t.cs() == "setlength") {
string const name = p.verbatim_item();
string const content = p.verbatim_item();
+ // Is this correct?
if (name == "parskip")
h_paragraph_separation = "skip";
else if (name == "parindent")
h_paragraph_separation = "skip";
else
- h_preamble << "\\setlength{" << name << "}{" << content << "}\n";
+ h_preamble << "\\setlength{" << name << "}{" << content << "}";
}
- else if (t.cs() == "par")
- h_preamble << '\n';
-
else if (t.cs() == "begin") {
string const name = p.getArg('{', '}');
if (name == "document")
}
else if (t.cs().size())
- h_preamble << '\\' << t.cs() << ' ';
+ h_preamble << '\\' << t.cs();
}
+ p.skip_spaces();
// Force textclass if the user wanted it
if (forceclass.size()) {
CatCode theCatcode[256];
-void skipSpaceTokens(istream & is, char c)
-{
- // skip trailing spaces
- while (catcode(c) == catSpace || catcode(c) == catNewline)
- if (!is.get(c))
- break;
- //cerr << "putting back: " << c << "\n";
- is.putback(c);
-}
-
-
void catInit()
{
fill(theCatcode, theCatcode + 256, catOther);
ostream & operator<<(ostream & os, Token const & t)
{
- if (t.cs().size())
+ if (t.cat() == catComment)
+ os << '%' << t.cs() << '\n';
+ else if (t.cat() == catSpace)
+ os << t.cs();
+ else if (t.cat() == catEscape)
os << '\\' << t.cs() << ' ';
else if (t.cat() == catLetter)
os << t.character();
else if (t.cat() == catNewline)
- os << "[\\n," << t.cat() << "]\n";
+ os << "[" << t.cs().size() << "\\n," << t.cat() << "]\n";
else
os << '[' << t.character() << ',' << t.cat() << ']';
return os;
string Token::asInput() const
{
- return char_ ? string(1, char_) : '\\' + cs_ + ' ';
+ if (cat_ == catComment)
+ return '%' + cs_ + '\n';
+ if (cat_ == catSpace || cat_ == catNewline)
+ return cs_;
+ return char_ ? string(1, char_) : '\\' + cs_;
}
Token const & Parser::prev_token() const
+{
+ static const Token dummy;
+ return pos_ > 1 ? tokens_[pos_ - 2] : dummy;
+}
+
+
+Token const & Parser::curr_token() const
{
static const Token dummy;
return pos_ > 0 ? tokens_[pos_ - 1] : dummy;
}
-void Parser::skip_spaces()
+void Parser::skip_spaces(bool skip_comments)
{
- while (1) {
- if (next_token().cat() == catSpace || next_token().cat() == catNewline)
+ // We just silently return if we have no more tokens.
+ // skip_spaces() should be callable at any time,
+ // the caller must check p::good() anyway.
+ while (good()) {
+ if ( next_token().cat() == catSpace ||
+ (next_token().cat() == catNewline && next_token().cs().size() == 1) ||
+ next_token().cat() == catComment && next_token().cs().empty())
get_token();
- else if (next_token().cat() == catComment)
- while (next_token().cat() != catNewline)
- get_token();
+ else if (skip_comments && next_token().cat() == catComment)
+ cerr << " Ignoring comment: " << get_token().asInput();
+ else
+ break;
+ }
+}
+
+
+void Parser::unskip_spaces(bool skip_comments)
+{
+ while (pos_ > 0) {
+ if ( curr_token().cat() == catSpace ||
+ (curr_token().cat() == catNewline && curr_token().cs().size() == 1))
+ putback();
+ else if (skip_comments && curr_token().cat() == catComment) {
+ // TODO: Get rid of this
+ cerr << "Unignoring comment: " << curr_token().asInput();
+ putback();
+ }
else
break;
}
string Parser::getArg(char left, char right)
{
- skip_spaces();
+ skip_spaces(true);
+
+ // This is needed if a partial file ends with a command without arguments,
+ // e. g. \medskip
+ if (! good())
+ return string();
string result;
char c = getChar();
if (c != left)
putback();
else
- while ((c = getChar()) != right && good())
- result += c;
+ while ((c = getChar()) != right && good()) {
+ // Ignore comments
+ if (curr_token().cat() == catComment) {
+ if (curr_token().cs().size())
+ cerr << "Ignoring comment: " << curr_token().asInput();
+ }
+ else if (curr_token().cat() == catSpace || curr_token().cat() == catNewline)
+ result += curr_token().cs();
+ else
+ result += c;
+ }
return result;
}
//cerr << "reading c: " << c << "\n";
switch (catcode(c)) {
+ case catSpace: {
+ string s(1, c);
+ while (is.get(c) && catcode(c) == catSpace)
+ s += c;
+ if (catcode(c) != catSpace)
+ is.putback(c);
+ push_back(Token(s, catSpace));
+ break;
+ }
+
case catNewline: {
++lineno_;
- is.get(c);
- if (catcode(c) == catNewline) {
- //do {
- is.get(c);
- //} while (catcode(c) == catNewline);
- push_back(Token("par"));
- } else {
- push_back(Token('\n', catNewline));
+ string s(1, c);
+ while (is.get(c) && catcode(c) == catNewline) {
+ ++lineno_;
+ s += c;
}
- is.putback(c);
+ if (catcode(c) != catNewline)
+ is.putback(c);
+ push_back(Token(s, catNewline));
break;
}
case catComment: {
- push_back(Token(c, catComment));
+ // We don't treat "%\n" combinations here specially because
+ // we want to preserve them in the preamble
+ string s;
while (is.get(c) && catcode(c) != catNewline)
- push_back(Token(c, catLetter));
- push_back(Token(c, catNewline));
+ s += c;
+ // Note: The '%' at the beginning and the '\n' at the end
+ // of the comment are not stored.
++lineno_;
- is.get(c);
- if (catcode(c) == catNewline) {
- push_back(Token("par"));
- ++lineno_;
- } else {
- is.putback(c);
- }
+ push_back(Token(s, catComment));
break;
}
// collect letters
while (is.get(c) && catcode(c) == catLetter)
s += c;
- skipSpaceTokens(is, c);
+ if (catcode(c) != catLetter)
+ is.putback(c);
}
- push_back(Token(s));
+ push_back(Token(s, catEscape));
}
break;
}
- case catSuper:
- case catSub: {
- push_back(Token(c, catcode(c)));
- is.get(c);
- skipSpaceTokens(is, c);
- break;
- }
-
case catIgnore: {
if (c != 13)
cerr << "ignoring a char: " << int(c) << "\n";
}
-void handle_ert(ostream & os, string const & s, Context const & 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.
+ context.check_layout(os);
+ }
Context newcontext(true, context.textclass);
begin_inset(os, "ERT");
os << "\nstatus Collapsed\n";
}
+void handle_comment(ostream & os, string const & s, Context & context)
+{
+ // TODO: Handle this better
+ Context newcontext(true, context.textclass);
+ begin_inset(os, "ERT");
+ os << "\nstatus Collapsed\n";
+ newcontext.check_layout(os);
+ for (string::const_iterator it = s.begin(), et = s.end(); it != et; ++it) {
+ if (*it == '\\')
+ os << "\n\\backslash \n";
+ else
+ os << *it;
+ }
+ // make sure that our comment is the last thing on the line
+ os << "\n\\newline";
+ newcontext.check_end_layout(os);
+ end_inset(os);
+}
+
+
struct isLayout {
isLayout(string const name) : name_(name) {}
bool operator()(LyXLayout_ptr const & ptr) {
context.check_deeper(os);
context.check_layout(os);
if (context.layout->optionalargs > 0) {
+ p.skip_spaces();
if (p.next_token().character() == '[') {
p.get_token(); // eat '['
begin_inset(os, "OptArg\n");
- os << "collapsed true\n";
+ os << "collapsed true\n\n";
parse_text_in_inset(p, os, FLAG_BRACK_LAST, outer, context);
end_inset(os);
}
parse_text_snippet(p, os, FLAG_ITEM, outer, context);
context.check_end_layout(os);
context.check_end_deeper(os);
+ // We don't need really a new paragraph, but
+ // we must make sure that the next item gets a \begin_layout.
+ parent_context.new_paragraph(os);
}
+/*!
+ * Output a space if necessary.
+ * This function gets called for every whitespace token.
+ *
+ * We have three cases here:
+ * 1. A space must be suppressed. Example: The lyxcode case below
+ * 2. A space may be suppressed. Example: Spaces before "\par"
+ * 3. A space must not be suppressed. Example: A space between two words
+ *
+ * We currently handle only 1. and 3 and from 2. only the case of
+ * spaces before newlines as a side effect.
+ *
+ * 2. could be used to suppress as many spaces as possible. This has two effects:
+ * - Reimporting LyX generated LaTeX files changes almost no whitespace
+ * - Superflous whitespace from non LyX generated LaTeX files is removed.
+ * The drawback is that the logic inside the function becomes
+ * complicated, and that is the reason why it is not implemented.
+ */
+void check_space(Parser const & p, ostream & os, Context & context)
+{
+ Token const next = p.next_token();
+ Token const curr = p.curr_token();
+ // A space before a single newline and vice versa must be ignored
+ // LyX emits a newline before \end{lyxcode}.
+ // This newline must be ignored,
+ // otherwise LyX will add an additional protected space.
+ if (next.cat() == catSpace ||
+ next.cat() == catNewline ||
+ (next.cs() == "end" && context.layout->free_spacing && curr.cat() == catNewline)) {
+ return;
+ }
+ context.check_layout(os);
+ os << ' ';
+}
+
void parse_environment(Parser & p, ostream & os, bool outer,
Context & parent_context)
{
const bool is_starred = suffixIs(name, '*');
string const unstarred_name = rtrim(name, "*");
active_environments.push_back(name);
+ p.skip_spaces();
+
if (is_math_env(name)) {
parent_context.check_layout(os);
begin_inset(os, "Formula ");
os << "placement " << p.getArg('[', ']') << '\n';
}
os << "wide " << tostr(is_starred)
- << "\ncollapsed false\n";
+ << "\ncollapsed false\n\n";
parse_text_in_inset(p, os, FLAG_END, outer, parent_context);
end_inset(os);
+ // We don't need really a new paragraph, but
+ // we must make sure that the next item gets a \begin_layout.
+ parent_context.new_paragraph(os);
}
else if (name == "minipage") {
- parent_context.check_layout(os);
string position = "1";
string inner_pos = "0";
string height = "0pt";
if (p.next_token().asInput() == "[") {
latex_inner_pos = p.getArg('[', ']');
switch(latex_inner_pos[0]) {
- case 't': inner_pos = "0"; break;
- case 'c': inner_pos = "1"; break;
+ case 'c': inner_pos = "0"; break;
+ case 't': inner_pos = "1"; break;
case 'b': inner_pos = "2"; break;
case 's': inner_pos = "3"; break;
default:
ss << '[' << latex_inner_pos << ']';
ss << "{" << width << "}";
handle_ert(os, ss.str(), parent_context);
- parent_context.check_end_layout(os);
- parent_context.need_layout = true;
+ parent_context.new_paragraph(os);
parse_text_in_inset(p, os, FLAG_END, outer, parent_context);
handle_ert(os, "\\end{minipage}", parent_context);
} else {
+ parent_context.check_layout(os);
begin_inset(os, "Minipage\n");
os << "position " << position << '\n';
os << "inner_position " << inner_pos << '\n';
parse_text_in_inset(p, os, FLAG_END, outer, parent_context);
end_inset(os);
}
-
}
- else if (name == "center") {
+ // Alignment settings
+ else if (name == "center" || name == "flushleft" || name == "flushright" ||
+ name == "centering" || name == "raggedright" || name == "raggedleft") {
+ // We must begin a new paragraph if not already done
+ if (! parent_context.atParagraphStart()) {
+ parent_context.check_end_layout(os);
+ parent_context.new_paragraph(os);
+ }
+ if (name == "flushleft" || name == "raggedright")
+ parent_context.extra_stuff += "\\align left ";
+ else if (name == "flushright" || name == "raggedleft")
+ parent_context.extra_stuff += "\\align right ";
+ else
+ parent_context.extra_stuff += "\\align center ";
parse_text(p, os, FLAG_END, outer, parent_context);
+ // Just in case the environment is empty ..
+ parent_context.extra_stuff.erase();
+ // We must begin a new paragraph to reset the alignment
+ parent_context.new_paragraph(os);
}
// The single '=' is meant here.
case LATEX_LIST_ENVIRONMENT:
context.extra_stuff = "\\labelwidthstring "
+ p.verbatim_item() + '\n';
+ p.skip_spaces();
break;
case LATEX_BIB_ENVIRONMENT:
p.verbatim_item(); // swallow next arg
+ p.skip_spaces();
break;
default:
break;
parse_text(p, os, FLAG_END, outer, context);
context.check_end_layout(os);
context.check_end_deeper(os);
+ parent_context.new_paragraph(os);
}
else if (name == "appendix") {
else if (name == "tabbing") {
// We need to remember that we have to handle '\=' specially
- parent_context.check_layout(os);
handle_ert(os, "\\begin{" + name + "}", parent_context);
parse_text_snippet(p, os, FLAG_END | FLAG_TABBING, outer, parent_context);
handle_ert(os, "\\end{" + name + "}", parent_context);
}
else {
- parent_context.check_layout(os);
handle_ert(os, "\\begin{" + name + "}", parent_context);
parse_text_snippet(p, os, FLAG_END, outer, parent_context);
handle_ert(os, "\\end{" + name + "}", parent_context);
}
+
active_environments.pop_back();
+ if (name != "math")
+ p.skip_spaces();
}
} // anonymous namespace
skip_braces(p);
}
+ else if (t.cat() == catSpace || (t.cat() == catNewline && t.cs().size() == 1))
+ check_space(p, os, context);
else if (t.cat() == catLetter ||
- t.cat() == catSpace ||
t.cat() == catOther ||
t.cat() == catAlign ||
t.cat() == catParameter) {
os << t.character();
}
- else if (t.cat() == catNewline) {
- if (p.next_token().cat() == catNewline) {
- // this should have been be done by
- // the parser already
- cerr << "what are we doing here?" << endl;
- p.get_token();
- context.need_layout = true;
- } else {
- os << " "; // note the space
- }
+ else if (t.cat() == catNewline || (t.cat() == catEscape && t.cs() == "par")) {
+ p.skip_spaces();
+ context.new_paragraph(os);
}
else if (t.cat() == catActive) {
}
else if (t.cat() == catBegin) {
-// FIXME???
// special handling of size changes
context.check_layout(os);
bool const is_size = is_known(p.next_token().cs(), known_sizes);
- Context newcontext(false, context.textclass);
-// need_end_layout = false;
- string const s = parse_text(p, FLAG_BRACE_LAST, outer, newcontext);
-// need_end_layout = true;
- if (s.empty() && p.next_token().character() == '`')
- ; // ignore it in {}``
+ Token const prev = p.prev_token();
+ string const s = parse_text(p, FLAG_BRACE_LAST, outer, context);
+ if (s.empty() && (p.next_token().character() == '`' ||
+ (prev.character() == '-' && p.next_token().character())))
+ ; // ignore it in {}`` or -{}-
else if (is_size || s == "[" || s == "]" || s == "*")
os << s;
else {
- handle_ert(os, "{", context);
+ handle_ert(os, "{", context, false);
+ // s will end the current layout and begin a new one if necessary
os << s;
handle_ert(os, "}", context);
}
else if (t.cat() == catEnd) {
if (flags & FLAG_BRACE_LAST) {
- context.check_end_layout(os);
return;
}
cerr << "stray '}' in text\n";
handle_ert(os, "}", context);
}
- else if (t.cat() == catComment)
- handle_comment(p);
+ else if (t.cat() == catComment) {
+ context.check_layout(os);
+ if (t.cs().size()) {
+ handle_comment(os, '%' + t.cs(), context);
+ if (p.next_token().cat() == catNewline) {
+ // A newline after a comment line starts a new paragraph
+ context.new_paragraph(os);
+ p.skip_spaces();
+ }
+ } else {
+ // "%\n" combination
+ p.skip_spaces();
+ }
+ }
//
// control sequences
}
else if (t.cs() == "item") {
- // should be done automatically by Parser::tokenize
- //p.skip_spaces();
+ p.skip_spaces();
string s;
bool optarg = false;
if (p.next_token().character() == '[') {
s = parse_text(p, FLAG_BRACK_LAST, outer, newcontext);
optarg = true;
}
- context.need_layout = true;
- context.has_item = true;
+ context.set_item();
context.check_layout(os);
if (optarg) {
- if (active_environment() == "itemize") {
+ if (context.layout->labeltype != LABEL_MANUAL) {
// lyx does not support \item[\mybullet] in itemize environments
handle_ert(os, "[", context);
os << s;
} else if (s.size()) {
// The space is needed to separate the item from the rest of the sentence.
os << s << ' ';
+ p.skip_spaces();
}
}
}
else if (t.cs() == "bibitem") {
- context.need_layout = true;
- context.has_item = true;
+ context.set_item();
context.check_layout(os);
os << "\\bibitem ";
os << p.getOpt();
}
else if (t.cs() == "def") {
+ p.skip_spaces();
context.check_layout(os);
string name = p.get_token().cs();
while (p.next_token().cat() != catBegin)
handle_ert(os, "\\def\\" + name + '{' + p.verbatim_item() + '}', context);
}
- else if (t.cs() == "par") {
+ else if (t.cs() == "noindent") {
p.skip_spaces();
- context.check_end_layout(os);
- context.need_layout = true;
+ context.extra_stuff += "\\noindent ";
}
else if (t.cs() == "appendix") {
- context.check_end_layout(os);
- Context newcontext(true, context.textclass, context.layout,
- context.layout);
- newcontext.check_layout(os);
- os << "\\start_of_appendix\n";
- parse_text(p, os, FLAG_END, outer, newcontext);
- newcontext.check_end_layout(os);
+ p.skip_spaces();
+ context.extra_stuff += "\\start_of_appendix ";
}
// Must attempt to parse "Section*" before "Section".
newlayout->isCommand()) {
p.get_token();
output_command_layout(os, p, outer, context, newlayout);
+ p.skip_spaces();
}
// The single '=' is meant here.
else if ((newlayout = findLayout(context.textclass, t.cs())).get() &&
newlayout->isCommand()) {
output_command_layout(os, p, outer, context, newlayout);
+ p.skip_spaces();
}
else if (t.cs() == "includegraphics") {
}
else if (t.cs() == "footnote") {
+ p.skip_spaces();
context.check_layout(os);
begin_inset(os, "Foot\n");
- os << "collapsed true\n";
+ os << "collapsed true\n\n";
parse_text_in_inset(p, os, FLAG_ITEM, false, context);
end_inset(os);
}
else if (t.cs() == "marginpar") {
+ p.skip_spaces();
context.check_layout(os);
begin_inset(os, "Marginal\n");
- os << "collapsed true\n";
+ os << "collapsed true\n\n";
parse_text_in_inset(p, os, FLAG_ITEM, false, context);
end_inset(os);
}
else if (t.cs() == "ensuremath") {
+ p.skip_spaces();
context.check_layout(os);
Context newcontext(false, context.textclass);
string s = parse_text(p, FLAG_ITEM, false, newcontext);
context.check_layout(os);
os << "\n\\hfill\n";
skip_braces(p);
+ p.skip_spaces();
}
- else if (t.cs() == "makeindex" || t.cs() == "maketitle")
+ else if (t.cs() == "makeindex" || t.cs() == "maketitle") {
+ p.skip_spaces();
skip_braces(p); // swallow this
+ }
else if (t.cs() == "tableofcontents") {
+ p.skip_spaces();
context.check_layout(os);
begin_inset(os, "LatexCommand \\tableofcontents\n");
end_inset(os);
}
else if (t.cs() == "listoffigures") {
+ p.skip_spaces();
context.check_layout(os);
begin_inset(os, "FloatList figure\n");
end_inset(os);
}
else if (t.cs() == "listoftables") {
+ p.skip_spaces();
context.check_layout(os);
begin_inset(os, "FloatList table\n");
end_inset(os);
}
else if (t.cs() == "listof") {
+ p.skip_spaces(true);
string const name = p.get_token().asString();
if (context.textclass.floats().typeExist(name)) {
context.check_layout(os);
else if (is_known(t.cs(), known_quotes)) {
char const ** where = is_known(t.cs(), known_quotes);
+ context.check_layout(os);
begin_inset(os, "Quotes ");
os << known_coded_quotes[where - known_quotes];
end_inset(os);
char const ** where = is_known(t.cs(), known_sizes);
context.check_layout(os);
os << "\n\\size " << known_coded_sizes[where - known_sizes] << "\n";
+ p.skip_spaces();
}
else if (t.cs() == "LyX" || t.cs() == "TeX"
end_inset(os);
}
+ else if ( t.cs() == "smallskip" ||
+ t.cs() == "medskip" ||
+ t.cs() == "bigskip" ||
+ t.cs() == "vfill" ||
+ (t.cs() == "vspace" && p.next_token().asInput() != "*")) {
+ string arg;
+ if (t.cs() == "vspace")
+ arg = p.getArg('{', '}');
+ else
+ arg = t.cs();
+ // We may only add the vspace to the current context if the
+ // current paragraph is not empty.
+ if (context.atParagraphStart()
+ && (p.next_token().cat() != catNewline || p.next_token().cs().size() == 1)
+ && (! (p.next_token().cat() == catEscape && p.next_token().cs() == "end"))
+ && (! (p.next_token().cat() == catEscape && p.next_token().cs() == "par"))) {
+ context.extra_stuff += "\\added_space_top " + arg + " ";
+ p.skip_spaces();
+ } else {
+ if (t.cs() == "vspace")
+ handle_ert(os, t.asInput() + '{' + arg + '}', context);
+ else
+ handle_ert(os, t.asInput(), context);
+ }
+ // Would be nice to recognize added_space_bottom too...
+ // At the moment this is parsed as added_space_top of the
+ // next paragraph.
+ }
+
else if (t.cs() == "psfrag") {
// psfrag{ps-text}[ps-pos][tex-pos]{tex-text}
// TODO: Generalize this!
arguments += '}';
arguments += p.getOpt();
arguments += p.getOpt();
- p.skip_spaces();
handle_ert(os, "\\psfrag{" + arguments, context);
}
handle_ert(os, s + ' ', context);
*/
context.check_layout(os);
- handle_ert(os, t.asInput() + ' ', context);
+ string name = t.asInput();
+ if (p.next_token().asInput() == "*") {
+ // Starred commands like \vspace*{}
+ p.get_token(); // Eat '*'
+ name += '*';
+ }
+ handle_ert(os, name, context);
}
if (flags & FLAG_LEAVE) {