This is a fix for
http://bugzilla.lyx.org/show_bug.cgi?id=465

What this does is to basically rewrite the setCounter code to use
proper ParIterator and fix nesting of enumerate and itemize when they
are in nested insets. This is demonstrated by file bug465.lyx.

It also fixes a nesting bug that was already present in 1.3.x (without
any insets), as demonstrated by bug465.lyx.

While I am rather confident that the code works better than what we
have (at least now I understand it :), I'd appreciate testing.

Of course I plan to remove the debug output once I am ready to commit.

Lars, can I commit it? I do not have new ideas about things to test,
so I guess real world testing is the best :)

JMarc

Index: src/ChangeLog
===================================================================
RCS file: /usr/local/lyx/cvsroot/lyx-devel/src/ChangeLog,v
retrieving revision 1.2259
diff -u -p -r1.2259 ChangeLog
--- src/ChangeLog	30 Jul 2005 07:55:37 -0000	1.2259
+++ src/ChangeLog	31 Jul 2005 15:57:25 -0000
@@ -1,3 +1,23 @@
+2005-07-31  Jean-Marc Lasgouttes  <[EMAIL PROTECTED]>
+
+	bug 465.
+
+	* dociterator.h (clear, push_back, pop_back): change from
+	protected to public.
+
+	* buffer_funcs.C (getItemDepth): renamed from incrementItemDepth
+	and changed to just return the value of the item depth; take a
+	ParIterator as argument; take the itemdepth at outer nesting level
+	in account if necessary; cleanup and comment the code.
+	(resetEnumCounterNeeded): renamed from resetEnumCounterIfNeeded
+	and changed to just return true if reset is needed; take a
+	ParIterator as argument; cleanup and comment the code.
+	(setCounter): adapt to above changes.
+
+2005-07-30  Jean-Marc Lasgouttes  <[EMAIL PROTECTED]>
+
+	* text3.C (dispatch): make debug message optional
+
 2005-07-20  John Levon  <[EMAIL PROTECTED]>
 
 	* text2.C (insertStringAsLines): remove old dubious code,
Index: src/buffer_funcs.C
===================================================================
RCS file: /usr/local/lyx/cvsroot/lyx-devel/src/buffer_funcs.C,v
retrieving revision 1.31
diff -u -p -r1.31 buffer_funcs.C
--- src/buffer_funcs.C	9 Jun 2005 09:58:05 -0000	1.31
+++ src/buffer_funcs.C	31 Jul 2005 15:57:25 -0000
@@ -12,8 +12,9 @@
 
 #include <config.h>
 
-#include "buffer_funcs.h"
+#include "debug.h"
 
+#include "buffer_funcs.h"
 #include "buffer.h"
 #include "bufferlist.h"
 #include "bufferparams.h"
