Listview Updates (C0)
Dimitrie O. Paun
dpaun at rogers.com
Tue Sep 17 02:58:10 CDT 2002
ChangeLog:
-- Optimize the heck out of Report drawing
-- A bit of organization, for sanity's sake
-- Many simplifications, cleanups, etc.
Index: dlls/comctl32/listview.c
===================================================================
RCS file: /var/cvs/wine/dlls/comctl32/listview.c,v
retrieving revision 1.145
diff -u -r1.145 listview.c
--- dlls/comctl32/listview.c 16 Sep 2002 22:37:40 -0000 1.145
+++ dlls/comctl32/listview.c 17 Sep 2002 07:50:01 -0000
@@ -106,11 +106,11 @@
BOOL valid;
} LISTVIEW_ITEM;
-typedef struct tagLISTVIEW_SELECTION
+typedef struct tagRANGE
{
- DWORD lower;
- DWORD upper;
-} LISTVIEW_SELECTION;
+ INT lower;
+ INT upper;
+} RANGE;
typedef struct tagLISTVIEW_INFO
{
@@ -244,7 +244,7 @@
/*
* forward declarations
*/
-static LRESULT LISTVIEW_GetItemT(LISTVIEW_INFO *, LPLVITEMW, BOOL, BOOL);
+static BOOL LISTVIEW_GetItemT(LISTVIEW_INFO *, LPLVITEMW, BOOL, BOOL);
static INT LISTVIEW_SuperHitTestItem(LISTVIEW_INFO *, LPLV_INTHIT, BOOL);
static INT LISTVIEW_HitTestItem(LISTVIEW_INFO *, LPLVHITTESTINFO, BOOL);
static void LISTVIEW_AlignLeft(LISTVIEW_INFO *);
@@ -254,12 +254,12 @@
static INT LISTVIEW_GetItemHeight(LISTVIEW_INFO *);
static BOOL LISTVIEW_GetItemBoundBox(LISTVIEW_INFO *, INT, LPRECT);
static BOOL LISTVIEW_GetItemPosition(LISTVIEW_INFO *, INT, LPPOINT);
-static LRESULT LISTVIEW_GetItemRect(LISTVIEW_INFO *, INT, LPRECT);
-static LRESULT LISTVIEW_GetSubItemRect(LISTVIEW_INFO *, INT, INT, INT, LPRECT);
+static BOOL LISTVIEW_GetItemRect(LISTVIEW_INFO *, INT, LPRECT);
+static BOOL LISTVIEW_GetSubItemRect(LISTVIEW_INFO *, INT, INT, INT, LPRECT);
static INT LISTVIEW_GetItemWidth(LISTVIEW_INFO *);
static INT LISTVIEW_GetLabelWidth(LISTVIEW_INFO *, INT);
-static LRESULT LISTVIEW_GetOrigin(LISTVIEW_INFO *, LPPOINT);
-static LRESULT LISTVIEW_GetViewRect(LISTVIEW_INFO *, LPRECT);
+static BOOL LISTVIEW_GetOrigin(LISTVIEW_INFO *, LPPOINT);
+static BOOL LISTVIEW_GetViewRect(LISTVIEW_INFO *, LPRECT);
static BOOL LISTVIEW_RemoveColumn(HDPA, INT);
static BOOL LISTVIEW_RemoveSubItem(HDPA, INT);
static void LISTVIEW_SetGroupSelection(LISTVIEW_INFO *, INT);
@@ -268,7 +268,6 @@
static void LISTVIEW_UpdateScroll(LISTVIEW_INFO *);
static void LISTVIEW_SetSelection(LISTVIEW_INFO *, INT);
static BOOL LISTVIEW_UpdateSize(LISTVIEW_INFO *);
-static LRESULT LISTVIEW_SetViewRect(LISTVIEW_INFO *, LPRECT);
static void LISTVIEW_UnsupportedStyles(LONG);
static HWND LISTVIEW_EditLabelT(LISTVIEW_INFO *, INT, BOOL);
static LRESULT LISTVIEW_Command(LISTVIEW_INFO *, WPARAM, LPARAM);
@@ -291,64 +290,61 @@
#define COUNTOF(array) (sizeof(array)/sizeof(array[0]))
+
+/******** Text handling functions *************************************/
+
+/* A text pointer is either NULL, LPSTR_TEXTCALLBACK, or points to a
+ * text string. The string may be ANSI or Unicode, in which case
+ * the boolean isW tells us the type of the string.
+ *
+ * The name of the function tell what type of strings it expects:
+ * W: Unicode, T: ANSI/Unicode - function of isW
+ */
+
static inline BOOL is_textW(LPCWSTR text)
{
- return text != NULL && text != LPSTR_TEXTCALLBACKW;
+ return text != NULL && text != LPSTR_TEXTCALLBACKW;
}
static inline BOOL is_textT(LPCWSTR text, BOOL isW)
{
- /* we can ignore isW since LPSTR_TEXTCALLBACKW == LPSTR_TEXTCALLBACKA */
- return is_textW(text);
+ /* we can ignore isW since LPSTR_TEXTCALLBACKW == LPSTR_TEXTCALLBACKA */
+ return is_textW(text);
}
static inline int textlenT(LPCWSTR text, BOOL isW)
{
- return !is_textT(text, isW) ? 0 :
- isW ? lstrlenW(text) : lstrlenA((LPCSTR)text);
+ return !is_textT(text, isW) ? 0 :
+ isW ? lstrlenW(text) : lstrlenA((LPCSTR)text);
}
static inline void textcpynT(LPWSTR dest, BOOL isDestW, LPCWSTR src, BOOL isSrcW, INT max)
{
- if (isDestW)
- if (isSrcW) lstrcpynW(dest, src, max);
- else MultiByteToWideChar(CP_ACP, 0, (LPCSTR)src, -1, dest, max);
- else
- if (isSrcW) WideCharToMultiByte(CP_ACP, 0, src, -1, (LPSTR)dest, max, NULL, NULL);
- else lstrcpynA((LPSTR)dest, (LPCSTR)src, max);
-}
-
-static inline LPCSTR debugtext_t(LPCWSTR text, BOOL isW)
-{
- if (text == LPSTR_TEXTCALLBACKW) return "(callback)";
- return isW ? debugstr_w(text) : debugstr_a((LPCSTR)text);
-}
-
-static inline LPCSTR debugtext_tn(LPCWSTR text, BOOL isW, INT n)
-{
- if (text == LPSTR_TEXTCALLBACKW) return "(callback)";
- n = min(textlenT(text, isW), n);
- return isW ? debugstr_wn(text, n) : debugstr_an((LPCSTR)text, n);
+ if (isDestW)
+ if (isSrcW) lstrcpynW(dest, src, max);
+ else MultiByteToWideChar(CP_ACP, 0, (LPCSTR)src, -1, dest, max);
+ else
+ if (isSrcW) WideCharToMultiByte(CP_ACP, 0, src, -1, (LPSTR)dest, max, NULL, NULL);
+ else lstrcpynA((LPSTR)dest, (LPCSTR)src, max);
}
static inline LPWSTR textdupTtoW(LPCWSTR text, BOOL isW)
{
- LPWSTR wstr = (LPWSTR)text;
+ LPWSTR wstr = (LPWSTR)text;
- TRACE("(text=%s, isW=%d)\n", debugtext_t(text, isW), isW);
- if (!isW && is_textT(text, isW))
- {
- INT len = MultiByteToWideChar(CP_ACP, 0, (LPCSTR)text, -1, NULL, 0);
- wstr = HeapAlloc(GetProcessHeap(), 0, len * sizeof(WCHAR));
- if (wstr) MultiByteToWideChar(CP_ACP, 0, (LPCSTR)text, -1, wstr, len);
- }
- TRACE(" wstr=%s\n", debugstr_w(wstr));
- return wstr;
+ if (!isW && is_textT(text, isW))
+ {
+ INT len = MultiByteToWideChar(CP_ACP, 0, (LPCSTR)text, -1, NULL, 0);
+ wstr = HeapAlloc(GetProcessHeap(), 0, len * sizeof(WCHAR));
+ if (wstr) MultiByteToWideChar(CP_ACP, 0, (LPCSTR)text, -1, wstr, len);
+ }
+ TRACE(" wstr=%s\n", debugstr_w(wstr));
+ return wstr;
}
static inline void textfreeT(LPWSTR wstr, BOOL isW)
{
- if (!isW && is_textT(wstr, isW)) HeapFree(GetProcessHeap(), 0, wstr);
+ if (!isW && is_textT(wstr, isW)) HeapFree(GetProcessHeap(), 0, wstr);
}
/*
@@ -394,51 +390,102 @@
return 1;
}
-static inline LRESULT CallWindowProcT(WNDPROC proc, HWND hwnd, UINT uMsg,
- WPARAM wParam, LPARAM lParam, BOOL isW)
+static inline int lstrncmpiW(LPCWSTR s1, LPCWSTR s2, int n)
{
- if (isW)
- return CallWindowProcW(proc, hwnd, uMsg, wParam, lParam);
- else
- return CallWindowProcA(proc, hwnd, uMsg, wParam, lParam);
+ int res;
+
+ n = min(min(n, strlenW(s1)), strlenW(s2));
+ res = CompareStringW(LOCALE_USER_DEFAULT, NORM_IGNORECASE, s1, n, s2, n);
+ return res ? res - sizeof(WCHAR) : res;
+}
+
+/******** Debugging functions *****************************************/
+
+static inline LPCSTR debugtext_t(LPCWSTR text, BOOL isW)
+{
+ if (text == LPSTR_TEXTCALLBACKW) return "(callback)";
+ return isW ? debugstr_w(text) : debugstr_a((LPCSTR)text);
+}
+
+static inline LPCSTR debugtext_tn(LPCWSTR text, BOOL isW, INT n)
+{
+ if (text == LPSTR_TEXTCALLBACKW) return "(callback)";
+ n = min(textlenT(text, isW), n);
+ return isW ? debugstr_wn(text, n) : debugstr_an((LPCSTR)text, n);
+}
+
+static char* debuglvitem_t(LPLVITEMW lpLVItem, BOOL isW)
+{
+ static int index = 0;
+ static char buffers[20][256];
+ char* buf = buffers[index++ % 20];
+ if (lpLVItem == NULL) return "(null)";
+ snprintf(buf, 256, "{mask=%x, iItem=%d, iSubItem=%d, state=%x, stateMask=%x,"
+ " pszText=%s, cchTextMax=%d, iImage=%d, lParam=%lx, iIndent=%d}",
+ lpLVItem->mask, lpLVItem->iItem, lpLVItem->iSubItem,
+ lpLVItem->state, lpLVItem->stateMask,
+ debugtext_tn(lpLVItem->pszText, isW, 80),
+ lpLVItem->cchTextMax, lpLVItem->iImage, lpLVItem->lParam,
+ lpLVItem->iIndent);
+ return buf;
+}
+
+static char* debuglvcolumn_t(LPLVCOLUMNW lpColumn, BOOL isW)
+{
+ static int index = 0;
+ static char buffers[20][256];
+ char* buf = buffers[index++ % 20];
+ if (lpColumn == NULL) return "(null)";
+ snprintf(buf, 256, "{mask=%x, fmt=%x, cx=%d,"
+ " pszText=%s, cchTextMax=%d, iSubItem=%d}",
+ lpColumn->mask, lpColumn->fmt, lpColumn->cx,
+ lpColumn->mask & LVCF_TEXT ? debugtext_tn(lpColumn->pszText, isW, 80): "",
+ lpColumn->mask & LVCF_TEXT ? lpColumn->cchTextMax: 0, lpColumn->iSubItem);
+ return buf;
}
+/******** Notification functions i************************************/
+
static inline BOOL notify(LISTVIEW_INFO *infoPtr, INT code, LPNMHDR pnmh)
{
- pnmh->hwndFrom = infoPtr->hwndSelf;
- pnmh->idFrom = GetWindowLongW(infoPtr->hwndSelf, GWL_ID);
- pnmh->code = code;
- return (BOOL)SendMessageW(GetParent(infoPtr->hwndSelf), WM_NOTIFY,
- (WPARAM)pnmh->idFrom, (LPARAM)pnmh);
+ pnmh->hwndFrom = infoPtr->hwndSelf;
+ pnmh->idFrom = GetWindowLongW(infoPtr->hwndSelf, GWL_ID);
+ pnmh->code = code;
+ return (BOOL)SendMessageW(GetParent(infoPtr->hwndSelf), WM_NOTIFY,
+ (WPARAM)pnmh->idFrom, (LPARAM)pnmh);
}
static inline void notify_itemactivate(LISTVIEW_INFO *infoPtr)
{
- hwnd_notify(infoPtr->hwndSelf, LVN_ITEMACTIVATE);
+ NMHDR nmh;
+ notify(infoPtr, LVN_ITEMACTIVATE, &nmh);
}
-static inline BOOL listview_notify(LISTVIEW_INFO *infoPtr, INT code, LPNMLISTVIEW plvnm)
+static inline BOOL notify_listview(LISTVIEW_INFO *infoPtr, INT code, LPNMLISTVIEW plvnm)
{
- return notify(infoPtr, code, (LPNMHDR)plvnm);
+ return notify(infoPtr, code, (LPNMHDR)plvnm);
}
static int tabNotification[] = {
- LVN_BEGINLABELEDITW, LVN_BEGINLABELEDITA,
- LVN_ENDLABELEDITW, LVN_ENDLABELEDITA,
- LVN_GETDISPINFOW, LVN_GETDISPINFOA,
- LVN_SETDISPINFOW, LVN_SETDISPINFOA,
- LVN_ODFINDITEMW, LVN_ODFINDITEMA,
- LVN_GETINFOTIPW, LVN_GETINFOTIPA,
- 0
+ LVN_BEGINLABELEDITW, LVN_BEGINLABELEDITA,
+ LVN_ENDLABELEDITW, LVN_ENDLABELEDITA,
+ LVN_GETDISPINFOW, LVN_GETDISPINFOA,
+ LVN_SETDISPINFOW, LVN_SETDISPINFOA,
+ LVN_ODFINDITEMW, LVN_ODFINDITEMA,
+ LVN_GETINFOTIPW, LVN_GETINFOTIPA,
+ 0
};
static int get_ansi_notification(INT unicodeNotificationCode)
{
- int *pTabNotif = tabNotification;
- while (*pTabNotif && (unicodeNotificationCode != *pTabNotif++));
- if (*pTabNotif) return *pTabNotif;
- ERR("unknown notification %x\n", unicodeNotificationCode);
- return unicodeNotificationCode;
+ int *pTabNotif;
+
+ for(pTabNotif = tabNotification; *pTabNotif; pTabNotif += 2)
+ if (*pTabNotif == unicodeNotificationCode)
+ return *(pTabNotif + 1);
+
+ ERR("unknown notification %x\n", unicodeNotificationCode);
+ return unicodeNotificationCode;
}
/*
@@ -449,7 +496,7 @@
pdi : dispinfo structure (can be unicode or ansi)
isW : TRUE if dispinfo is Unicode
*/
-static BOOL dispinfo_notifyT(LISTVIEW_INFO *infoPtr, INT notificationCode, LPNMLVDISPINFOW pdi, BOOL isW)
+static BOOL notify_dispinfoT(LISTVIEW_INFO *infoPtr, INT notificationCode, LPNMLVDISPINFOW pdi, BOOL isW)
{
BOOL bResult = FALSE;
BOOL convertToAnsi = FALSE, convertToUnicode = FALSE;
@@ -520,135 +567,93 @@
return bResult;
}
-static inline LRESULT LISTVIEW_GetItemW(LISTVIEW_INFO *infoPtr, LPLVITEMW lpLVItem, BOOL internal)
+static inline void notify_odcachehint(LISTVIEW_INFO *infoPtr, INT iFrom, INT iTo)
{
- return LISTVIEW_GetItemT(infoPtr, lpLVItem, internal, TRUE);
+ NMLVCACHEHINT nmlv;
+
+ nmlv.iFrom = iFrom;
+ nmlv.iTo = iTo;
+ notify(infoPtr, LVN_ODCACHEHINT, &nmlv.hdr);
}
-static inline int lstrncmpiW(LPCWSTR s1, LPCWSTR s2, int n)
+static BOOL notify_customdraw (LISTVIEW_INFO *infoPtr, DWORD dwDrawStage, HDC hdc, RECT rc)
{
- int res;
+ NMLVCUSTOMDRAW nmlvcd;
- n = min(min(n, strlenW(s1)), strlenW(s2));
- res = CompareStringW(LOCALE_USER_DEFAULT, NORM_IGNORECASE, s1, n, s2, n);
- return res ? res - sizeof(WCHAR) : res;
+ TRACE("(dwDrawStage=%lx, hdc=%x, rc=?)\n", dwDrawStage, hdc);
+
+ nmlvcd.nmcd.dwDrawStage = dwDrawStage;
+ nmlvcd.nmcd.hdc = hdc;
+ nmlvcd.nmcd.rc = rc;
+ nmlvcd.nmcd.dwItemSpec = 0;
+ nmlvcd.nmcd.uItemState = 0;
+ nmlvcd.nmcd.lItemlParam = 0;
+ nmlvcd.clrText = infoPtr->clrText;
+ nmlvcd.clrTextBk = infoPtr->clrBk;
+
+ return (BOOL)notify(infoPtr, NM_CUSTOMDRAW, &nmlvcd.nmcd.hdr);
}
-static char* debuglvitem_t(LPLVITEMW lpLVItem, BOOL isW)
+/* FIXME: we should inline this where it's called somehow
+ * I think we need to pass in the structure
+ */
+static BOOL notify_customdrawitem (LISTVIEW_INFO *infoPtr, HDC hdc, UINT iItem, UINT iSubItem, UINT uItemDrawState)
{
- static int index = 0;
- static char buffers[20][256];
- char* buf = buffers[index++ % 20];
- if (lpLVItem == NULL) return "(null)";
- snprintf(buf, 256, "{mask=%x, iItem=%d, iSubItem=%d, state=%x, stateMask=%x,"
- " pszText=%s, cchTextMax=%d, iImage=%d, lParam=%lx, iIndent=%d}",
- lpLVItem->mask, lpLVItem->iItem, lpLVItem->iSubItem,
- lpLVItem->state, lpLVItem->stateMask,
- debugtext_tn(lpLVItem->pszText, isW, 80),
- lpLVItem->cchTextMax, lpLVItem->iImage, lpLVItem->lParam,
- lpLVItem->iIndent);
- return buf;
+ NMLVCUSTOMDRAW nmlvcd;
+ UINT uItemState;
+ RECT itemRect;
+ LVITEMW item;
+ BOOL bReturn;
+
+ item.iItem = iItem;
+ item.mask = LVIF_PARAM;
+ LISTVIEW_GetItemT(infoPtr, &item, TRUE, TRUE);
+
+ uItemState = 0;
+
+ if (LISTVIEW_GetItemState(infoPtr, iItem, LVIS_SELECTED)) uItemState |= CDIS_SELECTED;
+ if (LISTVIEW_GetItemState(infoPtr, iItem, LVIS_FOCUSED)) uItemState |= CDIS_FOCUS;
+ if (iItem == infoPtr->nHotItem) uItemState |= CDIS_HOT;
+
+ itemRect.left = LVIR_BOUNDS;
+ LISTVIEW_GetItemRect(infoPtr, iItem, &itemRect);
+
+ nmlvcd.nmcd.dwDrawStage = CDDS_ITEM | uItemDrawState;
+ nmlvcd.nmcd.hdc = hdc;
+ nmlvcd.nmcd.rc = itemRect;
+ nmlvcd.nmcd.dwItemSpec = iItem;
+ nmlvcd.nmcd.uItemState = uItemState;
+ nmlvcd.nmcd.lItemlParam = item.lParam;
+ nmlvcd.clrText = infoPtr->clrText;
+ nmlvcd.clrTextBk = infoPtr->clrBk;
+ nmlvcd.iSubItem = iSubItem;
+
+ TRACE("drawstage=%lx hdc=%x item=%lx, itemstate=%x, lItemlParam=%lx\n",
+ nmlvcd.nmcd.dwDrawStage, nmlvcd.nmcd.hdc, nmlvcd.nmcd.dwItemSpec,
+ nmlvcd.nmcd.uItemState, nmlvcd.nmcd.lItemlParam);
+
+ bReturn = notify(infoPtr, NM_CUSTOMDRAW, &nmlvcd.nmcd.hdr);
+
+ infoPtr->clrText = nmlvcd.clrText;
+ infoPtr->clrBk = nmlvcd.clrTextBk;
+
+ return bReturn;
}
-static char* debuglvcolumn_t(LPLVCOLUMNW lpColumn, BOOL isW)
+/******** Misc helper functions ************************************/
+
+static inline LRESULT CallWindowProcT(WNDPROC proc, HWND hwnd, UINT uMsg,
+ WPARAM wParam, LPARAM lParam, BOOL isW)
{
- static int index = 0;
- static char buffers[20][256];
- char* buf = buffers[index++ % 20];
- if (lpColumn == NULL) return "(null)";
- snprintf(buf, 256, "{mask=%x, fmt=%x, cx=%d,"
- " pszText=%s, cchTextMax=%d, iSubItem=%d}",
- lpColumn->mask, lpColumn->fmt, lpColumn->cx,
- lpColumn->mask & LVCF_TEXT ? debugtext_tn(lpColumn->pszText, isW, 80): "",
- lpColumn->mask & LVCF_TEXT ? lpColumn->cchTextMax: 0, lpColumn->iSubItem);
- return buf;
-}
-
-static BOOL
-LISTVIEW_SendCustomDrawNotify (LISTVIEW_INFO *infoPtr, DWORD dwDrawStage, HDC hdc,
- RECT rc)
-{
- NMLVCUSTOMDRAW nmcdhdr;
- LPNMCUSTOMDRAW nmcd;
-
- TRACE("(dwDrawStage=%lx, hdc=%x, rc=?)\n", dwDrawStage, hdc);
-
- nmcd= & nmcdhdr.nmcd;
- nmcd->hdr.hwndFrom = infoPtr->hwndSelf;
- nmcd->hdr.idFrom = GetWindowLongW( infoPtr->hwndSelf, GWL_ID);
- nmcd->hdr.code = NM_CUSTOMDRAW;
- nmcd->dwDrawStage= dwDrawStage;
- nmcd->hdc = hdc;
- nmcd->rc.left = rc.left;
- nmcd->rc.right = rc.right;
- nmcd->rc.bottom = rc.bottom;
- nmcd->rc.top = rc.top;
- nmcd->dwItemSpec = 0;
- nmcd->uItemState = 0;
- nmcd->lItemlParam= 0;
- nmcdhdr.clrText = infoPtr->clrText;
- nmcdhdr.clrTextBk= infoPtr->clrBk;
-
- return (BOOL)SendMessageW (GetParent (infoPtr->hwndSelf), WM_NOTIFY,
- (WPARAM) nmcd->hdr.idFrom, (LPARAM)&nmcdhdr);
-}
-
-static BOOL
-LISTVIEW_SendCustomDrawItemNotify (LISTVIEW_INFO *infoPtr, HDC hdc,
- UINT iItem, UINT iSubItem,
- UINT uItemDrawState)
-{
- NMLVCUSTOMDRAW nmcdhdr;
- LPNMCUSTOMDRAW nmcd;
- DWORD dwDrawStage,dwItemSpec;
- UINT uItemState;
- INT retval;
- RECT itemRect;
- LVITEMW item;
-
- ZeroMemory(&item,sizeof(item));
- item.iItem = iItem;
- item.mask = LVIF_PARAM;
- ListView_GetItemW(infoPtr->hwndSelf,&item);
-
- dwDrawStage=CDDS_ITEM | uItemDrawState;
- dwItemSpec=iItem;
- uItemState=0;
-
- if (LISTVIEW_GetItemState(infoPtr, iItem, LVIS_SELECTED)) uItemState |= CDIS_SELECTED;
- if (LISTVIEW_GetItemState(infoPtr, iItem, LVIS_FOCUSED)) uItemState |= CDIS_FOCUS;
- if (iItem == infoPtr->nHotItem) uItemState |= CDIS_HOT;
-
- itemRect.left = LVIR_BOUNDS;
- LISTVIEW_GetItemRect(infoPtr, iItem, &itemRect);
-
- nmcd= & nmcdhdr.nmcd;
- nmcd->hdr.hwndFrom = infoPtr->hwndSelf;
- nmcd->hdr.idFrom = GetWindowLongW( infoPtr->hwndSelf, GWL_ID);
- nmcd->hdr.code = NM_CUSTOMDRAW;
- nmcd->dwDrawStage= dwDrawStage;
- nmcd->hdc = hdc;
- nmcd->rc.left = itemRect.left;
- nmcd->rc.right = itemRect.right;
- nmcd->rc.bottom = itemRect.bottom;
- nmcd->rc.top = itemRect.top;
- nmcd->dwItemSpec = dwItemSpec;
- nmcd->uItemState = uItemState;
- nmcd->lItemlParam= item.lParam;
- nmcdhdr.clrText = infoPtr->clrText;
- nmcdhdr.clrTextBk= infoPtr->clrBk;
- nmcdhdr.iSubItem =iSubItem;
-
- TRACE("drawstage=%lx hdc=%x item=%lx, itemstate=%x, lItemlParam=%lx\n",
- nmcd->dwDrawStage, nmcd->hdc, nmcd->dwItemSpec,
- nmcd->uItemState, nmcd->lItemlParam);
-
- retval=SendMessageW (GetParent (infoPtr->hwndSelf), WM_NOTIFY,
- (WPARAM)nmcd->hdr.idFrom, (LPARAM)&nmcdhdr);
-
- infoPtr->clrText=nmcdhdr.clrText;
- infoPtr->clrBk =nmcdhdr.clrTextBk;
- return (BOOL) retval;
+ if (isW) return CallWindowProcW(proc, hwnd, uMsg, wParam, lParam);
+ else return CallWindowProcA(proc, hwnd, uMsg, wParam, lParam);
+}
+
+/******** Internal API functions ************************************/
+
+static inline BOOL LISTVIEW_GetItemW(LISTVIEW_INFO *infoPtr, LPLVITEMW lpLVItem, BOOL internal)
+{
+ return LISTVIEW_GetItemT(infoPtr, lpLVItem, internal, TRUE);
}
static inline int LISTVIEW_GetType(LISTVIEW_INFO *infoPtr)
@@ -668,9 +673,9 @@
*/
static inline INT LISTVIEW_GetCountPerRow(LISTVIEW_INFO *infoPtr)
{
- INT nListWidth = infoPtr->rcList.right - infoPtr->rcList.left;
+ INT nListWidth = infoPtr->rcList.right - infoPtr->rcList.left;
- return max(nListWidth/infoPtr->nItemWidth, 1);
+ return max(nListWidth/infoPtr->nItemWidth, 1);
}
/***
@@ -686,26 +691,29 @@
*/
static inline INT LISTVIEW_GetCountPerColumn(LISTVIEW_INFO *infoPtr)
{
- INT nListHeight = infoPtr->rcList.bottom - infoPtr->rcList.top;
+ INT nListHeight = infoPtr->rcList.bottom - infoPtr->rcList.top;
- return max(nListHeight / infoPtr->nItemHeight, 1);
+ return max(nListHeight / infoPtr->nItemHeight, 1);
}
/***
* DESCRIPTION:
- * Retrieves the count of visible items. Note that the returned count may
- * be a bit larger than the actual count.
+ * Retrieves the range of visible items. Note that the upper limit
+ * may be a bit larger than the actual last visible item.
*
* PARAMETER(S):
* [I] infoPtr : valid pointer to the listview structure
*
* RETURN:
- * maximum visible item count
+ * maximum range of visible items
*/
-static INT LISTVIEW_GetVisibleCount(LISTVIEW_INFO *infoPtr)
+static RANGE LISTVIEW_GetVisibleRange(LISTVIEW_INFO *infoPtr)
{
UINT uView = LISTVIEW_GetType(infoPtr);
INT nPerCol, nPerRow;
+ RANGE visrange;
+
+ visrange.lower = LISTVIEW_GetTopIndex(infoPtr);
if (uView == LVS_REPORT)
{
@@ -723,7 +731,11 @@
nPerRow = LISTVIEW_GetCountPerRow(infoPtr) + 1;
}
- return nPerCol * nPerRow;
+ visrange.upper = visrange.lower + nPerCol * nPerRow;
+ if (visrange.upper > GETITEMCOUNT(infoPtr))
+ visrange.upper = GETITEMCOUNT(infoPtr);
+
+ return visrange;
}
@@ -1053,13 +1065,11 @@
*/
static void LISTVIEW_InvalidateSelectedItems(LISTVIEW_INFO *infoPtr)
{
- INT i, nTop, nBottom;
+ RANGE visrange;
+ INT i;
- nTop = LISTVIEW_GetTopIndex(infoPtr);
- nBottom = nTop + LISTVIEW_GetVisibleCount(infoPtr);
- if (nBottom > GETITEMCOUNT(infoPtr)) nBottom = GETITEMCOUNT(infoPtr);
-
- for (i = nTop; i <= nBottom; i++)
+ visrange = LISTVIEW_GetVisibleRange(infoPtr);
+ for (i = visrange.lower; i <= visrange.upper; i++)
{
if (LISTVIEW_GetItemState(infoPtr, i, LVIS_SELECTED))
{
@@ -1165,7 +1175,7 @@
rcView.bottom = ptItem.y-off_y;
}
- LISTVIEW_SetViewRect(infoPtr, &rcView);
+ infoPtr->rcView = rcView;
}
}
@@ -1230,40 +1240,10 @@
rcView.right = ptItem.x;
}
- LISTVIEW_SetViewRect(infoPtr, &rcView);
+ infoPtr->rcView = rcView;
}
}
-/***
- * DESCRIPTION:
- * Set the bounding rectangle of all the items.
- *
- * PARAMETER(S):
- * [I] infoPtr : valid pointer to the listview structure
- * [I] LPRECT : bounding rectangle
- *
- * RETURN:
- * SUCCESS : TRUE
- * FAILURE : FALSE
- */
-static LRESULT LISTVIEW_SetViewRect(LISTVIEW_INFO *infoPtr, LPRECT lprcView)
-{
- BOOL bResult = FALSE;
-
- TRACE("(left=%d, top=%d, right=%d, bottom=%d)\n",
- lprcView->left, lprcView->top, lprcView->right, lprcView->bottom);
-
- if (lprcView != NULL)
- {
- bResult = TRUE;
- infoPtr->rcView.left = lprcView->left;
- infoPtr->rcView.top = lprcView->top;
- infoPtr->rcView.right = lprcView->right;
- infoPtr->rcView.bottom = lprcView->bottom;
- }
-
- return bResult;
-}
/***
* DESCRIPTION:
@@ -1271,35 +1251,29 @@
*
* PARAMETER(S):
* [I] infoPtr : valid pointer to the listview structure
- * [O] LPRECT : bounding rectangle
+ * [O] lprcView : bounding rectangle
*
* RETURN:
* SUCCESS : TRUE
* FAILURE : FALSE
*/
-static LRESULT LISTVIEW_GetViewRect(LISTVIEW_INFO *infoPtr, LPRECT lprcView)
+static BOOL LISTVIEW_GetViewRect(LISTVIEW_INFO *infoPtr, LPRECT lprcView)
{
- BOOL bResult = FALSE;
- POINT ptOrigin;
+ POINT ptOrigin;
- TRACE("(lprcView=%p)\n", lprcView);
+ TRACE("(lprcView=%p)\n", lprcView);
- if (lprcView != NULL)
- {
- bResult = LISTVIEW_GetOrigin(infoPtr, &ptOrigin);
- if (bResult)
- {
- lprcView->left = infoPtr->rcView.left + ptOrigin.x;
- lprcView->top = infoPtr->rcView.top + ptOrigin.y;
- lprcView->right = infoPtr->rcView.right + ptOrigin.x;
- lprcView->bottom = infoPtr->rcView.bottom + ptOrigin.y;
- }
+ if (!lprcView) return FALSE;
+
+ if (!LISTVIEW_GetOrigin(infoPtr, &ptOrigin)) return FALSE;
+
+ *lprcView = infoPtr->rcView;
+ OffsetRect(lprcView, ptOrigin.x, ptOrigin.y);
TRACE("(left=%d, top=%d, right=%d, bottom=%d)\n",
lprcView->left, lprcView->top, lprcView->right, lprcView->bottom);
- }
- return bResult;
+ return TRUE;
}
/***
@@ -1446,28 +1420,22 @@
*/
static INT LISTVIEW_GetItemHeight(LISTVIEW_INFO *infoPtr)
{
- UINT uView = LISTVIEW_GetType(infoPtr);
- INT nItemHeight = 0;
+ INT nItemHeight;
- if (uView == LVS_ICON)
- {
- nItemHeight = infoPtr->iconSpacing.cy;
- }
- else
- {
- if(infoPtr->himlState || infoPtr->himlSmall)
- nItemHeight = max(infoPtr->ntmHeight, infoPtr->iconSize.cy) + HEIGHT_PADDING;
+ if (LISTVIEW_GetType(infoPtr) == LVS_ICON)
+ nItemHeight = infoPtr->iconSpacing.cy;
+ else if(infoPtr->himlState || infoPtr->himlSmall)
+ nItemHeight = max(infoPtr->ntmHeight, infoPtr->iconSize.cy) + HEIGHT_PADDING;
else
- nItemHeight = infoPtr->ntmHeight;
- }
+ nItemHeight = infoPtr->ntmHeight;
- return nItemHeight;
+ return nItemHeight;
}
#if 0
static void LISTVIEW_PrintSelectionRanges(LISTVIEW_INFO *infoPtr)
{
- LISTVIEW_SELECTION *selection;
+ RANGE *selection;
INT topSelection = infoPtr->hdpaSelectionRanges->nItemCount;
INT i;
@@ -1496,11 +1464,9 @@
*/
static INT CALLBACK LISTVIEW_CompareSelectionRanges(LPVOID range1, LPVOID range2, LPARAM flags)
{
- if (((LISTVIEW_SELECTION*)(range1))->upper <
- ((LISTVIEW_SELECTION*)(range2))->lower)
+ if (((RANGE*)range1)->upper < ((RANGE*)range2)->lower)
return -1;
- if (((LISTVIEW_SELECTION*)(range2))->upper <
- ((LISTVIEW_SELECTION*)(range1))->lower)
+ if (((RANGE*)range2)->upper < ((RANGE*)range1)->lower)
return 1;
return 0;
}
@@ -1510,7 +1476,7 @@
*/
static BOOL add_selection_range(LISTVIEW_INFO *infoPtr, INT lower, INT upper, BOOL adj_sel_only)
{
- LISTVIEW_SELECTION selection;
+ RANGE selection;
LVITEMW lvItem;
INT index, i;
@@ -1524,10 +1490,10 @@
if (index == -1)
{
- LISTVIEW_SELECTION *newsel;
+ RANGE *newsel;
/* create the brand new selection to insert */
- newsel = (LISTVIEW_SELECTION *)COMCTL32_Alloc(sizeof(LISTVIEW_SELECTION));
+ newsel = (RANGE *)COMCTL32_Alloc(sizeof(RANGE));
if(!newsel) return FALSE;
newsel->lower = lower;
newsel->upper = upper;
@@ -1542,19 +1508,19 @@
}
else
{
- LISTVIEW_SELECTION *chksel, *mrgsel;
+ RANGE *chksel, *mrgsel;
INT fromindex, mergeindex;
chksel = DPA_GetPtr(infoPtr->hdpaSelectionRanges, index);
if (!chksel) return FALSE;
- TRACE("Merge with index %i (%lu - %lu)\n",
- index,chksel->lower, chksel->upper);
+ TRACE("Merge with index %i (%d - %d)\n",
+ index, chksel->lower, chksel->upper);
chksel->lower = min(lower, chksel->lower);
chksel->upper = max(upper, chksel->upper);
- TRACE("New range %i (%lu - %lu)\n",
- index,chksel->lower, chksel->upper);
+ TRACE("New range %i (%d - %d)\n",
+ index, chksel->lower, chksel->upper);
/* merge now common selection ranges */
fromindex = 0;
@@ -1585,8 +1551,7 @@
} while(1);
}
- /* FIXME: do we really need it? */
- DPA_Sort(infoPtr->hdpaSelectionRanges, LISTVIEW_CompareSelectionRanges, 0);
+ /*DPA_Sort(infoPtr->hdpaSelectionRanges, LISTVIEW_CompareSelectionRanges, 0);*/
if (adj_sel_only) return TRUE;
@@ -1605,7 +1570,7 @@
*/
static BOOL remove_selection_range(LISTVIEW_INFO *infoPtr, INT lower, INT upper, BOOL adj_sel_only)
{
- LISTVIEW_SELECTION remsel, tmpsel, *chksel;
+ RANGE remsel, tmpsel, *chksel;
BOOL done = FALSE;
LVITEMW lvItem;
INT index, i;
@@ -1616,7 +1581,7 @@
remsel.lower = lower;
remsel.upper = upper;
- TRACE("range: (%lu - %lu)\n", remsel.lower, remsel.upper);
+ TRACE("range: (%d - %d)\n", remsel.lower, remsel.upper);
do
{
@@ -1627,7 +1592,7 @@
chksel = DPA_GetPtr(infoPtr->hdpaSelectionRanges, index);
if (!chksel) return FALSE;
- TRACE("Matches range index %i (%lu-%lu)\n",
+ TRACE("Matches range index %i (%d - %d)\n",
index, chksel->lower, chksel->upper);
/* case 1: Same range */
@@ -1658,16 +1623,15 @@
/* case 5: fully internal */
else
{
- LISTVIEW_SELECTION *newsel =
- (LISTVIEW_SELECTION *)COMCTL32_Alloc(sizeof(LISTVIEW_SELECTION));
+ RANGE *newsel =
+ (RANGE *)COMCTL32_Alloc(sizeof(RANGE));
if (!newsel) return FALSE;
tmpsel = *chksel;
newsel->lower = chksel->lower;
newsel->upper = remsel.lower - 1;
chksel->lower = remsel.upper + 1;
DPA_InsertPtr(infoPtr->hdpaSelectionRanges, index, newsel);
- /*FIXME: why do we need the sort??? */
- DPA_Sort(infoPtr->hdpaSelectionRanges, LISTVIEW_CompareSelectionRanges, 0);
+ /*DPA_Sort(infoPtr->hdpaSelectionRanges, LISTVIEW_CompareSelectionRanges, 0);*/
chksel = &tmpsel;
}
@@ -1731,7 +1695,7 @@
*/
static LRESULT LISTVIEW_RemoveAllSelections(LISTVIEW_INFO *infoPtr)
{
- LISTVIEW_SELECTION *sel;
+ RANGE *sel;
static BOOL removing_all_selections = FALSE;
if (removing_all_selections) return TRUE;
@@ -1783,15 +1747,15 @@
*
* PARAMETER(S):
* [I] infoPtr : valid pointer to the listview structure
-* [I] INT : item index
-* [I] INT : Direction of shift, +1 or -1.
+* [I] nItem : item index
+* [I] direction : Direction of shift, +1 or -1.
*
* RETURN:
* None
*/
static void LISTVIEW_ShiftIndices(LISTVIEW_INFO *infoPtr, INT nItem, INT direction)
{
- LISTVIEW_SELECTION selection,*checkselection;
+ RANGE selection,*checkselection;
INT index;
TRACE("Shifting %iu, %i steps\n",nItem,direction);
@@ -1865,7 +1829,6 @@
if (nFirst == -1)
nFirst = nItem;
- ZeroMemory(&item,sizeof(item));
item.stateMask = LVIS_SELECTED;
item.state = LVIS_SELECTED;
@@ -1896,7 +1859,6 @@
{
LVITEMW item;
- ZeroMemory(&item,sizeof(item));
item.state = LVIS_SELECTED;
item.stateMask = LVIS_SELECTED;
@@ -1906,35 +1868,6 @@
infoPtr->nSelectionMark = nItem;
}
-/***
- * DESCRIPTION:
- * Selects items based on view coordinates.
- *
- * PARAMETER(S):
- * [I] infoPtr : valid pointer to the listview structure
- * [I] rcSelRect : selection rectangle
- *
- * RETURN:
- * None
- */
-static void LISTVIEW_SetSelectionRect(LISTVIEW_INFO *infoPtr, RECT rcSelRect)
-{
- POINT ptItem;
- INT i;
- LVITEMW item;
-
- ZeroMemory(&item,sizeof(item));
- item.stateMask = LVIS_SELECTED;
-
- /* FIXME: shouldn't we iterate over visible items only? */
- for (i = 0; i < GETITEMCOUNT(infoPtr); i++)
- {
- LISTVIEW_GetItemPosition(infoPtr, i, &ptItem);
-
- item.state = PtInRect(&rcSelRect, ptItem) ? LVIS_SELECTED : 0;
- LISTVIEW_SetItemState(infoPtr,i,&item);
- }
-}
/***
* DESCRIPTION:
@@ -1949,57 +1882,45 @@
*/
static void LISTVIEW_SetGroupSelection(LISTVIEW_INFO *infoPtr, INT nItem)
{
- UINT uView = LISTVIEW_GetType(infoPtr);
- LVITEMW item;
-
- ZeroMemory(&item,sizeof(item));
- item.stateMask = LVIS_SELECTED;
+ UINT uView = LISTVIEW_GetType(infoPtr);
+ INT i, nFirst, nLast;
+ LVITEMW item;
+ POINT ptItem;
+ RECT rcSel;
- if ((uView == LVS_LIST) || (uView == LVS_REPORT))
- {
- INT i;
- INT nFirst, nLast;
+ item.stateMask = LVIS_SELECTED;
- if (infoPtr->nSelectionMark == -1)
+ if ((uView == LVS_LIST) || (uView == LVS_REPORT))
{
- infoPtr->nSelectionMark = nFirst = nLast = nItem;
+ if (infoPtr->nSelectionMark == -1)
+ infoPtr->nSelectionMark = nFirst = nLast = nItem;
+ else
+ {
+ nFirst = min(infoPtr->nSelectionMark, nItem);
+ nLast = max(infoPtr->nSelectionMark, nItem);
+ }
}
else
{
- nFirst = min(infoPtr->nSelectionMark, nItem);
- nLast = max(infoPtr->nSelectionMark, nItem);
+ RECT rcItem, rcSelMark;
+ LISTVIEW_GetItemBoundBox(infoPtr, nItem, &rcItem);
+ LISTVIEW_GetItemBoundBox(infoPtr, infoPtr->nSelectionMark, &rcSelMark);
+ UnionRect(&rcSel, &rcItem, &rcSelMark);
+ nFirst = nLast = -1;
}
for (i = 0; i <= GETITEMCOUNT(infoPtr); i++)
{
- if ((i < nFirst) || (i > nLast))
- item.state = 0;
- else
- item.state = LVIS_SELECTED;
- LISTVIEW_SetItemState(infoPtr,i,&item);
+ if (nFirst > -1)
+ item.state = (i < nFirst) || (i > nLast) ? 0 : LVIS_SELECTED;
+ else
+ {
+ LISTVIEW_GetItemPosition(infoPtr, i, &ptItem);
+ item.state = PtInRect(&rcSel, ptItem) ? LVIS_SELECTED : 0;
+ }
+ LISTVIEW_SetItemState(infoPtr, i, &item);
}
- }
- else
- {
- RECT rcItem;
- RECT rcSelMark;
- RECT rcSel;
- LISTVIEW_GetItemBoundBox(infoPtr, nItem, &rcItem);
- LISTVIEW_GetItemBoundBox(infoPtr, infoPtr->nSelectionMark, &rcSelMark);
- rcSel.left = min(rcSelMark.left, rcItem.left);
- rcSel.top = min(rcSelMark.top, rcItem.top);
- rcSel.right = max(rcSelMark.right, rcItem.right);
- rcSel.bottom = max(rcSelMark.bottom, rcItem.bottom);
- LISTVIEW_SetSelectionRect(infoPtr, rcSel);
- TRACE("item %d (%d,%d)-(%d,%d), mark %d (%d,%d)-(%d,%d), sel (%d,%d)-(%d,%d)\n",
- nItem, rcItem.left, rcItem.top, rcItem.right, rcItem.bottom,
- infoPtr->nSelectionMark,
- rcSelMark.left, rcSelMark.top, rcSelMark.right, rcSelMark.bottom,
- rcSel.left, rcSel.top, rcSel.right, rcSel.bottom);
-
- }
-
- LISTVIEW_SetItemFocus(infoPtr, nItem);
+ LISTVIEW_SetItemFocus(infoPtr, nItem);
}
/***
@@ -2015,16 +1936,15 @@
*/
static void LISTVIEW_SetSelection(LISTVIEW_INFO *infoPtr, INT nItem)
{
- LVITEMW lvItem;
+ LVITEMW lvItem;
- LISTVIEW_RemoveAllSelections(infoPtr);
+ LISTVIEW_RemoveAllSelections(infoPtr);
- ZeroMemory(&lvItem, sizeof(lvItem));
- lvItem.state = LVIS_FOCUSED | LVIS_SELECTED;
- lvItem.stateMask = LVIS_FOCUSED | LVIS_SELECTED;
- LISTVIEW_SetItemState(infoPtr, nItem, &lvItem);
+ lvItem.state = LVIS_FOCUSED | LVIS_SELECTED;
+ lvItem.stateMask = LVIS_FOCUSED | LVIS_SELECTED;
+ LISTVIEW_SetItemState(infoPtr, nItem, &lvItem);
- infoPtr->nSelectionMark = nItem;
+ infoPtr->nSelectionMark = nItem;
}
/***
@@ -2093,14 +2013,12 @@
*/
static INT LISTVIEW_GetItemAtPt(LISTVIEW_INFO *infoPtr, POINT pt)
{
- INT i, nTop, nBottom;
+ RANGE visrange;
RECT rcItem;
+ INT i;
- nTop = LISTVIEW_GetTopIndex(infoPtr);
- nBottom = nTop + LISTVIEW_GetVisibleCount(infoPtr);
- if (nBottom > GETITEMCOUNT(infoPtr)) nBottom = GETITEMCOUNT(infoPtr);
-
- for (i = nTop; i <= nBottom; i++)
+ visrange = LISTVIEW_GetVisibleRange(infoPtr);
+ for (i = visrange.lower; i <= visrange.upper; i++)
{
rcItem.left = LVIR_SELECTBOUNDS;
if (LISTVIEW_GetItemRect(infoPtr, i, &rcItem))
@@ -2335,7 +2253,7 @@
nmlv.uNewState = lpLVItem->state;
nmlv.uOldState = oldState;
nmlv.uChanged = LVIF_STATE;
- listview_notify(infoPtr, LVN_ITEMCHANGED, &nmlv);
+ notify_listview(infoPtr, LVN_ITEMCHANGED, &nmlv);
return TRUE;
}
@@ -2376,7 +2294,7 @@
nmlv.lParam = lpItem->lParam;
/* send LVN_ITEMCHANGING notification, if the item is not being inserted */
- if(lpItem->valid && listview_notify(infoPtr, LVN_ITEMCHANGING, &nmlv))
+ if(lpItem->valid && notify_listview(infoPtr, LVN_ITEMCHANGING, &nmlv))
return FALSE;
/* copy information */
@@ -2429,7 +2347,7 @@
/* send LVN_ITEMCHANGED notification */
nmlv.lParam = lpItem->lParam;
- listview_notify(infoPtr, LVN_ITEMCHANGED, &nmlv);
+ notify_listview(infoPtr, LVN_ITEMCHANGED, &nmlv);
return TRUE;
}
@@ -2623,11 +2541,10 @@
nItem, nSubItem);
/* get information needed for drawing the item */
- ZeroMemory(&lvItem, sizeof(lvItem));
lvItem.mask = LVIF_TEXT;
lvItem.iItem = nItem;
lvItem.iSubItem = nSubItem;
- lvItem.cchTextMax = DISP_TEXT_SIZE;
+ lvItem.cchTextMax = COUNTOF(szDispText);
lvItem.pszText = szDispText;
*lvItem.pszText = '\0';
LISTVIEW_GetItemW(infoPtr, &lvItem, TRUE);
@@ -3099,158 +3016,145 @@
*/
static void LISTVIEW_RefreshReport(LISTVIEW_INFO *infoPtr, HDC hdc, DWORD cdmode)
{
- SCROLLINFO scrollInfo;
- INT nDrawPosY = infoPtr->rcList.top;
- INT nColumnCount;
- RECT rcItem, rcFull, *lprcFocus;
- INT j;
- INT nItem;
- INT nLast;
- BOOL FullSelected;
- DWORD cditemmode = CDRF_DODEFAULT;
- LONG lStyle = GetWindowLongW(infoPtr->hwndSelf, GWL_STYLE);
- INT scrollOffset;
-
- TRACE("\n");
-
- nItem = ListView_GetTopIndex(infoPtr->hwndSelf);
-
- /* add 1 for displaying a partial item at the bottom */
- nLast = min(nItem + LISTVIEW_GetCountPerColumn(infoPtr) + 1, GETITEMCOUNT(infoPtr));
-
- /* send cache hint notification */
- if (lStyle & LVS_OWNERDATA)
- {
- NMLVCACHEHINT nmlv;
-
- nmlv.hdr.hwndFrom = infoPtr->hwndSelf;
- nmlv.hdr.idFrom = GetWindowLongW(infoPtr->hwndSelf,GWL_ID);
- nmlv.hdr.code = LVN_ODCACHEHINT;
- nmlv.iFrom = nItem;
- nmlv.iTo = nLast;
-
- SendMessageW(GetParent(infoPtr->hwndSelf), WM_NOTIFY, (WPARAM)nmlv.hdr.idFrom,
- (LPARAM)&nmlv);
- }
-
- nColumnCount = Header_GetItemCount(infoPtr->hwndHeader);
- infoPtr->nColumnCount = nColumnCount; /* update nColumnCount */
- FullSelected = infoPtr->dwExStyle & LVS_EX_FULLROWSELECT;
-
- /* nothing to draw */
- if(GETITEMCOUNT(infoPtr) == 0)
- return;
+ SCROLLINFO scrollInfo;
+ INT rgntype, scrollOffset, nDrawPosY, j;
+ INT nTop, nItem, nLast, nUpdateHeight, nUpdateWidth;
+ INT nColumnCount, nFirstCol, nLastCol;
+ RECT rcItem, rcClip, *lprcFocus, *lprcCols;
+ BOOL bFullSelected;
+ DWORD cditemmode = CDRF_DODEFAULT;
+ LONG lStyle = GetWindowLongW(infoPtr->hwndSelf, GWL_STYLE);
+ UINT uID = GetWindowLongW(infoPtr->hwndSelf, GWL_ID);
- /* if we have focus, precompute full select rect, if need be */
- if (infoPtr->bFocus && FullSelected)
- {
- RECT br;
+ TRACE("\n");
- Header_GetItemRect(infoPtr->hwndHeader, 0, &rcFull);
- Header_GetItemRect(infoPtr->hwndHeader, nColumnCount-1, &br);
+ /* nothing to draw */
+ if(GETITEMCOUNT(infoPtr) == 0) return;
- rcFull.left += REPORT_MARGINX;
- rcFull.right = max(rcFull.left, br.right - REPORT_MARGINX);
- }
+ /* figure out what to draw */
+ rgntype = GetClipBox(hdc, &rcClip);
+ if (rgntype == NULLREGION) return;
+ nUpdateHeight = rcClip.bottom - rcClip.top + 1;
+ nUpdateWidth = rcClip.right - rcClip.left;
+ nTop = LISTVIEW_GetTopIndex(infoPtr);
+ nItem = nTop + (rcClip.top - infoPtr->rcList.top) / infoPtr->nItemHeight;
+ nLast = nItem + nUpdateHeight / infoPtr->nItemHeight;
+ if (nUpdateHeight % infoPtr->nItemHeight) nLast++;
+
+ /* send cache hint notification */
+ if (lStyle & LVS_OWNERDATA)
+ notify_odcachehint(infoPtr, nItem, nLast);
+
+ /* cache column info */
+ nColumnCount = Header_GetItemCount(infoPtr->hwndHeader);
+ infoPtr->nColumnCount = nColumnCount; /* update nColumnCount */
+ lprcCols = COMCTL32_Alloc(nColumnCount * sizeof(RECT));
+ if (!lprcCols) return;
+ for (j = 0; j < nColumnCount; j++)
+ Header_GetItemRect(infoPtr->hwndHeader, j, &lprcCols[j]);
- /* Get scroll bar info once before loop */
- ZeroMemory(&scrollInfo, sizeof(SCROLLINFO));
- scrollInfo.cbSize = sizeof(SCROLLINFO);
- scrollInfo.fMask = SIF_POS;
- GetScrollInfo(infoPtr->hwndSelf, SB_HORZ, &scrollInfo);
- scrollOffset = scrollInfo.nPos;
-
- for (; nItem < nLast; nItem++)
- {
- /* Do Owner Draw */
- if (lStyle & LVS_OWNERDRAWFIXED)
+ /* Get scroll bar info once before loop */
+ ZeroMemory(&scrollInfo, sizeof(SCROLLINFO));
+ scrollInfo.cbSize = sizeof(SCROLLINFO);
+ scrollInfo.fMask = SIF_POS;
+ GetScrollInfo(infoPtr->hwndSelf, SB_HORZ, &scrollInfo);
+ scrollOffset = scrollInfo.nPos;
+
+ /* we now narrow the columns as well */
+ nLastCol = nColumnCount - 1;
+ for(nFirstCol = 0; nFirstCol < nColumnCount; nFirstCol++)
+ if (lprcCols[nFirstCol].right - scrollOffset >= rcClip.left) break;
+ for(nLastCol = nColumnCount - 1; nLastCol >= 0; nLastCol--)
+ if (lprcCols[nLastCol].left - scrollOffset < rcClip.right) break;
+
+ /* a last few bits before we start drawing */
+ TRACE("nTop=%d, nItem=%d, nLast=%d, nFirstCol=%d, nLastCol=%d\n",
+ nTop, nItem, nLast, nFirstCol, nLastCol);
+ bFullSelected = infoPtr->dwExStyle & LVS_EX_FULLROWSELECT;
+ nDrawPosY = infoPtr->rcList.top + (nItem - nTop) * infoPtr->nItemHeight;
+
+ /* iterate through the invalidated rows */
+ for (; nItem < nLast; nItem++, nDrawPosY += infoPtr->nItemHeight)
{
- UINT uID = GetWindowLongW(infoPtr->hwndSelf, GWL_ID);
- DRAWITEMSTRUCT dis;
- LVITEMW item;
- RECT br;
-
- TRACE("Owner Drawn\n");
- dis.CtlType = ODT_LISTVIEW;
- dis.CtlID = uID;
- dis.itemID = nItem;
- dis.itemAction = ODA_DRAWENTIRE;
- dis.itemState = 0;
-
- if (LISTVIEW_GetItemState(infoPtr, nItem, LVIS_SELECTED))
- dis.itemState |= ODS_SELECTED;
- if (LISTVIEW_GetItemState(infoPtr, nItem, LVIS_FOCUSED))
- dis.itemState |= ODS_FOCUS;
-
- dis.hwndItem = infoPtr->hwndSelf;
- dis.hDC = hdc;
-
- Header_GetItemRect(infoPtr->hwndHeader, nColumnCount-1, &br);
-
- dis.rcItem.left = -scrollOffset;
- dis.rcItem.right = max(dis.rcItem.left, br.right - scrollOffset);
- dis.rcItem.top = nDrawPosY;
- dis.rcItem.bottom = dis.rcItem.top + infoPtr->nItemHeight;
-
- ZeroMemory(&item,sizeof(item));
- item.iItem = nItem;
- item.mask = LVIF_PARAM;
- ListView_GetItemW(infoPtr->hwndSelf, &item);
+ /* if owner wants to take a first stab at it, have it his way... */
+ if (lStyle & LVS_OWNERDRAWFIXED)
+ {
+ DRAWITEMSTRUCT dis;
+ LVITEMW item;
- dis.itemData = item.lParam;
+ TRACE("Owner Drawn\n");
+ dis.CtlType = ODT_LISTVIEW;
+ dis.CtlID = uID;
+ dis.itemID = nItem;
+ dis.itemAction = ODA_DRAWENTIRE;
+ dis.itemState = 0;
+
+ if (LISTVIEW_GetItemState(infoPtr, nItem, LVIS_SELECTED))
+ dis.itemState |= ODS_SELECTED;
+ if (LISTVIEW_GetItemState(infoPtr, nItem, LVIS_FOCUSED))
+ dis.itemState |= ODS_FOCUS;
+
+ dis.hwndItem = infoPtr->hwndSelf;
+ dis.hDC = hdc;
+
+ dis.rcItem.left = lprcCols[0].left;
+ dis.rcItem.right = lprcCols[nColumnCount - 1].right;
+ dis.rcItem.top = nDrawPosY;
+ dis.rcItem.bottom = dis.rcItem.top + infoPtr->nItemHeight;
+ OffsetRect(&dis.rcItem, -scrollOffset, 0);
+
+ item.iItem = nItem;
+ item.iSubItem = 0;
+ item.mask = LVIF_PARAM;
+ dis.itemData = LISTVIEW_GetItemW(infoPtr, &item, TRUE) ? item.lParam : 0;
- if (SendMessageW(GetParent(infoPtr->hwndSelf),WM_DRAWITEM,(WPARAM)uID,(LPARAM)&dis))
- {
- nDrawPosY += infoPtr->nItemHeight;
- continue;
+ if (SendMessageW(GetParent(infoPtr->hwndSelf), WM_DRAWITEM, uID, (LPARAM)&dis))
+ continue;
}
- }
- /* if we have focus, calculate focus rect */
- if (infoPtr->bFocus && LISTVIEW_GetItemState(infoPtr, nItem, LVIS_FOCUSED))
- lprcFocus = &infoPtr->rcFocus;
- else
- lprcFocus = 0;
-
- for (j = 0; j < nColumnCount; j++)
- {
- if (cdmode & CDRF_NOTIFYITEMDRAW)
- cditemmode = LISTVIEW_SendCustomDrawItemNotify (infoPtr, hdc, nItem, j,
- CDDS_ITEMPREPAINT);
- if (cditemmode & CDRF_SKIPDEFAULT)
- continue;
+ /* if we have focus, mark to calculate focus rect */
+ if (infoPtr->bFocus && LISTVIEW_GetItemState(infoPtr, nItem, LVIS_FOCUSED))
+ lprcFocus = &infoPtr->rcFocus;
+ else
+ lprcFocus = 0;
- Header_GetItemRect(infoPtr->hwndHeader, j, &rcItem);
+ /* iterate through the invalidated columns */
+ for (j = nFirstCol; j <= nLastCol; j++)
+ {
+
+ if (cdmode & CDRF_NOTIFYITEMDRAW)
+ cditemmode = notify_customdrawitem (infoPtr, hdc, nItem, j, CDDS_ITEMPREPAINT);
+ if (cditemmode & CDRF_SKIPDEFAULT) continue;
+
+ rcItem = lprcCols[j];
+ rcItem.left += REPORT_MARGINX;
+ rcItem.right = max(rcItem.left, rcItem.right - REPORT_MARGINX);
+ rcItem.top = nDrawPosY;
+ rcItem.bottom = rcItem.top + infoPtr->nItemHeight;
- rcItem.left += REPORT_MARGINX;
- rcItem.right = max(rcItem.left, rcItem.right - REPORT_MARGINX);
- rcItem.top = nDrawPosY;
- rcItem.bottom = rcItem.top + infoPtr->nItemHeight;
-
- /* Offset the Scroll Bar Pos */
- rcItem.left -= scrollOffset;
- rcItem.right -= scrollOffset;
+ /* Offset the Scroll Bar Pos */
+ OffsetRect(&rcItem, -scrollOffset, 0);
+
+ if (j == 0)
+ LISTVIEW_DrawItem(infoPtr, hdc, nItem, rcItem, bFullSelected, lprcFocus);
+ else
+ LISTVIEW_DrawSubItem(infoPtr, hdc, nItem, j, rcItem, bFullSelected);
- if (j == 0)
- LISTVIEW_DrawItem(infoPtr, hdc, nItem, rcItem, FullSelected, lprcFocus);
- else
- LISTVIEW_DrawSubItem(infoPtr, hdc, nItem, j, rcItem, FullSelected);
+ if (cditemmode & CDRF_NOTIFYPOSTPAINT)
+ notify_customdrawitem(infoPtr, hdc, nItem, 0, CDDS_ITEMPOSTPAINT);
+ }
- if (cditemmode & CDRF_NOTIFYPOSTPAINT)
- LISTVIEW_SendCustomDrawItemNotify(infoPtr, hdc, nItem, 0,
- CDDS_ITEMPOSTPAINT);
- }
-
- /* Adjust focus if we have it, and we are in full select */
- if (lprcFocus && FullSelected)
- {
- rcFull.top = nDrawPosY;
- rcFull.bottom = rcFull.top + infoPtr->nItemHeight;
- infoPtr->rcFocus = rcFull;
+ /* Adjust focus if we have it, and we are in full select */
+ if (lprcFocus && bFullSelected)
+ {
+ infoPtr->rcFocus.left = lprcCols[0].left + REPORT_MARGINX;
+ infoPtr->rcFocus.right = max(infoPtr->rcFocus.left, lprcCols[nColumnCount - 1].right - REPORT_MARGINX);
+ infoPtr->rcFocus.top = nDrawPosY;
+ infoPtr->rcFocus.bottom = infoPtr->rcFocus.top + infoPtr->nItemHeight;
+ }
}
-
- nDrawPosY += infoPtr->nItemHeight;
- }
+
+ COMCTL32_Free(lprcCols);
}
/***
@@ -3297,7 +3201,7 @@
return;
if (cdmode & CDRF_NOTIFYITEMDRAW)
- cditemmode = LISTVIEW_SendCustomDrawItemNotify (infoPtr, hdc, nItem, 0,
+ cditemmode = notify_customdrawitem (infoPtr, hdc, nItem, 0,
CDDS_ITEMPREPAINT);
if (cditemmode & CDRF_SKIPDEFAULT)
continue;
@@ -3316,7 +3220,7 @@
LISTVIEW_DrawItem(infoPtr, hdc, nItem, rcItem, FALSE, lprcFocus);
if (cditemmode & CDRF_NOTIFYPOSTPAINT)
- LISTVIEW_SendCustomDrawItemNotify(infoPtr, hdc, nItem, 0,
+ notify_customdrawitem(infoPtr, hdc, nItem, 0,
CDDS_ITEMPOSTPAINT);
}
@@ -3354,7 +3258,7 @@
for (i = 0; i < GETITEMCOUNT(infoPtr); i++)
{
if (cdmode & CDRF_NOTIFYITEMDRAW)
- cditemmode = LISTVIEW_SendCustomDrawItemNotify (infoPtr, hdc, i, 0,
+ cditemmode = notify_customdrawitem (infoPtr, hdc, i, 0,
CDDS_ITEMPREPAINT);
if (cditemmode & CDRF_SKIPDEFAULT)
continue;
@@ -3391,7 +3295,7 @@
}
}
if (cditemmode & CDRF_NOTIFYPOSTPAINT)
- LISTVIEW_SendCustomDrawItemNotify(infoPtr, hdc, i, 0,
+ notify_customdrawitem(infoPtr, hdc, i, 0,
CDDS_ITEMPOSTPAINT);
}
}
@@ -3418,7 +3322,7 @@
GetClientRect(infoPtr->hwndSelf, &rcClient);
- cdmode = LISTVIEW_SendCustomDrawNotify(infoPtr, CDDS_PREPAINT, hdc, rcClient);
+ cdmode = notify_customdraw(infoPtr, CDDS_PREPAINT, hdc, rcClient);
if (cdmode == CDRF_SKIPDEFAULT) return;
infoPtr->bIsDrawing = TRUE;
@@ -3448,7 +3352,7 @@
SelectObject(hdc, hOldFont);
if (cdmode & CDRF_NOTIFYPOSTPAINT)
- LISTVIEW_SendCustomDrawNotify(infoPtr, CDDS_POSTPAINT, hdc, rcClient);
+ notify_customdraw(infoPtr, CDDS_POSTPAINT, hdc, rcClient);
infoPtr->bIsDrawing = FALSE;
}
@@ -3607,7 +3511,7 @@
suppressed */
ZeroMemory(&nmlv, sizeof(NMLISTVIEW));
nmlv.iItem = -1;
- bSuppress = listview_notify(infoPtr, LVN_DELETEALLITEMS, &nmlv);
+ bSuppress = notify_listview(infoPtr, LVN_DELETEALLITEMS, &nmlv);
for (i = 0; i < GETITEMCOUNT(infoPtr); i++)
{
@@ -3636,7 +3540,7 @@
/* send LVN_DELETEITEM notification */
nmlv.iItem = i;
nmlv.lParam = lpItem->lParam;
- listview_notify(infoPtr, LVN_DELETEITEM, &nmlv);
+ notify_listview(infoPtr, LVN_DELETEITEM, &nmlv);
}
/* free item string */
@@ -3882,7 +3786,7 @@
dispInfo.item.lParam = lpItem->lParam;
/* Do we need to update the Item Text */
- if(dispinfo_notifyT(infoPtr, LVN_ENDLABELEDITW, &dispInfo, isW))
+ if(notify_dispinfoT(infoPtr, LVN_ENDLABELEDITW, &dispInfo, isW))
if (lpItem->hdr.pszText != LPSTR_TEXTCALLBACKW && !(lStyle & LVS_OWNERDATA))
bResult = textsetptrT(&lpItem->hdr.pszText, pszText, isW);
@@ -3974,7 +3878,7 @@
dispInfo.item.iImage = lpItem->hdr.iImage;
dispInfo.item.lParam = lpItem->lParam;
- if (dispinfo_notifyT(infoPtr, LVN_BEGINLABELEDITW, &dispInfo, isW))
+ if (notify_dispinfoT(infoPtr, LVN_BEGINLABELEDITW, &dispInfo, isW))
return 0;
rect.left = LVIR_LABEL;
@@ -4569,7 +4473,7 @@
*/
static inline BOOL is_item_selected(LISTVIEW_INFO *infoPtr, INT nItem)
{
- LISTVIEW_SELECTION selection = { nItem, nItem };
+ RANGE selection = { nItem, nItem };
return DPA_Search(infoPtr->hdpaSelectionRanges, &selection, 0,
LISTVIEW_CompareSelectionRanges, 0, DPAS_SORTED) != -1;
@@ -4591,7 +4495,7 @@
* SUCCESS : TRUE
* FAILURE : FALSE
*/
-static LRESULT LISTVIEW_GetItemT(LISTVIEW_INFO *infoPtr, LPLVITEMW lpLVItem, BOOL internal, BOOL isW)
+static BOOL LISTVIEW_GetItemT(LISTVIEW_INFO *infoPtr, LPLVITEMW lpLVItem, BOOL internal, BOOL isW)
{
NMLVDISPINFOW dispInfo;
LISTVIEW_ITEM *lpItem;
@@ -4642,7 +4546,7 @@
{
memcpy(&dispInfo.item, lpLVItem, sizeof(LVITEMW));
dispInfo.item.stateMask &= infoPtr->uCallbackMask;
- dispinfo_notifyT(infoPtr, LVN_GETDISPINFOW, &dispInfo, isW);
+ notify_dispinfoT(infoPtr, LVN_GETDISPINFOW, &dispInfo, isW);
memcpy(lpLVItem, &dispInfo.item, sizeof(LVITEMW));
TRACE(" getdispinfo(1):lpLVItem=%s\n", debuglvitem_t(lpLVItem, isW));
}
@@ -4713,7 +4617,7 @@
dispInfo.item.iItem = lpLVItem->iItem;
dispInfo.item.iSubItem = lpLVItem->iSubItem;
dispInfo.item.lParam = lpItem->lParam;
- dispinfo_notifyT(infoPtr, LVN_GETDISPINFOW, &dispInfo, isW);
+ notify_dispinfoT(infoPtr, LVN_GETDISPINFOW, &dispInfo, isW);
TRACE(" getdispinfo(2):item=%s\n", debuglvitem_t(&dispInfo.item, isW));
}
@@ -5116,7 +5020,7 @@
* is the one with the focus. Ensure that the control's record of which
* item has the focus agrees with the items' records.
*/
-static LRESULT LISTVIEW_GetItemRect(LISTVIEW_INFO *infoPtr, INT nItem, LPRECT lprc)
+static BOOL LISTVIEW_GetItemRect(LISTVIEW_INFO *infoPtr, INT nItem, LPRECT lprc)
{
UINT uView = LISTVIEW_GetType(infoPtr);
BOOL bResult = FALSE;
@@ -5495,7 +5399,7 @@
}
-static LRESULT LISTVIEW_GetSubItemRect(LISTVIEW_INFO *infoPtr, INT nItem, INT nSubItem, INT
+static BOOL LISTVIEW_GetSubItemRect(LISTVIEW_INFO *infoPtr, INT nItem, INT nSubItem, INT
flags, LPRECT lprc)
{
UINT uView = LISTVIEW_GetType(infoPtr);
@@ -5809,7 +5713,7 @@
* SUCCESS : TRUE
* FAILURE : FALSE
*/
-static LRESULT LISTVIEW_GetOrigin(LISTVIEW_INFO *infoPtr, LPPOINT lpptOrigin)
+static BOOL LISTVIEW_GetOrigin(LISTVIEW_INFO *infoPtr, LPPOINT lpptOrigin)
{
LONG lStyle = GetWindowLongW(infoPtr->hwndSelf, GWL_STYLE);
UINT uView = lStyle & LVS_TYPEMASK;
@@ -6383,7 +6287,7 @@
ZeroMemory(&nmlv, sizeof(NMLISTVIEW));
nmlv.iItem = nItem;
nmlv.lParam = lpItem->lParam;
- listview_notify(infoPtr, LVN_INSERTITEM, &nmlv);
+ notify_listview(infoPtr, LVN_INSERTITEM, &nmlv);
/* align items (set position of each item) */
if ((uView == LVS_SMALLICON) || (uView == LVS_ICON))
@@ -7047,7 +6951,7 @@
*/
do
{
- LISTVIEW_SELECTION *selection;
+ RANGE *selection;
selection = DPA_GetPtr(infoPtr->hdpaSelectionRanges,0);
if (selection)
LISTVIEW_RemoveSelectionRange(infoPtr,selection->lower,
@@ -8055,7 +7959,7 @@
}
nmlv.ptAction.x = pts.x;
nmlv.ptAction.y = pts.y;
- listview_notify(infoPtr, NM_DBLCLK, &nmlv);
+ notify_listview(infoPtr, NM_DBLCLK, &nmlv);
/* To send the LVN_ITEMACTIVATE, it must be on an Item */
@@ -8195,7 +8099,7 @@
}
nmlv.ptAction.x = pts.x;
nmlv.ptAction.y = pts.y;
- listview_notify(infoPtr, NM_CLICK, &nmlv);
+ notify_listview(infoPtr, NM_CLICK, &nmlv);
/* set left button flag */
infoPtr->bLButtonDown = FALSE;
@@ -8300,7 +8204,7 @@
ZeroMemory(&nmlv, sizeof(NMLISTVIEW));
nmlv.iItem = -1;
nmlv.iSubItem = ((LPNMHEADERW)lpnmh)->iItem;
- listview_notify(infoPtr, LVN_COLUMNCLICK, &nmlv);
+ notify_listview(infoPtr, LVN_COLUMNCLICK, &nmlv);
}
else if(lpnmh->code == NM_RELEASEDCAPTURE)
{
@@ -8464,7 +8368,7 @@
}
nmlv.ptAction.x = pts.x;
nmlv.ptAction.y = pts.y;
- listview_notify(infoPtr, NM_RCLICK, &nmlv);
+ notify_listview(infoPtr, NM_RCLICK, &nmlv);
return 0;
}
More information about the wine-patches
mailing list