The attached patch makes tex2lyx output an Inset VSpace where possible for 
vertical spaces. Unfortunately it needed more code than I thought to handle 
corner cases correctly. There are some overlaps with lyxlength.C 
(translate_len() could vanish), but lyxlength.C needs some bufferview 
stuff, so this cannot be used in the current form for tex2lyx.
However, I think that in the long term the length handling in LyX should be 
unified. See the comment about "text%" in lengthcommon.h. I also see no 
reason to disallow the use of \textheight etc. in the vspace inset, if 
literal lengths are allowed.

A few testcases can be found in vspace-test2.tex.

Comments?

Georg
Index: lib/ChangeLog
===================================================================
RCS file: /cvs/lyx/lyx-devel/lib/ChangeLog,v
retrieving revision 1.548
diff -u -p -r1.548 ChangeLog
--- lib/ChangeLog	2003/12/06 09:31:29	1.548
+++ lib/ChangeLog	2003/12/06 20:30:03
@@ -1,3 +1,7 @@
+2003-12-06  Georg Baum  <[EMAIL PROTECTED]>
+
+	* reLyX/syntax.default: add \psfrag and \psfrag*
+
 2003-12-06  Martin Vermeer  <[EMAIL PROTECTED]>
 
 	* db_stdclass.inc:
Index: lib/reLyX/syntax.default
===================================================================
RCS file: /cvs/lyx/lyx-devel/lib/reLyX/syntax.default,v
retrieving revision 1.7
diff -u -p -r1.7 syntax.default
--- lib/reLyX/syntax.default	2003/02/11 13:32:13	1.7
+++ lib/reLyX/syntax.default	2003/12/06 20:30:11
@@ -545,6 +545,8 @@ $$
 \providecommand{}[][]{}
 \providecommand*{}[][]{}
 \ps
+\psfrag{}[][][][]{translate}
+\psfrag*{}[][][][]{translate}
 \pushtabs
 % \put(,){}     %picture
 % \qbezier[](,)(,)(,)     %picture
Index: src/tex2lyx/ChangeLog
===================================================================
RCS file: /cvs/lyx/lyx-devel/src/tex2lyx/ChangeLog,v
retrieving revision 1.42
diff -u -p -r1.42 ChangeLog
--- src/tex2lyx/ChangeLog	2003/11/19 10:35:50	1.42
+++ src/tex2lyx/ChangeLog	2003/12/06 20:30:24
@@ -1,3 +1,14 @@
+2003-12-06  Georg Baum  <[EMAIL PROTECTED]>
+
+	* text.C: Use the new VSpace inset (fixes a bug with added_space top)
+	* text.C: Fix \= in tabbing env again
+	* text.C: Fix invocation of parse_command()
+
 2003-11-18  Georg Baum  <[EMAIL PROTECTED]>
 
 	* tex2lyx.C:
Index: src/tex2lyx/Makefile.am
===================================================================
RCS file: /cvs/lyx/lyx-devel/src/tex2lyx/Makefile.am,v
retrieving revision 1.15
diff -u -p -r1.15 Makefile.am
--- src/tex2lyx/Makefile.am	2003/10/17 23:41:14	1.15
+++ src/tex2lyx/Makefile.am	2003/12/06 20:30:24
@@ -18,6 +19,7 @@ BUILT_SOURCES = \
 	FloatList.C \
 	Floating.C \
 	counters.C \
+	lengthcommon.C \
 	lyxlayout.h \
 	lyxlayout.C \
 	lyxtextclass.C \
Index: src/tex2lyx/text.C
===================================================================
RCS file: /cvs/lyx/lyx-devel/src/tex2lyx/text.C,v
retrieving revision 1.28
diff -u -p -r1.28 text.C
--- src/tex2lyx/text.C	2003/11/19 10:35:50	1.28
+++ src/tex2lyx/text.C	2003/12/06 20:30:33
@@ -16,6 +16,7 @@
 #include "tex2lyx.h"
 #include "context.h"
 #include "FloatList.h"
+#include "lengthcommon.h"
 #include "support/lstrings.h"
 #include "support/tostr.h"
 #include "support/filetools.h"
