The attached patch makes tex2lyx output file format 227 with minipages and parboxes converted to frameless box insets. The conversion was starightforward, although I had to change the length functions again. We could simplify the code if LyX would use the LaTeX names for length variables and not "col%" etc.
Jürgen, tex2lyx produces a valid LyX file again with this patch, so I have nothing aginst removing minipages from LyX anymore ;-) Georg
Index: src/tex2lyx/ChangeLog =================================================================== RCS file: /cvs/lyx/lyx-devel/src/tex2lyx/ChangeLog,v retrieving revision 1.43 diff -u -p -r1.43 ChangeLog --- src/tex2lyx/ChangeLog 2003/12/10 08:33:11 1.43 +++ src/tex2lyx/ChangeLog 2003/12/11 20:55:41 @@ -1,3 +1,9 @@ +2003-12-11 Georg Baum <[EMAIL PROTECTED]> + + * preamble.C: Change file format to 227 + * text.C: Convert minipages and parboxes to box insets + * context.[Ch]: New function Context::add_extra_stuff() + 2003-12-08 Georg Baum <[EMAIL PROTECTED]> * text.C: Use the new VSpace inset (fixes a bug with added_space top) Index: src/tex2lyx/context.C =================================================================== RCS file: /cvs/lyx/lyx-devel/src/tex2lyx/context.C,v retrieving revision 1.8 diff -u -p -r1.8 context.C --- src/tex2lyx/context.C 2003/11/05 10:14:12 1.8 +++ src/tex2lyx/context.C 2003/12/11 20:55:41 @@ -12,6 +12,7 @@ #include <iostream> +#include "support/lstrings.h" #include "context.h" using std::ostream; @@ -152,6 +162,13 @@ void Context::new_paragraph(ostream & os { check_end_layout(os); need_layout = true; +} + + +void Context::add_extra_stuff(std::string const & stuff) +{ + if (!lyx::support::contains(extra_stuff, stuff)) + extra_stuff += stuff; } Index: src/tex2lyx/preamble.C =================================================================== RCS file: /cvs/lyx/lyx-devel/src/tex2lyx/preamble.C,v retrieving revision 1.18 diff -u -p -r1.18 preamble.C --- src/tex2lyx/preamble.C 2003/11/19 10:35:50 1.18 +++ src/tex2lyx/preamble.C 2003/12/11 20:55:43 @@ -143,7 +145,7 @@ void handle_package(string const & name, void end_preamble(ostream & os, LyXTextClass const & /*textclass*/) { os << "#LyX file created by tex2lyx 0.1.2 \n" - << "\\lyxformat 225\n" + << "\\lyxformat 227\n" << "\\textclass " << h_textclass << "\n" << "\\begin_preamble\n" << h_preamble.str() << "\n\\end_preamble\n"; if (!h_options.empty()) Index: src/tex2lyx/context.h =================================================================== RCS file: /cvs/lyx/lyx-devel/src/tex2lyx/context.h,v retrieving revision 1.8 diff -u -p -r1.8 context.h --- src/tex2lyx/context.h 2003/11/05 10:14:12 1.8 +++ src/tex2lyx/context.h 2003/12/11 20:55:41 @@ -45,6 +52,9 @@ struct Context { /// Start a new paragraph void new_paragraph(std::ostream & os); + + /// Add extra stuff if not already there + void add_extra_stuff(std::string const &); // Do we need to output some \begin_layout command before the // next characters? Index: src/tex2lyx/text.C =================================================================== RCS file: /cvs/lyx/lyx-devel/src/tex2lyx/text.C,v retrieving revision 1.29 diff -u -p -r1.29 text.C --- src/tex2lyx/text.C 2003/12/10 08:33:11 1.29 +++ src/tex2lyx/text.C 2003/12/11 20:55:52 @@ -38,6 +38,7 @@ using std::vector; using lyx::support::rtrim; using lyx::support::suffixIs; +using lyx::support::contains; // thin wrapper around parse_text using a string @@ -134,7 +135,7 @@ bool splitLatexLength(string const & len if (value == "-") value = "-1.0"; // 'cM' is a valid LaTeX length unit. Change it to 'cm' - if (lyx::support::contains(len, '\\')) + if (contains(len, '\\')) unit = trim(string(len, i)); else unit = lyx::support::lowercase(trim(string(len, i))); @@ -144,13 +145,10 @@ bool splitLatexLength(string const & len // A simple function to translate a latex length to something lyx can // understand. Not perfect, but rather best-effort. -string translate_len(string const & length) +bool translate_len(string const & length, string & valstring, string & unit) { - string unit; - string valstring; - // If the input is invalid, return what we have. if (!splitLatexLength(length, valstring, unit)) - return length; + return false; // LyX uses percent values double value; istringstream iss(valstring); @@ -161,23 +159,64 @@ string translate_len(string const & leng string const percentval = oss.str(); // a normal length if (unit.empty() || unit[0] != '\\') - return valstring + unit; + return true; const string::size_type i = unit.find(" ", i); string const endlen = (i == string::npos) ? string() : string(unit, i); - if (unit == "\\textwidth") - return percentval + "text%" + endlen; - else if (unit == "\\columnwidth") - return percentval + "col%" + endlen; - else if (unit == "\\paperwidth") - return percentval + "page%" + endlen; - else if (unit == "\\linewidth") - return percentval + "line%" + endlen; - else if (unit == "\\paperheight") - return percentval + "pheight%" + endlen; - else if (unit == "\\textheight") - return percentval + "theight%" + endlen; - else - return valstring + unit; + if (unit == "\\textwidth") { + valstring = percentval; + unit = "text%" + endlen; + } else if (unit == "\\columnwidth") { + valstring = percentval; + unit = "col%" + endlen; + } else if (unit == "\\paperwidth") { + valstring = percentval; + unit = "page%" + endlen; + } else if (unit == "\\linewidth") { + valstring = percentval; + unit = "line%" + endlen; + } else if (unit == "\\paperheight") { + valstring = percentval; + unit = "pheight%" + endlen; + } else if (unit == "\\textheight") { + valstring = percentval; + unit = "theight%" + endlen; + } + return true; +} + + +string translate_len(string const & length) +{ + string unit; + string value; + if (translate_len(length, value, unit)) + return value + unit; + // If the input is invalid, return what we have. + return length; +} + + +/*! + * Translates a LaTeX length into \param value, \param unit and \param special parts + * suitable for a box inset. + * The difference from translate_len() is that a box inset knows about some special + * "units" that are stored in \param special. + */ +void translate_box_len(string const & length, string & value, string & unit, string & special) +{ + if (translate_len(length, value, unit)) { + if (unit == "\\height" || unit == "\\depth" || + unit == "\\totalheight" || unit == "\\width") { + special = unit.substr(1); + // The unit is not used, but LyX requires a dummy setting + unit = "in"; + } else + special = "none"; + } else { + value.clear(); + unit = length; + special = "none"; + } } @@ -367,6 +422,90 @@ bool parse_command(string const & comman } +/// Parses a minipage or parbox +void parse_box(Parser & p, ostream & os, unsigned flags, bool outer, + Context & parent_context, bool use_parbox) +{ + string position; + string inner_pos; + string height_value = "0"; + string height_unit = "pt"; + string height_special = "none"; + string latex_height; + if (p.next_token().asInput() == "[") { + position = p.getArg('[', ']'); + if (position != "t" && position != "c" && position != "b") { + position = "c"; + cerr << "invalid position for minipage/parbox" << endl; + } + if (p.next_token().asInput() == "[") { + latex_height = p.getArg('[', ']'); + translate_box_len(latex_height, height_value, height_unit, height_special); + + if (p.next_token().asInput() == "[") { + inner_pos = p.getArg('[', ']'); + if (inner_pos != "c" && inner_pos != "t" && + inner_pos != "b" && inner_pos != "s") { + inner_pos = position; + cerr << "invalid inner_pos for minipage/parbox" + << endl; + } + } + } + } + string width_value; + string width_unit; + string width_special; + string const latex_width = p.verbatim_item(); + translate_box_len(latex_width, width_value, width_unit, width_special); + if (contains(width_unit, "\\") || contains(height_unit, "\\")) { + // LyX can't handle length variables + ostringstream ss; + if (use_parbox) + ss << "\\parbox"; + else + ss << "\\begin{minipage}"; + if (!position.empty()) + ss << '[' << position << ']'; + if (!latex_height.empty()) + ss << '[' << latex_height << ']'; + if (!inner_pos.empty()) + ss << '[' << inner_pos << ']'; + ss << "{" << latex_width << "}"; + if (use_parbox) + ss << '{'; + handle_ert(os, ss.str(), parent_context); + parent_context.new_paragraph(os); + parse_text_in_inset(p, os, flags, outer, parent_context); + if (use_parbox) + handle_ert(os, "}", parent_context); + else + handle_ert(os, "\\end{minipage}", parent_context); + } else { + // LyX does not like empty positions, so we have + // to set them to the LaTeX default values here. + if (position.empty()) + position = "c"; + if (inner_pos.empty()) + inner_pos = position; + parent_context.check_layout(os); + begin_inset(os, "Box Frameless\n"); + os << "position \"" << position << "\"\n"; + os << "hor_pos \"c\"\n"; + os << "has_inner_box 1\n"; + os << "inner_pos \"" << inner_pos << "\"\n"; + os << "use_parbox " << use_parbox << "\n"; + os << "width \"" << width_value << width_unit << "\"\n"; + os << "special \"" << width_special << "\"\n"; + os << "height \"" << height_value << height_unit << "\"\n"; + os << "height_special \"" << height_special << "\"\n"; + os << "collapsed false\n\n"; + parse_text_in_inset(p, os, flags, outer, parent_context); + end_inset(os); + } +} + + void parse_environment(Parser & p, ostream & os, bool outer, Context & parent_context) { @@ -408,72 +568,9 @@ void parse_environment(Parser & p, ostre parent_context.new_paragraph(os); } - else if (name == "minipage") { - string position = "1"; - string inner_pos = "0"; - string height = "0pt"; - string latex_position; - string latex_inner_pos; - string latex_height; - if (p.next_token().asInput() == "[") { - latex_position = p.getArg('[', ']'); - switch(latex_position[0]) { - case 't': position = "0"; break; - case 'c': position = "1"; break; - case 'b': position = "2"; break; - default: - cerr << "invalid position for minipage" - << endl; - break; - } - if (p.next_token().asInput() == "[") { - latex_height = p.getArg('[', ']'); - height = translate_len(latex_height); + else if (name == "minipage") + parse_box(p, os, FLAG_END, outer, parent_context, false); - if (p.next_token().asInput() == "[") { - latex_inner_pos = p.getArg('[', ']'); - switch(latex_inner_pos[0]) { - 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: - cerr << "invalid inner_pos for minipage" - << endl; - break; - } - } - } - } - string width = translate_len(p.verbatim_item()); - if (width[0] == '\\') { - // lyx can't handle length variables - ostringstream ss; - ss << "\\begin{minipage}"; - if (!latex_position.empty()) - ss << '[' << latex_position << ']'; - if (!latex_height.empty()) - ss << '[' << latex_height << ']'; - if (!latex_inner_pos.empty()) - ss << '[' << latex_inner_pos << ']'; - ss << "{" << width << "}"; - handle_ert(os, ss.str(), parent_context); - 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'; - os << "height \"" << height << "\"\n"; - os << "width \"" << width << "\"\n"; - os << "collapsed false\n\n"; - parse_text_in_inset(p, os, FLAG_END, outer, parent_context); - end_inset(os); - } - } - // Alignment settings else if (name == "center" || name == "flushleft" || name == "flushright" || name == "centering" || name == "raggedright" || name == "raggedleft") { @@ -483,11 +580,11 @@ void parse_environment(Parser & p, ostre parent_context.new_paragraph(os); } if (name == "flushleft" || name == "raggedright") - parent_context.extra_stuff += "\\align left "; + parent_context.add_extra_stuff("\\align left "); else if (name == "flushright" || name == "raggedleft") - parent_context.extra_stuff += "\\align right "; + parent_context.add_extra_stuff("\\align right "); else - parent_context.extra_stuff += "\\align center "; + parent_context.add_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(); @@ -796,12 +916,12 @@ void parse_text(Parser & p, ostream & os else if (t.cs() == "noindent") { p.skip_spaces(); - context.extra_stuff += "\\noindent "; + context.add_extra_stuff("\\noindent "); } else if (t.cs() == "appendix") { p.skip_spaces(); - context.extra_stuff += "\\start_of_appendix "; + context.add_extra_stuff("\\start_of_appendix "); } // Must attempt to parse "Section*" before "Section". @@ -1269,6 +1389,9 @@ void parse_text(Parser & p, ostream & os os << '{' << p.verbatim_item() << "}\n"; end_inset(os); } + + else if (t.cs() == "parbox") + parse_box(p, os, FLAG_ITEM, outer, context, true); else if (t.cs() == "smallskip" || t.cs() == "medskip" ||