*
*/
+#include <assert.h>
#include <stdarg.h>
#include <string.h>
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 */
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;
/******************************************************************************
#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)
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
*/
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",
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)
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)
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;
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);