@@ -272,75 +273,77 @@ int countWords(DocIterator const & from,
 
 namespace {
 
-void incrementItemDepth(ParagraphList & pars, pit_type pit, pit_type first_pit)
+lyx::depth_type getDepth(DocIterator const & it)
 {
-	int const cur_labeltype = pars[pit].layout()->labeltype;
-
-	if (cur_labeltype != LABEL_ENUMERATE && cur_labeltype != LABEL_ITEMIZE)
-		return;
-
-	int const cur_depth = pars[pit].getDepth();
+	lyx::depth_type depth = 0;
+	for (size_t i = 0 ; i < it.depth() ; ++i) 
+		if (!it[i].inset().inMathed())
+			depth += it[i].paragraph().getDepth() + 1;
+	// remove 1 since the outer inset does not count
+	return depth - 1;
+}
 
-	pit_type prev_pit = pit - 1;
+lyx::depth_type getItemDepth(ParIterator const & it)
+{	
+	Paragraph const & par = *it;
+	LYX_LABEL_TYPES const labeltype = par.layout()->labeltype;
+
+	if (labeltype != LABEL_ENUMERATE && labeltype != LABEL_ITEMIZE)
+ 		return 0;
+
+	// this will hold the lowest depth that has been ecountered up to now. 
+	lyx::depth_type min_depth = getDepth(it);
+	ParIterator prev_it = it;
 	while (true) {
-		int const prev_depth = pars[prev_pit].getDepth();
-		int const prev_labeltype = pars[prev_pit].layout()->labeltype;
-		if (prev_depth == 0 && cur_depth > 0) {
-			if (prev_labeltype == cur_labeltype) {
-				pars[pit].itemdepth = pars[prev_pit].itemdepth + 1;
+		if (prev_it.pit())
+			--prev_it.top().pit();
+		else {
+			// start of nested inset: go to outer par
+			prev_it.pop_back();
+			if (prev_it.empty()) {
+				// start of document: nothing to do
+				return 0;
 			}
-			break;
-		} else if (prev_depth < cur_depth) {
-			if (prev_labeltype == cur_labeltype) {
-				pars[pit].itemdepth = pars[prev_pit].itemdepth + 1;
-				break;
+		}
+		
+		// We search for the first paragraph with same label
+		// that is not more deeply nested.
+		Paragraph & prev_par = *prev_it;
+		lyx::depth_type const prev_depth = getDepth(prev_it);
+		lyxerr << "par(id=" << par.id() << ",depth=" << min_depth << ",label-type=" << labeltype
+		       << ") prev_par(id=" << prev_par.id() << ",depth=" << prev_depth << ",label-type=" << prev_par.layout()->labeltype << ")" << std::endl;
+	 	if (labeltype == prev_par.layout()->labeltype) {
+			if (prev_depth < min_depth) {
+				return prev_par.itemdepth + 1;
 			}
-		} else if (prev_depth == cur_depth) {
-			if (prev_labeltype == cur_labeltype) {
-				pars[pit].itemdepth = pars[prev_pit].itemdepth;
-				break;
+			else if (prev_depth == min_depth) {
+				return prev_par.itemdepth;
 			}
 		}
-		if (prev_pit == first_pit)
-			break;
-
-		--prev_pit;
+		min_depth = std::min(min_depth, prev_depth);
+		// small optimization: if we are at depth 0, we won't
+		// find anything else
+		if (prev_depth == 0) {
+			return 0;
+		}
 	}
 }
 
 
-void resetEnumCounterIfNeeded(ParagraphList & pars, pit_type pit,
-	pit_type firstpit, Counters & counters)
+bool needEnumCounterReset(ParIterator const & it)
 {
-	if (pit == firstpit)
-		return;
-
-	int const cur_depth = pars[pit].getDepth();
-	pit_type prev_pit = pit - 1;
-	while (true) {
-		int const prev_depth = pars[prev_pit].getDepth();
-		int const prev_labeltype = pars[prev_pit].layout()->labeltype;
-		if (prev_depth <= cur_depth) {
-			if (prev_labeltype != LABEL_ENUMERATE) {
-				switch (pars[pit].itemdepth) {
-				case 0:
-					counters.reset("enumi");
-				case 1:
-					counters.reset("enumii");
-				case 2:
-					counters.reset("enumiii");
-				case 3:
-					counters.reset("enumiv");
-				}
-			}
-			break;
-		}
-
-		if (prev_pit == firstpit)
-			break;
-
-		--prev_pit;
+	Paragraph const & par = *it;
+	BOOST_ASSERT(par.layout()->labeltype == LABEL_ENUMERATE);
+	lyx::depth_type const cur_depth = par.getDepth();
+	ParIterator prev_it = it;
+	while (prev_it.pit()) {
+		--prev_it.top().pit();
+		Paragraph const & prev_par = *prev_it;
+		if (prev_par.getDepth() <= cur_depth)
+			return  prev_par.layout()->labeltype != LABEL_ENUMERATE;
 	}
+	// start of nested inset: reset
+	return true;
 }
 
 
@@ -353,9 +356,6 @@ void setCounter(Buffer const & buf, ParI
 	LyXLayout_ptr const & layout = par.layout();
 	Counters & counters = textclass.counters();
 
-	// Always reset
-	par.itemdepth = 0;
-
 	if (it.pit() == 0) {
 		par.params().appendix(par.params().startOfAppendix());
 	} else {
@@ -365,11 +365,11 @@ void setCounter(Buffer const & buf, ParI
 			par.params().appendix(true);
 			textclass.counters().reset();
 		}
-
-		// Maybe we have to increment the item depth.
-		incrementItemDepth(it.plist(), it.pit(), 0);
 	}
 
+	// Compute the item depth of the paragraph
+	par.itemdepth = getItemDepth(it);
+
 	// erase what was there before
 	par.params().labelString(string());
 
@@ -414,9 +414,6 @@ void setCounter(Buffer const & buf, ParI
 
 		par.params().labelString(itemlabel);
 	} else if (layout->labeltype == LABEL_ENUMERATE) {
-		// Maybe we have to reset the enumeration counter.
-		resetEnumCounterIfNeeded(it.plist(), it.pit(), 0, counters);
-
 		// FIXME
 		// Yes I know this is a really, really! bad solution
 		// (Lgb)
@@ -437,6 +434,10 @@ void setCounter(Buffer const & buf, ParI
 			// not a valid enumdepth...
 			break;
 		}
+
+		// Maybe we have to reset the enumeration counter.
+		if (needEnumCounterReset(it))
+			counters.reset(enumcounter);
 
 		counters.step(enumcounter);
 
Index: src/dociterator.h
===================================================================
RCS file: /usr/local/lyx/cvsroot/lyx-devel/src/dociterator.h,v
retrieving revision 1.21
diff -u -p -r1.21 dociterator.h
--- src/dociterator.h	15 Jul 2005 15:49:31 -0000	1.21
+++ src/dociterator.h	31 Jul 2005 15:57:25 -0000
@@ -207,7 +207,7 @@ public:
 	friend bool operator==(DocIterator const &, DocIterator const &);
 	///
 	friend class StableDocIterator;
-protected:
+//protected:
 	///
 	void clear() { slices_.clear(); }
 	///
Index: src/text3.C
===================================================================
RCS file: /usr/local/lyx/cvsroot/lyx-devel/src/text3.C,v
retrieving revision 1.305
diff -u -p -r1.305 text3.C
--- src/text3.C	18 Jul 2005 12:13:32 -0000	1.305
+++ src/text3.C	31 Jul 2005 15:57:25 -0000
@@ -1519,8 +1519,10 @@ void LyXText::dispatch(LCursor & cur, Fu
 		break;
 
 	default:
-		lyxerr << BOOST_CURRENT_FUNCTION
-					 << ": Command " << cmd << " not DISPATCHED by LyXText" << endl;
+		lyxerr[Debug::ACTION] 
+			<< BOOST_CURRENT_FUNCTION
+			<< ": Command " << cmd 
+			<< " not DISPATCHED by LyXText" << endl;
 		cur.undispatched();
 		break;
 	}
#LyX 1.4.0cvs created this file. For more info see http://www.lyx.org/
\lyxformat 221
\textclass article
\language english
\inputencoding auto
\fontscheme default
\graphics default
\paperfontsize default
\papersize default
\use_geometry 0
\use_amsmath 1
\use_natbib 0
\use_numerical_citations 0
\paperorientation portrait
\secnumdepth 3
\tocdepth 3
\paragraph_separation indent
\defskip medskip
\quotes_language english
\quotes_times 2
\papercolumns 1
\papersides 1
\paperpagestyle default

\layout Itemize
item

\layout Enumerate
enum

\layout Enumerate
enum

\layout Standard
standard

\layout Enumerate
enum 

\begin_deeper
\layout Enumerate
enum

\layout Itemize
item

\begin_deeper
\layout Standard
standard

\layout Itemize
item

\layout Enumerate
enum

\end_deeper
\end_deeper
\layout Enumerate
enum

\begin_deeper
\layout Standard
\begin_inset Tabular
<lyxtabular version="3" rows="1" columns="3">
<features>
<column alignment="block" valignment="top" leftline="true" width="3cm">
<column alignment="block" valignment="top" leftline="true" width="3cm">
<column alignment="block" valignment="top" leftline="true" rightline="true" 
width="3cm">
<row topline="true" bottomline="true">
<cell alignment="center" valignment="top" topline="true" leftline="true" 
usebox="none">
\begin_inset Text

\layout Enumerate
enum

\layout Enumerate
enum

\end_inset
</cell>
<cell alignment="center" valignment="top" topline="true" leftline="true" 
usebox="none">
\begin_inset Text

\layout Enumerate
enum

\layout Itemize
item

\end_inset
</cell>
<cell alignment="center" valignment="top" topline="true" leftline="true" 
rightline="true" usebox="none">
\begin_inset Text

\layout Enumerate
enum

\begin_deeper
\layout Enumerate
enum

\end_inset
</cell>
</row>
</lyxtabular>

\end_inset



\layout Enumerate
enum 
\begin_inset Tabular
<lyxtabular version="3" rows="1" columns="3">
<features>
<column alignment="block" valignment="top" leftline="true" width="3cm">
<column alignment="block" valignment="top" leftline="true" width="3cm">
<column alignment="block" valignment="top" leftline="true" rightline="true" 
width="3cm">
<row topline="true" bottomline="true">
<cell alignment="center" valignment="top" topline="true" leftline="true" 
usebox="none">
\begin_inset Text

\layout Enumerate
enum

\end_inset
</cell>
<cell alignment="center" valignment="top" topline="true" leftline="true" 
usebox="none">
\begin_inset Text

\layout Enumerate
enum

\end_inset
</cell>
<cell alignment="center" valignment="top" topline="true" leftline="true" 
rightline="true" usebox="none">
\begin_inset Text

\layout Enumerate
enum

\end_inset
</cell>
</row>
</lyxtabular>

\end_inset



\end_deeper
\layout Enumerate
enum
\begin_inset Foot
collapsed false

\layout Enumerate
enum

\layout Itemize
item

\begin_deeper
\layout Standard
standard

\layout Itemize
item

\layout Enumerate
enum

\end_inset



\the_end

Reply via email to