[PATCH 10/10] Store item data in DPA

Nikolay Sivov nsivov at codeweavers.com
Sun Sep 26 18:05:24 CDT 2010


---
 dlls/comctl32/tab.c |  166 ++++++++++++++++++++++----------------------------
 1 files changed, 73 insertions(+), 93 deletions(-)

diff --git a/dlls/comctl32/tab.c b/dlls/comctl32/tab.c
index 28c8bfd..7c8f782 100644
--- a/dlls/comctl32/tab.c
+++ b/dlls/comctl32/tab.c
@@ -52,6 +52,7 @@
  *
  */
 
+#include <assert.h>
 #include <stdarg.h>
 #include <string.h>
 
@@ -108,7 +109,6 @@ typedef struct
   INT        iSelected;       /* the currently selected item */
   INT        iHotTracked;     /* the highlighted item under the mouse */
   INT        uFocus;          /* item which has the focus */
-  TAB_ITEM*  items;           /* pointer to an array of TAB_ITEM's */
   BOOL       DoRedraw;        /* flag for redrawing when tab contents is changed*/
   BOOL       needsScrolling;  /* TRUE if the size of the tabs is greater than
                                * the size of the control */
@@ -120,6 +120,8 @@ typedef struct
   DWORD      exStyle;         /* Extended style used, currently:
                                  TCS_EX_FLATSEPARATORS, TCS_EX_REGISTERDROP */
   DWORD      dwStyle;         /* the cached window GWL_STYLE */
+
+  HDPA       items;           /* dynamic array of TAB_ITEM* pointers */
 } TAB_INFO;
 
 /******************************************************************************
@@ -139,9 +141,6 @@ typedef struct
 #define EXTRA_ICON_PADDING      3
 
 #define TAB_GetInfoPtr(hwnd) ((TAB_INFO *)GetWindowLongPtrW(hwnd,0))
-/* Since items are variable sized, cannot directly access them */
-#define TAB_GetItem(info,i) \
-  ((TAB_ITEM*)((LPBYTE)info->items + (i) * TAB_ITEM_SIZE(info)))
 
 #define GET_DEFAULT_MIN_TAB_WIDTH(infoPtr) (DEFAULT_MIN_TAB_WIDTH - (DEFAULT_PADDING_X - (infoPtr)->uHItemPadding) * 2)
 
@@ -153,6 +152,12 @@ typedef struct
 
 static const WCHAR themeClass[] = { 'T','a','b',0 };
 
+static inline TAB_ITEM* TAB_GetItem(const TAB_INFO *infoPtr, INT i)
+{
+    assert(i >= 0 && i < infoPtr->uNumItem);
+    return DPA_GetPtr(infoPtr->items, i);
+}
+
 /******************************************************************************
  * Prototypes
  */
