Commit 82258f4f authored by Nikolay Sivov's avatar Nikolay Sivov Committed by Alexandre Julliard

comctl32/tab: Use dpa to store item data.

parent 6867735e
...@@ -52,6 +52,7 @@ ...@@ -52,6 +52,7 @@
* *
*/ */
#include <assert.h>
#include <stdarg.h> #include <stdarg.h>
#include <string.h> #include <string.h>
...@@ -110,7 +111,6 @@ typedef struct ...@@ -110,7 +111,6 @@ typedef struct
INT iSelected; /* the currently selected item */ INT iSelected; /* the currently selected item */
INT iHotTracked; /* the highlighted item under the mouse */ INT iHotTracked; /* the highlighted item under the mouse */
INT uFocus; /* item which has the focus */ 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 DoRedraw; /* flag for redrawing when tab contents is changed*/
BOOL needsScrolling; /* TRUE if the size of the tabs is greater than BOOL needsScrolling; /* TRUE if the size of the tabs is greater than
* the size of the control */ * the size of the control */
...@@ -122,6 +122,8 @@ typedef struct ...@@ -122,6 +122,8 @@ typedef struct
DWORD exStyle; /* Extended style used, currently: DWORD exStyle; /* Extended style used, currently:
TCS_EX_FLATSEPARATORS, TCS_EX_REGISTERDROP */ TCS_EX_FLATSEPARATORS, TCS_EX_REGISTERDROP */
DWORD dwStyle; /* the cached window GWL_STYLE */ DWORD dwStyle; /* the cached window GWL_STYLE */
HDPA items; /* dynamic array of TAB_ITEM* pointers */
} TAB_INFO; } TAB_INFO;
/****************************************************************************** /******************************************************************************
...@@ -141,9 +143,6 @@ typedef struct ...@@ -141,9 +143,6 @@ typedef struct
#define EXTRA_ICON_PADDING 3 #define EXTRA_ICON_PADDING 3
#define TAB_GetInfoPtr(hwnd) ((TAB_INFO *)GetWindowLongPtrW(hwnd,0)) #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) #define GET_DEFAULT_MIN_TAB_WIDTH(infoPtr) (DEFAULT_MIN_TAB_WIDTH - (DEFAULT_PADDING_X - (infoPtr)->uHItemPadding) * 2)
...@@ -155,6 +154,12 @@ typedef struct ...@@ -155,6 +154,12 @@ typedef struct
static const WCHAR themeClass[] = { 'T','a','b',0 }; 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 * Prototypes
*/ */
...@@ -209,9 +214,8 @@ static void ...@@ -209,9 +214,8 @@ static void
TAB_DumpItemInternal(const TAB_INFO *infoPtr, UINT iItem) TAB_DumpItemInternal(const TAB_INFO *infoPtr, UINT iItem)
{ {
if (TRACE_ON(tab)) { 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", TRACE("tab %d, dwState=0x%08x, pszText=%s, iImage=%d\n",
iItem, ti->dwState, debugstr_w(ti->pszText), ti->iImage); iItem, ti->dwState, debugstr_w(ti->pszText), ti->iImage);
TRACE("tab %d, rect.left=%d, rect.top(row)=%d\n", TRACE("tab %d, rect.left=%d, rect.top(row)=%d\n",
...@@ -2640,42 +2644,21 @@ TAB_InsertItemT (TAB_INFO *infoPtr, INT iItem, const TCITEMW *pti, BOOL bUnicode ...@@ -2640,42 +2644,21 @@ TAB_InsertItemT (TAB_INFO *infoPtr, INT iItem, const TCITEMW *pti, BOOL bUnicode
TAB_DumpItemExternalT(pti, iItem, bUnicode); TAB_DumpItemExternalT(pti, iItem, bUnicode);
if (!(item = Alloc(sizeof(TAB_ITEM_SIZE(infoPtr))))) return FALSE;
if (infoPtr->uNumItem == 0) { if (DPA_InsertPtr(infoPtr->items, iItem, item) == -1)
infoPtr->items = Alloc (TAB_ITEM_SIZE(infoPtr)); {
infoPtr->uNumItem++; Free(item);
infoPtr->iSelected = 0; 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++; infoPtr->iSelected++;
Free (oldItems); infoPtr->uNumItem++;
}
item = TAB_GetItem(infoPtr, iItem);
item->pszText = NULL; item->pszText = NULL;
if (pti->mask & TCIF_TEXT) if (pti->mask & TCIF_TEXT)
{ {
if (bUnicode) if (bUnicode)
...@@ -2885,64 +2868,49 @@ TAB_GetItemT (TAB_INFO *infoPtr, INT iItem, LPTCITEMW tabItem, BOOL bUnicode) ...@@ -2885,64 +2868,49 @@ TAB_GetItemT (TAB_INFO *infoPtr, INT iItem, LPTCITEMW tabItem, BOOL bUnicode)
static LRESULT TAB_DeleteItem (TAB_INFO *infoPtr, INT iItem) static LRESULT TAB_DeleteItem (TAB_INFO *infoPtr, INT iItem)
{ {
BOOL bResult = FALSE; TAB_ITEM *item;
TRACE("(%p, %d)\n", infoPtr, iItem); TRACE("(%p, %d)\n", infoPtr, iItem);
if ((iItem >= 0) && (iItem < infoPtr->uNumItem)) if (iItem < 0 || iItem >= infoPtr->uNumItem) return FALSE;
{
TAB_ITEM *item = TAB_GetItem(infoPtr, iItem);
LPBYTE oldItems = (LPBYTE)infoPtr->items;
TAB_InvalidateTabArea(infoPtr); item = TAB_GetItem(infoPtr, iItem);
Free(item->pszText); Free(item->pszText);
Free(item);
infoPtr->uNumItem--; infoPtr->uNumItem--;
DPA_DeletePtr(infoPtr->items, iItem);
if (!infoPtr->uNumItem) TAB_InvalidateTabArea(infoPtr);
if (infoPtr->uNumItem == 0)
{ {
infoPtr->items = NULL;
if (infoPtr->iHotTracked >= 0) if (infoPtr->iHotTracked >= 0)
{ {
KillTimer(infoPtr->hwnd, TAB_HOTTRACK_TIMER); KillTimer(infoPtr->hwnd, TAB_HOTTRACK_TIMER);
infoPtr->iHotTracked = -1; infoPtr->iHotTracked = -1;
} }
infoPtr->iSelected = -1;
} }
else 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) if (iItem <= infoPtr->iHotTracked)
{ {
/* When tabs move left/up, the hot track item may change */ /* When tabs move left/up, the hot track item may change */
FIXME("Recalc hot track\n"); FIXME("Recalc hot track\n");
} }
} }
Free(oldItems);
/* Readjust the selected index */ /* adjust the selected index */
if (iItem == infoPtr->iSelected) if (iItem == infoPtr->iSelected)
infoPtr->iSelected = -1; infoPtr->iSelected = -1;
else if (iItem < infoPtr->iSelected) else if (iItem < infoPtr->iSelected)
infoPtr->iSelected--; infoPtr->iSelected--;
if (infoPtr->uNumItem == 0) /* reposition and repaint tabs */
infoPtr->iSelected = -1;
/* Reposition and repaint tabs */
TAB_SetItemBounds(infoPtr); TAB_SetItemBounds(infoPtr);
bResult = TRUE; return TRUE;
}
return bResult;
} }
static inline LRESULT TAB_DeleteAllItems (TAB_INFO *infoPtr) static inline LRESULT TAB_DeleteAllItems (TAB_INFO *infoPtr)
...@@ -3063,7 +3031,7 @@ static LRESULT TAB_Create (HWND hwnd, LPARAM lParam) ...@@ -3063,7 +3031,7 @@ static LRESULT TAB_Create (HWND hwnd, LPARAM lParam)
infoPtr->uHItemPadding_s = 6; infoPtr->uHItemPadding_s = 6;
infoPtr->uVItemPadding_s = 3; infoPtr->uVItemPadding_s = 3;
infoPtr->hFont = 0; infoPtr->hFont = 0;
infoPtr->items = 0; infoPtr->items = DPA_Create(8);
infoPtr->hcurArrow = LoadCursorW (0, (LPWSTR)IDC_ARROW); infoPtr->hcurArrow = LoadCursorW (0, (LPWSTR)IDC_ARROW);
infoPtr->iSelected = -1; infoPtr->iSelected = -1;
infoPtr->iHotTracked = -1; infoPtr->iHotTracked = -1;
...@@ -3147,16 +3115,22 @@ static LRESULT TAB_Create (HWND hwnd, LPARAM lParam) ...@@ -3147,16 +3115,22 @@ static LRESULT TAB_Create (HWND hwnd, LPARAM lParam)
static LRESULT static LRESULT
TAB_Destroy (TAB_INFO *infoPtr) TAB_Destroy (TAB_INFO *infoPtr)
{ {
UINT iItem; INT iItem;
SetWindowLongPtrW(infoPtr->hwnd, 0, 0); SetWindowLongPtrW(infoPtr->hwnd, 0, 0);
if (infoPtr->items) { for (iItem = infoPtr->uNumItem - 1; iItem >= 0; iItem--)
for (iItem = 0; iItem < infoPtr->uNumItem; iItem++) { {
Free (TAB_GetItem(infoPtr, iItem)->pszText); TAB_ITEM *tab = TAB_GetItem(infoPtr, iItem);
}
Free (infoPtr->items); DPA_DeletePtr(infoPtr->items, iItem);
infoPtr->uNumItem--;
Free(tab->pszText);
Free(tab);
} }
DPA_Destroy(infoPtr->items);
infoPtr->items = NULL;
if (infoPtr->hwndToolTip) if (infoPtr->hwndToolTip)
DestroyWindow (infoPtr->hwndToolTip); DestroyWindow (infoPtr->hwndToolTip);
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment