Am Montag, 17. Oktober 2005 16:40 schrieb Bennett Helm:
> Opening old beamer presentations results in a crash. The problem is  
> that the beamer.layout file contains the following line:
> 
> MaxCounter        Counter_Section
> 
> (In fact, any .layout file with this line in it will cause LyX to  
> crash.) Commenting out this line in the .layout file enables  
> everything to work.

This reminds me of the layout file converter that I sent some days ago. It 
will convert old layout files to the new format. There was a discussion 
how to call it from LyX, but nobody commented on my questions whether we 
want it in 1.4.0
IMO, it should be included. We put a lot of work into lyx2lyx to convert 
old .lyx files properly. This work would be in part useless if we do not 
maintain layout file compatibility, especially since we encourage users 
to create their own layout file if they use custom document classes.
I have thought about the 'how' question again and came up with the 
attached patch. It adds version information to the layout files, and LyX 
will convert the layout files if the version information is missing.
I prefer this approach over doing the conversion in configure, since it 
guarantees that every layout file that LyX reads is in the correct 
format.
The changes are isolated and well tested, so the risk of breaking 
something is very low. You will get some warnings about already existing 
counters if you test this, but they are harmless and will disappear if 
all layout files have the version number added (which would be done of 
course if the patch goes in).
I would really like to put this in. Cooments?


Georg
diff -p -r -U 3 -X excl.tmp lyx-1.4-clean/lib/ChangeLog lyx-1.4-cvs/lib/ChangeLog
--- lyx-1.4-clean/lib/ChangeLog	2005-10-12 20:36:22.000000000 +0200
+++ lyx-1.4-cvs/lib/ChangeLog	2005-10-19 23:02:40.000000000 +0200
@@ -1,3 +1,8 @@
+2005-10-19  Georg Baum  <[EMAIL PROTECTED]>
+
+	* scripts/layout2layout.py: new layout file converter
+	* Makefile.am: install scripts/layout2layout.py
+
 2005-10-12  Hartmut Haase  <[EMAIL PROTECTED]>
 
 	* example/de_Minipage.lyx: update.
diff -p -r -U 3 -X excl.tmp lyx-1.4-clean/lib/Makefile.am lyx-1.4-cvs/lib/Makefile.am
--- lyx-1.4-clean/lib/Makefile.am	2005-07-31 13:55:59.000000000 +0200
+++ lyx-1.4-cvs/lib/Makefile.am	2005-10-12 13:47:19.000000000 +0200
@@ -848,6 +851,7 @@ dist_scripts_DATA = \
 	scripts/fig2pdftex.sh \
 	scripts/fig2pstex.sh \
 	scripts/fig_copy.sh \
+	scripts/layout2layout.py \
 	scripts/legacy_lyxpreview2ppm.py \
 	scripts/listerrors \
 	scripts/lyxpreview2bitmap.py \
diff -p -r -U 3 -X excl.tmp lyx-1.4-clean/lib/scripts/layout2layout.py lyx-1.4-cvs/lib/scripts/layout2layout.py
--- lyx-1.4-clean/lib/scripts/layout2layout.py	2005-10-19 20:59:26.000000000 +0200
+++ lyx-1.4-cvs/lib/scripts/layout2layout.py	2005-10-19 23:00:15.000000000 +0200
@@ -0,0 +1,146 @@
+#! /usr/bin/env python
+# -*- coding: iso-8859-1 -*-
+
+# file layout2layout.py
+# This file is part of LyX, the document processor.
+# Licence details can be found in the file COPYING.
+
+# author Georg Baum
+
+# Full author contact details are available in file CREDITS
+
+# This script will update a .layout file to format 2
+
+
+import os, re, string, sys
+
+
+def usage(prog_name):
+    return ("Usage: %s inputfile outputfile\n" % prog_name +
+            "or     %s <inputfile >outputfile" % prog_name)
+
+
+def error(message):
+    sys.stderr.write(message + '\n')
+    sys.exit(1)
+
+
+def trim_eol(line):
+    " Remove end of line char(s)."
+    if line[-2:-1] == '\r':
+        return line[:-2]
+    else:
+        return line[:-1]
+
+
+def read(input):
+    " Read input file and strip lineendings."
+    lines = list()
+    while 1:
+        line = input.readline()
+        if not line:
+            break
+        lines.append(trim_eol(line))
+    return lines
+
+
+def write(output, lines):
+    " Write output file with native lineendings."
+    for line in lines:
+        output.write(line + os.linesep)
+
+
+def convert(lines):
+    " Convert to new format."
+    re_Comment = re.compile(r'^(\s*)#')
+    re_Empty = re.compile(r'^(\s*)$')
+    re_Format = re.compile(r'^(\s*)(Format)(\s+)(\S+)', re.IGNORECASE)
+    re_Preamble = re.compile(r'^(\s*)Preamble', re.IGNORECASE)
+    re_EndPreamble = re.compile(r'^(\s*)EndPreamble', re.IGNORECASE)
+    re_MaxCounter = re.compile(r'^\s*MaxCounter', re.IGNORECASE)
+    re_LabelType = re.compile(r'^(\s*)(LabelType)(\s+)(\S+)', re.IGNORECASE)
+
+    i = 0
+    only_comment = 1
+    while i < len(lines):
+
+        # Skip comments and empty lines
+        if re_Comment.match(lines[i]) or re_Empty.match(lines[i]):
+            i = i + 1
+            continue
+
+	# insert file format if not already there
+        if (only_comment):
+                match = re_Format.match(lines[i])
+                if match:
+                        format = match.group(4)
+                        if format == '2':
+                                # nothing to do
+                                return
+                        error('Cannot convert file format %s' % format)
+                else:
+	                lines.insert(i, "Format 2")
+                        only_comment = 0
+                        continue
+
+        # Don't get confused by LaTeX code
+        if re_Preamble.match(lines[i]):
+            i = i + 1
+            while i < len(lines) and not re_EndPreamble.match(lines[i]):
+                i = i + 1
+            continue
+
+        # Delete MaxCounter
+        if re_MaxCounter.match(lines[i]):
+            del lines[i]
+            continue
+
+        # Replace line
+        #
+        # LabelType Counter_EnumI
+        #
+        # with two lines
+        #
+        # LabelType Counter
+        # LabelCounter EnumI
+        #
+        match = re_LabelType.match(lines[i])
+        if match:
+            label = match.group(4)
+            if string.lower(label[:8]) == "counter_":
+                counter = label[8:]
+                lines[i] = re_LabelType.sub(r'\1\2\3Counter', lines[i])
+                # use the same indentation
+                space1 = match.group(1)
+                lines.insert(i + 1, "%sLabelCounter %s" % (space1, counter))
+
+        i = i + 1
+
+
+def main(argv):
+
+    # Open files
+    if len(argv) == 1:
+        input = sys.stdin
+        output = sys.stdout
+    elif len(argv) == 3:
+        input = open(argv[1], 'rb')
+        output = open(argv[2], 'wb')
+    else:
+        error(usage(argv[0]))
+
+    # Do the real work
+    lines = read(input)
+    convert(lines)
+    write(output, lines)
+
+    # Close files
+    if len(argv) == 3:
+        input.close()
+        output.close()
+
+    return 0
+
+
+if __name__ == "__main__":
+    main(sys.argv)
diff -p -r -U 3 -X excl.tmp lyx-1.4-clean/src/ChangeLog lyx-1.4-cvs/src/ChangeLog
--- lyx-1.4-clean/src/ChangeLog	2005-10-19 20:54:28.000000000 +0200
+++ lyx-1.4-cvs/src/ChangeLog	2005-10-19 22:24:13.000000000 +0200
@@ -1,3 +1,8 @@
+2005-10-19  Georg Baum  <[EMAIL PROTECTED]>
+
+	* lyxtextclass.C (Read): convert layout file if the format is wrong
+	* lyxtextclass.C (layout2layout): new, needed for the above
+
 2005-10-18  Jean-Marc Lasgouttes  <[EMAIL PROTECTED]>
 
 	* messages.C: do not forget to include <cerrno>.
diff -p -r -U 3 -X excl.tmp lyx-1.4-clean/src/lyxtextclass.C lyx-1.4-cvs/src/lyxtextclass.C
--- lyx-1.4-clean/src/lyxtextclass.C	2005-06-10 18:46:35.000000000 +0200
+++ lyx-1.4-cvs/src/lyxtextclass.C	2005-10-19 23:09:11.717593784 +0200
@@ -22,10 +22,14 @@
 #include "FloatList.h"
 
 #include "support/lstrings.h"
+#include "support/lyxlib.h"
 #include "support/filetools.h"
 
+#include <sstream>
+
 using lyx::support::LibFileSearch;
 using lyx::support::MakeDisplayPath;
+using lyx::support::QuoteName;
 using lyx::support::rtrim;
 using lyx::support::subst;
 
@@ -51,6 +55,37 @@ private:
 	string name_;
 };
 
+
+int const FORMAT = 2;
+
+
+bool layout2layout(string const & filename, string const & tempfile)
+{
+	string const script = LibFileSearch("scripts", "layout2layout.py");
+	if (script.empty()) {
+		lyxerr << "Could not find layout conversion "
+		          "script layout2layout.py." << endl;
+		return false;
+	}
+
+	std::ostringstream command;
+	command << "python " << QuoteName(script)
+		<< ' ' << QuoteName(filename)
+		<< ' ' << QuoteName(tempfile);
+	string const command_str = command.str();
+
+	lyxerr[Debug::TCLASS] << "Running '" << command_str << '\'' << endl;
+
+	lyx::support::cmd_ret const ret =
+		lyx::support::RunCommand(command_str);
+	if (ret.first != 0) {
+		lyxerr << "Could not run layout conversion "
+		          "script layout2layout.py." << endl;
+		return false;
+	}
+	return true;
+}
+
 } // namespace anon
 
 
@@ -124,9 +159,11 @@ enum TextClassTags {
 	TC_COUNTER,
 	TC_NOFLOAT,
 	TC_TITLELATEXNAME,
-	TC_TITLELATEXTYPE
+	TC_TITLELATEXTYPE,
+	TC_FORMAT
 };
 
+
 // Reads a textclass structure from file.
 bool LyXTextClass::Read(string const & filename, bool merge)
 {
@@ -139,6 +176,7 @@ bool LyXTextClass::Read(string const & f
 		{ "defaultstyle",    TC_DEFAULTSTYLE },
 		{ "environment",     TC_ENVIRONMENT },
 		{ "float",           TC_FLOAT },
+		{ "format",          TC_FORMAT },
 		{ "input",           TC_INPUT },
 		{ "leftmargin",      TC_LEFTMARGIN },
 		{ "nofloat",         TC_NOFLOAT },
@@ -170,10 +208,12 @@ bool LyXTextClass::Read(string const & f
 
 	LyXLex lexrc(textClassTags,
 		sizeof(textClassTags) / sizeof(textClassTags[0]));
-	bool error = false;
 
 	lexrc.setFile(filename);
-	if (!lexrc.isOK()) error = true;
+	bool error = !lexrc.isOK();
+
+	// Format of files before the 'Format' tag was introduced
+	int format = 1;
 
 	// parsing
 	while (lexrc.isOK() && !error) {
@@ -194,6 +234,11 @@ bool LyXTextClass::Read(string const & f
 
 		switch (static_cast<TextClassTags>(le)) {
 
+		case TC_FORMAT:
+			if (lexrc.next())
+				format = lexrc.getInteger();
+			break;
+
 		case TC_OUTPUTTYPE:   // output type definition
 			readOutputType(lexrc);
 			break;
@@ -373,6 +418,19 @@ bool LyXTextClass::Read(string const & f
 			}
 			break;
 		}
+		if (format != FORMAT)
+			break;
+	}
+
+	if (format != FORMAT) {
+		lyxerr[Debug::TCLASS] << "Converting layout file from format "
+		                      << format << " to " << FORMAT << endl;
+		string const tempfile = lyx::support::tempName();
+		error = !layout2layout(filename, tempfile);
+		if (!error)
+			error = Read(tempfile, merge);
+		lyx::support::unlink(tempfile);
+		return error;
 	}
 
 	if (!merge) { // we are at top level here.

Reply via email to