[4/7] comctl32/listview: Implement LVM_MAPIDTOINDEX/LVM_MAPINDEXTOID
Nikolay Sivov
bunglehead at gmail.com
Sun Jun 21 17:50:13 CDT 2009
Changelog:
- Implement LVM_MAPIDTOINDEX/LVM_MAPINDEXTOID
>From 264b5eaac9eab18fd6aa708f619cfc5e00be070b Mon Sep 17 00:00:00 2001
From: Nikolay Sivov <bunglehead at gmail.com>
Date: Sun, 21 Jun 2009 00:48:07 +0400
Subject: Implement LVM_MAPIDTOINDEX/LVM_MAPINDEXTOID
---
dlls/comctl32/listview.c | 120 +++++++++++++++++++++++++++++++++++++++-
dlls/comctl32/tests/listview.c | 33 ++++++++++-
2 files changed, 147 insertions(+), 6 deletions(-)
diff --git a/dlls/comctl32/listview.c b/dlls/comctl32/listview.c
index c56d294..3bc90fd 100644
--- a/dlls/comctl32/listview.c
+++ b/dlls/comctl32/listview.c
@@ -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: */
diff --git a/dlls/comctl32/tests/listview.c b/dlls/comctl32/tests/listview.c
index a97a8dc..3f182e8 100644
--- a/dlls/comctl32/tests/listview.c
+++ b/dlls/comctl32/tests/listview.c
@@ -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);
}
--
1.5.6.5
More information about the wine-patches
mailing list