@@ -103,45 +104,80 @@ map<string, string> split_map(string con
 	return res;
 }
 
-// A simple function to translate a latex length to something lyx can
-// understand. Not perfect, but rather best-effort.
-string translate_len(string const & len)
+
+/*!
+ * Split a LaTeX length into value and unit.
+ * The latter can be a real unit like "pt", or a latex length variable
+ * like "\textwidth". The unit may contain additional stuff like glue
+ * lengths, but we don't care, because such lengths are ERT anyway.
+ * \return true if \param value and \param unit are valid.
+ */
+bool splitLatexLength(string const & len, string & value, string & unit)
 {
-	const string::size_type i = len.find_first_not_of(" -0123456789.,");
+	if (len.empty())
+		return false;
+	const string::size_type i = len.find_first_not_of(" -+0123456789.,");
 	//'4,5' is a valid LaTeX length number. Change it to '4.5'
 	string const length = lyx::support::subst(len, ',', '.');
-	// a normal length
-	if (i == string::npos || len[i]  != '\\')
-		return length;
-	double val;
+	if (i == string::npos)
+		return false;
 	if (i == 0) {
-		// We had something like \textwidth without a factor
-		val = 100;
+		if (len[0] == '\\') {
+			// We had something like \textwidth without a factor
+			value = "1.0";
+		} else {
+			return false;
+		}
 	} else {
-		istringstream iss(string(length, 0, i));
-		iss >> val;
-		val = val * 100;
+		value = trim(string(length, 0, i));
 	}
+	if (value == "-")
+		value = "-1.0";
+	// 'cM' is a valid LaTeX length unit. Change it to 'cm'
+	if (lyx::support::contains(len, '\\'))
+		unit = trim(string(len, i));
+	else
+		unit = lyx::support::lowercase(trim(string(len, i)));
+	return true;
+}
+
+
+// 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)
+{
+	string unit;
+	string valstring;
+	// If the input is invalid, return what we have.
+	if (!splitLatexLength(length, valstring, unit))
+		return length;
+	// LyX uses percent values
+	double value;
+	istringstream iss(valstring);
+	iss >> value;
+	value *= 100;
 	ostringstream oss;
-	oss << val;
-	string const valstring = oss.str();
-	const string::size_type i2 = length.find(" ", i);
-	string const unit = string(len, i, i2 - i);
-	string const endlen = (i2 == string::npos) ? string() : string(len, i2);
+	oss << value;
+	string const percentval = oss.str();
+	// a normal length
+	if (unit.empty() || unit[0] != '\\')
+		return valstring + unit;
+	const string::size_type i = unit.find(" ", i);
+	string const endlen = (i == string::npos) ? string() : string(unit, i);
 	if (unit == "\\textwidth")
-		return valstring + "text%" + endlen;
+		return percentval + "text%" + endlen;
 	else if (unit == "\\columnwidth")
-		return valstring + "col%" + endlen;
+		return percentval + "col%" + endlen;
 	else if (unit == "\\paperwidth")
-		return valstring + "page%" + endlen;
+		return percentval + "page%" + endlen;
 	else if (unit == "\\linewidth")
-		return valstring + "line%" + endlen;
+		return percentval + "line%" + endlen;
 	else if (unit == "\\paperheight")
-		return valstring + "pheight%" + endlen;
+		return percentval + "pheight%" + endlen;
 	else if (unit == "\\textheight")
-		return valstring + "theight%" + endlen;
+		return percentval + "theight%" + endlen;
 	else
-		return length;
+		return valstring + unit;
 }
 
 
