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