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:
Francois Gouget 1999-12-25 22:57:17 +00:00 committed by Alexandre Julliard
parent e175445eae
commit 7e5f828b12
1 changed files with 134 additions and 179 deletions

View File

@ -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: */