From d841355b7e95ae6971edee7dca18f6ab05f20938 Mon Sep 17 00:00:00 2001 From: Richard Heck Date: Mon, 6 Oct 2008 14:37:28 +0000 Subject: [PATCH] Fix bug 5316 properly. The fix is to make the routine that reads a counter update an existing counter rather than overwrite it. This turns out to be more complicated than it might seem. There are two large parts to the patch. One moves the counter read routine out of TextClass and into the Counter and Counters classes. The other changes the syntax of counters from: Counter Name whatever .... to: Counter whatever .... This allows us to get the name of the counter right away, so we can decide whether it is an old one or a new one. So the layout format had to be changed (again), with corresponding layout2layout code. git-svn-id: svn://svn.lyx.org/lyx/lyx-devel/trunk@26779 a592a061-630c-0410-9148-cb99ea01b6c8 --- lib/scripts/layout2layout.py | 28 ++++++++++- src/Counters.cpp | 76 +++++++++++++++++++++++++++++ src/Counters.h | 9 +++- src/TextClass.cpp | 93 +++++++----------------------------- src/TextClass.h | 2 - 5 files changed, 128 insertions(+), 80 deletions(-) diff --git a/lib/scripts/layout2layout.py b/lib/scripts/layout2layout.py index 3d27398ecc..f42a508a6c 100644 --- a/lib/scripts/layout2layout.py +++ b/lib/scripts/layout2layout.py @@ -33,7 +33,10 @@ import os, re, string, sys # 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): @@ -87,6 +90,8 @@ def concatenate_label(old, new): 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) @@ -175,6 +180,27 @@ def convert(lines): 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 diff --git a/src/Counters.cpp b/src/Counters.cpp index 1cc78431c7..cf4bfeed43 100644 --- a/src/Counters.cpp +++ b/src/Counters.cpp @@ -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 @@ Counter::Counter(docstring const & mc, docstring const & ls, } +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::hasCounter(docstring const & c) const } +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); diff --git a/src/Counters.h b/src/Counters.h index 721e4e307d..538dcd4792 100644 --- a/src/Counters.h +++ b/src/Counters.h @@ -23,6 +23,8 @@ namespace lyx { +class Lexer; + /// This represents a single counter. class Counter { public: @@ -31,6 +33,8 @@ public: /// Counter(docstring const & mc, docstring const & ls, docstring const & lsa); + /// \return true on success + bool read(Lexer & lex); /// void set(int v); /// @@ -75,8 +79,6 @@ class Counters { public: /// Counters() : appendix_(false), subfloat_(false) {} - /// Add a new counter to array. - void newCounter(docstring const & newc); /// Add new counter newc having masterc as its master, /// ls as its label, and lsa as its appendix label. void newCounter(docstring const & newc, @@ -85,6 +87,9 @@ public: 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); /// diff --git a/src/TextClass.cpp b/src/TextClass.cpp index acf41f5054..63719188f2 100644 --- a/src/TextClass.cpp +++ b/src/TextClass.cpp @@ -61,7 +61,7 @@ private: }; -int const FORMAT = 9; +int const FORMAT = 10; bool layout2layout(FileName const & filename, FileName const & tempfile) @@ -520,7 +520,23 @@ TextClass::ReturnValues TextClass::read(Lexer & lexrc, ReadType rt) 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: @@ -825,79 +841,6 @@ void TextClass::readFloat(Lexer & lexrc) } -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; diff --git a/src/TextClass.h b/src/TextClass.h index 36630238ae..fd2b50bb9f 100644 --- a/src/TextClass.h +++ b/src/TextClass.h @@ -305,8 +305,6 @@ private: void readCharStyle(Lexer &, std::string const &); /// void readFloat(Lexer &); - /// - void readCounter(Lexer &); }; -- 2.39.5