@@ -1151,8 +1248,11 @@ void parse_text(Parser & p, ostream & os
 		// Problem: \= creates a tabstop inside the tabbing environment
 		// and else an accent. In the latter case we really would want
 		// \={o} instead of \= o.
+		else if (t.cs() == "=" && (flags & FLAG_TABBING))
+			handle_ert(os, t.asInput(), context);
+
 		else if (t.cs() == "H" || t.cs() == "c" || t.cs() == "^" || t.cs() == "'"
-		      || t.cs() == "~" || t.cs() == "." || (t.cs() == "=" && ! (flags & FLAG_TABBING))) {
+		      || t.cs() == "~" || t.cs() == "." || t.cs() == "=") {
 			// we need the trim as the LyX parser chokes on such spaces
 			context.check_layout(os);
 			os << "\n\\i \\" << t.cs() << "{"
@@ -1231,33 +1331,93 @@ void parse_text(Parser & p, ostream & os
 			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() == "smallskip" ||
+		         t.cs() == "medskip" ||
+			 t.cs() == "bigskip" ||
+			 t.cs() == "vfill") {
+			context.check_layout(os);
+			begin_inset(os, "VSpace ");
+			os << t.cs();
+			end_inset(os);
+		}
+
+		else if (t.cs() == "vspace") {
+			bool starred = false;
+			if (p.next_token().asInput() == "*") {
+				p.get_token();
+				starred = true;
+			}
+			string const length = p.verbatim_item();
+			string unit;
+			string valstring;
+			bool valid = splitLatexLength(length, valstring, unit);
+			bool known_vspace = false;
+			bool known_unit = false;
+			double value;
+			if (valid) {
+				istringstream iss(valstring);
+				iss >> value;
+				if (value == 1.0) {
+					if (unit == "\\smallskipamount") {
+						unit = "smallskip";
+						known_vspace = true;
+					} else if (unit == "\\medskipamount") {
+						unit = "medskip";
+						known_vspace = true;
+					} else if (unit == "\\bigskipamount") {
+						unit = "bigskip";
+						known_vspace = true;
+					} else if (unit == "\\fill") {
+						unit = "vfill";
+						known_vspace = true;
+					}
+				} else {
+					switch (unitFromString(unit)) {
+					case LyXLength::SP:
+					case LyXLength::PT:
+					case LyXLength::BP:
+					case LyXLength::DD:
+					case LyXLength::MM:
+					case LyXLength::PC:
+					case LyXLength::CC:
+					case LyXLength::CM:
+					case LyXLength::IN:
+					case LyXLength::EX:
+					case LyXLength::EM:
+					case LyXLength::MU:
+						known_unit = true;
+						break;
+					default:
+						break;
+					}
+				}
+			}
+
+			if (known_unit || known_vspace) {
+				// Literal length or known variable
+				context.check_layout(os);
+				begin_inset(os, "VSpace ");
+				if (known_unit)
+					os << value;
+				os << unit;
+				if (starred)
+					os << '*';
+				end_inset(os);
 			} else {
-				if (t.cs() == "vspace")
-					handle_ert(os, t.asInput() + '{' + arg + '}', context);
-				else
-					handle_ert(os, t.asInput(), context);
+				// LyX can't handle other length variables in Inset VSpace
+				string name = t.asInput();
+				if (starred)
+					name += '*';
+				if (valid) {
+					if (value == 1.0)
+						handle_ert(os, name + '{' + unit + '}', context);
+					else if (value == -1.0)
+						handle_ert(os, name + "{-" + unit + '}', context);
+					else
+						handle_ert(os, name + '{' + valstring + unit + '}', context);
+				} else
+					handle_ert(os, name + '{' + length + '}', 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 {
@@ -1280,7 +1440,7 @@ void parse_text(Parser & p, ostream & os
 				p.get_token();				// Eat '*'
 				name += '*';
 			}
-			if (! parse_command(t.asInput(), p, os, outer, context))
+			if (! parse_command(name, p, os, outer, context))
 				handle_ert(os, name, context);
 		}
 
\documentclass{book}
\begin{document}
bla bla
\vspace*{0.5cm}
x
\vspace{ 0.5cm }
x
\vspace{ 0.5cm}
x
\vspace{-0.5cm}
x
\vspace{+0.5cm}
x
\vspace{ 0,5cm}
x
\vspace{0,5cM}
x
\vspace{0,5cM plus 3pt}
x
\vspace{0,5cM plus 3pt minus 2pt}
x
\vspace{0.2\textwidth}
x
\vspace{\textwidth}
x
\vspace{-\textwidth}
x
\vspace{\smallskipamount}
x
\vspace*{\smallskipamount}
x
\vspace*{0.3\smallskipamount}
x
\vspace*{\fill}
x
\vfill
x
\end{document}

Reply via email to