comctl32/listview: Implement LVM_MAPIDTOINDEX/LVM_MAPINDEXTOID.

This commit is contained in:
Nikolay Sivov 2009-06-21 00:48:07 +04:00 committed by Alexandre Julliard
parent 2286a321c2
commit 85224d7f17
2 changed files with 147 additions and 6 deletions

View File

@ -124,7 +124,6 @@
* -- LVM_INSERTGROUPSORTED
* -- LVM_INSERTMARKHITTEST
* -- LVM_ISGROUPVIEWENABLED
* -- LVM_MAPIDTOINDEX, LVM_MAPINDEXTOID
* -- LVM_MOVEGROUP
* -- LVM_MOVEITEMTOGROUP
* -- LVM_SETINFOTIP
@ -194,14 +193,23 @@ typedef struct tagSUBITEM_INFO
INT iSubItem;
} SUBITEM_INFO;
typedef struct tagITEM_ID ITEM_ID;
typedef struct tagITEM_INFO
{
ITEMHDR hdr;
UINT state;
LPARAM lParam;
INT iIndent;
ITEM_ID *id;
} ITEM_INFO;
struct tagITEM_ID
{
UINT id; /* item id */
HDPA item; /* link to item data */
};
typedef struct tagRANGE
{
INT lower;
@ -278,6 +286,7 @@ typedef struct tagLISTVIEW_INFO
DWORD uView; /* current view available through LVM_[G,S]ETVIEW */
INT nItemCount; /* the number of items in the list */
HDPA hdpaItems; /* array ITEM_INFO pointers */
HDPA hdpaItemIds; /* array of ITEM_ID pointers */
HDPA hdpaPosX; /* maintains the (X, Y) coordinates of the */
HDPA hdpaPosY; /* items in LVS_ICON, and LVS_SMALLICON modes */
HDPA hdpaColumns; /* array of COLUMN_INFO pointers */
@ -1430,6 +1439,19 @@ static inline void map_style_view(LISTVIEW_INFO *infoPtr)
}
}
/* computes next item id value */
static DWORD get_next_itemid(const LISTVIEW_INFO *infoPtr)
{
INT count = DPA_GetPtrCount(infoPtr->hdpaItemIds);
if (count > 0)
{
ITEM_ID *lpID = DPA_GetPtr(infoPtr->hdpaItemIds, count - 1);
return lpID->id + 1;
}
return 0;
}
/******** Internal API functions ************************************/
static inline COLUMN_INFO * LISTVIEW_GetColumnInfo(const LISTVIEW_INFO *infoPtr, INT nSubItem)
@ -2310,6 +2332,76 @@ static void LISTVIEW_GetItemBox(const LISTVIEW_INFO *infoPtr, INT nItem, LPRECT
OffsetRect(lprcBox, Position.x + Origin.x, Position.y + Origin.y);
}
/* LISTVIEW_MapIdToIndex helper */
INT CALLBACK MapIdSearchCompare(LPVOID p1, LPVOID p2, LPARAM lParam)
{
ITEM_ID *id1 = (ITEM_ID*)p1;
ITEM_ID *id2 = (ITEM_ID*)p2;
if (id1->id == id2->id) return 0;
return (id1->id < id2->id) ? -1 : 1;
}
/***
* DESCRIPTION:
* Returns the item index for id specified.
*
* PARAMETER(S):
* [I] infoPtr : valid pointer to the listview structure
* [I] iID : item id to get index for
*
* RETURN:
* Item index, or -1 on failure.
*/
static INT LISTVIEW_MapIdToIndex(const LISTVIEW_INFO *infoPtr, UINT iID)
{
ITEM_ID ID;
INT index;
TRACE("iID=%d\n", iID);
if (infoPtr->dwStyle & LVS_OWNERDATA) return -1;
if (infoPtr->nItemCount == 0) return -1;
ID.id = iID;
index = DPA_Search(infoPtr->hdpaItemIds, &ID, -1, &MapIdSearchCompare, 0, DPAS_SORTED);
if (index != -1)
{
ITEM_ID *lpID = DPA_GetPtr(infoPtr->hdpaItemIds, index);
return DPA_GetPtrIndex(infoPtr->hdpaItems, lpID->item);
}
return -1;
}
/***
* DESCRIPTION:
* Returns the item id for index given.
*
* PARAMETER(S):
* [I] infoPtr : valid pointer to the listview structure
* [I] iItem : item index to get id for
*
* RETURN:
* Item id.
*/
static DWORD LISTVIEW_MapIndexToId(const LISTVIEW_INFO *infoPtr, INT iItem)
{
ITEM_INFO *lpItem;
HDPA hdpaSubItems;
TRACE("iItem=%d\n", iItem);
if (infoPtr->dwStyle & LVS_OWNERDATA) return -1;
if (iItem < 0 || iItem >= infoPtr->nItemCount) return -1;
hdpaSubItems = DPA_GetPtr(infoPtr->hdpaItems, iItem);
lpItem = DPA_GetPtr(hdpaSubItems, 0);
return lpItem->id->id;
}
/***
* DESCRIPTION:
@ -4988,9 +5080,18 @@ static BOOL LISTVIEW_DeleteItem(LISTVIEW_INFO *infoPtr, INT nItem)
{
HDPA hdpaSubItems;
ITEMHDR *hdrItem;
ITEM_INFO *lpItem;
ITEM_ID *lpID;
INT i;
hdpaSubItems = DPA_DeletePtr(infoPtr->hdpaItems, nItem);
lpItem = DPA_GetPtr(hdpaSubItems, 0);
/* free id struct */
i = DPA_GetPtrIndex(infoPtr->hdpaItemIds, lpItem->id);
lpID = DPA_GetPtr(infoPtr->hdpaItemIds, i);
DPA_DeletePtr(infoPtr->hdpaItemIds, i);
Free(lpID);
for (i = 0; i < DPA_GetPtrCount(hdpaSubItems); i++)
{
hdrItem = DPA_GetPtr(hdpaSubItems, i);
@ -6815,6 +6916,7 @@ static INT LISTVIEW_InsertItemT(LISTVIEW_INFO *infoPtr, const LVITEMW *lpLVItem,
HDPA hdpaSubItems;
NMLISTVIEW nmlv;
ITEM_INFO *lpItem;
ITEM_ID *lpID;
BOOL is_sorted, has_changed;
LVITEMW item;
HWND hwndSelf = infoPtr->hwndSelf;
@ -6834,6 +6936,13 @@ static INT LISTVIEW_InsertItemT(LISTVIEW_INFO *infoPtr, const LVITEMW *lpLVItem,
if ( !(hdpaSubItems = DPA_Create(8)) ) goto fail;
if ( !DPA_SetPtr(hdpaSubItems, 0, lpItem) ) assert (FALSE);
/* link with id struct */
if (!(lpID = Alloc(sizeof(ITEM_ID)))) goto fail;
lpItem->id = lpID;
lpID->item = hdpaSubItems;
lpID->id = get_next_itemid(infoPtr);
if ( DPA_InsertPtr(infoPtr->hdpaItemIds, infoPtr->nItemCount, lpID) == -1) goto fail;
is_sorted = (infoPtr->dwStyle & (LVS_SORTASCENDING | LVS_SORTDESCENDING)) &&
!(infoPtr->dwStyle & LVS_OWNERDRAWFIXED) && (LPSTR_TEXTCALLBACKW != lpLVItem->pszText);
@ -8483,6 +8592,7 @@ static LRESULT LISTVIEW_NCCreate(HWND hwnd, const CREATESTRUCTW *lpcs)
/* allocate memory for the data structure */
if (!(infoPtr->selectionRanges = ranges_create(10))) goto fail;
if (!(infoPtr->hdpaItems = DPA_Create(10))) goto fail;
if (!(infoPtr->hdpaItemIds = DPA_Create(10))) goto fail;
if (!(infoPtr->hdpaPosX = DPA_Create(10))) goto fail;
if (!(infoPtr->hdpaPosY = DPA_Create(10))) goto fail;
if (!(infoPtr->hdpaColumns = DPA_Create(10))) goto fail;
@ -8492,6 +8602,7 @@ fail:
DestroyWindow(infoPtr->hwndHeader);
ranges_destroy(infoPtr->selectionRanges);
DPA_Destroy(infoPtr->hdpaItems);
DPA_Destroy(infoPtr->hdpaItemIds);
DPA_Destroy(infoPtr->hdpaPosX);
DPA_Destroy(infoPtr->hdpaPosY);
DPA_Destroy(infoPtr->hdpaColumns);
@ -9264,6 +9375,7 @@ static LRESULT LISTVIEW_NCDestroy(LISTVIEW_INFO *infoPtr)
/* destroy data structure */
DPA_Destroy(infoPtr->hdpaItems);
DPA_Destroy(infoPtr->hdpaItemIds);
DPA_Destroy(infoPtr->hdpaPosX);
DPA_Destroy(infoPtr->hdpaPosY);
DPA_Destroy(infoPtr->hdpaColumns);
@ -10381,9 +10493,11 @@ LISTVIEW_WindowProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
case LVM_ISITEMVISIBLE:
return LISTVIEW_IsItemVisible(infoPtr, (INT)wParam);
/* case LVM_MAPIDTOINDEX: */
case LVM_MAPIDTOINDEX:
return LISTVIEW_MapIdToIndex(infoPtr, (UINT)wParam);
/* case LVM_MAPINDEXTOID: */
case LVM_MAPINDEXTOID:
return LISTVIEW_MapIndexToId(infoPtr, (INT)wParam);
/* case LVM_MOVEGROUP: */

View File

@ -3588,24 +3588,51 @@ static void test_mapidindex(void)
HWND hwnd;
DWORD ret;
/* LVM_MAPINDEXTOID unsupported with LVS_OWNERDATA */
hwnd = create_listview_control(LVS_OWNERDATA);
ok(hwnd != NULL, "failed to create a listview window\n");
insert_item(hwnd, 0);
ret = SendMessage(hwnd, LVM_MAPINDEXTOID, 0, 0);
expect(-1, ret);
DestroyWindow(hwnd);
hwnd = create_listview_control(0);
ok(hwnd != NULL, "failed to create a listview window\n");
/* LVM_MAPINDEXTOID with invalid index */
ret = SendMessage(hwnd, LVM_MAPINDEXTOID, 0, 0);
expect(-1, ret);
insert_item(hwnd, 0);
insert_item(hwnd, 1);
ret = SendMessage(hwnd, LVM_MAPINDEXTOID, -1, 0);
expect(-1, ret);
ret = SendMessage(hwnd, LVM_MAPINDEXTOID, 2, 0);
expect(-1, ret);
ret = SendMessage(hwnd, LVM_MAPINDEXTOID, 0, 0);
expect(0, ret);
ret = SendMessage(hwnd, LVM_MAPINDEXTOID, 1, 0);
todo_wine expect(1, ret);
expect(1, ret);
/* remove 0 indexed item, id retained */
SendMessage(hwnd, LVM_DELETEITEM, 0, 0);
ret = SendMessage(hwnd, LVM_MAPINDEXTOID, 0, 0);
todo_wine expect(1, ret);
expect(1, ret);
/* new id starts from previous value */
insert_item(hwnd, 1);
ret = SendMessage(hwnd, LVM_MAPINDEXTOID, 1, 0);
todo_wine expect(2, ret);
expect(2, ret);
/* get index by id */
ret = SendMessage(hwnd, LVM_MAPIDTOINDEX, -1, 0);
expect(-1, ret);
ret = SendMessage(hwnd, LVM_MAPIDTOINDEX, 0, 0);
expect(-1, ret);
ret = SendMessage(hwnd, LVM_MAPIDTOINDEX, 1, 0);
expect(0, ret);
ret = SendMessage(hwnd, LVM_MAPIDTOINDEX, 2, 0);
expect(1, ret);
DestroyWindow(hwnd);
}