The cause of the bug is that the counter-reading code overwrites an existing counter when it is read again, rather than updating it, as for other bits of layout information. This patch fixes the bug and, along the way, makes the counter-reading code more like the style-reading code. The bulk of it is moved to Counters.cpp.

The counter syntax is changed from:
   Counter
      Name cnt
to the more sensible:
   Counter cnt
This is more like styles, etc, and makes the code in TextClass::read() parallel to that for styles.

I've checked this and it seems to work. Comments welcome.

If it's committed, then we'll want to update all the files containing counters to the new format.

Richard

Index: src/Counters.h
===================================================================
--- src/Counters.h	(revision 26762)
+++ src/Counters.h	(working copy)
@@ -23,6 +23,8 @@
 
 namespace lyx {
 
+class Lexer;
+
 /// This represents a single counter.
 class Counter {
 public:
@@ -31,6 +33,8 @@
 	///
 	Counter(docstring const & mc, docstring const & ls, 
 		docstring const & lsa);
+	/// \return true on success
+	bool read(Lexer & lex);
 	///
 	void set(int v);
 	///
@@ -44,27 +48,27 @@
 	/// Returns the master counter of this counter.
 	docstring const & master() const;
 	/// Returns a LaTeX-like string to format the counter. 
-	/* This is similar to what one gets in LaTeX when using
-	 * "\the<counter>".
+	/** This is similar to what one gets in LaTeX when using
+	 *  "\the<counter>".
 	 */
 	docstring const & labelString() const;
 	/// Returns a LaTeX-like string to format the counter in appendix.
-	/* This is similar to what one gets in LaTeX when using
-	 * "\the<counter>" in an appendix.
+	/** This is similar to what one gets in LaTeX when using
+	 *  "\the<counter>" in an appendix.
 	 */
 	docstring const & labelStringAppendix() const;
 private:
 	///
 	int value_;
 	/// contains master counter name.
-	/* The master counter is the counter that, if stepped
-	 * (incremented) zeroes this counter. E.g. "subsection"'s
-	 * master is "section".
+	/** The master counter is the counter that, if stepped
+	 *  (incremented) zeroes this counter. E.g. "subsection"'s
+	 *  master is "section".
 	 */
 	docstring master_;
-	// Contains a LaTeX-like string to format the counter.
+	/// Contains a LaTeX-like string to format the counter.
 	docstring labelstring_;
-	// The same as labelstring_, but in appendices.
+	/// The same as labelstring_, but in appendices.
 	docstring labelstringappendix_;
 };
 
@@ -84,6 +88,9 @@
 			docstring const & lsa);
 	/// Checks whether the given counter exists.
 	bool hasCounter(docstring const & c) const;
+	/// reads the counter name
+	/// \return true on success
+	bool read(Lexer & lex, docstring const & name);
 	///
 	void set(docstring const & ctr, int val);
 	///
@@ -92,8 +99,8 @@
 	int value(docstring const & ctr) const;
 	/// Increment by one counter named by arg, and zeroes slave
 	/// counter(s) for which it is the master.
-	/* Sub-slaves not zeroed! That happens at slave's first step
-	 * 0->1. Seems to be sufficient.
+	/** Sub-slaves not zeroed! That happens at slave's first step
+	 *  0->1. Seems to be sufficient.
 	 */
 	void step(docstring const & ctr);
 	/// Reset all counters.
@@ -129,9 +136,9 @@
 	                     std::set<docstring> & callers);
 	/// Returns the value of the counter according to the
 	/// numbering scheme numbertype.
-	/* Available numbering schemes are arabic (1, 2,...), roman
-	 * (i, ii,...), Roman (I, II,...), alph (a, b,...), Alpha (A,
-	 * B,...) and hebrew.
+	/** Available numbering schemes are arabic (1, 2,...), roman
+	 *  (i, ii,...), Roman (I, II,...), alph (a, b,...), Alpha (A,
+	 *  B,...) and hebrew.
 	 */
 	docstring labelItem(docstring const & ctr,
 			    docstring const & numbertype);
Index: src/Counters.cpp
===================================================================
--- src/Counters.cpp	(revision 26762)
+++ src/Counters.cpp	(working copy)
@@ -15,6 +15,8 @@
 
 #include "Counters.h"
 
+#include "Lexer.h"
+
 #include "support/convert.h"
 #include "support/debug.h"
 #include "support/lstrings.h"
@@ -43,6 +45,63 @@
 }
 
 
+bool Counter::read(Lexer & lex)
+{
+	enum {
+		CT_WITHIN = 1,
+		CT_LABELSTRING,
+		CT_LABELSTRING_APPENDIX,
+		CT_END
+	};
+
+	LexerKeyword counterTags[] = {
+		{ "end", CT_END },
+		{ "labelstring", CT_LABELSTRING },
+		{ "labelstringappendix", CT_LABELSTRING_APPENDIX },
+		{ "within", CT_WITHIN }
+	};
+
+	lex.pushTable(counterTags);
+
+	bool getout = false;
+	while (!getout && lex.isOK()) {
+		int le = lex.lex();
+		switch (le) {
+			case Lexer::LEX_UNDEF:
+				lex.printError("Unknown counter tag `$$Token'");
+				continue;
+			default: 
+				break;
+		}
+		switch (le) {
+			case CT_WITHIN:
+				lex.next();
+				master_ = lex.getDocString();
+				if (master_ == "none")
+					master_.erase();
+				break;
+			case CT_LABELSTRING:
+				lex.next();
+				labelstring_ = lex.getDocString();
+				labelstringappendix_ = labelstring_;
+				break;
+			case CT_LABELSTRING_APPENDIX:
+				lex.next();
+				labelstringappendix_ = lex.getDocString();
+				break;
+			case CT_END:
+				getout = true;
+				break;
+		}
+	}
+
+	// Here if have a full counter if getout == true
+	if (!getout)
+		LYXERR0("No End tag found for counter!");
+	lex.popTable();
+	return getout;
+}
+
 void Counter::set(int v)
 {
 	value_ = v;
@@ -112,6 +171,23 @@
 }
 
 
+bool Counters::read(Lexer & lex, docstring const & name)
+{
+	if (hasCounter(name)) {
+		LYXERR(Debug::TCLASS, "Reading existing counter " << to_utf8(name));
+		return counterList[name].read(lex);
+	}
+	LYXERR(Debug::TCLASS, "Reading new counter " << to_utf8(name));
+	Counter cnt;
+	bool success = cnt.read(lex);
+	if (success)
+		counterList[name] = cnt;
+	else
+		LYXERR0("Error reading counter `" << name << "'!");
+	return success;
+}
+
+
 void Counters::set(docstring const & ctr, int const val)
 {
 	CounterList::iterator const it = counterList.find(ctr);
Index: src/TextClass.h
===================================================================
--- src/TextClass.h	(revision 26762)
+++ src/TextClass.h	(working copy)
@@ -305,8 +305,6 @@
 	void readCharStyle(Lexer &, std::string const &);
 	///
 	void readFloat(Lexer &);
-	///
-	void readCounter(Lexer &);
 };
 
 
Index: src/TextClass.cpp
===================================================================
--- src/TextClass.cpp	(revision 26762)
+++ src/TextClass.cpp	(working copy)
@@ -61,7 +61,7 @@
 };
 
 
-int const FORMAT = 9;
+int const FORMAT = 10;
 
 
 bool layout2layout(FileName const & filename, FileName const & tempfile)
@@ -223,13 +223,14 @@
 
 bool TextClass::convertLayoutFormat(support::FileName const & filename, ReadType rt)
 {
-	LYXERR(Debug::TCLASS, "Converting layout file to " << FORMAT);
-		FileName const tempfile = FileName::tempName("convert_layout");
-		bool success = layout2layout(filename, tempfile);
-		if (success)
-			success = read(tempfile, rt);
-		tempfile.removeFile();
-		return success;
+	FileName const tempfile = FileName::tempName("convert_layout");
+	LYXERR(Debug::TCLASS, "Converting layout file " << filename << 
+			" to temporary " << tempfile << ", format " << FORMAT);
+	bool success = layout2layout(filename, tempfile);
+	if (success)
+		success = read(tempfile, rt);
+	tempfile.removeFile();
+	return success;
 }
 
 bool TextClass::read(FileName const & filename, ReadType rt)
@@ -261,8 +262,8 @@
 	
 	bool const worx = convertLayoutFormat(filename, rt);
 	if (!worx) {
-		lyxerr << "Unable to convert " << filename << 
-			" to format " << FORMAT << std::endl;
+		LYXERR0("Unable to convert " << filename <<
+			" to format " << FORMAT);
 		return false;
 	}
 	return true;
@@ -398,10 +399,6 @@
 				}
 			}
 			else {
-				//FIXME Should we also eat the style here? viz:
-				//Layout layout;
-				//readStyle(lexrc, layout);
-				//as above...
 				lexrc.printError("No name given for style: `$$Token'.");
 				error = true;
 			}
@@ -524,7 +521,23 @@
 			break;
 
 		case TC_COUNTER:
-			readCounter(lexrc);
+			if (lexrc.next()) {
+				docstring const name = lexrc.getDocString();
+				if (name.empty()) {
+					string s = "Could not read name for counter: `$$Token' "
+							+ lexrc.getString() + " is probably not valid UTF-8!";
+					lexrc.printError(s.c_str());
+					Counter c;
+					// Since we couldn't read the name, we just scan the rest
+					// and discard it.
+					c.read(lexrc);
+				} else
+					error = !counters_.read(lexrc, name);
+			}
+			else {
+				lexrc.printError("No name given for style: `$$Token'.");
+				error = true;
+			}
 			break;
 
 		case TC_TITLELATEXTYPE:
@@ -542,7 +555,7 @@
 				floatlist_.erase(nofloat);
 			}
 			break;
-		}
+		} // end of switch
 
 		//Note that this is triggered the first time through the loop unless
 		//we hit a format tag.
@@ -829,79 +842,6 @@
 }
 
 
-void TextClass::readCounter(Lexer & lexrc)
-{
-	enum {
-		CT_NAME = 1,
-		CT_WITHIN,
-		CT_LABELSTRING,
-		CT_LABELSTRING_APPENDIX,
-		CT_END
-	};
-
-	LexerKeyword counterTags[] = {
-		{ "end", CT_END },
-		{ "labelstring", CT_LABELSTRING },
-		{ "labelstringappendix", CT_LABELSTRING_APPENDIX },
-		{ "name", CT_NAME },
-		{ "within", CT_WITHIN }
-	};
-
-	lexrc.pushTable(counterTags);
-
-	docstring name;
-	docstring within;
-	docstring labelstring;
-	docstring labelstring_appendix;
-
-	bool getout = false;
-	while (!getout && lexrc.isOK()) {
-		int le = lexrc.lex();
-		switch (le) {
-		case Lexer::LEX_UNDEF:
-			lexrc.printError("Unknown counter tag `$$Token'");
-			continue;
-		default: break;
-		}
-		switch (le) {
-		case CT_NAME:
-			lexrc.next();
-			name = lexrc.getDocString();
-			if (counters_.hasCounter(name))
-				LYXERR(Debug::TCLASS, "Reading existing counter " << to_utf8(name));
-			else
-				LYXERR(Debug::TCLASS, "Reading new counter " << to_utf8(name));
-			break;
-		case CT_WITHIN:
-			lexrc.next();
-			within = lexrc.getDocString();
-			if (within == "none")
-				within.erase();
-			break;
-		case CT_LABELSTRING:
-			lexrc.next();
-			labelstring = lexrc.getDocString();
-			labelstring_appendix = labelstring;
-			break;
-		case CT_LABELSTRING_APPENDIX:
-			lexrc.next();
-			labelstring_appendix = lexrc.getDocString();
-			break;
-		case CT_END:
-			getout = true;
-			break;
-		}
-	}
-
-	// Here if have a full counter if getout == true
-	if (getout)
-		counters_.newCounter(name, within, 
-				      labelstring, labelstring_appendix);
-
-	lexrc.popTable();
-}
-
-
 bool TextClass::hasLayout(docstring const & n) const
 {
 	docstring const name = n.empty() ? defaultLayoutName() : n;
Index: lib/scripts/layout2layout.py
===================================================================
--- lib/scripts/layout2layout.py	(revision 26762)
+++ lib/scripts/layout2layout.py	(working copy)
@@ -33,9 +33,12 @@
 # Incremented to format 9, 5 October 2008 by rgh
 # ForcePlain and CustomPars tags added to InsetLayout
 
-currentFormat = 9
+# Incremented to format 10, 6 October 2008 by rgh
+# Change format of counters
 
+currentFormat = 10
 
+
 def usage(prog_name):
     return ("Usage: %s inputfile outputfile\n" % prog_name +
             "or     %s <inputfile >outputfile" % prog_name)
@@ -87,6 +90,8 @@
 def convert(lines):
     " Convert to new format."
     re_Comment = re.compile(r'^(\s*)#')
+    re_Counter = re.compile(r'\s*Counter\s*')
+    re_Name = re.compile(r'\s*Name\s+(\S+)\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)
@@ -153,21 +158,21 @@
 
         # insert file format if not already there
         if (only_comment):
-                match = re_Format.match(lines[i])
-                if match:
-                        format = int(match.group(4))
-                        if format > 1 and format < currentFormat:
-                            lines[i] = "Format %d" % (format + 1)
-                            only_comment = 0
-                        elif format == currentFormat:
-                                # nothing to do
-                                return format
-                        else:
-                            error('Cannot convert file format %s' % format)
+            match = re_Format.match(lines[i])
+            if match:
+                format = int(match.group(4))
+                if format > 1 and format < currentFormat:
+                    lines[i] = "Format %d" % (format + 1)
+                    only_comment = 0
+                elif format == currentFormat:
+                    # nothing to do
+                    return format
                 else:
-                        lines.insert(i, "Format 2")
-                        only_comment = 0
-                        continue
+                    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]):
@@ -176,6 +181,27 @@
                 i += 1
             continue
 
+        if format == 9:
+            match = re_Counter.match(lines[i])
+            if match:
+                counterline = i
+                i += 1
+                while i < len(lines):
+                    namem = re_Name.match(lines[i])
+                    if namem:
+                        name = namem.group(1)
+                        lines.pop(i)
+                        lines[counterline] = "Counter %s" % name
+                        # we don't need to increment i
+                        continue
+                    endem = re_End.match(lines[i])
+                    if endem:
+                        i += 1
+                        break
+                    i += 1
+            i += 1
+            continue
+
         # These just involved new features, not any changes to old ones
         if format >= 5 and format <= 8:
           i += 1

Reply via email to