Better support very long strings by avoiding to copy them in a fixed
size buffer (one exception partly remains: callback strings). Raise the buffer size to 512 characters. Merge the handling of item 0 and other items together in GetItemA to reduce code duplication.
This commit is contained in:
parent
e175445eae
commit
7e5f828b12
|
@ -54,7 +54,7 @@ DEFAULT_DEBUG_CHANNEL(listview)
|
||||||
*/
|
*/
|
||||||
|
|
||||||
/* maximum size of a label */
|
/* maximum size of a label */
|
||||||
#define DISP_TEXT_SIZE 128
|
#define DISP_TEXT_SIZE 512
|
||||||
|
|
||||||
/* padding for items in list and small icon display modes */
|
/* padding for items in list and small icon display modes */
|
||||||
#define WIDTH_PADDING 12
|
#define WIDTH_PADDING 12
|
||||||
|
@ -99,6 +99,7 @@ HWND CreateEditLabel(LPCSTR text, DWORD style, INT x, INT y,
|
||||||
/*
|
/*
|
||||||
* forward declarations
|
* forward declarations
|
||||||
*/
|
*/
|
||||||
|
static LRESULT LISTVIEW_GetItemA(HWND hwnd, LPLVITEMA lpLVItem, BOOL internal);
|
||||||
static INT LISTVIEW_HitTestItem(HWND, LPLVHITTESTINFO);
|
static INT LISTVIEW_HitTestItem(HWND, LPLVHITTESTINFO);
|
||||||
static INT LISTVIEW_GetCountPerRow(HWND);
|
static INT LISTVIEW_GetCountPerRow(HWND);
|
||||||
static INT LISTVIEW_GetCountPerColumn(HWND);
|
static INT LISTVIEW_GetCountPerColumn(HWND);
|
||||||
|
@ -1777,7 +1778,7 @@ static VOID LISTVIEW_DrawSubItem(HWND hwnd, HDC hdc, INT nItem, INT nSubItem,
|
||||||
lvItem.iSubItem = nSubItem;
|
lvItem.iSubItem = nSubItem;
|
||||||
lvItem.cchTextMax = DISP_TEXT_SIZE;
|
lvItem.cchTextMax = DISP_TEXT_SIZE;
|
||||||
lvItem.pszText = szDispText;
|
lvItem.pszText = szDispText;
|
||||||
ListView_GetItemA(hwnd, &lvItem);
|
LISTVIEW_GetItemA(hwnd, &lvItem, TRUE);
|
||||||
|
|
||||||
/* set item colors */
|
/* set item colors */
|
||||||
SetBkColor(hdc, infoPtr->clrTextBk);
|
SetBkColor(hdc, infoPtr->clrTextBk);
|
||||||
|
@ -1821,7 +1822,7 @@ static VOID LISTVIEW_DrawItem(HWND hwnd, HDC hdc, INT nItem, RECT rcItem)
|
||||||
lvItem.iSubItem = 0;
|
lvItem.iSubItem = 0;
|
||||||
lvItem.cchTextMax = DISP_TEXT_SIZE;
|
lvItem.cchTextMax = DISP_TEXT_SIZE;
|
||||||
lvItem.pszText = szDispText;
|
lvItem.pszText = szDispText;
|
||||||
ListView_GetItemA(hwnd, &lvItem);
|
LISTVIEW_GetItemA(hwnd, &lvItem, TRUE);
|
||||||
|
|
||||||
/* state icons */
|
/* state icons */
|
||||||
if (infoPtr->himlState != NULL)
|
if (infoPtr->himlState != NULL)
|
||||||
|
@ -1942,7 +1943,7 @@ bottom=%d)\n", hwnd, hdc, nItem, rcItem.left, rcItem.top, rcItem.right,
|
||||||
lvItem.iSubItem = 0;
|
lvItem.iSubItem = 0;
|
||||||
lvItem.cchTextMax = DISP_TEXT_SIZE;
|
lvItem.cchTextMax = DISP_TEXT_SIZE;
|
||||||
lvItem.pszText = szDispText;
|
lvItem.pszText = szDispText;
|
||||||
ListView_GetItemA(hwnd, &lvItem);
|
LISTVIEW_GetItemA(hwnd, &lvItem, TRUE);
|
||||||
|
|
||||||
if (lvItem.state & LVIS_SELECTED)
|
if (lvItem.state & LVIS_SELECTED)
|
||||||
{
|
{
|
||||||
|
@ -3151,7 +3152,7 @@ static LRESULT LISTVIEW_FindItem(HWND hwnd, INT nStart,
|
||||||
|
|
||||||
lvItem.iItem = nItem;
|
lvItem.iItem = nItem;
|
||||||
lvItem.iSubItem = 0;
|
lvItem.iSubItem = 0;
|
||||||
if (ListView_GetItemA(hwnd, &lvItem) != FALSE)
|
if (LISTVIEW_GetItemA(hwnd, &lvItem, TRUE) != FALSE)
|
||||||
{
|
{
|
||||||
if (lvItem.mask & LVIF_TEXT)
|
if (lvItem.mask & LVIF_TEXT)
|
||||||
{
|
{
|
||||||
|
@ -3530,65 +3531,94 @@ static LRESULT LISTVIEW_GetImageList(HWND hwnd, INT nImageList)
|
||||||
* PARAMETER(S):
|
* PARAMETER(S):
|
||||||
* [I] HWND : window handle
|
* [I] HWND : window handle
|
||||||
* [IO] LPLVITEMA : item info
|
* [IO] LPLVITEMA : item info
|
||||||
|
* [I] internal : if true then we will use tricks that avoid copies
|
||||||
|
* but are not compatible with the regular interface
|
||||||
*
|
*
|
||||||
* RETURN:
|
* RETURN:
|
||||||
* SUCCESS : TRUE
|
* SUCCESS : TRUE
|
||||||
* FAILURE : FALSE
|
* FAILURE : FALSE
|
||||||
*/
|
*/
|
||||||
static LRESULT LISTVIEW_GetItemA(HWND hwnd, LPLVITEMA lpLVItem)
|
static LRESULT LISTVIEW_GetItemA(HWND hwnd, LPLVITEMA lpLVItem, BOOL internal)
|
||||||
{
|
{
|
||||||
LISTVIEW_INFO *infoPtr = (LISTVIEW_INFO *)GetWindowLongA(hwnd, 0);
|
LISTVIEW_INFO *infoPtr = (LISTVIEW_INFO *)GetWindowLongA(hwnd, 0);
|
||||||
LONG lCtrlId = GetWindowLongA(hwnd, GWL_ID);
|
LONG lCtrlId = GetWindowLongA(hwnd, GWL_ID);
|
||||||
BOOL bResult = FALSE;
|
|
||||||
NMLVDISPINFOA dispInfo;
|
NMLVDISPINFOA dispInfo;
|
||||||
LISTVIEW_SUBITEM *lpSubItem;
|
LISTVIEW_SUBITEM *lpSubItem;
|
||||||
LISTVIEW_ITEM *lpItem;
|
LISTVIEW_ITEM *lpItem;
|
||||||
|
INT* piImage;
|
||||||
|
LPSTR* ppszText;
|
||||||
HDPA hdpaSubItems;
|
HDPA hdpaSubItems;
|
||||||
|
/* In the following:
|
||||||
|
* lpLVItem describes the information requested by the user
|
||||||
|
* lpItem/lpSubItem is what we have
|
||||||
|
* dispInfo is a structure we use to request the missing
|
||||||
|
* information from the application
|
||||||
|
*/
|
||||||
|
|
||||||
TRACE("(hwnd=%x, lpLVItem=%p)\n", hwnd, lpLVItem);
|
TRACE("(hwnd=%x, lpLVItem=%p)\n", hwnd, lpLVItem);
|
||||||
|
|
||||||
if (lpLVItem != NULL)
|
if ((lpLVItem == NULL) ||
|
||||||
{
|
(lpLVItem->iItem < 0) ||
|
||||||
if ((lpLVItem->iItem >= 0) && (lpLVItem->iItem < GETITEMCOUNT(infoPtr)))
|
(lpLVItem->iItem >= GETITEMCOUNT(infoPtr))
|
||||||
{
|
)
|
||||||
ZeroMemory(&dispInfo, sizeof(NMLVDISPINFOA));
|
return FALSE;
|
||||||
|
|
||||||
hdpaSubItems = (HDPA)DPA_GetPtr(infoPtr->hdpaItems, lpLVItem->iItem);
|
hdpaSubItems = (HDPA)DPA_GetPtr(infoPtr->hdpaItems, lpLVItem->iItem);
|
||||||
if (hdpaSubItems != NULL)
|
if (hdpaSubItems == NULL)
|
||||||
{
|
return FALSE;
|
||||||
|
|
||||||
lpItem = (LISTVIEW_ITEM *)DPA_GetPtr(hdpaSubItems, 0);
|
lpItem = (LISTVIEW_ITEM *)DPA_GetPtr(hdpaSubItems, 0);
|
||||||
if (lpItem != NULL)
|
if (lpItem == NULL)
|
||||||
{
|
return FALSE;
|
||||||
bResult = TRUE;
|
|
||||||
|
ZeroMemory(&dispInfo, sizeof(NMLVDISPINFOA));
|
||||||
if (lpLVItem->iSubItem == 0)
|
if (lpLVItem->iSubItem == 0)
|
||||||
{
|
{
|
||||||
if ((lpItem->iImage == I_IMAGECALLBACK) &&
|
piImage=&lpItem->iImage;
|
||||||
(lpLVItem->mask & LVIF_IMAGE))
|
ppszText=&lpItem->pszText;
|
||||||
{
|
|
||||||
dispInfo.item.mask |= LVIF_IMAGE;
|
|
||||||
}
|
|
||||||
|
|
||||||
if ((lpItem->pszText == LPSTR_TEXTCALLBACKA) &&
|
|
||||||
(lpLVItem->mask & LVIF_TEXT))
|
|
||||||
{
|
|
||||||
dispInfo.item.mask |= LVIF_TEXT;
|
|
||||||
ZeroMemory(lpLVItem->pszText, sizeof(CHAR)*lpLVItem->cchTextMax);
|
|
||||||
dispInfo.item.pszText = lpLVItem->pszText;
|
|
||||||
dispInfo.item.cchTextMax = lpLVItem->cchTextMax;
|
|
||||||
}
|
|
||||||
|
|
||||||
if ((infoPtr->uCallbackMask != 0) && (lpLVItem->mask & LVIF_STATE))
|
if ((infoPtr->uCallbackMask != 0) && (lpLVItem->mask & LVIF_STATE))
|
||||||
{
|
{
|
||||||
dispInfo.item.mask |= LVIF_STATE;
|
dispInfo.item.mask |= LVIF_STATE;
|
||||||
dispInfo.item.stateMask = infoPtr->uCallbackMask;
|
dispInfo.item.stateMask = infoPtr->uCallbackMask;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
lpSubItem = LISTVIEW_GetSubItemPtr(hdpaSubItems, lpLVItem->iSubItem);
|
||||||
|
if (lpSubItem != NULL)
|
||||||
|
{
|
||||||
|
piImage=&lpItem->iImage;
|
||||||
|
ppszText=&lpItem->pszText;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
piImage=NULL;
|
||||||
|
ppszText=NULL;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if ((lpLVItem->mask & LVIF_IMAGE) &&
|
||||||
|
((piImage==NULL) || (*piImage == I_IMAGECALLBACK)))
|
||||||
|
{
|
||||||
|
dispInfo.item.mask |= LVIF_IMAGE;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ((lpLVItem->mask & LVIF_TEXT) &&
|
||||||
|
((ppszText==NULL) || (*ppszText == LPSTR_TEXTCALLBACKA)))
|
||||||
|
{
|
||||||
|
dispInfo.item.mask |= LVIF_TEXT;
|
||||||
|
dispInfo.item.pszText = lpLVItem->pszText;
|
||||||
|
dispInfo.item.cchTextMax = lpLVItem->cchTextMax;
|
||||||
|
}
|
||||||
|
|
||||||
if (dispInfo.item.mask != 0)
|
if (dispInfo.item.mask != 0)
|
||||||
{
|
{
|
||||||
|
/* We don't have all the requested info, query the application */
|
||||||
dispInfo.hdr.hwndFrom = hwnd;
|
dispInfo.hdr.hwndFrom = hwnd;
|
||||||
dispInfo.hdr.idFrom = lCtrlId;
|
dispInfo.hdr.idFrom = lCtrlId;
|
||||||
dispInfo.hdr.code = LVN_GETDISPINFOA;
|
dispInfo.hdr.code = LVN_GETDISPINFOA;
|
||||||
dispInfo.item.iItem = lpLVItem->iItem;
|
dispInfo.item.iItem = lpLVItem->iItem;
|
||||||
dispInfo.item.iSubItem = 0;
|
dispInfo.item.iSubItem = lpLVItem->iSubItem;
|
||||||
dispInfo.item.lParam = lpItem->lParam;
|
dispInfo.item.lParam = lpItem->lParam;
|
||||||
ListView_Notify(GetParent(hwnd), lCtrlId, &dispInfo);
|
ListView_Notify(GetParent(hwnd), lCtrlId, &dispInfo);
|
||||||
}
|
}
|
||||||
|
@ -3599,30 +3629,34 @@ static LRESULT LISTVIEW_GetItemA(HWND hwnd, LPLVITEMA lpLVItem)
|
||||||
}
|
}
|
||||||
else if (lpLVItem->mask & LVIF_IMAGE)
|
else if (lpLVItem->mask & LVIF_IMAGE)
|
||||||
{
|
{
|
||||||
lpLVItem->iImage = lpItem->iImage;
|
lpLVItem->iImage = *piImage;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (dispInfo.item.mask & LVIF_TEXT)
|
if (dispInfo.item.mask & LVIF_TEXT)
|
||||||
{
|
{
|
||||||
if (dispInfo.item.mask & LVIF_DI_SETITEM)
|
if ((dispInfo.item.mask & LVIF_DI_SETITEM) && (ppszText != NULL))
|
||||||
{
|
{
|
||||||
Str_SetPtrA(&lpItem->pszText, dispInfo.item.pszText);
|
Str_SetPtrA(ppszText, dispInfo.item.pszText);
|
||||||
}
|
}
|
||||||
strncpy(lpLVItem->pszText, dispInfo.item.pszText, lpLVItem->cchTextMax);
|
/* Here lpLVItem->pszText==dispInfo.item.pszText so a copy is unnecessary */
|
||||||
lpLVItem->pszText[lpLVItem->cchTextMax-1]='\0';
|
|
||||||
}
|
}
|
||||||
else if (lpLVItem->mask & LVIF_TEXT)
|
else if (lpLVItem->mask & LVIF_TEXT)
|
||||||
{
|
{
|
||||||
strncpy(lpLVItem->pszText, lpItem->pszText, lpLVItem->cchTextMax);
|
if (internal==TRUE)
|
||||||
lpLVItem->pszText[lpLVItem->cchTextMax-1]='\0';
|
{
|
||||||
|
lpLVItem->pszText=*ppszText;
|
||||||
|
} else {
|
||||||
|
lstrcpynA(lpLVItem->pszText, *ppszText, lpLVItem->cchTextMax);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (lpLVItem->iSubItem == 0)
|
||||||
|
{
|
||||||
if (dispInfo.item.mask & LVIF_STATE)
|
if (dispInfo.item.mask & LVIF_STATE)
|
||||||
{
|
{
|
||||||
lpLVItem->state = lpItem->state;
|
lpLVItem->state = lpItem->state;
|
||||||
lpLVItem->state &= ~dispInfo.item.stateMask;
|
lpLVItem->state &= ~dispInfo.item.stateMask;
|
||||||
lpLVItem->state |= (dispInfo.item.state &
|
lpLVItem->state |= (dispInfo.item.state & dispInfo.item.stateMask);
|
||||||
dispInfo.item.stateMask);
|
|
||||||
}
|
}
|
||||||
else if (lpLVItem->mask & LVIF_STATE)
|
else if (lpLVItem->mask & LVIF_STATE)
|
||||||
{
|
{
|
||||||
|
@ -3639,87 +3673,8 @@ static LRESULT LISTVIEW_GetItemA(HWND hwnd, LPLVITEMA lpLVItem)
|
||||||
lpLVItem->iIndent = lpItem->iIndent;
|
lpLVItem->iIndent = lpItem->iIndent;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
|
||||||
{
|
|
||||||
lpSubItem = LISTVIEW_GetSubItemPtr(hdpaSubItems,
|
|
||||||
lpLVItem->iSubItem);
|
|
||||||
if (lpSubItem != NULL)
|
|
||||||
{
|
|
||||||
if ((lpSubItem->iImage == I_IMAGECALLBACK) &&
|
|
||||||
(lpLVItem->mask & LVIF_IMAGE))
|
|
||||||
{
|
|
||||||
dispInfo.item.mask |= LVIF_IMAGE;
|
|
||||||
}
|
|
||||||
|
|
||||||
if ((lpSubItem->pszText == LPSTR_TEXTCALLBACKA) &&
|
return TRUE;
|
||||||
(lpLVItem->mask & LVIF_TEXT))
|
|
||||||
{
|
|
||||||
dispInfo.item.mask |= LVIF_TEXT;
|
|
||||||
ZeroMemory(lpLVItem->pszText,
|
|
||||||
sizeof(CHAR)*lpLVItem->cchTextMax);
|
|
||||||
dispInfo.item.pszText = lpLVItem->pszText;
|
|
||||||
dispInfo.item.cchTextMax = lpLVItem->cchTextMax;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
if (lpLVItem->mask & LVIF_IMAGE)
|
|
||||||
{
|
|
||||||
dispInfo.item.mask |= LVIF_IMAGE;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (lpLVItem->mask & LVIF_TEXT)
|
|
||||||
{
|
|
||||||
dispInfo.item.mask |= LVIF_TEXT;
|
|
||||||
ZeroMemory(lpLVItem->pszText,
|
|
||||||
sizeof(CHAR)*lpLVItem->cchTextMax);
|
|
||||||
dispInfo.item.pszText = lpLVItem->pszText;
|
|
||||||
dispInfo.item.cchTextMax = lpLVItem->cchTextMax;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (dispInfo.item.mask != 0)
|
|
||||||
{
|
|
||||||
dispInfo.hdr.hwndFrom = hwnd;
|
|
||||||
dispInfo.hdr.idFrom = lCtrlId;
|
|
||||||
dispInfo.hdr.code = LVN_GETDISPINFOA;
|
|
||||||
dispInfo.item.iItem = lpLVItem->iItem;
|
|
||||||
dispInfo.item.iSubItem = lpLVItem->iSubItem;
|
|
||||||
dispInfo.item.lParam = lpItem->lParam;
|
|
||||||
ListView_Notify(GetParent(hwnd), lCtrlId, &dispInfo);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (dispInfo.item.mask & LVIF_IMAGE)
|
|
||||||
{
|
|
||||||
lpLVItem->iImage = dispInfo.item.iImage;
|
|
||||||
}
|
|
||||||
else if (lpLVItem->mask & LVIF_IMAGE)
|
|
||||||
{
|
|
||||||
lpLVItem->iImage = lpItem->iImage;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (dispInfo.item.mask & LVIF_TEXT)
|
|
||||||
{
|
|
||||||
if (dispInfo.item.mask & LVIF_DI_SETITEM)
|
|
||||||
{
|
|
||||||
if (lpSubItem)
|
|
||||||
Str_SetPtrA(&lpSubItem->pszText, dispInfo.item.pszText);
|
|
||||||
}
|
|
||||||
strncpy(lpLVItem->pszText, dispInfo.item.pszText, lpLVItem->cchTextMax);
|
|
||||||
lpLVItem->pszText[lpLVItem->cchTextMax-1]='\0';
|
|
||||||
}
|
|
||||||
else if (lpLVItem->mask & LVIF_TEXT)
|
|
||||||
{
|
|
||||||
strncpy(lpLVItem->pszText, lpSubItem->pszText, lpLVItem->cchTextMax);
|
|
||||||
lpLVItem->pszText[lpLVItem->cchTextMax-1]='\0';
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return bResult;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* LISTVIEW_GetItemW */
|
/* LISTVIEW_GetItemW */
|
||||||
|
@ -4207,7 +4162,7 @@ static INT LISTVIEW_GetLabelWidth(HWND hwnd, INT nItem)
|
||||||
lvItem.iItem = nItem;
|
lvItem.iItem = nItem;
|
||||||
lvItem.cchTextMax = DISP_TEXT_SIZE;
|
lvItem.cchTextMax = DISP_TEXT_SIZE;
|
||||||
lvItem.pszText = szDispText;
|
lvItem.pszText = szDispText;
|
||||||
if (ListView_GetItemA(hwnd, &lvItem) != FALSE)
|
if (LISTVIEW_GetItemA(hwnd, &lvItem, TRUE) != FALSE)
|
||||||
{
|
{
|
||||||
nLabelWidth = ListView_GetStringWidthA(hwnd, lvItem.pszText);
|
nLabelWidth = ListView_GetStringWidthA(hwnd, lvItem.pszText);
|
||||||
}
|
}
|
||||||
|
@ -4268,7 +4223,7 @@ static LRESULT LISTVIEW_GetItemState(HWND hwnd, INT nItem, UINT uMask)
|
||||||
lvItem.iItem = nItem;
|
lvItem.iItem = nItem;
|
||||||
lvItem.stateMask = uMask;
|
lvItem.stateMask = uMask;
|
||||||
lvItem.mask = LVIF_STATE;
|
lvItem.mask = LVIF_STATE;
|
||||||
if (ListView_GetItemA(hwnd, &lvItem) != FALSE)
|
if (LISTVIEW_GetItemA(hwnd, &lvItem, TRUE) != FALSE)
|
||||||
{
|
{
|
||||||
uState = lvItem.state;
|
uState = lvItem.state;
|
||||||
}
|
}
|
||||||
|
@ -4301,7 +4256,7 @@ static LRESULT LISTVIEW_GetItemTextA(HWND hwnd, INT nItem, LPLVITEMA lpLVItem)
|
||||||
{
|
{
|
||||||
lpLVItem->mask = LVIF_TEXT;
|
lpLVItem->mask = LVIF_TEXT;
|
||||||
lpLVItem->iItem = nItem;
|
lpLVItem->iItem = nItem;
|
||||||
if (ListView_GetItemA(hwnd, lpLVItem) != FALSE)
|
if (LISTVIEW_GetItemA(hwnd, lpLVItem, FALSE) != FALSE)
|
||||||
{
|
{
|
||||||
nLength = lstrlenA(lpLVItem->pszText);
|
nLength = lstrlenA(lpLVItem->pszText);
|
||||||
}
|
}
|
||||||
|
@ -7085,7 +7040,7 @@ static LRESULT WINAPI LISTVIEW_WindowProc(HWND hwnd, UINT uMsg, WPARAM wParam,
|
||||||
/* case LVM_GETISEARCHSTRING: */
|
/* case LVM_GETISEARCHSTRING: */
|
||||||
|
|
||||||
case LVM_GETITEMA:
|
case LVM_GETITEMA:
|
||||||
return LISTVIEW_GetItemA(hwnd, (LPLVITEMA)lParam);
|
return LISTVIEW_GetItemA(hwnd, (LPLVITEMA)lParam, FALSE);
|
||||||
|
|
||||||
/* case LVM_GETITEMW: */
|
/* case LVM_GETITEMW: */
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue