From 4d6df2cb91cce53352939921814c8df352401279 Mon Sep 17 00:00:00 2001 From: Luc Tourangeau Date: Fri, 12 Mar 1999 17:31:08 +0000 Subject: [PATCH] Changed the listview control to add the report view and fix some bugs for the list view. --- dlls/comctl32/header.c | 27 +- dlls/comctl32/listview.c | 5875 ++++++++++++++++++++++++-------------- include/commctrl.h | 27 +- include/listview.h | 31 +- 4 files changed, 3870 insertions(+), 2090 deletions(-) diff --git a/dlls/comctl32/header.c b/dlls/comctl32/header.c index 280e61b156e..f7dc5bf3398 100644 --- a/dlls/comctl32/header.c +++ b/dlls/comctl32/header.c @@ -730,19 +730,26 @@ HEADER_InsertItemA (WND *wndPtr, WPARAM wParam, LPARAM lParam) infoPtr->uNumItem++; infoPtr->items = COMCTL32_Alloc (sizeof (HEADER_ITEM) * infoPtr->uNumItem); - /* pre insert copy */ - if (nItem > 0) { - memcpy (&infoPtr->items[0], &oldItems[0], - nItem * sizeof(HEADER_ITEM)); + if (nItem == 0) { + memcpy (&infoPtr->items[1], &oldItems[0], + (infoPtr->uNumItem-1) * sizeof(HEADER_ITEM)); } + else + { + /* pre insert copy */ + if (nItem > 0) { + memcpy (&infoPtr->items[0], &oldItems[0], + nItem * sizeof(HEADER_ITEM)); + } - /* post insert copy */ - if (nItem < infoPtr->uNumItem - 1) { - memcpy (&infoPtr->items[nItem+1], &oldItems[nItem], - (infoPtr->uNumItem - nItem) * sizeof(HEADER_ITEM)); + /* post insert copy */ + if (nItem < infoPtr->uNumItem - 1) { + memcpy (&infoPtr->items[nItem+1], &oldItems[nItem], + (infoPtr->uNumItem - nItem) * sizeof(HEADER_ITEM)); + } } - - COMCTL32_Free (oldItems); + + COMCTL32_Free (oldItems); } lpItem = (HEADER_ITEM*)&infoPtr->items[nItem]; diff --git a/dlls/comctl32/listview.c b/dlls/comctl32/listview.c index 157af47f982..208f927e02c 100644 --- a/dlls/comctl32/listview.c +++ b/dlls/comctl32/listview.c @@ -5,139 +5,1310 @@ * Copyright 1999 Luc Tourangeau * * NOTES - * Listview control implementation. The behavior conforms to version 4.70 - * and earlier of the listview contol. + * Listview control implementation. * * TODO: - * Most messages and notifications - * Report, small icon and icon display modes + * LISTVIEW_GetMaxItemWidth : large icon view + * LISTVIEW_Notify : notification from children + * LISTVIEW_KeyDown : key press messages + * LISTVIEW_HScroll : small icon and icon + * LISTVIEW_VScroll : small icon and icon + * LISTVIEW_SortItems : empty stub + * LISTVIEW_SetItemPosition : small icon and icon + * LISTVIEW_SetItemCount : empty stub + * LISTVIEW_SetItem32W : no unicode yet! + * LISTVIEW_SetColumn32A : DOUBLE CHECK + * LISTVIEW_Scroll : scrolling in pixels + * LISTVIEW_RedrawItems : define bounding rect + * LISTVIEW_InsertItem32W : no unicode yet! + * LISTVIEW_InsertColumn32W : no unicode yet! + * LISTVIEW_GetViewRect : small icon and icon + * LISTVIEW_GetOrigin : small icon and icon + * LISTVIEW_GetNumberOfWorkAreas : small icon and icon + * LISTVIEW_GetNextItem : all + * LISTVIEW_SetScroll : scrolling in pixels + * LISTVIEW_GetItemRect : all + * LISTVIEW_GetHotCursor : all + * LISTVIEW_GetHotItem : all + * LISTVIEW_GetHoverTime : all + * LISTVIEW_GetISearchString : all + * LISTVIEW_GetBkImage : all + * LISTVIEW_FindItem : all + * LISTVIEW_EnsureVisible : some + * LISTVIEW_EditLabel : REPORT (need to implement a timer) + * LISTVIEW_GetItemPosition : small icon and icon + * LISTVIEW_GetItemRect : some + * LISTVIEW_Arrange : small icon and icon + * LISTVIEW_ApproximateViewRect : report, small icon and icon + * LISTVIEW_RefreshIcon : large icon draw function */ -#include +#include "windows.h" #include "commctrl.h" #include "listview.h" #include "win.h" #include "debug.h" #include "winuser.h" +#include "string.h" -/* prototypes */ -static INT LISTVIEW_GetItemCountPerColumn(HWND hwnd); -static INT LISTVIEW_GetItemCountPerRow(HWND hwnd); -static INT LISTVIEW_GetFirstVisibleItem(HWND hwnd); -static VOID LISTVIEW_SetVisible(HWND hwnd, INT nItem); +/* constants */ +#define DISP_TEXT_SIZE 128 +#define WIDTH_PADDING 12 +#define HEIGHT_PADDING 2 +#define MIN_COLUMN_WIDTH 96 + +/* macro section */ +#define GETITEMCOUNT(infoPtr) ((infoPtr)->hdpaItems->nItemCount) +#define ListView_LVNotify(hwnd,lCtrlId,plvnm) \ + (BOOL)SendMessageA((hwnd),WM_NOTIFY,(WPARAM)(INT)lCtrlId,(LPARAM)(LPNMLISTVIEW)(plvnm)) +#define ListView_Notify(hwnd,lCtrlId,pnmh) \ + (BOOL)SendMessageA((hwnd),WM_NOTIFY,(WPARAM)(INT)lCtrlId,(LPARAM)(LPNMHDR)(pnmh)) + +/* forward declarations */ +static VOID LISTVIEW_SetSize(HWND hwnd, LONG lStyle, LONG lWidth, + LONG lHeight); +static VOID LISTVIEW_SetViewInfo(HWND hwnd); +static VOID LISTVIEW_SetScroll(HWND hwnd); +static VOID LISTVIEW_AddGroupSelection(HWND hwnd, INT nItem); +static VOID LISTVIEW_AddSelection(HWND hwnd, INT nItem); +static BOOL LISTVIEW_ToggleSelection(HWND hwnd, INT nItem); +static VOID LISTVIEW_SetGroupSelection(HWND hwnd, INT nItem); +static VOID LISTVIEW_SetSelection(HWND hwnd, INT nItem); +static VOID LISTVIEW_RemoveSelections(HWND hwnd, INT nFirst, INT nLast); +static VOID LISTVIEW_SetItemFocus(HWND hwnd, INT nItem); +static BOOL LISTVIEW_RemoveSubItem(HDPA hdpaSubItems, INT nSubItem); +static BOOL LISTVIEW_RemoveColumn(HDPA hdpaItems, INT nColumn); +static BOOL LISTVIEW_InitItem(HWND hwnd, LISTVIEW_ITEM *lpItem, + LPLVITEMA lpLVItem); +static BOOL LISTVIEW_InitSubItem(HWND hwnd, LISTVIEW_SUBITEM *lpSubItem, + LPLVITEMA lpLVItem); +static BOOL LISTVIEW_AddSubItem(HWND hwnd, LPLVITEMA lpLVItem); +static BOOL LISTVIEW_SetItem(HWND hwnd, LPLVITEMA lpLVItem); +static BOOL LISTVIEW_SetSubItem(HWND hwnd, LPLVITEMA lpLVItem); +static INT LISTVIEW_FindInsertPosition(HDPA hdpaSubItems, INT nSubItem); +static LISTVIEW_SUBITEM* LISTVIEW_GetSubItem(HDPA hdpaSubItems, INT nSubItem); /*** * DESCRIPTION: - * Scrolls the specified item into the visible area. + * Prints a message for unsupported window styles. * * PARAMETER(S): - * [I] HWND32 : window handle - * [I] INT32 : item index + * [I] LONG : window style * * RETURN: * None */ -static VOID LISTVIEW_SetVisible(HWND hwnd, INT nItem) +static VOID LISTVIEW_UnsupportedStyles(LONG lStyle) +{ + if ((LVS_TYPEMASK & lStyle) == LVS_ALIGNLEFT) + { + FIXME(listview, " LVS_ALIGNLEFT\n"); + } + + if ((LVS_TYPEMASK & lStyle) == LVS_ALIGNTOP) + { + FIXME(listview, " LVS_ALIGNTOP\n"); + } + + if ((LVS_TYPEMASK & lStyle) == LVS_AUTOARRANGE) + { + FIXME(listview, " LVS_AUTOARRANGE\n"); + } + + if ((LVS_TYPEMASK & lStyle) == LVS_EDITLABELS) + { + FIXME(listview, " LVS_EDITLABELS\n"); + } + + if ((LVS_TYPEMASK & lStyle) == LVS_ICON) + { + FIXME(listview, " LVS_ICON\n"); + } + + if ((LVS_TYPEMASK & lStyle) == LVS_NOCOLUMNHEADER) + { + FIXME(listview, " LVS_SORTDESCENDING\n"); + } + + if ((LVS_TYPEMASK & lStyle) == LVS_NOLABELWRAP) + { + FIXME(listview, " LVS_NOLABELWRAP\n"); + } + + if ((LVS_TYPEMASK & lStyle) == LVS_NOSCROLL) + { + FIXME(listview, " LVS_NOSCROLL\n"); + } + + if ((LVS_TYPEMASK & lStyle) == LVS_NOSORTHEADER) + { + FIXME(listview, " LVS_NOSORTHEADER\n"); + } + + if ((LVS_TYPEMASK & lStyle) == LVS_OWNERDRAWFIXED) + { + FIXME(listview, " LVS_OWNERDRAWFIXED\n"); + } + + if ((LVS_TYPEMASK & lStyle) == LVS_SHAREIMAGELISTS) + { + FIXME(listview, " LVS_SHAREIMAGELISTS\n"); + } + + if ((LVS_TYPEMASK & lStyle) == LVS_SHOWSELALWAYS) + { + FIXME(listview, " LVS_SHOWSELALWAYS\n"); + } + + if ((LVS_TYPEMASK & lStyle) == LVS_SINGLESEL) + { + FIXME(listview, " LVS_SINGLESEL\n"); + } + + if ((LVS_TYPEMASK & lStyle) == LVS_SMALLICON) + { + FIXME(listview, " LVS_SMALLICON\n"); + } + + if ((LVS_TYPEMASK & lStyle) == LVS_SORTDESCENDING) + { + FIXME(listview, " LVS_SORTDESCENDING\n"); + } + + if ((LVS_TYPEMASK & lStyle) == LVS_SORTDESCENDING) + { + FIXME(listview, " LVS_SORTDESCENDING\n"); + } +} + +/*** + * DESCRIPTION: + * Retrieves display information. + * + * PARAMETER(S): + * [I] HWND : window handle + * [I] LISTVIEW_ITEM* : listview control item + * [O] INT : image index + * [O] UINT : state value + * [O] CHAR** : string + * [I] INT : size of string + * + * RETURN: + * None + */ +static VOID LISTVIEW_GetItemDispInfo(HWND hwnd, INT nItem, + LISTVIEW_ITEM *lpItem, INT *pnDispImage, + UINT *puState, CHAR **ppszDispText, + INT nDispTextSize) +{ + LISTVIEW_INFO *infoPtr = (LISTVIEW_INFO *)GetWindowLongA(hwnd, 0); + LONG lCtrlId = GetWindowLongA(hwnd, GWL_ID); + NMLVDISPINFOA dispInfo; + ZeroMemory(&dispInfo, sizeof(NMLVDISPINFOA)); + + if ((pnDispImage != NULL) && (lpItem->iImage == I_IMAGECALLBACK)) + { + dispInfo.item.mask |= LVIF_IMAGE; + } + + if ((ppszDispText != NULL) && (lpItem->pszText == LPSTR_TEXTCALLBACKA)) + { + ZeroMemory(*ppszDispText, sizeof(CHAR)*nDispTextSize); + dispInfo.item.mask |= LVIF_TEXT; + dispInfo.item.pszText = *ppszDispText; + dispInfo.item.cchTextMax = nDispTextSize; + } + + if ((puState != NULL) && (infoPtr->uCallbackMask != 0)) + { + dispInfo.item.mask |= LVIF_STATE; + dispInfo.item.stateMask = infoPtr->uCallbackMask; + } + + if (dispInfo.item.mask != 0) + { + dispInfo.hdr.hwndFrom = hwnd; + dispInfo.hdr.idFrom = lCtrlId; + dispInfo.hdr.code = LVN_GETDISPINFOA; + dispInfo.item.iItem = nItem; + dispInfo.item.iSubItem = 0; + dispInfo.item.lParam = lpItem->lParam; + ListView_Notify(GetParent(hwnd), lCtrlId, &dispInfo); + } + + if (pnDispImage != NULL) + { + if (dispInfo.item.mask & LVIF_IMAGE) + { + *pnDispImage = dispInfo.item.iImage; + } + else + { + *pnDispImage = lpItem->iImage; + } + } + + if (ppszDispText != NULL) + { + if (dispInfo.item.mask & LVIF_TEXT) + { + if (dispInfo.item.mask & LVIF_DI_SETITEM) + { + Str_SetPtrA(&lpItem->pszText, dispInfo.item.pszText); + } + *ppszDispText = dispInfo.item.pszText; + } + else + { + *ppszDispText = lpItem->pszText; + } + } + + if (puState != NULL) + { + if (dispInfo.item.mask & LVIF_STATE) + { + *puState = lpItem->state; + *puState &= ~dispInfo.item.stateMask; + *puState |= (dispInfo.item.state & dispInfo.item.stateMask); + } + else + { + *puState = lpItem->state; + } + } +} + +/*** + * DESCRIPTION: + * Retrieves display information. + * + * PARAMETER(S): + * [I] HWND : window handle + * [I] LISTVIEW_SUBITEM* : listview control subitem + * [O] INT : image index + * [O] UINT : state value + * [O] CHAR** : string + * [I] INT : size of string + * + * RETURN: + * None + */ +static VOID LISTVIEW_GetSubItemDispInfo(HWND hwnd, INT nItem, LPARAM lParam, + LISTVIEW_SUBITEM *lpSubItem, + INT nColumn, INT *pnDispImage, + CHAR **ppszDispText, INT nDispTextSize) +{ + LONG lCtrlId = GetWindowLongA(hwnd, GWL_ID); + NMLVDISPINFOA dispInfo; + ZeroMemory(&dispInfo, sizeof(NMLVDISPINFOA)); + + if (lpSubItem == NULL) + { + ZeroMemory(*ppszDispText, sizeof(CHAR)*nDispTextSize); + dispInfo.item.mask |= LVIF_TEXT; + dispInfo.item.pszText = *ppszDispText; + dispInfo.item.cchTextMax = nDispTextSize; + dispInfo.hdr.hwndFrom = hwnd; + dispInfo.hdr.idFrom = lCtrlId; + dispInfo.hdr.code = LVN_GETDISPINFOA; + dispInfo.item.iItem = nItem; + dispInfo.item.iSubItem = nColumn; + dispInfo.item.lParam = lParam; + ListView_Notify(GetParent(hwnd), lCtrlId, &dispInfo); + if (dispInfo.item.mask & LVIF_DI_SETITEM) + { + Str_SetPtrA(&lpSubItem->pszText, dispInfo.item.pszText); + } + *ppszDispText = dispInfo.item.pszText; + } + else + { + if ((pnDispImage != NULL) && (lpSubItem->iImage == I_IMAGECALLBACK)) + { + dispInfo.item.mask |= LVIF_IMAGE; + } + + if ((ppszDispText != NULL) && (lpSubItem->pszText == LPSTR_TEXTCALLBACKA)) + { + ZeroMemory(*ppszDispText, sizeof(CHAR)*nDispTextSize); + dispInfo.item.mask |= LVIF_TEXT; + dispInfo.item.pszText = *ppszDispText; + dispInfo.item.cchTextMax = nDispTextSize; + } + + if (dispInfo.item.mask != 0) + { + dispInfo.hdr.hwndFrom = hwnd; + dispInfo.hdr.idFrom = lCtrlId; + dispInfo.hdr.code = LVN_GETDISPINFOA; + dispInfo.item.iItem = nItem; + dispInfo.item.iSubItem = lpSubItem->iSubItem; + dispInfo.item.lParam = lParam; + ListView_Notify(GetParent(hwnd), lCtrlId, &dispInfo); + } + + if (pnDispImage != NULL) + { + if (dispInfo.item.mask & LVIF_IMAGE) + { + *pnDispImage = dispInfo.item.iImage; + } + else + { + *pnDispImage = lpSubItem->iImage; + } + } + + if (ppszDispText != NULL) + { + if (dispInfo.item.mask & LVIF_TEXT) + { + if (dispInfo.item.mask & LVIF_DI_SETITEM) + { + Str_SetPtrA(&lpSubItem->pszText, dispInfo.item.pszText); + } + *ppszDispText = dispInfo.item.pszText; + } + else + { + *ppszDispText = lpSubItem->pszText; + } + } + } +} + +/*** + * DESCRIPTION: + * Calculates a new column width. + * + * PARAMETER(S): + * [I] HWND : window handle + * + * RETURN: + * Returns item width. + */ +static INT LISTVIEW_GetMaxItemWidth(HWND hwnd) +{ + LISTVIEW_INFO *infoPtr = (LISTVIEW_INFO *)GetWindowLongA(hwnd, 0); + LONG lStyle = GetWindowLongA(hwnd, GWL_STYLE); + LISTVIEW_ITEM *lpItem; + HDPA hdpaSubItems; + INT nStringWidth; + INT nMaxItemWidth = 0; + INT i; + + if ((LVS_TYPEMASK & lStyle) == LVS_ICON) + { + /* TO DO */ + } + else + { + for (i = 0; i < GETITEMCOUNT(infoPtr); i++) + { + hdpaSubItems = (HDPA)DPA_GetPtr(infoPtr->hdpaItems, i); + if (hdpaSubItems != NULL) + { + lpItem = (LISTVIEW_ITEM *)DPA_GetPtr(hdpaSubItems, 0); + if (lpItem != NULL) + { + CHAR szDispText[DISP_TEXT_SIZE]; + LPSTR pszDispText; + pszDispText = szDispText; + LISTVIEW_GetItemDispInfo(hwnd, i, lpItem, NULL, NULL, &pszDispText, + DISP_TEXT_SIZE); + nStringWidth = ListView_GetStringWidthA(hwnd, pszDispText); + nMaxItemWidth = max(nMaxItemWidth, nStringWidth); + } + } + } + + /* add arbitrary padding for separating columns */ + nMaxItemWidth += WIDTH_PADDING; + + if (infoPtr->himlSmall != NULL) + { + nMaxItemWidth += infoPtr->iconSize.cx; + } + + if (infoPtr->himlState != NULL) + { + nMaxItemWidth += infoPtr->iconSize.cx; + } + } + + nMaxItemWidth = max(MIN_COLUMN_WIDTH, nMaxItemWidth); + + return nMaxItemWidth; +} + +/*** + * DESCRIPTION: + * Sets diplay information (needed for drawing and calculations). + * + * PARAMETER(S): + * [I] HWND : window handle + * + * RETURN: + * None + */ +static VOID LISTVIEW_SetViewInfo(HWND hwnd) +{ + LISTVIEW_INFO *infoPtr = (LISTVIEW_INFO *)GetWindowLongA(hwnd, 0); + LONG lStyle = GetWindowLongA(hwnd, GWL_STYLE); + INT nHeight; + INT nWidth; + HDC hdc; + HFONT hOldFont; + TEXTMETRICA tm; + + /* get text height */ + hdc = GetDC(hwnd); + hOldFont = SelectObject(hdc, infoPtr->hFont); + GetTextMetricsA(hdc, &tm); + + nHeight = infoPtr->rcList.bottom - infoPtr->rcList.top; + nWidth = infoPtr->rcList.right - infoPtr->rcList.left; + + switch (LVS_TYPEMASK & lStyle) + { + case LVS_LIST: + infoPtr->nColumnWidth = LISTVIEW_GetMaxItemWidth(hwnd); + infoPtr->nItemHeight = (max(tm.tmHeight, infoPtr->iconSize.cy) + + HEIGHT_PADDING); + + infoPtr->nCountPerColumn = nHeight / infoPtr->nItemHeight; + if (infoPtr->nCountPerColumn == 0) + { + infoPtr->nCountPerColumn = 1; + } + + infoPtr->nCountPerRow = nWidth / infoPtr->nColumnWidth; + if (infoPtr->nCountPerRow == 0) + { + infoPtr->nCountPerRow = 1; + } + break; + + case LVS_REPORT: + infoPtr->nItemHeight = (max(tm.tmHeight, infoPtr->iconSize.cy) + + HEIGHT_PADDING); + infoPtr->nCountPerRow = 1; + infoPtr->nCountPerColumn = nHeight / infoPtr->nItemHeight; + if (infoPtr->nCountPerColumn == 0) + { + infoPtr->nCountPerColumn = 1; + } + break; + + } + + SelectObject(hdc, hOldFont); + ReleaseDC(hwnd, hdc); +} + +/*** + * DESCRIPTION: + * Adds a block of selections. + * + * PARAMETER(S): + * [I] HWND : window handle + * [I] INT : item index + * + * RETURN: + * None + */ +static VOID LISTVIEW_AddGroupSelection(HWND hwnd, INT nItem) +{ + LISTVIEW_INFO *infoPtr = (LISTVIEW_INFO *)GetWindowLongA(hwnd, 0); + INT nFirst = min(infoPtr->nSelectionMark, nItem); + INT nLast = max(infoPtr->nSelectionMark, nItem); + LVITEMA lvItem; + INT i; + + lvItem.state = LVIS_SELECTED; + lvItem.stateMask= LVIS_SELECTED; + + for (i = nFirst; i <= nLast; i++) + { + ListView_SetItemState(hwnd, i, &lvItem); + } + + LISTVIEW_SetItemFocus(hwnd, nItem); + infoPtr->nSelectionMark = nItem; +} + +/*** + * DESCRIPTION: + * Adds a single selection. + * + * PARAMETER(S): + * [I] HWND : window handle + * [I] INT : item index + * + * RETURN: + * None + */ +static VOID LISTVIEW_AddSelection(HWND hwnd, INT nItem) +{ + LISTVIEW_INFO *infoPtr = (LISTVIEW_INFO *)GetWindowLongA(hwnd, 0); + LVITEMA lvItem; + + lvItem.state = LVIS_SELECTED; + lvItem.stateMask= LVIS_SELECTED; + + ListView_SetItemState(hwnd, nItem, &lvItem); + + LISTVIEW_SetItemFocus(hwnd, nItem); + infoPtr->nSelectionMark = nItem; +} + +/*** + * DESCRIPTION: + * Selects or unselects an item. + * + * PARAMETER(S): + * [I] HWND : window handle + * [I] INT : item index + * + * RETURN: + * SELECT: TRUE + * UNSELECT : FALSE + */ +static BOOL LISTVIEW_ToggleSelection(HWND hwnd, INT nItem) +{ + LISTVIEW_INFO *infoPtr = (LISTVIEW_INFO *)GetWindowLongA(hwnd, 0); + BOOL bResult; + LVITEMA lvItem; + + lvItem.stateMask= LVIS_SELECTED; + + if (ListView_GetItemState(hwnd, nItem, LVIS_SELECTED) & LVIS_SELECTED) + { + lvItem.state = 0; + ListView_SetItemState(hwnd, nItem, &lvItem); + bResult = FALSE; + } + else + { + lvItem.state = LVIS_SELECTED; + ListView_SetItemState(hwnd, nItem, &lvItem); + bResult = TRUE; + } + + LISTVIEW_SetItemFocus(hwnd, nItem); + infoPtr->nSelectionMark = nItem; + + return bResult; +} + +/*** + * DESCRIPTION: + * Reinitilizes the listview items. + * + * PARAMETER(S): + * [I] HWND : window handle + * [I] INT : item index + * + * RETURN: + * None + */ +static VOID LISTVIEW_SetGroupSelection(HWND hwnd, INT nItem) +{ + LISTVIEW_INFO *infoPtr = (LISTVIEW_INFO *)GetWindowLongA(hwnd, 0); + INT nFirst = min(infoPtr->nSelectionMark, nItem); + INT nLast = max(infoPtr->nSelectionMark, nItem); + LVITEMA lvItem; + INT i; + + if (nFirst > 0) + { + LISTVIEW_RemoveSelections(hwnd, 0, nFirst - 1); + } + + if (nLast < GETITEMCOUNT(infoPtr)) + { + LISTVIEW_RemoveSelections(hwnd, nLast + 1, GETITEMCOUNT(infoPtr)); + } + + lvItem.state = LVIS_SELECTED; + lvItem.stateMask = LVIS_SELECTED; + + for (i = nFirst; i <= nLast; i++) + { + ListView_SetItemState(hwnd, i, &lvItem); + } + + LISTVIEW_SetItemFocus(hwnd, nItem); +} + +/*** + * DESCRIPTION: + * Manages the item focus. + * + * PARAMETER(S): + * [I] HWND : window handle + * [I] INT : item index + * + * RETURN: + * None + */ +static VOID LISTVIEW_SetItemFocus(HWND hwnd, INT nItem) +{ + LISTVIEW_INFO *infoPtr = (LISTVIEW_INFO *)GetWindowLongA(hwnd, 0); + LVITEMA lvItem; + + lvItem.state = 0; + lvItem.stateMask = LVIS_FOCUSED; + ListView_SetItemState(hwnd, infoPtr->nFocusedItem, &lvItem); + + lvItem.state = LVIS_FOCUSED; + lvItem.stateMask = LVIS_FOCUSED; + ListView_SetItemState(hwnd, nItem, &lvItem); + + infoPtr->nFocusedItem = nItem; + + /* if multiple selection is allowed */ + ListView_EnsureVisible(hwnd, nItem, FALSE); +} + +/*** + * DESCRIPTION: + * Reinitilizes the listview items. + * + * PARAMETER(S): + * [I] HWND : window handle + * [I] INT : item index + * + * RETURN: + * None + */ +static VOID LISTVIEW_SetSelection(HWND hwnd, INT nItem) +{ + LISTVIEW_INFO *infoPtr = (LISTVIEW_INFO *)GetWindowLongA(hwnd, 0); + LVITEMA lvItem; + + if (nItem > 0) + { + LISTVIEW_RemoveSelections(hwnd, 0, nItem - 1); + } + + if (nItem < GETITEMCOUNT(infoPtr)) + { + LISTVIEW_RemoveSelections(hwnd, nItem + 1, GETITEMCOUNT(infoPtr)); + } + + lvItem.state = 0; + lvItem.stateMask = LVIS_FOCUSED; + ListView_SetItemState(hwnd, infoPtr->nFocusedItem, &lvItem); + + lvItem.state = LVIS_SELECTED | LVIS_FOCUSED; + lvItem.stateMask = LVIS_SELECTED | LVIS_FOCUSED; + ListView_SetItemState(hwnd, nItem, &lvItem); + + infoPtr->nFocusedItem = nItem; + infoPtr->nSelectionMark = nItem; +} + +/*** + * DESCRIPTION: + * Reinitilizes the listview items. + * + * PARAMETER(S): + * [I] HWND : window handle + * [I] INT : item index + * + * RETURN: + * None + */ +static VOID LISTVIEW_KeySelection(HWND hwnd, INT nItem) +{ + WORD wShift = HIWORD(GetKeyState(VK_SHIFT)); + WORD wCtrl = HIWORD(GetKeyState(VK_CONTROL)); + + if (wShift) + { + LISTVIEW_SetGroupSelection(hwnd, nItem); + } + else if (wCtrl) + { + LISTVIEW_SetItemFocus(hwnd, nItem); + } + else + { + LISTVIEW_SetSelection(hwnd, nItem); + + /* if multiple selection is allowed */ + ListView_EnsureVisible(hwnd, nItem, FALSE); + } +} + +/*** + * DESCRIPTION: + * Removes all selection states. + * + * PARAMETER(S): + * [I] HWND : window handle + * [I] INT : item index + * + * RETURN: + * SUCCCESS : TRUE + * FAILURE : FALSE + */ +static VOID LISTVIEW_RemoveSelections(HWND hwnd, INT nFirst, INT nLast) +{ + LVITEMA lvItem; + INT i; + + lvItem.state = 0; + lvItem.stateMask = LVIS_SELECTED; + + for (i = nFirst; i <= nLast; i++) + { + ListView_SetItemState(hwnd, i, &lvItem); + } +} + +/*** + * DESCRIPTION: + * Removes a column. + * + * PARAMETER(S): + * [IO] HDPA : dynamic pointer array handle + * [I] INT : column index (subitem index) + * + * RETURN: + * SUCCCESS : TRUE + * FAILURE : FALSE + */ +static BOOL LISTVIEW_RemoveColumn(HDPA hdpaItems, INT nSubItem) +{ + BOOL bResult = TRUE; + HDPA hdpaSubItems; + INT i; + + for (i = 0; i < hdpaItems->nItemCount; i++) + { + hdpaSubItems = (HDPA)DPA_GetPtr(hdpaItems, i); + if (hdpaSubItems != NULL) + { + if (LISTVIEW_RemoveSubItem(hdpaSubItems, nSubItem) == FALSE) + { + bResult = FALSE; + } + } + } + + return bResult; +} + +/*** + * DESCRIPTION: + * Removes a subitem at a given position. + * + * PARAMETER(S): + * [IO] HDPA : dynamic pointer array handle + * [I] INT : subitem index + * + * RETURN: + * SUCCCESS : TRUE + * FAILURE : FALSE + */ +static BOOL LISTVIEW_RemoveSubItem(HDPA hdpaSubItems, INT nSubItem) +{ + LISTVIEW_SUBITEM *lpSubItem; + INT i; + + for (i = 1; i < hdpaSubItems->nItemCount; i++) + { + lpSubItem = (LISTVIEW_SUBITEM *)DPA_GetPtr(hdpaSubItems, i); + if (lpSubItem != NULL) + { + if (lpSubItem->iSubItem == nSubItem) + { + /* free string */ + if ((lpSubItem->pszText != NULL) && + (lpSubItem->pszText != LPSTR_TEXTCALLBACKA)) + { + COMCTL32_Free(lpSubItem->pszText); + } + + /* free item */ + COMCTL32_Free(lpSubItem); + + /* free dpa memory */ + if (DPA_DeletePtr(hdpaSubItems, i) == NULL) + { + return FALSE; + } + } + else if (lpSubItem->iSubItem > nSubItem) + { + return TRUE; + } + } + } + + return TRUE; +} + +/*** + * DESCRIPTION: + * Compares the item information. + * + * PARAMETER(S): + * [I] LISTVIEW_ITEM *: destination item + * [I] LPLVITEM : source item + * + * RETURN: + * SUCCCESS : TRUE (EQUAL) + * FAILURE : FALSE (NOT EQUAL) + */ +static UINT LISTVIEW_GetItemChanges(LISTVIEW_ITEM *lpItem, LPLVITEMA lpLVItem) +{ + UINT uChanged = 0; + + if ((lpItem != NULL) && (lpLVItem != NULL)) + { + if (lpLVItem->mask & LVIF_STATE) + { + if ((lpItem->state & lpLVItem->stateMask) != + (lpLVItem->state & lpLVItem->stateMask)) + { + uChanged |= LVIF_STATE; + } + } + + if (lpLVItem->mask & LVIF_IMAGE) + { + if (lpItem->iImage != lpLVItem->iImage) + { + uChanged |= LVIF_IMAGE; + } + } + + if (lpLVItem->mask & LVIF_PARAM) + { + if (lpItem->lParam != lpLVItem->lParam) + { + uChanged |= LVIF_PARAM; + } + } + + if (lpLVItem->mask & LVIF_INDENT) + { + if (lpItem->iIndent != lpLVItem->iIndent) + { + uChanged |= LVIF_INDENT; + } + } + + if (lpLVItem->mask & LVIF_TEXT) + { + if (lpLVItem->pszText == LPSTR_TEXTCALLBACKA) + { + if (lpItem->pszText != LPSTR_TEXTCALLBACKA) + { + uChanged |= LVIF_TEXT; + } + } + else + { + if (lpItem->pszText == LPSTR_TEXTCALLBACKA) + { + uChanged |= LVIF_TEXT; + } + } + } + } + + return uChanged; +} + +/*** + * DESCRIPTION: + * Initializes item attributes. + * + * PARAMETER(S): + * [I] HWND : window handle + * [O] LISTVIEW_ITEM *: destination item + * [I] LPLVITEM : source item + * + * RETURN: + * SUCCCESS : TRUE + * FAILURE : FALSE + */ +static BOOL LISTVIEW_InitItem(HWND hwnd, LISTVIEW_ITEM *lpItem, + LPLVITEMA lpLVItem) { LONG lStyle = GetWindowLongA(hwnd, GWL_STYLE); - INT nItemCountPerRow; - INT nItemCountPerColumn; - INT nLastItem; - INT nFirstItem; - INT nHScrollPos; - INT nVScrollPos; + BOOL bResult = FALSE; - /* retrieve the index of the first visible fully item */ - nFirstItem = LISTVIEW_GetFirstVisibleItem(hwnd); - - /* nunber of fully visible items per row */ - nItemCountPerRow = LISTVIEW_GetItemCountPerRow(hwnd); - - /* nunber of fully visible items per column */ - nItemCountPerColumn = LISTVIEW_GetItemCountPerColumn(hwnd); - - if ((nItemCountPerRow > 0) && (nItemCountPerColumn > 0)) + if ((lpItem != NULL) && (lpLVItem != NULL)) { - if (lStyle & LVS_LIST) + bResult = TRUE; + + if (lpLVItem->mask & LVIF_STATE) { - if (lStyle & WS_HSCROLL) - { - /* last visible item index */ - nLastItem = nItemCountPerColumn * nItemCountPerRow + nFirstItem - 1; - if (nItem > nLastItem) - { - /* calculate new scroll position based on item index */ - if (((nItem - nLastItem) % nItemCountPerColumn) == 0) - nHScrollPos = (nItem - nLastItem) / nItemCountPerColumn; - else - nHScrollPos = (nItem - nLastItem) / nItemCountPerColumn + 1; - SendMessageA(hwnd, LVM_SCROLL, (WPARAM)nHScrollPos, (LPARAM)0); - } - else if (nItem < nFirstItem) - { - /* calculate new scroll position based on item index */ - if (((nItem - nFirstItem) % nItemCountPerColumn) == 0) - nHScrollPos = (nItem - nFirstItem) / nItemCountPerColumn; - else - nHScrollPos = (nItem - nFirstItem) / nItemCountPerColumn - 1; - SendMessageA(hwnd, LVM_SCROLL, (WPARAM)nHScrollPos, (LPARAM)0); - } - } + lpItem->state &= ~lpLVItem->stateMask; + lpItem->state |= (lpLVItem->state & lpLVItem->stateMask); } - else if (lStyle & LVS_REPORT) + + if (lpLVItem->mask & LVIF_IMAGE) { - if (lStyle & WS_VSCROLL) - { - if (nFirstItem > 0) - { - nLastItem = nItemCountPerColumn + nFirstItem; - } - else -{ - nLastItem = nItemCountPerColumn + nFirstItem - 1; - } - - if (nItem > nLastItem) - { - /* calculate new scroll position based on item index */ - nVScrollPos = nItem - nLastItem; - SendMessageA(hwnd, LVM_SCROLL, (WPARAM)0, (LPARAM)nVScrollPos); - } - else if (nItem < nFirstItem) - { - /* calculate new scroll position based on item index */ - nVScrollPos = nItem - nFirstItem; - SendMessageA(hwnd, LVM_SCROLL, (WPARAM)0, (LPARAM)nVScrollPos); - } - } + lpItem->iImage = lpLVItem->iImage; } - else if ((lStyle & LVS_SMALLICON) || (lStyle & LVS_ICON)) + + if (lpLVItem->mask & LVIF_PARAM) { - if (lStyle & WS_VSCROLL) - { - /* last visible item index */ - nLastItem = nItemCountPerColumn * nItemCountPerRow + nFirstItem - 1; - if (nItem > nLastItem) - { - /* calculate new scroll position based on item index */ - nVScrollPos = (nItem - nLastItem) / nItemCountPerRow + 1; - SendMessageA(hwnd, LVM_SCROLL, (WPARAM)0, (LPARAM)nVScrollPos); - } - else if (nItem < nFirstItem) - { - /* calculate new scroll position based on item index */ - nHScrollPos = (nItem - nFirstItem) / nItemCountPerRow - 1; - SendMessageA(hwnd, LVM_SCROLL, (WPARAM)0, (LPARAM)nHScrollPos); - } - } + lpItem->lParam = lpLVItem->lParam; + } + + if (lpLVItem->mask & LVIF_INDENT) + { + lpItem->iIndent = lpLVItem->iIndent; } - /* refresh display */ - InvalidateRect(hwnd, NULL, FALSE); - UpdateWindow(hwnd); + if (lpLVItem->mask & LVIF_TEXT) + { + if (lpLVItem->pszText == LPSTR_TEXTCALLBACKA) + { + if ((lStyle & LVS_SORTASCENDING) || (lStyle & LVS_SORTDESCENDING)) + { + return FALSE; + } + if ((lpItem->pszText != NULL) && + (lpItem->pszText != LPSTR_TEXTCALLBACKA)) + { + COMCTL32_Free(lpItem->pszText); + } + + lpItem->pszText = LPSTR_TEXTCALLBACKA; + } + else + { + if (lpItem->pszText == LPSTR_TEXTCALLBACKA) + { + lpItem->pszText = NULL; + } + + bResult = Str_SetPtrA(&lpItem->pszText, lpLVItem->pszText); + } + } + } + + return bResult; } + +/*** + * DESCRIPTION: + * Initializes subitem attributes. + * + * NOTE: the documentation specifies that the operation fails if the user + * tries to set the indent of a subitem. + * + * PARAMETER(S): + * [I] HWND : window handle + * [O] LISTVIEW_SUBITEM *: destination subitem + * [I] LPLVITEM : source subitem + * + * RETURN: + * SUCCCESS : TRUE + * FAILURE : FALSE + */ +static BOOL LISTVIEW_InitSubItem(HWND hwnd, LISTVIEW_SUBITEM *lpSubItem, + LPLVITEMA lpLVItem) +{ + LONG lStyle = GetWindowLongA(hwnd, GWL_STYLE); + BOOL bResult = FALSE; + + if ((lpSubItem != NULL) && (lpLVItem != NULL)) + { + if (!(lpLVItem->mask & LVIF_INDENT)) + { + bResult = TRUE; + ZeroMemory(lpSubItem, sizeof(LISTVIEW_SUBITEM)); + + lpSubItem->iSubItem = lpLVItem->iSubItem; + + if (lpLVItem->mask & LVIF_IMAGE) + { + lpSubItem->iImage = lpLVItem->iImage; + } + + if (lpLVItem->mask & LVIF_TEXT) + { + if (lpLVItem->pszText == LPSTR_TEXTCALLBACKA) + { + if ((lStyle & LVS_SORTASCENDING) || (lStyle & LVS_SORTDESCENDING)) + { + return FALSE; + } + + if ((lpSubItem->pszText != NULL) && + (lpSubItem->pszText != LPSTR_TEXTCALLBACKA)) + { + COMCTL32_Free(lpSubItem->pszText); + } + + lpSubItem->pszText = LPSTR_TEXTCALLBACKA; + } + else + { + if (lpSubItem->pszText == LPSTR_TEXTCALLBACKA) + { + lpSubItem->pszText = NULL; + } + + bResult = Str_SetPtrA(&lpSubItem->pszText, lpLVItem->pszText); + } + } + } + } + + return bResult; +} + +/*** + * DESCRIPTION: + * Adds a subitem at a given position (column index). + * + * PARAMETER(S): + * [I] HWND : window handle + * [I] LPLVITEM : new subitem atttributes + * + * RETURN: + * SUCCESS : TRUE + * FAILURE : FALSE + */ +static BOOL LISTVIEW_AddSubItem(HWND hwnd, LPLVITEMA lpLVItem) +{ + LISTVIEW_INFO *infoPtr = (LISTVIEW_INFO *)GetWindowLongA(hwnd, 0); + BOOL bResult = FALSE; + HDPA hdpaSubItems; + LISTVIEW_SUBITEM *lpSubItem = NULL; + INT nPosition, nItem; + + if (lpLVItem != NULL) + { + hdpaSubItems = (HDPA)DPA_GetPtr(infoPtr->hdpaItems, lpLVItem->iItem); + if (hdpaSubItems != NULL) + { + lpSubItem = (LISTVIEW_SUBITEM *)COMCTL32_Alloc(sizeof(LISTVIEW_SUBITEM)); + if (lpSubItem != NULL) + { + if (LISTVIEW_InitSubItem(hwnd, lpSubItem, lpLVItem) == TRUE) + { + nPosition = LISTVIEW_FindInsertPosition(hdpaSubItems, + lpSubItem->iSubItem); + nItem = DPA_InsertPtr(hdpaSubItems, nPosition, lpSubItem); + if (nItem != -1) + { + bResult = TRUE; + } + } + } + } + } + + /* cleanup if unsuccessful */ + if ((bResult == FALSE) && (lpSubItem != NULL)) + { + COMCTL32_Free(lpSubItem); + } + + return bResult; +} + +/*** + * DESCRIPTION: + * Finds the dpa insert position (array index). + * + * PARAMETER(S): + * [I] HWND : window handle + * [I] INT : subitem index + * + * RETURN: + * SUCCESS : TRUE + * FAILURE : FALSE + */ +static INT LISTVIEW_FindInsertPosition(HDPA hdpaSubItems, INT nSubItem) +{ + LISTVIEW_SUBITEM *lpSubItem; + INT i; + + for (i = 1; i < hdpaSubItems->nItemCount; i++) + { + lpSubItem = (LISTVIEW_SUBITEM *)DPA_GetPtr(hdpaSubItems, i); + if (lpSubItem != NULL) + { + if (lpSubItem->iSubItem > nSubItem) + { + return i; + } + } + } + + return hdpaSubItems->nItemCount; +} + +/*** + * DESCRIPTION: + * Retrieves a listview subitem at a given position (column index). + * + * PARAMETER(S): + * [I] HWND : window handle + * [I] INT : subitem index + * + * RETURN: + * SUCCESS : TRUE + * FAILURE : FALSE + */ +static LISTVIEW_SUBITEM* LISTVIEW_GetSubItem(HDPA hdpaSubItems, INT nSubItem) +{ + LISTVIEW_SUBITEM *lpSubItem; + INT i; + + for (i = 1; i < hdpaSubItems->nItemCount; i++) + { + lpSubItem = (LISTVIEW_SUBITEM *)DPA_GetPtr(hdpaSubItems, i); + if (lpSubItem != NULL) + { + if (lpSubItem->iSubItem == nSubItem) + { + return lpSubItem; + } + else if (lpSubItem->iSubItem > nSubItem) + { + return NULL; + } + } + } + + return NULL; +} + +/*** + * DESCRIPTION: + * Sets item attributes. + * + * PARAMETER(S): + * [I] HWND : window handle + * [I] LPLVITEM : new item atttributes + * + * RETURN: + * SUCCESS : TRUE + * FAILURE : FALSE + */ +static BOOL LISTVIEW_SetItem(HWND hwnd, LPLVITEMA lpLVItem) +{ + LISTVIEW_INFO *infoPtr = (LISTVIEW_INFO *)GetWindowLongA(hwnd, 0); + BOOL bResult = FALSE; + HDPA hdpaSubItems; + LISTVIEW_ITEM *lpItem; + NMLISTVIEW nmlv; + UINT uChanged; + LONG lCtrlId = GetWindowLongA(hwnd, GWL_ID); + + if (lpLVItem != NULL) + { + if (lpLVItem->iSubItem == 0) + { + hdpaSubItems = (HDPA)DPA_GetPtr(infoPtr->hdpaItems, lpLVItem->iItem); + if (hdpaSubItems != NULL) + { + lpItem = (LISTVIEW_ITEM *)DPA_GetPtr(hdpaSubItems, lpLVItem->iSubItem); + if (lpItem != NULL) + { + ZeroMemory(&nmlv, sizeof(NMLISTVIEW)); + nmlv.hdr.hwndFrom = hwnd; + nmlv.hdr.idFrom = lCtrlId; + nmlv.hdr.code = LVN_ITEMCHANGING; + nmlv.lParam = lpItem->lParam; + uChanged = LISTVIEW_GetItemChanges(lpItem, lpLVItem); + if (uChanged != 0) + { + if (uChanged & LVIF_STATE) + { + nmlv.uNewState = lpLVItem->state & lpLVItem->stateMask; + nmlv.uOldState = lpItem->state & lpLVItem->stateMask; + } + + nmlv.uChanged = uChanged; + nmlv.iItem = lpLVItem->iItem; + nmlv.lParam = lpItem->lParam; + /* send LVN_ITEMCHANGING notification */ + ListView_LVNotify(GetParent(hwnd), lCtrlId, &nmlv); + + /* copy information */ + bResult = LISTVIEW_InitItem(hwnd, lpItem, lpLVItem); + + /* send LVN_ITEMCHANGED notification */ + nmlv.hdr.code = LVN_ITEMCHANGED; + ListView_LVNotify(GetParent(hwnd), lCtrlId, &nmlv); + } + else + { + bResult = TRUE; + } + + InvalidateRect(hwnd, NULL, FALSE); + } + } + } + } + + return bResult; +} + +/*** + * DESCRIPTION: + * Sets subitem attributes. + * + * PARAMETER(S): + * [I] HWND : window handle + * [I] LPLVITEM : new subitem atttributes + * + * RETURN: + * SUCCESS : TRUE + * FAILURE : FALSE + */ +static BOOL LISTVIEW_SetSubItem(HWND hwnd, LPLVITEMA lpLVItem) +{ + LISTVIEW_INFO *infoPtr = (LISTVIEW_INFO *)GetWindowLongA(hwnd, 0); + BOOL bResult = FALSE; + HDPA hdpaSubItems; + LISTVIEW_SUBITEM *lpSubItem; + + if (lpLVItem != NULL) + { + if (lpLVItem->iSubItem > 0) + { + hdpaSubItems = (HDPA)DPA_GetPtr(infoPtr->hdpaItems, lpLVItem->iItem); + if (hdpaSubItems != NULL) + { + /* set subitem only if column is present */ + if (Header_GetItemCount(infoPtr->hwndHeader) > lpLVItem->iSubItem) + { + lpSubItem = LISTVIEW_GetSubItem(hdpaSubItems, lpLVItem->iSubItem); + if (lpSubItem != NULL) + { + bResult = LISTVIEW_InitSubItem(hwnd, lpSubItem, lpLVItem); + } + else + { + bResult = LISTVIEW_AddSubItem(hwnd, lpLVItem); + } + + InvalidateRect(hwnd, NULL, FALSE); + } + } + } + } + + return bResult; } /*** @@ -145,55 +1316,32 @@ static VOID LISTVIEW_SetVisible(HWND hwnd, INT nItem) * Retrieves the index of the item at coordinate (0, 0) of the client area. * * PARAMETER(S): - * [I] HWND32 : window handle + * [I] HWND : window handle * * RETURN: * item index */ -static INT LISTVIEW_GetFirstVisibleItem(HWND hwnd) +static INT LISTVIEW_GetTopIndex(HWND hwnd) { + LISTVIEW_INFO *infoPtr = (LISTVIEW_INFO *) GetWindowLongA(hwnd, 0); LONG lStyle = GetWindowLongA(hwnd, GWL_STYLE); - INT nItemCountPerRow; - INT nItemCountPerColumn; - INT nMinRange; - INT nMaxRange; - INT nHScrollPos; -/* INT32 nVScrollPos; */ INT nItem = 0; - /* get number of items per column */ - nItemCountPerColumn = LISTVIEW_GetItemCountPerColumn(hwnd); - - /* get number of fully visble items per row */ - nItemCountPerRow = LISTVIEW_GetItemCountPerRow(hwnd); - - if ((nItemCountPerRow > 0) && (nItemCountPerColumn > 0)) + switch (LVS_TYPEMASK & lStyle) { - if (lStyle & LVS_LIST) + case LVS_LIST: + if (lStyle & WS_HSCROLL) { - if (lStyle & WS_HSCROLL) - { - GetScrollRange(hwnd, SB_HORZ, &nMinRange, &nMaxRange); - nHScrollPos = GetScrollPos(hwnd, SB_HORZ); - if (nMinRange < nHScrollPos) - { - nItem = ((nHScrollPos - nMinRange) * nItemCountPerColumn * - nItemCountPerRow); - } - } + nItem = GetScrollPos(hwnd, SB_HORZ) * infoPtr->nCountPerColumn; } - else if (lStyle & LVS_REPORT) + break; + + case LVS_REPORT: + if (lStyle & WS_VSCROLL) { - /* TO DO */ - } - else if (lStyle & LVS_SMALLICON) - { - /* TO DO */ - } - else if (lStyle & LVS_ICON) - { - /* TO DO */ + nItem = GetScrollPos(hwnd, SB_VERT); } + break; } return nItem; @@ -201,525 +1349,313 @@ static INT LISTVIEW_GetFirstVisibleItem(HWND hwnd) /*** * DESCRIPTION: - * Retrieves the number of items per row. In other words, the number - * visible display columns. + * Sets scrollbar(s). * * PARAMETER(S): - * [I] HWND32 : window handle + * [I] HWND : window handle * * RETURN: - * Number of items per row. + * TRUE if scrollbars were added, modified or removed. */ -static INT LISTVIEW_GetItemCountPerRow(HWND hwnd) +static VOID LISTVIEW_SetVScroll(HWND hwnd) { LISTVIEW_INFO *infoPtr = (LISTVIEW_INFO *)GetWindowLongA(hwnd, 0); LONG lStyle = GetWindowLongA(hwnd, GWL_STYLE); - INT nItemCountPerRow = 0; + INT nScrollPos; + INT nMaxRange; - if (infoPtr->nWidth > 0) + switch (LVS_TYPEMASK & lStyle) { - if (lStyle & LVS_LIST) - { - if (infoPtr->nColumnWidth > 0) - { - nItemCountPerRow = infoPtr->nWidth / infoPtr->nColumnWidth; - if (nItemCountPerRow == 0) - nItemCountPerRow = 1; - } - } - else if (lStyle & LVS_REPORT) - { - /* TO DO */ - } - else if (lStyle & LVS_SMALLICON) - { - /* TO DO */ - } - else if (lStyle & LVS_ICON) - { - /* TO DO */ - } + case LVS_REPORT: + nMaxRange = GETITEMCOUNT(infoPtr) - infoPtr->nCountPerColumn; + SetScrollRange(hwnd, SB_VERT, 0, nMaxRange, FALSE); + nScrollPos = ListView_GetTopIndex(hwnd); + SetScrollPos(hwnd, SB_VERT, nScrollPos, TRUE); + break; + + default: + /* TO DO */ } - - return nItemCountPerRow; } -/*** - * DESCRIPTION: - * Retrieves the number of items that can be displayed vertically in - * the listview. - * - * PARAMETER(S): - * [I] HWND32 : window handle - * - * RETURN: - * Number of items per column. - */ -static INT LISTVIEW_GetItemCountPerColumn(HWND hwnd) +static VOID LISTVIEW_SetHScroll(HWND hwnd) { - LISTVIEW_INFO *infoPtr = (LISTVIEW_INFO *)GetWindowLongA(hwnd, 0); +/* LISTVIEW_INFO *infoPtr = (LISTVIEW_INFO *)GetWindowLongA(hwnd, 0); */ LONG lStyle = GetWindowLongA(hwnd, GWL_STYLE); - INT nItemCountPerColumn = 0; - - if (infoPtr->nHeight > 0) +/* INT nScrollPos; */ +/* INT nMaxRange; */ + + switch (LVS_TYPEMASK & lStyle) { - if (lStyle & LVS_LIST) - { - if (infoPtr->nItemHeight > 0) - nItemCountPerColumn = infoPtr->nHeight / infoPtr->nItemHeight; - } - else if (lStyle & LVS_REPORT) - { - /* TO DO */ - } - else if (lStyle & LVS_SMALLICON) - { - /* TO DO */ - } - else if (lStyle & LVS_ICON) - { - /* TO DO */ - } + case LVS_REPORT: + /* TO DO */ + break; + + default: + /* TO DO */ } - - return nItemCountPerColumn; } -/*** - * DESCRIPTION: - * Retrieves the number of columns needed to display - * all the items in listview. - * - * PARAMETER(S): - * [I] HWND32 : window handle - * - * RETURN: - * Number of columns. - */ -static INT LISTVIEW_GetColumnCount(HWND hwnd) -{ - LISTVIEW_INFO *infoPtr = (LISTVIEW_INFO *)GetWindowLongA(hwnd, 0); - LONG lStyle = GetWindowLongA(hwnd, GWL_STYLE); - INT nColumnCount = 0; - INT nItemCountPerColumn; - - nItemCountPerColumn = LISTVIEW_GetItemCountPerColumn(hwnd); - - if ((infoPtr->nItemCount > 0) && (nItemCountPerColumn > 0)) - { - if (lStyle & LVS_LIST) - { - if ((infoPtr->nItemCount % nItemCountPerColumn) == 0) - { - nColumnCount = infoPtr->nItemCount / nItemCountPerColumn ; - } - else - { - nColumnCount = infoPtr->nItemCount / nItemCountPerColumn + 1; - } - } - else if (lStyle & LVS_REPORT) - { - /* TO DO */ - } - else if (lStyle & LVS_SMALLICON) - { - /* TO DO */ - } - else if (lStyle & LVS_ICON) - { - /* TO DO */ - } - } - - return nColumnCount; -} - -/*** - * DESCRIPTION: - * Sets the scrolling parameters. - * - * PARAMETER(S): - * [I] HWND32 : window handle - * - * RETURN: - * None - */ static VOID LISTVIEW_SetScroll(HWND hwnd) { LISTVIEW_INFO *infoPtr = (LISTVIEW_INFO *)GetWindowLongA(hwnd, 0); LONG lStyle = GetWindowLongA(hwnd, GWL_STYLE); - INT nColumnCount; - INT nItemCountPerRow; - INT nItemCountPerColumn; - INT nMinRange, nMaxRange; - INT nHScrollPos; -/* INT32 nVScrollPos; */ + INT nHiddenItemCount; + INT nScrollPos; + INT nMaxRange; + INT nCountPerPage; + RECT rc; + BOOL bHScroll = FALSE; + BOOL bVScroll = FALSE; + INT nHeaderWidth = 0; + INT nItemCount; + INT i; - nItemCountPerColumn = LISTVIEW_GetItemCountPerColumn(hwnd); - nItemCountPerRow = LISTVIEW_GetItemCountPerRow(hwnd); - - if ((nItemCountPerColumn > 0) && (nItemCountPerRow > 0)) + switch (LVS_TYPEMASK & lStyle) { - if (lStyle & LVS_LIST) + case LVS_LIST: + nCountPerPage = infoPtr->nCountPerRow * infoPtr->nCountPerColumn; + if (nCountPerPage < GETITEMCOUNT(infoPtr)) { - /* get number of columns needed to display all the listview items */ - nColumnCount = LISTVIEW_GetColumnCount(hwnd); - if (nColumnCount > 0) + /* add scrollbar if not already present */ + if (!(lStyle & WS_HSCROLL)) { - if (nColumnCount > nItemCountPerRow) - { - /* add scrollbar if not already present */ - if (!(lStyle & WS_HSCROLL)) - { - /* display scrollbar */ - ShowScrollBar(hwnd, SB_HORZ, TRUE); - - /* set scrollbar range and position */ - nMaxRange = nColumnCount - nItemCountPerRow; - SetScrollRange(hwnd, SB_HORZ, 0, nMaxRange, FALSE); - SetScrollPos(hwnd, SB_HORZ, 0, TRUE); - } - else - { - nHScrollPos = GetScrollPos(hwnd, SB_HORZ); - GetScrollRange(hwnd, SB_HORZ, &nMinRange, &nMaxRange); - if (nMaxRange != nColumnCount - nItemCountPerRow) - { - nMaxRange = nColumnCount - nItemCountPerRow; - SetScrollRange(hwnd, SB_HORZ, nMinRange, nMaxRange, FALSE); + ShowScrollBar(hwnd, SB_HORZ, TRUE); + } - if (nHScrollPos > nMaxRange) - nHScrollPos = nMaxRange; + /* calculate new scrollbar range */ + nHiddenItemCount = GETITEMCOUNT(infoPtr) - nCountPerPage; + if ((nHiddenItemCount % infoPtr->nCountPerColumn) == 0) + { + nMaxRange = nHiddenItemCount / infoPtr->nCountPerColumn; + } + else + { + nMaxRange = nHiddenItemCount / infoPtr->nCountPerColumn + 1; + } - SetScrollPos(hwnd, SB_HORZ, nHScrollPos, TRUE); - } - } - - /* refresh the client area */ - InvalidateRect(hwnd,NULL, TRUE); - UpdateWindow(hwnd); - } - else - { - /* remove scrollbar if present */ - if (lStyle & WS_HSCROLL) - { - /* hide scrollbar */ - ShowScrollBar(hwnd, SB_HORZ, FALSE); - - /* refresh the client area */ - InvalidateRect(hwnd,NULL, TRUE); - UpdateWindow(hwnd); - } - } + SetScrollRange(hwnd, SB_HORZ, 0, nMaxRange, FALSE); + nScrollPos = ListView_GetTopIndex(hwnd) / infoPtr->nCountPerColumn; + SetScrollPos(hwnd, SB_HORZ, nScrollPos, TRUE); + } + else + { + /* remove scrollbar if present */ + if (lStyle & WS_HSCROLL) + { + /* hide scrollbar */ + ShowScrollBar(hwnd, SB_HORZ, FALSE); } } - else if (lStyle & LVS_REPORT) + break; + + case LVS_REPORT: + nItemCount = Header_GetItemCount(infoPtr->hwndHeader); + for (i = 0; i < nItemCount; i++) { - HDLAYOUT hl; - WINDOWPOS wp; - RECT rc; - - rc.top = 0; - rc.left = 0; - rc.right = infoPtr->nWidth; - rc.bottom = infoPtr->nHeight; + if (Header_GetItemRect(infoPtr->hwndHeader, i, &rc) != 0) + { + nHeaderWidth += (rc.right - rc.left); + } + } - hl.prc = &rc; - hl.pwpos = ℘ - SendMessageA(infoPtr->hwndHeader, HDM_LAYOUT, 0, (LPARAM)&hl); - - SetWindowPos(infoPtr->hwndHeader, hwnd, - wp.x, wp.y, wp.cx, wp.cy, wp.flags); - -/* infoPtr->rcList.top += wp.cy; */ - } - else if (lStyle & LVS_SMALLICON) + if (nHeaderWidth > (infoPtr->rcList.right - infoPtr->rcList.left)) { - /* TO DO */ + bHScroll = TRUE; + + /* add horizontal scrollbar if not present */ + if (!(lStyle & WS_HSCROLL)) + { + /* display scrollbar */ + ShowScrollBar(hwnd, SB_HORZ, TRUE); + } } - else if (lStyle & LVS_ICON) + else { - /* TO DO */ + /* remove scrollbar if present */ + if (lStyle & WS_HSCROLL) + { + /* hide scrollbar */ + ShowScrollBar(hwnd, SB_HORZ, FALSE); + } + } + + if (infoPtr->nCountPerColumn < GETITEMCOUNT(infoPtr)) + { + bVScroll = TRUE; + + /* add scrollbar if not already present */ + if (!(lStyle & WS_VSCROLL)) + { + /* display scrollbar */ + ShowScrollBar(hwnd, SB_VERT, TRUE); + } + } + else + { + /* remove scrollbar if present */ + if (lStyle & WS_VSCROLL) + { + /* hide scrollbar */ + ShowScrollBar(hwnd, SB_VERT, FALSE); + } + } + break; + + default: + /* TO DO */ + } + + /* set range and position */ + GetClientRect(hwnd, &rc); + if ((bHScroll == TRUE) || (bVScroll == TRUE)) + { + LISTVIEW_SetSize(hwnd, lStyle, rc.right, rc.bottom); + LISTVIEW_SetViewInfo(hwnd); + if (bHScroll == TRUE) + { + LISTVIEW_SetHScroll(hwnd); + } + + if (bVScroll == TRUE) + { + LISTVIEW_SetVScroll(hwnd); } } } /*** * DESCRIPTION: - * Modifies the state (selected and focused) of the listview items. + * Draws a subitem. * * PARAMETER(S): - * [I] HWND32 : window handle - * [I] INT32 : focused item index - * [I] BOOL32 : flag for determining weither the control keys are used or not - * [I] BOOL32 : flag for determining the input type (mouse or keyboard) + * [I] HDC : device context handle + * [I] LISTVIEW_INFO * : listview information + * [I] LISTVIEW_SUBITEM * : subitem + * [I] RECT * : clipping rectangle * * RETURN: * None */ -static VOID LISTVIEW_SetItemStates(HWND hwnd, INT nFocusedItem, - BOOL bVirtualKeys, BOOL bMouseInput) +static VOID LISTVIEW_DrawSubItem(HWND hwnd, HDC hdc, INT nItem, LPARAM lParam, + LISTVIEW_SUBITEM *lpSubItem, INT nColumn, + RECT *lprc) { LISTVIEW_INFO *infoPtr = (LISTVIEW_INFO *)GetWindowLongA(hwnd, 0); - WORD wShift = HIWORD(GetKeyState(VK_SHIFT)); - WORD wCtrl = HIWORD(GetKeyState(VK_CONTROL)); - INT i; - LVITEMA lvItem; + CHAR szDispText[DISP_TEXT_SIZE]; + LPSTR pszDispText = NULL; - /* initialize memory */ - ZeroMemory(&lvItem, sizeof(LVITEMA)); - - if (wShift && (bVirtualKeys == TRUE)) + /* set item colors */ + SetBkColor(hdc, infoPtr->clrTextBk); + SetTextColor(hdc, infoPtr->clrText); + + pszDispText = szDispText; + LISTVIEW_GetSubItemDispInfo(hwnd, nItem, lParam, lpSubItem, nColumn, NULL, + &pszDispText, DISP_TEXT_SIZE); + + /* draw text : using arbitrary offset of 10 pixels */ + ExtTextOutA(hdc, lprc->left + 10, lprc->top, ETO_OPAQUE|ETO_CLIPPED, + lprc, pszDispText, lstrlenA(pszDispText), NULL); +} + +/*** + * DESCRIPTION: + * Draws an item. + * + * PARAMETER(S): + * [I] HDC : device context handle + * [I] LISTVIEW_INFO * : listview information + * [I] LISTVIEW_ITEM * : item + * [I] RECT * : clipping rectangle + * + * RETURN: + * None + */ +static VOID LISTVIEW_DrawItem(HWND hwnd, HDC hdc, LISTVIEW_ITEM *lpItem, + INT nItem, RECT *lprc) +{ + LISTVIEW_INFO *infoPtr = (LISTVIEW_INFO *)GetWindowLongA(hwnd, 0); + BOOL bSelected; + INT nLabelWidth; + INT nImage; + CHAR szDispText[DISP_TEXT_SIZE]; + LPSTR pszDispText = NULL; + UINT uState; + + pszDispText = szDispText; + LISTVIEW_GetItemDispInfo(hwnd, nItem, lpItem, &nImage, &uState, &pszDispText, + DISP_TEXT_SIZE); + if (uState & LVIS_SELECTED) { - /* reset the selected and focused states of all the items */ - lvItem.stateMask = LVIS_SELECTED | LVIS_FOCUSED; - lvItem.state = 0; - SendMessageA(hwnd, LVM_SETITEMSTATE, (WPARAM)-1, (LPARAM)&lvItem); + bSelected = TRUE; - if (infoPtr->nSelectionMark > nFocusedItem) - { - for (i = infoPtr->nSelectionMark; i > nFocusedItem; i--) - { - /* select items */ - lvItem.stateMask = LVIS_SELECTED; - lvItem.state = LVIS_SELECTED; - SendMessageA(hwnd, LVM_SETITEMSTATE, (WPARAM)i, (LPARAM)&lvItem); - } - } - else - { - for (i = infoPtr->nSelectionMark; i < nFocusedItem; i++) - { - /* select items */ - lvItem.stateMask = LVIS_SELECTED; - lvItem.state = LVIS_SELECTED; - SendMessageA(hwnd, LVM_SETITEMSTATE, (WPARAM)i, (LPARAM)&lvItem); - } - } - - /* select anf focus item */ - lvItem.stateMask = LVIS_SELECTED | LVIS_FOCUSED; - lvItem.state = LVIS_SELECTED | LVIS_FOCUSED; - SendMessageA(hwnd, LVM_SETITEMSTATE, (WPARAM)i, (LPARAM)&lvItem); + /* set item colors */ + SetBkColor(hdc, GetSysColor(COLOR_HIGHLIGHT)); + SetTextColor(hdc, GetSysColor(COLOR_HIGHLIGHTTEXT)); + + /* set raster mode */ + SetROP2(hdc, R2_XORPEN); } else { - if (wCtrl && (bVirtualKeys == TRUE)) - { - /* make sure the focus is lost */ - lvItem.stateMask = LVIS_FOCUSED; - lvItem.state = 0; - SendMessageA(hwnd, LVM_SETITEMSTATE, (WPARAM)-1, (LPARAM)&lvItem); + bSelected = FALSE; - if (bMouseInput == TRUE) - { - if (SendMessageA(hwnd, LVM_GETITEMSTATE, (WPARAM)nFocusedItem, - (LPARAM)LVIS_SELECTED) & LVIS_SELECTED) - { - /* focus and unselect (toggle selection) */ - lvItem.stateMask = LVIS_SELECTED | LVIS_FOCUSED; - lvItem.state = LVIS_FOCUSED; - SendMessageA(hwnd, LVM_SETITEMSTATE, (WPARAM)nFocusedItem, - (LPARAM)&lvItem); - } - else - { - /* select and focus */ - lvItem.stateMask = LVIS_SELECTED | LVIS_FOCUSED; - lvItem.state = LVIS_SELECTED | LVIS_FOCUSED; - SendMessageA(hwnd, LVM_SETITEMSTATE, (WPARAM)nFocusedItem, - (LPARAM)&lvItem); - } - - /* set the group selection start position */ - infoPtr->nSelectionMark = nFocusedItem; - } - else - { - /* focus */ - lvItem.stateMask = LVIS_FOCUSED; - lvItem.state = LVIS_FOCUSED; - SendMessageA(hwnd, LVM_SETITEMSTATE, (WPARAM)nFocusedItem, - (LPARAM)&lvItem); - } + /* set item colors */ + SetBkColor(hdc, infoPtr->clrTextBk); + SetTextColor(hdc, infoPtr->clrText); + + /* set raster mode */ + SetROP2(hdc, R2_COPYPEN); + } + + /* state icons */ + if (infoPtr->himlState != NULL) + { + /* right shift 12 bits to obtain index in image list */ + if (bSelected == TRUE) + { + ImageList_Draw(infoPtr->himlState, uState >> 12, hdc, lprc->left, + lprc->top, ILD_SELECTED); } else { - /* clear selection and focus for all the items */ - lvItem.stateMask = LVIS_SELECTED | LVIS_FOCUSED; - lvItem.state = 0; - SendMessageA(hwnd, LVM_SETITEMSTATE, (WPARAM)-1, (LPARAM)&lvItem); - - /* set select and focus for this particular item */ - lvItem.stateMask = LVIS_FOCUSED | LVIS_SELECTED; - lvItem.state = LVIS_FOCUSED | LVIS_SELECTED; - SendMessageA(hwnd, LVM_SETITEMSTATE, (WPARAM)nFocusedItem, - (LPARAM)&lvItem); - - /* set the new group selection start position */ - infoPtr->nSelectionMark = nFocusedItem; + ImageList_Draw(infoPtr->himlState, uState >> 12, hdc, lprc->left, + lprc->top, ILD_NORMAL); } + + lprc->left += infoPtr->iconSize.cx; } -} - -/*** - * DESCRIPTION: - * Draws listview items when in list display maode. - * - * PARAMETER(S): - * [I] HWND32 : window handle - * [I] HDC32 : device context handle - * - * RETURN: - * None - */ -static VOID LISTVIEW_RefreshList(HWND hwnd, HDC hdc) -{ - LISTVIEW_INFO *infoPtr = (LISTVIEW_INFO *)GetWindowLongA(hwnd, 0); - LISTVIEW_ITEM *lpItem; - HFONT hOldFont; - HPEN hPen, hOldPen; - INT nItemCountPerColumn; - INT nItemCountPerRow; - INT nSmallIconWidth; - SIZE labelSize; - INT nDrawPosX = 0; - INT nDrawPosY = 0; - BOOL bSelected; - RECT rcBoundingBox; - COLORREF clrHighlight; - COLORREF clrHighlightText; - INT i; - INT nColumn = 0; - INT nRow; - INT j; - - /* get number of items per column */ - nItemCountPerColumn = LISTVIEW_GetItemCountPerColumn(hwnd); - - /* get number of items per row */ - nItemCountPerRow = LISTVIEW_GetItemCountPerColumn(hwnd); - if ((nItemCountPerColumn > 0) && (nItemCountPerRow > 0)) + /* small icons */ + if (infoPtr->himlSmall != NULL) { - /* select font */ - hOldFont = SelectObject(hdc, infoPtr->hFont); - - /* inititialize system dependent information */ - clrHighlight = GetSysColor(COLOR_HIGHLIGHT); - clrHighlightText = GetSysColor(COLOR_HIGHLIGHTTEXT); - nSmallIconWidth = GetSystemMetrics(SM_CXSMICON); - - /* select transparent brush (for drawing the focus box) */ - SelectObject(hdc, GetStockObject(NULL_BRUSH)); - - /* select the doted pen (for drawing the focus box) */ - hPen = CreatePen(PS_DOT, 1, 0); - hOldPen = SelectObject(hdc, hPen); - - /* get starting index */ - i = LISTVIEW_GetFirstVisibleItem(hwnd); - - /* DRAW ITEMS */ - for (j = 0; i < infoPtr->nItemCount; i++, j++) + if (bSelected == TRUE) { - /* set draw position for current item */ - nRow = j % nItemCountPerColumn; - nColumn = j / nItemCountPerColumn; - if (nRow == 0) - nDrawPosY = 0; - else - nDrawPosY += infoPtr->nItemHeight; - - nDrawPosX = nColumn * infoPtr->nColumnWidth; - - /* get item */ - lpItem = (LISTVIEW_ITEM *)DPA_GetPtr(infoPtr->hdpaItems, i); - if (lpItem != NULL) - { - if (lpItem->state & LVIS_SELECTED) - { - bSelected = TRUE; - - /* set item colors */ - SetBkColor(hdc, clrHighlight); - SetTextColor(hdc, clrHighlightText); - - /* set raster mode */ - SetROP2(hdc, R2_XORPEN); - } - else - { - bSelected = FALSE; - - /* set item colors */ - SetBkColor(hdc, infoPtr->clrTextBk); - SetTextColor(hdc, infoPtr->clrText); - - /* set raster mode */ - SetROP2(hdc, R2_COPYPEN); - } - - /* state images */ - if (infoPtr->himlState != NULL) - { - /* right shift 12 bits to obtain index in image list */ - if (bSelected == TRUE) - ImageList_Draw(infoPtr->himlState, lpItem->state >> 12, hdc, - nDrawPosX, nDrawPosY, ILD_SELECTED); - else - ImageList_Draw(infoPtr->himlState, lpItem->state >> 12, hdc, - nDrawPosX, nDrawPosY, ILD_NORMAL); - - nDrawPosX += nSmallIconWidth; - } - - /* small icons */ - if (infoPtr->himlSmall != NULL) - { - if (bSelected == TRUE) - ImageList_Draw(infoPtr->himlSmall, lpItem->iImage, hdc, nDrawPosX, - nDrawPosY, ILD_SELECTED); - else - ImageList_Draw(infoPtr->himlSmall, lpItem->iImage, hdc, nDrawPosX, - nDrawPosY, ILD_NORMAL); - - nDrawPosX += nSmallIconWidth; - } - - /* get string size (in pixels) */ - GetTextExtentPoint32A(hdc, lpItem->pszText, - lstrlenA(lpItem->pszText), &labelSize); - - /* define a bounding box */ - rcBoundingBox.left = nDrawPosX; - rcBoundingBox.top = nDrawPosY; - - /* 2 pixels for padding purposes */ - rcBoundingBox.right = nDrawPosX + labelSize.cx + 2; - - /* padding already included in infoPtr->nItemHeight */ - rcBoundingBox.bottom = nDrawPosY + infoPtr->nItemHeight; - - /* draw text */ - ExtTextOutA(hdc, nDrawPosX + 1, nDrawPosY+ 1, - ETO_OPAQUE|ETO_CLIPPED, &rcBoundingBox, - lpItem->pszText, lstrlenA(lpItem->pszText), NULL); - - if (lpItem->state & LVIS_FOCUSED) - Rectangle(hdc, rcBoundingBox.left, rcBoundingBox.top, - rcBoundingBox.right, rcBoundingBox.bottom); - } + ImageList_Draw(infoPtr->himlSmall, nImage, hdc, lprc->left, + lprc->top, ILD_SELECTED); } + else + { + ImageList_Draw(infoPtr->himlSmall, nImage, hdc, lprc->left, + lprc->top, ILD_NORMAL); + } + + lprc->left += infoPtr->iconSize.cx; + } - /* unselect objects */ - SelectObject(hdc, hOldFont); - SelectObject(hdc, hOldPen); + nLabelWidth = ListView_GetStringWidthA(hwnd, pszDispText); + if (lprc->left + nLabelWidth < lprc->right) + { + lprc->right = lprc->left + nLabelWidth; + } - /* delete pen */ - DeleteObject(hPen); + /* draw text */ + ExtTextOutA(hdc, lprc->left + 1, lprc->top + 1, ETO_OPAQUE|ETO_CLIPPED, + lprc, pszDispText, lstrlenA(pszDispText), NULL); + + if (lpItem->state & LVIS_FOCUSED) + { + Rectangle(hdc, lprc->left, lprc->top, lprc->right, lprc->bottom); } } @@ -728,15 +1664,152 @@ static VOID LISTVIEW_RefreshList(HWND hwnd, HDC hdc) * Draws listview items when in report display mode. * * PARAMETER(S): - * [I] HWND32 : window handle - * [I] HDC32 : device context handle + * [I] HWND : window handle + * [I] HDC : device context handle * * RETURN: * None */ static VOID LISTVIEW_RefreshReport(HWND hwnd, HDC hdc) { - /* TO DO */ + LISTVIEW_INFO *infoPtr = (LISTVIEW_INFO *)GetWindowLongA(hwnd,0); + INT nDrawPosY = infoPtr->rcList.top; + LISTVIEW_ITEM *lpItem; + LISTVIEW_SUBITEM *lpSubItem = NULL; + INT nColumnCount; + HDPA hdpaSubItems; + RECT rc; + INT j, k; + INT nItem; + INT nLast; + BOOL bNeedSubItem = TRUE; + + nItem = ListView_GetTopIndex(hwnd); + nLast = nItem + infoPtr->nCountPerColumn; + while (nItem <= nLast) + { + hdpaSubItems = (HDPA)DPA_GetPtr(infoPtr->hdpaItems, nItem); + if (hdpaSubItems != NULL) + { + lpItem = (LISTVIEW_ITEM *)DPA_GetPtr(hdpaSubItems, 0); + if (lpItem != NULL) + { + Header_GetItemRect(infoPtr->hwndHeader, 0, &rc); + rc.top = nDrawPosY; + rc.bottom = rc.top + infoPtr->nItemHeight; + + /* draw state icon + icon + text */ + LISTVIEW_DrawItem(hwnd, hdc, lpItem, nItem, &rc); + } + + nColumnCount = Header_GetItemCount(infoPtr->hwndHeader); + for (k = 1, j = 1; j < nColumnCount; j++) + { + Header_GetItemRect(infoPtr->hwndHeader, j, &rc); + rc.top = nDrawPosY; + rc.bottom = rc.top + infoPtr->nItemHeight; + + if (k < hdpaSubItems->nItemCount) + { + if (bNeedSubItem == TRUE) + { + lpSubItem = (LISTVIEW_SUBITEM *)DPA_GetPtr(hdpaSubItems, k); + k++; + } + + if (lpSubItem != NULL) + { + if (lpSubItem->iSubItem == j) + { + LISTVIEW_DrawSubItem(hwnd, hdc, nItem, lpItem->lParam, lpSubItem, + j, &rc); + bNeedSubItem = TRUE; + } + else + { + LISTVIEW_DrawSubItem(hwnd, hdc, nItem, lpItem->lParam, NULL, j, + &rc); + bNeedSubItem = FALSE; + } + } + else + { + LISTVIEW_DrawSubItem(hwnd, hdc, nItem, lpItem->lParam, NULL, j, + &rc); + bNeedSubItem = TRUE; + } + } + else + { + LISTVIEW_DrawSubItem(hwnd, hdc, nItem, lpItem->lParam, NULL, j, &rc); + } + } + } + + nDrawPosY += infoPtr->nItemHeight; + nItem++; + } +} + +/*** + * DESCRIPTION: + * Draws listview items when in list display mode. + * + * PARAMETER(S): + * [I] HWND : window handle + * [I] HDC : device context handle + * + * RETURN: + * None + */ +static VOID LISTVIEW_RefreshList(HWND hwnd, HDC hdc) +{ + LISTVIEW_INFO *infoPtr = (LISTVIEW_INFO *)GetWindowLongA(hwnd, 0); + LISTVIEW_ITEM *lpItem; + HDPA hdpaSubItems; + RECT rc; + INT i, j; + INT nColumnCount; + INT nItem = ListView_GetTopIndex(hwnd); + + if (infoPtr->rcList.right > 0) + { + /* get number of display columns */ + if (infoPtr->rcList.right % infoPtr->nColumnWidth == 0) + { + nColumnCount = infoPtr->rcList.right / infoPtr->nColumnWidth; + } + else + { + nColumnCount = infoPtr->rcList.right / infoPtr->nColumnWidth + 1; + } + + for (i = 0; i < nColumnCount; i++) + { + j = 0; + while ((nItem < GETITEMCOUNT(infoPtr)) && (j < infoPtr->nCountPerColumn)) + { + hdpaSubItems = (HDPA)DPA_GetPtr(infoPtr->hdpaItems, nItem); + if (hdpaSubItems != NULL) + { + lpItem = (LISTVIEW_ITEM *)DPA_GetPtr(hdpaSubItems, 0); + if (lpItem != NULL) + { + rc.top = j * infoPtr->nItemHeight; + rc.left = i * infoPtr->nColumnWidth; + rc.bottom = rc.top + infoPtr->nItemHeight; + rc.right = rc.left + infoPtr->nColumnWidth; + + /* draw state icon + icon + text */ + LISTVIEW_DrawItem(hwnd, hdc, lpItem, nItem, &rc); + } + } + + nItem++; + j++; + } + } + } } /*** @@ -744,15 +1817,46 @@ static VOID LISTVIEW_RefreshReport(HWND hwnd, HDC hdc) * Draws listview items when in small icon display mode. * * PARAMETER(S): - * [I] HWND32 : window handle - * [I] HDC32 : device context handle + * [I] HWND : window handle + * [I] HDC : device context handle * * RETURN: * None */ static VOID LISTVIEW_RefreshSmallIcon(HWND hwnd, HDC hdc) { - /* TO DO */ + LISTVIEW_INFO *infoPtr = (LISTVIEW_INFO *)GetWindowLongA(hwnd, 0); + LISTVIEW_ITEM *lpItem; + HDPA hdpaSubItems; + RECT rc; + INT i, j; + INT nItem = ListView_GetTopIndex(hwnd); + + for (i = 0; i < infoPtr->nCountPerColumn; i++) + { + j = 0; + while ((nItem < GETITEMCOUNT(infoPtr)) && (j < infoPtr->nCountPerRow)) + { + hdpaSubItems = (HDPA)DPA_GetPtr(infoPtr->hdpaItems, nItem); + if (hdpaSubItems != NULL) + { + lpItem = (LISTVIEW_ITEM *)DPA_GetPtr(hdpaSubItems, 0); + if (lpItem != NULL) + { + rc.top = i * infoPtr->nItemHeight; + rc.left = j * infoPtr->nColumnWidth; + rc.bottom = rc.top + infoPtr->nItemHeight; + rc.right = rc.left + infoPtr->nColumnWidth; + + /* draw state icon + icon + text */ + LISTVIEW_DrawItem(hwnd, hdc, lpItem, nItem, &rc); + } + } + + nItem++; + j++; + } + } } /*** @@ -760,8 +1864,8 @@ static VOID LISTVIEW_RefreshSmallIcon(HWND hwnd, HDC hdc) * Draws listview items when in icon display mode. * * PARAMETER(S): - * [I] HWND32 : window handle - * [I] HDC32 : device context handle + * [I] HWND : window handle + * [I] HDC : device context handle * * RETURN: * None @@ -776,32 +1880,50 @@ static VOID LISTVIEW_RefreshIcon(HWND hwnd, HDC hdc) * Draws listview items. * * PARAMETER(S): - * [I] HWND32 : window handle - * [I] HDC32 : device context handle + * [I] HWND : window handle + * [I] HDC : device context handle * * RETURN: - * None + * NoneX */ static VOID LISTVIEW_Refresh(HWND hwnd, HDC hdc) { + LISTVIEW_INFO *infoPtr = (LISTVIEW_INFO *)GetWindowLongA(hwnd, 0); LONG lStyle = GetWindowLongA(hwnd, GWL_STYLE); - - if (lStyle & LVS_LIST) - { - LISTVIEW_RefreshList(hwnd, hdc); - } - else if (lStyle & LVS_REPORT) + HFONT hOldFont; + HPEN hPen, hOldPen; + + /* select font */ + hOldFont = SelectObject(hdc, infoPtr->hFont); + + /* select the doted pen (for drawing the focus box) */ + hPen = CreatePen(PS_DOT, 1, 0); + hOldPen = SelectObject(hdc, hPen); + + /* select transparent brush (for drawing the focus box) */ + SelectObject(hdc, GetStockObject(NULL_BRUSH)); + + switch (LVS_TYPEMASK & lStyle) { + case LVS_LIST: + LISTVIEW_RefreshList(hwnd, hdc); + break; + case LVS_REPORT: LISTVIEW_RefreshReport(hwnd, hdc); - } - else if (lStyle & LVS_SMALLICON) - { + break; + case LVS_SMALLICON: LISTVIEW_RefreshSmallIcon(hwnd, hdc); - } - else if (lStyle & LVS_ICON) - { + break; + case LVS_ICON: LISTVIEW_RefreshIcon(hwnd, hdc); } + + /* unselect objects */ + SelectObject(hdc, hOldFont); + SelectObject(hdc, hOldPen); + + /* delete pen */ + DeleteObject(hPen); } @@ -810,10 +1932,10 @@ static VOID LISTVIEW_Refresh(HWND hwnd, HDC hdc) * Calculates the approximate width and height of a given number of items. * * PARAMETER(S): - * [I] HWND32 : window handle - * [I] INT32 : number of items - * [I] INT32 : width - * [I] INT32 : height + * [I] HWND : window handle + * [I] INT : number of items + * [I] INT : width + * [I] INT : height * * RETURN: * Returns a DWORD. The width in the low word and the height in high word. @@ -828,14 +1950,14 @@ static LRESULT LISTVIEW_ApproximateViewRect(HWND hwnd, INT nItemCount, DWORD dwViewRect = 0; if (nItemCount == -1) - nItemCount = infoPtr->nItemCount; + nItemCount = GETITEMCOUNT(infoPtr); if (lStyle & LVS_LIST) { if (wHeight == 0xFFFF) { /* use current height */ - wHeight = infoPtr->nHeight; + wHeight = infoPtr->rcList.bottom; } if (wHeight < infoPtr->nItemHeight) @@ -858,6 +1980,7 @@ static LRESULT LISTVIEW_ApproximateViewRect(HWND hwnd, INT nItemCount, } } + /* Microsoft padding magic */ wHeight = nItemCountPerColumn * infoPtr->nItemHeight + 2; wWidth = nColumnCount * infoPtr->nColumnWidth + 2; @@ -884,8 +2007,8 @@ static LRESULT LISTVIEW_ApproximateViewRect(HWND hwnd, INT nItemCount, * Arranges listview items in icon display mode. * * PARAMETER(S): - * [I] HWND32 : window handle - * [I] INT32 : alignment code + * [I] HWND : window handle + * [I] INT : alignment code * * RETURN: * SUCCESS : TRUE @@ -893,11 +2016,11 @@ static LRESULT LISTVIEW_ApproximateViewRect(HWND hwnd, INT nItemCount, */ static LRESULT LISTVIEW_Arrange(HWND hwnd, INT nAlignCode) { - /* LISTVIEW_INFO *infoPtr = (LISTVIEW_INFO *)GetWindowLong32A(hwnd, 0); */ LONG lStyle = GetWindowLongA(hwnd, GWL_STYLE); BOOL bResult = FALSE; - if (lStyle & LVS_ICON) + if (((LVS_TYPEMASK & lStyle) == LVS_ICON) || + ((LVS_TYPEMASK & lStyle) == LVS_SMALLICON)) { switch (nAlignCode) { @@ -922,10 +2045,10 @@ static LRESULT LISTVIEW_Arrange(HWND hwnd, INT nAlignCode) /*** * DESCRIPTION: - * Removes all listview items. + * Removes all listview items and subitems. * * PARAMETER(S): - * [I] HWND32 : window handle + * [I] HWND : window handle * * RETURN: * SUCCESS : TRUE @@ -936,58 +2059,88 @@ static LRESULT LISTVIEW_DeleteAllItems(HWND hwnd) LISTVIEW_INFO *infoPtr = (LISTVIEW_INFO *)GetWindowLongA(hwnd, 0); LONG lCtrlId = GetWindowLongA(hwnd, GWL_ID); LISTVIEW_ITEM *lpItem; + LISTVIEW_SUBITEM *lpSubItem; NMLISTVIEW nmlv; - BOOL bNotify; + BOOL bSuppress; + BOOL bResult = FALSE; INT i; - BOOL bResult = TRUE; + INT j; + HDPA hdpaSubItems; - if (infoPtr->nItemCount > 0) + if (GETITEMCOUNT(infoPtr) > 0) { + /* initialize memory */ + ZeroMemory(&nmlv, sizeof(NMLISTVIEW)); + /* send LVN_DELETEALLITEMS notification */ - ZeroMemory (&nmlv, sizeof (NMLISTVIEW)); nmlv.hdr.hwndFrom = hwnd; nmlv.hdr.idFrom = lCtrlId; - nmlv.hdr.code = LVN_DELETEALLITEMS; - nmlv.iItem = -1; - bNotify = !(BOOL)SendMessageA(GetParent(hwnd), WM_NOTIFY, - (WPARAM)lCtrlId, (LPARAM)&nmlv); + nmlv.hdr.code = LVN_DELETEALLITEMS; + nmlv.iItem = -1; - nmlv.hdr.code = LVN_DELETEITEM; + /* verify if subsequent LVN_DELETEITEM notifications should be + suppressed */ + bSuppress = ListView_LVNotify(GetParent(hwnd), lCtrlId, &nmlv); - for (i = 0; i < infoPtr->nItemCount; i++) + for (i = 0; i < GETITEMCOUNT(infoPtr); i++) { - if (bNotify == TRUE) + hdpaSubItems = (HDPA)DPA_GetPtr(infoPtr->hdpaItems, i); + if (hdpaSubItems != NULL) { - /* send LVN_DELETEITEM notification */ - nmlv.iItem = i; - SendMessageA(GetParent(hwnd), WM_NOTIFY, (WPARAM)lCtrlId, - (LPARAM)&nmlv); - } + for (j = 1; j < hdpaSubItems->nItemCount; j++) + { + lpSubItem = (LISTVIEW_SUBITEM *)DPA_GetPtr(hdpaSubItems, j); + if (lpSubItem != NULL) + { + /* free subitem string */ + if ((lpSubItem->pszText != NULL) && + (lpSubItem->pszText != LPSTR_TEXTCALLBACKA)) + { + COMCTL32_Free(lpSubItem->pszText); + } + + /* free subitem */ + COMCTL32_Free(lpSubItem); + } + } + + lpItem = (LISTVIEW_ITEM *)DPA_GetPtr(hdpaSubItems, 0); + if (lpItem != NULL) + { + if (bSuppress == FALSE) + { + /* send LVN_DELETEITEM notification */ + nmlv.hdr.code = LVN_DELETEITEM; + nmlv.iItem = i; + nmlv.lParam = lpItem->lParam; + ListView_LVNotify(GetParent(hwnd), lCtrlId, &nmlv); + } - /* get item */ - lpItem = (LISTVIEW_ITEM *)DPA_GetPtr(infoPtr->hdpaItems, i); - if (lpItem != NULL) - { - /* free item string */ - if ((lpItem->pszText != NULL) && - (lpItem->pszText != LPSTR_TEXTCALLBACKA)) - COMCTL32_Free (lpItem->pszText); - - /* free item */ - COMCTL32_Free (lpItem); - } + /* free item string */ + if ((lpItem->pszText != NULL) && + (lpItem->pszText != LPSTR_TEXTCALLBACKA)) + { + COMCTL32_Free(lpItem->pszText); + } + + /* free item */ + COMCTL32_Free(lpItem); + } + + DPA_Destroy(hdpaSubItems); + } } - /* ???? needs follow up */ - DPA_DeleteAllPtrs (infoPtr->hdpaItems); - - /* reset item counter */ - infoPtr->nItemCount = 0; - - /* reset scrollbar */ + /* reinitialize listview memory */ + bResult = DPA_DeleteAllPtrs(infoPtr->hdpaItems); + + /* reset scroll parameters */ LISTVIEW_SetScroll(hwnd); -} + /* invalidate client area (optimization needed) */ + InvalidateRect(hwnd, NULL, FALSE); + } + return bResult; } @@ -996,8 +2149,8 @@ static LRESULT LISTVIEW_DeleteAllItems(HWND hwnd) * Removes a column from the listview control. * * PARAMETER(S): - * [I] HWND32 : window handle - * [I] INT32 : column index + * [I] HWND : window handle + * [I] INT : column index * * RETURN: * SUCCESS : TRUE @@ -1005,17 +2158,21 @@ static LRESULT LISTVIEW_DeleteAllItems(HWND hwnd) */ static LRESULT LISTVIEW_DeleteColumn(HWND hwnd, INT nColumn) { -/* LISTVIEW_INFO *infoPtr = (LISTVIEW_INFO *)GetWindowLong32A(hwnd, 0); */ + LISTVIEW_INFO *infoPtr = (LISTVIEW_INFO *)GetWindowLongA(hwnd, 0); + BOOL bResult = FALSE; + + if (Header_DeleteItem(infoPtr->hwndHeader, nColumn) == TRUE) + { + bResult = LISTVIEW_RemoveColumn(infoPtr->hdpaItems, nColumn); + } - /* FIXME ??? */ -/* if (infoPtr->nItemCount > 0) */ -/* return FALSE; */ -/* if (!SendMessage32A(infoPtr->hwndHeader, HDM_DELETEITEM, wParam, 0)) */ -/* return FALSE; */ -/* infoPtr->nColumnCount--; */ -/* FIXME (listview, "semi stub!\n"); */ + /* reset scroll parameters */ + LISTVIEW_SetScroll(hwnd); - return TRUE; + /* refresh client area */ + InvalidateRect(hwnd, NULL, FALSE); + + return bResult; } /*** @@ -1023,8 +2180,8 @@ static LRESULT LISTVIEW_DeleteColumn(HWND hwnd, INT nColumn) * Removes an item from the listview control. * * PARAMETER(S): - * [I] HWND32 : window handle - * [I] INT32 : item index + * [I] HWND : window handle + * [I] INT : item index * * RETURN: * SUCCESS : TRUE @@ -1034,56 +2191,174 @@ static LRESULT LISTVIEW_DeleteItem(HWND hwnd, INT nItem) { LISTVIEW_INFO *infoPtr = (LISTVIEW_INFO *)GetWindowLongA(hwnd, 0); LONG lCtrlId = GetWindowLongA(hwnd, GWL_ID); - LISTVIEW_ITEM *lpItem; - NMLISTVIEW nmlv; + NMLISTVIEW nmlv; BOOL bResult = FALSE; + HDPA hdpaSubItems; + LISTVIEW_ITEM *lpItem; + LISTVIEW_SUBITEM *lpSubItem; + INT i; - if ((nItem >= 0) && (nItem < infoPtr->nItemCount)) + if ((nItem >= 0) && (nItem < GETITEMCOUNT(infoPtr))) { - /* send LVN_DELETEITEM notification */ - ZeroMemory (&nmlv, sizeof (NMLISTVIEW)); - nmlv.hdr.hwndFrom = hwnd; - nmlv.hdr.idFrom = lCtrlId; - nmlv.hdr.code = LVN_DELETEITEM; - nmlv.iItem = nItem; - SendMessageA(GetParent(hwnd), WM_NOTIFY, (WPARAM)lCtrlId, - (LPARAM)&nmlv); + /* initialize memory */ + ZeroMemory(&nmlv, sizeof(NMLISTVIEW)); - /* remove item */ - lpItem = (LISTVIEW_ITEM*)DPA_DeletePtr (infoPtr->hdpaItems, nItem); - if (lpItem != NULL) + hdpaSubItems = (HDPA)DPA_DeletePtr(infoPtr->hdpaItems, nItem); + if (hdpaSubItems != NULL) { - /* free item string */ - if ((lpItem->pszText != NULL) && - (lpItem->pszText != LPSTR_TEXTCALLBACKA)) - COMCTL32_Free (lpItem->pszText); + for (i = 1; i < hdpaSubItems->nItemCount; i++) + { + lpSubItem = (LISTVIEW_SUBITEM *)DPA_GetPtr(hdpaSubItems, i); + if (lpSubItem != NULL) + { + /* free item string */ + if ((lpSubItem->pszText != NULL) && + (lpSubItem->pszText != LPSTR_TEXTCALLBACKA)) + { + COMCTL32_Free(lpSubItem->pszText); + } + + /* free item */ + COMCTL32_Free(lpSubItem); + } + } + + lpItem = (LISTVIEW_ITEM *)DPA_GetPtr(hdpaSubItems, 0); + if (lpItem != NULL) + { + /* send LVN_DELETEITEM notification */ + nmlv.hdr.hwndFrom = hwnd; + nmlv.hdr.idFrom = lCtrlId; + nmlv.hdr.code = LVN_DELETEITEM; + nmlv.iItem = nItem; + nmlv.lParam = lpItem->lParam; + SendMessageA(GetParent(hwnd), WM_NOTIFY, (WPARAM)lCtrlId, + (LPARAM)&nmlv); - /* free item */ - COMCTL32_Free (lpItem); + /* free item string */ + if ((lpItem->pszText != NULL) && + (lpItem->pszText != LPSTR_TEXTCALLBACKA)) + { + COMCTL32_Free(lpItem->pszText); + } + + /* free item */ + COMCTL32_Free(lpItem); + } + + bResult = DPA_Destroy(hdpaSubItems); } - /* decrement item counter */ - infoPtr->nItemCount--; - - /* reset some of the draw data */ - LISTVIEW_SetScroll(hwnd); - - bResult = TRUE; -} - + /* refresh client area */ + InvalidateRect(hwnd, NULL, FALSE); + } + return bResult; } /* << LISTVIEW_EditLabel >> */ -/* << LISTVIEW_EnsureVisible >> */ +/*** + * DESCRIPTION: + * Ensures the specified item is visible, scrolling into view if necessary. + * + * PARAMETER(S): + * [I] HWND : window handle + * [I] INT : item index + * [I] BOOL : partially or entirely visible + * + * RETURN: + * SUCCESS : TRUE + * FAILURE : FALSE + */ +static BOOL LISTVIEW_EnsureVisible(HWND hwnd, INT nItem, BOOL bPartial) +{ + LISTVIEW_INFO *infoPtr = (LISTVIEW_INFO *)GetWindowLongA(hwnd, 0); + LONG lStyle = GetWindowLongA(hwnd, GWL_STYLE); + INT nLast; + INT nFirst; + INT nScrollPos; + BOOL bResult = TRUE; + + switch (LVS_TYPEMASK & lStyle) + { + case LVS_LIST: + if (lStyle & WS_HSCROLL) + { + nFirst = ListView_GetTopIndex(hwnd); + + /* calculate last fully visible item index */ + nLast = infoPtr->nCountPerColumn * infoPtr->nCountPerRow + nFirst - 1; + + if (nItem > nLast) + { + /* calculate new scroll position based on item index */ + if (((nItem - nLast) % infoPtr->nCountPerColumn) == 0) + { + nScrollPos = (nItem - nLast) / infoPtr->nCountPerColumn; + } + else + { + nScrollPos = (nItem - nLast) / infoPtr->nCountPerColumn + 1; + } + + bResult = ListView_Scroll(hwnd, nScrollPos, 0); + } + else if (nItem < nFirst) + { + /* calculate new scroll position based on item index */ + if (((nItem - nFirst) % infoPtr->nCountPerColumn) == 0) + { + nScrollPos = (nItem - nFirst) / infoPtr->nCountPerColumn; + } + else + { + nScrollPos = (nItem - nFirst) / infoPtr->nCountPerColumn -1; + } + + bResult = ListView_Scroll(hwnd, nScrollPos, 0); + } + } + break; + + case LVS_REPORT: + if (lStyle & WS_VSCROLL) + { + nFirst = ListView_GetTopIndex(hwnd); + + /* calculate last fully visible item index */ + nLast = infoPtr->nCountPerColumn + nFirst - 1; + if (nItem > nLast) + { + nScrollPos = nItem - nLast; + bResult = ListView_Scroll(hwnd, 0, nScrollPos); + } + else if (nItem < nFirst) + { + nScrollPos = nItem - nFirst; + bResult = ListView_Scroll(hwnd, 0, nScrollPos); + } + } + break; + + case LVS_SMALLICON: + /* TO DO */ + break; + + case LVS_ICON: + /* TO DO */ + break; + } + + return bResult; +} /*** * DESCRIPTION: * Searches for an item with specific characteristics. * * PARAMETER(S): - * [I] HWND32 : window handle - * [I] INT32 : base item index + * [I] HWND : window handle + * [I] INT : base item index * [I] LPLVFINDINFO : item information to look for * * RETURN: @@ -1093,11 +2368,11 @@ static LRESULT LISTVIEW_DeleteItem(HWND hwnd, INT nItem) static LRESULT LISTVIEW_FindItem(HWND hwnd, INT nStart, LPLVFINDINFO lpFindInfo) { -/* LISTVIEW_INFO *infoPtr = (LISTVIEW_INFO *)GetWindowLong32A(hwnd, 0); */ +/* LISTVIEW_INFO *infoPtr = (LISTVIEW_INFO *)GetWindowLongA(hwnd, 0); */ /* LISTVIEW_ITEM *lpItem; */ -/* INT32 nItem; */ -/* INT32 nEnd = infoPtr->nItemCount; */ -/* BOOL32 bWrap = FALSE; */ +/* INT nItem; */ +/* INT nEnd = GETITEMCOUNT(infoPtr); */ +/* BOOL bWrap = FALSE; */ /* if (nStart == -1) */ /* nStart = 0; */ /* else */ @@ -1163,7 +2438,7 @@ static LRESULT LISTVIEW_FindItem(HWND hwnd, INT nStart, * Retrieves the background color of the listview control. * * PARAMETER(S): - * [I] HWND32 : window handle + * [I] HWND : window handle * * RETURN: * COLORREF associated with the background. @@ -1172,7 +2447,7 @@ static LRESULT LISTVIEW_GetBkColor(HWND hwnd) { LISTVIEW_INFO *infoPtr = (LISTVIEW_INFO *)GetWindowLongA(hwnd, 0); - return infoPtr->clrBk; + return infoPtr->clrBk; } /*** @@ -1180,103 +2455,146 @@ static LRESULT LISTVIEW_GetBkColor(HWND hwnd) * Retrieves the background image of the listview control. * * PARAMETER(S): - * [I] HWND32 : window handle - * [O] LPLVMKBIMAGE : background image information + * [I] HWND : window handle + * [O] LPLVMKBIMAGE : background image attributes * * RETURN: * SUCCESS : TRUE - * FAILURE : FALSE + * FAILURE : FALSE` */ -/* static LRESULT LISTVIEW_GetBkImage(HWND32 hwnd, LPLVBKIMAGE lpBkImage) */ -/* { */ -/* return FALSE; */ -/* } */ +/* static LRESULT LISTVIEW_GetBkImage(HWND hwnd, LPLVBKIMAGE lpBkImage) */ +/* { */ +/* return FALSE; */ +/* } */ -/* << LISTVIEW_GetCallbackMask >> */ +/*** + * DESCRIPTION: + * Retrieves the callback mask. + * + * PARAMETER(S): + * [I] HWND : window handle + * + * RETURN: + * Value of mask + */ +static UINT LISTVIEW_GetCallbackMask(HWND hwnd) +{ + LISTVIEW_INFO *infoPtr = (LISTVIEW_INFO *)GetWindowLongA(hwnd, 0); + + return infoPtr->uCallbackMask; +} /*** * DESCRIPTION: * Retrieves column attributes. * * PARAMETER(S): - * [I] HWND32 : window handle - * [I] INT32 : column index - * [IO] LPLVCOLUMN32A : column information + * [I] HWND : window handle + * [I] INT : column index + * [IO] LPLVCOLUMNA : column information * * RETURN: * SUCCESS : TRUE * FAILURE : FALSE */ -static LRESULT LISTVIEW_GetColumnA(HWND hwnd, INT nIndex, +static LRESULT LISTVIEW_GetColumnA(HWND hwnd, INT nItem, LPLVCOLUMNA lpColumn) { LISTVIEW_INFO *infoPtr = (LISTVIEW_INFO *)GetWindowLongA(hwnd, 0); - HDITEMA hdi; + HDITEMA hdi; + BOOL bResult = FALSE; - if (lpColumn == NULL) - return FALSE; - - ZeroMemory (&hdi, sizeof(HDITEMA)); - - if (lpColumn->mask & LVCF_FMT) - hdi.mask |= HDI_FORMAT; - - if (lpColumn->mask & LVCF_WIDTH) - hdi.mask |= HDI_WIDTH; - - if (lpColumn->mask & LVCF_TEXT) - hdi.mask |= (HDI_TEXT | HDI_FORMAT); - - if (lpColumn->mask & LVCF_IMAGE) - hdi.mask |= HDI_IMAGE; - - if (lpColumn->mask & LVCF_ORDER) - hdi.mask |= HDI_ORDER; - - if (!SendMessageA (infoPtr->hwndHeader, HDM_GETITEMA, - (WPARAM)nIndex, (LPARAM)&hdi)) - return FALSE; - - if (lpColumn->mask & LVCF_FMT) + if (lpColumn != NULL) { - lpColumn->fmt = 0; - - if (hdi.fmt & HDF_LEFT) - lpColumn->fmt |= LVCFMT_LEFT; - else if (hdi.fmt & HDF_RIGHT) - lpColumn->fmt |= LVCFMT_RIGHT; - else if (hdi.fmt & HDF_CENTER) - lpColumn->fmt |= LVCFMT_CENTER; - - if (hdi.fmt & HDF_IMAGE) - lpColumn->fmt |= LVCFMT_COL_HAS_IMAGES; + /* initialize memory */ + ZeroMemory(&hdi, sizeof(HDITEMA)); + + if (lpColumn->mask & LVCF_FMT) + { + hdi.mask |= HDI_FORMAT; } - if (lpColumn->mask & LVCF_WIDTH) - lpColumn->cx = hdi.cxy; + if (lpColumn->mask & LVCF_WIDTH) + { + hdi.mask |= HDI_WIDTH; + } - if ((lpColumn->mask & LVCF_TEXT) && (lpColumn->pszText) && (hdi.pszText)) - lstrcpynA (lpColumn->pszText, hdi.pszText, lpColumn->cchTextMax); + if (lpColumn->mask & LVCF_TEXT) + { + hdi.mask |= (HDI_TEXT | HDI_FORMAT); + } - if (lpColumn->mask & LVCF_IMAGE) - lpColumn->iImage = hdi.iImage; + if (lpColumn->mask & LVCF_IMAGE) + { + hdi.mask |= HDI_IMAGE; + } - if (lpColumn->mask & LVCF_ORDER) - lpColumn->iOrder = hdi.iOrder; + if (lpColumn->mask & LVCF_ORDER) + { + hdi.mask |= HDI_ORDER; + } - return TRUE; + bResult = Header_GetItemA(infoPtr->hwndHeader, nItem, &hdi); + if (bResult == TRUE) + { + if (lpColumn->mask & LVCF_FMT) + { + lpColumn->fmt = 0; + + if (hdi.fmt & HDF_LEFT) + { + lpColumn->fmt |= LVCFMT_LEFT; + } + else if (hdi.fmt & HDF_RIGHT) + { + lpColumn->fmt |= LVCFMT_RIGHT; + } + else if (hdi.fmt & HDF_CENTER) + { + lpColumn->fmt |= LVCFMT_CENTER; + } + + if (hdi.fmt & HDF_IMAGE) + { + lpColumn->fmt |= LVCFMT_COL_HAS_IMAGES; + } + } + + if (lpColumn->mask & LVCF_WIDTH) + { + lpColumn->cx = hdi.cxy; + } + + if ((lpColumn->mask & LVCF_TEXT) && (lpColumn->pszText) && (hdi.pszText)) + { + lstrcpynA (lpColumn->pszText, hdi.pszText, lpColumn->cchTextMax); + } + + if (lpColumn->mask & LVCF_IMAGE) + { + lpColumn->iImage = hdi.iImage; + } + + if (lpColumn->mask & LVCF_ORDER) + { + lpColumn->iOrder = hdi.iOrder; + } + } + } + + return bResult; } -/* << LISTVIEW_GetColumn32W >> */ +/* << LISTVIEW_GetColumnW >> */ /* << LISTVIEW_GetColumnOrderArray >> */ /*** * DESCRIPTION: - * Retrieves the column width when list or report display mode. + * Retrieves the column width. * * PARAMETER(S): - * [I] HWND32 : window handle - * [I] int32 : column index + * [I] HWND : window handle + * [I] int : column index * * RETURN: * SUCCESS : column width @@ -1286,23 +2604,21 @@ static LRESULT LISTVIEW_GetColumnWidth(HWND hwnd, INT nColumn) { LISTVIEW_INFO *infoPtr = (LISTVIEW_INFO *)GetWindowLongA(hwnd, 0); LONG lStyle = GetWindowLongA(hwnd, GWL_STYLE); - HDITEMA hdi; + HDITEMA hdi; INT nColumnWidth = 0; - if ((lStyle & LVS_LIST) || (lStyle & LVS_SMALLICON) || (lStyle & LVS_ICON)) + if ((LVS_TYPEMASK & lStyle) == LVS_LIST) { nColumnWidth = infoPtr->nColumnWidth; } - else if (lStyle & LVS_REPORT) + else if ((LVS_TYPEMASK & lStyle) == LVS_REPORT) { - /* verify validity of index */ - if ((nColumn >= 0) && (nColumn < infoPtr->nColumnCount)) - { - /* get column width from header */ + /* get column width from header */ + ZeroMemory(&hdi, sizeof(HDITEMA)); hdi.mask = HDI_WIDTH; - if (SendMessageA (infoPtr->hwndHeader, HDM_GETITEMA, - (WPARAM)nColumn, (LPARAM)&hdi)) - nColumnWidth = hdi.cxy; + if (Header_GetItemA(infoPtr->hwndHeader, nColumn, &hdi) == TRUE) + { + nColumnWidth = hdi.cxy; } } @@ -1316,7 +2632,7 @@ static LRESULT LISTVIEW_GetColumnWidth(HWND hwnd, INT nColumn) * retrieves the total number of visible items. * * PARAMETER(S): - * [I] HWND32 : window handle + * [I] HWND : window handle * * RETURN: * Number of fully visible items. @@ -1326,23 +2642,22 @@ static LRESULT LISTVIEW_GetCountPerPage(HWND hwnd) LISTVIEW_INFO *infoPtr = (LISTVIEW_INFO *)GetWindowLongA(hwnd, 0); LONG lStyle = GetWindowLongA(hwnd, GWL_STYLE); INT nItemCount = 0; - INT nItemCountPerRow = LISTVIEW_GetItemCountPerRow(hwnd); - INT nItemCountPerColumn = LISTVIEW_GetItemCountPerColumn(hwnd); - if (lStyle & LVS_LIST) + switch (LVS_TYPEMASK & lStyle) { - if ((nItemCountPerRow > 0) && (nItemCountPerColumn > 0)) + case LVS_LIST: + if (infoPtr->rcList.right / infoPtr->nColumnWidth) { - nItemCount = nItemCountPerRow * nItemCountPerColumn; + nItemCount = infoPtr->nCountPerRow * infoPtr->nCountPerColumn; } - } - else if (lStyle & LVS_REPORT) - { - nItemCount = nItemCountPerColumn; - } - else if ((lStyle & LVS_SMALLICON) || (lStyle & LVS_ICON)) - { - nItemCount = infoPtr->nItemCount; + break; + + case LVS_REPORT: + nItemCount = infoPtr->nCountPerColumn; + break; + + default: + nItemCount = GETITEMCOUNT(infoPtr); } return nItemCount; @@ -1356,7 +2671,7 @@ static LRESULT LISTVIEW_GetCountPerPage(HWND hwnd) * Retrieves a header handle. * * PARAMETER(S): - * [I] HWND32 : window handle + * [I] HWND : window handle * * RETURN: * Header handle. @@ -1365,7 +2680,7 @@ static LRESULT LISTVIEW_GetHeader(HWND hwnd) { LISTVIEW_INFO *infoPtr = (LISTVIEW_INFO *)GetWindowLongA(hwnd, 0); - return infoPtr->hwndHeader; + return infoPtr->hwndHeader; } /* << LISTVIEW_GetHotCursor >> */ @@ -1377,8 +2692,8 @@ static LRESULT LISTVIEW_GetHeader(HWND hwnd) * Retrieves an image list handle. * * PARAMETER(S): - * [I] HWND32 : window handle - * [I] INT32 : image list identifier + * [I] HWND : window handle + * [I] INT : image list identifier * * RETURN: * SUCCESS : image list handle @@ -1391,18 +2706,20 @@ static LRESULT LISTVIEW_GetImageList(HWND hwnd, INT nImageList) switch (nImageList) { - case LVSIL_NORMAL: + case LVSIL_NORMAL: himl = infoPtr->himlNormal; - case LVSIL_SMALL: + break; + case LVSIL_SMALL: himl = infoPtr->himlSmall; - case LVSIL_STATE: + break; + case LVSIL_STATE: himl = infoPtr->himlState; - } + break; + } return (LRESULT)himl; } - /* << LISTVIEW_GetISearchString >> */ /*** @@ -1410,55 +2727,97 @@ static LRESULT LISTVIEW_GetImageList(HWND hwnd, INT nImageList) * Retrieves item attributes. * * PARAMETER(S): - * [I] HWND32 : window handle - * [IO] LPLVITEM32A : item info + * [I] HWND : window handle + * [IO] LPLVITEMA : item info * * RETURN: * SUCCESS : TRUE * FAILURE : FALSE */ -static LRESULT LISTVIEW_GetItemA(HWND hwnd, LPLVITEMA lpItem) +static LRESULT LISTVIEW_GetItemA(HWND hwnd, LPLVITEMA lpLVItem) { LISTVIEW_INFO *infoPtr = (LISTVIEW_INFO *)GetWindowLongA(hwnd, 0); - LISTVIEW_ITEM *lpListItem; + LISTVIEW_ITEM *lpItem; + LISTVIEW_SUBITEM *lpSubItem; + HDPA hdpaSubItems; BOOL bResult = FALSE; - if (lpItem != NULL) + if (lpLVItem != NULL) { - if ((lpItem->iItem >= 0) && (lpItem->iItem < infoPtr->nItemCount)) + if ((lpLVItem->iItem >= 0) && (lpLVItem->iItem < GETITEMCOUNT(infoPtr))) { - /* get item */ - lpListItem = DPA_GetPtr(infoPtr->hdpaItems, lpItem->iItem); - if (lpListItem != NULL) + hdpaSubItems = (HDPA)DPA_GetPtr(infoPtr->hdpaItems, lpLVItem->iItem); + if (hdpaSubItems != NULL) { - /* not tested for subitem > 0 */ - lpListItem += lpItem->iSubItem; - if (lpListItem != NULL) + if (lpLVItem->iSubItem == 0) { - /* retrieve valid data */ - if (lpItem->mask & LVIF_STATE) - lpItem->state = lpListItem->state & lpItem->stateMask; - - if (lpItem->mask & LVIF_TEXT) + lpItem = (LISTVIEW_ITEM *)DPA_GetPtr(hdpaSubItems, 0); + if (lpItem != NULL) { - if (lpListItem->pszText == LPSTR_TEXTCALLBACKA) - lpItem->pszText = LPSTR_TEXTCALLBACKA; - else - Str_GetPtrA(lpListItem->pszText, lpItem->pszText, - lpItem->cchTextMax); - } + bResult = TRUE; - if (lpItem->mask & LVIF_IMAGE) - lpItem->iImage = lpListItem->iImage; + /* retrieve valid data */ + if (lpLVItem->mask & LVIF_STATE) + { + lpLVItem->state = lpItem->state & lpLVItem->stateMask; + } - if (lpItem->mask & LVIF_PARAM) - lpItem->lParam = lpListItem->lParam; + if (lpLVItem->mask & LVIF_TEXT) + { + if (lpItem->pszText == LPSTR_TEXTCALLBACKA) + { + lpLVItem->pszText = LPSTR_TEXTCALLBACKA; + } + else + { + bResult = Str_GetPtrA(lpItem->pszText, lpLVItem->pszText, + lpLVItem->cchTextMax); + } + } - if (lpItem->mask & LVIF_INDENT) - lpItem->iIndent = lpListItem->iIndent; + if (lpLVItem->mask & LVIF_IMAGE) + { + lpLVItem->iImage = lpItem->iImage; + } + + if (lpLVItem->mask & LVIF_PARAM) + { + lpLVItem->lParam = lpItem->lParam; + } + + if (lpLVItem->mask & LVIF_INDENT) + { + lpLVItem->iIndent = lpItem->iIndent; + } + } + } + else + { + lpSubItem = (LISTVIEW_SUBITEM *)DPA_GetPtr(hdpaSubItems, + lpLVItem->iSubItem); + if (lpSubItem != NULL) + { + bResult = TRUE; - bResult = TRUE; -} + if (lpLVItem->mask & LVIF_TEXT) + { + if (lpSubItem->pszText == LPSTR_TEXTCALLBACKA) + { + lpLVItem->pszText = LPSTR_TEXTCALLBACKA; + } + else + { + bResult = Str_GetPtrA(lpSubItem->pszText, lpLVItem->pszText, + lpLVItem->cchTextMax); + } + } + + if (lpLVItem->mask & LVIF_IMAGE) + { + lpLVItem->iImage = lpSubItem->iImage; + } + } + } } } } @@ -1466,7 +2825,7 @@ static LRESULT LISTVIEW_GetItemA(HWND hwnd, LPLVITEMA lpItem) return bResult; } -/* << LISTVIEW_GetItem32W >> */ +/* << LISTVIEW_GetItemW >> */ /* << LISTVIEW_GetHotCursor >> */ /* << LISTVIEW_GetHotItem >> */ /* << LISTVIEW_GetHoverTime >> */ @@ -1476,16 +2835,16 @@ static LRESULT LISTVIEW_GetItemA(HWND hwnd, LPLVITEMA lpItem) * Retrieves the number of items in the listview control. * * PARAMETER(S): - * [I] HWND32 : window handle + * [I] HWND : window handle * * RETURN: * Number of items. */ static LRESULT LISTVIEW_GetItemCount(HWND hwnd) { - LISTVIEW_INFO *infoPtr = (LISTVIEW_INFO*)GetWindowLongA(hwnd, 0); + LISTVIEW_INFO *infoPtr = (LISTVIEW_INFO *)GetWindowLongA(hwnd, 0); - return infoPtr->nItemCount; + return GETITEMCOUNT(infoPtr); } /*** @@ -1493,73 +2852,87 @@ static LRESULT LISTVIEW_GetItemCount(HWND hwnd) * Retrieves the position (upper-left) of the listview control item. * * PARAMETER(S): - * [I] HWND32 : window handle - * [I] INT32 : item index - * [O] LPPOINT32 : coordinate information + * [I] HWND : window handle + * [I] INT : item index + * [O] LPPOINT : coordinate information * * RETURN: * SUCCESS : TRUE * FAILURE : FALSE */ static LRESULT LISTVIEW_GetItemPosition(HWND hwnd, INT nItem, - LPPOINT lpPt) + LPPOINT lppt) { LISTVIEW_INFO *infoPtr = (LISTVIEW_INFO *)GetWindowLongA(hwnd, 0); LONG lStyle = GetWindowLongA(hwnd, GWL_STYLE); INT nColumn; INT nRow; BOOL bResult = FALSE; - INT nItemCountPerColumn; - INT nItemCountPerRow; - INT nFirstItem; - INT nLastItem; + INT nFirst; + INT nLast; - if ((nItem >= 0) && (nItem < infoPtr->nItemCount) && (lpPt != NULL)) + if ((nItem >= 0) && (nItem < GETITEMCOUNT(infoPtr)) && (lppt != NULL)) { - if (lStyle & LVS_LIST) -{ - nItemCountPerColumn = LISTVIEW_GetItemCountPerColumn(hwnd); - nItemCountPerRow = LISTVIEW_GetItemCountPerRow(hwnd); + switch (LVS_TYPEMASK & lStyle) + { + case LVS_LIST: + nFirst = ListView_GetTopIndex(hwnd); + nLast = infoPtr->nCountPerColumn * infoPtr->nCountPerRow + nFirst - 1; - if ((nItemCountPerColumn > 0) && (nItemCountPerRow > 0)) + if ((nItem >= nFirst) || (nItem <= nLast)) { - nFirstItem = LISTVIEW_GetFirstVisibleItem(hwnd); - nLastItem = nFirstItem + nItemCountPerRow * nItemCountPerRow - 1; + nItem -= nFirst; + + /* get column */ + nColumn = nItem / infoPtr->nCountPerColumn; - if ((nItem >= nFirstItem) || (nItem <= nLastItem)) - { - nItem -= nFirstItem; + /* get row */ + nRow = nItem % infoPtr->nCountPerColumn; + + /* X coordinate of the column */ + lppt->x = nColumn * infoPtr->nColumnWidth + infoPtr->rcList.left; - /* get column */ - nColumn = nItem / nItemCountPerColumn; - - /* get row */ - nRow = nItem % nItemCountPerColumn; - - /* X coordinate of the column */ - lpPt->x = nColumn * infoPtr->nColumnWidth; - - /* Y coordinate of the item */ - lpPt->y = nRow * infoPtr->nItemHeight; - - bResult = TRUE; - } + /* Y coordinate of the item */ + lppt->y = nRow * infoPtr->nItemHeight + infoPtr->rcList.top; + + bResult = TRUE; } - else if (lStyle & LVS_REPORT) + break; + + case LVS_REPORT: + nFirst = ListView_GetTopIndex(hwnd); + nLast = infoPtr->nCountPerColumn * infoPtr->nCountPerRow + nFirst - 1; + + /* get column */ + nColumn = nItem / infoPtr->nCountPerColumn; + + /* get row */ + nRow = nItem % infoPtr->nCountPerColumn; + + if ((nItem >= nFirst) || (nItem <= nLast)) { - /* TO DO */ - } - else if (lStyle & LVS_SMALLICON) - { - /* TO DO */ - } - else if (lStyle & LVS_ICON) -{ - /* TO DO */ - } + nItem -= nFirst; + + /* get column */ + nColumn = nItem / infoPtr->nCountPerColumn; + + /* get row */ + nRow = nItem % infoPtr->nCountPerColumn; + + /* X coordinate of the column */ + lppt->x = infoPtr->rcList.left; + + /* Y coordinate of the item */ + lppt->y = nRow * infoPtr->nItemHeight + infoPtr->rcList.top; + + bResult = TRUE; + } + + default: + /* TO DO */ } } - + return bResult; } @@ -1568,64 +2941,96 @@ static LRESULT LISTVIEW_GetItemPosition(HWND hwnd, INT nItem, * Retrieves the bounding rectangle for a listview control item. * * PARAMETER(S): - * [I] HWND32 : window handle - * [I] INT32 : item index - * [IO] LPRECT32 : bounding rectangle coordinates + * [I] HWND : window handle + * [I] INT : item index + * [IO] LPRECT : bounding rectangle coordinates * * RETURN: * SUCCESS : TRUE * FAILURE : FALSE */ -static LRESULT LISTVIEW_GetItemRect(HWND hwnd, INT nItem, LPRECT lpRect) +static LRESULT LISTVIEW_GetItemRect(HWND hwnd, INT nItem, LPRECT lprc) { LISTVIEW_INFO *infoPtr = (LISTVIEW_INFO *)GetWindowLongA(hwnd, 0); + LONG lStyle = GetWindowLongA(hwnd, GWL_STYLE); LISTVIEW_ITEM *lpItem; - POINT pt; - INT nLabelWidth; + HDPA hdpaSubItems; + INT nLabelWidth = 0; + INT nStateWidth = 0; + INT nIconWidth = 0; BOOL bResult = FALSE; - INT nSmallIconWidth; + CHAR szDispText[DISP_TEXT_SIZE]; + LPSTR pszDispText; + POINT pt; - nSmallIconWidth = GetSystemMetrics(SM_CXSMICON); + /*init pointer */ + pszDispText = szDispText; - if ((nItem < 0) || (nItem >= infoPtr->nItemCount) || (lpRect == NULL)) - return FALSE; + if ((nItem >= 0) && (nItem < GETITEMCOUNT(infoPtr)) && (lprc != NULL)) + { + hdpaSubItems = (HDPA)DPA_GetPtr(infoPtr->hdpaItems, nItem); + if (hdpaSubItems != NULL) + { + lpItem = (LISTVIEW_ITEM *)DPA_GetPtr(hdpaSubItems, 0); + if (lpItem != NULL) + { + if ((LVS_TYPEMASK & lStyle) == LVS_ICON) + { - /* get item */ - lpItem = (LISTVIEW_ITEM *)DPA_GetPtr(infoPtr->hdpaItems, nItem); - if (lpItem == NULL) - return FALSE; + } + else + { + if (ListView_GetItemPosition(hwnd, nItem, &pt) == TRUE) + { + /* get width of label in pixels */ + LISTVIEW_GetItemDispInfo(hwnd, nItem, lpItem, NULL, NULL, + &pszDispText, DISP_TEXT_SIZE); + nLabelWidth = ListView_GetStringWidthA(hwnd, pszDispText); + } - if (!SendMessageA(hwnd, LVM_GETITEMPOSITION, (WPARAM)nItem, (LPARAM)&pt)) - return FALSE; + if (infoPtr->himlState != NULL) + { + nStateWidth = infoPtr->iconSize.cx; + } - nLabelWidth = SendMessageA(hwnd, LVM_GETSTRINGWIDTHA, (WPARAM)0, - (LPARAM)lpItem->pszText); - switch(lpRect->left) - { - case LVIR_BOUNDS: - lpRect->left = pt.x; - lpRect->top = pt.y; - lpRect->right = lpRect->left + nSmallIconWidth + nLabelWidth; - lpRect->bottom = lpRect->top + infoPtr->nItemHeight; - bResult = TRUE; - break; - case LVIR_ICON: - lpRect->left = pt.x; - lpRect->top = pt.y; - lpRect->right = lpRect->left + nSmallIconWidth; - lpRect->bottom = lpRect->top + infoPtr->nItemHeight; - bResult = TRUE; - break; - case LVIR_LABEL: - lpRect->left = pt.x + nSmallIconWidth; - lpRect->top = pt.y; - lpRect->right = lpRect->left + nLabelWidth; - lpRect->bottom = infoPtr->nItemHeight; - bResult = TRUE; - break; - case LVIR_SELECTBOUNDS: - /* TO DO */ - break; + if (infoPtr->himlSmall == NULL) + { + nIconWidth = infoPtr->iconSize.cx; + } + + switch(lprc->left) + { + case LVIR_BOUNDS: + lprc->left = pt.x; + lprc->top = pt.y; + lprc->right = lprc->left + nStateWidth + nIconWidth + nLabelWidth; + lprc->bottom = lprc->top + infoPtr->nItemHeight; + bResult = TRUE; + break; + case LVIR_ICON: + lprc->left = pt.x + nStateWidth; + lprc->top = pt.y; + lprc->right = lprc->left + nIconWidth; + lprc->bottom = lprc->top + infoPtr->nItemHeight; + bResult = TRUE; + break; + case LVIR_LABEL: + lprc->left = pt.x + nIconWidth + nStateWidth; + lprc->top = pt.y; + lprc->right = lprc->left + nLabelWidth; + lprc->bottom = infoPtr->nItemHeight; + bResult = TRUE; + break; + case LVIR_SELECTBOUNDS: + lprc->left = pt.x + nStateWidth; + lprc->top = pt.y; + lprc->right = lprc->left + nIconWidth + nLabelWidth; + lprc->bottom = lprc->top + infoPtr->nItemHeight; + bResult = TRUE; + } + } + } + } } return bResult; @@ -1636,34 +3041,28 @@ static LRESULT LISTVIEW_GetItemRect(HWND hwnd, INT nItem, LPRECT lpRect) * Retrieves the spacing between listview control items. * * PARAMETER(S): - * [I] HWND32 : window handle - * [I] BOOL32 : small icon (TRUE) or large icon (FALSE) + * [I] HWND : window handle + * [I] BOOL : flag for small or large icon * * RETURN: * Horizontal + vertical spacing */ static LRESULT LISTVIEW_GetItemSpacing(HWND hwnd, BOOL bSmall) { - INT nSmallIconHSpacing; - INT nSmallIconVSpacing; - INT nIconHSpacing; - INT nIconVSpacing; - LONG lResult = 0; + LISTVIEW_INFO *infoPtr = (LISTVIEW_INFO *)GetWindowLongA(hwnd, 0); + LONG lResult; if (bSmall == TRUE) { - /* ??? */ - nSmallIconHSpacing = 0; - nSmallIconVSpacing = 0; - lResult = MAKELONG(nSmallIconHSpacing, nSmallIconVSpacing); - } - else - { - nIconHSpacing = GetSystemMetrics(SM_CXICONSPACING); - nIconVSpacing = GetSystemMetrics(SM_CYICONSPACING); - lResult = MAKELONG(nIconHSpacing, nIconVSpacing); + lResult = MAKELONG(infoPtr->largeIconSpacing.cx, + infoPtr->largeIconSpacing.cy); } - + else + { + lResult = MAKELONG(infoPtr->smallIconSpacing.cx, + infoPtr->smallIconSpacing.cy); + } + return lResult; } @@ -1672,9 +3071,9 @@ static LRESULT LISTVIEW_GetItemSpacing(HWND hwnd, BOOL bSmall) * Retrieves the state of a listview control item. * * PARAMETER(S): - * [I] HWND32 : window handle - * [I] INT32 : item index - * [I] UINT32 : state mask + * [I] HWND : window handle + * [I] INT : item index + * [I] UINT : state mask * * RETURN: * State specified by the mask. @@ -1682,17 +3081,22 @@ static LRESULT LISTVIEW_GetItemSpacing(HWND hwnd, BOOL bSmall) static LRESULT LISTVIEW_GetItemState(HWND hwnd, INT nItem, UINT uMask) { LISTVIEW_INFO *infoPtr = (LISTVIEW_INFO *)GetWindowLongA(hwnd, 0); - LISTVIEW_ITEM *lpItem; - INT nState = 0; + LVITEMA lvItem; + UINT uState = 0; - if ((nItem >= 0) && (nItem < infoPtr->nItemCount)) + if ((nItem >= 0) && (nItem < GETITEMCOUNT(infoPtr))) { - lpItem = (LISTVIEW_ITEM *)DPA_GetPtr(infoPtr->hdpaItems, nItem); - if (lpItem != NULL) - nState = lpItem->state & uMask; + ZeroMemory(&lvItem, sizeof(LVITEMA)); + lvItem.iItem = nItem; + lvItem.stateMask = uMask; + lvItem.mask = LVIF_STATE; + if (ListView_GetItemA(hwnd, &lvItem) == TRUE) + { + uState = lvItem.state; + } } - return nState; + return uState; } /*** @@ -1700,34 +3104,73 @@ static LRESULT LISTVIEW_GetItemState(HWND hwnd, INT nItem, UINT uMask) * Retrieves the text of a listview control item or subitem. * * PARAMETER(S): - * [I] HWND32 : window handle - * [I] INT32 : item index - * [IO] LPLVITEM32A : item information + * [I] HWND : window handle + * [I] INT : item index + * [IO] LPLVITEMA : item information * * RETURN: * None */ -static VOID LISTVIEW_GetItemTextA(HWND hwnd, INT nItem, - LPLVITEMA lpItem) +static LRESULT LISTVIEW_GetItemTextA(HWND hwnd, INT nItem, + LPLVITEMA lpLVItem) { LISTVIEW_INFO *infoPtr = (LISTVIEW_INFO *)GetWindowLongA(hwnd, 0); - LISTVIEW_ITEM *lpListItem; + LISTVIEW_ITEM *lpItem; + LISTVIEW_SUBITEM *lpSubItem; + HDPA hdpaSubItems; + INT nLength = 0; + + if (lpLVItem != NULL) + { + if ((nItem >= 0) && (nItem < GETITEMCOUNT(infoPtr))) + { + hdpaSubItems = (HDPA)DPA_GetPtr(infoPtr->hdpaItems, lpLVItem->iItem); + if (hdpaSubItems != NULL) + { + if (lpLVItem->iSubItem == 0) + { + lpItem = (LISTVIEW_ITEM *)DPA_GetPtr(hdpaSubItems, 0); + if (lpItem != NULL) + { + if (lpLVItem->mask & LVIF_TEXT) + { + if (lpItem->pszText == LPSTR_TEXTCALLBACKA) + { + lpLVItem->pszText = LPSTR_TEXTCALLBACKA; + } + else + { + nLength = Str_GetPtrA(lpItem->pszText, lpLVItem->pszText, + lpLVItem->cchTextMax); + } + } + } + } + else + { + lpSubItem = (LISTVIEW_SUBITEM *)DPA_GetPtr(hdpaSubItems, + lpLVItem->iSubItem); + if (lpSubItem != NULL) + { + if (lpLVItem->mask & LVIF_TEXT) + { + if (lpSubItem->pszText == LPSTR_TEXTCALLBACKA) + { + lpLVItem->pszText = LPSTR_TEXTCALLBACKA; + } + else + { + nLength = Str_GetPtrA(lpSubItem->pszText, lpLVItem->pszText, + lpLVItem->cchTextMax); + } + } + } + } + } + } + } - if ((nItem < 0) || (nItem >= infoPtr->nItemCount) || (lpItem == NULL)) - return; - - lpListItem = (LISTVIEW_ITEM *)DPA_GetPtr(infoPtr->hdpaItems, nItem); - if (lpListItem == NULL) - return; - - lpListItem += lpItem->iSubItem; - if (lpListItem == NULL) - return; - - if (lpListItem->pszText == LPSTR_TEXTCALLBACKA) - lpItem->pszText = LPSTR_TEXTCALLBACKA; - else - Str_GetPtrA(lpListItem->pszText, lpItem->pszText, lpItem->cchTextMax); + return nLength; } /*** @@ -1735,28 +3178,35 @@ static VOID LISTVIEW_GetItemTextA(HWND hwnd, INT nItem, * Searches for an item based on properties + relationships. * * PARAMETER(S): - * [I] HWND32 : window handle - * [I] INT32 : item index - * [I] UINT32 : relationship flag + * [I] HWND : window handle + * [I] INT : item index + * [I] UINT : relationship flag * * RETURN: * SUCCESS : item index * FAILURE : -1 */ -static LRESULT LISTVIEW_GetNextItem (HWND hwnd, INT nItem, UINT uFlags) +static LRESULT LISTVIEW_GetNextItem(HWND hwnd, INT nItem, UINT uFlags) { LISTVIEW_INFO *infoPtr = (LISTVIEW_INFO *)GetWindowLongA(hwnd, 0); INT nResult = -1; - /* start at begin */ if (nItem == -1) + { + /* start at begin */ nItem = 0; + } + else + { + /* exclude specified item */ + nItem++; + } - if ((nItem >= 0) && (nItem < infoPtr->nItemCount)) + if ((nItem >= 0) && (nItem < GETITEMCOUNT(infoPtr))) { /* TO DO */ -} - + } + return nResult; } @@ -1767,8 +3217,8 @@ static LRESULT LISTVIEW_GetNextItem (HWND hwnd, INT nItem, UINT uFlags) * Retrieves the current origin when in icon or small icon display mode. * * PARAMETER(S): - * [I] HWND32 : window handle - * [O] LPPOINT32 : coordinate information + * [I] HWND : window handle + * [O] LPPOINT : coordinate information * * RETURN: * SUCCESS : TRUE @@ -1779,13 +3229,17 @@ static LRESULT LISTVIEW_GetOrigin(HWND hwnd, LPPOINT lpOrigin) LONG lStyle = GetWindowLongA(hwnd, GWL_ID); BOOL bResult = FALSE; - if (lStyle & LVS_SMALLICON) + if ((lStyle & LVS_TYPEMASK) == LVS_SMALLICON) { /* TO DO */ + lpOrigin->x = 0; + lpOrigin->y = 0; } - else if (lStyle & LVS_ICON) + else if ((lStyle & LVS_TYPEMASK) == LVS_ICON) { /* TO DO */ + lpOrigin->x = 0; + lpOrigin->y = 0; } return bResult; @@ -1796,7 +3250,7 @@ static LRESULT LISTVIEW_GetOrigin(HWND hwnd, LPPOINT lpOrigin) * Retrieves the number of items that are marked as selected. * * PARAMETER(S): - * [I] HWND32 : window handle + * [I] HWND : window handle * * RETURN: * Number of items selected. @@ -1804,17 +3258,14 @@ static LRESULT LISTVIEW_GetOrigin(HWND hwnd, LPPOINT lpOrigin) static LRESULT LISTVIEW_GetSelectedCount(HWND hwnd) { LISTVIEW_INFO *infoPtr = (LISTVIEW_INFO *)GetWindowLongA(hwnd, 0); - LISTVIEW_ITEM *lpItem; INT nSelectedCount = 0; INT i; - for (i = 0; i < infoPtr->nItemCount; i++) + for (i = 0; i < GETITEMCOUNT(infoPtr); i++) { - lpItem = (LISTVIEW_ITEM *)DPA_GetPtr(infoPtr->hdpaItems, i); - if (lpItem != NULL) + if (ListView_GetItemState(hwnd, i, LVIS_SELECTED) & LVIS_SELECTED) { - if (lpItem->state & LVIS_SELECTED) - nSelectedCount++; + nSelectedCount++; } } @@ -1826,7 +3277,7 @@ static LRESULT LISTVIEW_GetSelectedCount(HWND hwnd) * Retrieves item index that marks the start of a multiple selection. * * PARAMETER(S): - * [I] HWND32 : window handle + * [I] HWND : window handle * * RETURN: * Index number or -1 if there is no selection mark. @@ -1834,12 +3285,8 @@ static LRESULT LISTVIEW_GetSelectedCount(HWND hwnd) static LRESULT LISTVIEW_GetSelectionMark(HWND hwnd) { LISTVIEW_INFO *infoPtr = (LISTVIEW_INFO *)GetWindowLongA(hwnd, 0); - INT nResult = -1; - if (SendMessageA(hwnd, LVM_GETSELECTEDCOUNT, (WPARAM)0, (LPARAM)0) != 0) - nResult = infoPtr->nSelectionMark; - - return nResult; + return infoPtr->nSelectionMark; } /*** @@ -1847,7 +3294,7 @@ static LRESULT LISTVIEW_GetSelectionMark(HWND hwnd) * Retrieves the width of a string. * * PARAMETER(S): - * [I] HWND32 : window handle + * [I] HWND : window handle * * RETURN: * SUCCESS : string width (in pixels) @@ -1856,23 +3303,23 @@ static LRESULT LISTVIEW_GetSelectionMark(HWND hwnd) static LRESULT LISTVIEW_GetStringWidthA(HWND hwnd, LPCSTR lpsz) { LISTVIEW_INFO *infoPtr = (LISTVIEW_INFO *)GetWindowLongA(hwnd, 0); - HFONT hFont, hOldFont; - HDC hdc; + HFONT hFont, hOldFont; + HDC hdc; SIZE textSize; - INT nResult = 0; + /* initialize */ + ZeroMemory(&textSize, sizeof(SIZE)); if (lpsz != NULL) { - hFont = infoPtr->hFont ? infoPtr->hFont : GetStockObject (SYSTEM_FONT); + hFont = infoPtr->hFont ? infoPtr->hFont : infoPtr->hDefaultFont; hdc = GetDC(hwnd); - hOldFont = SelectObject (hdc, hFont); - GetTextExtentPoint32A(hdc, lpsz, lstrlenA(lpsz), &textSize); - SelectObject (hdc, hOldFont); + hOldFont = SelectObject(hdc, hFont); + GetTextExtentPointA(hdc, lpsz, lstrlenA(lpsz), &textSize); + SelectObject(hdc, hOldFont); ReleaseDC(hwnd, hdc); - nResult = textSize.cx; } - return nResult; + return textSize.cx; } /*** @@ -1880,7 +3327,7 @@ static LRESULT LISTVIEW_GetStringWidthA(HWND hwnd, LPCSTR lpsz) * Retrieves the text backgound color. * * PARAMETER(S): - * [I] HWND32 : window handle + * [I] HWND : window handle * * RETURN: * COLORREF associated with the the background. @@ -1897,7 +3344,7 @@ static LRESULT LISTVIEW_GetTextBkColor(HWND hwnd) * Retrieves the text color. * * PARAMETER(S): - * [I] HWND32 : window handle + * [I] HWND : window handle * * RETURN: * COLORREF associated with the text. @@ -1914,22 +3361,23 @@ static LRESULT LISTVIEW_GetTextColor(HWND hwnd) * Retrieves the bounding rectangle of all the items. * * PARAMETER(S): - * [I] HWND32 : window handle - * [O] LPRECT32 : bounding rectangle + * [I] HWND : window handle + * [O] LPRECT : bounding rectangle * * RETURN: * SUCCESS : TRUE * FAILURE : FALSE */ -static LRESULT LISTVIEW_GetViewRect(HWND hwnd, LPRECT lpBoundingRect) +static LRESULT LISTVIEW_GetViewRect(HWND hwnd, LPRECT lprc) { - /* LISTVIEW_INFO *infoPtr = (LISTVIEW_INFO *)GetWindowLong32A(hwnd, 0); */ + /* LISTVIEW_INFO *infoPtr = (LISTVIEW_INFO *)GetWindowLongA(hwnd, 0); */ LONG lStyle = GetWindowLongA(hwnd, GWL_STYLE); BOOL bResult = FALSE; - if (lpBoundingRect != NULL) + if (lprc != NULL) { - if ((lStyle & LVS_ICON) || (lStyle & LVS_SMALLICON)) + if (((lStyle & LVS_TYPEMASK) == LVS_ICON) || + ((lStyle & LVS_TYPEMASK) == LVS_SMALLICON)) { /* TO DO */ } @@ -1940,197 +3388,106 @@ static LRESULT LISTVIEW_GetViewRect(HWND hwnd, LPRECT lpBoundingRect) /*** * DESCRIPTION: - * Determines item index when in small icon view. + * Determines which section of the item was selected (if any). * * PARAMETER(S): - * [I] HWND32 : window handle + * [I] HWND : window handle + * [I] INT : item index * [IO] LPLVHITTESTINFO : hit test information * * RETURN: * SUCCESS : item index * FAILURE : -1 */ -static LRESULT HitTestSmallIconView(HWND hwnd, LPLVHITTESTINFO lpHitTestInfo) +static INT LISTVIEW_HitTestItem(HWND hwnd, INT nItem, + LPLVHITTESTINFO lpHitTestInfo) { LISTVIEW_INFO *infoPtr = (LISTVIEW_INFO *)GetWindowLongA(hwnd, 0); + LONG lStyle = GetWindowLongA(hwnd, GWL_STYLE); + HDPA hdpaSubItems; LISTVIEW_ITEM *lpItem; - INT nColumn; - INT nRow; - INT nItem = 0; - INT nLabelWidth; INT nOffset; + INT nLabelWidth; INT nPosX = 0; - INT nSmallIconWidth; - INT nItemCountPerRow; + CHAR szDispText[DISP_TEXT_SIZE]; + LPSTR pszDispText; - /* get column */ - nColumn = lpHitTestInfo->pt.x / infoPtr->nColumnWidth; + /*init pointer */ + pszDispText = szDispText; - /* get row */ - nRow = lpHitTestInfo->pt.y / infoPtr->nItemHeight; - - /* calculate offset from start of column (in pixels) */ - nOffset = lpHitTestInfo->pt.x % infoPtr->nColumnWidth; - - /* get recommended width of a small icon */ - nSmallIconWidth = GetSystemMetrics(SM_CXSMICON); - - /* calculate index */ - nItemCountPerRow = LISTVIEW_GetItemCountPerRow(hwnd); - nItem = nRow * nItemCountPerRow + LISTVIEW_GetFirstVisibleItem(hwnd) + nColumn; + if ((LVS_TYPEMASK & lStyle) == LVS_LIST) + { + /* calculate offset from start of item (in pixels) */ + nOffset = lpHitTestInfo->pt.x % infoPtr->nColumnWidth; + } + else + { + nOffset = lpHitTestInfo->pt.x; + } /* verify existance of item */ - if (nItem < infoPtr->nItemCount) + if (nItem < GETITEMCOUNT(infoPtr)) { /* get item */ - lpItem = (LISTVIEW_ITEM *)DPA_GetPtr(infoPtr->hdpaItems, nItem); - if (lpItem != NULL) + hdpaSubItems = (HDPA)DPA_GetPtr(infoPtr->hdpaItems, nItem); + if (hdpaSubItems != NULL) { - if (infoPtr->himlState != NULL) + lpItem = (LISTVIEW_ITEM *)DPA_GetPtr(hdpaSubItems, 0); + if (lpItem != NULL) { - nPosX += nSmallIconWidth; - if (nOffset <= nPosX) + if (infoPtr->himlState != NULL) { - lpHitTestInfo->flags = LVHT_ONITEMSTATEICON | LVHT_ONITEM; + nPosX += infoPtr->iconSize.cx; + if (nOffset <= nPosX) + { + lpHitTestInfo->flags = LVHT_ONITEMSTATEICON | LVHT_ONITEM; + lpHitTestInfo->iItem = nItem; + lpHitTestInfo->iSubItem = 0; + return nItem; + } + } + + if (infoPtr->himlSmall != NULL) + { + nPosX += infoPtr->iconSize.cx; + if (nOffset <= nPosX) + { + lpHitTestInfo->flags = LVHT_ONITEMICON | LVHT_ONITEM; + lpHitTestInfo->iItem = nItem; + lpHitTestInfo->iSubItem = 0; + return nItem; + } + } + + /* get width of label in pixels */ + LISTVIEW_GetItemDispInfo(hwnd, nItem, lpItem, NULL, NULL, + &pszDispText, DISP_TEXT_SIZE); + nLabelWidth = ListView_GetStringWidthA(hwnd, pszDispText); + nLabelWidth += nPosX; + + if (nOffset <= nLabelWidth) + { + lpHitTestInfo->flags = LVHT_ONITEMLABEL | LVHT_ONITEM; lpHitTestInfo->iItem = nItem; lpHitTestInfo->iSubItem = 0; return nItem; } } - - if (infoPtr->himlSmall != NULL) - { - nPosX += nSmallIconWidth; - if (nOffset <= nPosX) - { - lpHitTestInfo->flags = LVHT_ONITEMICON | LVHT_ONITEM; - lpHitTestInfo->iItem = nItem; - lpHitTestInfo->iSubItem = 0; - return nItem; -} - } - - /* get width of label in pixels */ - nLabelWidth = SendMessageA(hwnd, LVM_GETSTRINGWIDTHA, (WPARAM)0, - (LPARAM)lpItem->pszText); - nLabelWidth += nPosX; - - if (nOffset <= nLabelWidth) -{ - lpHitTestInfo->flags = LVHT_ONITEMLABEL | LVHT_ONITEM; - lpHitTestInfo->iItem = nItem; - lpHitTestInfo->iSubItem = 0; - return nItem; - } } } - /* hit is not on an item */ + /* hit is not on item */ lpHitTestInfo->flags = LVHT_NOWHERE; return -1; } -/*** - * DESCRIPTION: - * Determines item index when in list display mode. - * - * PARAMETER(S): - * [I] HWND32 : window handle - * [IO] LPLVHITTESTINFO : hit test information - * - * RETURN: - * SUCCESS : item index - * FAILURE : -1 - */ -static LRESULT HitTestListView(HWND hwnd, LPLVHITTESTINFO lpHitTestInfo) -{ - LISTVIEW_INFO *infoPtr = (LISTVIEW_INFO *)GetWindowLongA(hwnd, 0); - LISTVIEW_ITEM *lpItem; - INT nColumn; - INT nRow; - INT nItem = 0; - INT nLabelWidth; - INT nOffset; - INT nPosX = 0; - INT nSmallIconWidth; - INT nItemCountPerColumn; - - /* get column */ - nColumn = lpHitTestInfo->pt.x / infoPtr->nColumnWidth; - - /* get row */ - nRow = lpHitTestInfo->pt.y / infoPtr->nItemHeight; - - /* calculate offset from start of column (in pixels) */ - nOffset = lpHitTestInfo->pt.x % infoPtr->nColumnWidth; - - /* get recommended width of a small icon */ - nSmallIconWidth = GetSystemMetrics(SM_CXSMICON); - - /* calculate index */ - nItemCountPerColumn = LISTVIEW_GetItemCountPerColumn(hwnd); - nItem = (nColumn * nItemCountPerColumn + LISTVIEW_GetFirstVisibleItem(hwnd) - + nRow); - - /* verify existance of item */ - if (nItem < infoPtr->nItemCount) - { - /* get item */ - lpItem = (LISTVIEW_ITEM *)DPA_GetPtr(infoPtr->hdpaItems, nItem); - if (lpItem != NULL) - { - if (infoPtr->himlState != NULL) - { - nPosX += nSmallIconWidth; - if (nOffset <= nPosX) - { - lpHitTestInfo->flags = LVHT_ONITEMSTATEICON | LVHT_ONITEM; - lpHitTestInfo->iItem = nItem; - lpHitTestInfo->iSubItem = 0; - return nItem; - } - } - - if (infoPtr->himlSmall != NULL) - { - nPosX += nSmallIconWidth; - if (nOffset <= nPosX) -{ - lpHitTestInfo->flags = LVHT_ONITEMICON | LVHT_ONITEM; - lpHitTestInfo->iItem = nItem; - lpHitTestInfo->iSubItem = 0; - return nItem; - } - } - - /* get width of label in pixels */ - nLabelWidth = SendMessageA(hwnd, LVM_GETSTRINGWIDTHA, (WPARAM)0, - (LPARAM)lpItem->pszText); - nLabelWidth += nPosX; - - if (nOffset <= nLabelWidth) - { - lpHitTestInfo->flags = LVHT_ONITEMLABEL | LVHT_ONITEM; - lpHitTestInfo->iItem = nItem; - lpHitTestInfo->iSubItem = 0; - return nItem; - } - } - } - - /* hit is not on an item */ - lpHitTestInfo->flags = LVHT_NOWHERE; - - return -1; -} - /*** * DESCRIPTION: * Determines wich listview item is located at the specified position. * * PARAMETER(S): - * [I] HWND32 : window handle + * [I] HWND : window handle * [IO} LPLVHITTESTINFO : hit test information * * RETURN: @@ -2139,24 +3496,68 @@ static LRESULT HitTestListView(HWND hwnd, LPLVHITTESTINFO lpHitTestInfo) */ static LRESULT LISTVIEW_HitTest(HWND hwnd, LPLVHITTESTINFO lpHitTestInfo) { + LISTVIEW_INFO *infoPtr = (LISTVIEW_INFO *)GetWindowLongA(hwnd, 0); LONG lStyle = GetWindowLongA(hwnd, GWL_STYLE); + INT nColumn; + INT nRow; + INT nTopIndex; + INT nItem = -1; - if (lStyle & LVS_LIST) - return HitTestListView(hwnd, lpHitTestInfo); - else if (lStyle & LVS_REPORT) + lpHitTestInfo->flags = 0; + if (infoPtr->rcList.left > lpHitTestInfo->pt.x) { - /* TO DO */ + lpHitTestInfo->flags = LVHT_TOLEFT; } - else if (lStyle & LVS_SMALLICON) + else if (infoPtr->rcList.right < lpHitTestInfo->pt.x) { - return HitTestSmallIconView(hwnd, lpHitTestInfo); + lpHitTestInfo->flags = LVHT_TORIGHT; } - else if (lStyle & LVS_ICON) + + if (infoPtr->rcList.top > lpHitTestInfo->pt.y) { - /* TO DO */ + lpHitTestInfo->flags |= LVHT_ABOVE; + } + else if (infoPtr->rcList.bottom < lpHitTestInfo->pt.y) + { + lpHitTestInfo->flags |= LVHT_BELOW; } - return -1; + if (lpHitTestInfo->flags == 0) + { + switch (LVS_TYPEMASK & lStyle) + { + case LVS_LIST: + /* get current column */ + nColumn = lpHitTestInfo->pt.x / infoPtr->nColumnWidth; + + /* get current row */ + nRow = lpHitTestInfo->pt.y / infoPtr->nItemHeight; + + /* get the index of the first visible item */ + nTopIndex = ListView_GetTopIndex(hwnd); + + nItem = nColumn * infoPtr->nCountPerColumn + nTopIndex + nRow; + nItem = LISTVIEW_HitTestItem(hwnd, nItem, lpHitTestInfo); + break; + + case LVS_REPORT: + /* get current row */ + nRow = ((lpHitTestInfo->pt.y - infoPtr->rcList.top) / + infoPtr->nItemHeight); + + /* get the index of the first visible item */ + nTopIndex = ListView_GetTopIndex(hwnd); + + nItem = nTopIndex + nRow; + nItem = LISTVIEW_HitTestItem(hwnd, nItem, lpHitTestInfo); + break; + + default: +/* nItem = LISTVIEW_HitTestItem(hwnd, nItem, lpHitTestInfo); */ + } + } + + return nItem; } /*** @@ -2164,223 +3565,202 @@ static LRESULT LISTVIEW_HitTest(HWND hwnd, LPLVHITTESTINFO lpHitTestInfo) * Inserts a new column. * * PARAMETER(S): - * [I] HWND32 : window handle - * [I] INT32 : column index - * [I] LPLVCOLUMN32A : column information + * [I] HWND : window handle + * [I] INT : column index + * [I] LPLVCOLUMNA : column information * * RETURN: * SUCCESS : new column index * FAILURE : -1 */ -static LRESULT LISTVIEW_InsertColumnA(HWND hwnd, INT nIndex, +static LRESULT LISTVIEW_InsertColumnA(HWND hwnd, INT nColumn, LPLVCOLUMNA lpColumn) { - LISTVIEW_INFO *infoPtr = (LISTVIEW_INFO*)GetWindowLongA(hwnd, 0); - HDITEMA hdi; - INT nResult; + LISTVIEW_INFO *infoPtr = (LISTVIEW_INFO *)GetWindowLongA(hwnd, 0); + HDITEMA hdi; + INT nNewColumn = -1; - if ((lpColumn == NULL) || (infoPtr->nItemCount > 0)) - return -1; - - FIXME (listview, "(%d %p): semi stub!\n", nIndex, lpColumn); - - /* initialize memory */ - ZeroMemory (&hdi, sizeof(HDITEMA)); - - if (lpColumn->mask & LVCF_FMT) + if (lpColumn != NULL) { - if (nIndex == 0) - hdi.fmt |= HDF_LEFT; - else if (lpColumn->fmt & LVCFMT_LEFT) - hdi.fmt |= HDF_LEFT; - else if (lpColumn->fmt & LVCFMT_RIGHT) - hdi.fmt |= HDF_RIGHT; - else if (lpColumn->fmt & LVCFMT_CENTER) - hdi.fmt |= HDF_CENTER; - if (lpColumn->fmt & LVCFMT_COL_HAS_IMAGES) - hdi.fmt |= HDF_IMAGE; - - hdi.mask |= HDI_FORMAT; + /* initialize memory */ + ZeroMemory(&hdi, sizeof(HDITEMA)); + + if (lpColumn->mask & LVCF_FMT) + { + /* format member is valid */ + hdi.mask |= HDI_FORMAT; + + /* set text alignment (leftmost column must be left-aligned) */ + if (nColumn == 0) + { + hdi.fmt |= HDF_LEFT; + } + else + { + if (lpColumn->fmt & LVCFMT_LEFT) + { + hdi.fmt |= HDF_LEFT; + } + else if (lpColumn->fmt & LVCFMT_RIGHT) + { + hdi.fmt |= HDF_RIGHT; + } + else if (lpColumn->fmt & LVCFMT_CENTER) + { + hdi.fmt |= HDF_CENTER; + } + } + + if (lpColumn->fmt & LVCFMT_BITMAP_ON_RIGHT) + { + hdi.fmt |= HDF_BITMAP_ON_RIGHT; + /* ??? */ + } + + if (lpColumn->fmt & LVCFMT_COL_HAS_IMAGES) + { + /* ??? */ + } + + if (lpColumn->fmt & LVCFMT_IMAGE) + { + hdi.fmt |= HDF_IMAGE; + hdi.iImage = I_IMAGECALLBACK; + } } - if (lpColumn->mask & LVCF_WIDTH) - { - hdi.mask |= HDI_WIDTH; - hdi.cxy = lpColumn->cx; + if (lpColumn->mask & LVCF_WIDTH) + { + hdi.mask |= HDI_WIDTH; + hdi.cxy = lpColumn->cx; } - - if (lpColumn->mask & LVCF_TEXT) - { - hdi.mask |= (HDI_TEXT | HDI_FORMAT); - hdi.pszText = lpColumn->pszText; - hdi.fmt |= HDF_STRING; + + if (lpColumn->mask & LVCF_TEXT) + { + hdi.mask |= HDI_TEXT | HDI_FORMAT; + hdi.pszText = lpColumn->pszText; + hdi.cchTextMax = lstrlenA(lpColumn->pszText); + hdi.fmt |= HDF_STRING; + } + + if (lpColumn->mask & LVCF_IMAGE) + { + hdi.mask |= HDI_IMAGE; + hdi.iImage = lpColumn->iImage; } - if (lpColumn->mask & LVCF_IMAGE) - { - hdi.mask |= HDI_IMAGE; - hdi.iImage = lpColumn->iImage; + if (lpColumn->mask & LVCF_ORDER) + { + hdi.mask |= HDI_ORDER; + hdi.iOrder = lpColumn->iOrder; } - if (lpColumn->mask & LVCF_ORDER) - { - hdi.mask |= HDI_ORDER; - hdi.iOrder = lpColumn->iOrder; - } + /* insert item in header control */ + nNewColumn = SendMessageA(infoPtr->hwndHeader, HDM_INSERTITEMA, + (WPARAM)nColumn, (LPARAM)&hdi); - nResult = SendMessageA (infoPtr->hwndHeader, HDM_INSERTITEMA, - (WPARAM)nIndex, (LPARAM)&hdi); - if (nResult == -1) - return -1; + LISTVIEW_SetScroll(hwnd); + InvalidateRect(hwnd, NULL, FALSE); + } - /* increment column counter */ - infoPtr->nColumnCount++; - - return nResult; + return nNewColumn; } -/* << LISTVIEW_InsertColumn32W >> */ +/* << LISTVIEW_InsertColumnW >> */ /*** * DESCRIPTION: * Inserts a new item in the listview control. * * PARAMETER(S): - * [I] HWND32 : window handle - * [I] LPLVITEM32A : item information + * [I] HWND : window handle + * [I] LPLVITEMA : item information * * RETURN: * SUCCESS : new item index * FAILURE : -1 */ -static LRESULT LISTVIEW_InsertItemA(HWND hwnd, LPLVITEMA lpItem) +static LRESULT LISTVIEW_InsertItemA(HWND hwnd, LPLVITEMA lpLVItem) { LISTVIEW_INFO *infoPtr = (LISTVIEW_INFO *)GetWindowLongA(hwnd, 0); - LONG lStyle = GetWindowLongA(hwnd, GWL_STYLE); LONG lCtrlId = GetWindowLongA(hwnd, GWL_ID); - LISTVIEW_ITEM *lpListItem; - INT nItem; - NMLISTVIEW nmlv; - LVITEMA lvItem; - INT nColumnWidth = 0; - INT nSmallIconWidth; + NMLISTVIEW nmlv; + INT nItem = -1; + HDPA hdpaSubItems; + LISTVIEW_ITEM *lpItem = NULL; - if (lpItem == NULL) - return -1; - - if (lpItem->iSubItem != 0) - return -1; - - /* allocate memory */ - lpListItem = (LISTVIEW_ITEM *)COMCTL32_Alloc(sizeof(LISTVIEW_ITEM)); - if (lpListItem == NULL) - return -1; - - nSmallIconWidth = GetSystemMetrics(SM_CXSMICON); - - /* initialize listview control item */ - ZeroMemory(lpListItem, sizeof(LISTVIEW_ITEM)); - - /* copy only valid data */ - if (lpItem->mask & LVIF_TEXT) + if (lpLVItem != NULL) { - if (lpItem->pszText == LPSTR_TEXTCALLBACKA) + /* make sure it's not a subitem; cannot insert a subitem */ + if (lpLVItem->iSubItem == 0) { - if ((lStyle & LVS_SORTASCENDING) || (lStyle & LVS_SORTDESCENDING)) - return -1; + lpItem = (LISTVIEW_ITEM *)COMCTL32_Alloc(sizeof(LISTVIEW_ITEM)); + if (lpItem != NULL) + { + ZeroMemory(lpItem, sizeof(LISTVIEW_ITEM)); + if (LISTVIEW_InitItem(hwnd, lpItem, lpLVItem) == TRUE) + { + /* insert item in listview control data structure */ + hdpaSubItems = DPA_Create(8); + if (hdpaSubItems != NULL) + { + nItem = DPA_InsertPtr(hdpaSubItems, 0, lpItem); + if (nItem != -1) + { + nItem = DPA_InsertPtr(infoPtr->hdpaItems, lpLVItem->iItem, + hdpaSubItems); + if (nItem != -1) + { + /* manage item focus */ + if (lpLVItem->mask & LVIF_STATE) + { + if (lpLVItem->stateMask & LVIS_FOCUSED) + { + LISTVIEW_SetItemFocus(hwnd, nItem); + } + } - lpListItem->pszText = LPSTR_TEXTCALLBACKA; - } - else - { - nColumnWidth = SendMessageA(hwnd, LVM_GETSTRINGWIDTHA, - (WPARAM)0, (LPARAM)lpItem->pszText); + /* send LVN_INSERTITEM notification */ + ZeroMemory(&nmlv, sizeof(NMLISTVIEW)); + nmlv.hdr.hwndFrom = hwnd; + nmlv.hdr.idFrom = lCtrlId; + nmlv.hdr.code = LVN_INSERTITEM; + nmlv.iItem = nItem; + nmlv.lParam = lpItem->lParam;; + ListView_LVNotify(GetParent(hwnd), lCtrlId, &nmlv); - /* add padding for separating columns */ - nColumnWidth += 10; - - /* calculate column width; make sure it's at least 96 pixels */ - if (nColumnWidth < 96) - nColumnWidth = 96; - - Str_SetPtrA(&lpListItem->pszText, lpItem->pszText); + /* set scrolling parameters */ + LISTVIEW_SetScroll(hwnd); + + /* refresh client area */ + InvalidateRect(hwnd, NULL, FALSE); + } + } + } + } + } } } - if (lpItem->mask & LVIF_STATE) + /* free memory if unsuccessful */ + if ((nItem == -1) && (lpItem != NULL)) { - if (lpItem->stateMask & LVIS_FOCUSED) - { - /* clear LVIS_FOCUSED states */ - ZeroMemory(&lvItem, sizeof(LVITEMA)); - lvItem.stateMask = LVIS_FOCUSED; - lvItem.state = 0; - SendMessageA(hwnd, LVM_SETITEMSTATE, (WPARAM)-1, (LPARAM)&lvItem); - - /* set focused item index */ - infoPtr->nFocusedItem = lpItem->iItem; - } - - lpListItem->state = lpItem->state & lpItem->stateMask; + COMCTL32_Free(lpItem); } - if (lpItem->mask & LVIF_IMAGE) - lpListItem->iImage = lpItem->iImage; - - if (lpItem->mask & LVIF_PARAM) - lpListItem->lParam = lpItem->lParam; - - if (lpItem->mask & LVIF_INDENT) - lpListItem->iIndent = lpItem->iIndent; - - /* insert item in listview control data structure */ - nItem = DPA_InsertPtr(infoPtr->hdpaItems, lpItem->iItem, lpListItem); - if (nItem == -1) - return -1; - - /* increment item counter */ - infoPtr->nItemCount++; - - /* calculate column width */ - if (infoPtr->himlSmall != NULL) - nColumnWidth += nSmallIconWidth; - - /* calculate column width */ - if (infoPtr->himlState != NULL) - nColumnWidth += nSmallIconWidth; - - /* set column width */ - if (nColumnWidth > infoPtr->nColumnWidth) - infoPtr->nColumnWidth = nColumnWidth; - - /* set drawing data */ - LISTVIEW_SetScroll(hwnd); - - /* send LVN_INSERTITEM notification */ - ZeroMemory (&nmlv, sizeof (NMLISTVIEW)); - nmlv.hdr.hwndFrom = hwnd; - nmlv.hdr.idFrom = lCtrlId; - nmlv.hdr.code = LVN_INSERTITEM; - nmlv.iItem = nItem; - SendMessageA(GetParent (hwnd), WM_NOTIFY, (WPARAM)lCtrlId, - (LPARAM)&nmlv); - - InvalidateRect(hwnd, NULL, FALSE); - UpdateWindow(hwnd); - return nItem; } -/* << LISTVIEW_InsertItem32W >> */ +/* << LISTVIEW_InsertItemW >> */ /*** * DESCRIPTION: * Redraws a range of items. * * PARAMETER(S): - * [I] HWND32 : window handle - * [I] INT32 : first item - * [I] INT32 : last item + * [I] HWND : window handle + * [I] INT : first item + * [I] INT : last item * * RETURN: * SUCCESS : TRUE @@ -2389,19 +3769,22 @@ static LRESULT LISTVIEW_InsertItemA(HWND hwnd, LPLVITEMA lpItem) static LRESULT LISTVIEW_RedrawItems(HWND hwnd, INT nFirst, INT nLast) { LISTVIEW_INFO *infoPtr = (LISTVIEW_INFO *)GetWindowLongA(hwnd, 0); + BOOL bResult = FALSE; + RECT rc; - if (nFirst > nLast) - return FALSE; + if (nFirst <= nLast) + { + if ((nFirst >= 0) && (nFirst < GETITEMCOUNT(infoPtr))) + { + if ((nLast >= 0) && (nLast < GETITEMCOUNT(infoPtr))) + { + /* bResult = */ + InvalidateRect(hwnd, &rc, FALSE); + } + } + } - if ((nFirst < 0) || (nFirst >= infoPtr->nItemCount)) - return FALSE; - - if ((nLast < 0) || (nLast >= infoPtr->nItemCount)) - return FALSE; - - /* TO DO */ - - return TRUE; + return bResult; } /*** @@ -2409,9 +3792,9 @@ static LRESULT LISTVIEW_RedrawItems(HWND hwnd, INT nFirst, INT nLast) * Scrolls the content of a listview. * * PARAMETER(S): - * [I] HWND32 : window handle - * [I] INT32 : amount of horizontal scrolling - * [I] INT32 : amount of vertical scrolling + * [I] HWND : window handle + * [I] INT : amount of horizontal scrolling + * [I] INT : amount of vertical scrolling * * RETURN: * SUCCESS : TRUE @@ -2420,39 +3803,57 @@ static LRESULT LISTVIEW_RedrawItems(HWND hwnd, INT nFirst, INT nLast) static LRESULT LISTVIEW_Scroll(HWND hwnd, INT nHScroll, INT nVScroll) { LONG lStyle = GetWindowLongA(hwnd, GWL_STYLE); + INT nScrollPos = 0; BOOL bResult = FALSE; - INT nHScrollPos; INT nMinRange; INT nMaxRange; - if (lStyle & LVS_LIST) + if (lStyle & WS_HSCROLL) { - nHScrollPos = GetScrollPos(hwnd, SB_HORZ); + nScrollPos = GetScrollPos(hwnd, SB_HORZ); GetScrollRange(hwnd, SB_HORZ, &nMinRange, &nMaxRange); + nScrollPos += nHScroll; - if ((nMinRange <= nHScrollPos + nHScroll) && - (nHScrollPos + nHScroll <= nMaxRange)) + if ((LVS_TYPEMASK & lStyle) == LVS_LIST) { - bResult = TRUE; - nHScrollPos += nHScroll; - SetScrollPos(hwnd, SB_HORZ, nHScrollPos, TRUE); - - /* refresh client area */ - InvalidateRect(hwnd, NULL, TRUE); - UpdateWindow(hwnd); + nScrollPos = GetScrollPos(hwnd, SB_HORZ); + GetScrollRange(hwnd, SB_HORZ, &nMinRange, &nMaxRange); + nScrollPos += nHScroll; + if ((nMinRange <= nScrollPos) && (nScrollPos <= nMaxRange)) + { + bResult = TRUE; + SetScrollPos(hwnd, SB_HORZ, nScrollPos, TRUE); + } + } + else + { + /* TO DO */ } - } - else if (lStyle & LVS_REPORT) - { - /* TO DO */ -} - else if (lStyle & LVS_SMALLICON) - { - /* TO DO */ } - else if (lStyle & LVS_ICON) + + if (lStyle & WS_VSCROLL) { - /* TO DO */ + if ((LVS_TYPEMASK & lStyle) == LVS_REPORT) + { + nScrollPos = GetScrollPos(hwnd, SB_VERT); + GetScrollRange(hwnd, SB_VERT, &nMinRange, &nMaxRange); + nScrollPos += nVScroll; + if ((nMinRange <= nScrollPos) && (nScrollPos <= nMaxRange)) + { + bResult = TRUE; + SetScrollPos(hwnd, SB_VERT, nScrollPos, TRUE); + } + } + else + { + /* TO DO */ + } + } + + if (bResult == TRUE) + { + /* refresh client area */ + InvalidateRect(hwnd, NULL, TRUE); } return bResult; @@ -2463,19 +3864,41 @@ static LRESULT LISTVIEW_Scroll(HWND hwnd, INT nHScroll, INT nVScroll) * Sets the background color. * * PARAMETER(S): - * [I] HWND32 : window handle + * [I] HWND : window handle * [I] COLORREF : background color * * RETURN: * SUCCESS : TRUE * FAILURE : FALSE -*/ + */ static LRESULT LISTVIEW_SetBkColor(HWND hwnd, COLORREF clrBk) { LISTVIEW_INFO *infoPtr = (LISTVIEW_INFO *)GetWindowLongA(hwnd, 0); infoPtr->clrBk = clrBk; InvalidateRect(hwnd, NULL, TRUE); + + return TRUE; +} + +/*** + * DESCRIPTION: + * Sets the callback mask. This mask will be used when the parent + * window stores the state information (some or all). + * + * PARAMETER(S): + * [I] HWND : window handle + * [I] UINT : state mask + * + * RETURN: + * SUCCESS : TRUE + * FAILURE : FALSE + */ +static BOOL LISTVIEW_SetCallbackMask(HWND hwnd, UINT uMask) +{ + LISTVIEW_INFO *infoPtr = (LISTVIEW_INFO *)GetWindowLongA(hwnd, 0); + + infoPtr->uCallbackMask = uMask; return TRUE; } @@ -2485,70 +3908,101 @@ static LRESULT LISTVIEW_SetBkColor(HWND hwnd, COLORREF clrBk) * Sets column attributes. * * PARAMETER(S): - * [I] HWND32 : window handle - * [I] INT32 : column index - * [I] LPLVCOLUMN32A : column information + * [I] HWND : window handle + * [I] INT : column index + * [I] LPLVCOLUMNA : column attributes * * RETURN: * SUCCESS : TRUE * FAILURE : FALSE */ -static LRESULT LISTVIEW_SetColumnA(HWND hwnd, INT nIndex, +static LRESULT LISTVIEW_SetColumnA(HWND hwnd, INT nColumn, LPLVCOLUMNA lpColumn) { LISTVIEW_INFO *infoPtr = (LISTVIEW_INFO *)GetWindowLongA(hwnd, 0); - HDITEMA hdi; + HDITEMA hdi; + BOOL bResult = FALSE; - if (lpColumn == NULL) - return -1; - - /* initialize memory */ - ZeroMemory (&hdi, sizeof(HDITEMA)); - - if (lpColumn->mask & LVCF_FMT) + if ((lpColumn != NULL) && (nColumn >= 0) && + (nColumn < Header_GetItemCount(infoPtr->hwndHeader))) { - if (nIndex == 0) - hdi.fmt |= HDF_LEFT; - else if (lpColumn->fmt & LVCFMT_LEFT) - hdi.fmt |= HDF_LEFT; - else if (lpColumn->fmt & LVCFMT_RIGHT) - hdi.fmt |= HDF_RIGHT; - else if (lpColumn->fmt & LVCFMT_CENTER) - hdi.fmt |= HDF_CENTER; + /* initialize memory */ + ZeroMemory(&hdi, sizeof(HDITEMA)); - if (lpColumn->fmt & LVCFMT_COL_HAS_IMAGES) - hdi.fmt |= HDF_IMAGE; - - hdi.mask |= HDI_FORMAT; + if (lpColumn->mask & LVCF_FMT) + { + /* format member is valid */ + hdi.mask |= HDI_FORMAT; + + /* set text alignment (leftmost column must be left-aligned) */ + if (nColumn == 0) + { + hdi.fmt |= HDF_LEFT; + } + else + { + if (lpColumn->fmt & LVCFMT_LEFT) + { + hdi.fmt |= HDF_LEFT; + } + else if (lpColumn->fmt & LVCFMT_RIGHT) + { + hdi.fmt |= HDF_RIGHT; + } + else if (lpColumn->fmt & LVCFMT_CENTER) + { + hdi.fmt |= HDF_CENTER; + } + } + + if (lpColumn->fmt & LVCFMT_BITMAP_ON_RIGHT) + { + hdi.fmt |= HDF_BITMAP_ON_RIGHT; + } + + if (lpColumn->fmt & LVCFMT_COL_HAS_IMAGES) + { + hdi.fmt |= HDF_IMAGE; + } + + if (lpColumn->fmt & LVCFMT_IMAGE) + { + hdi.fmt |= HDF_IMAGE; + hdi.iImage = I_IMAGECALLBACK; + } } - if (lpColumn->mask & LVCF_WIDTH) - { - hdi.mask |= HDI_WIDTH; - hdi.cxy = lpColumn->cx; + if (lpColumn->mask & LVCF_WIDTH) + { + hdi.mask |= HDI_WIDTH; + hdi.cxy = lpColumn->cx; } - if (lpColumn->mask & LVCF_TEXT) - { - hdi.mask |= (HDI_TEXT | HDI_FORMAT); - hdi.pszText = lpColumn->pszText; - hdi.fmt |= HDF_STRING; + if (lpColumn->mask & LVCF_TEXT) + { + hdi.mask |= HDI_TEXT | HDI_FORMAT; + hdi.pszText = lpColumn->pszText; + hdi.cchTextMax = lstrlenA(lpColumn->pszText); + hdi.fmt |= HDF_STRING; + } + + if (lpColumn->mask & LVCF_IMAGE) + { + hdi.mask |= HDI_IMAGE; + hdi.iImage = lpColumn->iImage; } - if (lpColumn->mask & LVCF_IMAGE) - { - hdi.mask |= HDI_IMAGE; - hdi.iImage = lpColumn->iImage; + if (lpColumn->mask & LVCF_ORDER) + { + hdi.mask |= HDI_ORDER; + hdi.iOrder = lpColumn->iOrder; } - if (lpColumn->mask & LVCF_ORDER) - { - hdi.mask |= HDI_ORDER; - hdi.iOrder = lpColumn->iOrder; - } - - return (LRESULT)SendMessageA (infoPtr->hwndHeader, HDM_SETITEMA, - (WPARAM)nIndex, (LPARAM)&hdi); + /* set header item attributes */ + bResult = Header_SetItemA(infoPtr->hwndHeader, nColumn, &hdi); + } + + return bResult; } /*** @@ -2556,36 +4010,38 @@ static LRESULT LISTVIEW_SetColumnA(HWND hwnd, INT nIndex, * Sets image list. * * PARAMETER(S): - * [I] HWND32 : window handle - * [I] INT32 : image list type + * [I] HWND : window handle + * [I] INT : image list type * [I] HIMAGELIST : image list handle * * RETURN: * SUCCESS : old image list * FAILURE : NULL -*/ + */ static LRESULT LISTVIEW_SetImageList(HWND hwnd, INT nType, HIMAGELIST himl) { LISTVIEW_INFO *infoPtr = (LISTVIEW_INFO *)GetWindowLongA(hwnd, 0); - HIMAGELIST himlTemp = 0; + HIMAGELIST himlTemp = 0; switch (nType) { - case LVSIL_NORMAL: - himlTemp = infoPtr->himlNormal; + case LVSIL_NORMAL: + himlTemp = infoPtr->himlNormal; infoPtr->himlNormal = himl; - return (LRESULT)himlTemp; - case LVSIL_SMALL: - himlTemp = infoPtr->himlSmall; - infoPtr->himlSmall = himl; - return (LRESULT)himlTemp; - case LVSIL_STATE: - himlTemp = infoPtr->himlState; - infoPtr->himlState = himl; - return (LRESULT)himlTemp; - } + return (LRESULT)himlTemp; - return (LRESULT)NULL; + case LVSIL_SMALL: + himlTemp = infoPtr->himlSmall; + infoPtr->himlSmall = himl; + return (LRESULT)himlTemp; + + case LVSIL_STATE: + himlTemp = infoPtr->himlState; + infoPtr->himlState = himl; + return (LRESULT)himlTemp; + } + + return (LRESULT)NULL; } @@ -2594,120 +4050,64 @@ static LRESULT LISTVIEW_SetImageList(HWND hwnd, INT nType, HIMAGELIST himl) * Sets item attributes. * * PARAMETER(S): - * [I] HWND32 : window handle - * [I] LPLVITEM32 : item information + * [I] HWND : window handle + * [I] LPLVITEM : item information * * RETURN: * SUCCESS : TRUE * FAILURE : FALSE */ -static LRESULT LISTVIEW_SetItemA(HWND hwnd, LPLVITEMA lpItem) +static LRESULT LISTVIEW_SetItemA(HWND hwnd, LPLVITEMA lpLVItem) { LISTVIEW_INFO *infoPtr = (LISTVIEW_INFO *)GetWindowLongA(hwnd, 0); - LONG lCtrlId = GetWindowLongA(hwnd, GWL_ID); - LISTVIEW_ITEM *lpListItem; - NMLISTVIEW nmlv; + BOOL bResult = FALSE; - if (lpItem == NULL) - return FALSE; - - if ((lpItem->iItem < 0) || (lpItem->iItem >= infoPtr->nItemCount)) - return FALSE; - - /* send LVN_ITEMCHANGING notification */ - ZeroMemory (&nmlv, sizeof (NMLISTVIEW)); - nmlv.hdr.hwndFrom = hwnd; - nmlv.hdr.idFrom = lCtrlId; - nmlv.hdr.code = LVN_ITEMCHANGING; - nmlv.iItem = lpItem->iItem; - nmlv.iSubItem = lpItem->iSubItem; - nmlv.uChanged = lpItem->mask; - if (SendMessageA(GetParent(hwnd), WM_NOTIFY, (WPARAM)lCtrlId, - (LPARAM)&nmlv) == FALSE) - return FALSE; - - /* get item */ - lpListItem = DPA_GetPtr(infoPtr->hdpaItems, lpItem->iItem); - if (lpListItem == NULL) - return FALSE; - - /* copy valid data */ - if (lpItem->iSubItem > 0) + if (lpLVItem != NULL) { - /* verify existance of sub-item */ - lpListItem += lpItem->iSubItem; - if (lpListItem == NULL) - return FALSE; - - /* exit if indent attribute is valid */ - if (lpItem->mask & LVIF_INDENT) - return FALSE; - - if (lpItem->mask & LVIF_IMAGE) + if ((lpLVItem->iItem >= 0) && (lpLVItem->iItem < GETITEMCOUNT(infoPtr))) { - /* set sub-item attribute */ - } - - } - else - { - if (lpItem->mask & LVIF_STATE) - { - lpListItem->state &= ~lpItem->stateMask; - lpListItem->state |= (lpItem->state & lpItem->stateMask); - } - - if (lpItem->mask & LVIF_IMAGE) - lpListItem->iImage = lpItem->iImage; - - if (lpItem->mask & LVIF_PARAM) - lpListItem->lParam = lpItem->lParam; - - if (lpItem->mask & LVIF_INDENT) - lpListItem->iIndent = lpItem->iIndent; - } - - if (lpItem->mask & LVIF_TEXT) - { - if (lpItem->pszText == LPSTR_TEXTCALLBACKA) - { - if ((lpListItem->pszText != NULL) && - (lpListItem->pszText != LPSTR_TEXTCALLBACKA)) - COMCTL32_Free (lpListItem->pszText); - - lpListItem->pszText = LPSTR_TEXTCALLBACKA; - } - else - { - if (lpListItem->pszText == LPSTR_TEXTCALLBACKA) - lpListItem->pszText = NULL; - - if (Str_SetPtrA(&lpListItem->pszText, lpItem->pszText) == FALSE) - return FALSE; + if (lpLVItem->iSubItem == 0) + { + bResult = LISTVIEW_SetItem(hwnd, lpLVItem); + } + else + { + bResult = LISTVIEW_SetSubItem(hwnd, lpLVItem); + } } } - /* send LVN_ITEMCHANGED notification */ - nmlv.hdr.code = LVN_ITEMCHANGED; - SendMessageA(GetParent(hwnd), WM_NOTIFY, (WPARAM)lCtrlId, - (LPARAM)&nmlv); - return TRUE; + return bResult; } -/* << LISTVIEW_SetItem32W >> */ +/* << LISTVIEW_SetItemW >> */ -/* LISTVIEW_SetItemCount*/ +/*** + * DESCRIPTION: + * Preallocates memory. + * + * PARAMETER(S): + * [I] HWND : window handle + * [I] INT : item count (prjected number of items) + * + * RETURN: + * None + */ +static VOID LISTVIEW_SetItemCount(HWND hwnd, INT nItemCount) +{ + /* TO DO */ +} /*** * DESCRIPTION: * Sets item position. * * PARAMETER(S): - * [I] HWND32 : window handle - * [I] INT32 : item index - * [I] INT32 : x coordinate - * [I] INT32 : y coordinate + * [I] HWND : window handle + * [I] INT : item index + * [I] INT : x coordinate + * [I] INT : y coordinate * * RETURN: * SUCCESS : TRUE @@ -2718,27 +4118,18 @@ static LRESULT LISTVIEW_SetItemPosition(HWND hwnd, INT nItem, { LISTVIEW_INFO *infoPtr = (LISTVIEW_INFO*)GetWindowLongA(hwnd, 0); LONG lStyle = GetWindowLongA(hwnd, GWL_STYLE); + BOOL bResult = FALSE; - if ((nItem < 0) || (nItem >= infoPtr->nItemCount)) - return FALSE; - - if ((lStyle & LVS_ICON) && (lStyle & LVS_SMALLICON)) + if ((nItem >= 0) || (nItem < GETITEMCOUNT(infoPtr))) { - /* get item */ - - /* set position of item */ - - /* refresh */ - if (lStyle & LVS_AUTOARRANGE) + if (((lStyle & LVS_TYPEMASK) == LVS_ICON) || + ((lStyle & LVS_TYPEMASK) == LVS_SMALLICON)) { - InvalidateRect(hwnd, NULL, FALSE); - UpdateWindow(hwnd); + /* TO DO */ } + } - return TRUE; -} - - return FALSE; + return bResult; } /*** @@ -2746,48 +4137,84 @@ static LRESULT LISTVIEW_SetItemPosition(HWND hwnd, INT nItem, * Sets the state of one or many items. * * PARAMETER(S): - * [I] HWND32 : window handle - * [I]INT32 : item index - * [I] LPLVITEM32 : item information + * [I] HWND : window handle + * [I]INT : item index + * [I] LPLVITEM : item or subitem info * * RETURN: * SUCCESS : TRUE * FAILURE : FALSE -*/ + */ static LRESULT LISTVIEW_SetItemState(HWND hwnd, INT nItem, - LPLVITEMA lpItem) + LPLVITEMA lpLVItem) { LISTVIEW_INFO *infoPtr = (LISTVIEW_INFO *)GetWindowLongA(hwnd, 0); - LISTVIEW_ITEM *lpListItem; + BOOL bResult = FALSE; + LVITEMA lvItem; INT i; if (nItem == -1) { - /* apply to all the items */ - for (i = 0; i< infoPtr->nItemCount; i++) + bResult = TRUE; + ZeroMemory(&lvItem, sizeof(LVITEMA)); + lvItem.mask = LVIF_STATE; + lvItem.state = lpLVItem->state; + lvItem.stateMask = lpLVItem->stateMask; + + /* apply to all items */ + for (i = 0; i< GETITEMCOUNT(infoPtr); i++) { - lpListItem = (LISTVIEW_ITEM *)DPA_GetPtr(infoPtr->hdpaItems, i); - if (lpListItem == NULL) - return FALSE; - - lpListItem->state &= ~lpItem->stateMask; - lpListItem->state |= (lpItem->state & lpItem->stateMask); - } - } - else if ((nItem >= 0) && (nItem < infoPtr->nItemCount)) - { - lpListItem = (LISTVIEW_ITEM *)DPA_GetPtr(infoPtr->hdpaItems, nItem); - if (lpListItem == NULL) - return FALSE; - - /* set state */ - lpListItem->state &= ~lpItem->stateMask; - lpListItem->state |= (lpItem->state & lpItem->stateMask); + lvItem.iItem = i; + if (ListView_SetItemA(hwnd, &lvItem) == FALSE) + { + bResult = FALSE; + } } + } else - return FALSE; + { + ZeroMemory(&lvItem, sizeof(LVITEMA)); + lvItem.mask = LVIF_STATE; + lvItem.state = lpLVItem->state; + lvItem.stateMask = lpLVItem->stateMask; + lvItem.iItem = nItem; + bResult = ListView_SetItemA(hwnd, &lvItem); + } - return TRUE; + return bResult; +} + +/*** + * DESCRIPTION: + * Sets the text of an item or subitem. + * + * PARAMETER(S): + * [I] HWND : window handle + * [I] INT : item index + * [I] LPLVITEMA : item or subitem info + * + * RETURN: + * SUCCESS : TRUE + * FAILURE : FALSE + */ +static BOOL LISTVIEW_SetItemTextA(HWND hwnd, INT nItem, + LPLVITEMA lpLVItem) +{ + LISTVIEW_INFO *infoPtr = (LISTVIEW_INFO *)GetWindowLongA(hwnd, 0); + BOOL bResult = FALSE; + LVITEMA lvItem; + + if ((nItem >= 0) && (nItem < GETITEMCOUNT(infoPtr))) + { + ZeroMemory(&lvItem, sizeof(LVITEMA)); + lvItem.mask = LVIF_TEXT; + lvItem.pszText = lpLVItem->pszText; + lvItem.iItem = nItem; + lvItem.iSubItem = lpLVItem->iSubItem; + bResult = ListView_SetItemA(hwnd, &lvItem); + } + + return bResult; } /*** @@ -2795,20 +4222,20 @@ static LRESULT LISTVIEW_SetItemState(HWND hwnd, INT nItem, * Sets the text background color. * * PARAMETER(S): - * [I] HWND32 : window handle + * [I] HWND : window handle * [I] COLORREF : text background color * * RETURN: * SUCCESS : TRUE * FAILURE : FALSE -*/ + */ static LRESULT LISTVIEW_SetTextBkColor(HWND hwnd, COLORREF clrTextBk) { LISTVIEW_INFO *infoPtr = (LISTVIEW_INFO *)GetWindowLongA(hwnd, 0); infoPtr->clrTextBk = clrTextBk; - return TRUE; + return TRUE; } /*** @@ -2816,7 +4243,7 @@ static LRESULT LISTVIEW_SetTextBkColor(HWND hwnd, COLORREF clrTextBk) * Sets the text background color. * * PARAMETER(S): - * [I] HWND32 : window handle + * [I] HWND : window handle * [I] COLORREF : text color * * RETURN: @@ -2829,61 +4256,63 @@ static LRESULT LISTVIEW_SetTextColor (HWND hwnd, COLORREF clrText) infoPtr->clrText = clrText; - return TRUE; + return TRUE; } /*** * DESCRIPTION: - * ?? + * Sort items. * * PARAMETER(S): - * [I] HWND32 : window handle + * [I] HWND : window handle * * RETURN: * SUCCESS : TRUE * FAILURE : FALSE -*/ + */ static LRESULT LISTVIEW_SortItems(HWND hwnd, WPARAM wParam, LPARAM lParam) { -/* LISTVIEW_INFO *infoPtr = (LISTVIEW_INFO*)GetWindowLong32A(hwnd, 0); */ + FIXME (listview, "empty stub!\n"); - FIXME (listview, "empty stub!\n"); - - return TRUE; + return TRUE; } /*** * DESCRIPTION: - * Updates an items. + * Updates an items or rearranges the listview control. * * PARAMETER(S): - * [I] HWND32 : window handle - * [I] INT32 : item index + * [I] HWND : window handle + * [I] INT : item index * * RETURN: * SUCCESS : TRUE * FAILURE : FALSE -*/ + */ static LRESULT LISTVIEW_Update(HWND hwnd, INT nItem) { - LISTVIEW_INFO *infoPtr = (LISTVIEW_INFO*)GetWindowLongA(hwnd, 0); + LISTVIEW_INFO *infoPtr = (LISTVIEW_INFO *)GetWindowLongA(hwnd, 0); LONG lStyle = GetWindowLongA(hwnd, GWL_STYLE); - RECT rcItemRect; BOOL bResult = FALSE; + RECT rc; - if ((nItem >= 0) || (nItem < infoPtr->nItemCount)) + if ((nItem >= 0) && (nItem < GETITEMCOUNT(infoPtr))) { - /* get item bounding rectangle */ - rcItemRect.left = LVIR_BOUNDS; - SendMessageA(hwnd, LVM_GETITEMRECT, (WPARAM)nItem, - (LPARAM)&rcItemRect); - - InvalidateRect(hwnd, &rcItemRect, FALSE); + bResult = TRUE; /* rearrange with default alignment style */ - if ((lStyle & LVS_AUTOARRANGE) && - ((lStyle & LVS_ICON) || (lStyle & LVS_SMALLICON))) - SendMessageA(hwnd, LVM_ARRANGE, (WPARAM)LVA_DEFAULT, (LPARAM)0); + if ((lStyle & LVS_AUTOARRANGE) && (((lStyle & LVS_TYPEMASK) == LVS_ICON) || + ((lStyle & LVS_TYPEMASK) == LVS_SMALLICON))) + { + ListView_Arrange(hwnd, 0); + } + else + { + /* get item bounding rectangle */ + rc.left = LVIR_BOUNDS; + ListView_GetItemRect(hwnd, nItem, &rc); + InvalidateRect(hwnd, &rc, FALSE); + } } return bResult; @@ -2894,7 +4323,7 @@ static LRESULT LISTVIEW_Update(HWND hwnd, INT nItem) * Creates a listview control. * * PARAMETER(S): - * [I] HWND32 : window handle + * [I] HWND : window handle * * RETURN: * Zero @@ -2902,80 +4331,120 @@ static LRESULT LISTVIEW_Update(HWND hwnd, INT nItem) static LRESULT LISTVIEW_Create(HWND hwnd, WPARAM wParam, LPARAM lParam) { LISTVIEW_INFO *infoPtr = (LISTVIEW_INFO *)GetWindowLongA(hwnd, 0); - LONG lStyle = GetWindowLongA(hwnd, GWL_STYLE); + LPCREATESTRUCTA lpcs = (LPCREATESTRUCTA)lParam; LOGFONTA logFont; - HFONT hOldFont; - HDC hdc; - TEXTMETRICA tm; - INT nSmallIconHeight; + HDLAYOUT hl; + WINDOWPOS wp; + + /* determine the type of structures to use */ + infoPtr->notifyFormat = SendMessageA(GetParent(hwnd), WM_NOTIFYFORMAT, + (WPARAM)hwnd, (LPARAM)NF_QUERY); + if (infoPtr->notifyFormat != NFR_ANSI) + { + FIXME (listview, "ANSI notify format is NOT used\n"); + } /* initialize color information */ infoPtr->clrBk = GetSysColor(COLOR_WINDOW); infoPtr->clrText = GetSysColor(COLOR_WINDOWTEXT); infoPtr->clrTextBk = GetSysColor(COLOR_WINDOW); - /* get default font (icon title) */ - SystemParametersInfoA (SPI_GETICONTITLELOGFONT, 0, &logFont, 0); - infoPtr->hDefaultFont = CreateFontIndirectA (&logFont); - infoPtr->hFont = infoPtr->hDefaultFont; + /* set default values */ + infoPtr->uCallbackMask = 0; + infoPtr->nFocusedItem = -1; + infoPtr->nSelectionMark = -1; + infoPtr->iconSize.cx = GetSystemMetrics(SM_CXSMICON); + infoPtr->iconSize.cy = GetSystemMetrics(SM_CYSMICON); + ZeroMemory(&infoPtr->rcList, sizeof(RECT)); - /* initialize column width */ - infoPtr->nColumnWidth = 96; + /* get default font (icon title) */ + SystemParametersInfoA(SPI_GETICONTITLELOGFONT, 0, &logFont, 0); + infoPtr->hDefaultFont = CreateFontIndirectA(&logFont); + infoPtr->hFont = infoPtr->hDefaultFont; + + /* create header */ + infoPtr->hwndHeader = CreateWindowA(WC_HEADERA, (LPCSTR)NULL, + WS_CHILD | HDS_HORZ | HDS_BUTTONS , + 0, 0, 0, 0, hwnd, (HMENU)0, + lpcs->hInstance, NULL); - /* get text height */ - hdc = GetDC(hwnd); - hOldFont = SelectObject(hdc, infoPtr->hFont); - GetTextMetricsA(hdc, &tm); + /* set header font */ + SendMessageA(infoPtr->hwndHeader, WM_SETFONT, (WPARAM)infoPtr->hFont, + (LPARAM)TRUE); - /* initialize item height with padding */ - if (!(lStyle & LVS_ICON)) + switch (lpcs->style & LVS_TYPEMASK) { - nSmallIconHeight = GetSystemMetrics(SM_CYSMICON); - infoPtr->nItemHeight = max(tm.tmHeight, nSmallIconHeight) + 2; + case LVS_REPORT: + /* reset header */ + hl.prc = &infoPtr->rcList; + hl.pwpos = ℘ + Header_Layout(infoPtr->hwndHeader, &hl); + SetWindowPos(infoPtr->hwndHeader, hwnd, wp.x, wp.y, wp.cx, wp.cy, + wp.flags); + + /* set new top coord */ + infoPtr->rcList.top = wp.cy; + + /* display header */ + ShowWindow(infoPtr->hwndHeader, SW_SHOWNORMAL); + break; + + case LVS_LIST: + break; + + default: + /* temporary (until there is support) */ + SetWindowLongA(hwnd, GWL_STYLE, + (lpcs->style & ~LVS_TYPEMASK) | LVS_LIST); } - SelectObject(hdc, hOldFont); - ReleaseDC(hwnd, hdc); - - /* create header */ - infoPtr->hwndHeader = CreateWindowA(WC_HEADERA, "", lStyle, 0, 0, 0, 0, - hwnd, (HMENU)0, - GetWindowLongA(hwnd, GWL_HINSTANCE), - NULL); - /* set header font */ - SendMessageA(infoPtr->hwndHeader, WM_SETFONT, (WPARAM)infoPtr->hFont, - (LPARAM)TRUE); + /* TEMPORARY */ + LISTVIEW_UnsupportedStyles(lpcs->style); /* allocate memory */ - infoPtr->hdpaItems = DPA_Create (10); + infoPtr->hdpaItems = DPA_Create(10); - return 0; + /* set view dependent information */ + LISTVIEW_SetViewInfo(hwnd); + + return 0; } -static LRESULT -LISTVIEW_Destroy (HWND hwnd, WPARAM wParam, LPARAM lParam) +/*** + * DESCRIPTION: + * Destroys the window + * + * PARAMETER(S): + * [I] HWND : window handle + * + * RETURN: + * Zero + */ +static LRESULT LISTVIEW_Destroy(HWND hwnd) { - LISTVIEW_INFO *infoPtr = (LISTVIEW_INFO*)GetWindowLongA(hwnd, 0); + LISTVIEW_INFO *infoPtr = (LISTVIEW_INFO*)GetWindowLongA(hwnd, 0); - /* delete all items */ - LISTVIEW_DeleteAllItems(hwnd); + /* delete all items */ + LISTVIEW_DeleteAllItems(hwnd); - /* destroy dpa */ - DPA_Destroy (infoPtr->hdpaItems); + /* destroy dpa */ + DPA_Destroy(infoPtr->hdpaItems); - /* destroy header */ - if (infoPtr->hwndHeader) - DestroyWindow (infoPtr->hwndHeader); + /* destroy header */ + if (infoPtr->hwndHeader) + { + DestroyWindow(infoPtr->hwndHeader); + } - /* destroy font */ - infoPtr->hFont = (HFONT)0; - if (infoPtr->hDefaultFont) - DeleteObject (infoPtr->hDefaultFont); + /* destroy font */ + infoPtr->hFont = (HFONT)0; + if (infoPtr->hDefaultFont) + { + DeleteObject(infoPtr->hDefaultFont); + } - infoPtr->nColumnWidth = 96; - - return 0; + return 0; } /*** @@ -2983,26 +4452,28 @@ LISTVIEW_Destroy (HWND hwnd, WPARAM wParam, LPARAM lParam) * Erases the background of the listview control * * PARAMETER(S): - * [I] HWND32 : window handle - * + * [I] HWND : window handle + * [I] WPARAM : device context handle + * [I] LPARAM : not used + * * RETURN: * SUCCESS : TRUE * FAILURE : FALSE */ -static LRESULT LISTVIEW_EraseBackground(HWND hwnd, WPARAM wParam, LPARAM lParam) +static LRESULT LISTVIEW_EraseBackground(HWND hwnd, WPARAM wParam, + LPARAM lParam) { LISTVIEW_INFO *infoPtr = (LISTVIEW_INFO *)GetWindowLongA(hwnd, 0); BOOL bResult; if (infoPtr->clrBk == CLR_NONE) + { bResult = SendMessageA(GetParent(hwnd), WM_ERASEBKGND, wParam, lParam); + } else { HBRUSH hBrush = CreateSolidBrush(infoPtr->clrBk); - RECT clientRect; - - GetClientRect(hwnd, &clientRect); - FillRect((HDC)wParam, &clientRect, hBrush); + FillRect((HDC)wParam, &infoPtr->rcList, hBrush); DeleteObject(hBrush); bResult = TRUE; } @@ -3015,7 +4486,7 @@ static LRESULT LISTVIEW_EraseBackground(HWND hwnd, WPARAM wParam, LPARAM lParam) * Gets the listview control font. * * PARAMETER(S): - * [I] HWND32 : window handle + * [I] HWND : window handle * * RETURN: * Font handle. @@ -3032,55 +4503,210 @@ static LRESULT LISTVIEW_GetFont(HWND hwnd) * Performs horizontal scrolling. * * PARAMETER(S): - * [I] HWND32 : window handle - * [I] INT32 : scroll code - * [I] INT32 : scroll position - * [I] HWND32 : scrollbar control window handle + * [I] HWND : window handle + * [I] INT : scroll code + * [I] INT : scroll position + * [I] HWND : scrollbar control window handle + * + * RETURN: + * Zero + */ +static LRESULT LISTVIEW_VScroll(HWND hwnd, INT nScrollCode, + INT nScroll, HWND hScrollWnd) +{ + LISTVIEW_INFO *infoPtr = (LISTVIEW_INFO *)GetWindowLongA(hwnd, 0); + LONG lStyle = GetWindowLongA(hwnd, GWL_STYLE); + INT nScrollPos, nOldScrollPos; + INT nMinRange; + INT nMaxRange; + + GetScrollRange(hwnd, SB_VERT, &nMinRange, &nMaxRange); + nOldScrollPos = nScrollPos = GetScrollPos(hwnd, SB_VERT); + + switch (LVS_TYPEMASK & lStyle) + { + case LVS_REPORT: + switch (nScrollCode) + { + case SB_LINEUP: + if (nScrollPos > nMinRange) + { + nScrollPos--; + } + break; + case SB_LINEDOWN: + if (nScrollPos < nMaxRange) + { + nScrollPos++; + } + break; + case SB_PAGEUP: + if (nScrollPos > nMinRange + infoPtr->nCountPerColumn) + { + nScrollPos -= infoPtr->nCountPerColumn; + } + else + { + nScrollPos = nMinRange; + } + break; + case SB_PAGEDOWN: + if (nScrollPos < nMaxRange - infoPtr->nCountPerColumn) + { + nScrollPos += infoPtr->nCountPerColumn; + } + else + { + nScrollPos = nMaxRange; + } + break; + case SB_THUMBPOSITION: + nScrollPos = nScroll; + break; + } + break; + + default: + /* TO DO */ + } + + /* set new scroll position */ + if (nScrollPos != nOldScrollPos) + { + SetScrollPos(hwnd, SB_VERT, nScrollPos, TRUE); + + /* refresh client area */ + InvalidateRect(hwnd, NULL, TRUE); + } + + return 0; +} + + +/*** + * DESCRIPTION: + * Performs horizontal scrolling. + * + * PARAMETER(S): + * [I] HWND : window handle + * [I] INT : scroll code + * [I] INT : scroll position + * [I] HWND : scrollbar control window handle * * RETURN: * Zero */ static LRESULT LISTVIEW_HScroll(HWND hwnd, INT nScrollCode, - INT nScrollPos, HWND hScrollWnd) + INT nScroll, HWND hScrollWnd) { + LISTVIEW_INFO *infoPtr = (LISTVIEW_INFO *)GetWindowLongA(hwnd, 0); LONG lStyle = GetWindowLongA(hwnd, GWL_STYLE); - INT nHScrollPos; + INT nScrollPos, nOldScrollPos; INT nMinRange; INT nMaxRange; GetScrollRange(hwnd, SB_HORZ, &nMinRange, &nMaxRange); - nHScrollPos = GetScrollPos(hwnd, SB_HORZ); + nOldScrollPos = nScrollPos = GetScrollPos(hwnd, SB_HORZ); - if (lStyle & LVS_LIST) + switch (LVS_TYPEMASK & lStyle) { + case LVS_LIST: + + /* list display mode horizontal scrolling */ switch (nScrollCode) { case SB_LINELEFT: - if (nHScrollPos > nMinRange) - nHScrollPos--; + if (nScrollPos > nMinRange) + { + nScrollPos--; + } break; case SB_LINERIGHT: - if (nHScrollPos < nMaxRange) - nHScrollPos++; + if (nScrollPos < nMaxRange) + { + nScrollPos++; + } break; case SB_PAGELEFT: - if (nHScrollPos > nMinRange) - nHScrollPos--; + if (nScrollPos > nMinRange) + { + nScrollPos = max(nMinRange, nScrollPos - infoPtr->nCountPerRow); + } + else + { + nScrollPos = nMinRange; + } break; case SB_PAGERIGHT: - if (nHScrollPos < nMaxRange) - nHScrollPos++; + if (nScrollPos < nMaxRange - 1) + { + nScrollPos = min(nMaxRange, nScrollPos + infoPtr->nCountPerRow); + } + else + { + nScrollPos = nMaxRange; + } break; case SB_THUMBPOSITION: - nHScrollPos = nScrollPos; - break; + nScrollPos = nScroll; + break; } + break; - SetScrollPos(hwnd, SB_HORZ, nHScrollPos, TRUE); + case LVS_REPORT: + + /* report/details display mode horizontal scrolling */ + switch (nScrollCode) + { + case SB_LINELEFT: + if (nScrollPos > nMinRange) + { + nScrollPos--; + } + break; + case SB_LINERIGHT: + if (nScrollPos < nMaxRange) + { + nScrollPos++; + } + break; + case SB_PAGELEFT: + if (nScrollPos > nMinRange) + { + nScrollPos = max(nMinRange, nScrollPos - infoPtr->rcList.right); + } + else + { + nScrollPos = nMinRange; + } + break; + case SB_PAGERIGHT: + if (nScrollPos < nMaxRange) + { + nScrollPos = min(nMaxRange, nScrollPos + infoPtr->rcList.right); + } + else + { + nScrollPos = nMaxRange; + } + break; + case SB_THUMBPOSITION: + nScrollPos = nScroll; + break; + } + break; + + default: + /* TO DO */ + } + + /* set new scroll position */ + if (nScrollPos != nOldScrollPos) + { + SetScrollPos(hwnd, SB_HORZ, nScrollPos, TRUE); /* refresh client area */ InvalidateRect(hwnd, NULL, TRUE); - UpdateWindow(hwnd); } return 0; @@ -3088,11 +4714,11 @@ static LRESULT LISTVIEW_HScroll(HWND hwnd, INT nScrollCode, /*** * DESCRIPTION: - * ????? + * ??? * * PARAMETER(S): - * [I] HWND32 : window handle - * [I] INT32 : virtual key + * [I] HWND : window handle + * [I] INT : virtual key * [I] LONG : key data * * RETURN: @@ -3102,173 +4728,125 @@ static LRESULT LISTVIEW_KeyDown(HWND hwnd, INT nVirtualKey, LONG lKeyData) { LISTVIEW_INFO *infoPtr = (LISTVIEW_INFO *)GetWindowLongA(hwnd, 0); LONG lStyle = GetWindowLongA(hwnd, GWL_STYLE); - LONG lCtrlId = GetWindowLongA(hwnd, GWL_ID); + INT nCtrlId = GetWindowLongA(hwnd, GWL_ID); HWND hwndParent = GetParent(hwnd); - INT nItemCountPerColumn; - INT nItemCountPerRow; + NMLVKEYDOWN nmKeyDown; NMHDR nmh; - INT nColumn; -/* NMLVKEYDOWN nmKeyDown; */ /* send LVN_KEYDOWN notification */ -/* nmh.hwndFrom = hwnd; */ -/* nmh.idFrom = lCtrlId; */ -/* nmh.code = LVN_KEYDOWN; */ -/* nmKeyDown.hdr = nmh; */ -/* nmKeyDown..wVKey = nVirtualKey; */ -/* nmKeyCode.flags = 0; */ -/* SendMessage32A(hwndParent, WM_NOTIFY, (WPARAM32)lCtrlId, (LPARAM)&nmKeyDown); */ + ZeroMemory(&nmKeyDown, sizeof(NMLVKEYDOWN)); + nmKeyDown.hdr.hwndFrom = hwnd; + nmKeyDown.hdr.idFrom = nCtrlId; + nmKeyDown.hdr.code = LVN_KEYDOWN; + nmKeyDown.wVKey = nVirtualKey; + nmKeyDown.flags = 0; + SendMessageA(hwndParent, WM_NOTIFY, (WPARAM)nCtrlId, (LPARAM)&nmKeyDown); + + /* initialize */ + nmh.hwndFrom = hwnd; + nmh.idFrom = nCtrlId; switch (nVirtualKey) { case VK_RETURN: - if ((infoPtr->nItemCount > 0) && (infoPtr->nFocusedItem != -1)) + if ((GETITEMCOUNT(infoPtr) > 0) && (infoPtr->nFocusedItem != -1)) { /* send NM_RETURN notification */ nmh.code = NM_RETURN; - SendMessageA(hwndParent, WM_NOTIFY, (WPARAM)lCtrlId, (LPARAM)&nmh); + ListView_Notify(hwndParent, nCtrlId, &nmh); /* send LVN_ITEMACTIVATE notification */ nmh.code = LVN_ITEMACTIVATE; - SendMessageA(hwndParent, WM_NOTIFY, (WPARAM)lCtrlId, (LPARAM)&nmh); + ListView_Notify(hwndParent, nCtrlId, &nmh); } break; case VK_HOME: - if (infoPtr->nItemCount > 0) + if (GETITEMCOUNT(infoPtr) > 0) { - /* set item state(s) */ - infoPtr->nFocusedItem = 0; - LISTVIEW_SetItemStates(hwnd, infoPtr->nFocusedItem, TRUE, FALSE); - - /* make item visible */ - LISTVIEW_SetVisible(hwnd, infoPtr->nFocusedItem); + LISTVIEW_KeySelection(hwnd, 0); } break; case VK_END: - if (infoPtr->nItemCount > 0) -{ - /* set item state(s) */ - infoPtr->nFocusedItem = infoPtr->nItemCount - 1; - LISTVIEW_SetItemStates(hwnd, infoPtr->nFocusedItem, TRUE, FALSE); - - /* make item visible */ - LISTVIEW_SetVisible(hwnd, infoPtr->nFocusedItem); + if (GETITEMCOUNT(infoPtr) > 0) + { + LISTVIEW_KeySelection(hwnd, GETITEMCOUNT(infoPtr) - 1); } - break; case VK_LEFT: - if (lStyle & LVS_LIST) + switch (LVS_TYPEMASK & lStyle) { - nItemCountPerColumn = LISTVIEW_GetItemCountPerColumn(hwnd); - if (infoPtr->nFocusedItem >= nItemCountPerColumn) + case LVS_LIST: + if (infoPtr->nFocusedItem >= infoPtr->nCountPerColumn) { - /* set item state(s) */ - infoPtr->nFocusedItem -= nItemCountPerColumn; - LISTVIEW_SetItemStates(hwnd, infoPtr->nFocusedItem, TRUE, FALSE); + LISTVIEW_KeySelection(hwnd, infoPtr->nFocusedItem - infoPtr->nCountPerColumn); + } + break; + case LVS_REPORT: + break; - /* make item visible */ - LISTVIEW_SetVisible(hwnd, infoPtr->nFocusedItem); + default: + if (infoPtr->nFocusedItem % infoPtr->nCountPerRow != 0) + { + LISTVIEW_SetSelection(hwnd, infoPtr->nFocusedItem - 1); } } - else if (lStyle & LVS_REPORT) - { - /* TO DO ; does not affect the focused item, it only scrolls */ - } - else if ((lStyle & LVS_SMALLICON) || (lStyle & LVS_ICON)) - { - nItemCountPerRow = LISTVIEW_GetItemCountPerRow(hwnd); - nColumn = infoPtr->nFocusedItem % nItemCountPerRow; - if (nColumn != 0) - { - infoPtr->nFocusedItem -= 1; - LISTVIEW_SetItemStates(hwnd, infoPtr->nFocusedItem, TRUE, FALSE); + break; - /* refresh display */ - InvalidateRect(hwnd, NULL, FALSE); - UpdateWindow(hwnd); + case VK_UP: + switch (LVS_TYPEMASK & lStyle) + { + case LVS_LIST: + case LVS_REPORT: + if (infoPtr->nFocusedItem > 0) + { + LISTVIEW_KeySelection(hwnd, infoPtr->nFocusedItem - 1); + } + break; + + default: + if (infoPtr->nFocusedItem >= infoPtr->nCountPerRow) + { + LISTVIEW_SetSelection(hwnd, infoPtr->nFocusedItem - + infoPtr->nCountPerRow); } } break; - case VK_UP: - if ((lStyle & LVS_LIST) || (lStyle & LVS_REPORT)) + case VK_RIGHT: + switch (LVS_TYPEMASK & lStyle) { - if (infoPtr->nFocusedItem > 0) + case LVS_LIST: + if (infoPtr->nFocusedItem < + (GETITEMCOUNT(infoPtr) - infoPtr->nCountPerColumn)) { - infoPtr->nFocusedItem -= 1; - LISTVIEW_SetItemStates(hwnd, infoPtr->nFocusedItem, TRUE, FALSE); + LISTVIEW_KeySelection(hwnd, infoPtr->nFocusedItem + + infoPtr->nCountPerColumn); + } + case LVS_REPORT: + break; - LISTVIEW_SetVisible(hwnd, infoPtr->nFocusedItem); -} - } - else if ((lStyle & LVS_SMALLICON) || (lStyle & LVS_ICON)) - { - nItemCountPerRow = LISTVIEW_GetItemCountPerRow(hwnd); - if (infoPtr->nFocusedItem >= nItemCountPerRow) + default: + if (infoPtr->nCountPerRow > 0) { - infoPtr->nFocusedItem -= nItemCountPerRow; - LISTVIEW_SetItemStates(hwnd, infoPtr->nFocusedItem, TRUE, FALSE); - - LISTVIEW_SetVisible(hwnd, infoPtr->nFocusedItem); } } break; - case VK_RIGHT: - if (lStyle & LVS_LIST) -{ - nItemCountPerColumn = LISTVIEW_GetItemCountPerColumn(hwnd); - if (infoPtr->nFocusedItem < infoPtr->nItemCount - nItemCountPerColumn) - { - infoPtr->nFocusedItem += nItemCountPerColumn; - LISTVIEW_SetItemStates(hwnd, infoPtr->nFocusedItem, TRUE, FALSE); - - LISTVIEW_SetVisible(hwnd, infoPtr->nFocusedItem); - } - } - else if (lStyle & LVS_REPORT) - { - } - else if ((lStyle & LVS_SMALLICON) || (lStyle & LVS_ICON)) - { - nItemCountPerRow = LISTVIEW_GetItemCountPerRow(hwnd); - nColumn = infoPtr->nFocusedItem % nItemCountPerRow; - if (nColumn != nItemCountPerRow - 1) - { - infoPtr->nFocusedItem += 1; - LISTVIEW_SetItemStates(hwnd, infoPtr->nFocusedItem, TRUE, FALSE); - - /* refresh display */ - InvalidateRect(hwnd, NULL, FALSE); - UpdateWindow(hwnd); -} - - } - break; - case VK_DOWN: - if ((lStyle & LVS_LIST) || (lStyle & LVS_REPORT)) -{ - if (infoPtr->nFocusedItem < infoPtr->nItemCount - 1) - { - infoPtr->nFocusedItem += 1; - LISTVIEW_SetItemStates(hwnd, infoPtr->nFocusedItem, TRUE, FALSE); - - LISTVIEW_SetVisible(hwnd, infoPtr->nFocusedItem); -} - } - else if ((lStyle & LVS_SMALLICON) || (lStyle & LVS_ICON)) + switch (LVS_TYPEMASK & lStyle) { - nItemCountPerRow = LISTVIEW_GetItemCountPerRow(hwnd); - if (infoPtr->nFocusedItem < infoPtr->nItemCount - nItemCountPerRow) + case LVS_LIST: + case LVS_REPORT: + if (infoPtr->nFocusedItem < GETITEMCOUNT(infoPtr) - 1) + { + LISTVIEW_KeySelection(hwnd, infoPtr->nFocusedItem + 1); + } + default: + if (infoPtr->nCountPerRow > 0) { - infoPtr->nFocusedItem += nItemCountPerRow; - LISTVIEW_SetItemStates(hwnd, infoPtr->nFocusedItem, TRUE, FALSE); - - LISTVIEW_SetVisible(hwnd, infoPtr->nFocusedItem); } } break; @@ -3280,6 +4858,9 @@ static LRESULT LISTVIEW_KeyDown(HWND hwnd, INT nVirtualKey, LONG lKeyData) break; } + /* refresh client area */ + InvalidateRect(hwnd, NULL, TRUE); + return 0; } @@ -3288,7 +4869,7 @@ static LRESULT LISTVIEW_KeyDown(HWND hwnd, INT nVirtualKey, LONG lKeyData) * Kills the focus. * * PARAMETER(S): - * [I] HWND32 : window handle + * [I] HWND : window handle * * RETURN: * Zero @@ -3296,19 +4877,19 @@ static LRESULT LISTVIEW_KeyDown(HWND hwnd, INT nVirtualKey, LONG lKeyData) static LRESULT LISTVIEW_KillFocus(HWND hwnd) { LISTVIEW_INFO *infoPtr = (LISTVIEW_INFO*)GetWindowLongA(hwnd, 0); - LONG lCtrlId = GetWindowLongA(hwnd, GWL_ID); - NMHDR nmh; + INT nCtrlId = GetWindowLongA(hwnd, GWL_ID); + NMHDR nmh; + /* send NM_KILLFOCUS notification */ nmh.hwndFrom = hwnd; - nmh.idFrom = lCtrlId; - nmh.code = NM_KILLFOCUS; - SendMessageA(GetParent(hwnd), WM_NOTIFY, (WPARAM)lCtrlId, - (LPARAM)&nmh); + nmh.idFrom = nCtrlId; + nmh.code = NM_KILLFOCUS; + ListView_Notify(GetParent(hwnd), nCtrlId, &nmh); /* set window focus flag */ - infoPtr->bFocus = FALSE; + infoPtr->bFocus = FALSE; - return 0; + return 0; } /*** @@ -3316,7 +4897,7 @@ static LRESULT LISTVIEW_KillFocus(HWND hwnd) * Left mouse button double click. * * PARAMETER(S): - * [I] HWND32 : window handle + * [I] HWND : window handle * [I] WORD : key flag * [I] WORD : x coordinate * [I] WORD : y coordinate @@ -3327,20 +4908,18 @@ static LRESULT LISTVIEW_KillFocus(HWND hwnd) static LRESULT LISTVIEW_LButtonDblClk(HWND hwnd, WORD wKey, WORD wPosX, WORD wPosY) { - LONG lCtrlId = GetWindowLongA(hwnd, GWL_ID); + LONG nCtrlId = GetWindowLongA(hwnd, GWL_ID); NMHDR nmh; /* send NM_DBLCLK notification */ nmh.hwndFrom = hwnd; - nmh.idFrom = lCtrlId; + nmh.idFrom = nCtrlId; nmh.code = NM_DBLCLK; - SendMessageA(GetParent (hwnd), WM_NOTIFY, (WPARAM)lCtrlId, - (LPARAM)&nmh); + ListView_Notify(GetParent(hwnd), nCtrlId, &nmh); /* send LVN_ITEMACTIVATE notification */ nmh.code = LVN_ITEMACTIVATE; - SendMessageA(GetParent (hwnd), WM_NOTIFY, (WPARAM)lCtrlId, - (LPARAM)&nmh); + ListView_Notify(GetParent(hwnd), nCtrlId, &nmh); return 0; } @@ -3350,7 +4929,7 @@ static LRESULT LISTVIEW_LButtonDblClk(HWND hwnd, WORD wKey, WORD wPosX, * Left mouse button down. * * PARAMETER(S): - * [I] HWND32 : window handle + * [I] HWND : window handle * [I] WORD : key flag * [I] WORD : x coordinate * [I] WORD : y coordinate @@ -3362,21 +4941,22 @@ static LRESULT LISTVIEW_LButtonDown(HWND hwnd, WORD wKey, WORD wPosX, WORD wPosY) { LISTVIEW_INFO *infoPtr = (LISTVIEW_INFO *)GetWindowLongA(hwnd, 0); - LONG lCtrlId = GetWindowLongA(hwnd, GWL_ID); + INT nCtrlId = GetWindowLongA(hwnd, GWL_ID); LVHITTESTINFO hitTestInfo; - LVITEMA lvItem; NMHDR nmh; INT nItem; + static BOOL bGroupSelect = TRUE; /* send NM_RELEASEDCAPTURE notification */ nmh.hwndFrom = hwnd; - nmh.idFrom = lCtrlId; + nmh.idFrom = nCtrlId; nmh.code = NM_RELEASEDCAPTURE; - SendMessageA(GetParent(hwnd), WM_NOTIFY, (WPARAM)lCtrlId, - (LPARAM)&nmh); - + ListView_Notify(GetParent(hwnd), nCtrlId, &nmh); + if (infoPtr->bFocus == FALSE) + { SetFocus(hwnd); + } /* set left button down flag */ infoPtr->bLButtonDown = TRUE; @@ -3386,39 +4966,41 @@ static LRESULT LISTVIEW_LButtonDown(HWND hwnd, WORD wKey, WORD wPosX, hitTestInfo.pt.y = wPosY; /* perform hit test */ - nItem = SendMessageA(hwnd, LVM_HITTEST, (WPARAM)0, (LPARAM)&hitTestInfo); - if ((nItem >= 0) && (nItem < infoPtr->nItemCount)) + nItem = ListView_HitTest(hwnd, &hitTestInfo); + if ((nItem >= 0) && (nItem < GETITEMCOUNT(infoPtr))) { - /* perform state changes (selection and focus) */ - infoPtr->nFocusedItem = nItem; - LISTVIEW_SetItemStates(hwnd, infoPtr->nFocusedItem, TRUE, TRUE); - - /* scroll intem into view if doing a multiple selection */ - - if ((wKey & MK_CONTROL) || (wKey & MK_SHIFT)) -{ - LISTVIEW_SetVisible(hwnd, infoPtr->nFocusedItem); + if ((wKey & MK_CONTROL) && (wKey & MK_SHIFT)) + { + if (bGroupSelect == TRUE) + { + LISTVIEW_AddGroupSelection(hwnd, nItem); + } + else + { + LISTVIEW_AddSelection(hwnd, nItem); + } + } + else if (wKey & MK_CONTROL) + { + bGroupSelect = LISTVIEW_ToggleSelection(hwnd, nItem); + } + else if (wKey & MK_SHIFT) + { + LISTVIEW_SetGroupSelection(hwnd, nItem); } else { - /* refresh display */ - InvalidateRect(hwnd, NULL, FALSE); - UpdateWindow(hwnd); + LISTVIEW_SetSelection(hwnd, nItem); } } else { - /* clear selection(s) */ - ZeroMemory(&lvItem, sizeof(LVITEMA)); - lvItem.stateMask = LVIS_SELECTED; - lvItem.state = 0; - SendMessageA(hwnd, LVM_SETITEMSTATE, (WPARAM)-1, (LPARAM)&lvItem); - - /* repaint everything */ - InvalidateRect(hwnd, NULL, FALSE); - UpdateWindow(hwnd); + /* remove all selections */ + LISTVIEW_RemoveSelections(hwnd, 0, GETITEMCOUNT(infoPtr)); } + InvalidateRect(hwnd, NULL, TRUE); + return 0; } @@ -3427,7 +5009,7 @@ static LRESULT LISTVIEW_LButtonDown(HWND hwnd, WORD wKey, WORD wPosX, * Left mouse button up. * * PARAMETER(S): - * [I] HWND32 : window handle + * [I] HWND : window handle * [I] WORD : key flag * [I] WORD : x coordinate * [I] WORD : y coordinate @@ -3439,23 +5021,22 @@ static LRESULT LISTVIEW_LButtonUp(HWND hwnd, WORD wKey, WORD wPosX, WORD wPosY) { LISTVIEW_INFO *infoPtr = (LISTVIEW_INFO *)GetWindowLongA(hwnd, 0); - LONG lCtrlId = GetWindowLongA(hwnd, GWL_ID); + INT nCtrlId = GetWindowLongA(hwnd, GWL_ID); NMHDR nmh; if (infoPtr->bLButtonDown == TRUE) { /* send NM_CLICK notification */ nmh.hwndFrom = hwnd; - nmh.idFrom = lCtrlId; + nmh.idFrom = nCtrlId; nmh.code = NM_CLICK; - SendMessageA(GetParent (hwnd), WM_NOTIFY, (WPARAM)lCtrlId, - (LPARAM)&nmh); + ListView_Notify(GetParent(hwnd), nCtrlId, &nmh); + + /* set left button flag */ + infoPtr->bLButtonDown = FALSE; } - /* set left button flag */ - infoPtr->bLButtonDown = FALSE; - - return 0; + return 0; } /*** @@ -3463,8 +5044,8 @@ static LRESULT LISTVIEW_LButtonUp(HWND hwnd, WORD wKey, WORD wPosX, * Creates the listview control (called before WM_CREATE). * * PARAMETER(S): - * [I] HWND32 : window handle - * [I] WPARAM32 : unhandled + * [I] HWND : window handle + * [I] WPARAM : unhandled * [I] LPARAM : widow creation info * * RETURN: @@ -3472,22 +5053,22 @@ static LRESULT LISTVIEW_LButtonUp(HWND hwnd, WORD wKey, WORD wPosX, */ static LRESULT LISTVIEW_NCCreate(HWND hwnd, WPARAM wParam, LPARAM lParam) { - LISTVIEW_INFO *infoPtr; + LISTVIEW_INFO *infoPtr; - /* allocate memory for info structure */ - infoPtr = (LISTVIEW_INFO *)COMCTL32_Alloc (sizeof(LISTVIEW_INFO)); + /* allocate memory for info structure */ + infoPtr = (LISTVIEW_INFO *)COMCTL32_Alloc(sizeof(LISTVIEW_INFO)); SetWindowLongA(hwnd, 0, (LONG)infoPtr); if (infoPtr == NULL) { - ERR (listview, "could not allocate info memory!\n"); - return 0; - } + ERR(listview, "could not allocate info memory!\n"); + return 0; + } if ((LISTVIEW_INFO *)GetWindowLongA(hwnd, 0) != infoPtr) { - ERR (listview, "pointer assignment error!\n"); - return 0; - } + ERR(listview, "pointer assignment error!\n"); + return 0; + } return DefWindowProcA(hwnd, WM_NCCREATE, wParam, lParam); } @@ -3497,7 +5078,7 @@ static LRESULT LISTVIEW_NCCreate(HWND hwnd, WPARAM wParam, LPARAM lParam) * Destroys the listview control (called after WM_DESTROY). * * PARAMETER(S): - * [I] HWND32 : window handle + * [I] HWND : window handle * * RETURN: * Zero @@ -3506,10 +5087,10 @@ static LRESULT LISTVIEW_NCDestroy(HWND hwnd) { LISTVIEW_INFO *infoPtr = (LISTVIEW_INFO *)GetWindowLongA(hwnd, 0); - /* free list view info data */ - COMCTL32_Free (infoPtr); + /* free listview info */ + COMCTL32_Free(infoPtr); - return 0; + return 0; } /*** @@ -3517,8 +5098,8 @@ static LRESULT LISTVIEW_NCDestroy(HWND hwnd) * Handles notification from children. * * PARAMETER(S): - * [I] HWND32 : window handle - * [I] INT32 : control identifier + * [I] HWND : window handle + * [I] INT : control identifier * [I] LPNMHDR : notification information * * RETURN: @@ -3527,19 +5108,35 @@ static LRESULT LISTVIEW_NCDestroy(HWND hwnd) static LRESULT LISTVIEW_Notify(HWND hwnd, INT nCtrlId, LPNMHDR lpnmh) { LISTVIEW_INFO *infoPtr = (LISTVIEW_INFO *)GetWindowLongA(hwnd, 0); - + if (lpnmh->hwndFrom == infoPtr->hwndHeader) { /* handle notification from header control */ - FIXME (listview, "WM_NOTIFY from header!\n"); - } - else - { - /* handle notification from unknown source */ - FIXME (listview, "WM_NOTIFY from unknown source!\n"); + if (lpnmh->code == HDN_ENDTRACKA) + { + InvalidateRect(hwnd, NULL, TRUE); } + } - return 0; + return 0; +} + +static LRESULT LISTVIEW_NotifyFormat(HWND hwndFrom, HWND hwnd, INT nCommand) +{ + LISTVIEW_INFO *infoPtr = (LISTVIEW_INFO *)GetWindowLongA(hwnd, 0); + + if (nCommand == NF_REQUERY) + { + /* determine the type of structures to use */ + infoPtr->notifyFormat = SendMessageA(hwndFrom, WM_NOTIFYFORMAT, + (WPARAM)hwnd, (LPARAM)NF_QUERY); + if (infoPtr->notifyFormat == NFR_UNICODE) + { + FIXME (listview, "NO support for unicode structures"); + } + } + + return 0; } /*** @@ -3547,34 +5144,36 @@ static LRESULT LISTVIEW_Notify(HWND hwnd, INT nCtrlId, LPNMHDR lpnmh) * Draws the listview control. * * PARAMETER(S): - * [I] HWND32 : window handle - * [I] HDC32 : device context handle + * [I] HWND : window handle + * [I] HDC : device context handle * * RETURN: * Zero */ static LRESULT LISTVIEW_Paint(HWND hwnd, HDC hdc) { - PAINTSTRUCT ps; + PAINTSTRUCT ps; if (hdc == 0) { hdc = BeginPaint(hwnd, &ps); LISTVIEW_Refresh(hwnd, hdc); EndPaint(hwnd, &ps); -} + } else + { LISTVIEW_Refresh(hwnd, hdc); + } return 0; } /*** * DESCRIPTION: - * Right mouse button double clisk. + * Right mouse button double click. * * PARAMETER(S): - * [I] HWND32 : window handle + * [I] HWND : window handle * [I] WORD : key flag * [I] WORD : x coordinate * [I] WORD : y coordinate @@ -3585,22 +5184,20 @@ static LRESULT LISTVIEW_Paint(HWND hwnd, HDC hdc) static LRESULT LISTVIEW_RButtonDblClk(HWND hwnd, WORD wKey, WORD wPosX, WORD wPosY) { - LONG lCtrlId = GetWindowLongA(hwnd, GWL_ID); + INT nCtrlId = GetWindowLongA(hwnd, GWL_ID); NMHDR nmh; /* send NM_RELEASEDCAPTURE notification */ nmh.hwndFrom = hwnd; - nmh.idFrom = lCtrlId; + nmh.idFrom = nCtrlId; nmh.code = NM_RELEASEDCAPTURE; - SendMessageA(GetParent(hwnd), WM_NOTIFY, (WPARAM)lCtrlId, - (LPARAM)&nmh); + ListView_Notify(GetParent(hwnd), nCtrlId, &nmh); /* send NM_RDBLCLK notification */ nmh.code = NM_RDBLCLK; - SendMessageA(GetParent(hwnd), WM_NOTIFY, (WPARAM)lCtrlId, - (LPARAM)&nmh); + ListView_Notify(GetParent(hwnd), nCtrlId, &nmh); - return 0; + return 0; } /*** @@ -3608,7 +5205,7 @@ static LRESULT LISTVIEW_RButtonDblClk(HWND hwnd, WORD wKey, WORD wPosX, * Right mouse button input. * * PARAMETER(S): - * [I] HWND32 : window handle + * [I] HWND : window handle * [I] WORD : key flag * [I] WORD : x coordinate * [I] WORD : y coordinate @@ -3620,27 +5217,24 @@ static LRESULT LISTVIEW_RButtonDown(HWND hwnd, WORD wKey, WORD wPosX, WORD wPosY) { LISTVIEW_INFO *infoPtr = (LISTVIEW_INFO *)GetWindowLongA(hwnd, 0); - LONG lCtrlId = GetWindowLongA(hwnd, GWL_ID); + INT nCtrlId = GetWindowLongA(hwnd, GWL_ID); LVHITTESTINFO hitTestInfo; NMHDR nmh; - LVITEMA lvItem; INT nItem; - /* The syslistview32 control sends a NM_RELEASEDCAPTURE notification. - I do not know why, but I decided to send it as well for compatibility - purposes. */ - ZeroMemory(&nmh, sizeof(NMHDR)); + /* send NM_RELEASEDCAPTURE notification */ nmh.hwndFrom = hwnd; - nmh.idFrom = lCtrlId; + nmh.idFrom = nCtrlId; nmh.code = NM_RELEASEDCAPTURE; - SendMessageA(GetParent(hwnd), WM_NOTIFY, (WPARAM)lCtrlId, - (LPARAM)&nmh); + ListView_Notify(GetParent(hwnd), nCtrlId, &nmh); - /* make sure listview control has focus */ + /* make sure the listview control window has the focus */ if (infoPtr->bFocus == FALSE) + { SetFocus(hwnd); + } - /* set left button down flag */ + /* set right button down flag */ infoPtr->bRButtonDown = TRUE; /* set hit coordinates */ @@ -3648,27 +5242,20 @@ static LRESULT LISTVIEW_RButtonDown(HWND hwnd, WORD wKey, WORD wPosX, hitTestInfo.pt.y = wPosY; /* perform hit test */ - nItem = SendMessageA(hwnd, LVM_HITTEST, (WPARAM)0, (LPARAM)&hitTestInfo); - if ((nItem >= 0) && (nItem < infoPtr->nItemCount)) + nItem = ListView_HitTest(hwnd, &hitTestInfo); + if ((nItem >= 0) && (nItem < GETITEMCOUNT(infoPtr))) { - /* perform state changes (selection and focus) */ - infoPtr->nFocusedItem = nItem; - LISTVIEW_SetItemStates(hwnd, infoPtr->nFocusedItem, FALSE, TRUE); + if (!((wKey & MK_SHIFT) || (wKey & MK_CONTROL))) + { + LISTVIEW_SetSelection(hwnd, nItem); + } } else { - /* clear selection(s) */ - ZeroMemory(&lvItem, sizeof(LVITEMA)); - lvItem.stateMask = LVIS_SELECTED; - lvItem.state = 0; - SendMessageA(hwnd, LVM_SETITEMSTATE, (WPARAM)-1, (LPARAM)&lvItem); + LISTVIEW_RemoveSelections(hwnd, 0, GETITEMCOUNT(infoPtr)); } - /* repaint everything */ - InvalidateRect(hwnd, NULL, FALSE); - UpdateWindow(hwnd); - - return 0; + return 0; } /*** @@ -3676,7 +5263,7 @@ static LRESULT LISTVIEW_RButtonDown(HWND hwnd, WORD wKey, WORD wPosX, * Right mouse button up. * * PARAMETER(S): - * [I] HWND32 : window handle + * [I] HWND : window handle * [I] WORD : key flag * [I] WORD : x coordinate * [I] WORD : y coordinate @@ -3688,24 +5275,23 @@ static LRESULT LISTVIEW_RButtonUp(HWND hwnd, WORD wKey, WORD wPosX, WORD wPosY) { LISTVIEW_INFO *infoPtr = (LISTVIEW_INFO *)GetWindowLongA(hwnd, 0); - LONG lCtrlId = GetWindowLongA(hwnd, GWL_ID); - NMHDR nmh; + INT nCtrlId = GetWindowLongA(hwnd, GWL_ID); + NMHDR nmh; if (infoPtr->bRButtonDown == TRUE) { - /* initialize notification information */ + /* send NM_RClICK notification */ ZeroMemory(&nmh, sizeof(NMHDR)); nmh.hwndFrom = hwnd; - nmh.idFrom = lCtrlId; + nmh.idFrom = nCtrlId; nmh.code = NM_RCLICK; - SendMessageA(GetParent (hwnd), WM_NOTIFY, (WPARAM)lCtrlId, - (LPARAM)&nmh); + ListView_Notify(GetParent(hwnd), nCtrlId, &nmh); + + /* set button flag */ + infoPtr->bRButtonDown = FALSE; } - - /* set button flag */ - infoPtr->bRButtonDown = FALSE; - - return 0; + + return 0; } /*** @@ -3713,8 +5299,8 @@ static LRESULT LISTVIEW_RButtonUp(HWND hwnd, WORD wKey, WORD wPosX, * Sets the focus. * * PARAMETER(S): - * [I] HWND32 : window handle - * [I] HWND32 : window handle of previously focused window + * [I] HWND : window handle + * [I] HWND : window handle of previously focused window * * RETURN: * Zero @@ -3722,15 +5308,14 @@ static LRESULT LISTVIEW_RButtonUp(HWND hwnd, WORD wKey, WORD wPosX, static LRESULT LISTVIEW_SetFocus(HWND hwnd, HWND hwndLoseFocus) { LISTVIEW_INFO *infoPtr = (LISTVIEW_INFO *)GetWindowLongA(hwnd, 0); - LONG lCtrlId = GetWindowLongA(hwnd, GWL_ID); + INT nCtrlId = GetWindowLongA(hwnd, GWL_ID); NMHDR nmh; - + /* send NM_SETFOCUS notification */ nmh.hwndFrom = hwnd; - nmh.idFrom = lCtrlId; + nmh.idFrom = nCtrlId; nmh.code = NM_SETFOCUS; - SendMessageA(GetParent(hwnd), WM_NOTIFY, (WPARAM)lCtrlId, - (LPARAM)&nmh); + ListView_Notify(GetParent(hwnd), nCtrlId, &nmh); /* set window focus flag */ infoPtr->bFocus = TRUE; @@ -3743,8 +5328,8 @@ static LRESULT LISTVIEW_SetFocus(HWND hwnd, HWND hwndLoseFocus) * Sets the font. * * PARAMETER(S): - * [I] HWND32 : window handle - * [I] HFONT32 : font handle + * [I] HWND : window handle + * [I] HFONT : font handle * [I] WORD : redraw flag * * RETURN: @@ -3762,20 +5347,22 @@ static LRESULT LISTVIEW_SetFont(HWND hwnd, HFONT hFont, WORD fRedraw) else { infoPtr->hFont = hFont; - } + } - if (lStyle & LVS_REPORT) + if ((LVS_TYPEMASK & lStyle ) == LVS_REPORT) { - /* set font of header */ + /* set header font */ SendMessageA(infoPtr->hwndHeader, WM_SETFONT, (WPARAM)hFont, MAKELPARAM(fRedraw, 0)); -} + } /* invalidate listview control client area */ InvalidateRect(hwnd, NULL, FALSE); - + if (fRedraw == TRUE) + { UpdateWindow(hwnd); + } return 0; } @@ -3785,7 +5372,7 @@ static LRESULT LISTVIEW_SetFont(HWND hwnd, HFONT hFont, WORD fRedraw) * Resizes the listview control. * * PARAMETER(S): - * [I] HWND32 : window handle + * [I] HWND : window handle * [I] WORD : new width * [I] WORD : new height * @@ -3794,31 +5381,156 @@ static LRESULT LISTVIEW_SetFont(HWND hwnd, HFONT hFont, WORD fRedraw) */ static LRESULT LISTVIEW_Size(HWND hwnd, WORD wWidth, WORD wHeight) { - LISTVIEW_INFO *infoPtr = (LISTVIEW_INFO *)GetWindowLongA(hwnd, 0); - LONG lStyle = GetWindowLongA(hwnd, GWL_STYLE); - INT nHScrollHeight; - - if (lStyle & LVS_LIST) - { - if (!(lStyle & WS_HSCROLL)) - { - nHScrollHeight = GetSystemMetrics(SM_CYHSCROLL); - if (wHeight > nHScrollHeight) - wHeight -= nHScrollHeight; - } - - infoPtr->nHeight = (INT)wHeight; - infoPtr->nWidth = (INT)wWidth; - } - - /* set scrollbar(s) if needed */ + LISTVIEW_SetSize(hwnd, GetWindowLongA(hwnd, GWL_STYLE), wWidth, wHeight); + LISTVIEW_SetViewInfo(hwnd); LISTVIEW_SetScroll(hwnd); - /* refresh client area */ + /* invalidate + erase background */ InvalidateRect(hwnd, NULL, TRUE); - UpdateWindow(hwnd); - return 0; + return 0; +} + +/*** + * DESCRIPTION: + * Sets the size information for a given style. + * + * PARAMETER(S): + * [I] HWND : window handle + * [I] LONG : window style + * [I] WORD : new width + * [I] WORD : new height + * + * RETURN: + * Zero + */ +static VOID LISTVIEW_SetSize(HWND hwnd, LONG lStyle, LONG lWidth, LONG lHeight) +{ + LISTVIEW_INFO *infoPtr = (LISTVIEW_INFO *)GetWindowLongA(hwnd, 0); + HDLAYOUT hl; + WINDOWPOS wp; + INT lTop = 0; + RECT rc; + + switch (lStyle & LVS_TYPEMASK) + { + case LVS_LIST: + if ((lStyle & LVS_TYPEMASK) == LVS_LIST) + { + if (!(lStyle & WS_HSCROLL)) + { + INT nHScrollHeight; + + nHScrollHeight = GetSystemMetrics(SM_CYHSCROLL); + if (lHeight > nHScrollHeight) + { + lHeight -= nHScrollHeight; + } + } + } + break; + + case LVS_REPORT: + rc.left = 0; + rc.top = 0; + rc.right = lWidth; + rc.bottom = lHeight; + hl.prc = &rc; + hl.pwpos = ℘ + Header_Layout(infoPtr->hwndHeader, &hl); + lTop = wp.cy; + break; + } + + infoPtr->rcList.top = lTop; + infoPtr->rcList.left = 0; + infoPtr->rcList.bottom = lHeight; + infoPtr->rcList.right = lWidth; +} + +/*** + * DESCRIPTION: + * Notification sent when the window style is modified. + * + * PARAMETER(S): + * [I] HWND : window handle + * [I] WPARAM : window style type (normal or extended) + * [I] LPSTYLESTRUCT : window style information + * + * RETURN: + * Zero + */ +static INT LISTVIEW_StyleChanged(HWND hwnd, WPARAM wStyleType, + LPSTYLESTRUCT lpss) +{ + LISTVIEW_INFO *infoPtr = (LISTVIEW_INFO *)GetWindowLongA(hwnd, 0); + HDLAYOUT hl; + WINDOWPOS wp; + HDC hdc; + RECT rc; + HBRUSH hBrush; + + if (wStyleType == GWL_STYLE) + { + /* remove vertical scrollbar */ + if (lpss->styleOld & WS_VSCROLL) + { + ShowScrollBar(hwnd, SB_VERT, FALSE); + } + + /* remove horizontal scrollbar */ + if (lpss->styleOld & WS_HSCROLL) + { + ShowScrollBar(hwnd, SB_HORZ, FALSE); + } + + if ((LVS_TYPEMASK & lpss->styleOld) == LVS_REPORT) + { + /* hide header */ + ShowWindow(infoPtr->hwndHeader, SW_HIDE); + } + + /* erase everything */ + GetClientRect(hwnd, &rc); + hdc = GetDC(hwnd); + hBrush = CreateSolidBrush(infoPtr->clrBk); + FillRect(hdc, &rc, hBrush); + DeleteObject(hBrush); + ReleaseDC(hwnd, hdc); + + if ((lpss->styleNew & LVS_TYPEMASK) == LVS_REPORT) + { + hl.prc = &rc; + hl.pwpos = ℘ + Header_Layout(infoPtr->hwndHeader, &hl); + SetWindowPos(infoPtr->hwndHeader, hwnd, wp.x, wp.y, wp.cx, wp.cy, + wp.flags); + ShowWindow(infoPtr->hwndHeader, SW_SHOWNORMAL); + } + else if (((lpss->styleNew & LVS_TYPEMASK) == LVS_ICON) || + ((lpss->styleNew & LVS_TYPEMASK) == LVS_SMALLICON)) + { + /* for NOW (it's only temporary) */ + SetWindowLongA(hwnd, GWL_STYLE, (lpss->styleNew&~LVS_TYPEMASK)|LVS_LIST); + } + + /* TEMPORARY */ + LISTVIEW_UnsupportedStyles(lpss->styleNew); + + /* set new size */ + LISTVIEW_SetSize(hwnd, lpss->styleNew, rc.right, rc.bottom); + + /* recalculate attributes */ + LISTVIEW_SetViewInfo(hwnd); + + /* set scrollbars, if needed */ + LISTVIEW_SetScroll(hwnd); + + /* invalidate + erase background */ + InvalidateRect(hwnd, NULL, TRUE); + } + + return 0; } /*** @@ -3826,9 +5538,9 @@ static LRESULT LISTVIEW_Size(HWND hwnd, WORD wWidth, WORD wHeight) * Window procedure of the listview control. * * PARAMETER(S): - * [I] HWND32 : - * [I] UINT32 : - * [I] WPARAM32 : + * [I] HWND : + * [I] UINT : + * [I] WPARAM : * [I] LPARAM : * * RETURN: @@ -3837,44 +5549,48 @@ static LRESULT LISTVIEW_Size(HWND hwnd, WORD wWidth, WORD wHeight) LRESULT WINAPI LISTVIEW_WindowProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam) { - switch (uMsg) - { + switch (uMsg) + { case LVM_APPROXIMATEVIEWRECT: return LISTVIEW_ApproximateViewRect(hwnd, (INT)wParam, LOWORD(lParam), HIWORD(lParam)); case LVM_ARRANGE: return LISTVIEW_Arrange(hwnd, (INT)wParam); -/* case LVM_CREATEDRAGIMAGE: */ +/* case LVM_CREATEDRAGIMAGE: */ - case LVM_DELETEALLITEMS: + case LVM_DELETEALLITEMS: return LISTVIEW_DeleteAllItems(hwnd); - case LVM_DELETECOLUMN: + case LVM_DELETECOLUMN: return LISTVIEW_DeleteColumn(hwnd, (INT)wParam); - case LVM_DELETEITEM: + case LVM_DELETEITEM: return LISTVIEW_DeleteItem(hwnd, (INT)wParam); /* case LVM_EDITLABEL: */ -/* case LVM_ENSUREVISIBLE: */ + + case LVM_ENSUREVISIBLE: + return LISTVIEW_EnsureVisible(hwnd, (INT)wParam, (BOOL)lParam); case LVM_FINDITEMA: return LISTVIEW_FindItem(hwnd, (INT)wParam, (LPLVFINDINFO)lParam); - case LVM_GETBKCOLOR: + case LVM_GETBKCOLOR: return LISTVIEW_GetBkColor(hwnd); /* case LVM_GETBKIMAGE: */ -/* case LVM_GETCALLBACKMASK: */ - case LVM_GETCOLUMNA: + case LVM_GETCALLBACKMASK: + return LISTVIEW_GetCallbackMask(hwnd); + + case LVM_GETCOLUMNA: return LISTVIEW_GetColumnA(hwnd, (INT)wParam, (LPLVCOLUMNA)lParam); -/* case LVM_GETCOLUMN32W: */ +/* case LVM_GETCOLUMNW: */ /* case LVM_GETCOLUMNORDERARRAY: */ - case LVM_GETCOLUMNWIDTH: + case LVM_GETCOLUMNWIDTH: return LISTVIEW_GetColumnWidth(hwnd, (INT)wParam); case LVM_GETCOUNTPERPAGE: @@ -3883,27 +5599,27 @@ LRESULT WINAPI LISTVIEW_WindowProc(HWND hwnd, UINT uMsg, WPARAM wParam, /* case LVM_GETEDITCONTROL: */ /* case LVM_GETEXTENDEDLISTVIEWSTYLE: */ - case LVM_GETHEADER: + case LVM_GETHEADER: return LISTVIEW_GetHeader(hwnd); /* case LVM_GETHOTCURSOR: */ /* case LVM_GETHOTITEM: */ /* case LVM_GETHOVERTIME: */ - case LVM_GETIMAGELIST: + case LVM_GETIMAGELIST: return LISTVIEW_GetImageList(hwnd, (INT)wParam); /* case LVM_GETISEARCHSTRING: */ - case LVM_GETITEMA: + case LVM_GETITEMA: return LISTVIEW_GetItemA(hwnd, (LPLVITEMA)lParam); -/* case LVM_GETITEM32W: */ +/* case LVM_GETITEMW: */ - case LVM_GETITEMCOUNT: + case LVM_GETITEMCOUNT: return LISTVIEW_GetItemCount(hwnd); - case LVM_GETITEMPOSITION: + case LVM_GETITEMPOSITION: return LISTVIEW_GetItemPosition(hwnd, (INT)wParam, (LPPOINT)lParam); case LVM_GETITEMRECT: @@ -3915,39 +5631,42 @@ LRESULT WINAPI LISTVIEW_WindowProc(HWND hwnd, UINT uMsg, WPARAM wParam, case LVM_GETITEMSTATE: return LISTVIEW_GetItemState(hwnd, (INT)wParam, (UINT)lParam); - case LVM_GETITEMTEXTA: + case LVM_GETITEMTEXTA: LISTVIEW_GetItemTextA(hwnd, (INT)wParam, (LPLVITEMA)lParam); break; -/* case LVM_GETITEMTEXT32W: */ +/* case LVM_GETITEMTEXTW: */ - case LVM_GETNEXTITEM: + case LVM_GETNEXTITEM: return LISTVIEW_GetNextItem(hwnd, (INT)wParam, LOWORD(lParam)); /* case LVM_GETNUMBEROFWORKAREAS: */ case LVM_GETORIGIN: return LISTVIEW_GetOrigin(hwnd, (LPPOINT)lParam); - case LVM_GETSELECTEDCOUNT: + case LVM_GETSELECTEDCOUNT: return LISTVIEW_GetSelectedCount(hwnd); case LVM_GETSELECTIONMARK: return LISTVIEW_GetSelectionMark(hwnd); - case LVM_GETSTRINGWIDTHA: + case LVM_GETSTRINGWIDTHA: return LISTVIEW_GetStringWidthA (hwnd, (LPCSTR)lParam); -/* case LVM_GETSTRINGWIDTH32W: */ +/* case LVM_GETSTRINGWIDTHW: */ /* case LVM_GETSUBITEMRECT: */ - case LVM_GETTEXTBKCOLOR: + case LVM_GETTEXTBKCOLOR: return LISTVIEW_GetTextBkColor(hwnd); - case LVM_GETTEXTCOLOR: + case LVM_GETTEXTCOLOR: return LISTVIEW_GetTextColor(hwnd); /* case LVM_GETTOOLTIPS: */ -/* case LVM_GETTOPINDEX: */ + + case LVM_GETTOPINDEX: + return LISTVIEW_GetTopIndex(hwnd); + /* case LVM_GETUNICODEFORMAT: */ case LVM_GETVIEWRECT: @@ -3955,36 +5674,38 @@ LRESULT WINAPI LISTVIEW_WindowProc(HWND hwnd, UINT uMsg, WPARAM wParam, /* case LVM_GETWORKAREAS: */ - case LVM_HITTEST: + case LVM_HITTEST: return LISTVIEW_HitTest(hwnd, (LPLVHITTESTINFO)lParam); - case LVM_INSERTCOLUMNA: + case LVM_INSERTCOLUMNA: return LISTVIEW_InsertColumnA(hwnd, (INT)wParam, (LPLVCOLUMNA)lParam); -/* case LVM_INSERTCOLUMN32W: */ +/* case LVM_INSERTCOLUMNW: */ - case LVM_INSERTITEMA: + case LVM_INSERTITEMA: return LISTVIEW_InsertItemA(hwnd, (LPLVITEMA)lParam); -/* case LVM_INSERTITEM32W: */ +/* case LVM_INSERTITEMW: */ - case LVM_REDRAWITEMS: + case LVM_REDRAWITEMS: return LISTVIEW_RedrawItems(hwnd, (INT)wParam, (INT)lParam); case LVM_SCROLL: return LISTVIEW_Scroll(hwnd, (INT)wParam, (INT)lParam); - case LVM_SETBKCOLOR: + case LVM_SETBKCOLOR: return LISTVIEW_SetBkColor(hwnd, (COLORREF)lParam); /* case LVM_SETBKIMAGE: */ -/* case LVM_SETCALLBACKMASK: */ - case LVM_SETCOLUMNA: + case LVM_SETCALLBACKMASK: + return LISTVIEW_SetCallbackMask(hwnd, (UINT)wParam); + + case LVM_SETCOLUMNA: return LISTVIEW_SetColumnA(hwnd, (INT)wParam, (LPLVCOLUMNA)lParam); -/* case LVM_SETCOLUMN32W: */ +/* case LVM_SETCOLUMNW: */ /* case LVM_SETCOLUMNORDERARRAY: */ /* case LVM_SETCOLUMNWIDTH: */ /* case LVM_SETEXTENDEDLISTVIEWSTYLE: */ @@ -3993,39 +5714,43 @@ LRESULT WINAPI LISTVIEW_WindowProc(HWND hwnd, UINT uMsg, WPARAM wParam, /* case LVM_SETHOVERTIME: */ /* case LVM_SETICONSPACING: */ - case LVM_SETIMAGELIST: + case LVM_SETIMAGELIST: return LISTVIEW_SetImageList(hwnd, (INT)wParam, (HIMAGELIST)lParam); - case LVM_SETITEMA: + case LVM_SETITEMA: return LISTVIEW_SetItemA(hwnd, (LPLVITEMA)lParam); -/* case LVM_SETITEM32W: */ -/* case LVM_SETITEMCOUNT: */ +/* case LVM_SETITEMW: */ - case LVM_SETITEMPOSITION16: - return LISTVIEW_SetItemPosition(hwnd, (INT)wParam, - (INT)LOWORD(lParam), - (INT) HIWORD(lParam)); + case LVM_SETITEMCOUNT: + LISTVIEW_SetItemCount(hwnd, (INT)wParam); + break; + + case LVM_SETITEMPOSITION: + return LISTVIEW_SetItemPosition(hwnd, (INT)wParam, (INT)LOWORD(lParam), + (INT)HIWORD(lParam)); -/* case LVM_SETITEMPOSITION32: */ +/* case LVM_SETITEMPOSITION: */ case LVM_SETITEMSTATE: return LISTVIEW_SetItemState(hwnd, (INT)wParam, (LPLVITEMA)lParam); -/* case LVM_SETITEMTEXT: */ + case LVM_SETITEMTEXTA: + return LISTVIEW_SetItemTextA(hwnd, (INT)wParam, (LPLVITEMA)lParam); + /* case LVM_SETSELECTIONMARK: */ - case LVM_SETTEXTBKCOLOR: + case LVM_SETTEXTBKCOLOR: return LISTVIEW_SetTextBkColor(hwnd, (COLORREF)lParam); - case LVM_SETTEXTCOLOR: + case LVM_SETTEXTCOLOR: return LISTVIEW_SetTextColor(hwnd, (COLORREF)lParam); /* case LVM_SETTOOLTIPS: */ /* case LVM_SETUNICODEFORMAT: */ /* case LVM_SETWORKAREAS: */ - case LVM_SORTITEMS: + case LVM_SORTITEMS: return LISTVIEW_SortItems(hwnd, wParam, lParam); /* case LVM_SUBITEMHITTEST: */ @@ -4036,19 +5761,19 @@ LRESULT WINAPI LISTVIEW_WindowProc(HWND hwnd, UINT uMsg, WPARAM wParam, /* case WM_CHAR: */ /* case WM_COMMAND: */ - case WM_CREATE: + case WM_CREATE: return LISTVIEW_Create(hwnd, wParam, lParam); + + case WM_DESTROY: + return LISTVIEW_Destroy(hwnd); + + case WM_ERASEBKGND: + return LISTVIEW_EraseBackground(hwnd, wParam, lParam); - case WM_DESTROY: - return LISTVIEW_Destroy(hwnd, wParam, lParam); + case WM_GETDLGCODE: + return DLGC_WANTTAB | DLGC_WANTARROWS; - case WM_ERASEBKGND: - return LISTVIEW_EraseBackground (hwnd, wParam, lParam); - - case WM_GETDLGCODE: - return DLGC_WANTTAB | DLGC_WANTARROWS; - - case WM_GETFONT: + case WM_GETFONT: return LISTVIEW_GetFont(hwnd); case WM_HSCROLL: @@ -4058,40 +5783,43 @@ LRESULT WINAPI LISTVIEW_WindowProc(HWND hwnd, UINT uMsg, WPARAM wParam, case WM_KEYDOWN: return LISTVIEW_KeyDown(hwnd, (INT)wParam, (LONG)lParam); - case WM_KILLFOCUS: + case WM_KILLFOCUS: return LISTVIEW_KillFocus(hwnd); - case WM_LBUTTONDBLCLK: + case WM_LBUTTONDBLCLK: return LISTVIEW_LButtonDblClk(hwnd, (WORD)wParam, LOWORD(lParam), HIWORD(lParam)); - - case WM_LBUTTONDOWN: + + case WM_LBUTTONDOWN: return LISTVIEW_LButtonDown(hwnd, (WORD)wParam, LOWORD(lParam), HIWORD(lParam)); case WM_LBUTTONUP: return LISTVIEW_LButtonUp(hwnd, (WORD)wParam, LOWORD(lParam), HIWORD(lParam)); - + /* case WM_MOUSEMOVE: */ /* return LISTVIEW_MouseMove (hwnd, wParam, lParam); */ - case WM_NCCREATE: + case WM_NCCREATE: return LISTVIEW_NCCreate(hwnd, wParam, lParam); - case WM_NCDESTROY: + case WM_NCDESTROY: return LISTVIEW_NCDestroy(hwnd); - case WM_NOTIFY: + case WM_NOTIFY: return LISTVIEW_Notify(hwnd, (INT)wParam, (LPNMHDR)lParam); - case WM_PAINT: + case WM_NOTIFYFORMAT: + return LISTVIEW_NotifyFormat(hwnd, (HWND)wParam, (INT)lParam); + + case WM_PAINT: return LISTVIEW_Paint(hwnd, (HDC)wParam); - case WM_RBUTTONDBLCLK: + case WM_RBUTTONDBLCLK: return LISTVIEW_RButtonDblClk(hwnd, (WORD)wParam, LOWORD(lParam), HIWORD(lParam)); - case WM_RBUTTONDOWN: + case WM_RBUTTONDOWN: return LISTVIEW_RButtonDown(hwnd, (WORD)wParam, LOWORD(lParam), HIWORD(lParam)); @@ -4099,32 +5827,41 @@ LRESULT WINAPI LISTVIEW_WindowProc(HWND hwnd, UINT uMsg, WPARAM wParam, return LISTVIEW_RButtonUp(hwnd, (WORD)wParam, LOWORD(lParam), HIWORD(lParam)); - case WM_SETFOCUS: + case WM_SETFOCUS: return LISTVIEW_SetFocus(hwnd, (HWND)wParam); - case WM_SETFONT: + case WM_SETFONT: return LISTVIEW_SetFont(hwnd, (HFONT)wParam, (WORD)lParam); /* case WM_SETREDRAW: */ - case WM_SIZE: + case WM_SIZE: return LISTVIEW_Size(hwnd, LOWORD(lParam), HIWORD(lParam)); + case WM_STYLECHANGED: + return LISTVIEW_StyleChanged(hwnd, wParam, (LPSTYLESTRUCT)lParam); + /* case WM_TIMER: */ -/* case WM_VSCROLL: */ + + case WM_VSCROLL: + return LISTVIEW_VScroll(hwnd, (INT)LOWORD(wParam), + (INT)HIWORD(wParam), (HWND)lParam); + /* case WM_WINDOWPOSCHANGED: */ /* case WM_WININICHANGE: */ - default: - if (uMsg >= WM_USER) - ERR (listview, "unknown msg %04x wp=%08x lp=%08lx\n", - uMsg, wParam, lParam); - - /* call default window procedure */ - return DefWindowProcA (hwnd, uMsg, wParam, lParam); + default: + if (uMsg >= WM_USER) + { + ERR(listview, "unknown msg %04x wp=%08x lp=%08lx\n", + uMsg, wParam, lParam); } - return 0; + /* call default window procedure */ + return DefWindowProcA(hwnd, uMsg, wParam, lParam); + } + + return 0; } /*** @@ -4139,20 +5876,20 @@ LRESULT WINAPI LISTVIEW_WindowProc(HWND hwnd, UINT uMsg, WPARAM wParam, */ VOID LISTVIEW_Register(VOID) { - WNDCLASSA wndClass; + WNDCLASSA wndClass; if (!GlobalFindAtomA(WC_LISTVIEWA)) { - ZeroMemory (&wndClass, sizeof(WNDCLASSA)); - wndClass.style = CS_GLOBALCLASS | CS_DBLCLKS; - wndClass.lpfnWndProc = (WNDPROC)LISTVIEW_WindowProc; - wndClass.cbClsExtra = 0; - wndClass.cbWndExtra = sizeof(LISTVIEW_INFO *); - wndClass.hCursor = LoadCursorA (0, IDC_ARROWA); + ZeroMemory(&wndClass, sizeof(WNDCLASSA)); + wndClass.style = CS_GLOBALCLASS | CS_DBLCLKS; + wndClass.lpfnWndProc = (WNDPROC)LISTVIEW_WindowProc; + wndClass.cbClsExtra = 0; + wndClass.cbWndExtra = sizeof(LISTVIEW_INFO *); + wndClass.hCursor = LoadCursorA(0, IDC_ARROWA); wndClass.hbrBackground = (HBRUSH)(COLOR_WINDOW + 1); wndClass.lpszClassName = WC_LISTVIEWA; RegisterClassA (&wndClass); -} + } } /*** @@ -4167,7 +5904,7 @@ VOID LISTVIEW_Register(VOID) */ VOID LISTVIEW_Unregister(VOID) { - if (GlobalFindAtomA (WC_LISTVIEWA)) - UnregisterClassA (WC_LISTVIEWA, (HINSTANCE)NULL); + if (GlobalFindAtomA(WC_LISTVIEWA)) + UnregisterClassA(WC_LISTVIEWA, (HINSTANCE)NULL); } diff --git a/include/commctrl.h b/include/commctrl.h index 91d2fded21b..de957de8cea 100644 --- a/include/commctrl.h +++ b/include/commctrl.h @@ -2170,6 +2170,7 @@ typedef struct tagNMTVGETINFOTIPW #define LVIF_STATE 0x0008 #define LVIF_INDENT 0x0010 #define LVIF_NORECOMPUTE 0x0800 +#define LVIF_DI_SETITEM 0x1000 #define LVIR_BOUNDS 0x0000 #define LVIR_LABEL 0x0002 @@ -2497,6 +2498,30 @@ typedef struct tagTCHITTESTINFO typedef INT (CALLBACK *PFNLVCOMPARE)(LPARAM, LPARAM, LPARAM); +#define ListView_Arrange(hwnd,code) \ + (INT)SendMessageA((hwnd),LVM_ARRANGE,(WPARAM)(INT)(code),0L) +#define ListView_GetItemPosition(hwnd,i,ppt) \ + (INT)SendMessageA((hwnd),LVM_GETITEMPOSITION,(WPARAM)(INT)(i),(LPARAM)(LPPOINT)(ppt)) +#define ListView_GetItemRect(hwnd,i,prc) \ + (INT)SendMessageA((hwnd),LVM_GETITEMRECT,(WPARAM)(INT)(i),(LPARAM)(LPRECT)(prc)) +#define ListView_SetItemA(hwnd,pitem) \ + (INT)SendMessageA((hwnd),LVM_SETITEMA,0,(LPARAM)(const LVITEMA *)(pitem)) +#define ListView_SetItemState(hwnd,i,pitem) \ + (BOOL)SendMessageA((hwnd),LVM_SETITEMSTATE,(WPARAM)(UINT)(i),(LPARAM)(LPLVITEMA)(pitem)) +#define ListView_GetItemState(hwnd,i,mask) \ + (BOOL)SendMessageA((hwnd),LVM_GETITEMSTATE,(WPARAM)(UINT)(i),(LPARAM)(UINT)(mask)) +#define ListView_GetCountPerPage(hwnd) \ + (BOOL)SendMessageW((hwnd),LVM_GETCOUNTPERPAGE,0,0L) +#define ListView_GetImageList(hwnd,iImageList) \ + (HIMAGELIST)SendMessageA((hwnd),LVM_GETIMAGELIST,(WPARAM)(INT)(iImageList),0L) +#define ListView_GetStringWidthA(hwnd,pstr) \ + (INT)SendMessageA((hwnd),LVM_GETSTRINGWIDTHA,0,(LPARAM)(LPCSTR)(pstr)) +#define ListView_GetTopIndex(hwnd) \ + (BOOL)SendMessageA((hwnd),LVM_GETTOPINDEX,0,0L) +#define ListView_Scroll(hwnd,dx,dy) \ + (BOOL)SendMessageA((hwnd),LVM_SCROLL,(WPARAM)(INT)(dx),(LPARAM)(INT)(dy)) +#define ListView_EnsureVisible(hwnd,i,fPartialOk) \ + (BOOL)SendMessageA((hwnd),LVM_ENSUREVISIBLE,(WPARAM)(INT)i,(LPARAM)(BOOL)fPartialOk) #define ListView_SetBkColor(hwnd,clrBk) \ (BOOL)SendMessageA((hwnd),LVM_SETBKCOLOR,0,(LPARAM)(COLORREF)(clrBk)) #define ListView_GetImageList(hwnd,iImageList) \ @@ -2511,7 +2536,7 @@ typedef INT (CALLBACK *PFNLVCOMPARE)(LPARAM, LPARAM, LPARAM); (BOOL)SendMessageW((hwnd),LVM_GETITEMW,0,(LPARAM)(LVITEMW *)(pitem)) #define ListView_GetItem WINELIB_NAME_AW(ListView_GetItem) #define ListView_HitTest(hwnd,pinfo) \ - (INT)SendMessageA((hwnd),LVMHITTEST,0,(LPARAM)(LPLVHITTESTINFO)(pinfo)) + (INT)SendMessageA((hwnd),LVM_HITTEST,0,(LPARAM)(LPLVHITTESTINFO)(pinfo)) #define ListView_InsertItemA(hwnd,pitem) \ (INT)SendMessageA((hwnd),LVM_INSERTITEMA,0,(LPARAM)(const LVITEMA *)(pitem)) #define ListView_InsertItemW(hwnd,pitem) \ diff --git a/include/listview.h b/include/listview.h index 55ab3b54780..28db989d8f1 100644 --- a/include/listview.h +++ b/include/listview.h @@ -7,6 +7,13 @@ #ifndef __WINE_LISTVIEW_H #define __WINE_LISTVIEW_H +typedef struct tagLISTVIEW_SUBITEM +{ + LPSTR pszText; + INT iImage; + INT iSubItem; + +} LISTVIEW_SUBITEM; typedef struct tagLISTVIEW_ITEM { @@ -27,19 +34,23 @@ typedef struct tagLISTVIEW_INFO HIMAGELIST himlNormal; HIMAGELIST himlSmall; HIMAGELIST himlState; - BOOL bLButtonDown; - BOOL bRButtonDown; - INT nColumnCount; - INT nFocusedItem; - INT nItemCount; - INT nItemHeight; - INT nColumnWidth; - INT nSelectionMark; + BOOL bLButtonDown; + BOOL bRButtonDown; + INT nCountPerColumn; + INT nCountPerRow; + INT nFocusedItem; + INT nItemHeight; + INT nColumnWidth; + INT nSelectionMark; + SHORT notifyFormat; + RECT rcList; + SIZE iconSize; + SIZE smallIconSpacing; + SIZE largeIconSpacing; + UINT uCallbackMask; HWND hwndHeader; HFONT hDefaultFont; HFONT hFont; - INT nWidth; - INT nHeight; BOOL bFocus; DWORD dwExStyle; /* extended listview style */ HDPA hdpaItems;