From e98f97ee9f622bf8dcfe5d3dbab9b3b374693057 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?G=C3=A9=20van=20Geldorp?= Date: Fri, 12 Aug 2005 16:31:56 +0000 Subject: [PATCH] Sync to Wine-20050725: Vitaliy Margolen - Send CDDS_ITEMPOSTERASE | CDDS_PREPAINT notify. Felix Nawothnig - Move DPA and DSA functions out of comctl32undoc.c as they are documented by now. - Fix some DPA functions so they pass the new tests. - Don't invalidate the whole propsheet when the page is switched. Dimi Paun - Silence uninitialized warnings. Robert Shearman - Call SetBkMode with the correct value from the NMTBCUSTOMDRAW structure. - Don't fill the NMTBCUSTOMDRAW structure in again for CDDS_POSTPAINT. - Remove redundant bBtnTransprnt value. - Height is now calculated based on the number of rows, not on the bounding rect. - Only call CalcToolbar in AutoSize if it has TBSTYLE_WRAPABLE or TBSTYLE_EX_UNDOC1 set. - Remove a bad test in SetButtonWidth that fixes a regression from the above change in IE. - Remove unnecessary nHeight data. - Remove duplicated code in Size by calling AutoSize. - Remove unnecessary bAutoSize value because SetWindowPos doesn't generate WM_SIZE when there is nothing to do on both Windows and Wine. - TBSTATE_INDETERMINATE only takes effect if the button is enabled, otherwise it should just appear like any other disabled button. - Native autosizes on inserting/adding buttons, so we should too. - The IsValidImageList test is not needed because if it isn't a valid image list we will have set the bitmap width and height to 1 and it does the wrong thing when no buttons are present. - The calculated button height should include the text height when no buttons are present. - Handle CopyImage and other functions failing by not adding the icon and notifying the caller. Thomas Weidenmueller - Support PSH_WIZARDHASFINISH in wizards. - Correct tab order of the wizard buttons. - Support PSM_IDTOINDEX. Aric Stewart - When adding an image copy the full previous buffer. - Implement replacing an icon with one from a resource. Kevin Koltzau - Forward some header notifications to parent of listview. Frank Richter - Enabled "tab" dialog texture for property sheet pages. - Add theming support for header controls. - Use theming for the ListView non-client area. - Let property sheets update the cached system colors upon receiving WM_SYSCOLORCHANGE. - Add theming for the up/down control. svn path=/trunk/; revision=17326 --- reactos/lib/comctl32/comctl32.xml | 3 + reactos/lib/comctl32/comctl32undoc.c | 1328 -------------------------- reactos/lib/comctl32/comctl_Cn.rc | 4 +- reactos/lib/comctl32/comctl_Cs.rc | 4 +- reactos/lib/comctl32/comctl_De.rc | 4 +- reactos/lib/comctl32/comctl_En.rc | 4 +- reactos/lib/comctl32/comctl_Es.rc | 4 +- reactos/lib/comctl32/comctl_Fr.rc | 4 +- reactos/lib/comctl32/comctl_It.rc | 4 +- reactos/lib/comctl32/comctl_Ja.rc | 4 +- reactos/lib/comctl32/comctl_Ko.rc | 4 +- reactos/lib/comctl32/comctl_Nl.rc | 4 +- reactos/lib/comctl32/comctl_Pl.rc | 4 +- reactos/lib/comctl32/comctl_Pt.rc | 4 +- reactos/lib/comctl32/comctl_Ru.rc | 4 +- reactos/lib/comctl32/comctl_Si.rc | 4 +- reactos/lib/comctl32/comctl_Sv.rc | 4 +- reactos/lib/comctl32/comctl_Th.rc | 4 +- reactos/lib/comctl32/comctl_Uk.rc | 4 +- reactos/lib/comctl32/dpa.c | 973 +++++++++++++++++++ reactos/lib/comctl32/dsa.c | 436 +++++++++ reactos/lib/comctl32/header.c | 102 +- reactos/lib/comctl32/imagelist.c | 45 +- reactos/lib/comctl32/listview.c | 120 ++- reactos/lib/comctl32/propsheet.c | 136 ++- reactos/lib/comctl32/toolbar.c | 350 +++---- reactos/lib/comctl32/updown.c | 142 ++- 27 files changed, 1998 insertions(+), 1705 deletions(-) create mode 100644 reactos/lib/comctl32/dpa.c create mode 100644 reactos/lib/comctl32/dsa.c diff --git a/reactos/lib/comctl32/comctl32.xml b/reactos/lib/comctl32/comctl32.xml index ca7aae051ba..b327524cc89 100644 --- a/reactos/lib/comctl32/comctl32.xml +++ b/reactos/lib/comctl32/comctl32.xml @@ -13,13 +13,16 @@ advapi32 gdi32 user32 + uxtheme winmm animate.c comboex.c comctl32undoc.c commctrl.c datetime.c + dpa.c draglist.c + dsa.c flatsb.c header.c hotkey.c diff --git a/reactos/lib/comctl32/comctl32undoc.c b/reactos/lib/comctl32/comctl32undoc.c index 27438d38c68..492e674a6ba 100644 --- a/reactos/lib/comctl32/comctl32undoc.c +++ b/reactos/lib/comctl32/comctl32undoc.c @@ -55,313 +55,8 @@ WINE_DEFAULT_DEBUG_CHANNEL(commctrl); -struct _DSA -{ - INT nItemCount; - LPVOID pData; - INT nMaxCount; - INT nItemSize; - INT nGrow; -}; - -struct _DPA -{ - INT nItemCount; - LPVOID *ptrs; - HANDLE hHeap; - INT nGrow; - INT nMaxCount; -}; - -typedef struct _STREAMDATA -{ - DWORD dwSize; - DWORD dwData2; - DWORD dwItems; -} STREAMDATA, *PSTREAMDATA; - -typedef struct _LOADDATA -{ - INT nCount; - PVOID ptr; -} LOADDATA, *LPLOADDATA; - -typedef HRESULT (CALLBACK *DPALOADPROC)(LPLOADDATA,IStream*,LPARAM); - static const WCHAR strMRUList[] = { 'M','R','U','L','i','s','t',0 }; -/************************************************************************** - * DPA_LoadStream [COMCTL32.9] - * - * Loads a dynamic pointer array from a stream - * - * PARAMS - * phDpa [O] pointer to a handle to a dynamic pointer array - * loadProc [I] pointer to a callback function - * pStream [I] pointer to a stream - * lParam [I] application specific value - * - * RETURNS - * Success: TRUE - * Failure: FALSE - * - * NOTES - * No more information available yet! - */ -HRESULT WINAPI DPA_LoadStream (HDPA *phDpa, DPALOADPROC loadProc, - IStream *pStream, LPARAM lParam) -{ - HRESULT errCode; - LARGE_INTEGER position; - ULARGE_INTEGER newPosition; - STREAMDATA streamData; - LOADDATA loadData; - ULONG ulRead; - HDPA hDpa; - PVOID *ptr; - - FIXME ("phDpa=%p loadProc=%p pStream=%p lParam=%lx\n", - phDpa, loadProc, pStream, lParam); - - if (!phDpa || !loadProc || !pStream) - return E_INVALIDARG; - - *phDpa = (HDPA)NULL; - - position.QuadPart = 0; - - /* - * Zero out our streamData - */ - memset(&streamData,0,sizeof(STREAMDATA)); - - errCode = IStream_Seek (pStream, position, STREAM_SEEK_CUR, &newPosition); - if (errCode != S_OK) - return errCode; - - errCode = IStream_Read (pStream, &streamData, sizeof(STREAMDATA), &ulRead); - if (errCode != S_OK) - return errCode; - - FIXME ("dwSize=%lu dwData2=%lu dwItems=%lu\n", - streamData.dwSize, streamData.dwData2, streamData.dwItems); - - if ( ulRead < sizeof(STREAMDATA) || - lParam < sizeof(STREAMDATA) || - streamData.dwSize < sizeof(STREAMDATA) || - streamData.dwData2 < 1) { - errCode = E_FAIL; - } - - if (streamData.dwItems > (UINT_MAX / 2 / sizeof(VOID*))) /* 536870911 */ - return E_OUTOFMEMORY; - - /* create the dpa */ - hDpa = DPA_Create (streamData.dwItems); - if (!hDpa) - return E_OUTOFMEMORY; - - if (!DPA_Grow (hDpa, streamData.dwItems)) - return E_OUTOFMEMORY; - - /* load data from the stream into the dpa */ - ptr = hDpa->ptrs; - for (loadData.nCount = 0; loadData.nCount < streamData.dwItems; loadData.nCount++) { - errCode = (loadProc)(&loadData, pStream, lParam); - if (errCode != S_OK) { - errCode = S_FALSE; - break; - } - - *ptr = loadData.ptr; - ptr++; - } - - /* set the number of items */ - hDpa->nItemCount = loadData.nCount; - - /* store the handle to the dpa */ - *phDpa = hDpa; - FIXME ("new hDpa=%p, errorcode=%lx\n", hDpa, errCode); - - return errCode; -} - - -/************************************************************************** - * DPA_SaveStream [COMCTL32.10] - * - * Saves a dynamic pointer array to a stream - * - * PARAMS - * hDpa [I] handle to a dynamic pointer array - * loadProc [I] pointer to a callback function - * pStream [I] pointer to a stream - * lParam [I] application specific value - * - * RETURNS - * Success: TRUE - * Failure: FALSE - * - * NOTES - * No more information available yet! - */ -HRESULT WINAPI DPA_SaveStream (const HDPA hDpa, DPALOADPROC loadProc, - IStream *pStream, LPARAM lParam) -{ - - FIXME ("hDpa=%p loadProc=%p pStream=%p lParam=%lx\n", - hDpa, loadProc, pStream, lParam); - - return E_FAIL; -} - - -/************************************************************************** - * DPA_Merge [COMCTL32.11] - * - * Merge two dynamic pointers arrays. - * - * PARAMS - * hdpa1 [I] handle to a dynamic pointer array - * hdpa2 [I] handle to a dynamic pointer array - * dwFlags [I] flags - * pfnCompare [I] pointer to sort function - * pfnMerge [I] pointer to merge function - * lParam [I] application specific value - * - * RETURNS - * Success: TRUE - * Failure: FALSE - * - * NOTES - * No more information available yet! - */ -BOOL WINAPI DPA_Merge (const HDPA hdpa1, const HDPA hdpa2, DWORD dwFlags, - PFNDPACOMPARE pfnCompare, PFNDPAMERGE pfnMerge, - LPARAM lParam) -{ - INT nCount; - LPVOID *pWork1, *pWork2; - INT nResult, i; - INT nIndex; - - TRACE("%p %p %08lx %p %p %08lx)\n", - hdpa1, hdpa2, dwFlags, pfnCompare, pfnMerge, lParam); - - if (IsBadWritePtr (hdpa1, sizeof(*hdpa1))) - return FALSE; - - if (IsBadWritePtr (hdpa2, sizeof(*hdpa2))) - return FALSE; - - if (IsBadCodePtr ((FARPROC)pfnCompare)) - return FALSE; - - if (IsBadCodePtr ((FARPROC)pfnMerge)) - return FALSE; - - if (!(dwFlags & DPAM_NOSORT)) { - TRACE("sorting dpa's!\n"); - if (hdpa1->nItemCount > 0) - DPA_Sort (hdpa1, pfnCompare, lParam); - TRACE ("dpa 1 sorted!\n"); - if (hdpa2->nItemCount > 0) - DPA_Sort (hdpa2, pfnCompare, lParam); - TRACE ("dpa 2 sorted!\n"); - } - - if (hdpa2->nItemCount < 1) - return TRUE; - - TRACE("hdpa1->nItemCount=%d hdpa2->nItemCount=%d\n", - hdpa1->nItemCount, hdpa2->nItemCount); - - - /* working but untrusted implementation */ - - pWork1 = &(hdpa1->ptrs[hdpa1->nItemCount - 1]); - pWork2 = &(hdpa2->ptrs[hdpa2->nItemCount - 1]); - - nIndex = hdpa1->nItemCount - 1; - nCount = hdpa2->nItemCount - 1; - - do - { - if (nIndex < 0) { - if ((nCount >= 0) && (dwFlags & DPAM_INSERT)) { - /* Now insert the remaining new items into DPA 1 */ - TRACE("%d items to be inserted at start of DPA 1\n", - nCount+1); - for (i=nCount; i>=0; i--) { - PVOID ptr; - - ptr = (pfnMerge)(3, *pWork2, NULL, lParam); - if (!ptr) - return FALSE; - DPA_InsertPtr (hdpa1, 0, ptr); - pWork2--; - } - } - break; - } - nResult = (pfnCompare)(*pWork1, *pWork2, lParam); - TRACE("compare result=%d, dpa1.cnt=%d, dpa2.cnt=%d\n", - nResult, nIndex, nCount); - - if (nResult == 0) - { - PVOID ptr; - - ptr = (pfnMerge)(1, *pWork1, *pWork2, lParam); - if (!ptr) - return FALSE; - - nCount--; - pWork2--; - *pWork1 = ptr; - nIndex--; - pWork1--; - } - else if (nResult > 0) - { - /* item in DPA 1 missing from DPA 2 */ - if (dwFlags & DPAM_DELETE) - { - /* Now delete the extra item in DPA1 */ - PVOID ptr; - - ptr = DPA_DeletePtr (hdpa1, hdpa1->nItemCount - 1); - - (pfnMerge)(2, ptr, NULL, lParam); - } - nIndex--; - pWork1--; - } - else - { - /* new item in DPA 2 */ - if (dwFlags & DPAM_INSERT) - { - /* Now insert the new item in DPA 1 */ - PVOID ptr; - - ptr = (pfnMerge)(3, *pWork2, NULL, lParam); - if (!ptr) - return FALSE; - DPA_InsertPtr (hdpa1, nIndex+1, ptr); - } - nCount--; - pWork2--; - } - - } - while (nCount >= 0); - - return TRUE; -} - - /************************************************************************** * Alloc [COMCTL32.71] * @@ -1415,912 +1110,6 @@ BOOL Str_SetPtrAtoW (LPWSTR *lppDest, LPCSTR lpSrc) } -/************************************************************************** - * DSA_Create [COMCTL32.320] - * - * Creates a dynamic storage array - * - * PARAMS - * nSize [I] size of the array elements - * nGrow [I] number of elements by which the array grows when it is filled - * - * RETURNS - * Success: pointer to an array control structure. Use this like a handle. - * Failure: NULL - * - * NOTES - * The DSA_ functions can be used to create and manipulate arrays of - * fixed-size memory blocks. These arrays can store any kind of data - * (e.g. strings and icons). - */ -HDSA WINAPI DSA_Create (INT nSize, INT nGrow) -{ - HDSA hdsa; - - TRACE("(size=%d grow=%d)\n", nSize, nGrow); - - hdsa = Alloc (sizeof(*hdsa)); - if (hdsa) - { - hdsa->nItemCount = 0; - hdsa->pData = NULL; - hdsa->nMaxCount = 0; - hdsa->nItemSize = nSize; - hdsa->nGrow = max(1, nGrow); - } - - return hdsa; -} - - -/************************************************************************** - * DSA_Destroy [COMCTL32.321] - * - * Destroys a dynamic storage array - * - * PARAMS - * hdsa [I] pointer to the array control structure - * - * RETURNS - * Success: TRUE - * Failure: FALSE - */ -BOOL WINAPI DSA_Destroy (const HDSA hdsa) -{ - TRACE("(%p)\n", hdsa); - - if (!hdsa) - return FALSE; - - if (hdsa->pData && (!Free (hdsa->pData))) - return FALSE; - - return Free (hdsa); -} - - -/************************************************************************** - * DSA_GetItem [COMCTL32.322] - * - * Copies the specified item into a caller-supplied buffer. - * - * PARAMS - * hdsa [I] pointer to the array control structure - * nIndex [I] number of the Item to get - * pDest [O] destination buffer. Has to be >= dwElementSize. - * - * RETURNS - * Success: TRUE - * Failure: FALSE - */ -BOOL WINAPI DSA_GetItem (const HDSA hdsa, INT nIndex, LPVOID pDest) -{ - LPVOID pSrc; - - TRACE("(%p %d %p)\n", hdsa, nIndex, pDest); - - if (!hdsa) - return FALSE; - if ((nIndex < 0) || (nIndex >= hdsa->nItemCount)) - return FALSE; - - pSrc = (char *) hdsa->pData + (hdsa->nItemSize * nIndex); - memmove (pDest, pSrc, hdsa->nItemSize); - - return TRUE; -} - - -/************************************************************************** - * DSA_GetItemPtr [COMCTL32.323] - * - * Retrieves a pointer to the specified item. - * - * PARAMS - * hdsa [I] pointer to the array control structure - * nIndex [I] index of the desired item - * - * RETURNS - * Success: pointer to an item - * Failure: NULL - */ -LPVOID WINAPI DSA_GetItemPtr (const HDSA hdsa, INT nIndex) -{ - LPVOID pSrc; - - TRACE("(%p %d)\n", hdsa, nIndex); - - if (!hdsa) - return NULL; - if ((nIndex < 0) || (nIndex >= hdsa->nItemCount)) - return NULL; - - pSrc = (char *) hdsa->pData + (hdsa->nItemSize * nIndex); - - TRACE("-- ret=%p\n", pSrc); - - return pSrc; -} - - -/************************************************************************** - * DSA_SetItem [COMCTL32.325] - * - * Sets the contents of an item in the array. - * - * PARAMS - * hdsa [I] pointer to the array control structure - * nIndex [I] index for the item - * pSrc [I] pointer to the new item data - * - * RETURNS - * Success: TRUE - * Failure: FALSE - */ -BOOL WINAPI DSA_SetItem (const HDSA hdsa, INT nIndex, LPVOID pSrc) -{ - INT nSize, nNewItems; - LPVOID pDest, lpTemp; - - TRACE("(%p %d %p)\n", hdsa, nIndex, pSrc); - - if ((!hdsa) || nIndex < 0) - return FALSE; - - if (hdsa->nItemCount <= nIndex) { - /* within the old array */ - if (hdsa->nMaxCount > nIndex) { - /* within the allocated space, set a new boundary */ - hdsa->nItemCount = nIndex + 1; - } - else { - /* resize the block of memory */ - nNewItems = - hdsa->nGrow * ((INT)(((nIndex + 1) - 1) / hdsa->nGrow) + 1); - nSize = hdsa->nItemSize * nNewItems; - - lpTemp = ReAlloc (hdsa->pData, nSize); - if (!lpTemp) - return FALSE; - - hdsa->nMaxCount = nNewItems; - hdsa->nItemCount = nIndex + 1; - hdsa->pData = lpTemp; - } - } - - /* put the new entry in */ - pDest = (char *) hdsa->pData + (hdsa->nItemSize * nIndex); - TRACE("-- move dest=%p src=%p size=%d\n", - pDest, pSrc, hdsa->nItemSize); - memmove (pDest, pSrc, hdsa->nItemSize); - - return TRUE; -} - - -/************************************************************************** - * DSA_InsertItem [COMCTL32.324] - * - * Inserts an item into the array at the specified index. - * - * PARAMS - * hdsa [I] pointer to the array control structure - * nIndex [I] index for the new item - * pSrc [I] pointer to the element - * - * RETURNS - * Success: position of the new item - * Failure: -1 - */ -INT WINAPI DSA_InsertItem (const HDSA hdsa, INT nIndex, LPVOID pSrc) -{ - INT nNewItems, nSize; - LPVOID lpTemp, lpDest; - - TRACE("(%p %d %p)\n", hdsa, nIndex, pSrc); - - if ((!hdsa) || nIndex < 0) - return -1; - - /* when nIndex >= nItemCount then append */ - if (nIndex >= hdsa->nItemCount) - nIndex = hdsa->nItemCount; - - /* do we need to resize ? */ - if (hdsa->nItemCount >= hdsa->nMaxCount) { - nNewItems = hdsa->nMaxCount + hdsa->nGrow; - nSize = hdsa->nItemSize * nNewItems; - - lpTemp = ReAlloc (hdsa->pData, nSize); - if (!lpTemp) - return -1; - - hdsa->nMaxCount = nNewItems; - hdsa->pData = lpTemp; - } - - /* do we need to move elements ? */ - if (nIndex < hdsa->nItemCount) { - lpTemp = (char *) hdsa->pData + (hdsa->nItemSize * nIndex); - lpDest = (char *) lpTemp + hdsa->nItemSize; - nSize = (hdsa->nItemCount - nIndex) * hdsa->nItemSize; - TRACE("-- move dest=%p src=%p size=%d\n", - lpDest, lpTemp, nSize); - memmove (lpDest, lpTemp, nSize); - } - - /* ok, we can put the new Item in */ - hdsa->nItemCount++; - lpDest = (char *) hdsa->pData + (hdsa->nItemSize * nIndex); - TRACE("-- move dest=%p src=%p size=%d\n", - lpDest, pSrc, hdsa->nItemSize); - memmove (lpDest, pSrc, hdsa->nItemSize); - - return nIndex; -} - - -/************************************************************************** - * DSA_DeleteItem [COMCTL32.326] - * - * Deletes the specified item from the array. - * - * PARAMS - * hdsa [I] pointer to the array control structure - * nIndex [I] index for the element to delete - * - * RETURNS - * Success: number of the deleted element - * Failure: -1 - */ -INT WINAPI DSA_DeleteItem (const HDSA hdsa, INT nIndex) -{ - LPVOID lpDest,lpSrc; - INT nSize; - - TRACE("(%p %d)\n", hdsa, nIndex); - - if (!hdsa) - return -1; - if (nIndex < 0 || nIndex >= hdsa->nItemCount) - return -1; - - /* do we need to move ? */ - if (nIndex < hdsa->nItemCount - 1) { - lpDest = (char *) hdsa->pData + (hdsa->nItemSize * nIndex); - lpSrc = (char *) lpDest + hdsa->nItemSize; - nSize = hdsa->nItemSize * (hdsa->nItemCount - nIndex - 1); - TRACE("-- move dest=%p src=%p size=%d\n", - lpDest, lpSrc, nSize); - memmove (lpDest, lpSrc, nSize); - } - - hdsa->nItemCount--; - - /* free memory ? */ - if ((hdsa->nMaxCount - hdsa->nItemCount) >= hdsa->nGrow) { - nSize = hdsa->nItemSize * hdsa->nItemCount; - - lpDest = ReAlloc (hdsa->pData, nSize); - if (!lpDest) - return -1; - - hdsa->nMaxCount = hdsa->nItemCount; - hdsa->pData = lpDest; - } - - return nIndex; -} - - -/************************************************************************** - * DSA_DeleteAllItems [COMCTL32.327] - * - * Removes all items and reinitializes the array. - * - * PARAMS - * hdsa [I] pointer to the array control structure - * - * RETURNS - * Success: TRUE - * Failure: FALSE - */ -BOOL WINAPI DSA_DeleteAllItems (const HDSA hdsa) -{ - TRACE("(%p)\n", hdsa); - - if (!hdsa) - return FALSE; - if (hdsa->pData && (!Free (hdsa->pData))) - return FALSE; - - hdsa->nItemCount = 0; - hdsa->pData = NULL; - hdsa->nMaxCount = 0; - - return TRUE; -} - - -/************************************************************************** - * DPA_Destroy [COMCTL32.329] - * - * Destroys a dynamic pointer array - * - * PARAMS - * hdpa [I] handle (pointer) to the pointer array - * - * RETURNS - * Success: TRUE - * Failure: FALSE - */ -BOOL WINAPI DPA_Destroy (const HDPA hdpa) -{ - TRACE("(%p)\n", hdpa); - - if (!hdpa) - return FALSE; - - if (hdpa->ptrs && (!HeapFree (hdpa->hHeap, 0, hdpa->ptrs))) - return FALSE; - - return HeapFree (hdpa->hHeap, 0, hdpa); -} - - -/************************************************************************** - * DPA_Grow [COMCTL32.330] - * - * Sets the growth amount. - * - * PARAMS - * hdpa [I] handle (pointer) to the existing (source) pointer array - * nGrow [I] number of items by which the array grows when it's too small - * - * RETURNS - * Success: TRUE - * Failure: FALSE - */ -BOOL WINAPI DPA_Grow (const HDPA hdpa, INT nGrow) -{ - TRACE("(%p %d)\n", hdpa, nGrow); - - if (!hdpa) - return FALSE; - - hdpa->nGrow = max(8, nGrow); - - return TRUE; -} - - -/************************************************************************** - * DPA_Clone [COMCTL32.331] - * - * Copies a pointer array to an other one or creates a copy - * - * PARAMS - * hdpa [I] handle (pointer) to the existing (source) pointer array - * hdpaNew [O] handle (pointer) to the destination pointer array - * - * RETURNS - * Success: pointer to the destination pointer array. - * Failure: NULL - * - * NOTES - * - If the 'hdpaNew' is a NULL-Pointer, a copy of the source pointer - * array will be created and it's handle (pointer) is returned. - * - If 'hdpa' is a NULL-Pointer, the original implementation crashes, - * this implementation just returns NULL. - */ -HDPA WINAPI DPA_Clone (const HDPA hdpa, const HDPA hdpaNew) -{ - INT nNewItems, nSize; - HDPA hdpaTemp; - - if (!hdpa) - return NULL; - - TRACE("(%p %p)\n", hdpa, hdpaNew); - - if (!hdpaNew) { - /* create a new DPA */ - hdpaTemp = HeapAlloc (hdpa->hHeap, HEAP_ZERO_MEMORY, - sizeof(*hdpaTemp)); - hdpaTemp->hHeap = hdpa->hHeap; - hdpaTemp->nGrow = hdpa->nGrow; - } - else - hdpaTemp = hdpaNew; - - if (hdpaTemp->ptrs) { - /* remove old pointer array */ - HeapFree (hdpaTemp->hHeap, 0, hdpaTemp->ptrs); - hdpaTemp->ptrs = NULL; - hdpaTemp->nItemCount = 0; - hdpaTemp->nMaxCount = 0; - } - - /* create a new pointer array */ - nNewItems = hdpaTemp->nGrow * - ((INT)((hdpa->nItemCount - 1) / hdpaTemp->nGrow) + 1); - nSize = nNewItems * sizeof(LPVOID); - hdpaTemp->ptrs = HeapAlloc (hdpaTemp->hHeap, HEAP_ZERO_MEMORY, nSize); - hdpaTemp->nMaxCount = nNewItems; - - /* clone the pointer array */ - hdpaTemp->nItemCount = hdpa->nItemCount; - memmove (hdpaTemp->ptrs, hdpa->ptrs, - hdpaTemp->nItemCount * sizeof(LPVOID)); - - return hdpaTemp; -} - - -/************************************************************************** - * DPA_GetPtr [COMCTL32.332] - * - * Retrieves a pointer from a dynamic pointer array - * - * PARAMS - * hdpa [I] handle (pointer) to the pointer array - * nIndex [I] array index of the desired pointer - * - * RETURNS - * Success: pointer - * Failure: NULL - */ -LPVOID WINAPI DPA_GetPtr (const HDPA hdpa, INT nIndex) -{ - TRACE("(%p %d)\n", hdpa, nIndex); - - if (!hdpa) - return NULL; - if (!hdpa->ptrs) { - WARN("no pointer array.\n"); - return NULL; - } - if ((nIndex < 0) || (nIndex >= hdpa->nItemCount)) { - WARN("not enough pointers in array (%d vs %d).\n",nIndex,hdpa->nItemCount); - return NULL; - } - - TRACE("-- %p\n", hdpa->ptrs[nIndex]); - - return hdpa->ptrs[nIndex]; -} - - -/************************************************************************** - * DPA_GetPtrIndex [COMCTL32.333] - * - * Retrieves the index of the specified pointer - * - * PARAMS - * hdpa [I] handle (pointer) to the pointer array - * p [I] pointer - * - * RETURNS - * Success: index of the specified pointer - * Failure: -1 - */ -INT WINAPI DPA_GetPtrIndex (const HDPA hdpa, LPVOID p) -{ - INT i; - - if (!hdpa || !hdpa->ptrs) - return -1; - - for (i = 0; i < hdpa->nItemCount; i++) { - if (hdpa->ptrs[i] == p) - return i; - } - - return -1; -} - - -/************************************************************************** - * DPA_InsertPtr [COMCTL32.334] - * - * Inserts a pointer into a dynamic pointer array - * - * PARAMS - * hdpa [I] handle (pointer) to the array - * i [I] array index - * p [I] pointer to insert - * - * RETURNS - * Success: index of the inserted pointer - * Failure: -1 - */ -INT WINAPI DPA_InsertPtr (const HDPA hdpa, INT i, LPVOID p) -{ - TRACE("(%p %d %p)\n", hdpa, i, p); - - if (!hdpa || i < 0) return -1; - - if (i >= 0x7fff) - i = hdpa->nItemCount; - - if (i >= hdpa->nItemCount) - return DPA_SetPtr(hdpa, i, p) ? i : -1; - - /* create empty spot at the end */ - if (!DPA_SetPtr(hdpa, hdpa->nItemCount, 0)) return -1; - memmove (hdpa->ptrs + i + 1, hdpa->ptrs + i, (hdpa->nItemCount - i - 1) * sizeof(LPVOID)); - hdpa->ptrs[i] = p; - return i; -} - -/************************************************************************** - * DPA_SetPtr [COMCTL32.335] - * - * Sets a pointer in the pointer array - * - * PARAMS - * hdpa [I] handle (pointer) to the pointer array - * i [I] index of the pointer that will be set - * p [I] pointer to be set - * - * RETURNS - * Success: TRUE - * Failure: FALSE - */ -BOOL WINAPI DPA_SetPtr (const HDPA hdpa, INT i, LPVOID p) -{ - LPVOID *lpTemp; - - TRACE("(%p %d %p)\n", hdpa, i, p); - - if (!hdpa || i < 0 || i > 0x7fff) - return FALSE; - - if (hdpa->nItemCount <= i) { - /* within the old array */ - if (hdpa->nMaxCount <= i) { - /* resize the block of memory */ - INT nNewItems = - hdpa->nGrow * ((INT)(((i+1) - 1) / hdpa->nGrow) + 1); - INT nSize = nNewItems * sizeof(LPVOID); - - if (hdpa->ptrs) - lpTemp = HeapReAlloc (hdpa->hHeap, HEAP_ZERO_MEMORY, hdpa->ptrs, nSize); - else - lpTemp = HeapAlloc (hdpa->hHeap, HEAP_ZERO_MEMORY, nSize); - - if (!lpTemp) - return FALSE; - - hdpa->nMaxCount = nNewItems; - hdpa->ptrs = lpTemp; - } - hdpa->nItemCount = i+1; - } - - /* put the new entry in */ - hdpa->ptrs[i] = p; - - return TRUE; -} - - -/************************************************************************** - * DPA_DeletePtr [COMCTL32.336] - * - * Removes a pointer from the pointer array. - * - * PARAMS - * hdpa [I] handle (pointer) to the pointer array - * i [I] index of the pointer that will be deleted - * - * RETURNS - * Success: deleted pointer - * Failure: NULL - */ -LPVOID WINAPI DPA_DeletePtr (const HDPA hdpa, INT i) -{ - LPVOID *lpDest, *lpSrc, lpTemp = NULL; - INT nSize; - - TRACE("(%p %d)\n", hdpa, i); - - if ((!hdpa) || i < 0 || i >= hdpa->nItemCount) - return NULL; - - lpTemp = hdpa->ptrs[i]; - - /* do we need to move ?*/ - if (i < hdpa->nItemCount - 1) { - lpDest = hdpa->ptrs + i; - lpSrc = lpDest + 1; - nSize = (hdpa->nItemCount - i - 1) * sizeof(LPVOID); - TRACE("-- move dest=%p src=%p size=%x\n", - lpDest, lpSrc, nSize); - memmove (lpDest, lpSrc, nSize); - } - - hdpa->nItemCount --; - - /* free memory ?*/ - if ((hdpa->nMaxCount - hdpa->nItemCount) >= hdpa->nGrow) { - INT nNewItems = max(hdpa->nGrow * 2, hdpa->nItemCount); - nSize = nNewItems * sizeof(LPVOID); - lpDest = HeapReAlloc (hdpa->hHeap, HEAP_ZERO_MEMORY, - hdpa->ptrs, nSize); - if (!lpDest) - return NULL; - - hdpa->nMaxCount = nNewItems; - hdpa->ptrs = (LPVOID*)lpDest; - } - - return lpTemp; -} - - -/************************************************************************** - * DPA_DeleteAllPtrs [COMCTL32.337] - * - * Removes all pointers and reinitializes the array. - * - * PARAMS - * hdpa [I] handle (pointer) to the pointer array - * - * RETURNS - * Success: TRUE - * Failure: FALSE - */ -BOOL WINAPI DPA_DeleteAllPtrs (const HDPA hdpa) -{ - TRACE("(%p)\n", hdpa); - - if (!hdpa) - return FALSE; - - if (hdpa->ptrs && (!HeapFree (hdpa->hHeap, 0, hdpa->ptrs))) - return FALSE; - - hdpa->nItemCount = 0; - hdpa->nMaxCount = hdpa->nGrow * 2; - hdpa->ptrs = HeapAlloc (hdpa->hHeap, HEAP_ZERO_MEMORY, - hdpa->nMaxCount * sizeof(LPVOID)); - - return TRUE; -} - - -/************************************************************************** - * DPA_QuickSort [Internal] - * - * Ordinary quicksort (used by DPA_Sort). - * - * PARAMS - * lpPtrs [I] pointer to the pointer array - * l [I] index of the "left border" of the partition - * r [I] index of the "right border" of the partition - * pfnCompare [I] pointer to the compare function - * lParam [I] user defined value (3rd parameter in compare function) - * - * RETURNS - * NONE - */ -static VOID DPA_QuickSort (LPVOID *lpPtrs, INT l, INT r, - PFNDPACOMPARE pfnCompare, LPARAM lParam) -{ - INT m; - LPVOID t; - - TRACE("l=%i r=%i\n", l, r); - - if (l==r) /* one element is always sorted */ - return; - if (r0) - { - t = lpPtrs[m+1]; - memmove(&lpPtrs[l+1],&lpPtrs[l],(m-l+1)*sizeof(lpPtrs[l])); - lpPtrs[l] = t; - - m++; - } - l++; - } -} - - -/************************************************************************** - * DPA_Sort [COMCTL32.338] - * - * Sorts a pointer array using a user defined compare function - * - * PARAMS - * hdpa [I] handle (pointer) to the pointer array - * pfnCompare [I] pointer to the compare function - * lParam [I] user defined value (3rd parameter of compare function) - * - * RETURNS - * Success: TRUE - * Failure: FALSE - */ -BOOL WINAPI DPA_Sort (const HDPA hdpa, PFNDPACOMPARE pfnCompare, LPARAM lParam) -{ - if (!hdpa || !pfnCompare) - return FALSE; - - TRACE("(%p %p 0x%lx)\n", hdpa, pfnCompare, lParam); - - if ((hdpa->nItemCount > 1) && (hdpa->ptrs)) - DPA_QuickSort (hdpa->ptrs, 0, hdpa->nItemCount - 1, - pfnCompare, lParam); - - return TRUE; -} - - -/************************************************************************** - * DPA_Search [COMCTL32.339] - * - * Searches a pointer array for a specified pointer - * - * PARAMS - * hdpa [I] handle (pointer) to the pointer array - * pFind [I] pointer to search for - * nStart [I] start index - * pfnCompare [I] pointer to the compare function - * lParam [I] user defined value (3rd parameter of compare function) - * uOptions [I] search options - * - * RETURNS - * Success: index of the pointer in the array. - * Failure: -1 - * - * NOTES - * Binary search taken from R.Sedgewick "Algorithms in C"! - * Function is NOT tested! - * If something goes wrong, blame HIM not ME! (Eric Kohl) - */ -INT WINAPI DPA_Search (const HDPA hdpa, LPVOID pFind, INT nStart, - PFNDPACOMPARE pfnCompare, LPARAM lParam, UINT uOptions) -{ - if (!hdpa || !pfnCompare || !pFind) - return -1; - - TRACE("(%p %p %d %p 0x%08lx 0x%08x)\n", - hdpa, pFind, nStart, pfnCompare, lParam, uOptions); - - if (uOptions & DPAS_SORTED) { - /* array is sorted --> use binary search */ - INT l, r, x, n; - LPVOID *lpPtr; - - TRACE("binary search\n"); - - l = (nStart == -1) ? 0 : nStart; - r = hdpa->nItemCount - 1; - lpPtr = hdpa->ptrs; - while (r >= l) { - x = (l + r) / 2; - n = (pfnCompare)(pFind, lpPtr[x], lParam); - if (n < 0) - r = x - 1; - else - l = x + 1; - if (n == 0) { - TRACE("-- ret=%d\n", n); - return n; - } - } - - if (uOptions & DPAS_INSERTBEFORE) { - if (r == -1) r = 0; - TRACE("-- ret=%d\n", r); - return r; - } - - if (uOptions & DPAS_INSERTAFTER) { - TRACE("-- ret=%d\n", l); - return l; - } - } - else { - /* array is not sorted --> use linear search */ - LPVOID *lpPtr; - INT nIndex; - - TRACE("linear search\n"); - - nIndex = (nStart == -1)? 0 : nStart; - lpPtr = hdpa->ptrs; - for (; nIndex < hdpa->nItemCount; nIndex++) { - if ((pfnCompare)(pFind, lpPtr[nIndex], lParam) == 0) { - TRACE("-- ret=%d\n", nIndex); - return nIndex; - } - } - } - - TRACE("-- not found: ret=-1\n"); - return -1; -} - - -/************************************************************************** - * DPA_CreateEx [COMCTL32.340] - * - * Creates a dynamic pointer array using the specified size and heap. - * - * PARAMS - * nGrow [I] number of items by which the array grows when it is filled - * hHeap [I] handle to the heap where the array is stored - * - * RETURNS - * Success: handle (pointer) to the pointer array. - * Failure: NULL - * - * NOTES - * The DPA_ functions can be used to create and manipulate arrays of - * pointers. - */ -HDPA WINAPI DPA_CreateEx (INT nGrow, HANDLE hHeap) -{ - HDPA hdpa; - - TRACE("(%d %p)\n", nGrow, hHeap); - - if (hHeap) - hdpa = HeapAlloc (hHeap, HEAP_ZERO_MEMORY, sizeof(*hdpa)); - else - hdpa = Alloc (sizeof(*hdpa)); - - if (hdpa) { - hdpa->nGrow = max(8, nGrow); - hdpa->hHeap = hHeap ? hHeap : GetProcessHeap(); - hdpa->nMaxCount = hdpa->nGrow * 2; - hdpa->ptrs = HeapAlloc (hdpa->hHeap, HEAP_ZERO_MEMORY, - hdpa->nMaxCount * sizeof(LPVOID)); - } - - TRACE("-- %p\n", hdpa); - - return hdpa; -} - - -/************************************************************************** - * DPA_Create [COMCTL32.328] - * - * Creates a dynamic pointer array. - * - * PARAMS - * nGrow [I] number of items by which the array grows when it is filled - * - * RETURNS - * Success: handle (pointer) to the pointer array. - * Failure: NULL - * - * NOTES - * The DPA_ functions can be used to create and manipulate arrays of - * pointers. - */ -HDPA WINAPI DPA_Create (INT nGrow) -{ - return DPA_CreateEx( nGrow, 0 ); -} - - /************************************************************************** * Notification functions */ @@ -2454,120 +1243,3 @@ LRESULT WINAPI SendNotifyEx (HWND hwndTo, HWND hwndFrom, UINT uCode, return DoNotify (¬ify, uCode, lpHdr); } - - - - -/************************************************************************** - * DPA_EnumCallback [COMCTL32.385] - * - * Enumerates all items in a dynamic pointer array. - * - * PARAMS - * hdpa [I] handle to the dynamic pointer array - * enumProc [I] - * lParam [I] - * - * RETURNS - * none - */ -VOID WINAPI DPA_EnumCallback (HDPA hdpa, PFNDPAENUMCALLBACK enumProc, - LPVOID lParam) -{ - INT i; - - TRACE("(%p %p %p)\n", hdpa, enumProc, lParam); - - if (!hdpa) - return; - if (hdpa->nItemCount <= 0) - return; - - for (i = 0; i < hdpa->nItemCount; i++) { - if ((enumProc)(hdpa->ptrs[i], lParam) == 0) - return; - } - - return; -} - - -/************************************************************************** - * DPA_DestroyCallback [COMCTL32.386] - * - * Enumerates all items in a dynamic pointer array and destroys it. - * - * PARAMS - * hdpa [I] handle to the dynamic pointer array - * enumProc [I] - * lParam [I] - * - * RETURNS - * none - */ -void WINAPI DPA_DestroyCallback (HDPA hdpa, PFNDPAENUMCALLBACK enumProc, - LPVOID lParam) -{ - TRACE("(%p %p %p)\n", hdpa, enumProc, lParam); - - DPA_EnumCallback (hdpa, enumProc, lParam); - DPA_Destroy (hdpa); -} - - -/************************************************************************** - * DSA_EnumCallback [COMCTL32.387] - * - * Enumerates all items in a dynamic storage array. - * - * PARAMS - * hdsa [I] handle to the dynamic storage array - * enumProc [I] - * lParam [I] - * - * RETURNS - * none - */ -VOID WINAPI DSA_EnumCallback (HDSA hdsa, PFNDSAENUMCALLBACK enumProc, - LPVOID lParam) -{ - INT i; - - TRACE("(%p %p %p)\n", hdsa, enumProc, lParam); - - if (!hdsa) - return; - if (hdsa->nItemCount <= 0) - return; - - for (i = 0; i < hdsa->nItemCount; i++) { - LPVOID lpItem = DSA_GetItemPtr (hdsa, i); - if ((enumProc)(lpItem, lParam) == 0) - return; - } - - return; -} - - -/************************************************************************** - * DSA_DestroyCallback [COMCTL32.388] - * - * Enumerates all items in a dynamic storage array and destroys it. - * - * PARAMS - * hdsa [I] handle to the dynamic storage array - * enumProc [I] - * lParam [I] - * - * RETURNS - * none - */ -void WINAPI DSA_DestroyCallback (HDSA hdsa, PFNDSAENUMCALLBACK enumProc, - LPVOID lParam) -{ - TRACE("(%p %p %p)\n", hdsa, enumProc, lParam); - - DSA_EnumCallback (hdsa, enumProc, lParam); - DSA_Destroy (hdsa); -} diff --git a/reactos/lib/comctl32/comctl_Cn.rc b/reactos/lib/comctl32/comctl_Cn.rc index 9c2835ec60d..4b5a61fc699 100644 --- a/reactos/lib/comctl32/comctl_Cn.rc +++ b/reactos/lib/comctl32/comctl_Cn.rc @@ -37,9 +37,9 @@ STYLE DS_MODALFRAME | WS_POPUP | WS_CAPTION | WS_SYSMENU | WS_VISIBLE CAPTION "Wizard" FONT 8, "MS Shell Dlg" BEGIN - DEFPUSHBUTTON "结束", IDC_FINISH_BUTTON,121,138,50,14 - DEFPUSHBUTTON "下一步(&N) >", IDC_NEXT_BUTTON,121,138,50,14 PUSHBUTTON "< 上一步(&B)", IDC_BACK_BUTTON,71,138,50,14 + DEFPUSHBUTTON "下一步(&N) >", IDC_NEXT_BUTTON,121,138,50,14 + DEFPUSHBUTTON "结束", IDC_FINISH_BUTTON,121,138,50,14 PUSHBUTTON "取消", IDCANCEL,178,138,50,14 PUSHBUTTON "帮助", IDHELP,235,138,50,14,WS_GROUP LTEXT "", IDC_SUNKEN_LINE,7,129,278,1,SS_SUNKEN diff --git a/reactos/lib/comctl32/comctl_Cs.rc b/reactos/lib/comctl32/comctl_Cs.rc index 23e8b1bbb80..d93649620e3 100644 --- a/reactos/lib/comctl32/comctl_Cs.rc +++ b/reactos/lib/comctl32/comctl_Cs.rc @@ -39,9 +39,9 @@ STYLE DS_MODALFRAME | WS_POPUP | WS_CAPTION | WS_SYSMENU | WS_VISIBLE CAPTION "Pr鵹odce" FONT 8, "MS Shell Dlg" BEGIN - DEFPUSHBUTTON "Dokon鑙t", IDC_FINISH_BUTTON,121,138,50,14 - DEFPUSHBUTTON "&Dal鬼 >", IDC_NEXT_BUTTON,121,138,50,14 PUSHBUTTON "< &Zp靦", IDC_BACK_BUTTON,71,138,50,14 + DEFPUSHBUTTON "&Dal鬼 >", IDC_NEXT_BUTTON,121,138,50,14 + DEFPUSHBUTTON "Dokon鑙t", IDC_FINISH_BUTTON,121,138,50,14 PUSHBUTTON "Storno", IDCANCEL,178,138,50,14 PUSHBUTTON "N醦ov靌a", IDHELP,235,138,50,14,WS_GROUP LTEXT "", IDC_SUNKEN_LINE,7,129,278,1,SS_SUNKEN diff --git a/reactos/lib/comctl32/comctl_De.rc b/reactos/lib/comctl32/comctl_De.rc index 723368dd5c4..a2a0d2a42d7 100644 --- a/reactos/lib/comctl32/comctl_De.rc +++ b/reactos/lib/comctl32/comctl_De.rc @@ -57,9 +57,9 @@ STYLE DS_MODALFRAME | WS_POPUP | WS_CAPTION | WS_SYSMENU | WS_VISIBLE CAPTION "Wizard" FONT 8, "MS Shell Dlg" BEGIN - DEFPUSHBUTTON "&Beenden", IDC_FINISH_BUTTON,121,138,50,14 - DEFPUSHBUTTON "&Weiter >", IDC_NEXT_BUTTON,121,138,50,14 PUSHBUTTON "< &Zur點k", IDC_BACK_BUTTON,71,138,50,14 + DEFPUSHBUTTON "&Weiter >", IDC_NEXT_BUTTON,121,138,50,14 + DEFPUSHBUTTON "&Beenden", IDC_FINISH_BUTTON,121,138,50,14 PUSHBUTTON "Abbrechen", IDCANCEL,178,138,50,14 PUSHBUTTON "&Hilfe", IDHELP,235,138,50,14,WS_GROUP LTEXT "", IDC_SUNKEN_LINE,7,129,278,1,SS_SUNKEN diff --git a/reactos/lib/comctl32/comctl_En.rc b/reactos/lib/comctl32/comctl_En.rc index d6ee377b72f..8e95a13ad08 100644 --- a/reactos/lib/comctl32/comctl_En.rc +++ b/reactos/lib/comctl32/comctl_En.rc @@ -36,9 +36,9 @@ STYLE DS_MODALFRAME | WS_POPUP | WS_CAPTION | WS_SYSMENU | WS_VISIBLE CAPTION "Wizard" FONT 8, "MS Shell Dlg" BEGIN - DEFPUSHBUTTON "Finish", IDC_FINISH_BUTTON,121,138,50,14 - DEFPUSHBUTTON "&Next >", IDC_NEXT_BUTTON,121,138,50,14 PUSHBUTTON "< &Back", IDC_BACK_BUTTON,71,138,50,14 + DEFPUSHBUTTON "&Next >", IDC_NEXT_BUTTON,121,138,50,14 + DEFPUSHBUTTON "Finish", IDC_FINISH_BUTTON,121,138,50,14 PUSHBUTTON "Cancel", IDCANCEL,178,138,50,14 PUSHBUTTON "Help", IDHELP,235,138,50,14,WS_GROUP LTEXT "", IDC_SUNKEN_LINE,7,129,278,1,SS_SUNKEN diff --git a/reactos/lib/comctl32/comctl_Es.rc b/reactos/lib/comctl32/comctl_Es.rc index feb479b5451..42014589de4 100644 --- a/reactos/lib/comctl32/comctl_Es.rc +++ b/reactos/lib/comctl32/comctl_Es.rc @@ -36,9 +36,9 @@ STYLE DS_MODALFRAME | WS_POPUP | WS_CAPTION | WS_SYSMENU | WS_VISIBLE CAPTION "Ayudante" FONT 8, "MS Shell Dlg" BEGIN - DEFPUSHBUTTON "Terminar", IDC_FINISH_BUTTON,121,138,50,14 - DEFPUSHBUTTON "&Siguiente >", IDC_NEXT_BUTTON,121,138,50,14 PUSHBUTTON "< &Anterior", IDC_BACK_BUTTON,71,138,50,14 + DEFPUSHBUTTON "&Siguiente >", IDC_NEXT_BUTTON,121,138,50,14 + DEFPUSHBUTTON "Terminar", IDC_FINISH_BUTTON,121,138,50,14 PUSHBUTTON "Cancelar", IDCANCEL,178,138,50,14 PUSHBUTTON "Ayuda", IDHELP,235,138,50,14,WS_GROUP LTEXT "", IDC_SUNKEN_LINE,7,129,278,1,SS_SUNKEN diff --git a/reactos/lib/comctl32/comctl_Fr.rc b/reactos/lib/comctl32/comctl_Fr.rc index ad078c96ce5..dbc11734bab 100644 --- a/reactos/lib/comctl32/comctl_Fr.rc +++ b/reactos/lib/comctl32/comctl_Fr.rc @@ -40,9 +40,9 @@ STYLE DS_MODALFRAME | WS_POPUP | WS_CAPTION | WS_SYSMENU | WS_VISIBLE CAPTION "Assistant" FONT 8, "MS Shell Dlg" BEGIN - DEFPUSHBUTTON "Terminer", IDC_FINISH_BUTTON,121,138,50,14 - DEFPUSHBUTTON "&Suivant >", IDC_NEXT_BUTTON,121,138,50,14 PUSHBUTTON "< &Pr閏閐ent", IDC_BACK_BUTTON,71,138,50,14 + DEFPUSHBUTTON "&Suivant >", IDC_NEXT_BUTTON,121,138,50,14 + DEFPUSHBUTTON "Terminer", IDC_FINISH_BUTTON,121,138,50,14 PUSHBUTTON "Annuler", IDCANCEL,178,138,50,14 PUSHBUTTON "Aide", IDHELP,235,138,50,14,WS_GROUP LTEXT "", IDC_SUNKEN_LINE,7,129,278,1,SS_SUNKEN diff --git a/reactos/lib/comctl32/comctl_It.rc b/reactos/lib/comctl32/comctl_It.rc index c3251b64bb5..647eda45b2c 100644 --- a/reactos/lib/comctl32/comctl_It.rc +++ b/reactos/lib/comctl32/comctl_It.rc @@ -37,9 +37,9 @@ STYLE DS_MODALFRAME | WS_POPUP | WS_CAPTION | WS_SYSMENU | WS_VISIBLE CAPTION "Wizard" FONT 8, "MS Shell Dlg" BEGIN - DEFPUSHBUTTON "Fine", IDC_FINISH_BUTTON,121,138,50,14 - DEFPUSHBUTTON "&Avanti >", IDC_NEXT_BUTTON,121,138,50,14 PUSHBUTTON "< &Indietro", IDC_BACK_BUTTON,71,138,50,14 + DEFPUSHBUTTON "&Avanti >", IDC_NEXT_BUTTON,121,138,50,14 + DEFPUSHBUTTON "Fine", IDC_FINISH_BUTTON,121,138,50,14 PUSHBUTTON "Anulla", IDCANCEL,178,138,50,14 PUSHBUTTON "Aiuto", IDHELP,235,138,50,14,WS_GROUP LTEXT "", IDC_SUNKEN_LINE,7,129,278,1,SS_SUNKEN diff --git a/reactos/lib/comctl32/comctl_Ja.rc b/reactos/lib/comctl32/comctl_Ja.rc index 76246cee4b7..a02a2ccb034 100644 --- a/reactos/lib/comctl32/comctl_Ja.rc +++ b/reactos/lib/comctl32/comctl_Ja.rc @@ -36,9 +36,9 @@ STYLE DS_MODALFRAME | WS_POPUP | WS_CAPTION | WS_SYSMENU | WS_VISIBLE CAPTION "Wizard" FONT 9, "MS UI Gothic" BEGIN - DEFPUSHBUTTON "姰椆", IDC_FINISH_BUTTON,121,138,50,14 - DEFPUSHBUTTON "恑傓(&N) >", IDC_NEXT_BUTTON,121,138,50,14 PUSHBUTTON "< 栠傞(&B)", IDC_BACK_BUTTON,71,138,50,14 + DEFPUSHBUTTON "恑傓(&N) >", IDC_NEXT_BUTTON,121,138,50,14 + DEFPUSHBUTTON "姰椆", IDC_FINISH_BUTTON,121,138,50,14 PUSHBUTTON "僉儍儞僙儖", IDCANCEL,178,138,50,14 PUSHBUTTON "僿儖僾", IDHELP,235,138,50,14,WS_GROUP LTEXT "", IDC_SUNKEN_LINE,7,129,278,1,SS_SUNKEN diff --git a/reactos/lib/comctl32/comctl_Ko.rc b/reactos/lib/comctl32/comctl_Ko.rc index 1ef0cf20a80..1198eb016ef 100644 --- a/reactos/lib/comctl32/comctl_Ko.rc +++ b/reactos/lib/comctl32/comctl_Ko.rc @@ -36,9 +36,9 @@ STYLE DS_MODALFRAME | WS_POPUP | WS_CAPTION | WS_SYSMENU | WS_VISIBLE CAPTION "Wizard" FONT 9, "MS Shell Dlg" BEGIN - DEFPUSHBUTTON "辆丰", IDC_FINISH_BUTTON,121,138,50,14 - DEFPUSHBUTTON "促澜(&N) >", IDC_NEXT_BUTTON,121,138,50,14 PUSHBUTTON "< 捞傈(&B)", IDC_BACK_BUTTON,71,138,50,14 + DEFPUSHBUTTON "促澜(&N) >", IDC_NEXT_BUTTON,121,138,50,14 + DEFPUSHBUTTON "辆丰", IDC_FINISH_BUTTON,121,138,50,14 PUSHBUTTON "秒家", IDCANCEL,178,138,50,14 PUSHBUTTON "档框富", IDHELP,235,138,50,14,WS_GROUP LTEXT "", IDC_SUNKEN_LINE,7,129,278,1,SS_SUNKEN diff --git a/reactos/lib/comctl32/comctl_Nl.rc b/reactos/lib/comctl32/comctl_Nl.rc index 2aa70684624..2e8764ad041 100644 --- a/reactos/lib/comctl32/comctl_Nl.rc +++ b/reactos/lib/comctl32/comctl_Nl.rc @@ -38,9 +38,9 @@ STYLE DS_MODALFRAME | WS_POPUP | WS_CAPTION | WS_SYSMENU | WS_VISIBLE CAPTION "Assistent" FONT 8, "MS Shell Dlg" BEGIN - DEFPUSHBUTTON "Be毛indigen", IDC_FINISH_BUTTON,121,138,50,14 - DEFPUSHBUTTON "&Volgende >", IDC_NEXT_BUTTON,121,138,50,14 PUSHBUTTON "< V&orige", IDC_BACK_BUTTON,71,138,50,14 + DEFPUSHBUTTON "&Volgende >", IDC_NEXT_BUTTON,121,138,50,14 + DEFPUSHBUTTON "Be毛indigen", IDC_FINISH_BUTTON,121,138,50,14 PUSHBUTTON "Annuleren", IDCANCEL,178,138,50,14 PUSHBUTTON "Help", IDHELP,235,138,50,14,WS_GROUP LTEXT "", IDC_SUNKEN_LINE,7,129,278,1,SS_SUNKEN diff --git a/reactos/lib/comctl32/comctl_Pl.rc b/reactos/lib/comctl32/comctl_Pl.rc index f0e64b6d345..d93ed6797b2 100644 --- a/reactos/lib/comctl32/comctl_Pl.rc +++ b/reactos/lib/comctl32/comctl_Pl.rc @@ -37,9 +37,9 @@ STYLE DS_MODALFRAME | WS_POPUP | WS_CAPTION | WS_SYSMENU | WS_VISIBLE CAPTION "Kreator" FONT 8, "MS Shell Dlg" BEGIN - DEFPUSHBUTTON "Zako馽z", IDC_FINISH_BUTTON,121,138,50,14 - DEFPUSHBUTTON "&Dalej >", IDC_NEXT_BUTTON,121,138,50,14 PUSHBUTTON "< &Wstecz", IDC_BACK_BUTTON,71,138,50,14 + DEFPUSHBUTTON "&Dalej >", IDC_NEXT_BUTTON,121,138,50,14 + DEFPUSHBUTTON "Zako馽z", IDC_FINISH_BUTTON,121,138,50,14 PUSHBUTTON "Anuluj", IDCANCEL,178,138,50,14 PUSHBUTTON "Pomoc", IDHELP,235,138,50,14,WS_GROUP LTEXT "", IDC_SUNKEN_LINE,7,129,278,1,SS_SUNKEN diff --git a/reactos/lib/comctl32/comctl_Pt.rc b/reactos/lib/comctl32/comctl_Pt.rc index 867aa17dae7..900c209a271 100644 --- a/reactos/lib/comctl32/comctl_Pt.rc +++ b/reactos/lib/comctl32/comctl_Pt.rc @@ -36,9 +36,9 @@ STYLE DS_MODALFRAME | WS_POPUP | WS_CAPTION | WS_SYSMENU | WS_VISIBLE CAPTION "Assistente" FONT 8, "MS Shell Dlg" BEGIN - DEFPUSHBUTTON "Finalizar", IDC_FINISH_BUTTON,121,138,50,14 - DEFPUSHBUTTON "&Avan鏰r >", IDC_NEXT_BUTTON,121,138,50,14 PUSHBUTTON "< &Voltar", IDC_BACK_BUTTON,71,138,50,14 + DEFPUSHBUTTON "&Avan鏰r >", IDC_NEXT_BUTTON,121,138,50,14 + DEFPUSHBUTTON "Finalizar", IDC_FINISH_BUTTON,121,138,50,14 PUSHBUTTON "Cancelar", IDCANCEL,178,138,50,14 PUSHBUTTON "Ajuda", IDHELP,235,138,50,14,WS_GROUP LTEXT "", IDC_SUNKEN_LINE,7,129,278,1,SS_SUNKEN diff --git a/reactos/lib/comctl32/comctl_Ru.rc b/reactos/lib/comctl32/comctl_Ru.rc index 3b4993da09f..6444e387328 100644 --- a/reactos/lib/comctl32/comctl_Ru.rc +++ b/reactos/lib/comctl32/comctl_Ru.rc @@ -38,9 +38,9 @@ STYLE DS_MODALFRAME | WS_POPUP | WS_CAPTION | WS_SYSMENU | WS_VISIBLE CAPTION "锑耱屦" FONT 8, "MS Shell Dlg" BEGIN - DEFPUSHBUTTON "青忮瘌栩", IDC_FINISH_BUTTON,121,138,50,14 - DEFPUSHBUTTON "&泥脲 >", IDC_NEXT_BUTTON,121,138,50,14 PUSHBUTTON "< &袜玎", IDC_BACK_BUTTON,71,138,50,14 + DEFPUSHBUTTON "&泥脲 >", IDC_NEXT_BUTTON,121,138,50,14 + DEFPUSHBUTTON "青忮瘌栩", IDC_FINISH_BUTTON,121,138,50,14 PUSHBUTTON "悟戾磬", IDCANCEL,178,138,50,14 PUSHBUTTON "&扬疣怅", IDHELP,235,138,50,14,WS_GROUP LTEXT "", IDC_SUNKEN_LINE,7,129,278,1,SS_SUNKEN diff --git a/reactos/lib/comctl32/comctl_Si.rc b/reactos/lib/comctl32/comctl_Si.rc index 445275248c6..0bf613de6a7 100644 --- a/reactos/lib/comctl32/comctl_Si.rc +++ b/reactos/lib/comctl32/comctl_Si.rc @@ -36,9 +36,9 @@ STYLE DS_MODALFRAME | WS_POPUP | WS_CAPTION | WS_SYSMENU | WS_VISIBLE CAPTION "萢rovnik" FONT 8, "MS Shell Dlg" BEGIN - DEFPUSHBUTTON "Dokon鑑j", IDC_FINISH_BUTTON,121,138,50,14 - DEFPUSHBUTTON "Naprej >", IDC_NEXT_BUTTON,121,138,50,14 PUSHBUTTON "< Na&zaj", IDC_BACK_BUTTON,71,138,50,14 + DEFPUSHBUTTON "Naprej >", IDC_NEXT_BUTTON,121,138,50,14 + DEFPUSHBUTTON "Dokon鑑j", IDC_FINISH_BUTTON,121,138,50,14 PUSHBUTTON "Prekli鑙", IDCANCEL,178,138,50,14 PUSHBUTTON "Pomo", IDHELP,235,138,50,14,WS_GROUP LTEXT "", IDC_SUNKEN_LINE,7,129,278,1,SS_SUNKEN diff --git a/reactos/lib/comctl32/comctl_Sv.rc b/reactos/lib/comctl32/comctl_Sv.rc index 273ee861da0..60f27a2b4e3 100644 --- a/reactos/lib/comctl32/comctl_Sv.rc +++ b/reactos/lib/comctl32/comctl_Sv.rc @@ -36,9 +36,9 @@ STYLE DS_MODALFRAME | WS_POPUP | WS_CAPTION | WS_SYSMENU | WS_VISIBLE CAPTION "Guide" FONT 8, "MS Shell Dlg" BEGIN - DEFPUSHBUTTON "Slutf鰎", IDC_FINISH_BUTTON,121,138,50,14 - DEFPUSHBUTTON "&N鋝ta >", IDC_NEXT_BUTTON,121,138,50,14 PUSHBUTTON "< &F鰎eg錯nde", IDC_BACK_BUTTON,71,138,50,14 + DEFPUSHBUTTON "&N鋝ta >", IDC_NEXT_BUTTON,121,138,50,14 + DEFPUSHBUTTON "Slutf鰎", IDC_FINISH_BUTTON,121,138,50,14 PUSHBUTTON "Avbryt", IDCANCEL,178,138,50,14 PUSHBUTTON "Hj鋖p", IDHELP,235,138,50,14,WS_GROUP LTEXT "", IDC_SUNKEN_LINE,7,129,278,1,SS_SUNKEN diff --git a/reactos/lib/comctl32/comctl_Th.rc b/reactos/lib/comctl32/comctl_Th.rc index 104fc76ee62..92317e5f072 100644 --- a/reactos/lib/comctl32/comctl_Th.rc +++ b/reactos/lib/comctl32/comctl_Th.rc @@ -36,9 +36,9 @@ STYLE DS_MODALFRAME | WS_POPUP | WS_CAPTION | WS_SYSMENU | WS_VISIBLE CAPTION "Wizard" FONT 8, "MS Shell Dlg" BEGIN - DEFPUSHBUTTON "讽毅碎嗍苗", IDC_FINISH_BUTTON,121,138,50,14 - DEFPUSHBUTTON "佃弯 >", IDC_NEXT_BUTTON,121,138,50,14 PUSHBUTTON "< 麻凸∨押", IDC_BACK_BUTTON,71,138,50,14 + DEFPUSHBUTTON "佃弯 >", IDC_NEXT_BUTTON,121,138,50,14 + DEFPUSHBUTTON "讽毅碎嗍苗", IDC_FINISH_BUTTON,121,138,50,14 PUSHBUTTON "隆嗯浴", IDCANCEL,178,138,50,14 PUSHBUTTON "锹嗨耪", IDHELP,235,138,50,14,WS_GROUP LTEXT "", IDC_SUNKEN_LINE,7,129,278,1,SS_SUNKEN diff --git a/reactos/lib/comctl32/comctl_Uk.rc b/reactos/lib/comctl32/comctl_Uk.rc index 3c86116d734..4cee185333c 100644 --- a/reactos/lib/comctl32/comctl_Uk.rc +++ b/reactos/lib/comctl32/comctl_Uk.rc @@ -38,9 +38,9 @@ STYLE DS_MODALFRAME | WS_POPUP | WS_CAPTION | WS_SYSMENU | WS_VISIBLE CAPTION "锑耱屦" FONT 8, "MS Shell Dlg" BEGIN - DEFPUSHBUTTON "&青忮瘌栩", IDC_FINISH_BUTTON,121,138,50,14 - DEFPUSHBUTTON "&泥氤 >", IDC_NEXT_BUTTON,121,138,50,14 PUSHBUTTON "< &袜玎", IDC_BACK_BUTTON,71,138,50,14 + DEFPUSHBUTTON "&泥氤 >", IDC_NEXT_BUTTON,121,138,50,14 + DEFPUSHBUTTON "&青忮瘌栩", IDC_FINISH_BUTTON,121,138,50,14 PUSHBUTTON "&鲁潇稠", IDCANCEL,178,138,50,14 PUSHBUTTON "&念獬潢", IDHELP,235,138,50,14,WS_GROUP LTEXT "", IDC_SUNKEN_LINE,7,129,278,1,SS_SUNKEN diff --git a/reactos/lib/comctl32/dpa.c b/reactos/lib/comctl32/dpa.c new file mode 100644 index 00000000000..bd406df4dc4 --- /dev/null +++ b/reactos/lib/comctl32/dpa.c @@ -0,0 +1,973 @@ +/* + * Dynamic pointer array (DPA) implementation + * + * Copyright 1998 Eric Kohl + * 1998 Juergen Schmied + * 2000 Eric Kohl for CodeWeavers + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + * NOTES + * These functions were involuntarily documented by Microsoft in 2002 as + * the outcome of an anti-trust suit brought by various U.S. governments. + * As a result the specifications on MSDN are inaccurate, incomplete + * and misleading. A much more complete (unofficial) documentation is + * available at: + * + * http://members.ozemail.com.au/~geoffch/samples/win32/shell/comctl32 + */ + +#define COBJMACROS + +#include +#include + +#include "windef.h" +#include "winbase.h" +#include "winuser.h" +#include "commctrl.h" +#include "objbase.h" + +#include "comctl32.h" +#include "wine/debug.h" + +WINE_DEFAULT_DEBUG_CHANNEL(dpa); + +struct _DPA +{ + INT nItemCount; + LPVOID *ptrs; + HANDLE hHeap; + INT nGrow; + INT nMaxCount; +}; + +typedef struct _STREAMDATA +{ + DWORD dwSize; + DWORD dwData2; + DWORD dwItems; +} STREAMDATA, *PSTREAMDATA; + +typedef struct _LOADDATA +{ + INT nCount; + PVOID ptr; +} LOADDATA, *LPLOADDATA; + +typedef HRESULT (CALLBACK *DPALOADPROC)(LPLOADDATA,IStream*,LPARAM); + + +/************************************************************************** + * DPA_LoadStream [COMCTL32.9] + * + * Loads a dynamic pointer array from a stream + * + * PARAMS + * phDpa [O] pointer to a handle to a dynamic pointer array + * loadProc [I] pointer to a callback function + * pStream [I] pointer to a stream + * lParam [I] application specific value + * + * RETURNS + * Success: TRUE + * Failure: FALSE + * + * NOTES + * No more information available yet! + */ +HRESULT WINAPI DPA_LoadStream (HDPA *phDpa, DPALOADPROC loadProc, + IStream *pStream, LPARAM lParam) +{ + HRESULT errCode; + LARGE_INTEGER position; + ULARGE_INTEGER newPosition; + STREAMDATA streamData; + LOADDATA loadData; + ULONG ulRead; + HDPA hDpa; + PVOID *ptr; + + FIXME ("phDpa=%p loadProc=%p pStream=%p lParam=%lx\n", + phDpa, loadProc, pStream, lParam); + + if (!phDpa || !loadProc || !pStream) + return E_INVALIDARG; + + *phDpa = (HDPA)NULL; + + position.QuadPart = 0; + + /* + * Zero out our streamData + */ + memset(&streamData,0,sizeof(STREAMDATA)); + + errCode = IStream_Seek (pStream, position, STREAM_SEEK_CUR, &newPosition); + if (errCode != S_OK) + return errCode; + + errCode = IStream_Read (pStream, &streamData, sizeof(STREAMDATA), &ulRead); + if (errCode != S_OK) + return errCode; + + FIXME ("dwSize=%lu dwData2=%lu dwItems=%lu\n", + streamData.dwSize, streamData.dwData2, streamData.dwItems); + + if ( ulRead < sizeof(STREAMDATA) || + lParam < sizeof(STREAMDATA) || + streamData.dwSize < sizeof(STREAMDATA) || + streamData.dwData2 < 1) { + errCode = E_FAIL; + } + + if (streamData.dwItems > (UINT_MAX / 2 / sizeof(VOID*))) /* 536870911 */ + return E_OUTOFMEMORY; + + /* create the dpa */ + hDpa = DPA_Create (streamData.dwItems); + if (!hDpa) + return E_OUTOFMEMORY; + + if (!DPA_Grow (hDpa, streamData.dwItems)) + return E_OUTOFMEMORY; + + /* load data from the stream into the dpa */ + ptr = hDpa->ptrs; + for (loadData.nCount = 0; loadData.nCount < streamData.dwItems; loadData.nCount++) { + errCode = (loadProc)(&loadData, pStream, lParam); + if (errCode != S_OK) { + errCode = S_FALSE; + break; + } + + *ptr = loadData.ptr; + ptr++; + } + + /* set the number of items */ + hDpa->nItemCount = loadData.nCount; + + /* store the handle to the dpa */ + *phDpa = hDpa; + FIXME ("new hDpa=%p, errorcode=%lx\n", hDpa, errCode); + + return errCode; +} + + +/************************************************************************** + * DPA_SaveStream [COMCTL32.10] + * + * Saves a dynamic pointer array to a stream + * + * PARAMS + * hDpa [I] handle to a dynamic pointer array + * loadProc [I] pointer to a callback function + * pStream [I] pointer to a stream + * lParam [I] application specific value + * + * RETURNS + * Success: TRUE + * Failure: FALSE + * + * NOTES + * No more information available yet! + */ +HRESULT WINAPI DPA_SaveStream (const HDPA hDpa, DPALOADPROC loadProc, + IStream *pStream, LPARAM lParam) +{ + + FIXME ("hDpa=%p loadProc=%p pStream=%p lParam=%lx\n", + hDpa, loadProc, pStream, lParam); + + return E_FAIL; +} + + +/************************************************************************** + * DPA_Merge [COMCTL32.11] + * + * Merge two dynamic pointers arrays. + * + * PARAMS + * hdpa1 [I] handle to a dynamic pointer array + * hdpa2 [I] handle to a dynamic pointer array + * dwFlags [I] flags + * pfnCompare [I] pointer to sort function + * pfnMerge [I] pointer to merge function + * lParam [I] application specific value + * + * RETURNS + * Success: TRUE + * Failure: FALSE + * + * NOTES + * No more information available yet! + */ +BOOL WINAPI DPA_Merge (const HDPA hdpa1, const HDPA hdpa2, DWORD dwFlags, + PFNDPACOMPARE pfnCompare, PFNDPAMERGE pfnMerge, + LPARAM lParam) +{ + INT nCount; + LPVOID *pWork1, *pWork2; + INT nResult, i; + INT nIndex; + + TRACE("%p %p %08lx %p %p %08lx)\n", + hdpa1, hdpa2, dwFlags, pfnCompare, pfnMerge, lParam); + + if (IsBadWritePtr (hdpa1, sizeof(*hdpa1))) + return FALSE; + + if (IsBadWritePtr (hdpa2, sizeof(*hdpa2))) + return FALSE; + + if (IsBadCodePtr ((FARPROC)pfnCompare)) + return FALSE; + + if (IsBadCodePtr ((FARPROC)pfnMerge)) + return FALSE; + + if (!(dwFlags & DPAM_NOSORT)) { + TRACE("sorting dpa's!\n"); + if (hdpa1->nItemCount > 0) + DPA_Sort (hdpa1, pfnCompare, lParam); + TRACE ("dpa 1 sorted!\n"); + if (hdpa2->nItemCount > 0) + DPA_Sort (hdpa2, pfnCompare, lParam); + TRACE ("dpa 2 sorted!\n"); + } + + if (hdpa2->nItemCount < 1) + return TRUE; + + TRACE("hdpa1->nItemCount=%d hdpa2->nItemCount=%d\n", + hdpa1->nItemCount, hdpa2->nItemCount); + + + /* working but untrusted implementation */ + + pWork1 = &(hdpa1->ptrs[hdpa1->nItemCount - 1]); + pWork2 = &(hdpa2->ptrs[hdpa2->nItemCount - 1]); + + nIndex = hdpa1->nItemCount - 1; + nCount = hdpa2->nItemCount - 1; + + do + { + if (nIndex < 0) { + if ((nCount >= 0) && (dwFlags & DPAM_INSERT)) { + /* Now insert the remaining new items into DPA 1 */ + TRACE("%d items to be inserted at start of DPA 1\n", + nCount+1); + for (i=nCount; i>=0; i--) { + PVOID ptr; + + ptr = (pfnMerge)(3, *pWork2, NULL, lParam); + if (!ptr) + return FALSE; + DPA_InsertPtr (hdpa1, 0, ptr); + pWork2--; + } + } + break; + } + nResult = (pfnCompare)(*pWork1, *pWork2, lParam); + TRACE("compare result=%d, dpa1.cnt=%d, dpa2.cnt=%d\n", + nResult, nIndex, nCount); + + if (nResult == 0) + { + PVOID ptr; + + ptr = (pfnMerge)(1, *pWork1, *pWork2, lParam); + if (!ptr) + return FALSE; + + nCount--; + pWork2--; + *pWork1 = ptr; + nIndex--; + pWork1--; + } + else if (nResult > 0) + { + /* item in DPA 1 missing from DPA 2 */ + if (dwFlags & DPAM_DELETE) + { + /* Now delete the extra item in DPA1 */ + PVOID ptr; + + ptr = DPA_DeletePtr (hdpa1, hdpa1->nItemCount - 1); + + (pfnMerge)(2, ptr, NULL, lParam); + } + nIndex--; + pWork1--; + } + else + { + /* new item in DPA 2 */ + if (dwFlags & DPAM_INSERT) + { + /* Now insert the new item in DPA 1 */ + PVOID ptr; + + ptr = (pfnMerge)(3, *pWork2, NULL, lParam); + if (!ptr) + return FALSE; + DPA_InsertPtr (hdpa1, nIndex+1, ptr); + } + nCount--; + pWork2--; + } + + } + while (nCount >= 0); + + return TRUE; +} + + +/************************************************************************** + * DPA_Destroy [COMCTL32.329] + * + * Destroys a dynamic pointer array + * + * PARAMS + * hdpa [I] handle (pointer) to the pointer array + * + * RETURNS + * Success: TRUE + * Failure: FALSE + */ +BOOL WINAPI DPA_Destroy (const HDPA hdpa) +{ + TRACE("(%p)\n", hdpa); + + if (!hdpa) + return FALSE; + + if (hdpa->ptrs && (!HeapFree (hdpa->hHeap, 0, hdpa->ptrs))) + return FALSE; + + return HeapFree (hdpa->hHeap, 0, hdpa); +} + + +/************************************************************************** + * DPA_Grow [COMCTL32.330] + * + * Sets the growth amount. + * + * PARAMS + * hdpa [I] handle (pointer) to the existing (source) pointer array + * nGrow [I] number of items by which the array grows when it's too small + * + * RETURNS + * Success: TRUE + * Failure: FALSE + */ +BOOL WINAPI DPA_Grow (const HDPA hdpa, INT nGrow) +{ + TRACE("(%p %d)\n", hdpa, nGrow); + + if (!hdpa) + return FALSE; + + hdpa->nGrow = max(8, nGrow); + + return TRUE; +} + + +/************************************************************************** + * DPA_Clone [COMCTL32.331] + * + * Copies a pointer array to an other one or creates a copy + * + * PARAMS + * hdpa [I] handle (pointer) to the existing (source) pointer array + * hdpaNew [O] handle (pointer) to the destination pointer array + * + * RETURNS + * Success: pointer to the destination pointer array. + * Failure: NULL + * + * NOTES + * - If the 'hdpaNew' is a NULL-Pointer, a copy of the source pointer + * array will be created and it's handle (pointer) is returned. + * - If 'hdpa' is a NULL-Pointer, the original implementation crashes, + * this implementation just returns NULL. + */ +HDPA WINAPI DPA_Clone (const HDPA hdpa, const HDPA hdpaNew) +{ + INT nNewItems, nSize; + HDPA hdpaTemp; + + if (!hdpa) + return NULL; + + TRACE("(%p %p)\n", hdpa, hdpaNew); + + if (!hdpaNew) { + /* create a new DPA */ + hdpaTemp = HeapAlloc (hdpa->hHeap, HEAP_ZERO_MEMORY, + sizeof(*hdpaTemp)); + hdpaTemp->hHeap = hdpa->hHeap; + hdpaTemp->nGrow = hdpa->nGrow; + } + else + hdpaTemp = hdpaNew; + + if (hdpaTemp->ptrs) { + /* remove old pointer array */ + HeapFree (hdpaTemp->hHeap, 0, hdpaTemp->ptrs); + hdpaTemp->ptrs = NULL; + hdpaTemp->nItemCount = 0; + hdpaTemp->nMaxCount = 0; + } + + /* create a new pointer array */ + nNewItems = hdpaTemp->nGrow * + ((INT)((hdpa->nItemCount - 1) / hdpaTemp->nGrow) + 1); + nSize = nNewItems * sizeof(LPVOID); + hdpaTemp->ptrs = HeapAlloc (hdpaTemp->hHeap, HEAP_ZERO_MEMORY, nSize); + hdpaTemp->nMaxCount = nNewItems; + + /* clone the pointer array */ + hdpaTemp->nItemCount = hdpa->nItemCount; + memmove (hdpaTemp->ptrs, hdpa->ptrs, + hdpaTemp->nItemCount * sizeof(LPVOID)); + + return hdpaTemp; +} + + +/************************************************************************** + * DPA_GetPtr [COMCTL32.332] + * + * Retrieves a pointer from a dynamic pointer array + * + * PARAMS + * hdpa [I] handle (pointer) to the pointer array + * nIndex [I] array index of the desired pointer + * + * RETURNS + * Success: pointer + * Failure: NULL + */ +LPVOID WINAPI DPA_GetPtr (const HDPA hdpa, INT nIndex) +{ + TRACE("(%p %d)\n", hdpa, nIndex); + + if (!hdpa) + return NULL; + if (!hdpa->ptrs) { + WARN("no pointer array.\n"); + return NULL; + } + if ((nIndex < 0) || (nIndex >= hdpa->nItemCount)) { + WARN("not enough pointers in array (%d vs %d).\n",nIndex,hdpa->nItemCount); + return NULL; + } + + TRACE("-- %p\n", hdpa->ptrs[nIndex]); + + return hdpa->ptrs[nIndex]; +} + + +/************************************************************************** + * DPA_GetPtrIndex [COMCTL32.333] + * + * Retrieves the index of the specified pointer + * + * PARAMS + * hdpa [I] handle (pointer) to the pointer array + * p [I] pointer + * + * RETURNS + * Success: index of the specified pointer + * Failure: -1 + */ +INT WINAPI DPA_GetPtrIndex (const HDPA hdpa, LPVOID p) +{ + INT i; + + if (!hdpa || !hdpa->ptrs) + return -1; + + for (i = 0; i < hdpa->nItemCount; i++) { + if (hdpa->ptrs[i] == p) + return i; + } + + return -1; +} + + +/************************************************************************** + * DPA_InsertPtr [COMCTL32.334] + * + * Inserts a pointer into a dynamic pointer array + * + * PARAMS + * hdpa [I] handle (pointer) to the array + * i [I] array index + * p [I] pointer to insert + * + * RETURNS + * Success: index of the inserted pointer + * Failure: -1 + */ +INT WINAPI DPA_InsertPtr (const HDPA hdpa, INT i, LPVOID p) +{ + TRACE("(%p %d %p)\n", hdpa, i, p); + + if (!hdpa || i < 0) return -1; + + /* append item if index is out of bounds */ + i = min(hdpa->nItemCount, i); + + /* create empty spot at the end */ + if (!DPA_SetPtr(hdpa, hdpa->nItemCount, 0)) return -1; + + if (i != hdpa->nItemCount - 1) + memmove (hdpa->ptrs + i + 1, hdpa->ptrs + i, + (hdpa->nItemCount - i - 1) * sizeof(LPVOID)); + + hdpa->ptrs[i] = p; + return i; +} + + +/************************************************************************** + * DPA_SetPtr [COMCTL32.335] + * + * Sets a pointer in the pointer array + * + * PARAMS + * hdpa [I] handle (pointer) to the pointer array + * i [I] index of the pointer that will be set + * p [I] pointer to be set + * + * RETURNS + * Success: TRUE + * Failure: FALSE + */ +BOOL WINAPI DPA_SetPtr (const HDPA hdpa, INT i, LPVOID p) +{ + LPVOID *lpTemp; + + TRACE("(%p %d %p)\n", hdpa, i, p); + + if (!hdpa || i < 0) + return FALSE; + + if (hdpa->nItemCount <= i) { + /* within the old array */ + if (hdpa->nMaxCount <= i) { + /* resize the block of memory */ + INT nNewItems = + hdpa->nGrow * ((INT)(((i+1) - 1) / hdpa->nGrow) + 1); + INT nSize = nNewItems * sizeof(LPVOID); + + if (hdpa->ptrs) + lpTemp = HeapReAlloc (hdpa->hHeap, HEAP_ZERO_MEMORY, hdpa->ptrs, nSize); + else + lpTemp = HeapAlloc (hdpa->hHeap, HEAP_ZERO_MEMORY, nSize); + + if (!lpTemp) + return FALSE; + + hdpa->nMaxCount = nNewItems; + hdpa->ptrs = lpTemp; + } + hdpa->nItemCount = i+1; + } + + /* put the new entry in */ + hdpa->ptrs[i] = p; + + return TRUE; +} + + +/************************************************************************** + * DPA_DeletePtr [COMCTL32.336] + * + * Removes a pointer from the pointer array. + * + * PARAMS + * hdpa [I] handle (pointer) to the pointer array + * i [I] index of the pointer that will be deleted + * + * RETURNS + * Success: deleted pointer + * Failure: NULL + */ +LPVOID WINAPI DPA_DeletePtr (const HDPA hdpa, INT i) +{ + LPVOID *lpDest, *lpSrc, lpTemp = NULL; + INT nSize; + + TRACE("(%p %d)\n", hdpa, i); + + if ((!hdpa) || i < 0 || i >= hdpa->nItemCount) + return NULL; + + lpTemp = hdpa->ptrs[i]; + + /* do we need to move ?*/ + if (i < hdpa->nItemCount - 1) { + lpDest = hdpa->ptrs + i; + lpSrc = lpDest + 1; + nSize = (hdpa->nItemCount - i - 1) * sizeof(LPVOID); + TRACE("-- move dest=%p src=%p size=%x\n", + lpDest, lpSrc, nSize); + memmove (lpDest, lpSrc, nSize); + } + + hdpa->nItemCount --; + + /* free memory ?*/ + if ((hdpa->nMaxCount - hdpa->nItemCount) >= hdpa->nGrow) { + INT nNewItems = max(hdpa->nGrow * 2, hdpa->nItemCount); + nSize = nNewItems * sizeof(LPVOID); + lpDest = HeapReAlloc (hdpa->hHeap, HEAP_ZERO_MEMORY, + hdpa->ptrs, nSize); + if (!lpDest) + return NULL; + + hdpa->nMaxCount = nNewItems; + hdpa->ptrs = (LPVOID*)lpDest; + } + + return lpTemp; +} + + +/************************************************************************** + * DPA_DeleteAllPtrs [COMCTL32.337] + * + * Removes all pointers and reinitializes the array. + * + * PARAMS + * hdpa [I] handle (pointer) to the pointer array + * + * RETURNS + * Success: TRUE + * Failure: FALSE + */ +BOOL WINAPI DPA_DeleteAllPtrs (const HDPA hdpa) +{ + TRACE("(%p)\n", hdpa); + + if (!hdpa) + return FALSE; + + if (hdpa->ptrs && (!HeapFree (hdpa->hHeap, 0, hdpa->ptrs))) + return FALSE; + + hdpa->nItemCount = 0; + hdpa->nMaxCount = hdpa->nGrow * 2; + hdpa->ptrs = HeapAlloc (hdpa->hHeap, HEAP_ZERO_MEMORY, + hdpa->nMaxCount * sizeof(LPVOID)); + + return TRUE; +} + + +/************************************************************************** + * DPA_QuickSort [Internal] + * + * Ordinary quicksort (used by DPA_Sort). + * + * PARAMS + * lpPtrs [I] pointer to the pointer array + * l [I] index of the "left border" of the partition + * r [I] index of the "right border" of the partition + * pfnCompare [I] pointer to the compare function + * lParam [I] user defined value (3rd parameter in compare function) + * + * RETURNS + * NONE + */ +static VOID DPA_QuickSort (LPVOID *lpPtrs, INT l, INT r, + PFNDPACOMPARE pfnCompare, LPARAM lParam) +{ + INT m; + LPVOID t; + + TRACE("l=%i r=%i\n", l, r); + + if (l==r) /* one element is always sorted */ + return; + if (r0) + { + t = lpPtrs[m+1]; + memmove(&lpPtrs[l+1],&lpPtrs[l],(m-l+1)*sizeof(lpPtrs[l])); + lpPtrs[l] = t; + + m++; + } + l++; + } +} + + +/************************************************************************** + * DPA_Sort [COMCTL32.338] + * + * Sorts a pointer array using a user defined compare function + * + * PARAMS + * hdpa [I] handle (pointer) to the pointer array + * pfnCompare [I] pointer to the compare function + * lParam [I] user defined value (3rd parameter of compare function) + * + * RETURNS + * Success: TRUE + * Failure: FALSE + */ +BOOL WINAPI DPA_Sort (const HDPA hdpa, PFNDPACOMPARE pfnCompare, LPARAM lParam) +{ + if (!hdpa || !pfnCompare) + return FALSE; + + TRACE("(%p %p 0x%lx)\n", hdpa, pfnCompare, lParam); + + if ((hdpa->nItemCount > 1) && (hdpa->ptrs)) + DPA_QuickSort (hdpa->ptrs, 0, hdpa->nItemCount - 1, + pfnCompare, lParam); + + return TRUE; +} + + +/************************************************************************** + * DPA_Search [COMCTL32.339] + * + * Searches a pointer array for a specified pointer + * + * PARAMS + * hdpa [I] handle (pointer) to the pointer array + * pFind [I] pointer to search for + * nStart [I] start index + * pfnCompare [I] pointer to the compare function + * lParam [I] user defined value (3rd parameter of compare function) + * uOptions [I] search options + * + * RETURNS + * Success: index of the pointer in the array. + * Failure: -1 + * + * NOTES + * Binary search taken from R.Sedgewick "Algorithms in C"! + * Function is NOT tested! + * If something goes wrong, blame HIM not ME! (Eric Kohl) + */ +INT WINAPI DPA_Search (const HDPA hdpa, LPVOID pFind, INT nStart, + PFNDPACOMPARE pfnCompare, LPARAM lParam, UINT uOptions) +{ + if (!hdpa || !pfnCompare || !pFind) + return -1; + + TRACE("(%p %p %d %p 0x%08lx 0x%08x)\n", + hdpa, pFind, nStart, pfnCompare, lParam, uOptions); + + if (uOptions & DPAS_SORTED) { + /* array is sorted --> use binary search */ + INT l, r, x, n; + LPVOID *lpPtr; + + TRACE("binary search\n"); + + l = (nStart == -1) ? 0 : nStart; + r = hdpa->nItemCount - 1; + lpPtr = hdpa->ptrs; + while (r >= l) { + x = (l + r) / 2; + n = (pfnCompare)(pFind, lpPtr[x], lParam); + if (n < 0) + r = x - 1; + else + l = x + 1; + if (n == 0) { + TRACE("-- ret=%d\n", n); + return n; + } + } + + if (uOptions & (DPAS_INSERTBEFORE | DPAS_INSERTAFTER)) { + TRACE("-- ret=%d\n", l); + return l; + } + } + else { + /* array is not sorted --> use linear search */ + LPVOID *lpPtr; + INT nIndex; + + TRACE("linear search\n"); + + nIndex = (nStart == -1)? 0 : nStart; + lpPtr = hdpa->ptrs; + for (; nIndex < hdpa->nItemCount; nIndex++) { + if ((pfnCompare)(pFind, lpPtr[nIndex], lParam) == 0) { + TRACE("-- ret=%d\n", nIndex); + return nIndex; + } + } + } + + TRACE("-- not found: ret=-1\n"); + return -1; +} + + +/************************************************************************** + * DPA_CreateEx [COMCTL32.340] + * + * Creates a dynamic pointer array using the specified size and heap. + * + * PARAMS + * nGrow [I] number of items by which the array grows when it is filled + * hHeap [I] handle to the heap where the array is stored + * + * RETURNS + * Success: handle (pointer) to the pointer array. + * Failure: NULL + * + * NOTES + * The DPA_ functions can be used to create and manipulate arrays of + * pointers. + */ +HDPA WINAPI DPA_CreateEx (INT nGrow, HANDLE hHeap) +{ + HDPA hdpa; + + TRACE("(%d %p)\n", nGrow, hHeap); + + if (hHeap) + hdpa = HeapAlloc (hHeap, HEAP_ZERO_MEMORY, sizeof(*hdpa)); + else + hdpa = Alloc (sizeof(*hdpa)); + + if (hdpa) { + hdpa->nGrow = max(8, nGrow); + hdpa->hHeap = hHeap ? hHeap : GetProcessHeap(); + hdpa->nMaxCount = hdpa->nGrow * 2; + hdpa->ptrs = HeapAlloc (hdpa->hHeap, HEAP_ZERO_MEMORY, + hdpa->nMaxCount * sizeof(LPVOID)); + } + + TRACE("-- %p\n", hdpa); + + return hdpa; +} + + +/************************************************************************** + * DPA_Create [COMCTL32.328] + * + * Creates a dynamic pointer array. + * + * PARAMS + * nGrow [I] number of items by which the array grows when it is filled + * + * RETURNS + * Success: handle (pointer) to the pointer array. + * Failure: NULL + * + * NOTES + * The DPA_ functions can be used to create and manipulate arrays of + * pointers. + */ +HDPA WINAPI DPA_Create (INT nGrow) +{ + return DPA_CreateEx( nGrow, 0 ); +} + + +/************************************************************************** + * DPA_EnumCallback [COMCTL32.385] + * + * Enumerates all items in a dynamic pointer array. + * + * PARAMS + * hdpa [I] handle to the dynamic pointer array + * enumProc [I] + * lParam [I] + * + * RETURNS + * none + */ +VOID WINAPI DPA_EnumCallback (HDPA hdpa, PFNDPAENUMCALLBACK enumProc, + LPVOID lParam) +{ + INT i; + + TRACE("(%p %p %p)\n", hdpa, enumProc, lParam); + + if (!hdpa) + return; + if (hdpa->nItemCount <= 0) + return; + + for (i = 0; i < hdpa->nItemCount; i++) { + if ((enumProc)(hdpa->ptrs[i], lParam) == 0) + return; + } + + return; +} + + +/************************************************************************** + * DPA_DestroyCallback [COMCTL32.386] + * + * Enumerates all items in a dynamic pointer array and destroys it. + * + * PARAMS + * hdpa [I] handle to the dynamic pointer array + * enumProc [I] + * lParam [I] + * + * RETURNS + * none + */ +void WINAPI DPA_DestroyCallback (HDPA hdpa, PFNDPAENUMCALLBACK enumProc, + LPVOID lParam) +{ + TRACE("(%p %p %p)\n", hdpa, enumProc, lParam); + + DPA_EnumCallback (hdpa, enumProc, lParam); + DPA_Destroy (hdpa); +} diff --git a/reactos/lib/comctl32/dsa.c b/reactos/lib/comctl32/dsa.c new file mode 100644 index 00000000000..9b247b91366 --- /dev/null +++ b/reactos/lib/comctl32/dsa.c @@ -0,0 +1,436 @@ +/* + * Dynamic structure array (DSA) implementation + * + * Copyright 1998 Eric Kohl + * 1998 Juergen Schmied + * 2000 Eric Kohl for CodeWeavers + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + * NOTES + * These functions were involuntarily documented by Microsoft in 2002 as + * the outcome of an anti-trust suit brought by various U.S. governments. + * As a result the specifications on MSDN are inaccurate, incomplete + * and misleading. A much more complete (unofficial) documentation is + * available at: + * + * http://members.ozemail.com.au/~geoffch/samples/win32/shell/comctl32 + */ + +#include + +#include "windef.h" +#include "winbase.h" +#include "winuser.h" +#include "commctrl.h" + +#include "comctl32.h" +#include "wine/debug.h" + +WINE_DEFAULT_DEBUG_CHANNEL(dsa); + +struct _DSA +{ + INT nItemCount; + LPVOID pData; + INT nMaxCount; + INT nItemSize; + INT nGrow; +}; + +/************************************************************************** + * DSA_Create [COMCTL32.320] + * + * Creates a dynamic storage array + * + * PARAMS + * nSize [I] size of the array elements + * nGrow [I] number of elements by which the array grows when it is filled + * + * RETURNS + * Success: pointer to an array control structure. Use this like a handle. + * Failure: NULL + * + * NOTES + * The DSA_ functions can be used to create and manipulate arrays of + * fixed-size memory blocks. These arrays can store any kind of data + * (e.g. strings and icons). + */ +HDSA WINAPI DSA_Create (INT nSize, INT nGrow) +{ + HDSA hdsa; + + TRACE("(size=%d grow=%d)\n", nSize, nGrow); + + hdsa = Alloc (sizeof(*hdsa)); + if (hdsa) + { + hdsa->nItemCount = 0; + hdsa->pData = NULL; + hdsa->nMaxCount = 0; + hdsa->nItemSize = nSize; + hdsa->nGrow = max(1, nGrow); + } + + return hdsa; +} + + +/************************************************************************** + * DSA_Destroy [COMCTL32.321] + * + * Destroys a dynamic storage array + * + * PARAMS + * hdsa [I] pointer to the array control structure + * + * RETURNS + * Success: TRUE + * Failure: FALSE + */ +BOOL WINAPI DSA_Destroy (const HDSA hdsa) +{ + TRACE("(%p)\n", hdsa); + + if (!hdsa) + return FALSE; + + if (hdsa->pData && (!Free (hdsa->pData))) + return FALSE; + + return Free (hdsa); +} + + +/************************************************************************** + * DSA_GetItem [COMCTL32.322] + * + * Copies the specified item into a caller-supplied buffer. + * + * PARAMS + * hdsa [I] pointer to the array control structure + * nIndex [I] number of the Item to get + * pDest [O] destination buffer. Has to be >= dwElementSize. + * + * RETURNS + * Success: TRUE + * Failure: FALSE + */ +BOOL WINAPI DSA_GetItem (const HDSA hdsa, INT nIndex, LPVOID pDest) +{ + LPVOID pSrc; + + TRACE("(%p %d %p)\n", hdsa, nIndex, pDest); + + if (!hdsa) + return FALSE; + if ((nIndex < 0) || (nIndex >= hdsa->nItemCount)) + return FALSE; + + pSrc = (char *) hdsa->pData + (hdsa->nItemSize * nIndex); + memmove (pDest, pSrc, hdsa->nItemSize); + + return TRUE; +} + + +/************************************************************************** + * DSA_GetItemPtr [COMCTL32.323] + * + * Retrieves a pointer to the specified item. + * + * PARAMS + * hdsa [I] pointer to the array control structure + * nIndex [I] index of the desired item + * + * RETURNS + * Success: pointer to an item + * Failure: NULL + */ +LPVOID WINAPI DSA_GetItemPtr (const HDSA hdsa, INT nIndex) +{ + LPVOID pSrc; + + TRACE("(%p %d)\n", hdsa, nIndex); + + if (!hdsa) + return NULL; + if ((nIndex < 0) || (nIndex >= hdsa->nItemCount)) + return NULL; + + pSrc = (char *) hdsa->pData + (hdsa->nItemSize * nIndex); + + TRACE("-- ret=%p\n", pSrc); + + return pSrc; +} + + +/************************************************************************** + * DSA_SetItem [COMCTL32.325] + * + * Sets the contents of an item in the array. + * + * PARAMS + * hdsa [I] pointer to the array control structure + * nIndex [I] index for the item + * pSrc [I] pointer to the new item data + * + * RETURNS + * Success: TRUE + * Failure: FALSE + */ +BOOL WINAPI DSA_SetItem (const HDSA hdsa, INT nIndex, LPVOID pSrc) +{ + INT nSize, nNewItems; + LPVOID pDest, lpTemp; + + TRACE("(%p %d %p)\n", hdsa, nIndex, pSrc); + + if ((!hdsa) || nIndex < 0) + return FALSE; + + if (hdsa->nItemCount <= nIndex) { + /* within the old array */ + if (hdsa->nMaxCount > nIndex) { + /* within the allocated space, set a new boundary */ + hdsa->nItemCount = nIndex + 1; + } + else { + /* resize the block of memory */ + nNewItems = + hdsa->nGrow * ((INT)(((nIndex + 1) - 1) / hdsa->nGrow) + 1); + nSize = hdsa->nItemSize * nNewItems; + + lpTemp = ReAlloc (hdsa->pData, nSize); + if (!lpTemp) + return FALSE; + + hdsa->nMaxCount = nNewItems; + hdsa->nItemCount = nIndex + 1; + hdsa->pData = lpTemp; + } + } + + /* put the new entry in */ + pDest = (char *) hdsa->pData + (hdsa->nItemSize * nIndex); + TRACE("-- move dest=%p src=%p size=%d\n", + pDest, pSrc, hdsa->nItemSize); + memmove (pDest, pSrc, hdsa->nItemSize); + + return TRUE; +} + + +/************************************************************************** + * DSA_InsertItem [COMCTL32.324] + * + * Inserts an item into the array at the specified index. + * + * PARAMS + * hdsa [I] pointer to the array control structure + * nIndex [I] index for the new item + * pSrc [I] pointer to the element + * + * RETURNS + * Success: position of the new item + * Failure: -1 + */ +INT WINAPI DSA_InsertItem (const HDSA hdsa, INT nIndex, LPVOID pSrc) +{ + INT nNewItems, nSize; + LPVOID lpTemp, lpDest; + + TRACE("(%p %d %p)\n", hdsa, nIndex, pSrc); + + if ((!hdsa) || nIndex < 0) + return -1; + + /* when nIndex >= nItemCount then append */ + if (nIndex >= hdsa->nItemCount) + nIndex = hdsa->nItemCount; + + /* do we need to resize ? */ + if (hdsa->nItemCount >= hdsa->nMaxCount) { + nNewItems = hdsa->nMaxCount + hdsa->nGrow; + nSize = hdsa->nItemSize * nNewItems; + + lpTemp = ReAlloc (hdsa->pData, nSize); + if (!lpTemp) + return -1; + + hdsa->nMaxCount = nNewItems; + hdsa->pData = lpTemp; + } + + /* do we need to move elements ? */ + if (nIndex < hdsa->nItemCount) { + lpTemp = (char *) hdsa->pData + (hdsa->nItemSize * nIndex); + lpDest = (char *) lpTemp + hdsa->nItemSize; + nSize = (hdsa->nItemCount - nIndex) * hdsa->nItemSize; + TRACE("-- move dest=%p src=%p size=%d\n", + lpDest, lpTemp, nSize); + memmove (lpDest, lpTemp, nSize); + } + + /* ok, we can put the new Item in */ + hdsa->nItemCount++; + lpDest = (char *) hdsa->pData + (hdsa->nItemSize * nIndex); + TRACE("-- move dest=%p src=%p size=%d\n", + lpDest, pSrc, hdsa->nItemSize); + memmove (lpDest, pSrc, hdsa->nItemSize); + + return nIndex; +} + + +/************************************************************************** + * DSA_DeleteItem [COMCTL32.326] + * + * Deletes the specified item from the array. + * + * PARAMS + * hdsa [I] pointer to the array control structure + * nIndex [I] index for the element to delete + * + * RETURNS + * Success: number of the deleted element + * Failure: -1 + */ +INT WINAPI DSA_DeleteItem (const HDSA hdsa, INT nIndex) +{ + LPVOID lpDest,lpSrc; + INT nSize; + + TRACE("(%p %d)\n", hdsa, nIndex); + + if (!hdsa) + return -1; + if (nIndex < 0 || nIndex >= hdsa->nItemCount) + return -1; + + /* do we need to move ? */ + if (nIndex < hdsa->nItemCount - 1) { + lpDest = (char *) hdsa->pData + (hdsa->nItemSize * nIndex); + lpSrc = (char *) lpDest + hdsa->nItemSize; + nSize = hdsa->nItemSize * (hdsa->nItemCount - nIndex - 1); + TRACE("-- move dest=%p src=%p size=%d\n", + lpDest, lpSrc, nSize); + memmove (lpDest, lpSrc, nSize); + } + + hdsa->nItemCount--; + + /* free memory ? */ + if ((hdsa->nMaxCount - hdsa->nItemCount) >= hdsa->nGrow) { + nSize = hdsa->nItemSize * hdsa->nItemCount; + + lpDest = ReAlloc (hdsa->pData, nSize); + if (!lpDest) + return -1; + + hdsa->nMaxCount = hdsa->nItemCount; + hdsa->pData = lpDest; + } + + return nIndex; +} + + +/************************************************************************** + * DSA_DeleteAllItems [COMCTL32.327] + * + * Removes all items and reinitializes the array. + * + * PARAMS + * hdsa [I] pointer to the array control structure + * + * RETURNS + * Success: TRUE + * Failure: FALSE + */ +BOOL WINAPI DSA_DeleteAllItems (const HDSA hdsa) +{ + TRACE("(%p)\n", hdsa); + + if (!hdsa) + return FALSE; + if (hdsa->pData && (!Free (hdsa->pData))) + return FALSE; + + hdsa->nItemCount = 0; + hdsa->pData = NULL; + hdsa->nMaxCount = 0; + + return TRUE; +} + + +/************************************************************************** + * DSA_EnumCallback [COMCTL32.387] + * + * Enumerates all items in a dynamic storage array. + * + * PARAMS + * hdsa [I] handle to the dynamic storage array + * enumProc [I] + * lParam [I] + * + * RETURNS + * none + */ +VOID WINAPI DSA_EnumCallback (HDSA hdsa, PFNDSAENUMCALLBACK enumProc, + LPVOID lParam) +{ + INT i; + + TRACE("(%p %p %p)\n", hdsa, enumProc, lParam); + + if (!hdsa) + return; + if (hdsa->nItemCount <= 0) + return; + + for (i = 0; i < hdsa->nItemCount; i++) { + LPVOID lpItem = DSA_GetItemPtr (hdsa, i); + if ((enumProc)(lpItem, lParam) == 0) + return; + } + + return; +} + + +/************************************************************************** + * DSA_DestroyCallback [COMCTL32.388] + * + * Enumerates all items in a dynamic storage array and destroys it. + * + * PARAMS + * hdsa [I] handle to the dynamic storage array + * enumProc [I] + * lParam [I] + * + * RETURNS + * none + */ +void WINAPI DSA_DestroyCallback (HDSA hdsa, PFNDSAENUMCALLBACK enumProc, + LPVOID lParam) +{ + TRACE("(%p %p %p)\n", hdsa, enumProc, lParam); + + DSA_EnumCallback (hdsa, enumProc, lParam); + DSA_Destroy (hdsa); +} diff --git a/reactos/lib/comctl32/header.c b/reactos/lib/comctl32/header.c index c66e48466d5..6bc3de0b501 100644 --- a/reactos/lib/comctl32/header.c +++ b/reactos/lib/comctl32/header.c @@ -43,6 +43,8 @@ #include "commctrl.h" #include "comctl32.h" #include "imagelist.h" +#include "tmschema.h" +#include "uxtheme.h" #include "wine/debug.h" WINE_DEFAULT_DEBUG_CHANNEL(header); @@ -94,6 +96,8 @@ typedef struct #define HEADER_GetInfoPtr(hwnd) ((HEADER_INFO *)GetWindowLongPtrW(hwnd,0)) +static const WCHAR themeClass[] = {'H','e','a','d','e','r',0}; + inline static LRESULT HEADER_IndexToOrder (HWND hwnd, INT iItem) @@ -164,6 +168,7 @@ HEADER_DrawItem (HWND hwnd, HDC hdc, INT iItem, BOOL bHotTrack) HEADER_ITEM *phdi = &infoPtr->items[iItem]; RECT r; INT oldBkMode, cxEdge = GetSystemMetrics(SM_CXEDGE); + HTHEME theme = GetWindowTheme (hwnd); TRACE("DrawItem(iItem %d bHotTrack %d unicode flag %d)\n", iItem, bHotTrack, infoPtr->bUnicode); @@ -174,25 +179,52 @@ HEADER_DrawItem (HWND hwnd, HDC hdc, INT iItem, BOOL bHotTrack) if (r.right - r.left == 0) return phdi->rect.right; - if (GetWindowLongW (hwnd, GWL_STYLE) & HDS_BUTTONS) { - if (phdi->bDown) { - DrawEdge (hdc, &r, BDR_RAISEDOUTER, - BF_RECT | BF_FLAT | BF_MIDDLE | BF_ADJUST); - r.left += 2; - r.top += 2; - } - else - DrawEdge (hdc, &r, EDGE_RAISED, - BF_RECT | BF_SOFT | BF_MIDDLE | BF_ADJUST); + if (theme != NULL) { + int state = (phdi->bDown) ? HIS_PRESSED : + (bHotTrack ? HIS_HOT : HIS_NORMAL); + DrawThemeBackground (theme, hdc, HP_HEADERITEM, state, + &r, NULL); + GetThemeBackgroundContentRect (theme, hdc, HP_HEADERITEM, state, + &r, &r); + } + else { + if (GetWindowLongW (hwnd, GWL_STYLE) & HDS_BUTTONS) { + if (phdi->bDown) { + DrawEdge (hdc, &r, BDR_RAISEDOUTER, + BF_RECT | BF_FLAT | BF_MIDDLE | BF_ADJUST); + } + else + DrawEdge (hdc, &r, EDGE_RAISED, + BF_RECT | BF_SOFT | BF_MIDDLE | BF_ADJUST); + } + else + DrawEdge (hdc, &r, EDGE_ETCHED, BF_BOTTOM | BF_RIGHT | BF_ADJUST); + } + if (phdi->bDown) { + r.left += 2; + r.top += 2; } - else - DrawEdge (hdc, &r, EDGE_ETCHED, BF_BOTTOM | BF_RIGHT | BF_ADJUST); r.left -= cxEdge; r.right += cxEdge; if (phdi->fmt & HDF_OWNERDRAW) { DRAWITEMSTRUCT dis; + NMCUSTOMDRAW nmcd; + + nmcd.hdr.hwndFrom = hwnd; + nmcd.hdr.idFrom = GetWindowLongPtrW (hwnd, GWLP_ID); + nmcd.hdr.code = NM_CUSTOMDRAW; + nmcd.dwDrawStage = CDDS_PREPAINT | CDDS_ITEM | CDDS_ITEMPOSTERASE; + nmcd.hdc = hdc; + nmcd.dwItemSpec = iItem; + nmcd.rc = r; + nmcd.uItemState = phdi->bDown ? CDIS_SELECTED : 0; + nmcd.lItemlParam = phdi->lParam; + + SendMessageW (infoPtr->hwndNotify, WM_NOTIFY, + (WPARAM)nmcd.hdr.idFrom, (LPARAM)&nmcd); + dis.CtlType = ODT_HEADER; dis.CtlID = GetWindowLongPtrW (hwnd, GWLP_ID); dis.itemID = iItem; @@ -315,7 +347,7 @@ HEADER_DrawItem (HWND hwnd, HDC hdc, INT iItem, BOOL bHotTrack) HDF_BITMAP_ON_RIGHT|HDF_IMAGE)))) /* no explicit format specified? */ && (phdi->pszText)) { oldBkMode = SetBkMode(hdc, TRANSPARENT); - SetTextColor (hdc, (bHotTrack) ? COLOR_HIGHLIGHT : COLOR_BTNTEXT); + SetTextColor (hdc, (bHotTrack && !theme) ? COLOR_HIGHLIGHT : COLOR_BTNTEXT); r.left = tx; r.right = tx + tw; DrawTextW (hdc, phdi->pszText, -1, @@ -338,6 +370,7 @@ HEADER_Refresh (HWND hwnd, HDC hdc) HBRUSH hbrBk; UINT i; INT x; + HTHEME theme = GetWindowTheme (hwnd); /* get rect for the bar, adjusted for the border */ GetClientRect (hwnd, &rect); @@ -346,20 +379,29 @@ HEADER_Refresh (HWND hwnd, HDC hdc) hOldFont = SelectObject (hdc, hFont); /* draw Background */ - hbrBk = GetSysColorBrush(COLOR_3DFACE); - FillRect(hdc, &rect, hbrBk); + if (theme == NULL) { + hbrBk = GetSysColorBrush(COLOR_3DFACE); + FillRect(hdc, &rect, hbrBk); + } x = rect.left; for (i = 0; i < infoPtr->uNumItem; i++) { - x = HEADER_DrawItem (hwnd, hdc, HEADER_OrderToIndex(hwnd,i), FALSE); + x = HEADER_DrawItem (hwnd, hdc, HEADER_OrderToIndex(hwnd,i), + infoPtr->iHotItem == i); } if ((x <= rect.right) && (infoPtr->uNumItem > 0)) { rect.left = x; - if (GetWindowLongW (hwnd, GWL_STYLE) & HDS_BUTTONS) - DrawEdge (hdc, &rect, EDGE_RAISED, BF_TOP|BF_LEFT|BF_BOTTOM|BF_SOFT); - else - DrawEdge (hdc, &rect, EDGE_ETCHED, BF_BOTTOM); + if (theme != NULL) { + DrawThemeBackground (theme, hdc, HP_HEADERITEM, HIS_NORMAL, &rect, + NULL); + } + else { + if (GetWindowLongW (hwnd, GWL_STYLE) & HDS_BUTTONS) + DrawEdge (hdc, &rect, EDGE_RAISED, BF_TOP|BF_LEFT|BF_BOTTOM|BF_SOFT); + else + DrawEdge (hdc, &rect, EDGE_ETCHED, BF_BOTTOM); + } } SelectObject (hdc, hOldFont); @@ -1278,6 +1320,7 @@ HEADER_Create (HWND hwnd, WPARAM wParam, LPARAM lParam) TEXTMETRICW tm; HFONT hOldFont; HDC hdc; + BOOL themingActive = IsAppThemed() && IsThemeActive(); infoPtr = (HEADER_INFO *)Alloc (sizeof(HEADER_INFO)); SetWindowLongPtrW (hwnd, 0, (DWORD_PTR)infoPtr); @@ -1307,6 +1350,8 @@ HEADER_Create (HWND hwnd, WPARAM wParam, LPARAM lParam) SelectObject (hdc, hOldFont); ReleaseDC (0, hdc); + if (themingActive) OpenThemeData(hwnd, themeClass); + return 0; } @@ -1317,6 +1362,7 @@ HEADER_Destroy (HWND hwnd, WPARAM wParam, LPARAM lParam) HEADER_INFO *infoPtr = HEADER_GetInfoPtr (hwnd); HEADER_ITEM *lpItem; INT nItem; + HTHEME theme; if (infoPtr->items) { lpItem = infoPtr->items; @@ -1332,6 +1378,9 @@ HEADER_Destroy (HWND hwnd, WPARAM wParam, LPARAM lParam) SetWindowLongPtrW (hwnd, 0, 0); Free (infoPtr); + + theme = GetWindowTheme(hwnd); + CloseThemeData(theme); return 0; } @@ -1692,6 +1741,16 @@ HEADER_SetFont (HWND hwnd, WPARAM wParam, LPARAM lParam) return 0; } +/* Update the theme handle after a theme change */ +static LRESULT HEADER_ThemeChanged(HWND hwnd) +{ + HTHEME theme = GetWindowTheme(hwnd); + CloseThemeData(theme); + OpenThemeData(hwnd, themeClass); + InvalidateRect(hwnd, NULL, FALSE); + return 0; +} + static LRESULT WINAPI HEADER_WindowProc (HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam) @@ -1804,6 +1863,9 @@ HEADER_WindowProc (HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam) case WM_SIZE: return HEADER_Size (hwnd, wParam); + case WM_THEMECHANGED: + return HEADER_ThemeChanged (hwnd); + case WM_PAINT: return HEADER_Paint (hwnd, wParam); diff --git a/reactos/lib/comctl32/imagelist.c b/reactos/lib/comctl32/imagelist.c index b87309d6513..dc191e4a755 100644 --- a/reactos/lib/comctl32/imagelist.c +++ b/reactos/lib/comctl32/imagelist.c @@ -2226,25 +2226,51 @@ ImageList_ReplaceIcon (HIMAGELIST himl, INT i, HICON hIcon) HBITMAP hbmOldSrc; ICONINFO ii; BITMAP bmp; + BOOL ret; TRACE("(%p %d %p)\n", himl, i, hIcon); - if (!is_valid(himl)) - return -1; - if ((i >= himl->cMaxImage) || (i < -1)) - return -1; + if (!is_valid(himl)) { + ERR("invalid image list\n"); + return -1; + } + if ((i >= himl->cMaxImage) || (i < -1)) { + ERR("invalid image index %d / %d\n", i, himl->cMaxImage); + return -1; + } hBestFitIcon = CopyImage( hIcon, IMAGE_ICON, himl->cx, himl->cy, LR_COPYFROMRESOURCE); + /* the above will fail if the icon wasn't loaded from a resource, so try + * again without LR_COPYFROMRESOURCE flag */ + if (!hBestFitIcon) + hBestFitIcon = CopyImage( + hIcon, IMAGE_ICON, + himl->cx, himl->cy, + 0); + if (!hBestFitIcon) + return -1; + + ret = GetIconInfo (hBestFitIcon, &ii); + if (!ret) { + DestroyIcon(hBestFitIcon); + return -1; + } - GetIconInfo (hBestFitIcon, &ii); - if (ii.hbmMask == 0) - ERR("no mask!\n"); if (ii.hbmColor == 0) ERR("no color!\n"); - GetObjectA (ii.hbmMask, sizeof(BITMAP), (LPVOID)&bmp); + ret = GetObjectW (ii.hbmMask, sizeof(BITMAP), (LPVOID)&bmp); + if (!ret) { + ERR("couldn't get mask bitmap info\n"); + if (ii.hbmColor) + DeleteObject (ii.hbmColor); + if (ii.hbmMask) + DeleteObject (ii.hbmMask); + DestroyIcon(hBestFitIcon); + return -1; + } if (i == -1) { if (himl->cCurImage + 1 > himl->cMaxImage) @@ -2276,8 +2302,7 @@ ImageList_ReplaceIcon (HIMAGELIST himl, INT i, HICON hIcon) SelectObject (hdcImage, hbmOldSrc); - if(hBestFitIcon) - DestroyIcon(hBestFitIcon); + DestroyIcon(hBestFitIcon); if (hdcImage) DeleteDC (hdcImage); if (ii.hbmColor) diff --git a/reactos/lib/comctl32/listview.c b/reactos/lib/comctl32/listview.c index 9f2a927da38..cc6cc6524ea 100644 --- a/reactos/lib/comctl32/listview.c +++ b/reactos/lib/comctl32/listview.c @@ -185,6 +185,7 @@ #include "winnls.h" #include "commctrl.h" #include "comctl32.h" +#include "uxtheme.h" #include "wine/debug.h" #include "wine/unicode.h" @@ -396,6 +397,8 @@ typedef struct tagLISTVIEW_INFO TRACE("hwndSelf=%p, rcList=%s\n", iP->hwndSelf, debugrect(&iP->rcList)); \ } while(0) +static const WCHAR themeClass[] = {'L','i','s','t','V','i','e','w',0}; + /* * forward declarations */ @@ -740,6 +743,12 @@ static inline LPCSTR debugscrollcode(int nScrollCode) /******** Notification functions i************************************/ +static LRESULT notify_forward_header(LISTVIEW_INFO *infoPtr, const NMHEADERW *lpnmh) +{ + return SendMessageW(infoPtr->hwndNotify, WM_NOTIFY, + (WPARAM)lpnmh->hdr.idFrom, (LPARAM)lpnmh); +} + static LRESULT notify_hdr(LISTVIEW_INFO *infoPtr, INT code, LPNMHDR pnmh) { LRESULT result; @@ -1967,6 +1976,7 @@ static void LISTVIEW_GetItemMetrics(LISTVIEW_INFO *infoPtr, const LVITEMW *lpLVI if (lprcState) *lprcState = State; TRACE(" - state=%s\n", debugrect(&State)); } + else State.right = 0; /************************************************************/ /* compute ICON bounding box (ala LVM_GETITEMRECT) */ @@ -1989,7 +1999,7 @@ static void LISTVIEW_GetItemMetrics(LISTVIEW_INFO *infoPtr, const LVITEMW *lpLVI } else /* LVS_SMALLICON, LVS_LIST or LVS_REPORT */ { - Icon.left = State.right; + Icon.left = State.right; Icon.top = Box.top; Icon.right = Icon.left; if (infoPtr->himlSmall && @@ -2001,6 +2011,7 @@ static void LISTVIEW_GetItemMetrics(LISTVIEW_INFO *infoPtr, const LVITEMW *lpLVI if(lprcIcon) *lprcIcon = Icon; TRACE(" - icon=%s\n", debugrect(&Icon)); } + else Icon.right = 0; /************************************************************/ /* compute LABEL bounding box (ala LVM_GETITEMRECT) */ @@ -4812,6 +4823,7 @@ static INT LISTVIEW_FindItemW(LISTVIEW_INFO *infoPtr, INT nStart, } bNearest = TRUE; } + else Destination.x = Destination.y = 0; /* if LVFI_PARAM is specified, all other flags are ignored */ if (lpFindInfo->flags & LVFI_PARAM) @@ -7444,6 +7456,25 @@ static BOOL LISTVIEW_SortItems(LISTVIEW_INFO *infoPtr, PFNLVCOMPARE pfnCompare, return TRUE; } +/*** + * DESCRIPTION: + * Update theme handle after a theme change. + * + * PARAMETER(S): + * [I] infoPtr : valid pointer to the listview structure + * + * RETURN: + * SUCCESS : 0 + * FAILURE : something else + */ +static LRESULT LISTVIEW_ThemeChanged(LISTVIEW_INFO *infoPtr) +{ + HTHEME theme = GetWindowTheme(infoPtr->hwndSelf); + CloseThemeData(theme); + OpenThemeData(infoPtr->hwndSelf, themeClass); + return 0; +} + /*** * DESCRIPTION: * Updates an items or rearranges the listview control. @@ -7489,6 +7520,7 @@ static LRESULT LISTVIEW_Create(HWND hwnd, const CREATESTRUCTW *lpcs) LISTVIEW_INFO *infoPtr; UINT uView = lpcs->style & LVS_TYPEMASK; LOGFONTW logFont; + BOOL themingActive = IsAppThemed() && IsThemeActive(); TRACE("(lpcs=%p)\n", lpcs); @@ -7571,6 +7603,8 @@ static LRESULT LISTVIEW_Create(HWND hwnd, const CREATESTRUCTW *lpcs) } } + if (themingActive) OpenThemeData(hwnd, themeClass); + return 0; fail: @@ -7584,6 +7618,24 @@ fail: return -1; } +/*** + * DESCRIPTION: + * Destroys the listview control. + * + * PARAMETER(S): + * [I] infoPtr : valid pointer to the listview structure + * + * RETURN: + * Success: 0 + * Failure: -1 + */ +static LRESULT LISTVIEW_Destroy(LISTVIEW_INFO *infoPtr) +{ + HTHEME theme = GetWindowTheme(infoPtr->hwndSelf); + CloseThemeData(theme); + return 0; +} + /*** * DESCRIPTION: * Enables the listview control. @@ -8274,10 +8326,15 @@ static LRESULT LISTVIEW_HeaderNotification(LISTVIEW_INFO *infoPtr, const NMHEADE switch (lpnmh->hdr.code) { - case HDN_TRACKW: - case HDN_TRACKA: + case HDN_ITEMCHANGINGW: + case HDN_ITEMCHANGINGA: + return notify_forward_header(infoPtr, lpnmh); case HDN_ITEMCHANGEDW: case HDN_ITEMCHANGEDA: + notify_forward_header(infoPtr, lpnmh); + /* Fall through */ + case HDN_TRACKW: + case HDN_TRACKA: { COLUMN_INFO *lpColumnInfo; INT dx, cxy; @@ -8347,6 +8404,53 @@ static LRESULT LISTVIEW_HeaderNotification(LISTVIEW_INFO *infoPtr, const NMHEADE return 0; } +/*** + * DESCRIPTION: + * Paint non-client area of control. + * + * PARAMETER(S): + * [I] infoPtr : valid pointer to the listview structureof the sender + * [I] region : update region + * + * RETURN: + * TRUE - frame was painted + * FALSE - call default window proc + */ +static BOOL LISTVIEW_NCPaint(LISTVIEW_INFO *infoPtr, HRGN region) +{ + HTHEME theme = GetWindowTheme (infoPtr->hwndSelf); + BOOL themingActive = IsAppThemed() && IsThemeActive(); + BOOL doTheming = themingActive && (theme != NULL); + HDC dc; + RECT r; + HRGN cliprgn; + int cxEdge = GetSystemMetrics (SM_CXEDGE), + cyEdge = GetSystemMetrics (SM_CYEDGE); + + if (!doTheming) return FALSE; + + GetWindowRect(infoPtr->hwndSelf, &r); + + cliprgn = CreateRectRgn (r.left + cxEdge, r.top + cyEdge, + r.right - cxEdge, r.bottom - cyEdge); + if (region != (HRGN)1) + CombineRgn (cliprgn, cliprgn, region, RGN_AND); + OffsetRect(&r, -r.left, -r.top); + + dc = GetDCEx(infoPtr->hwndSelf, region, DCX_WINDOW|DCX_INTERSECTRGN); + OffsetRect(&r, -r.left, -r.top); + + if (IsThemeBackgroundPartiallyTransparent (theme, 0, 0)) + DrawThemeParentBackground(infoPtr->hwndSelf, dc, &r); + DrawThemeBackground (theme, dc, 0, 0, &r, 0); + ReleaseDC(infoPtr->hwndSelf, dc); + + /* Call default proc to get the scrollbars etc. painted */ + DefWindowProcW (infoPtr->hwndSelf, WM_NCPAINT, (WPARAM)cliprgn, 0); + + return TRUE; +} + /*** * DESCRIPTION: * Determines the type of structure to use. @@ -9244,6 +9348,9 @@ LISTVIEW_WindowProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam) case WM_CREATE: return LISTVIEW_Create(hwnd, (LPCREATESTRUCTW)lParam); + case WM_DESTROY: + return LISTVIEW_Destroy(infoPtr); + case WM_ENABLE: return LISTVIEW_Enable(infoPtr, (BOOL)wParam); @@ -9283,6 +9390,11 @@ LISTVIEW_WindowProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam) case WM_NCDESTROY: return LISTVIEW_NCDestroy(infoPtr); + case WM_NCPAINT: + if (LISTVIEW_NCPaint(infoPtr, (HRGN)wParam)) + return 0; + goto fwd_msg; + case WM_NOTIFY: if (lParam && ((LPNMHDR)lParam)->hwndFrom == infoPtr->hwndHeader) return LISTVIEW_HeaderNotification(infoPtr, (LPNMHEADERW)lParam); @@ -9331,6 +9443,8 @@ LISTVIEW_WindowProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam) return 0; /* case WM_TIMER: */ + case WM_THEMECHANGED: + return LISTVIEW_ThemeChanged(infoPtr); case WM_VSCROLL: return LISTVIEW_VScroll(infoPtr, (INT)LOWORD(wParam), 0, (HWND)lParam); diff --git a/reactos/lib/comctl32/propsheet.c b/reactos/lib/comctl32/propsheet.c index 67609adbe3a..bcf8b428cc9 100644 --- a/reactos/lib/comctl32/propsheet.c +++ b/reactos/lib/comctl32/propsheet.c @@ -33,7 +33,6 @@ * - Enforcing of minimal wizard size * - Messages: * o PSM_GETRESULT - * o PSM_IDTOINDEX * o PSM_INSERTPAGE * o PSM_RECALCPAGESIZES * o PSM_SETHEADERSUBTITLE @@ -45,7 +44,6 @@ * o PSN_QUERYINITIALFOCUS * o PSN_TRANSLATEACCELERATOR * - Styles: - * o PSH_WIZARDHASFINISH * o PSH_RTLREADING * o PSH_STRETCHWATERMARK * o PSH_USEPAGELANG @@ -68,6 +66,7 @@ #include "commctrl.h" #include "prsht.h" #include "comctl32.h" +#include "uxtheme.h" #include "wine/debug.h" #include "wine/unicode.h" @@ -121,6 +120,7 @@ typedef struct tagPropSheetInfo BOOL isModeless; BOOL hasHelp; BOOL hasApply; + BOOL hasFinish; BOOL useCallback; BOOL restartWindows; BOOL rebootSystem; @@ -233,13 +233,11 @@ static VOID PROPSHEET_UnImplementedFlags(DWORD dwFlags) /* * unhandled header flags: - * PSH_WIZARDHASFINISH 0x00000010 * PSH_RTLREADING 0x00000800 * PSH_STRETCHWATERMARK 0x00040000 * PSH_USEPAGELANG 0x00200000 */ - add_flag(PSH_WIZARDHASFINISH); add_flag(PSH_RTLREADING); add_flag(PSH_STRETCHWATERMARK); add_flag(PSH_USEPAGELANG); @@ -341,6 +339,7 @@ static BOOL PROPSHEET_CollectSheetInfoA(LPCPROPSHEETHEADERA lppsh, psInfo->hasHelp = dwFlags & PSH_HASHELP; psInfo->hasApply = !(dwFlags & PSH_NOAPPLYNOW); + psInfo->hasFinish = dwFlags & PSH_WIZARDHASFINISH; psInfo->useCallback = (dwFlags & PSH_USECALLBACK )&& (lppsh->pfnCallback); psInfo->isModeless = dwFlags & PSH_MODELESS; @@ -396,6 +395,7 @@ static BOOL PROPSHEET_CollectSheetInfoW(LPCPROPSHEETHEADERW lppsh, psInfo->hasHelp = dwFlags & PSH_HASHELP; psInfo->hasApply = !(dwFlags & PSH_NOAPPLYNOW); + psInfo->hasFinish = dwFlags & PSH_WIZARDHASFINISH; psInfo->useCallback = (dwFlags & PSH_USECALLBACK) && (lppsh->pfnCallback); psInfo->isModeless = dwFlags & PSH_MODELESS; @@ -1004,6 +1004,8 @@ static BOOL PROPSHEET_AdjustButtonsWizard(HWND hwndParent, if (psInfo->hasHelp) num_buttons++; + if (psInfo->hasFinish) + num_buttons++; /* * Obtain the size of the buttons. @@ -1024,40 +1026,47 @@ static BOOL PROPSHEET_AdjustButtonsWizard(HWND hwndParent, * All buttons will be at this y coordinate. */ y = rcSheet.bottom - (padding.y + buttonHeight); - - /* - * Position the Next and the Finish buttons. - */ - hwndButton = GetDlgItem(hwndParent, IDC_NEXT_BUTTON); - - x = rcSheet.right - ((padding.x + buttonWidth) * (num_buttons - 1)); - - SetWindowPos(hwndButton, 0, x, y, 0, 0, - SWP_NOSIZE | SWP_NOZORDER | SWP_NOACTIVATE); - - hwndButton = GetDlgItem(hwndParent, IDC_FINISH_BUTTON); - - SetWindowPos(hwndButton, 0, x, y, 0, 0, - SWP_NOSIZE | SWP_NOZORDER | SWP_NOACTIVATE); - - ShowWindow(hwndButton, SW_HIDE); - + /* * Position the Back button. */ hwndButton = GetDlgItem(hwndParent, IDC_BACK_BUTTON); - x -= buttonWidth; + x = rcSheet.right - ((padding.x + buttonWidth) * (num_buttons - 1)) - buttonWidth; SetWindowPos(hwndButton, 0, x, y, 0, 0, SWP_NOSIZE | SWP_NOZORDER | SWP_NOACTIVATE); + /* + * Position the Next button. + */ + hwndButton = GetDlgItem(hwndParent, IDC_NEXT_BUTTON); + + x += buttonWidth; + + SetWindowPos(hwndButton, 0, x, y, 0, 0, + SWP_NOSIZE | SWP_NOZORDER | SWP_NOACTIVATE); + + /* + * Position the Finish button. + */ + hwndButton = GetDlgItem(hwndParent, IDC_FINISH_BUTTON); + + if (psInfo->hasFinish) + x += padding.x + buttonWidth; + + SetWindowPos(hwndButton, 0, x, y, 0, 0, + SWP_NOSIZE | SWP_NOZORDER | SWP_NOACTIVATE); + + if (!psInfo->hasFinish) + ShowWindow(hwndButton, SW_HIDE); + /* * Position the Cancel button. */ hwndButton = GetDlgItem(hwndParent, IDCANCEL); - x = rcSheet.right - ((padding.x + buttonWidth) * (num_buttons - 2)); + x += padding.x + buttonWidth; SetWindowPos(hwndButton, 0, x, y, 0, 0, SWP_NOSIZE | SWP_NOZORDER | SWP_NOACTIVATE); @@ -1069,7 +1078,7 @@ static BOOL PROPSHEET_AdjustButtonsWizard(HWND hwndParent, if (psInfo->hasHelp) { - x = rcSheet.right - (padding.x + buttonWidth); + x += padding.x + buttonWidth; SetWindowPos(hwndButton, 0, x, y, 0, 0, SWP_NOSIZE | SWP_NOZORDER | SWP_NOACTIVATE); @@ -1533,6 +1542,8 @@ static BOOL PROPSHEET_CreatePage(HWND hwndParent, SetWindowSubclass(hwndPage, PROPSHEET_WizardSubclassProc, 1, (DWORD_PTR)ppshpage); } + if (!(psInfo->ppshheader.dwFlags & INTRNL_ANY_WIZARD)) + EnableThemeDialogTexture (hwndPage, ETDT_ENABLETAB); return TRUE; } @@ -1623,9 +1634,6 @@ static BOOL PROPSHEET_ShowPage(HWND hwndDlg, int index, PropSheetInfo * psInfo) ShowWindow(hwndLineHeader, SW_SHOW); } - InvalidateRgn(hwndDlg, NULL, TRUE); - UpdateWindow(hwndDlg); - return TRUE; } @@ -2196,6 +2204,7 @@ static void PROPSHEET_SetTitleW(HWND hwndDlg, DWORD dwStyle, LPCWSTR lpszText) */ static void PROPSHEET_SetFinishTextA(HWND hwndDlg, LPCSTR lpszText) { + PropSheetInfo* psInfo = (PropSheetInfo*) GetPropW(hwndDlg, PropSheetInfoStr); HWND hwndButton = GetDlgItem(hwndDlg, IDC_FINISH_BUTTON); TRACE("'%s'\n", lpszText); @@ -2211,9 +2220,12 @@ static void PROPSHEET_SetFinishTextA(HWND hwndDlg, LPCSTR lpszText) hwndButton = GetDlgItem(hwndDlg, IDC_BACK_BUTTON); ShowWindow(hwndButton, SW_HIDE); - /* Hide Next button */ - hwndButton = GetDlgItem(hwndDlg, IDC_NEXT_BUTTON); - ShowWindow(hwndButton, SW_HIDE); + if (!psInfo->hasFinish) + { + /* Hide Next button */ + hwndButton = GetDlgItem(hwndDlg, IDC_NEXT_BUTTON); + ShowWindow(hwndButton, SW_HIDE); + } } /****************************************************************************** @@ -2221,6 +2233,7 @@ static void PROPSHEET_SetFinishTextA(HWND hwndDlg, LPCSTR lpszText) */ static void PROPSHEET_SetFinishTextW(HWND hwndDlg, LPCWSTR lpszText) { + PropSheetInfo* psInfo = (PropSheetInfo*) GetPropW(hwndDlg, PropSheetInfoStr); HWND hwndButton = GetDlgItem(hwndDlg, IDC_FINISH_BUTTON); TRACE("'%s'\n", debugstr_w(lpszText)); @@ -2236,9 +2249,12 @@ static void PROPSHEET_SetFinishTextW(HWND hwndDlg, LPCWSTR lpszText) hwndButton = GetDlgItem(hwndDlg, IDC_BACK_BUTTON); ShowWindow(hwndButton, SW_HIDE); - /* Hide Next button */ - hwndButton = GetDlgItem(hwndDlg, IDC_NEXT_BUTTON); - ShowWindow(hwndButton, SW_HIDE); + if (!psInfo->hasFinish) + { + /* Hide Next button */ + hwndButton = GetDlgItem(hwndDlg, IDC_NEXT_BUTTON); + ShowWindow(hwndButton, SW_HIDE); + } } /****************************************************************************** @@ -2439,6 +2455,8 @@ static BOOL PROPSHEET_RemovePage(HWND hwndDlg, */ static void PROPSHEET_SetWizButtons(HWND hwndDlg, DWORD dwFlags) { + PropSheetInfo* psInfo = (PropSheetInfo*) GetPropW(hwndDlg, + PropSheetInfoStr); HWND hwndBack = GetDlgItem(hwndDlg, IDC_BACK_BUTTON); HWND hwndNext = GetDlgItem(hwndDlg, IDC_NEXT_BUTTON); HWND hwndFinish = GetDlgItem(hwndDlg, IDC_FINISH_BUTTON); @@ -2454,8 +2472,11 @@ static void PROPSHEET_SetWizButtons(HWND hwndDlg, DWORD dwFlags) if (dwFlags & PSWIZB_NEXT) { - /* Hide the Finish button */ - ShowWindow(hwndFinish, SW_HIDE); + if (!psInfo->hasFinish) + { + /* Hide the Finish button */ + ShowWindow(hwndFinish, SW_HIDE); + } /* Show and enable the Next button */ ShowWindow(hwndNext, SW_SHOW); @@ -2465,20 +2486,27 @@ static void PROPSHEET_SetWizButtons(HWND hwndDlg, DWORD dwFlags) SendMessageW(hwndDlg, DM_SETDEFID, IDC_NEXT_BUTTON, 0); } - if ((dwFlags & PSWIZB_FINISH) || (dwFlags & PSWIZB_DISABLEDFINISH)) + if (!psInfo->hasFinish) { - /* Hide the Next button */ - ShowWindow(hwndNext, SW_HIDE); + if ((dwFlags & PSWIZB_FINISH) || (dwFlags & PSWIZB_DISABLEDFINISH)) + { + /* Hide the Next button */ + ShowWindow(hwndNext, SW_HIDE); + + /* Show the Finish button */ + ShowWindow(hwndFinish, SW_SHOW); - /* Show the Finish button */ - ShowWindow(hwndFinish, SW_SHOW); + if (!(dwFlags & PSWIZB_DISABLEDFINISH)) + { + EnableWindow(hwndFinish, TRUE); - if (dwFlags & PSWIZB_FINISH) - EnableWindow(hwndFinish, TRUE); - - /* Set the Finish button as the default pushbutton */ - SendMessageW(hwndDlg, DM_SETDEFID, IDC_FINISH_BUTTON, 0); + /* Set the Finish button as the default pushbutton */ + SendMessageW(hwndDlg, DM_SETDEFID, IDC_FINISH_BUTTON, 0); + } + } } + else if (!(dwFlags & PSWIZB_DISABLEDFINISH)) + EnableWindow(hwndFinish, TRUE); } /****************************************************************************** @@ -2596,7 +2624,17 @@ static LRESULT PROPSHEET_IndexToPage(HWND hwndDlg, int iPageIndex) */ static LRESULT PROPSHEET_IdToIndex(HWND hwndDlg, int iPageId) { - FIXME("(%p, %d): stub\n", hwndDlg, iPageId); + int index; + LPCPROPSHEETPAGEW psp; + PropSheetInfo * psInfo = (PropSheetInfo*) GetPropW(hwndDlg, + PropSheetInfoStr); + TRACE("(%p, %d)\n", hwndDlg, iPageId); + for (index = 0; index < psInfo->nPages; index++) { + psp = (LPCPROPSHEETPAGEW)psInfo->proppage[index].hpage; + if (psp->u.pszTemplate == (LPCWSTR)iPageId) + return index; + } + return -1; } @@ -3473,6 +3511,10 @@ PROPSHEET_DialogProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam) return FALSE; } + + case WM_SYSCOLORCHANGE: + COMCTL32_RefreshSysColors(); + return FALSE; case PSM_GETCURRENTPAGEHWND: { diff --git a/reactos/lib/comctl32/toolbar.c b/reactos/lib/comctl32/toolbar.c index cd8c0b43248..f2981a7635e 100644 --- a/reactos/lib/comctl32/toolbar.c +++ b/reactos/lib/comctl32/toolbar.c @@ -118,7 +118,6 @@ typedef struct typedef struct { DWORD dwStructSize; /* size of TBBUTTON struct */ - INT nHeight; /* height of the toolbar */ INT nWidth; /* width of the toolbar */ RECT client_rect; RECT rcBound; /* bounding rectangle */ @@ -156,8 +155,6 @@ typedef struct HWND hwndToolTip; /* handle to tool tip control */ HWND hwndNotify; /* handle to the window that gets notifications */ HWND hwndSelf; /* my own handle */ - BOOL bBtnTranspnt; /* button transparency flag */ - BOOL bAutoSize; /* auto size deadlock indicator */ BOOL bAnchor; /* anchor highlight enabled */ BOOL bDoRedraw; /* Redraw status */ BOOL bDragOutSent; /* has TBN_DRAGOUT notification been sent for this drag? */ @@ -249,6 +246,7 @@ static VOID TOOLBAR_DeleteImageList(PIMLENTRY **pies, INT *cies); static HIMAGELIST TOOLBAR_InsertImageList(PIMLENTRY **pies, INT *cies, HIMAGELIST himl, INT id); static LRESULT TOOLBAR_LButtonDown(HWND hwnd, WPARAM wParam, LPARAM lParam); static void TOOLBAR_SetHotItemEx (TOOLBAR_INFO *infoPtr, INT nHit, DWORD dwReason); +static LRESULT TOOLBAR_AutoSize(HWND hwnd); static LRESULT TOOLBAR_NotifyFormat(TOOLBAR_INFO *infoPtr, WPARAM wParam, LPARAM lParam); @@ -580,7 +578,7 @@ TOOLBAR_DrawString (TOOLBAR_INFO *infoPtr, RECT *rcText, LPWSTR lpText, else if ((state & CDIS_MARKED) && !(infoPtr->dwItemCDFlag & TBCDRF_NOMARK)) { clrOld = SetTextColor (hdc, tbcd->clrTextHighlight); clrOldBk = SetBkColor (hdc, tbcd->clrMark); - oldBkMode = SetBkMode (hdc, OPAQUE); /* FIXME: should this be in the NMTBCUSTOMDRAW structure? */ + oldBkMode = SetBkMode (hdc, tbcd->nHLStringBkMode); } else { clrOld = SetTextColor (hdc, tbcd->clrText); @@ -671,7 +669,7 @@ TOOLBAR_TranslateState(TBUTTON_INFO *btnPtr) retstate |= (btnPtr->fsState & TBSTATE_ENABLED) ? 0 : CDIS_DISABLED; retstate |= (btnPtr->fsState & TBSTATE_MARKED ) ? CDIS_MARKED : 0; retstate |= (btnPtr->bHot ) ? CDIS_HOT : 0; - retstate |= (btnPtr->fsState & TBSTATE_INDETERMINATE) ? CDIS_INDETERMINATE : 0; + retstate |= ((btnPtr->fsState & (TBSTATE_ENABLED|TBSTATE_INDETERMINATE)) == (TBSTATE_ENABLED|TBSTATE_INDETERMINATE)) ? CDIS_INDETERMINATE : 0; /* NOTE: we don't set CDIS_GRAYED, CDIS_FOCUS, CDIS_DEFAULT */ return retstate; } @@ -815,6 +813,7 @@ TOOLBAR_DrawButton (HWND hwnd, TBUTTON_INFO *btnPtr, HDC hdc) NMTBCUSTOMDRAW tbcd; DWORD ntfret; INT offset; + INT oldBkMode; rc = btnPtr->rect; CopyRect (&rcArrow, &rc); @@ -894,8 +893,8 @@ TOOLBAR_DrawButton (HWND hwnd, TBUTTON_INFO *btnPtr, HDC hdc) tbcd.clrBtnHighlight = comctl32_color.clrBtnHighlight; tbcd.clrMark = comctl32_color.clrHighlight; tbcd.clrHighlightHotTrack = 0; - tbcd.nStringBkMode = (infoPtr->bBtnTranspnt) ? TRANSPARENT : OPAQUE; - tbcd.nHLStringBkMode = (infoPtr->bBtnTranspnt) ? TRANSPARENT : OPAQUE; + tbcd.nStringBkMode = TRANSPARENT; + tbcd.nHLStringBkMode = OPAQUE; /* MSDN says that this is the text rectangle. * But (why always a but) tracing of v5.7 of native shows * that this is really a *relative* rectangle based on the @@ -983,8 +982,10 @@ TOOLBAR_DrawButton (HWND hwnd, TBUTTON_INFO *btnPtr, HDC hdc) if (drawSepDropDownArrow) TOOLBAR_DrawSepDDArrow(infoPtr, &tbcd, &rcArrow, btnPtr->bDropDownPressed); + oldBkMode = SetBkMode (hdc, tbcd.nStringBkMode); if (!(infoPtr->dwExStyle & TBSTYLE_EX_MIXEDBUTTONS) || (btnPtr->fsStyle & BTNS_SHOWTEXT)) TOOLBAR_DrawString (infoPtr, &rcText, lpText, &tbcd); + SetBkMode (hdc, oldBkMode); TOOLBAR_DrawImage(infoPtr, btnPtr, rcBitmap.left, rcBitmap.top, &tbcd); @@ -1007,16 +1008,8 @@ TOOLBAR_DrawButton (HWND hwnd, TBUTTON_INFO *btnPtr, HDC hdc) FINALNOTIFY: if (infoPtr->dwItemCustDraw & CDRF_NOTIFYPOSTPAINT) { - tbcd.nmcd.dwDrawStage = CDDS_ITEMPOSTPAINT; - tbcd.nmcd.hdc = hdc; - tbcd.nmcd.rc = rc; - tbcd.nmcd.dwItemSpec = btnPtr->idCommand; - tbcd.nmcd.uItemState = TOOLBAR_TranslateState(btnPtr); - tbcd.nmcd.lItemlParam = btnPtr->dwData; - tbcd.rcText = rcText; - tbcd.nStringBkMode = (infoPtr->bBtnTranspnt) ? TRANSPARENT : OPAQUE; - tbcd.nHLStringBkMode = (infoPtr->bBtnTranspnt) ? TRANSPARENT : OPAQUE; - ntfret = TOOLBAR_SendNotify(&tbcd.nmcd.hdr, infoPtr, NM_CUSTOMDRAW); + tbcd.nmcd.dwDrawStage = CDDS_ITEMPOSTPAINT; + TOOLBAR_SendNotify(&tbcd.nmcd.hdr, infoPtr, NM_CUSTOMDRAW); } } @@ -1027,7 +1020,7 @@ TOOLBAR_Refresh (HWND hwnd, HDC hdc, PAINTSTRUCT* ps) { TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd); TBUTTON_INFO *btnPtr; - INT i, oldBKmode = 0; + INT i; RECT rcTemp, rcClient; NMTBCUSTOMDRAW tbcd; DWORD ntfret; @@ -1055,9 +1048,6 @@ TOOLBAR_Refresh (HWND hwnd, HDC hdc, PAINTSTRUCT* ps) ntfret = TOOLBAR_SendNotify(&tbcd.nmcd.hdr, infoPtr, NM_CUSTOMDRAW); infoPtr->dwBaseCustDraw = ntfret & 0xffff; - if (infoPtr->bBtnTranspnt) - oldBKmode = SetBkMode (hdc, TRANSPARENT); - GetClientRect(hwnd, &rcClient); /* redraw necessary buttons */ @@ -1092,9 +1082,6 @@ TOOLBAR_Refresh (HWND hwnd, HDC hdc, PAINTSTRUCT* ps) COMCTL32_DrawInsertMark(hdc, &rcInsertMark, infoPtr->clrInsertMark, FALSE); } - if (infoPtr->bBtnTranspnt && (oldBKmode != TRANSPARENT)) - SetBkMode (hdc, oldBKmode); - if (infoPtr->dwBaseCustDraw & CDRF_NOTIFYPOSTPAINT) { ZeroMemory (&tbcd, sizeof(NMTBCUSTOMDRAW)); @@ -1175,12 +1162,20 @@ TOOLBAR_CalcStrings (HWND hwnd, LPSIZE lpSize) lpSize->cx = 0; lpSize->cy = 0; - if(infoPtr->nMaxTextRows == 0) + if (infoPtr->nMaxTextRows == 0) return; hdc = GetDC (hwnd); hOldFont = SelectObject (hdc, infoPtr->hFont); + if (infoPtr->nNumButtons == 0) + { + TEXTMETRICW tm; + + GetTextMetricsW(hdc, &tm); + lpSize->cy = tm.tmHeight; + } + btnPtr = infoPtr->buttons; for (i = 0; i < infoPtr->nNumButtons; i++, btnPtr++) { if(TOOLBAR_HasText(infoPtr, btnPtr)) @@ -1557,7 +1552,6 @@ TOOLBAR_CalcToolbar (HWND hwnd) INT x, y, cx, cy; SIZE sizeString, sizeButton; BOOL bWrap; - BOOL usesBitmaps = FALSE; BOOL validImageList = FALSE; BOOL hasDropDownArrows = TOOLBAR_HasDropDownArrows(infoPtr->dwExStyle); @@ -1565,14 +1559,9 @@ TOOLBAR_CalcToolbar (HWND hwnd) TOOLBAR_DumpToolbar (infoPtr, __LINE__); - for (i = 0; i < infoPtr->nNumButtons && !usesBitmaps; i++) - { - if (TOOLBAR_IsValidBitmapIndex(infoPtr,infoPtr->buttons[i].iBitmap)) - usesBitmaps = TRUE; - } if (TOOLBAR_IsValidImageList(infoPtr, 0)) validImageList = TRUE; - sizeButton = TOOLBAR_MeasureButton(infoPtr, sizeString, usesBitmaps, validImageList); + sizeButton = TOOLBAR_MeasureButton(infoPtr, sizeString, TRUE, validImageList); infoPtr->nButtonWidth = sizeButton.cx; infoPtr->nButtonHeight = sizeButton.cy; @@ -1584,14 +1573,14 @@ TOOLBAR_CalcToolbar (HWND hwnd) TOOLBAR_WrapToolbar( hwnd, dwStyle ); x = infoPtr->nIndent; - y = 0; + if (infoPtr->dwStyle & TBSTYLE_FLAT) + y = 0; + else + y = TOP_BORDER; /* from above, minimum is a button, and possible text */ cx = infoPtr->nButtonWidth; - - infoPtr->nHeight = infoPtr->nButtonHeight; - - cy = infoPtr->nHeight; + cy = infoPtr->nButtonHeight; nRows = nSepRows = 0; @@ -1613,7 +1602,7 @@ TOOLBAR_CalcToolbar (HWND hwnd) continue; } - cy = infoPtr->nHeight; + cy = infoPtr->nButtonHeight; /* UNDOCUMENTED: If a separator has a non zero bitmap index, */ /* it is the actual width of the separator. This is used for */ @@ -1728,27 +1717,7 @@ TOOLBAR_CalcToolbar (HWND hwnd) /* infoPtr->nRows is the number of rows on the toolbar */ infoPtr->nRows = nRows + nSepRows + 1; -#if 0 - /******************************************************************** - * The following while interesting, does not match the values * - * created above for the button rectangles, nor the rcBound rect. * - * We will comment it out and remove it later. * - * * - * The problem showed up as heights in the pager control that was * - * wrong. * - ********************************************************************/ - - /* nSepRows * (infoPtr->nBitmapHeight + 1) is the space following */ - /* the last row. */ - infoPtr->nHeight = TOP_BORDER + (nRows + 1) * infoPtr->nButtonHeight + - nSepRows * (SEPARATOR_WIDTH * 2 / 3) + - nSepRows * (infoPtr->nBitmapHeight + 1) + - BOTTOM_BORDER; -#endif - - infoPtr->nHeight = infoPtr->rcBound.bottom - infoPtr->rcBound.top; - - TRACE("toolbar height %d, button width %d\n", infoPtr->nHeight, infoPtr->nButtonWidth); + TRACE("toolbar button width %d\n", infoPtr->nButtonWidth); } @@ -2731,7 +2700,7 @@ TOOLBAR_AddBitmap (HWND hwnd, WPARAM wParam, LPARAM lParam) { TBITMAP_INFO *oldBitmaps = infoPtr->bitmaps; infoPtr->bitmaps = Alloc((infoPtr->nNumBitmapInfos + 1) * sizeof(TBITMAP_INFO)); - memcpy(&infoPtr->bitmaps[0], &oldBitmaps[0], infoPtr->nNumBitmapInfos); + memcpy(&infoPtr->bitmaps[0], &oldBitmaps[0], infoPtr->nNumBitmapInfos * sizeof(TBITMAP_INFO)); } infoPtr->bitmaps[infoPtr->nNumBitmapInfos].nButtons = nButtons; @@ -2821,6 +2790,7 @@ TOOLBAR_AddButtonsA (HWND hwnd, WPARAM wParam, LPARAM lParam) } TOOLBAR_CalcToolbar (hwnd); + TOOLBAR_AutoSize (hwnd); TOOLBAR_DumpToolbar (infoPtr, __LINE__); @@ -2889,6 +2859,7 @@ TOOLBAR_AddButtonsW (HWND hwnd, WPARAM wParam, LPARAM lParam) } TOOLBAR_CalcToolbar (hwnd); + TOOLBAR_AutoSize (hwnd); TOOLBAR_DumpToolbar (infoPtr, __LINE__); @@ -3082,66 +3053,66 @@ TOOLBAR_AutoSize (HWND hwnd) { TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd); RECT parent_rect; - RECT window_rect; HWND parent; INT x, y; INT cx, cy; - UINT uPosFlags = SWP_NOZORDER; - TRACE("resize forced, style=%lx!\n", infoPtr->dwStyle); + TRACE("auto sizing, style=%lx!\n", infoPtr->dwStyle); parent = GetParent (hwnd); + + if (!parent || !infoPtr->bDoRedraw) + return 0; + GetClientRect(parent, &parent_rect); x = parent_rect.left; y = parent_rect.top; - /* FIXME: we should be able to early out if nothing */ - /* has changed with nWidth != parent_rect width */ + TRACE("nRows: %d, infoPtr->nButtonHeight: %d\n", infoPtr->nRows, infoPtr->nButtonHeight); - if (infoPtr->dwStyle & CCS_NORESIZE) { - uPosFlags |= (SWP_NOSIZE | SWP_NOMOVE); - cx = 0; - cy = 0; - TOOLBAR_CalcToolbar (hwnd); + cy = TOP_BORDER + infoPtr->nRows * infoPtr->nButtonHeight + BOTTOM_BORDER; + cx = parent_rect.right - parent_rect.left; + + if ((infoPtr->dwStyle & TBSTYLE_WRAPABLE) || (infoPtr->dwExStyle & TBSTYLE_EX_UNDOC1)) + { + TOOLBAR_CalcToolbar(hwnd); + InvalidateRect( hwnd, NULL, TRUE ); } - else { - infoPtr->nWidth = parent_rect.right - parent_rect.left; - TOOLBAR_CalcToolbar (hwnd); - InvalidateRect( hwnd, NULL, TRUE ); - cy = infoPtr->nHeight; - cx = infoPtr->nWidth; - if ((infoPtr->dwStyle & CCS_BOTTOM) == CCS_NOMOVEY) { - GetWindowRect(hwnd, &window_rect); - ScreenToClient(parent, (LPPOINT)&window_rect.left); - y = window_rect.top; - } - if ((infoPtr->dwStyle & CCS_BOTTOM) == CCS_BOTTOM) { + if (!(infoPtr->dwStyle & CCS_NORESIZE)) + { + RECT window_rect; + UINT uPosFlags = SWP_NOZORDER; + + if ((infoPtr->dwStyle & CCS_BOTTOM) == CCS_NOMOVEY) + { + GetWindowRect(hwnd, &window_rect); + ScreenToClient(parent, (LPPOINT)&window_rect.left); + y = window_rect.top; + } + if ((infoPtr->dwStyle & CCS_BOTTOM) == CCS_BOTTOM) + { GetWindowRect(hwnd, &window_rect); y = parent_rect.bottom - ( window_rect.bottom - window_rect.top); } + + if (infoPtr->dwStyle & CCS_NOPARENTALIGN) + uPosFlags |= SWP_NOMOVE; + + if (!(infoPtr->dwStyle & CCS_NODIVIDER)) + cy += GetSystemMetrics(SM_CYEDGE); + + if (infoPtr->dwStyle & WS_BORDER) + { + x = y = 1; /* FIXME: this looks wrong */ + cy += GetSystemMetrics(SM_CYEDGE); + cx += GetSystemMetrics(SM_CXEDGE); + } + + SetWindowPos(hwnd, NULL, x, y, cx, cy, uPosFlags); } - if (infoPtr->dwStyle & CCS_NOPARENTALIGN) - uPosFlags |= SWP_NOMOVE; - - if (!(infoPtr->dwStyle & CCS_NODIVIDER)) - cy += GetSystemMetrics(SM_CYEDGE); - - if (infoPtr->dwStyle & WS_BORDER) - { - x = y = 1; - cy += GetSystemMetrics(SM_CYEDGE); - cx += GetSystemMetrics(SM_CXEDGE); - } - - infoPtr->bAutoSize = TRUE; - SetWindowPos (hwnd, HWND_TOP, x, y, cx, cy, uPosFlags); - /* The following line makes sure that the infoPtr->bAutoSize is turned off - * after the setwindowpos calls */ - infoPtr->bAutoSize = FALSE; - return 0; } @@ -3985,6 +3956,7 @@ TOOLBAR_InsertButtonA (HWND hwnd, WPARAM wParam, LPARAM lParam) Free (oldButtons); TOOLBAR_CalcToolbar (hwnd); + TOOLBAR_AutoSize (hwnd); InvalidateRect (hwnd, NULL, TRUE); @@ -4085,6 +4057,7 @@ TOOLBAR_InsertButtonW (HWND hwnd, WPARAM wParam, LPARAM lParam) Free (oldButtons); TOOLBAR_CalcToolbar (hwnd); + TOOLBAR_AutoSize (hwnd); InvalidateRect (hwnd, NULL, TRUE); @@ -4330,6 +4303,7 @@ TOOLBAR_MoveButton (HWND hwnd, WPARAM wParam, LPARAM lParam) } TOOLBAR_CalcToolbar(hwnd); + TOOLBAR_AutoSize(hwnd); InvalidateRect(hwnd, NULL, TRUE); return TRUE; @@ -4369,6 +4343,7 @@ TOOLBAR_ReplaceBitmap (HWND hwnd, WPARAM wParam, LPARAM lParam) TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd); LPTBREPLACEBITMAP lpReplace = (LPTBREPLACEBITMAP) lParam; HBITMAP hBitmap; + HBITMAP hbmLoad = NULL; int i = 0, nOldButtons = 0, pos = 0; int nOldBitmaps, nNewBitmaps = 0; HIMAGELIST himlDef = 0; @@ -4383,9 +4358,12 @@ TOOLBAR_ReplaceBitmap (HWND hwnd, WPARAM wParam, LPARAM lParam) return FALSE; } else if (lpReplace->hInstOld != 0) - { FIXME("resources not in the current module not implemented\n"); - return FALSE; + + if (lpReplace->hInstNew) + { + hbmLoad = LoadBitmapW(lpReplace->hInstNew,(LPWSTR)lpReplace->nIDNew); + hBitmap = hbmLoad; } else { @@ -4412,6 +4390,8 @@ TOOLBAR_ReplaceBitmap (HWND hwnd, WPARAM wParam, LPARAM lParam) if (nOldButtons == 0) { WARN("No hinst/bitmap found! hInst %p nID %x\n", lpReplace->hInstOld, lpReplace->nIDOld); + if (hbmLoad) + DeleteObject (hbmLoad); return FALSE; } @@ -4463,6 +4443,8 @@ TOOLBAR_ReplaceBitmap (HWND hwnd, WPARAM wParam, LPARAM lParam) InvalidateRect(hwnd, NULL, TRUE); + if (hbmLoad) + DeleteObject (hbmLoad); return TRUE; } @@ -4864,12 +4846,6 @@ TOOLBAR_SetButtonWidth (HWND hwnd, WPARAM wParam, LPARAM lParam) infoPtr->cxMin = (INT)LOWORD(lParam); infoPtr->cxMax = (INT)HIWORD(lParam); - /* if both values are 0 then we are done */ - if (lParam == 0) { - TRACE("setting both min and max to 0, norecalc\n"); - return TRUE; - } - /* otherwise we need to recalc the toolbar and in some cases recalc the bounding rectangle (does DrawText w/ DT_CALCRECT which doesn't actually draw - GA). */ @@ -5530,7 +5506,6 @@ TOOLBAR_Unkwn463 (HWND hwnd, WPARAM wParam, LPARAM lParam) break; case 1: lpsize->cy = infoPtr->rcBound.bottom - infoPtr->rcBound.top; - /* lpsize->cy = infoPtr->nHeight; */ break; default: ERR("Unknown wParam %d for Toolbar message [0463]. Please report\n", @@ -5566,7 +5541,6 @@ TOOLBAR_Create (HWND hwnd, WPARAM wParam, LPARAM lParam) infoPtr->nBitmapHeight = 15; infoPtr->nBitmapWidth = 16; - infoPtr->nHeight = infoPtr->nButtonHeight + TOP_BORDER + BOTTOM_BORDER; infoPtr->nMaxTextRows = 1; infoPtr->cxMin = -1; infoPtr->cxMax = -1; @@ -5579,7 +5553,6 @@ TOOLBAR_Create (HWND hwnd, WPARAM wParam, LPARAM lParam) infoPtr->nOldHit = -1; infoPtr->nHotItem = -1; infoPtr->hwndNotify = ((LPCREATESTRUCTW)lParam)->hwndParent; - infoPtr->bBtnTranspnt = (dwStyle & (TBSTYLE_FLAT | TBSTYLE_LIST)); infoPtr->dwDTFlags = (dwStyle & TBSTYLE_LIST) ? DT_LEFT | DT_VCENTER | DT_SINGLELINE | DT_END_ELLIPSIS: DT_CENTER | DT_END_ELLIPSIS; infoPtr->bAnchor = FALSE; /* no anchor highlighting */ infoPtr->bDragOutSent = FALSE; @@ -6641,131 +6614,50 @@ static LRESULT TOOLBAR_Size (HWND hwnd, WPARAM wParam, LPARAM lParam) { TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd); - DWORD dwStyle = infoPtr->dwStyle; - RECT parent_rect; - RECT window_rect; - HWND parent; - INT x, y; - INT cx, cy; - INT flags; - UINT uPosFlags = 0; - - /* Resize deadlock check */ - if (infoPtr->bAutoSize) { - infoPtr->bAutoSize = FALSE; - return 0; - } - - /* FIXME: optimize to only update size if the new size doesn't */ - /* match the current size */ - - flags = (INT) wParam; - - /* FIXME for flags = - * SIZE_MAXIMIZED, SIZE_MAXSHOW, SIZE_MINIMIZED - */ TRACE("sizing toolbar!\n"); - if (flags == SIZE_RESTORED) { - /* width and height don't apply */ - parent = GetParent (hwnd); - GetClientRect(parent, &parent_rect); - x = parent_rect.left; - y = parent_rect.top; + if (infoPtr->dwExStyle & TBSTYLE_EX_HIDECLIPPEDBUTTONS) + { + RECT delta_width, delta_height, client, dummy; + DWORD min_x, max_x, min_y, max_y; + TBUTTON_INFO *btnPtr; + INT i; - if (dwStyle & CCS_NORESIZE) { - uPosFlags |= (SWP_NOSIZE | SWP_NOMOVE); - - /* - * this sets the working width of the toolbar, and - * Calc Toolbar will not adjust it, only the height - */ - infoPtr->nWidth = parent_rect.right - parent_rect.left; - cy = infoPtr->nHeight; - cx = infoPtr->nWidth; - TOOLBAR_CalcToolbar (hwnd); - infoPtr->nWidth = cx; - infoPtr->nHeight = cy; - } - else { - infoPtr->nWidth = parent_rect.right - parent_rect.left; - TOOLBAR_CalcToolbar (hwnd); - cy = infoPtr->nHeight; - cx = infoPtr->nWidth; - - if ((dwStyle & CCS_BOTTOM) == CCS_NOMOVEY) { - GetWindowRect(hwnd, &window_rect); - ScreenToClient(parent, (LPPOINT)&window_rect.left); - y = window_rect.top; - } - if ((dwStyle & CCS_BOTTOM) == CCS_BOTTOM) { - GetWindowRect(hwnd, &window_rect); - y = parent_rect.bottom - - ( window_rect.bottom - window_rect.top); - } - } - - if (dwStyle & CCS_NOPARENTALIGN) { - uPosFlags |= SWP_NOMOVE; - cy = infoPtr->nHeight; - cx = infoPtr->nWidth; - } - - if (!(dwStyle & CCS_NODIVIDER)) - cy += GetSystemMetrics(SM_CYEDGE); - - if (dwStyle & WS_BORDER) - { - x = y = 1; - cy += GetSystemMetrics(SM_CYEDGE); - cx += GetSystemMetrics(SM_CXEDGE); - } - - if(infoPtr->dwExStyle & TBSTYLE_EX_HIDECLIPPEDBUTTONS) + GetClientRect(hwnd, &client); + if(client.right > infoPtr->client_rect.right) { - RECT delta_width, delta_height, client, dummy; - DWORD min_x, max_x, min_y, max_y; - TBUTTON_INFO *btnPtr; - INT i; - - GetClientRect(hwnd, &client); - if(client.right > infoPtr->client_rect.right) - { - min_x = infoPtr->client_rect.right; - max_x = client.right; - } - else - { - max_x = infoPtr->client_rect.right; - min_x = client.right; - } - if(client.bottom > infoPtr->client_rect.bottom) - { - min_y = infoPtr->client_rect.bottom; - max_y = client.bottom; - } - else - { - max_y = infoPtr->client_rect.bottom; - min_y = client.bottom; - } - - SetRect(&delta_width, min_x, 0, max_x, min_y); - SetRect(&delta_height, 0, min_y, max_x, max_y); - - TRACE("delta_width %s delta_height %s\n", wine_dbgstr_rect(&delta_width), wine_dbgstr_rect(&delta_height)); - btnPtr = infoPtr->buttons; - for (i = 0; i < infoPtr->nNumButtons; i++, btnPtr++) - if(IntersectRect(&dummy, &delta_width, &btnPtr->rect) || - IntersectRect(&dummy, &delta_height, &btnPtr->rect)) - InvalidateRect(hwnd, &btnPtr->rect, TRUE); + min_x = infoPtr->client_rect.right; + max_x = client.right; + } + else + { + max_x = infoPtr->client_rect.right; + min_x = client.right; + } + if(client.bottom > infoPtr->client_rect.bottom) + { + min_y = infoPtr->client_rect.bottom; + max_y = client.bottom; + } + else + { + max_y = infoPtr->client_rect.bottom; + min_y = client.bottom; } - if((uPosFlags & (SWP_NOSIZE | SWP_NOMOVE)) != (SWP_NOSIZE | SWP_NOMOVE)) - SetWindowPos (hwnd, 0, x, y, cx, cy, uPosFlags | SWP_NOZORDER); + SetRect(&delta_width, min_x, 0, max_x, min_y); + SetRect(&delta_height, 0, min_y, max_x, max_y); + + TRACE("delta_width %s delta_height %s\n", wine_dbgstr_rect(&delta_width), wine_dbgstr_rect(&delta_height)); + btnPtr = infoPtr->buttons; + for (i = 0; i < infoPtr->nNumButtons; i++, btnPtr++) + if(IntersectRect(&dummy, &delta_width, &btnPtr->rect) || + IntersectRect(&dummy, &delta_height, &btnPtr->rect)) + InvalidateRect(hwnd, &btnPtr->rect, TRUE); } GetClientRect(hwnd, &infoPtr->client_rect); + TOOLBAR_AutoSize(hwnd); return 0; } @@ -6782,8 +6674,6 @@ TOOLBAR_StyleChanged (HWND hwnd, INT nType, LPSTYLESTRUCT lpStyle) else infoPtr->dwDTFlags = DT_CENTER | DT_END_ELLIPSIS; - infoPtr->bBtnTranspnt = (lpStyle->styleNew & - (TBSTYLE_FLAT | TBSTYLE_LIST)); TOOLBAR_CheckStyle (hwnd, lpStyle->styleNew); TRACE("new style 0x%08lx\n", lpStyle->styleNew); diff --git a/reactos/lib/comctl32/updown.c b/reactos/lib/comctl32/updown.c index 5cdc23a5916..d8898815f3a 100644 --- a/reactos/lib/comctl32/updown.c +++ b/reactos/lib/comctl32/updown.c @@ -40,6 +40,8 @@ #include "winnls.h" #include "commctrl.h" #include "comctl32.h" +#include "uxtheme.h" +#include "tmschema.h" #include "wine/unicode.h" #include "wine/debug.h" @@ -75,7 +77,8 @@ typedef struct #define DEFAULT_ADDBOT 0 /* amount to extend below the buddy window */ #define DEFAULT_BUDDYBORDER 2 /* Width/height of the buddy border */ #define DEFAULT_BUDDYSPACER 2 /* Spacer between the buddy and the ctrl */ - +#define DEFAULT_BUDDYBORDER_THEMED 1 /* buddy border when theming is enabled */ +#define DEFAULT_BUDDYSPACER_THEMED 0 /* buddy spacer when theming is enabled */ /* Work constants */ @@ -175,6 +178,9 @@ static BOOL UPDOWN_HasBuddyBorder(UPDOWN_INFO* infoPtr) */ static void UPDOWN_GetArrowRect (UPDOWN_INFO* infoPtr, RECT *rect, int arrow) { + HTHEME theme = GetWindowTheme (infoPtr->Self); + const int border = theme ? DEFAULT_BUDDYBORDER_THEMED : DEFAULT_BUDDYBORDER; + const int spacer = theme ? DEFAULT_BUDDYSPACER_THEMED : DEFAULT_BUDDYSPACER; GetClientRect (infoPtr->Self, rect); /* @@ -183,17 +189,17 @@ static void UPDOWN_GetArrowRect (UPDOWN_INFO* infoPtr, RECT *rect, int arrow) */ if (UPDOWN_HasBuddyBorder(infoPtr)) { if (infoPtr->dwStyle & UDS_ALIGNLEFT) - rect->left += DEFAULT_BUDDYBORDER; + rect->left += border; else - rect->right -= DEFAULT_BUDDYBORDER; + rect->right -= border; - InflateRect(rect, 0, -DEFAULT_BUDDYBORDER); + InflateRect(rect, 0, -border); } /* now figure out if we need a space away from the buddy */ - if ( IsWindow(infoPtr->Buddy) ) { - if (infoPtr->dwStyle & UDS_ALIGNLEFT) rect->right -= DEFAULT_BUDDYSPACER; - else rect->left += DEFAULT_BUDDYSPACER; + if (IsWindow(infoPtr->Buddy) ) { + if (infoPtr->dwStyle & UDS_ALIGNLEFT) rect->right -= spacer; + else rect->left += spacer; } /* @@ -206,11 +212,11 @@ static void UPDOWN_GetArrowRect (UPDOWN_INFO* infoPtr, RECT *rect, int arrow) if (arrow & FLAG_INCR) rect->left = rect->left + len/2; if (arrow & FLAG_DECR) - rect->right = rect->left + len/2 - 1; + rect->right = rect->left + len/2 - (theme ? 0 : 1); } else { int len = rect->bottom - rect->top + 1; /* compute the height */ if (arrow & FLAG_INCR) - rect->bottom = rect->top + len/2 - 1; + rect->bottom = rect->top + len/2 - (theme ? 0 : 1); if (arrow & FLAG_DECR) rect->top = rect->top + len/2; } @@ -219,10 +225,10 @@ static void UPDOWN_GetArrowRect (UPDOWN_INFO* infoPtr, RECT *rect, int arrow) /*********************************************************************** * UPDOWN_GetArrowFromPoint * Returns the rectagle (for the up or down arrow) that contains pt. - * If it returns the up rect, it returns TRUE. - * If it returns the down rect, it returns FALSE. + * If it returns the up rect, it returns FLAG_INCR. + * If it returns the down rect, it returns FLAG_DECR. */ -static BOOL UPDOWN_GetArrowFromPoint (UPDOWN_INFO* infoPtr, RECT *rect, POINT pt) +static INT UPDOWN_GetArrowFromPoint (UPDOWN_INFO* infoPtr, RECT *rect, POINT pt) { UPDOWN_GetArrowRect (infoPtr, rect, FLAG_INCR); if(PtInRect(rect, pt)) return FLAG_INCR; @@ -341,6 +347,24 @@ static BOOL UPDOWN_SetBuddyInt (UPDOWN_INFO *infoPtr) return SetWindowTextW(infoPtr->Buddy, txt); } +/*********************************************************************** + * UPDOWN_DrawBuddyBackground + * + * Draw buddy background for visual integration. + */ +static BOOL UPDOWN_DrawBuddyBackground (UPDOWN_INFO *infoPtr, HDC hdc) +{ + RECT br; + HTHEME buddyTheme = GetWindowTheme (infoPtr->Buddy); + if (!buddyTheme) return FALSE; + + GetClientRect (infoPtr->Buddy, &br); + MapWindowPoints (infoPtr->Buddy, infoPtr->Self, (POINT*)&br, 2); + /* FIXME: take disabled etc. into account */ + DrawThemeBackground (buddyTheme, hdc, 0, 0, &br, NULL); + return TRUE; +} + /*********************************************************************** * UPDOWN_Draw * @@ -348,36 +372,61 @@ static BOOL UPDOWN_SetBuddyInt (UPDOWN_INFO *infoPtr) */ static LRESULT UPDOWN_Draw (UPDOWN_INFO *infoPtr, HDC hdc) { - BOOL pressed, hot; + BOOL uPressed, uHot, dPressed, dHot; RECT rect; + HTHEME theme = GetWindowTheme (infoPtr->Self); + int uPart = 0, uState = 0, dPart = 0, dState = 0; + BOOL needBuddyBg = FALSE; + + uPressed = (infoPtr->Flags & FLAG_PRESSED) && (infoPtr->Flags & FLAG_INCR); + uHot = (infoPtr->Flags & FLAG_INCR) && (infoPtr->Flags & FLAG_MOUSEIN); + dPressed = (infoPtr->Flags & FLAG_PRESSED) && (infoPtr->Flags & FLAG_DECR); + dHot = (infoPtr->Flags & FLAG_DECR) && (infoPtr->Flags & FLAG_MOUSEIN); + if (theme) { + uPart = (infoPtr->dwStyle & UDS_HORZ) ? SPNP_UPHORZ : SPNP_UP; + uState = (infoPtr->dwStyle & WS_DISABLED) ? DNS_DISABLED + : (uPressed ? DNS_PRESSED : (uHot ? DNS_HOT : DNS_NORMAL)); + dPart = (infoPtr->dwStyle & UDS_HORZ) ? SPNP_DOWNHORZ : SPNP_DOWN; + dState = (infoPtr->dwStyle & WS_DISABLED) ? DNS_DISABLED + : (dPressed ? DNS_PRESSED : (dHot ? DNS_HOT : DNS_NORMAL)); + needBuddyBg = IsWindow (infoPtr->Buddy) + && (IsThemeBackgroundPartiallyTransparent (theme, uPart, uState) + || IsThemeBackgroundPartiallyTransparent (theme, dPart, dState)); + } /* Draw the common border between ourselves and our buddy */ - if (UPDOWN_HasBuddyBorder(infoPtr)) { - GetClientRect(infoPtr->Self, &rect); - DrawEdge(hdc, &rect, EDGE_SUNKEN, - BF_BOTTOM | BF_TOP | - (infoPtr->dwStyle & UDS_ALIGNLEFT ? BF_LEFT : BF_RIGHT)); + if (UPDOWN_HasBuddyBorder(infoPtr) || needBuddyBg) { + if (!theme || !UPDOWN_DrawBuddyBackground (infoPtr, hdc)) { + GetClientRect(infoPtr->Self, &rect); + DrawEdge(hdc, &rect, EDGE_SUNKEN, + BF_BOTTOM | BF_TOP | + (infoPtr->dwStyle & UDS_ALIGNLEFT ? BF_LEFT : BF_RIGHT)); + } } /* Draw the incr button */ UPDOWN_GetArrowRect (infoPtr, &rect, FLAG_INCR); - pressed = (infoPtr->Flags & FLAG_PRESSED) && (infoPtr->Flags & FLAG_INCR); - hot = (infoPtr->Flags & FLAG_INCR) && (infoPtr->Flags & FLAG_MOUSEIN); - DrawFrameControl(hdc, &rect, DFC_SCROLL, - (infoPtr->dwStyle & UDS_HORZ ? DFCS_SCROLLRIGHT : DFCS_SCROLLUP) | - ((infoPtr->dwStyle & UDS_HOTTRACK) && hot ? DFCS_HOT : 0) | - (pressed ? DFCS_PUSHED : 0) | - (infoPtr->dwStyle & WS_DISABLED ? DFCS_INACTIVE : 0) ); + if (theme) { + DrawThemeBackground(theme, hdc, uPart, uState, &rect, NULL); + } else { + DrawFrameControl(hdc, &rect, DFC_SCROLL, + (infoPtr->dwStyle & UDS_HORZ ? DFCS_SCROLLRIGHT : DFCS_SCROLLUP) | + ((infoPtr->dwStyle & UDS_HOTTRACK) && uHot ? DFCS_HOT : 0) | + (uPressed ? DFCS_PUSHED : 0) | + (infoPtr->dwStyle & WS_DISABLED ? DFCS_INACTIVE : 0) ); + } /* Draw the decr button */ UPDOWN_GetArrowRect(infoPtr, &rect, FLAG_DECR); - pressed = (infoPtr->Flags & FLAG_PRESSED) && (infoPtr->Flags & FLAG_DECR); - hot = (infoPtr->Flags & FLAG_DECR) && (infoPtr->Flags & FLAG_MOUSEIN); - DrawFrameControl(hdc, &rect, DFC_SCROLL, - (infoPtr->dwStyle & UDS_HORZ ? DFCS_SCROLLLEFT : DFCS_SCROLLDOWN) | - ((infoPtr->dwStyle & UDS_HOTTRACK) && hot ? DFCS_HOT : 0) | - (pressed ? DFCS_PUSHED : 0) | - (infoPtr->dwStyle & WS_DISABLED ? DFCS_INACTIVE : 0) ); + if (theme) { + DrawThemeBackground(theme, hdc, dPart, dState, &rect, NULL); + } else { + DrawFrameControl(hdc, &rect, DFC_SCROLL, + (infoPtr->dwStyle & UDS_HORZ ? DFCS_SCROLLLEFT : DFCS_SCROLLDOWN) | + ((infoPtr->dwStyle & UDS_HOTTRACK) && dHot ? DFCS_HOT : 0) | + (dPressed ? DFCS_PUSHED : 0) | + (infoPtr->dwStyle & WS_DISABLED ? DFCS_INACTIVE : 0) ); + } return 0; } @@ -653,6 +702,7 @@ static void UPDOWN_HandleMouseEvent (UPDOWN_INFO *infoPtr, UINT msg, INT x, INT POINT pt = { x, y }; RECT rect; int temp, arrow; + TRACKMOUSEEVENT tme; TRACE("msg %04x point %s\n", msg, wine_dbgstr_point(&pt)); @@ -713,7 +763,19 @@ static void UPDOWN_HandleMouseEvent (UPDOWN_INFO *infoPtr, UINT msg, INT x, INT /* If state changed, redraw the control */ if(temp != infoPtr->Flags) - InvalidateRect (infoPtr->Self, &rect, FALSE); + InvalidateRect (infoPtr->Self, NULL, FALSE); + + /* Set up tracking so the mousein flags can be reset when the + * mouse leaves the control */ + tme.cbSize = sizeof( tme ); + tme.dwFlags = TME_LEAVE; + tme.hwndTrack = infoPtr->Self; + TrackMouseEvent (&tme); + + break; + case WM_MOUSELEAVE: + infoPtr->Flags &= ~(FLAG_MOUSEIN | FLAG_ARROW); + InvalidateRect (infoPtr->Self, NULL, FALSE); break; default: @@ -729,6 +791,8 @@ static LRESULT WINAPI UpDownWindowProc(HWND hwnd, UINT message, WPARAM wParam, L { UPDOWN_INFO *infoPtr = UPDOWN_GetInfoPtr (hwnd); int temp; + static const WCHAR themeClass[] = {'S','p','i','n',0}; + HTHEME theme; TRACE("hwnd=%p msg=%04x wparam=%08x lparam=%08lx\n", hwnd, message, wParam, lParam); @@ -761,6 +825,8 @@ static LRESULT WINAPI UpDownWindowProc(HWND hwnd, UINT message, WPARAM wParam, L if (infoPtr->dwStyle & UDS_AUTOBUDDY) UPDOWN_SetBuddy (infoPtr, GetWindow (hwnd, GW_HWNDPREV)); + OpenThemeData (hwnd, themeClass); + TRACE("UpDown Ctrl creation, hwnd=%p\n", hwnd); break; @@ -771,6 +837,8 @@ static LRESULT WINAPI UpDownWindowProc(HWND hwnd, UINT message, WPARAM wParam, L Free (infoPtr); SetWindowLongPtrW (hwnd, 0, 0); + theme = GetWindowTheme (hwnd); + CloseThemeData (theme); TRACE("UpDown Ctrl destruction, hwnd=%p\n", hwnd); break; @@ -791,6 +859,13 @@ static LRESULT WINAPI UpDownWindowProc(HWND hwnd, UINT message, WPARAM wParam, L } break; + case WM_THEMECHANGED: + theme = GetWindowTheme (hwnd); + CloseThemeData (theme); + OpenThemeData (hwnd, themeClass); + InvalidateRect (hwnd, NULL, FALSE); + break; + case WM_TIMER: /* is this the auto-press timer? */ if(wParam == TIMER_AUTOPRESS) { @@ -849,6 +924,7 @@ static LRESULT WINAPI UpDownWindowProc(HWND hwnd, UINT message, WPARAM wParam, L case WM_LBUTTONDOWN: case WM_MOUSEMOVE: + case WM_MOUSELEAVE: if(UPDOWN_IsEnabled(infoPtr)) UPDOWN_HandleMouseEvent (infoPtr, message, (SHORT)LOWORD(lParam), (SHORT)HIWORD(lParam)); break;