Jean-Marc Lasgouttes a écrit :
"Abdelrazak" == Abdelrazak Younes <[EMAIL PROTECTED]> writes:

Abdelrazak> bool needEnumCounterReset(ParagraphList & pars, size_t const pos)
Abdelrazak> Maybe I am missing something but this is simpler. Please
Abdelrazak> correct me if I am wrong.

I agree that using dociterators all over makes a code a bit longer,
but a big advantage is that we pass just one object to the function
instead of a (ParagraphList,pos) [and of course your pos should be a
pit, so your are preparing us for more confusion]. We have fixed
*many* bugs in the core where people used a parlist index with the
wrong parlist.
IMHO, this is because the code is not object oriented. In this context docIterator is an advantage. When/if we move to a truly object oriented way of dealing with insets I believe that most of the its use will disappear. Beside updating _all_ the counters of the document (including inside insets!) because of one new paragraph seems wrong to me.

 I am not going to fight about keeping this function as
it is, I do not really care. What would be more useful though is to
see a profile so that we see what the problem actually is. Rewriting
everything just in case it helps will not give us the solution.

This is something I don't understand, sorry. IMHO, rewriting is a sane thing to do in any case if you want more people to understand the code. There are really too much code of that sort in lyx. Please find attached a patch that improve the situation dramatically. The LABEL_ENUMERATE case optimization is not yet enabled but is almost ready. Passing (Buffer const & buf) is not nice from an OO point of view but this can be solved later.

I hope I did not waste my time.

Abdel.

Index: buffer_funcs.C
===================================================================
--- buffer_funcs.C      (revision 13538)
+++ buffer_funcs.C      (working copy)
@@ -329,23 +329,119 @@
 }
 
 
-bool needEnumCounterReset(ParIterator const & it)
+bool needEnumCounterReset(size_t const pit, ParagraphList const & pars)
 {
-       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;
+       // Do we really want this. I would say this is OK to call this function 
with
+       // labeltype != LABEL_ENUMERATE
+       BOOST_ASSERT(pars[pit].layout()->labeltype == LABEL_ENUMERATE);
+
+    // start of nested inset: reset
+       if (pit == 0)
+           return true;
+
+       // previous par has a lower deph: reset
+       size_t i = pit - 1;
+       lyx::depth_type const current_depth = pars[pit].getDepth();
+       if (pars[i].getDepth() < current_depth)
+               return true;
+
+       // reset if one of previous pars with same depth is not a 
LABEL_ENUMERATE
+       // In principle the case (pars[i].getDepth() < pars[pit].getDepth())
+       // should not occur.
+    for (; i >= 0; --i) {
+               if (pars[i].getDepth() <= current_depth)
+                       return pars[i].layout()->labeltype != LABEL_ENUMERATE;
        }
-       // start of nested inset: reset
-       return true;
+
+       // In principle, this is dead code.
+       return false;
 }
 
+void setItemLabel(Paragraph & par)
+{
+       BOOST_ASSERT(par.layout()->labeltype == LABEL_ITEMIZE);
+       
+       // At some point of time we should do something more
+       // clever here, like:
+       //   par.params().labelString(
+       //    bufparams.user_defined_bullet(par.itemdepth).getText());
+       // for now, use a simple hardcoded label
+       string itemlabel;
+       switch (par.itemdepth) {
+       case 0:
+               itemlabel = "*";
+               break;
+       case 1:
+               itemlabel = "-";
+               break;
+       case 2:
+               itemlabel = "@";
+               break;
+       case 3:
+               itemlabel = "·";
+               break;
+       }
+       
+       par.params().labelString(itemlabel);
+}
 
+void setEnumLabel(size_t pit, ParagraphList & pars,
+                                 Buffer const & buf)
+{
+       Paragraph & par = pars[pit];
+       Counters & counters = buf.params().getLyXTextClass().counters();
+
+       // FIXME
+       // Yes I know this is a really, really! bad solution
+       // (Lgb)
+       string enumcounter = "enum";
+       
+       switch (par.itemdepth) {
+       case 2:
+               enumcounter += 'i';
+       case 1:
+               enumcounter += 'i';
+       case 0:
+               enumcounter += 'i';
+               break;
+       case 3:
+               enumcounter += "iv";
+               break;
+       default:
+               // not a valid enumdepth...
+               break;
+       }
+       
+       // Maybe we have to reset the enumeration counter.
+       if (needEnumCounterReset(pit, pars))
+               counters.reset(enumcounter);
+       
+       counters.step(enumcounter);
+       
+       string format;
+       
+       switch (par.itemdepth) {
+       case 0:
+               format = N_("\\arabic{enumi}.");
+               break;
+       case 1:
+               format = N_("(\\alph{enumii})");
+               break;
+       case 2:
+               format = N_("\\roman{enumiii}.");
+               break;
+       case 3:
+               format = N_("\\Alph{enumiv}.");
+               break;
+       default:
+               // not a valid enumdepth...
+               break;
+       }
+       
+       par.params().labelString(counters.counterLabel(buf.B_(format)));
+}
+
+
 // set the counter of a paragraph. This includes the labels
 void setCounter(Buffer const & buf, ParIterator & it)
 {
@@ -379,6 +475,10 @@
                par.setLabelWidthString(string());
        }
 
+       // is it a layout that has no label at all (ex: standard layout)?
+       if (layout->labeltype == LABEL_NO_LABEL)
+               return;
+
        // is it a layout that has an automatic label?
        if (layout->labeltype == LABEL_COUNTER) {
                if (layout->toclevel <= buf.params().secnumdepth
@@ -390,77 +490,13 @@
                        par.params().labelString(label);
                }
        } else if (layout->labeltype == LABEL_ITEMIZE) {
-               // At some point of time we should do something more
-               // clever here, like:
-               //   par.params().labelString(
-               //    bufparams.user_defined_bullet(par.itemdepth).getText());
-               // for now, use a simple hardcoded label
-               string itemlabel;
-               switch (par.itemdepth) {
-               case 0:
-                       itemlabel = "*";
-                       break;
-               case 1:
-                       itemlabel = "-";
-                       break;
-               case 2:
-                       itemlabel = "@";
-                       break;
-               case 3:
-                       itemlabel = "·";
-                       break;
-               }
 
-               par.params().labelString(itemlabel);
+               setItemLabel(par);
+
        } else if (layout->labeltype == LABEL_ENUMERATE) {
-               // FIXME
-               // Yes I know this is a really, really! bad solution
-               // (Lgb)
-               string enumcounter = "enum";
+               
+               setEnumLabel(it.pit(), it.plist(), buf);
 
-               switch (par.itemdepth) {
-               case 2:
-                       enumcounter += 'i';
-               case 1:
-                       enumcounter += 'i';
-               case 0:
-                       enumcounter += 'i';
-                       break;
-               case 3:
-                       enumcounter += "iv";
-                       break;
-               default:
-                       // not a valid enumdepth...
-                       break;
-               }
-
-               // Maybe we have to reset the enumeration counter.
-               if (needEnumCounterReset(it))
-                       counters.reset(enumcounter);
-
-               counters.step(enumcounter);
-
-               string format;
-
-               switch (par.itemdepth) {
-               case 0:
-                       format = N_("\\arabic{enumi}.");
-                       break;
-               case 1:
-                       format = N_("(\\alph{enumii})");
-                       break;
-               case 2:
-                       format = N_("\\roman{enumiii}.");
-                       break;
-               case 3:
-                       format = N_("\\Alph{enumiv}.");
-                       break;
-               default:
-                       // not a valid enumdepth...
-                       break;
-               }
-
-               par.params().labelString(counters.counterLabel(buf.B_(format)));
        } else if (layout->labeltype == LABEL_BIBLIO) {// ale970302
                counters.step("bibitem");
                int number = counters.value("bibitem");
@@ -508,7 +544,9 @@
        // start over
        buf.params().getLyXTextClass().counters().reset();
 
-       for (ParIterator it = par_iterator_begin(buf.inset()); it; ++it) {
+       ParIterator end = par_iterator_end(buf.inset());
+
+       for (ParIterator it = par_iterator_begin(buf.inset()); it != end; ++it) 
{
                // reduce depth if necessary
                if (it.pit()) {
                        Paragraph const & prevpar = it.plist()[it.pit() - 1];
@@ -522,7 +560,28 @@
        }
 }
 
+bool needUpdateCounters(size_t const pit, ParagraphList & pars,
+                                               Buffer const & buf)
+{
+       Paragraph & current_par = pars[pit];
 
+       switch (current_par.layout()->labeltype) {
+       case LABEL_NO_LABEL:
+               return false;
+
+       case LABEL_ITEMIZE:
+               setItemLabel(current_par);
+               return false;
+
+//     case LABEL_ENUMERATE:
+//             setEnumLabel(pit, pars, buf);
+//             return false;
+       
+       default:
+               return true;
+       }
+}
+
 string expandLabel(Buffer const & buf,
        LyXLayout_ptr const & layout, bool appendix)
 {
Index: buffer_funcs.h
===================================================================
--- buffer_funcs.h      (revision 13538)
+++ buffer_funcs.h      (working copy)
@@ -13,6 +13,7 @@
 #define BUFFER_FUNCS_H
 
 #include "lyxlayout_ptr_fwd.h"
+#include "ParagraphList_fwd.h"
 
 #include <string>
 
@@ -48,6 +49,14 @@
 std::string expandLabel(Buffer const & buf, LyXLayout_ptr const & layout,
                        bool appendix);
 
+/// updates current counter and/or label if possible.
+/**
+\retval true if a full updateCounters is required.
+\retval false if a full updateCounters is required.
+*/
+bool needUpdateCounters(size_t const pit, ParagraphList & pars,
+                                               Buffer const & buf);
+
 /// updates all counters
 void updateCounters(Buffer const &);
 
Index: text.C
===================================================================
--- text.C      (revision 13538)
+++ text.C      (working copy)
@@ -1087,7 +1087,8 @@
        while (!pars_[next_par].empty() && pars_[next_par].isNewline(0))
                pars_[next_par].erase(0);
 
-       updateCounters(cur.buffer());
+       if (needUpdateCounters(next_par, pars_, cur.buffer()))
+               updateCounters(cur.buffer());
 
        // Mark "carriage return" as inserted if change tracking:
        if (cur.buffer().params().tracking_changes) {

Reply via email to