@@ -207,9 +212,8 @@ static void
 TAB_DumpItemInternal(const TAB_INFO *infoPtr, UINT iItem)
 {
     if (TRACE_ON(tab)) {
-	TAB_ITEM *ti;
+	TAB_ITEM *ti = TAB_GetItem(infoPtr, iItem);
 
-	ti = TAB_GetItem(infoPtr, iItem);
 	TRACE("tab %d, dwState=0x%08x, pszText=%s, iImage=%d\n",
 	      iItem, ti->dwState, debugstr_w(ti->pszText), ti->iImage);
 	TRACE("tab %d, rect.left=%d, rect.top(row)=%d\n",
@@ -427,9 +431,15 @@ static BOOL TAB_InternalGetItemRect(
 
   } else
   {
-    OffsetRect(itemRect,
-	     -TAB_GetItem(infoPtr, infoPtr->leftmostVisible)->rect.left,
-	     0);
+    const TAB_ITEM *item;
+
+    /* FIXME: temporary fix for invalid index */
+    if (infoPtr->leftmostVisible < 0)
+        item = TAB_GetItem(infoPtr, 0);
+    else
+        item = TAB_GetItem(infoPtr, infoPtr->leftmostVisible);
+
+    OffsetRect(itemRect, -item->rect.left, 0);
 
     /*
      * Move the rectangle so the first item is slightly offset from
@@ -2634,42 +2644,21 @@ TAB_InsertItemT (TAB_INFO *infoPtr, INT iItem, const TCITEMW *pti, BOOL bUnicode
 
   TAB_DumpItemExternalT(pti, iItem, bUnicode);
 
-
-  if (infoPtr->uNumItem == 0) {
-    infoPtr->items = Alloc (TAB_ITEM_SIZE(infoPtr));
-    infoPtr->uNumItem++;
-    infoPtr->iSelected = 0;
+  if (!(item = Alloc(sizeof(TAB_ITEM_SIZE(infoPtr))))) return FALSE;
+  if (DPA_InsertPtr(infoPtr->items, iItem, item) == -1)
+  {
+      Free(item);
+      return FALSE;
   }
-  else {
-    LPBYTE oldItems = (LPBYTE)infoPtr->items;
 
-    infoPtr->uNumItem++;
-    infoPtr->items = Alloc (TAB_ITEM_SIZE(infoPtr) * infoPtr->uNumItem);
-
-    /* pre insert copy */
-    if (iItem > 0) {
-      memcpy (infoPtr->items, oldItems,
-              iItem * TAB_ITEM_SIZE(infoPtr));
-    }
-
-    /* post insert copy */
-    if (iItem < infoPtr->uNumItem - 1) {
-      memcpy (TAB_GetItem(infoPtr, iItem + 1),
-              oldItems + iItem * TAB_ITEM_SIZE(infoPtr),
-              (infoPtr->uNumItem - iItem - 1) * TAB_ITEM_SIZE(infoPtr));
-
-    }
-
-    if (iItem <= infoPtr->iSelected)
+  if (infoPtr->uNumItem == 0)
+      infoPtr->iSelected = 0;
+  else if (iItem <= infoPtr->iSelected)
       infoPtr->iSelected++;
 
-    Free (oldItems);
-  }
-
-  item = TAB_GetItem(infoPtr, iItem);
+  infoPtr->uNumItem++;
 
   item->pszText = NULL;
-
   if (pti->mask & TCIF_TEXT)
   {
     if (bUnicode)
@@ -2879,64 +2868,49 @@ TAB_GetItemT (TAB_INFO *infoPtr, INT iItem, LPTCITEMW tabItem, BOOL bUnicode)
 
 static LRESULT TAB_DeleteItem (TAB_INFO *infoPtr, INT iItem)
 {
-    BOOL bResult = FALSE;
+    TAB_ITEM *item;
 
     TRACE("(%p, %d)\n", infoPtr, iItem);
 
-    if ((iItem >= 0) && (iItem < infoPtr->uNumItem))
-    {
-        TAB_ITEM *item = TAB_GetItem(infoPtr, iItem);
-        LPBYTE oldItems = (LPBYTE)infoPtr->items;
+    if (iItem < 0 || iItem >= infoPtr->uNumItem) return FALSE;
+
+    item = TAB_GetItem(infoPtr, iItem);
+    Free(item->pszText);
+    Free(item);
+    infoPtr->uNumItem--;
+    DPA_DeletePtr(infoPtr->items, iItem);
 
-	TAB_InvalidateTabArea(infoPtr);
-        Free(item->pszText);
-	infoPtr->uNumItem--;
+    TAB_InvalidateTabArea(infoPtr);
 
-	if (!infoPtr->uNumItem)
+    if (infoPtr->uNumItem == 0)
+    {
+        if (infoPtr->iHotTracked >= 0)
         {
-            infoPtr->items = NULL;
-            if (infoPtr->iHotTracked >= 0)
-            {
-                KillTimer(infoPtr->hwnd, TAB_HOTTRACK_TIMER);
-                infoPtr->iHotTracked = -1;
-            }
+            KillTimer(infoPtr->hwnd, TAB_HOTTRACK_TIMER);
+            infoPtr->iHotTracked = -1;
         }
-        else
-	{
-	    infoPtr->items = Alloc(TAB_ITEM_SIZE(infoPtr) * infoPtr->uNumItem);
-
-	    if (iItem > 0)
-	        memcpy(infoPtr->items, oldItems, iItem * TAB_ITEM_SIZE(infoPtr));
-
-	    if (iItem < infoPtr->uNumItem)
-	        memcpy(TAB_GetItem(infoPtr, iItem),
-                       oldItems + (iItem + 1) * TAB_ITEM_SIZE(infoPtr),
-		       (infoPtr->uNumItem - iItem) * TAB_ITEM_SIZE(infoPtr));
-
-            if (iItem <= infoPtr->iHotTracked)
-            {
-                /* When tabs move left/up, the hot track item may change */
-                FIXME("Recalc hot track\n");
-            }
-	}
-	Free(oldItems);
-
-	/* Readjust the selected index */
-	if (iItem == infoPtr->iSelected)
-	    infoPtr->iSelected = -1;
-	else if (iItem < infoPtr->iSelected)
-	    infoPtr->iSelected--;
 
-	if (infoPtr->uNumItem == 0)
-	    infoPtr->iSelected = -1;
+        infoPtr->iSelected = -1;
+    }
+    else
+    {
+        if (iItem <= infoPtr->iHotTracked)
+        {
+            /* When tabs move left/up, the hot track item may change */
+            FIXME("Recalc hot track\n");
+        }
+    }
 
-	/* Reposition and repaint tabs */
-	TAB_SetItemBounds(infoPtr);
+    /* adjust the selected index */
+    if (iItem == infoPtr->iSelected)
+        infoPtr->iSelected = -1;
+    else if (iItem < infoPtr->iSelected)
+        infoPtr->iSelected--;
 
-	bResult = TRUE;
-    }
+    /* reposition and repaint tabs */
+    TAB_SetItemBounds(infoPtr);
 
-    return bResult;
+    return TRUE;
 }
 
 static inline LRESULT TAB_DeleteAllItems (TAB_INFO *infoPtr)
@@ -3057,7 +3031,7 @@ static LRESULT TAB_Create (HWND hwnd, LPARAM lParam)
   infoPtr->uHItemPadding_s = 6;
   infoPtr->uVItemPadding_s = 3;
   infoPtr->hFont           = 0;
-  infoPtr->items           = 0;
+  infoPtr->items           = DPA_Create(8);
   infoPtr->hcurArrow       = LoadCursorW (0, (LPWSTR)IDC_ARROW);
   infoPtr->iSelected       = -1;
   infoPtr->iHotTracked     = -1;
@@ -3141,16 +3115,22 @@ static LRESULT TAB_Create (HWND hwnd, LPARAM lParam)
 static LRESULT
 TAB_Destroy (TAB_INFO *infoPtr)
 {
-  UINT iItem;
+  INT iItem;
 
   SetWindowLongPtrW(infoPtr->hwnd, 0, 0);
 
-  if (infoPtr->items) {
-    for (iItem = 0; iItem < infoPtr->uNumItem; iItem++) {
-      Free (TAB_GetItem(infoPtr, iItem)->pszText);
-    }
-    Free (infoPtr->items);
+  for (iItem = infoPtr->uNumItem - 1; iItem >= 0; iItem--)
+  {
+      TAB_ITEM *tab = TAB_GetItem(infoPtr, iItem);
+
+      DPA_DeletePtr(infoPtr->items, iItem);
+      infoPtr->uNumItem--;
+
+      Free(tab->pszText);
+      Free(tab);
   }
+  DPA_Destroy(infoPtr->items);
+  infoPtr->items = NULL;
 
   if (infoPtr->hwndToolTip)
     DestroyWindow (infoPtr->hwndToolTip);
-- 
1.5.6.5



--------------010401050902080901070707--



More information about the wine-patches mailing list