[prev in list] [next in list] [prev in thread] [next in thread] 

List:       kde-commits
Subject:    branches/KDE/3.5/kdelibs/khtml
From:       Maks Orlovich <maksim () kde ! org>
Date:       2006-01-19 17:42:41
Message-ID: 1137692561.154230.29067.nullmailer () svn ! kde ! org
[Download RAW message or body]

SVN commit 500223 by orlovich:

Optimize appends and clears to/of selects via explicit APIs. 
BUG:62785


 M  +1 -1      ecma/kjs_html.cpp  
 M  +42 -13    html/html_formimpl.cpp  
 M  +3 -2      html/html_formimpl.h  


--- branches/KDE/3.5/kdelibs/khtml/ecma/kjs_html.cpp #500222:500223
@@ -3336,7 +3336,7 @@
     }
     else // remove elements
       while (diff-- > 0)
-        element.remove(newLen);
+        element.remove(newLen + diff);
 
     return;
   }
--- branches/KDE/3.5/kdelibs/khtml/html/html_formimpl.cpp #500222:500223
@@ -1893,6 +1893,7 @@
     // 0 means invalid (i.e. not set)
     m_size = 0;
     m_minwidth = 0;
+    m_length   = 0;
 }
 
 HTMLSelectElementImpl::~HTMLSelectElementImpl()
@@ -1946,15 +1947,9 @@
 
 long HTMLSelectElementImpl::length() const
 {
-    int len = 0;
-    uint i;
-    QMemArray<HTMLGenericFormElementImpl*> items = listItems();
-    const uint itemsSize = items.size();
-    for (i = 0; i < itemsSize; ++i) {
-        if (items[i]->id() == ID_OPTION)
-            ++len;
-    }
-    return len;
+    if (m_recalcListItems)
+        recalcListItems();
+    return m_length;
 }
 
 void HTMLSelectElementImpl::add( const HTMLElement &element, const HTMLElement \
&before, int& exceptioncode ) @@ -1962,8 +1957,21 @@
     if(element.isNull() || element.handle()->id() != ID_OPTION)
         return;
 
-    insertBefore(element.handle(), before.handle(), exceptioncode );
-    if (!exceptioncode)
+    HTMLOptionElementImpl* option = \
static_cast<HTMLOptionElementImpl*>(element.handle());; +    //Fast path for \
appending an item. Can't be done if it is selected and  +    //we're single-select, \
since we may need to drop an implicitly-selected item +    bool fastAppendLast = \
false; +    if (before.handle() == 0 && (m_multiple || !option->selected()) && \
!m_recalcListItems) +        fastAppendLast = true;
+
+    insertBefore(option, before.handle(), exceptioncode );
+
+    if (fastAppendLast) {
+        m_listItems.resize(m_listItems.size() + 1);
+        m_listItems[m_listItems.size() - 1] = option;
+        ++m_length;
+        m_recalcListItems = false;
+    } else if (!exceptioncode)
         setRecalcListItems();
 }
 
@@ -1976,8 +1984,22 @@
     if(listIndex < 0 || index >= int(items.size()))
         return; // ### what should we do ? remove the last item?
 
+    //Fast path for last element, for e.g. clearing the box
+    //Note that if this is a single-select, we may have to recompute
+    //anyway if the item was selected, since we may want to set 
+    //a different one
+    bool fastRemoveLast = false;
+    if ((listIndex == items.size() - 1) && !m_recalcListItems && 
+        (m_multiple || \
!static_cast<HTMLOptionElementImpl*>(items[listIndex])->selected())) +            \
fastRemoveLast = true; +
     removeChild(items[listIndex], exceptioncode);
-    if( !exceptioncode )
+
+    if (fastRemoveLast) {
+        m_listItems.resize(m_listItems.size() - 1);
+        --m_length;
+        m_recalcListItems = false;
+    } else if( !exceptioncode)
         setRecalcListItems();
 }
 
@@ -2220,6 +2242,11 @@
     if (optionIndex < 0 || optionIndex >= itemsSize)
         return -1;
 
+    //See if we're asked for the very last item, and check whether it's an <option>
+    //to fastpath clear
+    if (optionIndex == (m_length - 1) && items[itemsSize - 1]->id() == ID_OPTION)
+        return itemsSize - 1;
+
     int listIndex = 0;
     int optionIndex2 = 0;
     for (;
@@ -2247,11 +2274,12 @@
     return optionIndex;
 }
 
-void HTMLSelectElementImpl::recalcListItems()
+void HTMLSelectElementImpl::recalcListItems() const
 {
     NodeImpl* current = firstChild();
     m_listItems.resize(0);
     HTMLOptionElementImpl* foundSelected = 0;
+    m_length = 0;
     while(current) {
         if (current->id() == ID_OPTGROUP && current->firstChild()) {
             // ### what if optgroup contains just comments? don't want one of no \
options in it... @@ -2260,6 +2288,7 @@
             current = current->firstChild();
         }
         if (current->id() == ID_OPTION) {
+            ++m_length;
             m_listItems.resize(m_listItems.size()+1);
             m_listItems[m_listItems.size()-1] = \
static_cast<HTMLGenericFormElementImpl*>(current);  if (!foundSelected && !m_multiple \
                && m_size <= 1) {
--- branches/KDE/3.5/kdelibs/khtml/html/html_formimpl.h #500222:500223
@@ -431,14 +431,15 @@
     void notifyOptionSelected(HTMLOptionElementImpl *selectedOption, bool selected);
 
 private:
-    void recalcListItems();
+    void recalcListItems() const;
 
 protected:
     mutable QMemArray<HTMLGenericFormElementImpl*> m_listItems;
     short m_minwidth;
     signed short m_size : 15;
     bool m_multiple : 1;
-    bool m_recalcListItems;
+    mutable bool m_recalcListItems :1;
+    mutable unsigned int   m_length:31;
 };
 
 // -------------------------------------------------------------------------


[prev in list] [next in list] [prev in thread] [next in thread] 

Configure | About | News | Add a list | Sponsored by KoreLogic