From 6477510568218ecc212fe5b89479b9713595e2af Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?G=C3=A9=20van=20Geldorp?= Date: Thu, 11 Mar 2004 11:13:28 +0000 Subject: [PATCH] Sync to Wine-20040309: Robert Shearman - Implement the drag list control. - Fix tabs in LBItemFromPt. - Move string functions to separate file. - Implement string functions in comctl32. - Use CompareString in shlwapi wherever possible instead of ugly helpers. - Forward some wrapper functions since we don't care about compatibility with Win98 in this case. - Documentation update. - Update common control function documentation. - Don't allocate space for text when nMaxTextRows = 0. - Support custom check background. - Reduce number of parameters needed for DrawString function. - Fix some traces. - The TBM_GET*HOTLIST functions take imagelist ID in wParam. - Implement TBM_GETSTRING{A,W}. - Implement undocumented 0x462 message. Alexandre Julliard - Removed a couple of unneeded helper functions. Maxime BellengT - Fix a regression in ImageList_Create when creating a dibsection. Ulrich Czekalla - Use dibsections for the images. Dimitrie O. Paun - LVN_BEGINRDRAG is implemented now. Fix typo. Aric Stewart - Implemented LISTVIEW_ApproximateViewRect for LVS_REPORT. Fabian Cenedese - ListView should behave in OWNERDRAW as in FULLROWSELECT. This allows to select cells not in the first column in REPORT mode with OWNERDRAW style set. Matt Chapman - Fix a reentrancy issue in the property sheet implementation by not caching a pointer that can change. - REBAR_Layout should respect the minimum size of bands even when RBBS_FIXEDSIZE is not set. - REBAR_ShowBand needs to force layout of the rebar after a band is hidden/unhidden. Vitaliy Margolen - Adjust all dimensions to match native. - Invalidate whole tab area when multi-line. - In vertical tab placement go from top to bottom. - Fix annoying visual artifacts. Huw Davies - If TBSTYLE_EX_HIDECLIPPEDBUTTONS is set then invalidate the area that changes in a resize. - Don't call SWP unless we're actually adjusting anything. Christian Costa - Accept null module instance, Loadstring can handle it. Steve Lustbader - Handle the firstVisible item being NULL in Mike Hearn - Grow the treeview control expander button by 1px in each direction to match the native look. svn path=/trunk/; revision=8639 --- reactos/include/wine/commctrl.h | 1 + reactos/lib/comctl32/Makefile.in | 2 + reactos/lib/comctl32/comctl32.h | 5 +- reactos/lib/comctl32/comctl32.spec | 34 +- reactos/lib/comctl32/comctl32undoc.c | 437 ++++--------- reactos/lib/comctl32/commctrl.c | 54 +- reactos/lib/comctl32/draglist.c | 305 +++++++-- reactos/lib/comctl32/flatsb.c | 48 +- reactos/lib/comctl32/imagelist.c | 155 +++-- reactos/lib/comctl32/listview.c | 28 +- reactos/lib/comctl32/propsheet.c | 36 +- reactos/lib/comctl32/rebar.c | 6 +- reactos/lib/comctl32/rsrc.rc | 27 + reactos/lib/comctl32/smoothscroll.c | 10 +- reactos/lib/comctl32/string.c | 853 ++++++++++++++++++++++++++ reactos/lib/comctl32/tab.c | 391 ++++++------ reactos/lib/comctl32/toolbar.c | 182 +++++- reactos/lib/comctl32/tooltips.c | 18 +- reactos/lib/comctl32/treeview.c | 6 +- reactos/lib/comctl32/winehq2ros.patch | 104 ++++ reactos/w32api/include/commctrl.h | 4 + 21 files changed, 2009 insertions(+), 697 deletions(-) create mode 100644 reactos/lib/comctl32/string.c diff --git a/reactos/include/wine/commctrl.h b/reactos/include/wine/commctrl.h index 4182c5d70ee..b8ae4a76a0f 100644 --- a/reactos/include/wine/commctrl.h +++ b/reactos/include/wine/commctrl.h @@ -47,6 +47,7 @@ typedef LPFINDINFOW LPLVFINDINFOW; #define TB_UNKWN45D (WM_USER+93) #define TB_UNKWN45E (WM_USER+94) #define TB_UNKWN460 (WM_USER+96) +#define TB_UNKWN462 (WM_USER+98) #define TB_UNKWN463 (WM_USER+99) #define TB_UNKWN464 (WM_USER+100) diff --git a/reactos/lib/comctl32/Makefile.in b/reactos/lib/comctl32/Makefile.in index 32a3b9c14ea..3a60a3b2557 100644 --- a/reactos/lib/comctl32/Makefile.in +++ b/reactos/lib/comctl32/Makefile.in @@ -28,6 +28,7 @@ C_SRCS = \ propsheet.c \ rebar.c \ smoothscroll.c \ + string.c \ status.c \ tab.c \ toolbar.c \ @@ -45,6 +46,7 @@ RC_BINARIES = \ idb_std_small.bmp \ idb_view_large.bmp \ idb_view_small.bmp \ + idc_copy.cur \ idc_divider.cur \ idc_divideropen.cur \ idi_dragarrow.ico \ diff --git a/reactos/lib/comctl32/comctl32.h b/reactos/lib/comctl32/comctl32.h index a9a12ce19a5..a5f2f280aaf 100644 --- a/reactos/lib/comctl32/comctl32.h +++ b/reactos/lib/comctl32/comctl32.h @@ -102,8 +102,9 @@ extern HBRUSH COMCTL32_hPattern55AABrush; #define IDC_DIVIDEROPEN 107 -/* DragList icon */ -#define IDI_DRAGARROW 150 +/* DragList resources */ +#define IDI_DRAGARROW 501 +#define IDC_COPY 502 /* HOTKEY internal strings */ diff --git a/reactos/lib/comctl32/comctl32.spec b/reactos/lib/comctl32/comctl32.spec index 75f3877b762..2348dbec56b 100644 --- a/reactos/lib/comctl32/comctl32.spec +++ b/reactos/lib/comctl32/comctl32.spec @@ -77,16 +77,16 @@ 363 stdcall -noname StrStrIW(wstr wstr) 364 stdcall -noname StrSpnW(wstr wstr) 365 stdcall -noname StrToIntW(wstr) -366 stub -noname StrChrIA -367 stub -noname StrChrIW -368 stub -noname StrRChrIA -369 stub -noname StrRChrIW -372 stub -noname StrRStrIA -373 stub -noname StrRStrIW -374 stub -noname StrCSpnIA -375 stub -noname StrCSpnIW -376 stub -noname IntlStrEqWorkerA -377 stub -noname IntlStrEqWorkerW +366 stdcall -noname StrChrIA(str long) +367 stdcall -noname StrChrIW(wstr long) +368 stdcall -noname StrRChrIA(str str long) +369 stdcall -noname StrRChrIW(wstr wstr long) +372 stdcall -noname StrRStrIA(str str str) +373 stdcall -noname StrRStrIW(wstr wstr wstr) +374 stdcall -noname StrCSpnIA(str str) +375 stdcall -noname StrCSpnIW(wstr wstr) +376 stdcall -noname IntlStrEqWorkerA(long str str long) +377 stdcall -noname IntlStrEqWorkerW(long wstr wstr long) 382 stdcall -noname SmoothScrollWindow(ptr) 383 stub -noname DoReaderMode 384 stub -noname SetPathWordBreakProc @@ -106,13 +106,13 @@ 412 stdcall RemoveWindowSubclass(long ptr long) 413 stdcall DefSubclassProc(long long long long) 414 stub -noname MirrorIcon -415 stdcall -noname DrawTextWrap(long long long long long) -416 stub -noname DrawTextExPrivWrap -417 stdcall -noname ExtTextOutWrap(long long long long ptr wstr long ptr) -418 stub -noname GetCharWidthWrap -419 stdcall -noname GetTextExtentPointWrap(long long long long) -420 stub -noname GetTextExtentPoint32Wrap -421 stub -noname TextOutWrap +415 stdcall DrawTextWrap(long wstr long ptr long) user32.DrawTextW +416 stdcall DrawTextExPrivWrap(long wstr long ptr long ptr) user32.DrawTextExW +417 stdcall ExtTextOutWrap(long long long long ptr wstr long ptr) gdi32.ExtTextOutW +418 stdcall GetCharWidthWrap(long long long long) gdi32.GetCharWidthW +419 stdcall GetTextExtentPointWrap(long wstr long ptr) gdi32.GetTextExtentPointW +420 stdcall GetTextExtentPoint32Wrap(long wstr long ptr) gdi32.GetTextExtentPoint32W +421 stdcall TextOutWrap(long long long wstr long) gdi32.TextOutW # Functions imported by name diff --git a/reactos/lib/comctl32/comctl32undoc.c b/reactos/lib/comctl32/comctl32undoc.c index 1a966566711..fabc4d59032 100644 --- a/reactos/lib/comctl32/comctl32undoc.c +++ b/reactos/lib/comctl32/comctl32undoc.c @@ -25,16 +25,12 @@ * These functions are used by EXPLORER.EXE, IEXPLORE.EXE and * COMCTL32.DLL (internally). * - * TODO - * - Add more functions. - * - Write some documentation. */ #include "config.h" #include "wine/port.h" #include #include -#include /* atoi */ #include #include @@ -101,6 +97,10 @@ typedef HRESULT (CALLBACK *DPALOADPROC)(LPLOADDATA,IStream*,LPARAM); * pStream [I] pointer to a stream * lParam [I] application specific value * + * RETURNS + * Success: TRUE + * Failure: FALSE + * * NOTES * No more information available yet! */ @@ -196,6 +196,10 @@ DPA_LoadStream (HDPA *phDpa, DPALOADPROC loadProc, IStream *pStream, LPARAM lPar * pStream [I] pointer to a stream * lParam [I] application specific value * + * RETURNS + * Success: TRUE + * Failure: FALSE + * * NOTES * No more information available yet! */ @@ -222,6 +226,10 @@ DPA_SaveStream (const HDPA hDpa, DPALOADPROC loadProc, IStream *pStream, LPARAM * pfnMerge [I] pointer to merge function * lParam [I] application specific value * + * RETURNS + * Success: TRUE + * Failure: FALSE + * * NOTES * No more information available yet! */ @@ -505,8 +513,9 @@ typedef struct tagWINEMRULIST #define WMRUF_CHANGED 0x0001 /* MRU list has changed */ /************************************************************************** - * MRU_SaveChanged - Localize MRU saving code + * MRU_SaveChanged (internal) * + * Localize MRU saving code */ VOID MRU_SaveChanged( LPWINEMRULIST mp ) { @@ -570,11 +579,16 @@ VOID MRU_SaveChanged( LPWINEMRULIST mp ) /************************************************************************** * FreeMRUList [COMCTL32.152] * + * Frees a most-recently-used items list. + * * PARAMS * hMRUList [I] Handle to list. * + * RETURNS + * Success: TRUE + * Failure: FALSE */ -DWORD WINAPI +BOOL WINAPI FreeMRUList (HANDLE hMRUList) { LPWINEMRULIST mp = (LPWINEMRULIST)hMRUList; @@ -764,6 +778,8 @@ AddMRUStringW(HANDLE hList, LPCWSTR lpszString) /************************************************************************** * AddMRUStringA [COMCTL32.153] + * + * See AddMRUStringW. */ INT WINAPI AddMRUStringA(HANDLE hList, LPCSTR lpszString) @@ -794,6 +810,8 @@ DelMRUString(HANDLE hList, INT nItemPos) /************************************************************************** * FindMRUStringW [COMCTL32.402] + * + * See FindMRUStringA. */ INT WINAPI FindMRUStringW (HANDLE hList, LPCWSTR lpszString, LPINT lpRegNum) @@ -831,7 +849,7 @@ FindMRUStringA (HANDLE hList, LPCSTR lpszString, LPINT lpRegNum) } /************************************************************************* - * CreateMRUListLazy_common + * CreateMRUListLazy_common (internal) */ HANDLE CreateMRUListLazy_common(LPWINEMRULIST mp) { @@ -915,6 +933,8 @@ HANDLE CreateMRUListLazy_common(LPWINEMRULIST mp) /************************************************************************** * CreateMRUListLazyW [COMCTL32.404] + * + * See CreateMRUListLazyA. */ HANDLE WINAPI CreateMRUListLazyW (LPCREATEMRULISTW lpcml, DWORD dwParam2, DWORD dwParam3, DWORD dwParam4) @@ -938,6 +958,17 @@ CreateMRUListLazyW (LPCREATEMRULISTW lpcml, DWORD dwParam2, DWORD dwParam3, DWOR /************************************************************************** * CreateMRUListLazyA [COMCTL32.157] + * + * Creates a most-recently-used list. + * + * PARAMS + * lpcml [I] ptr to CREATEMRULIST structure. + * dwParam2 [I] Unknown + * dwParam3 [I] Unknown + * dwParam4 [I] Unknown + * + * RETURNS + * Handle to MRU list. */ HANDLE WINAPI CreateMRUListLazyA (LPCREATEMRULISTA lpcml, DWORD dwParam2, DWORD dwParam3, DWORD dwParam4) @@ -964,11 +995,7 @@ CreateMRUListLazyA (LPCREATEMRULISTA lpcml, DWORD dwParam2, DWORD dwParam3, DWOR /************************************************************************** * CreateMRUListW [COMCTL32.400] * - * PARAMS - * lpcml [I] ptr to CREATEMRULIST structure. - * - * RETURNS - * Handle to MRU list. + * See CreateMRUListA. */ HANDLE WINAPI CreateMRUListW (LPCREATEMRULISTW lpcml) @@ -978,6 +1005,14 @@ CreateMRUListW (LPCREATEMRULISTW lpcml) /************************************************************************** * CreateMRUListA [COMCTL32.151] + * + * Creates a most-recently-used list. + * + * PARAMS + * lpcml [I] ptr to CREATEMRULIST structure. + * + * RETURNS + * Handle to MRU list. */ HANDLE WINAPI CreateMRUListA (LPCREATEMRULISTA lpcml) @@ -989,7 +1024,7 @@ CreateMRUListA (LPCREATEMRULISTA lpcml) /************************************************************************** * EnumMRUListW [COMCTL32.403] * - * Enumerate item in a list + * Enumerate item in a most-recenty-used list * * PARAMS * hList [I] list handle @@ -1027,6 +1062,7 @@ DWORD nBufferSize) /************************************************************************** * EnumMRUListA [COMCTL32.154] * + * See EnumMRUListW. */ INT WINAPI EnumMRUListA(HANDLE hList, INT nItemPos, LPVOID lpBuffer, DWORD nBufferSize) @@ -1061,12 +1097,15 @@ DWORD nBufferSize) /************************************************************************** * Str_GetPtrA [COMCTL32.233] * + * Copies a string into a destination buffer. + * * PARAMS - * lpSrc [I] - * lpDest [O] - * nMaxLen [I] + * lpSrc [I] Source string + * lpDest [O] Destination buffer + * nMaxLen [I] Size of buffer in characters * * RETURNS + * The number of characters copied. */ INT WINAPI @@ -1101,11 +1140,19 @@ Str_GetPtrA (LPCSTR lpSrc, LPSTR lpDest, INT nMaxLen) /************************************************************************** * Str_SetPtrA [COMCTL32.234] * + * Makes a copy of a string, allocating memory if necessary. + * * PARAMS - * lppDest [O] - * lpSrc [I] + * lppDest [O] Pointer to destination string + * lpSrc [I] Source string * * RETURNS + * Success: TRUE + * Failure: FALSE + * + * NOTES + * Set lpSrc to NULL to free the memory allocated by a previous call + * to this function. */ BOOL WINAPI @@ -1134,12 +1181,7 @@ Str_SetPtrA (LPSTR *lppDest, LPCSTR lpSrc) /************************************************************************** * Str_GetPtrW [COMCTL32.235] * - * PARAMS - * lpSrc [I] - * lpDest [O] - * nMaxLen [I] - * - * RETURNS + * See Str_GetPtrA. */ INT WINAPI @@ -1174,11 +1216,7 @@ Str_GetPtrW (LPCWSTR lpSrc, LPWSTR lpDest, INT nMaxLen) /************************************************************************** * Str_SetPtrW [COMCTL32.236] * - * PARAMS - * lpDest [O] - * lpSrc [I] - * - * RETURNS + * See Str_SetPtrA. */ BOOL WINAPI @@ -1292,13 +1330,9 @@ Str_SetPtrAtoW (LPWSTR *lppDest, LPCSTR lpSrc) /************************************************************************** - * The DSA-API is a set of functions to create and manipulate arrays of - * fixed-size memory blocks. These arrays can store any kind of data - * (strings, icons...). - */ - -/************************************************************************** - * DSA_Create [COMCTL32.320] Creates a dynamic storage array + * DSA_Create [COMCTL32.320] + * + * Creates a dynamic storage array * * PARAMS * nSize [I] size of the array elements @@ -1307,6 +1341,11 @@ Str_SetPtrAtoW (LPWSTR *lppDest, LPCSTR lpSrc) * 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 @@ -1331,7 +1370,9 @@ DSA_Create (INT nSize, INT nGrow) /************************************************************************** - * DSA_Destroy [COMCTL32.321] Destroys a dynamic storage array + * DSA_Destroy [COMCTL32.321] + * + * Destroys a dynamic storage array * * PARAMS * hdsa [I] pointer to the array control structure @@ -1359,6 +1400,8 @@ DSA_Destroy (const HDSA 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 @@ -1483,6 +1526,8 @@ DSA_SetItem (const HDSA hdsa, INT nIndex, LPVOID pSrc) /************************************************************************** * 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 @@ -1545,6 +1590,8 @@ DSA_InsertItem (const HDSA hdsa, INT nIndex, LPVOID pSrc) /************************************************************************** * 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 @@ -1627,12 +1674,9 @@ DSA_DeleteAllItems (const HDSA hdsa) /************************************************************************** - * The DPA-API is a set of functions to create and manipulate arrays of - * pointers. - */ - -/************************************************************************** - * DPA_Destroy [COMCTL32.329] Destroys a dynamic pointer array + * DPA_Destroy [COMCTL32.329] + * + * Destroys a dynamic pointer array * * PARAMS * hdpa [I] handle (pointer) to the pointer array @@ -2180,6 +2224,10 @@ DPA_Search (const HDPA hdpa, LPVOID pFind, INT nStart, * 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 @@ -2209,7 +2257,9 @@ DPA_CreateEx (INT nGrow, HANDLE hHeap) /************************************************************************** - * DPA_Create [COMCTL32.328] Creates a dynamic pointer array + * DPA_Create [COMCTL32.328] + * + * Creates a dynamic pointer array. * * PARAMS * nGrow [I] number of items by which the array grows when it is filled @@ -2217,6 +2267,10 @@ DPA_CreateEx (INT nGrow, HANDLE hHeap) * 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 @@ -2281,15 +2335,22 @@ DoNotify (LPNOTIFYDATA lpNotify, UINT uCode, LPNMHDR lpHdr) /************************************************************************** * SendNotify [COMCTL32.341] * + * Sends a WM_NOTIFY message to the specified window. + * * PARAMS - * hwndTo [I] - * hwndFrom [I] - * uCode [I] - * lpHdr [I] + * hwndTo [I] Window to receive the message + * hwndFrom [I] Window that the message is from (see notes) + * uCode [I] Notification code + * lpHdr [I] The NMHDR and any additional information to send or NULL * * RETURNS * Success: return value from notification * Failure: 0 + * + * NOTES + * If hwndFrom is -1 then the identifier of the control sending the + * message is taken from the NMHDR structure. + * If hwndFrom is not -1 then lpHdr can be NULL. */ LRESULT WINAPI SendNotify (HWND hwndTo, HWND hwndFrom, UINT uCode, LPNMHDR lpHdr) @@ -2311,16 +2372,23 @@ LRESULT WINAPI SendNotify (HWND hwndTo, HWND hwndFrom, UINT uCode, LPNMHDR lpHdr /************************************************************************** * SendNotifyEx [COMCTL32.342] * + * Sends a WM_NOTIFY message to the specified window. + * * PARAMS - * hwndFrom [I] - * hwndTo [I] - * uCode [I] - * lpHdr [I] - * dwParam5 [I] + * hwndFrom [I] Window to receive the message + * hwndTo [I] Window that the message is from + * uCode [I] Notification code + * lpHdr [I] The NMHDR and any additional information to send or NULL + * dwParam5 [I] Unknown * * RETURNS * Success: return value from notification * Failure: 0 + * + * NOTES + * If hwndFrom is -1 then the identifier of the control sending the + * message is taken from the NMHDR structure. + * If hwndFrom is not -1 then lpHdr can be NULL. */ LRESULT WINAPI SendNotifyEx (HWND hwndTo, HWND hwndFrom, UINT uCode, @@ -2350,96 +2418,6 @@ LRESULT WINAPI SendNotifyEx (HWND hwndTo, HWND hwndFrom, UINT uCode, } -/************************************************************************** - * StrChrA [COMCTL32.350] - * - */ - -LPSTR WINAPI StrChrA (LPCSTR lpString, CHAR cChar) -{ - return strchr (lpString, cChar); -} - - -/************************************************************************** - * StrStrIA [COMCTL32.355] - */ - -LPSTR WINAPI StrStrIA (LPCSTR lpStr1, LPCSTR lpStr2) -{ - INT len1, len2, i; - CHAR first; - - if (*lpStr2 == 0) - return ((LPSTR)lpStr1); - len1 = 0; - while (lpStr1[len1] != 0) ++len1; - len2 = 0; - while (lpStr2[len2] != 0) ++len2; - if (len2 == 0) - return ((LPSTR)(lpStr1 + len1)); - first = tolower (*lpStr2); - while (len1 >= len2) { - if (tolower(*lpStr1) == first) { - for (i = 1; i < len2; ++i) - if (tolower (lpStr1[i]) != tolower(lpStr2[i])) - break; - if (i >= len2) - return ((LPSTR)lpStr1); - } - ++lpStr1; --len1; - } - return (NULL); -} - -/************************************************************************** - * StrToIntA [COMCTL32.357] Converts a string to a signed integer. - */ - -INT WINAPI StrToIntA (LPSTR lpString) -{ - return atoi(lpString); -} - -/************************************************************************** - * StrStrIW [COMCTL32.363] - */ - -LPWSTR WINAPI StrStrIW (LPCWSTR lpStr1, LPCWSTR lpStr2) -{ - INT len1, len2, i; - WCHAR first; - - if (*lpStr2 == 0) - return ((LPWSTR)lpStr1); - len1 = 0; - while (lpStr1[len1] != 0) ++len1; - len2 = 0; - while (lpStr2[len2] != 0) ++len2; - if (len2 == 0) - return ((LPWSTR)(lpStr1 + len1)); - first = tolowerW (*lpStr2); - while (len1 >= len2) { - if (tolowerW (*lpStr1) == first) { - for (i = 1; i < len2; ++i) - if (tolowerW (lpStr1[i]) != tolowerW(lpStr2[i])) - break; - if (i >= len2) - return ((LPWSTR)lpStr1); - } - ++lpStr1; --len1; - } - return (NULL); -} - -/************************************************************************** - * StrToIntW [COMCTL32.365] Converts a wide char string to a signed integer. - */ - -INT WINAPI StrToIntW (LPWSTR lpString) -{ - return atoiW(lpString); -} /************************************************************************** @@ -2559,176 +2537,3 @@ DSA_DestroyCallback (HDSA hdsa, PFNDSAENUMCALLBACK enumProc, LPVOID lParam) DSA_EnumCallback (hdsa, enumProc, lParam); DSA_Destroy (hdsa); } - -/************************************************************************** - * StrCSpnA [COMCTL32.356] - * - */ -INT WINAPI StrCSpnA( LPCSTR lpStr, LPCSTR lpSet) -{ - return strcspn(lpStr, lpSet); -} - -/************************************************************************** - * StrChrW [COMCTL32.358] - * - */ -LPWSTR WINAPI StrChrW( LPCWSTR lpStart, WORD wMatch) -{ - return strchrW(lpStart, wMatch); -} - -/************************************************************************** - * StrCmpNA [COMCTL32.352] - * - */ -INT WINAPI StrCmpNA( LPCSTR lpStr1, LPCSTR lpStr2, int nChar) -{ - return strncmp(lpStr1, lpStr2, nChar); -} - -/************************************************************************** - * StrCmpNIA [COMCTL32.353] - * - */ -INT WINAPI StrCmpNIA( LPCSTR lpStr1, LPCSTR lpStr2, int nChar) -{ - return strncasecmp(lpStr1, lpStr2, nChar); -} - -/************************************************************************** - * StrCmpNW [COMCTL32.360] - * - */ -INT WINAPI StrCmpNW( LPCWSTR lpStr1, LPCWSTR lpStr2, int nChar) -{ - return strncmpW(lpStr1, lpStr2, nChar); -} - -/************************************************************************** - * StrCmpNIW [COMCTL32.361] - * - */ -INT WINAPI StrCmpNIW( LPCWSTR lpStr1, LPCWSTR lpStr2, int nChar) -{ - FIXME("(%s, %s, %i): stub\n", debugstr_w(lpStr1), debugstr_w(lpStr2), nChar); - return 0; -} - -/************************************************************************** - * StrRChrA [COMCTL32.351] - * - */ -LPSTR WINAPI StrRChrA( LPCSTR lpStart, LPCSTR lpEnd, WORD wMatch ) -{ - LPCSTR lpGotIt = NULL; - BOOL dbcs = IsDBCSLeadByte( LOBYTE(wMatch) ); - - TRACE("(%p, %p, %x)\n", lpStart, lpEnd, wMatch); - - if (!lpEnd) lpEnd = lpStart + strlen(lpStart); - - for(; lpStart < lpEnd; lpStart = CharNextA(lpStart)) - { - if (*lpStart != LOBYTE(wMatch)) continue; - if (dbcs && lpStart[1] != HIBYTE(wMatch)) continue; - lpGotIt = lpStart; - } - return (LPSTR)lpGotIt; -} - - -/************************************************************************** - * StrRChrW [COMCTL32.359] - * - */ -LPWSTR WINAPI StrRChrW( LPCWSTR lpStart, LPCWSTR lpEnd, WORD wMatch) -{ - LPCWSTR lpGotIt = NULL; - - TRACE("(%p, %p, %x)\n", lpStart, lpEnd, wMatch); - if (!lpEnd) lpEnd = lpStart + strlenW(lpStart); - - for(; lpStart < lpEnd; lpStart = CharNextW(lpStart)) - if (*lpStart == wMatch) lpGotIt = lpStart; - - return (LPWSTR)lpGotIt; -} - - -/************************************************************************** - * StrStrA [COMCTL32.354] - * - */ -LPSTR WINAPI StrStrA( LPCSTR lpFirst, LPCSTR lpSrch) -{ - return strstr(lpFirst, lpSrch); -} - -/************************************************************************** - * StrStrW [COMCTL32.362] - * - */ -LPWSTR WINAPI StrStrW( LPCWSTR lpFirst, LPCWSTR lpSrch) -{ - return strstrW(lpFirst, lpSrch); -} - -/************************************************************************** - * StrSpnW [COMCTL32.364] - * - */ -INT WINAPI StrSpnW( LPWSTR lpStr, LPWSTR lpSet) -{ - LPWSTR lpLoop = lpStr; - - /* validate ptr */ - if ((lpStr == 0) || (lpSet == 0)) return 0; - -/* while(*lpLoop) { if lpLoop++; } */ - - for(; (*lpLoop != 0); lpLoop++) - if( strchrW(lpSet, *(WORD*)lpLoop)) - return (INT)(lpLoop-lpStr); - - return (INT)(lpLoop-lpStr); -} - -/************************************************************************** - * @ [COMCTL32.415] - * - * FIXME: What's this supposed to do? - * Parameter 1 is an HWND, you're on your own for the rest. - */ - -BOOL WINAPI DrawTextWrap( HWND hwnd, DWORD b, DWORD c, DWORD d, DWORD e) -{ - - FIXME("(%p, %lx, %lx, %lx, %lx): stub!\n", hwnd, b, c, d, e); - - return TRUE; -} - -/************************************************************************** - * @ [COMCTL32.417] - * - */ -BOOL WINAPI ExtTextOutWrap(HDC hdc, INT x, INT y, UINT flags, const RECT *lprect, - LPCWSTR str, UINT count, const INT *lpDx) -{ - return ExtTextOutW(hdc, x, y, flags, lprect, str, count, lpDx); -} - -/************************************************************************** - * @ [COMCTL32.419] - * - * FIXME: What's this supposed to do? - */ - -BOOL WINAPI GetTextExtentPointWrap( DWORD a, DWORD b, DWORD c, DWORD d) -{ - - FIXME("(%lx, %lx, %lx, %lx): stub!\n", a, b, c, d); - - return TRUE; -} diff --git a/reactos/lib/comctl32/commctrl.c b/reactos/lib/comctl32/commctrl.c index a4e20417ee7..0d66491ce2b 100644 --- a/reactos/lib/comctl32/commctrl.c +++ b/reactos/lib/comctl32/commctrl.c @@ -131,7 +131,9 @@ static const WORD wPattern55AA[] = /*********************************************************************** - * DllMain [Internal] Initializes the internal 'COMCTL32.DLL'. + * DllMain [Internal] + * + * Initializes the internal 'COMCTL32.DLL'. * * PARAMS * hinstDLL [I] handle to the 'dlls' instance @@ -223,6 +225,9 @@ BOOL WINAPI DllMain(HINSTANCE hinstDLL, DWORD fdwReason, LPVOID lpvReserved) /*********************************************************************** * MenuHelp [COMCTL32.2] * + * Handles the setting of status bar help messages when the user + * selects menu items. + * * PARAMS * uMsg [I] message (WM_MENUSELECT) (see NOTES) * wParam [I] wParam of the message uMsg @@ -378,6 +383,8 @@ ShowHideMenuCtl (HWND hwnd, UINT uFlags, LPINT lpInfo) /*********************************************************************** * GetEffectiveClientRect [COMCTL32.4] * + * Calculates the coordinates of a rectangle in the client area. + * * PARAMS * hwnd [I] handle to the client window. * lpRect [O] pointer to the rectangle of the client window @@ -536,7 +543,9 @@ CreateStatusWindowA (LONG style, LPCSTR text, HWND parent, UINT wid) /*********************************************************************** - * CreateStatusWindowW [COMCTL32.@] Creates a status bar control + * CreateStatusWindowW [COMCTL32.@] + * + * Creates a status bar control * * PARAMS * style [I] window style @@ -560,7 +569,9 @@ CreateStatusWindowW (LONG style, LPCWSTR text, HWND parent, UINT wid) /*********************************************************************** - * CreateUpDownControl [COMCTL32.16] Creates an up-down control + * CreateUpDownControl [COMCTL32.16] + * + * Creates an up-down control * * PARAMS * style [I] window styles @@ -711,7 +722,9 @@ InitCommonControlsEx (LPINITCOMMONCONTROLSEX lpInitCtrls) /*********************************************************************** - * CreateToolbarEx [COMCTL32.@] Creates a tool bar window + * CreateToolbarEx [COMCTL32.@] + * + * Creates a toolbar window. * * PARAMS * hwnd @@ -794,12 +807,14 @@ CreateToolbarEx (HWND hwnd, DWORD style, UINT wID, INT nBitmaps, /*********************************************************************** * CreateMappedBitmap [COMCTL32.8] * + * Loads a bitmap resource using a colour map. + * * PARAMS - * hInstance [I] - * idBitmap [I] - * wFlags [I] - * lpColorMap [I] - * iNumMaps [I] + * hInstance [I] Handle to the module containing the bitmap. + * idBitmap [I] The bitmap resource ID. + * wFlags [I] CMB_MASKED for using bitmap as a mask or 0 for normal. + * lpColorMap [I] Colour information needed for the bitmap or NULL (uses system colours). + * iNumMaps [I] Number of COLORMAP's pointed to by lpColorMap. * * RETURNS * Success: handle to the new bitmap @@ -900,7 +915,9 @@ CreateMappedBitmap (HINSTANCE hInstance, INT idBitmap, UINT wFlags, /*********************************************************************** - * CreateToolbar [COMCTL32.7] Creates a tool bar control + * CreateToolbar [COMCTL32.7] + * + * Creates a toolbar control. * * PARAMS * hwnd @@ -969,6 +986,12 @@ COMCTL32_DllGetVersion (DLLVERSIONINFO *pdvi) /*********************************************************************** * DllInstall (COMCTL32.@) + * + * Installs the ComCtl32 DLL. + * + * RETURNS + * Success: S_OK + * Failure: A HRESULT error */ HRESULT WINAPI COMCTL32_DllInstall(BOOL bInstall, LPCWSTR cmdline) { @@ -1011,9 +1034,10 @@ _TrackMouseEvent (TRACKMOUSEEVENT *ptme) /************************************************************************* * GetMUILanguage [COMCTL32.@] * - * FIXME: "Returns the language currently in use by the common controls - * for a particular process." (MSDN) + * Returns the user interface language in use by the current process. * + * RETURNS + * Language ID in use by the current process. */ LANGID WINAPI GetMUILanguage (VOID) { @@ -1024,11 +1048,11 @@ LANGID WINAPI GetMUILanguage (VOID) /************************************************************************* * InitMUILanguage [COMCTL32.@] * - * FIXME: "Enables an application to specify a language to be used with - * the common controls that is different than the system language." (MSDN) + * Sets the user interface language to be used by the current process. * + * RETURNS + * Nothing. */ - VOID WINAPI InitMUILanguage (LANGID uiLang) { COMCTL32_uiLang = uiLang; diff --git a/reactos/lib/comctl32/draglist.c b/reactos/lib/comctl32/draglist.c index cb896f4a938..939a27798c5 100644 --- a/reactos/lib/comctl32/draglist.c +++ b/reactos/lib/comctl32/draglist.c @@ -2,6 +2,7 @@ * Drag List control * * Copyright 1999 Eric Kohl + * Copyright 2004 Robert Shearman * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public @@ -17,13 +18,6 @@ * 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 - * This is just a dummy control. An author is needed! Any volunteers? - * I will only improve this control once in a while. - * Eric - * - * TODO: - * - Everything. */ #include @@ -33,37 +27,265 @@ #include "wingdi.h" #include "winuser.h" #include "winnls.h" +#include "winnt.h" #include "commctrl.h" +#include "comctl32.h" #include "wine/debug.h" WINE_DEFAULT_DEBUG_CHANNEL(commctrl); +#ifndef TEXT +# define TEXT(string) string +#endif +#define DRAGLIST_SUBCLASSID 0 +#define DRAGLIST_SCROLLPERIOD 200 +#define DRAGLIST_TIMERID 666 + +/* properties relating to IDI_DRAGICON */ +#define DRAGICON_HOTSPOT_X 17 +#define DRAGICON_HOTSPOT_Y 7 +#define DRAGICON_HEIGHT 32 + +/* internal Wine specific data for the drag list control */ +typedef struct _DRAGLISTDATA +{ + /* are we currently in dragging mode? */ + BOOL dragging; + + /* cursor to use as determined by DL_DRAGGING notification. + * NOTE: as we use LoadCursor we don't have to use DeleteCursor + * when we are finished with it */ + HCURSOR cursor; + + /* optimisation so that we don't have to load the cursor + * all of the time whilst dragging */ + LRESULT last_dragging_response; + /* prevents flicker with drawing drag arrow */ + RECT last_drag_icon_rect; +} DRAGLISTDATA; + +static UINT uDragListMessage = 0; /* registered window message code */ static DWORD dwLastScrollTime = 0; +static HICON hDragArrow = NULL; + +/*********************************************************************** + * DragList_Notify (internal) + * + * Sends notification messages to the parent control. Note that it + * does not use WM_NOTIFY like the rest of the controls, but a registered + * window message. + */ +static LRESULT DragList_Notify(HWND hwndLB, UINT uNotification) +{ + DRAGLISTINFO dli; + dli.hWnd = hwndLB; + dli.uNotification = uNotification; + GetCursorPos(&dli.ptCursor); + return SendMessageW(GetParent(hwndLB), uDragListMessage, GetDlgCtrlID(hwndLB), (LPARAM)&dli); +} + +/* cleans up after dragging */ +static inline void DragList_EndDrag(HWND hwnd, DRAGLISTDATA * data) +{ + KillTimer(hwnd, DRAGLIST_TIMERID); + ReleaseCapture(); + data->dragging = FALSE; + /* clear any drag insert icon present */ + InvalidateRect(GetParent(hwnd), &data->last_drag_icon_rect, TRUE); +} + +/*********************************************************************** + * DragList_SubclassWindowProc (internal) + * + * Handles certain messages to enable dragging for the ListBox and forwards + * the rest to the ListBox. + */ +static LRESULT CALLBACK +DragList_SubclassWindowProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam, UINT_PTR uIdSubclass, DWORD_PTR dwRefData) +{ + DRAGLISTDATA * data = (DRAGLISTDATA*)dwRefData; + switch (uMsg) + { + case WM_LBUTTONDOWN: + SetFocus(hwnd); + data->cursor = NULL; + SetRectEmpty(&data->last_drag_icon_rect); + data->dragging = DragList_Notify(hwnd, DL_BEGINDRAG); + if (data->dragging) + { + SetCapture(hwnd); + SetTimer(hwnd, DRAGLIST_TIMERID, DRAGLIST_SCROLLPERIOD, NULL); + } + /* note that we don't absorb this message to let the list box + * do its thing (normally selecting an item) */ + break; + + case WM_KEYDOWN: + case WM_RBUTTONDOWN: + /* user cancelled drag by either right clicking or + * by pressing the escape key */ + if ((data->dragging) && + ((uMsg == WM_RBUTTONDOWN) || (wParam == VK_ESCAPE))) + { + /* clean up and absorb message */ + DragList_EndDrag(hwnd, data); + DragList_Notify(hwnd, DL_CANCELDRAG); + return 0; + } + break; + + case WM_MOUSEMOVE: + case WM_TIMER: + if (data->dragging) + { + LRESULT cursor = DragList_Notify(hwnd, DL_DRAGGING); + /* optimisation so that we don't have to load the cursor + * all of the time whilst dragging */ + if (data->last_dragging_response != cursor) + { + switch (cursor) + { + case DL_STOPCURSOR: + data->cursor = LoadCursorW(NULL, (LPCWSTR)IDC_NO); + SetCursor(data->cursor); + break; + case DL_COPYCURSOR: + data->cursor = LoadCursorW(COMCTL32_hModule, (LPCWSTR)IDC_COPY); + SetCursor(data->cursor); + break; + case DL_MOVECURSOR: + data->cursor = LoadCursorW(NULL, (LPCWSTR)IDC_ARROW); + SetCursor(data->cursor); + break; + } + data->last_dragging_response = cursor; + } + /* don't pass this message on to List Box */ + return 0; + } + break; + + case WM_LBUTTONUP: + if (data->dragging) + { + DragList_EndDrag(hwnd, data); + DragList_Notify(hwnd, DL_DROPPED); + } + break; + + case WM_SETCURSOR: + /* if app has told us to set a cursor then do so */ + if (data->dragging && data->cursor) + { + SetCursor(data->cursor); + return TRUE; + } + break; + + case WM_GETDLGCODE: + /* tell dialog boxes that we want to receive WM_KEYDOWN events + * for keys like VK_ESCAPE */ + if (data->dragging) + return DLGC_WANTALLKEYS; + break; + case WM_NCDESTROY: + RemoveWindowSubclass(hwnd, DragList_SubclassWindowProc, DRAGLIST_SUBCLASSID); + Free(data); + break; + } + return DefSubclassProc(hwnd, uMsg, wParam, lParam); +} /*********************************************************************** * MakeDragList (COMCTL32.13) + * + * Makes a normal ListBox into a DragList by subclassing it. + * + * RETURNS + * Success: Non-zero + * Failure: Zero */ BOOL WINAPI MakeDragList (HWND hwndLB) { - FIXME("(%p)\n", hwndLB); + DRAGLISTDATA * data = Alloc(sizeof(DRAGLISTDATA)); + TRACE("(%p)\n", hwndLB); - return FALSE; + if (!uDragListMessage) + uDragListMessage = RegisterWindowMessageA(DRAGLISTMSGSTRING); + + return SetWindowSubclass(hwndLB, DragList_SubclassWindowProc, DRAGLIST_SUBCLASSID, (DWORD_PTR)data); } /*********************************************************************** * DrawInsert (COMCTL32.15) + * + * Draws insert arrow by the side of the ListBox item in the parent window. + * + * RETURNS + * Nothing. */ VOID WINAPI DrawInsert (HWND hwndParent, HWND hwndLB, INT nItem) { - FIXME("(%p %p %d)\n", hwndParent, hwndLB, nItem); + RECT rcItem, rcListBox, rcDragIcon; + HDC hdc; + DRAGLISTDATA * data; + TRACE("(%p %p %d)\n", hwndParent, hwndLB, nItem); + if (!hDragArrow) + hDragArrow = LoadIconW(COMCTL32_hModule, (LPCWSTR)IDI_DRAGARROW); + + if (LB_ERR == SendMessageW(hwndLB, LB_GETITEMRECT, nItem, (LPARAM)&rcItem)) + return; + + if (!GetWindowRect(hwndLB, &rcListBox)) + return; + + /* convert item rect to parent co-ordinates */ + if (!MapWindowPoints(hwndLB, hwndParent, (LPPOINT)&rcItem, 2)) + return; + + /* convert list box rect to parent co-ordinates */ + if (!MapWindowPoints(HWND_DESKTOP, hwndParent, (LPPOINT)&rcListBox, 2)) + return; + + rcDragIcon.left = rcListBox.left - DRAGICON_HOTSPOT_X; + rcDragIcon.top = rcItem.top - DRAGICON_HOTSPOT_Y; + rcDragIcon.right = rcListBox.left; + rcDragIcon.bottom = rcDragIcon.top + DRAGICON_HEIGHT; + + if (!GetWindowSubclass(hwndLB, DragList_SubclassWindowProc, DRAGLIST_SUBCLASSID, (DWORD_PTR*)&data)) + return; + + /* prevent flicker by only redrawing when necessary */ + if (!EqualRect(&rcDragIcon, &data->last_drag_icon_rect)) + { + /* get rid of any previous inserts drawn */ + RedrawWindow(hwndParent, &data->last_drag_icon_rect, NULL, + RDW_INTERNALPAINT | RDW_ERASE | RDW_INVALIDATE | RDW_UPDATENOW); + + if (nItem >= 0) + { + hdc = GetDC(hwndParent); + + DrawIcon(hdc, rcDragIcon.left, rcDragIcon.top, hDragArrow); + + ReleaseDC(hwndParent, hdc); + } + } + CopyRect(&data->last_drag_icon_rect, &rcDragIcon); } /*********************************************************************** * LBItemFromPt (COMCTL32.14) + * + * Gets the index of the ListBox item under the specified point, + * scrolling if bAutoScroll is TRUE and pt is outside of the ListBox. + * + * RETURNS + * The ListBox item ID if pt is over a list item or -1 otherwise. */ INT WINAPI LBItemFromPt (HWND hwndLB, POINT pt, BOOL bAutoScroll) { @@ -71,8 +293,8 @@ INT WINAPI LBItemFromPt (HWND hwndLB, POINT pt, BOOL bAutoScroll) INT nIndex; DWORD dwScrollTime; - FIXME("(%p %ld x %ld %s)\n", - hwndLB, pt.x, pt.y, bAutoScroll ? "TRUE" : "FALSE"); + TRACE("(%p %ld x %ld %s)\n", + hwndLB, pt.x, pt.y, bAutoScroll ? "TRUE" : "FALSE"); ScreenToClient (hwndLB, &pt); GetClientRect (hwndLB, &rcClient); @@ -80,54 +302,41 @@ INT WINAPI LBItemFromPt (HWND hwndLB, POINT pt, BOOL bAutoScroll) if (PtInRect (&rcClient, pt)) { - /* point is inside -- get the item index */ - while (TRUE) - { - if (SendMessageA (hwndLB, LB_GETITEMRECT, nIndex, (LPARAM)&rcClient) == LB_ERR) - return -1; + /* point is inside -- get the item index */ + while (TRUE) + { + if (SendMessageA (hwndLB, LB_GETITEMRECT, nIndex, (LPARAM)&rcClient) == LB_ERR) + return -1; - if (PtInRect (&rcClient, pt)) - return nIndex; + if (PtInRect (&rcClient, pt)) + return nIndex; - nIndex++; - } + nIndex++; + } } else { - /* point is outside */ - if (!bAutoScroll) - return -1; + /* point is outside */ + if (!bAutoScroll) + return -1; - if ((pt.x > rcClient.right) || (pt.x < rcClient.left)) - return -1; + if ((pt.x > rcClient.right) || (pt.x < rcClient.left)) + return -1; - if (pt.y < 0) - nIndex--; - else - nIndex++; + if (pt.y < 0) + nIndex--; + else + nIndex++; - dwScrollTime = GetTickCount (); + dwScrollTime = GetTickCount (); - if ((dwScrollTime - dwLastScrollTime) < 200) - return -1; + if ((dwScrollTime - dwLastScrollTime) < DRAGLIST_SCROLLPERIOD) + return -1; - dwLastScrollTime = dwScrollTime; + dwLastScrollTime = dwScrollTime; - SendMessageA (hwndLB, LB_SETTOPINDEX, (WPARAM)nIndex, 0); + SendMessageA (hwndLB, LB_SETTOPINDEX, (WPARAM)nIndex, 0); } return -1; } - - -#if 0 -static LRESULT CALLBACK -DRAGLIST_WindowProc (HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam) -{ - - return FALSE; -} -#endif - - - diff --git a/reactos/lib/comctl32/flatsb.c b/reactos/lib/comctl32/flatsb.c index b13618fd2dc..0c69a326bbe 100644 --- a/reactos/lib/comctl32/flatsb.c +++ b/reactos/lib/comctl32/flatsb.c @@ -53,8 +53,15 @@ typedef struct /*********************************************************************** * InitializeFlatSB (COMCTL32.@) * - * returns nonzero if successful, zero otherwise + * Initializes flat scroll bars for the specified window. * + * RETURNS + * Success: Non-zero + * Failure: Zero + * + * NOTES + * Subclasses specified window so that flat scroll bars may be drawn + * and used. */ BOOL WINAPI InitializeFlatSB(HWND hwnd) { @@ -65,11 +72,16 @@ BOOL WINAPI InitializeFlatSB(HWND hwnd) /*********************************************************************** * UninitializeFlatSB (COMCTL32.@) * - * returns: + * Uninitializes flat scroll bars for the specified window. + * + * RETURNS * E_FAIL if one of the scroll bars is currently in use - * S_FALSE if InitializeFlatSB was never called on this hwnd + * S_FALSE if InitializeFlatSB() was never called on this hwnd * S_OK otherwise * + * NOTES + * Removes any subclassing on the specified window so that regular + * scroll bars are drawn and used. */ HRESULT WINAPI UninitializeFlatSB(HWND hwnd) { @@ -80,10 +92,12 @@ HRESULT WINAPI UninitializeFlatSB(HWND hwnd) /*********************************************************************** * FlatSB_GetScrollProp (COMCTL32.@) * - * Returns nonzero if successful, or zero otherwise. If index is WSB_PROP_HSTYLE, - * the return is nonzero if InitializeFlatSB has been called for this window, or - * zero otherwise. + * Retrieves flat-scroll-bar-specific properties for the specified window. * + * RETURNS + * nonzero if successful, or zero otherwise. If index is WSB_PROP_HSTYLE, + * the return is nonzero if InitializeFlatSB has been called for this window, or + * zero otherwise. */ BOOL WINAPI FlatSB_GetScrollProp(HWND hwnd, INT propIndex, LPINT prop) @@ -94,6 +108,12 @@ FlatSB_GetScrollProp(HWND hwnd, INT propIndex, LPINT prop) /*********************************************************************** * FlatSB_SetScrollProp (COMCTL32.@) + * + * Sets flat-scroll-bar-specific properties for the specified window. + * + * RETURNS + * Success: Non-zero + * Failure: Zero */ BOOL WINAPI FlatSB_SetScrollProp(HWND hwnd, UINT index, INT newValue, BOOL flag) @@ -120,6 +140,8 @@ FlatSB_SetScrollProp(HWND hwnd, UINT index, INT newValue, BOOL flag) /*********************************************************************** * FlatSB_EnableScrollBar (COMCTL32.@) + * + * See EnableScrollBar. */ BOOL WINAPI FlatSB_EnableScrollBar(HWND hwnd, int nBar, UINT flags) @@ -129,6 +151,8 @@ FlatSB_EnableScrollBar(HWND hwnd, int nBar, UINT flags) /*********************************************************************** * FlatSB_ShowScrollBar (COMCTL32.@) + * + * See ShowScrollBar. */ BOOL WINAPI FlatSB_ShowScrollBar(HWND hwnd, int nBar, BOOL fShow) @@ -138,6 +162,8 @@ FlatSB_ShowScrollBar(HWND hwnd, int nBar, BOOL fShow) /*********************************************************************** * FlatSB_GetScrollRange (COMCTL32.@) + * + * See GetScrollRange. */ BOOL WINAPI FlatSB_GetScrollRange(HWND hwnd, int nBar, LPINT min, LPINT max) @@ -147,6 +173,8 @@ FlatSB_GetScrollRange(HWND hwnd, int nBar, LPINT min, LPINT max) /*********************************************************************** * FlatSB_GetScrollInfo (COMCTL32.@) + * + * See GetScrollInfo. */ BOOL WINAPI FlatSB_GetScrollInfo(HWND hwnd, int nBar, LPSCROLLINFO info) @@ -156,6 +184,8 @@ FlatSB_GetScrollInfo(HWND hwnd, int nBar, LPSCROLLINFO info) /*********************************************************************** * FlatSB_GetScrollPos (COMCTL32.@) + * + * See GetScrollPos. */ INT WINAPI FlatSB_GetScrollPos(HWND hwnd, int nBar) @@ -165,6 +195,8 @@ FlatSB_GetScrollPos(HWND hwnd, int nBar) /*********************************************************************** * FlatSB_SetScrollPos (COMCTL32.@) + * + * See SetScrollPos. */ INT WINAPI FlatSB_SetScrollPos(HWND hwnd, int nBar, INT pos, BOOL bRedraw) @@ -174,6 +206,8 @@ FlatSB_SetScrollPos(HWND hwnd, int nBar, INT pos, BOOL bRedraw) /*********************************************************************** * FlatSB_SetScrollInfo (COMCTL32.@) + * + * See SetScrollInfo. */ INT WINAPI FlatSB_SetScrollInfo(HWND hwnd, int nBar, LPSCROLLINFO info, BOOL bRedraw) @@ -183,6 +217,8 @@ FlatSB_SetScrollInfo(HWND hwnd, int nBar, LPSCROLLINFO info, BOOL bRedraw) /*********************************************************************** * FlatSB_SetScrollRange (COMCTL32.@) + * + * See SetScrollRange. */ INT WINAPI FlatSB_SetScrollRange(HWND hwnd, int nBar, INT min, INT max, BOOL bRedraw) diff --git a/reactos/lib/comctl32/imagelist.c b/reactos/lib/comctl32/imagelist.c index dbcfb07eaf2..bf81080837a 100644 --- a/reactos/lib/comctl32/imagelist.c +++ b/reactos/lib/comctl32/imagelist.c @@ -33,6 +33,7 @@ * TODO: * - Add support for ILD_PRESERVEALPHA, ILD_SCALE, ILD_DPISCALE * - Add support for ILS_GLOW, ILS_SHADOW, ILS_SATURATE, ILS_ALPHA + * - Thread-safe locking * * FIXME: * - Hotspot handling still not correct. The Hotspot passed to BeginDrag @@ -80,6 +81,7 @@ typedef struct static INTERNALDRAG InternalDrag = { 0, 0, 0, 0, 0, 0, FALSE, 0, FALSE }; +static HBITMAP ImageList_CreateImage(HDC hdc, HIMAGELIST himl, UINT width, UINT height); static inline BOOL is_valid(HIMAGELIST himl) { @@ -120,31 +122,36 @@ IMAGELIST_InternalExpandBitmaps (HIMAGELIST himl, INT nImageCount, INT cx, INT c TRACE("Create expanded bitmaps : himl=%p x=%d y=%d count=%d\n", himl, nNewWidth, cy, nNewCount); hdcBitmap = CreateCompatibleDC (0); - hbmNewBitmap = - CreateBitmap (nNewWidth, cy, 1, himl->uBitsPixel, NULL); + hbmNewBitmap = ImageList_CreateImage(hdcBitmap, himl, nNewWidth, cy); + if (hbmNewBitmap == 0) ERR("creating new image bitmap (x=%d y=%d)!\n", nNewWidth, cy); - hbmNull = SelectObject (hdcBitmap, hbmNewBitmap); - BitBlt (hdcBitmap, 0, 0, himl->cCurImage * himl->cx, cy, - himl->hdcImage, 0, 0, SRCCOPY); - - SelectObject (hdcBitmap, hbmNull); + if(himl->cCurImage) + { + hbmNull = SelectObject (hdcBitmap, hbmNewBitmap); + BitBlt (hdcBitmap, 0, 0, himl->cCurImage * himl->cx, cy, + himl->hdcImage, 0, 0, SRCCOPY); + SelectObject (hdcBitmap, hbmNull); + } SelectObject (himl->hdcImage, hbmNewBitmap); DeleteObject (himl->hbmImage); himl->hbmImage = hbmNewBitmap; - if (himl->hbmMask) { - hbmNewBitmap = - CreateBitmap (nNewWidth, cy, 1, 1, NULL); + if (himl->flags & ILC_MASK) + { + hbmNewBitmap = CreateBitmap (nNewWidth, cy, 1, 1, NULL); if (hbmNewBitmap == 0) ERR("creating new mask bitmap!\n"); - SelectObject (hdcBitmap, hbmNewBitmap); - BitBlt (hdcBitmap, 0, 0, himl->cCurImage * himl->cx, cy, - himl->hdcMask, 0, 0, SRCCOPY); - SelectObject (hdcBitmap, hbmNull); + if(himl->cCurImage) + { + hbmNull = SelectObject (hdcBitmap, hbmNewBitmap); + BitBlt (hdcBitmap, 0, 0, himl->cCurImage * himl->cx, cy, + himl->hdcMask, 0, 0, SRCCOPY); + SelectObject (hdcBitmap, hbmNull); + } SelectObject (himl->hdcMask, hbmNewBitmap); DeleteObject (himl->hbmMask); himl->hbmMask = hbmNewBitmap; @@ -524,7 +531,9 @@ ImageList_Copy (HIMAGELIST himlDst, INT iDst, HIMAGELIST himlSrc, /************************************************************************* - * ImageList_Create [COMCTL32.@] Creates a new image list. + * ImageList_Create [COMCTL32.@] + * + * Creates a new image list. * * PARAMS * cx [I] image height @@ -537,7 +546,6 @@ ImageList_Copy (HIMAGELIST himlDst, INT iDst, HIMAGELIST himlSrc, * Success: Handle to the created image list * Failure: NULL */ - HIMAGELIST WINAPI ImageList_Create (INT cx, INT cy, UINT flags, INT cInitial, INT cGrow) @@ -545,6 +553,7 @@ ImageList_Create (INT cx, INT cy, UINT flags, HIMAGELIST himl; INT nCount; HBITMAP hbmTemp; + UINT ilc = (flags & 0xFE); static WORD aBitBlend25[] = {0xAA, 0x00, 0x55, 0x00, 0xAA, 0x00, 0x55, 0x00}; @@ -583,22 +592,22 @@ ImageList_Create (INT cx, INT cy, UINT flags, goto cleanup; } - himl->uBitsPixel = (UINT)GetDeviceCaps (himl->hdcImage, BITSPIXEL); + /* Default to ILC_COLOR4 if non of the ILC_COLOR* flags are specified */ + if (ilc == ILC_COLOR) + ilc = ILC_COLOR4; - TRACE("Image: %d Bits per Pixel\n", himl->uBitsPixel); + if (ilc >= ILC_COLOR4 && ilc <= ILC_COLOR32) + himl->uBitsPixel = ilc; + else + himl->uBitsPixel = (UINT)GetDeviceCaps (himl->hdcImage, BITSPIXEL); if (himl->cMaxImage > 0) { - himl->hbmImage = - CreateBitmap (himl->cx * himl->cMaxImage, himl->cy, - 1, himl->uBitsPixel, NULL); - if (himl->hbmImage == 0) { - ERR("Error creating image bitmap!\n"); - goto cleanup; - } - SelectObject(himl->hdcImage, himl->hbmImage); - } + himl->hbmImage = ImageList_CreateImage(himl->hdcImage, himl, cx * himl->cMaxImage, cy); + SelectObject(himl->hdcImage, himl->hbmImage); + } else + himl->hbmImage = 0; - if (himl->flags & ILC_MASK) { + if ((himl->cMaxImage > 0) && (himl->flags & ILC_MASK)) { himl->hbmMask = CreateBitmap (himl->cx * himl->cMaxImage, himl->cy, 1, 1, NULL); @@ -953,7 +962,9 @@ ImageList_DragShowNolock (BOOL bShow) /************************************************************************* - * ImageList_Draw [COMCTL32.@] Draws an image. + * ImageList_Draw [COMCTL32.@] + * + * Draws an image. * * PARAMS * himl [I] handle to image list @@ -1034,7 +1045,7 @@ ImageList_DrawEx (HIMAGELIST himl, INT i, HDC hdc, INT x, INT y, /************************************************************************* * ImageList_DrawIndirect [COMCTL32.@] * - * Draws an image using ... + * Draws an image using various parameters specified in pimldp. * * PARAMS * pimldp [I] pointer to IMAGELISTDRAWPARAMS structure. @@ -1071,8 +1082,8 @@ ImageList_DrawIndirect (IMAGELISTDRAWPARAMS *pimldp) bIsTransparent = (fStyle & ILD_TRANSPARENT) || clrBk == CLR_NONE; bBlend = fStyle & (ILD_BLEND25 | ILD_BLEND50); - TRACE("hbmMask(%p) iImage(%d) x(%d) y(%d) cx(%d) cy(%d)\n", - himl->hbmMask, pimldp->i, pimldp->x, pimldp->y, cx, cy); + TRACE("himl(0x%lx) hbmMask(%p) iImage(%d) x(%d) y(%d) cx(%d) cy(%d)\n", + (DWORD)himl, himl->hbmMask, pimldp->i, pimldp->x, pimldp->y, cx, cy); /* we will use these DCs to access the images and masks in the ImageList */ hImageListDC = himl->hdcImage; @@ -1200,7 +1211,9 @@ cleanup: /************************************************************************* - * ImageList_Duplicate [COMCTL32.@] Duplicates an image list. + * ImageList_Duplicate [COMCTL32.@] + * + * Duplicates an image list. * * PARAMS * himlSrc [I] source image list handle @@ -1240,7 +1253,7 @@ ImageList_Duplicate (HIMAGELIST himlSrc) /************************************************************************* - * ImageList_EndDrag [COMCTL32.@] Finishes a drag operation. + * ImageList_EndDrag [COMCTL32.@] * * Finishes a drag operation. * @@ -1326,6 +1339,14 @@ ImageList_GetDragImage (POINT *ppt, POINT *pptHotspot) /************************************************************************* * ImageList_GetFlags [COMCTL32.@] * + * Gets the flags of the specified image list. + * + * PARAMS + * himl [I] Handle to image list + * + * RETURNS + * Image list flags. + * * BUGS * Stub. */ @@ -2012,7 +2033,9 @@ HIMAGELIST WINAPI ImageList_Read (LPSTREAM pstm) /************************************************************************* - * ImageList_Remove [COMCTL32.@] Removes an image from an image list + * ImageList_Remove [COMCTL32.@] + * + * Removes an image from an image list * * PARAMS * himl [I] image list handle @@ -2055,8 +2078,7 @@ ImageList_Remove (HIMAGELIST himl, INT i) for (nCount = 0; nCount < MAX_OVERLAYIMAGE; nCount++) himl->nOvlIdx[nCount] = -1; - hbmNewImage = CreateBitmap (himl->cMaxImage * himl->cx, himl->cy, - 1, himl->uBitsPixel, NULL); + hbmNewImage = ImageList_CreateImage(himl->hdcImage, himl, himl->cMaxImage * himl->cx, himl->cy); SelectObject (himl->hdcImage, hbmNewImage); DeleteObject (himl->hbmImage); himl->hbmImage = hbmNewImage; @@ -2074,15 +2096,15 @@ ImageList_Remove (HIMAGELIST himl, INT i) TRACE("Remove single image! %d\n", i); /* create new bitmap(s) */ - cxNew = (himl->cCurImage + himl->cGrow - 1) * himl->cx; + nCount = (himl->cCurImage + himl->cGrow - 1); + cxNew = nCount * himl->cx; TRACE(" - Number of images: %d / %d (Old/New)\n", himl->cCurImage, himl->cCurImage - 1); TRACE(" - Max. number of images: %d / %d (Old/New)\n", himl->cMaxImage, himl->cCurImage + himl->cGrow - 1); - hbmNewImage = - CreateBitmap (cxNew, himl->cy, 1, himl->uBitsPixel, NULL); + hbmNewImage = ImageList_CreateImage(himl->hdcImage, himl, cxNew, himl->cy); if (himl->hbmMask) hbmNewMask = CreateBitmap (cxNew, himl->cy, 1, 1, NULL); @@ -2438,6 +2460,15 @@ ImageList_SetFilter (HIMAGELIST himl, INT i, DWORD dwFilter) /************************************************************************* * ImageList_SetFlags [COMCTL32.@] * + * Sets the image list flags. + * + * PARAMS + * himl [I] Handle to image list + * flags [I] Flags to set + * + * RETURNS + * Old flags? + * * BUGS * Stub. */ @@ -2484,8 +2515,7 @@ ImageList_SetIconSize (HIMAGELIST himl, INT cx, INT cy) for (nCount = 0; nCount < MAX_OVERLAYIMAGE; nCount++) himl->nOvlIdx[nCount] = -1; - hbmNew = CreateBitmap (himl->cMaxImage * himl->cx, himl->cy, - 1, himl->uBitsPixel, NULL); + hbmNew = ImageList_CreateImage(himl->hdcImage, himl, himl->cMaxImage * himl->cx, himl->cy); SelectObject (himl->hdcImage, hbmNew); DeleteObject (himl->hbmImage); himl->hbmImage = hbmNew; @@ -2540,8 +2570,8 @@ ImageList_SetImageCount (HIMAGELIST himl, UINT iImageCount) hdcBitmap = CreateCompatibleDC (0); - hbmNewBitmap = CreateBitmap (nNewCount * himl->cx, himl->cy, - 1, himl->uBitsPixel, NULL); + hbmNewBitmap = ImageList_CreateImage(hdcBitmap, himl, nNewCount * himl->cx, himl->cy); + if (hbmNewBitmap != 0) { SelectObject (hdcBitmap, hbmNewBitmap); @@ -2782,3 +2812,40 @@ ImageList_Write (HIMAGELIST himl, LPSTREAM pstm) return TRUE; } + + +static HBITMAP ImageList_CreateImage(HDC hdc, HIMAGELIST himl, UINT width, UINT height) +{ + HBITMAP hbmNewBitmap; + UINT ilc = (himl->flags & 0xFE); + + if ((ilc >= ILC_COLOR4 && ilc <= ILC_COLOR32) || ilc == ILC_COLOR) + { + VOID* bits; + BITMAPINFO bmi; + + TRACE("Creating DIBSection: %d Bits per Pixel\n", himl->uBitsPixel); + + bmi.bmiHeader.biSize = sizeof(BITMAPINFOHEADER); + bmi.bmiHeader.biWidth = width; + bmi.bmiHeader.biHeight = height; + bmi.bmiHeader.biPlanes = 1; + bmi.bmiHeader.biBitCount = himl->uBitsPixel; + bmi.bmiHeader.biCompression = BI_RGB; + bmi.bmiHeader.biSizeImage = 0; + bmi.bmiHeader.biXPelsPerMeter = 0; + bmi.bmiHeader.biYPelsPerMeter = 0; + bmi.bmiHeader.biClrUsed = 0; + bmi.bmiHeader.biClrImportant = 0; + + hbmNewBitmap = CreateDIBSection(hdc, &bmi, DIB_RGB_COLORS, &bits, 0, 0); + } + else /*if (ilc == ILC_COLORDDB)*/ + { + TRACE("Creating Bitmap: %d Bits per Pixel\n", himl->uBitsPixel); + + hbmNewBitmap = CreateBitmap (width, height, 1, himl->uBitsPixel, NULL); + } + + return hbmNewBitmap; +} diff --git a/reactos/lib/comctl32/listview.c b/reactos/lib/comctl32/listview.c index 8c43634ede9..cfc92ed2e88 100644 --- a/reactos/lib/comctl32/listview.c +++ b/reactos/lib/comctl32/listview.c @@ -93,7 +93,6 @@ * -- LVS_EX_UNDERLINEHOT * * Notifications: - * -- LVN_BEGINRDRAG * -- LVN_BEGINSCROLL, LVN_ENDSCROLL * -- LVN_GETINFOTIP * -- LVN_HOTTRACK @@ -4000,7 +3999,26 @@ static DWORD LISTVIEW_ApproximateViewRect(LISTVIEW_INFO *infoPtr, INT nItemCount dwViewRect = MAKELONG(wWidth, wHeight); } else if (uView == LVS_REPORT) - FIXME("uView == LVS_REPORT: not implemented\n"); + { + RECT rcBox; + + if (infoPtr->nItemCount > 0) + { + LISTVIEW_GetItemBox(infoPtr, 0, &rcBox); + wWidth = rcBox.right - rcBox.left; + wHeight = (rcBox.bottom - rcBox.top) * nItemCount; + } + else + { + /* use current height and width */ + if (wHeight == 0xffff) + wHeight = infoPtr->rcList.bottom - infoPtr->rcList.top; + if (wWidth == 0xffff) + wWidth = infoPtr->rcList.right - infoPtr->rcList.left; + } + + dwViewRect = MAKELONG(wWidth, wHeight); + } else if (uView == LVS_SMALLICON) FIXME("uView == LVS_SMALLICON: not implemented\n"); else if (uView == LVS_ICON) @@ -4971,7 +4989,7 @@ static HIMAGELIST LISTVIEW_GetImageList(LISTVIEW_INFO *infoPtr, INT nImageList) * the buffer pointer you provided on input. Most code already does * that, so it's not a problem. * For the two cases when the text must be copied (that is, - * for LVM_GETITEM, and LVMGETITEMTEXT), use LISTVIEW_GetItemExtT. + * for LVM_GETITEM, and LVM_GETITEMTEXT), use LISTVIEW_GetItemExtT. * * RETURN: * SUCCESS : TRUE @@ -5980,7 +5998,9 @@ static INT LISTVIEW_HitTest(LISTVIEW_INFO *infoPtr, LPLVHITTESTINFO lpht, BOOL s } } - if (select && !(uView == LVS_REPORT && (infoPtr->dwLvExStyle & LVS_EX_FULLROWSELECT))) + if (select && !(uView == LVS_REPORT && + ((infoPtr->dwLvExStyle & LVS_EX_FULLROWSELECT) || + (infoPtr->dwStyle & LVS_OWNERDRAWFIXED)))) { if (uView == LVS_REPORT) { diff --git a/reactos/lib/comctl32/propsheet.c b/reactos/lib/comctl32/propsheet.c index c1b4a7c789d..edc61ec36eb 100644 --- a/reactos/lib/comctl32/propsheet.c +++ b/reactos/lib/comctl32/propsheet.c @@ -1381,7 +1381,6 @@ static BOOL PROPSHEET_CreatePage(HWND hwndParent, DLGTEMPLATE* pTemplate; HWND hwndPage; RECT rc; - PropPageInfo* ppInfo = psInfo->proppage; PADDING_INFO padding; UINT pageWidth,pageHeight; DWORD resSize; @@ -1494,7 +1493,7 @@ static BOOL PROPSHEET_CreatePage(HWND hwndParent, if(temp) Free(temp); - ppInfo[index].hwndPage = hwndPage; + psInfo->proppage[index].hwndPage = hwndPage; if (psInfo->ppshheader.dwFlags & INTRNL_ANY_WIZARD) { /* FIXME: This code may no longer be correct. @@ -2278,7 +2277,6 @@ static BOOL PROPSHEET_RemovePage(HWND hwndDlg, if (!psInfo) { return FALSE; } - oldPages = psInfo->proppage; /* * hpage takes precedence over index. */ @@ -2345,6 +2343,7 @@ static BOOL PROPSHEET_RemovePage(HWND hwndDlg, /* Remove the tab */ SendMessageW(hwndTabControl, TCM_DELETEITEM, index, 0); + oldPages = psInfo->proppage; psInfo->nPages--; psInfo->proppage = Alloc(sizeof(PropPageInfo) * psInfo->nPages); @@ -2478,6 +2477,15 @@ static void PROPSHEET_CleanUp(HWND hwndDlg) /****************************************************************************** * PropertySheet (COMCTL32.@) * PropertySheetA (COMCTL32.@) + * + * Creates a property sheet in the specified property sheet header. + * + * RETURNS + * Modal property sheets: Positive if successful or -1 otherwise. + * Modeless property sheets: Property sheet handle. + * Or: + *| ID_PSREBOOTSYSTEM - The user must reboot the computer for the changes to take effect. + *| ID_PSRESTARTWINDOWS - The user must restart Windows for the changes to take effect. */ INT WINAPI PropertySheetA(LPCPROPSHEETHEADERA lppsh) { @@ -2523,6 +2531,8 @@ INT WINAPI PropertySheetA(LPCPROPSHEETHEADERA lppsh) /****************************************************************************** * PropertySheetW (COMCTL32.@) + * + * See PropertySheetA. */ INT WINAPI PropertySheetW(LPCPROPSHEETHEADERW lppsh) { @@ -2569,6 +2579,16 @@ INT WINAPI PropertySheetW(LPCPROPSHEETHEADERW lppsh) /****************************************************************************** * CreatePropertySheetPage (COMCTL32.@) * CreatePropertySheetPageA (COMCTL32.@) + * + * Creates a new property sheet page. + * + * RETURNS + * Success: Handle to new property sheet page. + * Failure: NULL. + * + * NOTES + * An application must use the PSM_ADDPAGE message to add the new page to + * an existing property sheet. */ HPROPSHEETPAGE WINAPI CreatePropertySheetPageA( LPCPROPSHEETPAGEA lpPropSheetPage) @@ -2602,6 +2622,8 @@ HPROPSHEETPAGE WINAPI CreatePropertySheetPageA( /****************************************************************************** * CreatePropertySheetPageW (COMCTL32.@) + * + * See CreatePropertySheetA. */ HPROPSHEETPAGE WINAPI CreatePropertySheetPageW(LPCPROPSHEETPAGEW lpPropSheetPage) { @@ -2639,6 +2661,14 @@ HPROPSHEETPAGE WINAPI CreatePropertySheetPageW(LPCPROPSHEETPAGEW lpPropSheetPage /****************************************************************************** * DestroyPropertySheetPage (COMCTL32.@) + * + * Destroys a property sheet page previously created with + * CreatePropertySheetA() or CreatePropertySheetW() and frees the associated + * memory. + * + * RETURNS + * Success: TRUE + * Failure: FALSE */ BOOL WINAPI DestroyPropertySheetPage(HPROPSHEETPAGE hPropPage) { diff --git a/reactos/lib/comctl32/rebar.c b/reactos/lib/comctl32/rebar.c index d349d5d0385..04668822880 100644 --- a/reactos/lib/comctl32/rebar.c +++ b/reactos/lib/comctl32/rebar.c @@ -1497,10 +1497,7 @@ REBAR_Layout (REBAR_INFO *infoPtr, LPRECT lpRect, BOOL notify, BOOL resetclient) /* separator from previous band */ cxsep = (cntonrow == 0) ? 0 : SEP_WIDTH; - - /* Header: includes gripper, text, image */ - cx = lpBand->cxHeader; - if (lpBand->fStyle & RBBS_FIXEDSIZE) cx = lpBand->lcx; + cx = lpBand->lcx; if (infoPtr->dwStyle & CCS_VERT) dobreak = (y + cx + cxsep > adjcy); @@ -3747,6 +3744,7 @@ REBAR_ShowBand (REBAR_INFO *infoPtr, WPARAM wParam, LPARAM lParam) ShowWindow (lpBand->hwndChild, SW_HIDE); } + infoPtr->fStatus |= BAND_NEEDS_LAYOUT; REBAR_Layout (infoPtr, NULL, TRUE, FALSE); InvalidateRect(infoPtr->hwndSelf, 0, 1); diff --git a/reactos/lib/comctl32/rsrc.rc b/reactos/lib/comctl32/rsrc.rc index 0bb670fc7c5..b1c28fc5b6b 100644 --- a/reactos/lib/comctl32/rsrc.rc +++ b/reactos/lib/comctl32/rsrc.rc @@ -971,6 +971,33 @@ IDB_HIST_LARGE BITMAP LOADONCALL DISCARDABLE idb_hist_large.bmp } */ +/* BINRES idc_copy.cur */ +IDC_COPY CURSOR LOADONCALL DISCARDABLE idc_copy.cur +/* { + '00 00 02 00 01 00 20 20 00 00 00 00 00 00 30 01' + '00 00 16 00 00 00 28 00 00 00 20 00 00 00 40 00' + '00 00 01 00 01 00 00 00 00 00 00 01 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 FF FF FF 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 00 00 00 00 00 00 00 00 00 C0 00 00 00 C0' + '00 00 01 80 00 00 01 80 00 00 03 00 00 00 43 00' + '00 00 66 00 00 00 76 00 00 00 7E 00 00 00 7F C0' + '00 00 7F 80 00 00 7F 00 00 00 7E 00 00 00 7C 00' + '00 00 78 00 00 00 70 00 00 00 60 00 00 00 40 00' + '00 00 00 00 00 00 FF FF FF FF FF FF FF FF FF FF' + 'FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF' + 'FF FF FF FF FF FF FF FD FF FF FF FD FF FF FF F0' + '7F FF FF FD FF FF FF 3D FF FF FE 1F FF FF FE 1F' + 'FF FF FC 3F FF FF 7C 3F FF FF 38 7F FF FF 18 7F' + 'FF FF 00 FF FF FF 00 FF FF FF 00 0F FF FF 00 1F' + 'FF FF 00 3F FF FF 00 7F FF FF 00 FF FF FF 01 FF' + 'FF FF 03 FF FF FF 07 FF FF FF 0F FF FF FF 1F FF' + 'FF FF 3F FF FF FF' +} */ + + /* BINRES idc_divider.cur */ IDC_DIVIDER CURSOR LOADONCALL DISCARDABLE idc_divider.cur /* { diff --git a/reactos/lib/comctl32/smoothscroll.c b/reactos/lib/comctl32/smoothscroll.c index 1eb503978b8..658be6259f2 100644 --- a/reactos/lib/comctl32/smoothscroll.c +++ b/reactos/lib/comctl32/smoothscroll.c @@ -63,10 +63,14 @@ typedef struct tagSMOOTHSCROLLSTRUCT { * * Lots of magic for smooth scrolling windows. * - * Currently only scrolls ONCE. The comctl32 implementation uses GetTickCount - * and what else to do smooth scrolling. + * RETURNS + * Success: TRUE + * Failure: FALSE + * + * BUGS + * Currently only scrolls ONCE. The comctl32 implementation uses GetTickCount + * and what else to do smooth scrolling. */ - BOOL WINAPI SmoothScrollWindow( SMOOTHSCROLLSTRUCT *smooth ) { LPRECT lpupdaterect = smooth->lpupdaterect; HRGN hrgnupdate = smooth->hrgnupdate; diff --git a/reactos/lib/comctl32/string.c b/reactos/lib/comctl32/string.c new file mode 100644 index 00000000000..2eb6172f936 --- /dev/null +++ b/reactos/lib/comctl32/string.c @@ -0,0 +1,853 @@ +/* + * String manipulation functions + * + * Copyright 1998 Eric Kohl + * 1998 Juergen Schmied + * 2000 Eric Kohl for CodeWeavers + * Copyright 2002 Jon Griffiths + * + * 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 + * + */ + +#include +#include +#include /* atoi */ + +#include "windef.h" +#include "winbase.h" +#include "winuser.h" +#include "winnls.h" + +#include "wine/unicode.h" + +#include "wine/debug.h" + +WINE_DEFAULT_DEBUG_CHANNEL(commctrl); + +/************************************************************************* + * COMCTL32_ChrCmpHelperA + * + * Internal helper for ChrCmpA/COMCTL32_ChrCmpIA. + * + * NOTES + * Both this function and its Unicode counterpart are very inneficient. To + * fix this, CompareString must be completely implemented and optimised + * first. Then the core character test can be taken out of that function and + * placed here, so that it need never be called at all. Until then, do not + * attempt to optimise this code unless you are willing to test that it + * still performs correctly. + */ +static BOOL COMCTL32_ChrCmpHelperA(WORD ch1, WORD ch2, DWORD dwFlags) +{ + char str1[3], str2[3]; + + str1[0] = LOBYTE(ch1); + if (IsDBCSLeadByte(str1[0])) + { + str1[1] = HIBYTE(ch1); + str1[2] = '\0'; + } + else + str1[1] = '\0'; + + str2[0] = LOBYTE(ch2); + if (IsDBCSLeadByte(str2[0])) + { + str2[1] = HIBYTE(ch2); + str2[2] = '\0'; + } + else + str2[1] = '\0'; + + return CompareStringA(GetThreadLocale(), dwFlags, str1, -1, str2, -1) - 2; +} + +/************************************************************************* + * COMCTL32_ChrCmpHelperW + * + * Internal helper for COMCTL32_ChrCmpW/ChrCmpIW. + */ +static BOOL COMCTL32_ChrCmpHelperW(WCHAR ch1, WCHAR ch2, DWORD dwFlags) +{ + WCHAR str1[2], str2[2]; + + str1[0] = ch1; + str1[1] = '\0'; + str2[0] = ch2; + str2[1] = '\0'; + return CompareStringW(GetThreadLocale(), dwFlags, str1, 2, str2, 2) - 2; +} + +/************************************************************************* + * COMCTL32_ChrCmpA (internal) + * + * Internal helper function. + */ +static BOOL COMCTL32_ChrCmpA(WORD ch1, WORD ch2) +{ + return COMCTL32_ChrCmpHelperA(ch1, ch2, 0); +} + +/************************************************************************* + * COMCTL32_ChrCmpIA (internal) + * + * Compare two characters, ignoring case. + * + * PARAMS + * ch1 [I] First character to compare + * ch2 [I] Second character to compare + * + * RETURNS + * FALSE, if the characters are equal. + * Non-zero otherwise. + */ +static BOOL COMCTL32_ChrCmpIA(WORD ch1, WORD ch2) +{ + TRACE("(%d,%d)\n", ch1, ch2); + + return COMCTL32_ChrCmpHelperA(ch1, ch2, NORM_IGNORECASE); +} + +/************************************************************************* + * COMCTL32_ChrCmpW + * + * Internal helper function. + */ +static BOOL COMCTL32_ChrCmpW(WCHAR ch1, WCHAR ch2) +{ + return COMCTL32_ChrCmpHelperW(ch1, ch2, 0); +} + +/************************************************************************** + * StrChrA [COMCTL32.350] + * + * Find a given character in a string. + * + * PARAMS + * lpszStr [I] String to search in. + * ch [I] Character to search for. + * + * RETURNS + * Success: A pointer to the first occurrence of ch in lpszStr, or NULL if + * not found. + * Failure: NULL, if any arguments are invalid. + */ +LPSTR WINAPI StrChrA(LPCSTR lpszStr, WORD ch) +{ + TRACE("(%s,%i)\n", debugstr_a(lpszStr), ch); + + if (lpszStr) + { + while (*lpszStr) + { + if (!COMCTL32_ChrCmpA(*lpszStr, ch)) + return (LPSTR)lpszStr; + lpszStr = CharNextA(lpszStr); + } + } + return NULL; +} + +/************************************************************************* + * COMCTL32_StrStrHelperA + * + * Internal implementation of StrStrA/StrStrIA + */ +static LPSTR COMCTL32_StrStrHelperA(LPCSTR lpszStr, LPCSTR lpszSearch, + int (*pStrCmpFn)(LPCSTR,LPCSTR,size_t)) +{ + size_t iLen; + + if (!lpszStr || !lpszSearch || !*lpszSearch) + return NULL; + + iLen = strlen(lpszSearch); + + while (*lpszStr) + { + if (!pStrCmpFn(lpszStr, lpszSearch, iLen)) + return (LPSTR)lpszStr; + lpszStr = CharNextA(lpszStr); + } + return NULL; +} + +/************************************************************************* + * COMCTL32_StrStrHelperW + * + * Internal implementation of StrStrW/StrStrIW + */ +static LPWSTR COMCTL32_StrStrHelperW(LPCWSTR lpszStr, LPCWSTR lpszSearch, + int (*pStrCmpFn)(LPCWSTR,LPCWSTR,int)) +{ + int iLen; + + if (!lpszStr || !lpszSearch || !*lpszSearch) + return NULL; + + iLen = strlenW(lpszSearch); + + while (*lpszStr) + { + if (!pStrCmpFn(lpszStr, lpszSearch, iLen)) + return (LPWSTR)lpszStr; + lpszStr = CharNextW(lpszStr); + } + return NULL; +} + +/************************************************************************** + * StrStrIA [COMCTL32.355] + * + * Find a substring within a string, ignoring case. + * + * PARAMS + * lpszStr [I] String to search in + * lpszSearch [I] String to look for + * + * RETURNS + * The start of lpszSearch within lpszStr, or NULL if not found. + */ +LPSTR WINAPI StrStrIA(LPCSTR lpszStr, LPCSTR lpszSearch) +{ + TRACE("(%s,%s)\n", debugstr_a(lpszStr), debugstr_a(lpszSearch)); + + return COMCTL32_StrStrHelperA(lpszStr, lpszSearch, strncasecmp); +} + +/************************************************************************** + * StrToIntA [COMCTL32.357] + * + * Read a signed integer from a string. + * + * PARAMS + * lpszStr [I] String to read integer from + * + * RETURNS + * The signed integer value represented by the string, or 0 if no integer is + * present. + */ +INT WINAPI StrToIntA (LPSTR lpszStr) +{ + return atoi(lpszStr); +} + +/************************************************************************** + * StrStrIW [COMCTL32.363] + * + * See StrStrIA. + */ +LPWSTR WINAPI StrStrIW(LPCWSTR lpszStr, LPCWSTR lpszSearch) +{ + TRACE("(%s,%s)\n", debugstr_w(lpszStr), debugstr_w(lpszSearch)); + + return COMCTL32_StrStrHelperW(lpszStr, lpszSearch, (int (*)(LPCWSTR,LPCWSTR,int)) wcsnicmp); +} + +/************************************************************************** + * StrToIntW [COMCTL32.365] + * + * See StrToIntA. + */ +INT WINAPI StrToIntW (LPWSTR lpString) +{ + return atoiW(lpString); +} + +/************************************************************************* + * COMCTL32_StrSpnHelperA (internal) + * + * Internal implementation of StrSpnA/StrCSpnA/StrCSpnIA + */ +static int COMCTL32_StrSpnHelperA(LPCSTR lpszStr, LPCSTR lpszMatch, + LPSTR (WINAPI *pStrChrFn)(LPCSTR,WORD), + BOOL bInvert) +{ + LPCSTR lpszRead = lpszStr; + if (lpszStr && *lpszStr && lpszMatch) + { + while (*lpszRead) + { + LPCSTR lpszTest = pStrChrFn(lpszMatch, *lpszRead); + + if (!bInvert && !lpszTest) + break; + if (bInvert && lpszTest) + break; + lpszRead = CharNextA(lpszRead); + }; + } + return lpszRead - lpszStr; +} + +/************************************************************************** + * StrCSpnA [COMCTL32.356] + * + * Find the length of the start of a string that does not contain certain + * characters. + * + * PARAMS + * lpszStr [I] String to search + * lpszMatch [I] Characters that cannot be in the substring + * + * RETURNS + * The length of the part of lpszStr containing only chars not in lpszMatch, + * or 0 if any parameter is invalid. + */ +int WINAPI StrCSpnA(LPCSTR lpszStr, LPCSTR lpszMatch) +{ + TRACE("(%s,%s)\n",debugstr_a(lpszStr), debugstr_a(lpszMatch)); + + return COMCTL32_StrSpnHelperA(lpszStr, lpszMatch, StrChrA, TRUE); +} + +/************************************************************************** + * StrChrW [COMCTL32.358] + * + * See StrChrA. + */ +LPWSTR WINAPI StrChrW(LPCWSTR lpszStr, WCHAR ch) +{ + LPWSTR lpszRet = NULL; + + TRACE("(%s,%i)\n", debugstr_w(lpszStr), ch); + + if (lpszStr) + lpszRet = strchrW(lpszStr, ch); + return lpszRet; +} + +/************************************************************************** + * StrCmpNA [COMCTL32.352] + * + * Compare two strings, up to a maximum length. + * + * PARAMS + * lpszStr [I] First string to compare + * lpszComp [I] Second string to compare + * iLen [I] Maximum number of chars to compare. + * + * RETURNS + * An integer less than, equal to or greater than 0, indicating that + * lpszStr is less than, the same, or greater than lpszComp. + */ +INT WINAPI StrCmpNA(LPCSTR lpszStr, LPCSTR lpszComp, INT iLen) +{ + INT iRet; + + TRACE("(%s,%s,%i)\n", debugstr_a(lpszStr), debugstr_a(lpszComp), iLen); + + iRet = CompareStringA(GetThreadLocale(), 0, lpszStr, iLen, lpszComp, iLen); + return iRet == CSTR_LESS_THAN ? -1 : iRet == CSTR_GREATER_THAN ? 1 : 0; +} + +/************************************************************************** + * StrCmpNIA [COMCTL32.353] + * + * Compare two strings, up to a maximum length, ignoring case. + * + * PARAMS + * lpszStr [I] First string to compare + * lpszComp [I] Second string to compare + * iLen [I] Maximum number of chars to compare. + * + * RETURNS + * An integer less than, equal to or greater than 0, indicating that + * lpszStr is less than, the same, or greater than lpszComp. + */ +int WINAPI StrCmpNIA(LPCSTR lpszStr, LPCSTR lpszComp, int iLen) +{ + INT iRet; + + TRACE("(%s,%s,%i)\n", debugstr_a(lpszStr), debugstr_a(lpszComp), iLen); + + iRet = CompareStringA(GetThreadLocale(), NORM_IGNORECASE, lpszStr, iLen, lpszComp, iLen); + return iRet == CSTR_LESS_THAN ? -1 : iRet == CSTR_GREATER_THAN ? 1 : 0; +} + +/************************************************************************* + * StrCmpNIW [COMCTL32.361] + * + * See StrCmpNIA. + */ +INT WINAPI StrCmpNIW(LPCWSTR lpszStr, LPCWSTR lpszComp, int iLen) +{ + INT iRet; + + TRACE("(%s,%s,%i)\n", debugstr_w(lpszStr), debugstr_w(lpszComp), iLen); + + iRet = CompareStringW(GetThreadLocale(), NORM_IGNORECASE, lpszStr, iLen, lpszComp, iLen); + return iRet == CSTR_LESS_THAN ? -1 : iRet == CSTR_GREATER_THAN ? 1 : 0; +} + +/************************************************************************** + * StrCmpNW [COMCTL32.360] + * + * See StrCmpNA. + */ +INT WINAPI StrCmpNW(LPCWSTR lpszStr, LPCWSTR lpszComp, INT iLen) +{ + INT iRet; + + TRACE("(%s,%s,%i)\n", debugstr_w(lpszStr), debugstr_w(lpszComp), iLen); + + iRet = CompareStringW(GetThreadLocale(), 0, lpszStr, iLen, lpszComp, iLen); + return iRet == CSTR_LESS_THAN ? -1 : iRet == CSTR_GREATER_THAN ? 1 : 0; +} + +/************************************************************************** + * StrRChrA [COMCTL32.351] + * + * Find the last occurence of a character in string. + * + * PARAMS + * lpszStr [I] String to search in + * lpszEnd [I] Place to end search, or NULL to search until the end of lpszStr + * ch [I] Character to search for. + * + * RETURNS + * Success: A pointer to the last occurrence of ch in lpszStr before lpszEnd, + * or NULL if not found. + * Failure: NULL, if any arguments are invalid. + */ +LPSTR WINAPI StrRChrA(LPCSTR lpszStr, LPCSTR lpszEnd, WORD ch) +{ + LPCSTR lpszRet = NULL; + + TRACE("(%s,%s,%x)\n", debugstr_a(lpszStr), debugstr_a(lpszEnd), ch); + + if (lpszStr) + { + WORD ch2; + + if (!lpszEnd) + lpszEnd = lpszStr + lstrlenA(lpszStr); + + while (*lpszStr && lpszStr <= lpszEnd) + { + ch2 = IsDBCSLeadByte(*lpszStr)? *lpszStr << 8 | lpszStr[1] : *lpszStr; + + if (!COMCTL32_ChrCmpA(ch, ch2)) + lpszRet = lpszStr; + lpszStr = CharNextA(lpszStr); + } + } + return (LPSTR)lpszRet; +} + + +/************************************************************************** + * StrRChrW [COMCTL32.359] + * + * See StrRChrA. + */ +LPWSTR WINAPI StrRChrW(LPCWSTR lpszStr, LPCWSTR lpszEnd, WORD ch) +{ + LPCWSTR lpszRet = NULL; + + TRACE("(%s,%s,%x)\n", debugstr_w(lpszStr), debugstr_w(lpszEnd), ch); + + if (lpszStr) + { + if (!lpszEnd) + lpszEnd = lpszStr + strlenW(lpszStr); + + while (*lpszStr && lpszStr <= lpszEnd) + { + if (!COMCTL32_ChrCmpW(ch, *lpszStr)) + lpszRet = lpszStr; + lpszStr = CharNextW(lpszStr); + } + } + return (LPWSTR)lpszRet; +} + +/************************************************************************** + * StrStrA [COMCTL32.354] + * + * Find a substring within a string. + * + * PARAMS + * lpszStr [I] String to search in + * lpszSearch [I] String to look for + * + * RETURNS + * The start of lpszSearch within lpszStr, or NULL if not found. + */ +LPSTR WINAPI StrStrA(LPCSTR lpszStr, LPCSTR lpszSearch) +{ + TRACE("(%s,%s)\n", debugstr_a(lpszStr), debugstr_a(lpszSearch)); + + return COMCTL32_StrStrHelperA(lpszStr, lpszSearch, strncmp); +} + +/************************************************************************** + * StrStrW [COMCTL32.362] + * + * See StrStrA. + */ +LPWSTR WINAPI StrStrW(LPCWSTR lpszStr, LPCWSTR lpszSearch) +{ + TRACE("(%s,%s)\n", debugstr_w(lpszStr), debugstr_w(lpszSearch)); + + return COMCTL32_StrStrHelperW(lpszStr, lpszSearch, (int (*)(LPCWSTR,LPCWSTR,int)) wcsncmp); +} + +/************************************************************************* + * StrChrIA [COMCTL32.366] + * + * Find a given character in a string, ignoring case. + * + * PARAMS + * lpszStr [I] String to search in. + * ch [I] Character to search for. + * + * RETURNS + * Success: A pointer to the first occurrence of ch in lpszStr, or NULL if + * not found. + * Failure: NULL, if any arguments are invalid. + */ +LPSTR WINAPI StrChrIA(LPCSTR lpszStr, WORD ch) +{ + TRACE("(%s,%i)\n", debugstr_a(lpszStr), ch); + + if (lpszStr) + { + while (*lpszStr) + { + if (!COMCTL32_ChrCmpIA(*lpszStr, ch)) + return (LPSTR)lpszStr; + lpszStr = CharNextA(lpszStr); + } + } + return NULL; +} + +/************************************************************************* + * StrChrIW [COMCTL32.367] + * + * See StrChrA. + */ +LPWSTR WINAPI StrChrIW(LPCWSTR lpszStr, WCHAR ch) +{ + TRACE("(%s,%i)\n", debugstr_w(lpszStr), ch); + + if (lpszStr) + { + ch = toupperW(ch); + while (*lpszStr) + { + if (toupperW(*lpszStr) == ch) + return (LPWSTR)lpszStr; + lpszStr = CharNextW(lpszStr); + } + lpszStr = NULL; + } + return (LPWSTR)lpszStr; +} + +/************************************************************************* + * StrRStrIA [COMCTL32.372] + * + * Find the last occurence of a substring within a string. + * + * PARAMS + * lpszStr [I] String to search in + * lpszEnd [I] End of lpszStr + * lpszSearch [I] String to look for + * + * RETURNS + * The last occurence lpszSearch within lpszStr, or NULL if not found. + */ +LPSTR WINAPI StrRStrIA(LPCSTR lpszStr, LPCSTR lpszEnd, LPCSTR lpszSearch) +{ + LPSTR lpszRet = NULL; + WORD ch1, ch2; + INT iLen; + + TRACE("(%s,%s)\n", debugstr_a(lpszStr), debugstr_a(lpszSearch)); + + if (!lpszStr || !lpszSearch || !*lpszSearch) + return NULL; + + if (!lpszEnd) + lpszEnd = lpszStr + lstrlenA(lpszStr); + + if (IsDBCSLeadByte(*lpszSearch)) + ch1 = *lpszSearch << 8 | lpszSearch[1]; + else + ch1 = *lpszSearch; + iLen = lstrlenA(lpszSearch); + + while (lpszStr <= lpszEnd && *lpszStr) + { + ch2 = IsDBCSLeadByte(*lpszStr)? *lpszStr << 8 | lpszStr[1] : *lpszStr; + if (!COMCTL32_ChrCmpIA(ch1, ch2)) + { + if (!StrCmpNIA(lpszStr, lpszSearch, iLen)) + lpszRet = (LPSTR)lpszStr; + } + lpszStr = CharNextA(lpszStr); + } + return lpszRet; +} + +/************************************************************************* + * StrRStrIW [COMCTL32.373] + * + * See StrRStrIA. + */ +LPWSTR WINAPI StrRStrIW(LPCWSTR lpszStr, LPCWSTR lpszEnd, LPCWSTR lpszSearch) +{ + LPWSTR lpszRet = NULL; + INT iLen; + + TRACE("(%s,%s)\n", debugstr_w(lpszStr), debugstr_w(lpszSearch)); + + if (!lpszStr || !lpszSearch || !*lpszSearch) + return NULL; + + if (!lpszEnd) + lpszEnd = lpszStr + strlenW(lpszStr); + + iLen = strlenW(lpszSearch); + + while (lpszStr <= lpszEnd && *lpszStr) + { + if (!COMCTL32_ChrCmpIA(*lpszSearch, *lpszStr)) + { + if (!StrCmpNIW(lpszStr, lpszSearch, iLen)) + lpszRet = (LPWSTR)lpszStr; + } + lpszStr = CharNextW(lpszStr); + } + return lpszRet; +} + +/************************************************************************* + * COMCTL32_StrSpnHelperW + * + * Internal implementation of StrSpnW/StrCSpnW/StrCSpnIW + */ +static int COMCTL32_StrSpnHelperW(LPCWSTR lpszStr, LPCWSTR lpszMatch, + LPWSTR (WINAPI *pStrChrFn)(LPCWSTR,WCHAR), + BOOL bInvert) +{ + LPCWSTR lpszRead = lpszStr; + if (lpszStr && *lpszStr && lpszMatch) + { + while (*lpszRead) + { + LPCWSTR lpszTest = pStrChrFn(lpszMatch, *lpszRead); + + if (!bInvert && !lpszTest) + break; + if (bInvert && lpszTest) + break; + lpszRead = CharNextW(lpszRead); + }; + } + return lpszRead - lpszStr; +} + +/************************************************************************* + * StrCSpnIA [COMCTL32.374] + * + * Find the length of the start of a string that does not contain certain + * characters, ignoring case. + * + * PARAMS + * lpszStr [I] String to search + * lpszMatch [I] Characters that cannot be in the substring + * + * RETURNS + * The length of the part of lpszStr containing only chars not in lpszMatch, + * or 0 if any parameter is invalid. + */ +int WINAPI StrCSpnIA(LPCSTR lpszStr, LPCSTR lpszMatch) +{ + TRACE("(%s,%s)\n",debugstr_a(lpszStr), debugstr_a(lpszMatch)); + + return COMCTL32_StrSpnHelperA(lpszStr, lpszMatch, StrChrIA, TRUE); +} + +/************************************************************************* + * StrCSpnIW [COMCTL32.375] + * + * See StrCSpnIA. + */ +int WINAPI StrCSpnIW(LPCWSTR lpszStr, LPCWSTR lpszMatch) +{ + TRACE("(%s,%s)\n",debugstr_w(lpszStr), debugstr_w(lpszMatch)); + + return COMCTL32_StrSpnHelperW(lpszStr, lpszMatch, StrChrIW, TRUE); +} + +/************************************************************************** + * StrRChrIA [COMCTL32.368] + * + * Find the last occurence of a character in string, ignoring case. + * + * PARAMS + * lpszStr [I] String to search in + * lpszEnd [I] Place to end search, or NULL to search until the end of lpszStr + * ch [I] Character to search for. + * + * RETURNS + * Success: A pointer to the last occurrence of ch in lpszStr before lpszEnd, + * or NULL if not found. + * Failure: NULL, if any arguments are invalid. + */ +LPSTR WINAPI StrRChrIA(LPCSTR lpszStr, LPCSTR lpszEnd, WORD ch) +{ + LPCSTR lpszRet = NULL; + + TRACE("(%s,%s,%x)\n", debugstr_a(lpszStr), debugstr_a(lpszEnd), ch); + + if (lpszStr) + { + WORD ch2; + + if (!lpszEnd) + lpszEnd = lpszStr + lstrlenA(lpszStr); + + while (*lpszStr && lpszStr <= lpszEnd) + { + ch2 = IsDBCSLeadByte(*lpszStr)? *lpszStr << 8 | lpszStr[1] : *lpszStr; + + if (ch == ch2) + lpszRet = lpszStr; + lpszStr = CharNextA(lpszStr); + } + } + return (LPSTR)lpszRet; +} + +/************************************************************************** + * StrRChrIW [COMCTL32.369] + * + * See StrRChrIA. + */ +LPWSTR WINAPI StrRChrIW(LPCWSTR lpszStr, LPCWSTR lpszEnd, WORD ch) +{ + LPCWSTR lpszRet = NULL; + + TRACE("(%s,%s,%x)\n", debugstr_w(lpszStr), debugstr_w(lpszEnd), ch); + + if (lpszStr) + { + if (!lpszEnd) + lpszEnd = lpszStr + strlenW(lpszStr); + + while (*lpszStr && lpszStr <= lpszEnd) + { + if (ch == *lpszStr) + lpszRet = lpszStr; + lpszStr = CharNextW(lpszStr); + } + } + return (LPWSTR)lpszRet; +} + +/************************************************************************* + * StrSpnW [COMCTL32.364] + * + * See StrSpnA. + */ +int WINAPI StrSpnW(LPCWSTR lpszStr, LPCWSTR lpszMatch) +{ + TRACE("(%s,%s)\n",debugstr_w(lpszStr), debugstr_w(lpszMatch)); + + return COMCTL32_StrSpnHelperW(lpszStr, lpszMatch, StrChrW, FALSE); +} + +/************************************************************************* + * StrCSpnW [COMCTL32.@] + * + * See StrCSpnA. + */ +int WINAPI StrCSpnW(LPCWSTR lpszStr, LPCWSTR lpszMatch) +{ + TRACE("(%s,%s)\n",debugstr_w(lpszStr), debugstr_w(lpszMatch)); + + return COMCTL32_StrSpnHelperW(lpszStr, lpszMatch, StrChrW, TRUE); +} + +/************************************************************************* + * IntlStrEqWorkerA [COMCTL32.376] + * + * Compare two strings. + * + * PARAMS + * bCase [I] Whether to compare case sensitively + * lpszStr [I] First string to compare + * lpszComp [I] Second string to compare + * iLen [I] Length to compare + * + * RETURNS + * TRUE If the strings are equal. + * FALSE Otherwise. + */ +BOOL WINAPI IntlStrEqWorkerA(BOOL bCase, LPCSTR lpszStr, LPCSTR lpszComp, + int iLen) +{ + DWORD dwFlags = LOCALE_USE_CP_ACP; + int iRet; + + TRACE("(%d,%s,%s,%d)\n", bCase, + debugstr_a(lpszStr), debugstr_a(lpszComp), iLen); + + /* FIXME: These flags are undocumented and unknown by our CompareString. + * We need defines for them. + */ + dwFlags |= bCase ? 0x10000000 : 0x10000001; + + iRet = CompareStringA(GetThreadLocale(), + dwFlags, lpszStr, iLen, lpszComp, iLen); + + if (!iRet) + iRet = CompareStringA(2048, dwFlags, lpszStr, iLen, lpszComp, iLen); + + return iRet == 2 ? TRUE : FALSE; +} + +/************************************************************************* + * IntlStrEqWorkerW [COMCTL32.377] + * + * See IntlStrEqWorkerA. + */ +BOOL WINAPI IntlStrEqWorkerW(BOOL bCase, LPCWSTR lpszStr, LPCWSTR lpszComp, + int iLen) +{ + DWORD dwFlags; + int iRet; + + TRACE("(%d,%s,%s,%d)\n", bCase, + debugstr_w(lpszStr),debugstr_w(lpszComp), iLen); + + /* FIXME: These flags are undocumented and unknown by our CompareString. + * We need defines for them. + */ + dwFlags = bCase ? 0x10000000 : 0x10000001; + + iRet = CompareStringW(GetThreadLocale(), + dwFlags, lpszStr, iLen, lpszComp, iLen); + + if (!iRet) + iRet = CompareStringW(2048, dwFlags, lpszStr, iLen, lpszComp, iLen); + + return iRet == 2 ? TRUE : FALSE; +} diff --git a/reactos/lib/comctl32/tab.c b/reactos/lib/comctl32/tab.c index f38dd9cda25..7a332c2d095 100644 --- a/reactos/lib/comctl32/tab.c +++ b/reactos/lib/comctl32/tab.c @@ -33,8 +33,6 @@ * TCM_GETEXTENDEDSTYLE * TCM_SETEXTENDEDSTYLE * - * FIXME: - * UpDown control not displayed until after a tab is clicked on */ #include @@ -107,7 +105,7 @@ typedef struct #define CONTROL_BORDER_SIZEX 2 #define CONTROL_BORDER_SIZEY 2 #define BUTTON_SPACINGX 3 -#define BUTTON_SPACINGY 4 +#define BUTTON_SPACINGY 3 #define FLAT_BTN_SPACINGX 8 #define DEFAULT_TAB_WIDTH 96 @@ -327,40 +325,29 @@ static BOOL TAB_InternalGetItemRect( /* calculate the times bottom and top based on the row */ GetClientRect(hwnd, &clientRect); - if ((lStyle & TCS_BOTTOM) && !(lStyle & TCS_VERTICAL)) + if ((lStyle & TCS_BOTTOM) && (lStyle & TCS_VERTICAL)) { - itemRect->bottom = clientRect.bottom - - itemRect->top * (infoPtr->tabHeight - 2) - - ((lStyle & TCS_BUTTONS) ? itemRect->top * BUTTON_SPACINGY : SELECTED_TAB_OFFSET); - - itemRect->top = clientRect.bottom - - infoPtr->tabHeight - - itemRect->top * (infoPtr->tabHeight - 2) - - ((lStyle & TCS_BUTTONS) ? itemRect->top * BUTTON_SPACINGY : SELECTED_TAB_OFFSET); + itemRect->right = clientRect.right - SELECTED_TAB_OFFSET - itemRect->left * infoPtr->tabHeight - + ((lStyle & TCS_BUTTONS) ? itemRect->left * BUTTON_SPACINGX : 0); + itemRect->left = itemRect->right - infoPtr->tabHeight; } - else if((lStyle & TCS_BOTTOM) && (lStyle & TCS_VERTICAL)) + else if (lStyle & TCS_VERTICAL) { - itemRect->right = clientRect.right - SELECTED_TAB_OFFSET - itemRect->left * (infoPtr->tabHeight - 2) - - ((lStyle & TCS_BUTTONS) ? itemRect->left * BUTTON_SPACINGY : 0); - itemRect->left = clientRect.right - infoPtr->tabHeight - itemRect->left * (infoPtr->tabHeight - 2) - - ((lStyle & TCS_BUTTONS) ? itemRect->left * BUTTON_SPACINGY : 0); + itemRect->left = clientRect.left + SELECTED_TAB_OFFSET + itemRect->left * infoPtr->tabHeight + + ((lStyle & TCS_BUTTONS) ? itemRect->left * BUTTON_SPACINGX : 0); + itemRect->right = itemRect->left + infoPtr->tabHeight; } - else if((lStyle & TCS_VERTICAL) && !(lStyle & TCS_BOTTOM)) + else if (lStyle & TCS_BOTTOM) { - itemRect->right = clientRect.left + infoPtr->tabHeight + itemRect->left * (infoPtr->tabHeight - 2) + - ((lStyle & TCS_BUTTONS) ? itemRect->left * BUTTON_SPACINGY : 0); - itemRect->left = clientRect.left + SELECTED_TAB_OFFSET + itemRect->left * (infoPtr->tabHeight - 2) + - ((lStyle & TCS_BUTTONS) ? itemRect->left * BUTTON_SPACINGY : 0); + itemRect->bottom = clientRect.bottom - itemRect->top * infoPtr->tabHeight - + ((lStyle & TCS_BUTTONS) ? itemRect->top * BUTTON_SPACINGY : SELECTED_TAB_OFFSET); + itemRect->top = itemRect->bottom - infoPtr->tabHeight; } - else if(!(lStyle & TCS_VERTICAL) && !(lStyle & TCS_BOTTOM)) /* not TCS_BOTTOM and not TCS_VERTICAL */ + else /* not TCS_BOTTOM and not TCS_VERTICAL */ { - itemRect->bottom = clientRect.top + - infoPtr->tabHeight + - itemRect->top * (infoPtr->tabHeight - 2) + - ((lStyle & TCS_BUTTONS) ? itemRect->top * BUTTON_SPACINGY : SELECTED_TAB_OFFSET); - itemRect->top = clientRect.top + - itemRect->top * (infoPtr->tabHeight - 2) + - ((lStyle & TCS_BUTTONS) ? itemRect->top * BUTTON_SPACINGY : SELECTED_TAB_OFFSET); + itemRect->top = clientRect.top + itemRect->top * infoPtr->tabHeight + + ((lStyle & TCS_BUTTONS) ? itemRect->top * BUTTON_SPACINGY : SELECTED_TAB_OFFSET); + itemRect->bottom = itemRect->top + infoPtr->tabHeight; } /* @@ -371,7 +358,7 @@ static BOOL TAB_InternalGetItemRect( { OffsetRect(itemRect, 0, - -(clientRect.bottom - infoPtr->items[infoPtr->leftmostVisible].rect.bottom)); + -infoPtr->items[infoPtr->leftmostVisible].rect.top); /* * Move the rectangle so the first item is slightly offset from @@ -379,7 +366,7 @@ static BOOL TAB_InternalGetItemRect( */ OffsetRect(itemRect, 0, - -SELECTED_TAB_OFFSET); + SELECTED_TAB_OFFSET); } else { @@ -411,23 +398,23 @@ static BOOL TAB_InternalGetItemRect( InflateRect(selectedRect, SELECTED_TAB_OFFSET, 0); /* If it also a bit higher. */ - if ((lStyle & TCS_BOTTOM) && !(lStyle & TCS_VERTICAL)) + if ((lStyle & TCS_BOTTOM) && (lStyle & TCS_VERTICAL)) + { + selectedRect->left -= 2; /* the border is thicker on the right */ + selectedRect->right += SELECTED_TAB_OFFSET; + } + else if (lStyle & TCS_VERTICAL) + { + selectedRect->left -= SELECTED_TAB_OFFSET; + selectedRect->right += 1; + } + else if (lStyle & TCS_BOTTOM) { selectedRect->bottom += SELECTED_TAB_OFFSET; } - else if((lStyle & TCS_BOTTOM) && (lStyle & TCS_VERTICAL)) + else /* not TCS_BOTTOM and not TCS_VERTICAL */ { - selectedRect->left -= 2; /* the border is thicker on the right */ - selectedRect->right += SELECTED_TAB_OFFSET; - } - else if(lStyle & TCS_VERTICAL) - { - selectedRect->left -= SELECTED_TAB_OFFSET; - selectedRect->right += 1; - } - else - { - selectedRect->top -= SELECTED_TAB_OFFSET; + selectedRect->top -= SELECTED_TAB_OFFSET; selectedRect->bottom -= 1; } } @@ -853,72 +840,53 @@ static LRESULT TAB_AdjustRect( WPARAM fLarger, LPRECT prc) { - TAB_INFO *infoPtr = TAB_GetInfoPtr(hwnd); - DWORD lStyle = GetWindowLongA(hwnd, GWL_STYLE); + TAB_INFO *infoPtr = TAB_GetInfoPtr(hwnd); + DWORD lStyle = GetWindowLongA(hwnd, GWL_STYLE); + LONG *iRightBottom, *iLeftTop; + + TRACE ("hwnd=%p fLarger=%d (%ld,%ld)-(%ld,%ld)\n", hwnd, fLarger, prc->left, prc->top, prc->right, prc->bottom); + + if(lStyle & TCS_VERTICAL) + { + iRightBottom = &(prc->right); + iLeftTop = &(prc->left); + } + else + { + iRightBottom = &(prc->bottom); + iLeftTop = &(prc->top); + } - if(lStyle & TCS_VERTICAL) - { if (fLarger) /* Go from display rectangle */ { - /* Add the height of the tabs. */ - if (lStyle & TCS_BOTTOM) - prc->right += (infoPtr->tabHeight - 2) * infoPtr->uNumRows + 2; - else - prc->left -= (infoPtr->tabHeight - 2) * infoPtr->uNumRows + 2; + /* Add the height of the tabs. */ + if (lStyle & TCS_BOTTOM) + *iRightBottom += infoPtr->tabHeight * infoPtr->uNumRows; + else + *iLeftTop -= infoPtr->tabHeight * infoPtr->uNumRows + + ((lStyle & TCS_BUTTONS)? 3 * (infoPtr->uNumRows - 1) : 0); - /* FIXME: not sure if these InflateRect's need to have different values for TCS_VERTICAL */ - /* Inflate the rectangle for the padding */ - InflateRect(prc, DISPLAY_AREA_PADDINGX, DISPLAY_AREA_PADDINGY); + /* Inflate the rectangle for the padding */ + InflateRect(prc, DISPLAY_AREA_PADDINGX, DISPLAY_AREA_PADDINGY); - /* Inflate for the border */ - InflateRect(prc, CONTROL_BORDER_SIZEX, CONTROL_BORDER_SIZEX); + /* Inflate for the border */ + InflateRect(prc, CONTROL_BORDER_SIZEX, CONTROL_BORDER_SIZEY); } else /* Go from window rectangle. */ { - /* FIXME: not sure if these InflateRect's need to have different values for TCS_VERTICAL */ - /* Deflate the rectangle for the border */ - InflateRect(prc, -CONTROL_BORDER_SIZEX, -CONTROL_BORDER_SIZEX); + /* Deflate the rectangle for the border */ + InflateRect(prc, -CONTROL_BORDER_SIZEX, -CONTROL_BORDER_SIZEY); - /* Deflate the rectangle for the padding */ - InflateRect(prc, -DISPLAY_AREA_PADDINGX, -DISPLAY_AREA_PADDINGY); + /* Deflate the rectangle for the padding */ + InflateRect(prc, -DISPLAY_AREA_PADDINGX, -DISPLAY_AREA_PADDINGY); - /* Remove the height of the tabs. */ - if (lStyle & TCS_BOTTOM) - prc->right -= (infoPtr->tabHeight - 2) * infoPtr->uNumRows + 2; - else - prc->left += (infoPtr->tabHeight - 2) * infoPtr->uNumRows + 2; + /* Remove the height of the tabs. */ + if (lStyle & TCS_BOTTOM) + *iRightBottom -= infoPtr->tabHeight * infoPtr->uNumRows; + else + *iLeftTop += (infoPtr->tabHeight) * infoPtr->uNumRows + + ((lStyle & TCS_BUTTONS)? 3 * (infoPtr->uNumRows - 1) : 0); } - } - else { - if (fLarger) /* Go from display rectangle */ - { - /* Add the height of the tabs. */ - if (lStyle & TCS_BOTTOM) - prc->bottom += (infoPtr->tabHeight - 2) * infoPtr->uNumRows + 2; - else - prc->top -= (infoPtr->tabHeight - 2) * infoPtr->uNumRows + 2; - - /* Inflate the rectangle for the padding */ - InflateRect(prc, DISPLAY_AREA_PADDINGX, DISPLAY_AREA_PADDINGY); - - /* Inflate for the border */ - InflateRect(prc, CONTROL_BORDER_SIZEX, CONTROL_BORDER_SIZEX); - } - else /* Go from window rectangle. */ - { - /* Deflate the rectangle for the border */ - InflateRect(prc, -CONTROL_BORDER_SIZEX, -CONTROL_BORDER_SIZEX); - - /* Deflate the rectangle for the padding */ - InflateRect(prc, -DISPLAY_AREA_PADDINGX, -DISPLAY_AREA_PADDINGY); - - /* Remove the height of the tabs. */ - if (lStyle & TCS_BOTTOM) - prc->bottom -= (infoPtr->tabHeight - 2) * infoPtr->uNumRows + 2; - else - prc->top += (infoPtr->tabHeight - 2) * infoPtr->uNumRows + 2; - } - } return 0; } @@ -1147,7 +1115,7 @@ static void TAB_SetItemBounds (HWND hwnd) * Make sure there is enough space for the letters + icon + growing the * selected item + extra space for the selected item. */ - infoPtr->tabHeight = item_height + SELECTED_TAB_OFFSET + + infoPtr->tabHeight = item_height + ((lStyle & TCS_BUTTONS) ? 2 : 1) * infoPtr->uVItemPadding; @@ -1201,12 +1169,13 @@ static void TAB_SetItemBounds (HWND hwnd) * Check if this is a multiline tab control and if so * check to see if we should wrap the tabs * - * Wrap all these tabs. We will arange them evenly later. + * Wrap all these tabs. We will arrange them evenly later. * */ if (((lStyle & TCS_MULTILINE) || (lStyle & TCS_VERTICAL)) && - (infoPtr->items[curItem].rect.right > clientRect.right)) + (infoPtr->items[curItem].rect.right > + (clientRect.right - CONTROL_BORDER_SIZEX - DISPLAY_AREA_PADDINGX))) { infoPtr->items[curItem].rect.right -= infoPtr->items[curItem].rect.left; @@ -1268,7 +1237,7 @@ static void TAB_SetItemBounds (HWND hwnd) /* Set the number of rows */ infoPtr->uNumRows = curItemRowCount; - /* Arange all tabs evenly if style says so */ + /* Arrange all tabs evenly if style says so */ if (!(lStyle & TCS_RAGGEDRIGHT) && ((lStyle & TCS_MULTILINE) || (lStyle & TCS_VERTICAL)) && (infoPtr->uNumItem > 0)) { INT tabPerRow,remTab; @@ -1303,17 +1272,6 @@ static void TAB_SetItemBounds (HWND hwnd) /* move to the next row, reset our current item left position and */ /* the count of items on this row */ - /* ************ FIXME FIXME FIXME *************** */ - /* */ - /* FIXME: */ - /* if vertical, */ - /* if item n and n+1 are in the same row, */ - /* then the display has n+1 lower (toward the */ - /* bottom) than n. We do it just the */ - /* opposite!!! */ - /* */ - /* ************ FIXME FIXME FIXME *************** */ - if (lStyle & TCS_VERTICAL) { /* Vert: Add the remaining tabs in the *last* remainder rows */ if (iCount >= ((iRow>=(INT)infoPtr->uNumRows - remTab)?tabPerRow + 1:tabPerRow)) { @@ -1429,8 +1387,8 @@ static void TAB_SetItemBounds (HWND hwnd) rcOriginal = *rcItem; - /* this is rotating the items by 90 degrees around the center of the control */ - rcItem->top = (clientRect.right - (rcOriginal.left - clientRect.left)) - (rcOriginal.right - rcOriginal.left); + /* this is rotating the items by 90 degrees clockwise around the center of the control */ + rcItem->top = (rcOriginal.left - clientRect.left); rcItem->bottom = rcItem->top + (rcOriginal.right - rcOriginal.left); rcItem->left = rcOriginal.top; rcItem->right = rcOriginal.bottom; @@ -1533,7 +1491,7 @@ TAB_DrawItemInterior INT oldBkMode; HFONT hOldFont; - if (drawRect == NULL) +/* if (drawRect == NULL) */ { BOOL isVisible; RECT itemRect; @@ -1557,40 +1515,75 @@ TAB_DrawItemInterior * would have liked to avoid code duplication, but couldn't figure * out how without making spaghetti of TAB_DrawItem. */ + if (iItem == infoPtr->iSelected) + *drawRect = selectedRect; + else + *drawRect = itemRect; + if (lStyle & TCS_BUTTONS) { - *drawRect = itemRect; if (iItem == infoPtr->iSelected) { - OffsetRect(drawRect, 1, 1); + drawRect->left += 4; + drawRect->top += 4; + drawRect->right -= 4; + drawRect->bottom -= 1; + } + else + { + drawRect->left += 2; + drawRect->top += 2; + drawRect->right -= 2; + drawRect->bottom -= 2; } } else { - if (iItem == infoPtr->iSelected) + if ((lStyle & TCS_VERTICAL) && (lStyle & TCS_BOTTOM)) { - *drawRect = selectedRect; - if (lStyle & TCS_BOTTOM) + if (iItem != infoPtr->iSelected) { - if (lStyle & TCS_VERTICAL) - { - drawRect->left++; - } - else - { - drawRect->top += 3; - drawRect->left += 1; - } + drawRect->left += 2; + drawRect->top += 2; + drawRect->bottom -= 2; + } + } + else if (lStyle & TCS_VERTICAL) + { + if (iItem == infoPtr->iSelected) + { + drawRect->right += 1; + } + else + { + drawRect->top += 2; + drawRect->right -= 2; + drawRect->bottom -= 2; + } + } + else if (lStyle & TCS_BOTTOM) + { + if (iItem == infoPtr->iSelected) + { + drawRect->top -= 2; + } + else + { + InflateRect(drawRect, -2, -2); + drawRect->bottom += 2; } } else - *drawRect = itemRect; - - - if (lStyle & TCS_BOTTOM && !(lStyle & TCS_VERTICAL)) { - drawRect->top--; - drawRect->bottom--; + if (iItem == infoPtr->iSelected) + { + drawRect->bottom += 3; + } + else + { + drawRect->bottom -= (infoPtr->items[iItem].rect.top != infoPtr->uNumRows-1)? 2:2; + InflateRect(drawRect, -2, 0); + } } } } @@ -1661,7 +1654,6 @@ TAB_DrawItemInterior dis.hwndItem = hwnd; /* */ dis.hDC = hdc; CopyRect(&dis.rcItem,drawRect); - InflateRect(&dis.rcItem, -2, -2); dis.itemData = infoPtr->items[iItem].lParam; /* @@ -1717,6 +1709,9 @@ TAB_DrawItemInterior if (center_offset_h < 2) center_offset_h = 2; + if (center_offset_v < 0) + center_offset_v = 0; + TRACE("for <%s>, c_o_h=%d, c_o_v=%d, draw=(%ld,%ld)-(%ld,%ld), textlen=%ld\n", debugstr_w(infoPtr->items[iItem].pszText), center_offset_h, center_offset_v, drawRect->left, drawRect->top, drawRect->right, drawRect->bottom, @@ -1773,14 +1768,22 @@ TAB_DrawItemInterior else drawRect->bottom-=center_offset_h; - drawRect->left += ((drawRect->right - drawRect->left) - ((rcText.bottom - rcText.top) + infoPtr->uVItemPadding)) / 2; + center_offset_v = ((drawRect->right - drawRect->left) - ((rcText.bottom - rcText.top) + infoPtr->uVItemPadding)) / 2; } else { drawRect->left += center_offset_h; - drawRect->top += ((drawRect->bottom - drawRect->top) - ((rcText.bottom - rcText.top) + infoPtr->uVItemPadding)) / 2; + center_offset_v = ((drawRect->bottom - drawRect->top) - ((rcText.bottom - rcText.top) + infoPtr->uVItemPadding)) / 2; } + if (center_offset_v < 0) + center_offset_v = 0; + + if(lStyle & TCS_VERTICAL) + drawRect->left += center_offset_v; + else + drawRect->top += center_offset_v; + /* Draw the text */ if(lStyle & TCS_VERTICAL) /* if we are vertical rotate the text and each character */ { @@ -1830,6 +1833,10 @@ TAB_DrawItemInterior } else { + TRACE("for <%s>, c_o_h=%d, c_o_v=%d, draw=(%ld,%ld)-(%ld,%ld), textlen=%ld\n", + debugstr_w(infoPtr->items[iItem].pszText), center_offset_h, center_offset_v, + drawRect->left, drawRect->top, drawRect->right, drawRect->bottom, + (rcText.right-rcText.left)); DrawTextW ( hdc, @@ -1958,10 +1965,10 @@ static void TAB_DrawItem( /* if leftmost draw the line longer */ if(selectedRect.top == 0) - fillRect.top += 2; + fillRect.top += CONTROL_BORDER_SIZEY; /* if rightmost draw the line longer */ if(selectedRect.bottom == clBottom) - fillRect.bottom -= 2; + fillRect.bottom -= CONTROL_BORDER_SIZEY; } if (lStyle & TCS_BOTTOM) @@ -1969,7 +1976,7 @@ static void TAB_DrawItem( /* Adjust both rectangles to match native */ r.left += (1-ZZ); - TRACE(" item=%d, fill=(%ld,%ld)-(%ld,%ld), edge=(%ld,%ld)-(%ld,%ld)\n", + TRACE(" item=%d, fill=(%ld,%ld)-(%ld,%ld), edge=(%ld,%ld)-(%ld,%ld)\n", iItem, fillRect.left,fillRect.top,fillRect.right,fillRect.bottom, r.left,r.top,r.right,r.bottom); @@ -2010,9 +2017,6 @@ static void TAB_DrawItem( } else { - /* Adjust both rectangles to match native */ - fillRect.right += (1-ZZ); - TRACE(" item=%d, fill=(%ld,%ld)-(%ld,%ld), edge=(%ld,%ld)-(%ld,%ld)\n", iItem, fillRect.left,fillRect.top,fillRect.right,fillRect.bottom, @@ -2049,26 +2053,23 @@ static void TAB_DrawItem( { /* These are for adjusting the drawing of a Selected tab */ /* The initial values are for the normal case of non-Selected */ - int ZZ = 1; /* Do not strech if selected */ if (iItem == infoPtr->iSelected) { - ZZ = 0; - /* if leftmost draw the line longer */ if(selectedRect.left == 0) - fillRect.left += 2; + fillRect.left += CONTROL_BORDER_SIZEX; /* if rightmost draw the line longer */ if(selectedRect.right == clRight) - fillRect.right -= 2; + fillRect.right -= CONTROL_BORDER_SIZEX; } if (lStyle & TCS_BOTTOM) { - - /* Adjust both rectangles to match native */ - fillRect.top--; - fillRect.bottom--; - r.bottom--; - r.top -= ZZ; + /* Adjust both rectangles for topmost row */ + if (infoPtr->items[iItem].rect.top == infoPtr->uNumRows-1) + { + fillRect.top -= 2; + r.top -= 1; + } TRACE(" item=%d, fill=(%ld,%ld)-(%ld,%ld), edge=(%ld,%ld)-(%ld,%ld)\n", iItem, @@ -2117,9 +2118,12 @@ static void TAB_DrawItem( } else { - - /* Adjust both rectangles to match native */ - fillRect.bottom += (1-ZZ); + /* Adjust both rectangles for bottommost row */ + if (infoPtr->items[iItem].rect.top == infoPtr->uNumRows-1) + { + fillRect.bottom += 3; + r.bottom += 2; + } TRACE(" item=%d, fill=(%ld,%ld)-(%ld,%ld), edge=(%ld,%ld)-(%ld,%ld)\n", iItem, @@ -2151,7 +2155,6 @@ static void TAB_DrawItem( ExtTextOutA(hdc, 0, 0, 2, &r1, NULL, 0, 0); r1.top++; DrawEdge(hdc, &r1, EDGE_RAISED, BF_SOFT|BF_DIAGONAL_ENDTOPRIGHT); - } } } @@ -2184,21 +2187,13 @@ static void TAB_DrawBorder (HWND hwnd, HDC hdc) if (infoPtr->uNumItem) { if ((lStyle & TCS_BOTTOM) && !(lStyle & TCS_VERTICAL)) - { - rect.bottom -= (infoPtr->tabHeight - 2) * infoPtr->uNumRows + 3; - } + rect.bottom -= infoPtr->tabHeight * infoPtr->uNumRows + CONTROL_BORDER_SIZEX; else if((lStyle & TCS_BOTTOM) && (lStyle & TCS_VERTICAL)) - { - rect.right -= (infoPtr->tabHeight - 2) * infoPtr->uNumRows + 2; - } + rect.right -= infoPtr->tabHeight * infoPtr->uNumRows + CONTROL_BORDER_SIZEX; else if(lStyle & TCS_VERTICAL) - { - rect.left += (infoPtr->tabHeight - 2) * infoPtr->uNumRows + 2; - } + rect.left += infoPtr->tabHeight * infoPtr->uNumRows + CONTROL_BORDER_SIZEX; else /* not TCS_VERTICAL and not TCS_BOTTOM */ - { - rect.top += (infoPtr->tabHeight - 2) * infoPtr->uNumRows + 2; - } + rect.top += infoPtr->tabHeight * infoPtr->uNumRows + CONTROL_BORDER_SIZEX; } TRACE("border=(%ld,%ld)-(%ld,%ld)\n", @@ -2418,7 +2413,7 @@ static void TAB_InvalidateTabArea( HWND hwnd, TAB_INFO* infoPtr) { - RECT clientRect, rInvalidate; + RECT clientRect, rInvalidate, rAdjClient; DWORD lStyle = GetWindowLongA(hwnd, GWL_STYLE); INT lastRow = infoPtr->uNumRows - 1; RECT rect; @@ -2427,36 +2422,34 @@ static void TAB_InvalidateTabArea( GetClientRect(hwnd, &clientRect); rInvalidate = clientRect; + rAdjClient = clientRect; + + TAB_AdjustRect(hwnd, 0, &rAdjClient); TAB_InternalGetItemRect(hwnd, infoPtr, infoPtr->uNumItem-1 , &rect, NULL); - if ((lStyle & TCS_BOTTOM) && !(lStyle & TCS_VERTICAL)) + if ((lStyle & TCS_BOTTOM) && (lStyle & TCS_VERTICAL)) { - rInvalidate.top = clientRect.bottom - - infoPtr->tabHeight - - lastRow * (infoPtr->tabHeight - 2) - - ((lStyle & TCS_BUTTONS) ? lastRow * BUTTON_SPACINGY : 0) - 3; - rInvalidate.right = clientRect.left + rect.right + 2 * SELECTED_TAB_OFFSET; - } - else if((lStyle & TCS_BOTTOM) && (lStyle & TCS_VERTICAL)) - { - rInvalidate.left = clientRect.right - infoPtr->tabHeight - - lastRow * (infoPtr->tabHeight - 2) - - ((lStyle & TCS_BUTTONS) ? lastRow * BUTTON_SPACINGY : 0) - 2; - rInvalidate.bottom = clientRect.top + rect.bottom + 2 * SELECTED_TAB_OFFSET; + rInvalidate.left = rAdjClient.right; + if (infoPtr->uNumRows == 1) + rInvalidate.bottom = clientRect.top + rect.bottom + 2 * SELECTED_TAB_OFFSET; } else if(lStyle & TCS_VERTICAL) { - rInvalidate.right = clientRect.left + infoPtr->tabHeight + - lastRow * (infoPtr->tabHeight - 2) - - ((lStyle & TCS_BUTTONS) ? lastRow * BUTTON_SPACINGY : 0) + 2; - rInvalidate.bottom = clientRect.top + rect.bottom + 2 * SELECTED_TAB_OFFSET; + rInvalidate.right = rAdjClient.left; + if (infoPtr->uNumRows == 1) + rInvalidate.bottom = clientRect.top + rect.bottom + 2 * SELECTED_TAB_OFFSET; } - else + else if (lStyle & TCS_BOTTOM) { - rInvalidate.bottom = clientRect.top + infoPtr->tabHeight + - lastRow * (infoPtr->tabHeight - 2) + - ((lStyle & TCS_BUTTONS) ? lastRow * BUTTON_SPACINGY : 0) + 2; - rInvalidate.right = clientRect.left + rect.right + 2 * SELECTED_TAB_OFFSET; + rInvalidate.top = rAdjClient.bottom; + if (infoPtr->uNumRows == 1) + rInvalidate.right = clientRect.left + rect.right + 2 * SELECTED_TAB_OFFSET; + } + else + { + rInvalidate.bottom = rAdjClient.top; + if (infoPtr->uNumRows == 1) + rInvalidate.right = clientRect.left + rect.right + 2 * SELECTED_TAB_OFFSET; } /* Punch out the updown control */ @@ -2470,8 +2463,8 @@ static void TAB_InvalidateTabArea( } TRACE("invalidate (%ld,%ld)-(%ld,%ld)\n", - clientRect.left,clientRect.top, - clientRect.right,clientRect.bottom); + rInvalidate.left, rInvalidate.top, + rInvalidate.right, rInvalidate.bottom); InvalidateRect(hwnd, &rInvalidate, TRUE); } diff --git a/reactos/lib/comctl32/toolbar.c b/reactos/lib/comctl32/toolbar.c index 73d5cf3133c..3e1fa927e31 100644 --- a/reactos/lib/comctl32/toolbar.c +++ b/reactos/lib/comctl32/toolbar.c @@ -113,6 +113,7 @@ typedef struct DWORD dwStructSize; /* size of TBBUTTON struct */ INT nHeight; /* height of the toolbar */ INT nWidth; /* width of the toolbar */ + RECT client_rect; INT nButtonHeight; INT nButtonWidth; INT nBitmapHeight; @@ -392,8 +393,8 @@ TOOLBAR_DrawImageList (TOOLBAR_INFO *infoPtr, TBUTTON_INFO *btnPtr, IMAGE_LIST_T if (!TOOLBAR_IsValidBitmapIndex(infoPtr,btnPtr->iBitmap)) { if (btnPtr->iBitmap == I_IMAGENONE) return FALSE; - ERR("index %d is not valid, max %d\n", - btnPtr->iBitmap, infoPtr->nNumBitmaps); + ERR("index %d,%d is not valid, max %d\n", + HIWORD(btnPtr->iBitmap), LOWORD(btnPtr->iBitmap), infoPtr->nNumBitmaps); return FALSE; } @@ -497,7 +498,7 @@ TOOLBAR_DrawFlatSeparator (LPRECT lpRect, HDC hdc, TOOLBAR_INFO *infoPtr) /*********************************************************************** * TOOLBAR_DrawDDFlatSeparator * -* This function draws the separator that was flaged as BTNS_DROPDOWN. +* This function draws the separator that was flagged as BTNS_DROPDOWN. * In this case, the separator is a pixel high line of COLOR_BTNSHADOW, * followed by a pixel high line of COLOR_BTNHIGHLIGHT. These separators * are horizontal as opposed to the vertical separators for not dropdown @@ -565,13 +566,13 @@ TOOLBAR_DrawArrow (HDC hdc, INT left, INT top, INT colorRef) * an image list */ static void -TOOLBAR_DrawString (TOOLBAR_INFO *infoPtr, TBUTTON_INFO *btnPtr, - HDC hdc, DWORD dwStyle, - RECT *rcText, LPWSTR lpText, NMTBCUSTOMDRAW *tbcd) +TOOLBAR_DrawString (TOOLBAR_INFO *infoPtr, RECT *rcText, LPWSTR lpText, + NMTBCUSTOMDRAW *tbcd) { HFONT hOldFont = 0; COLORREF clrOld = 0; UINT state = tbcd->nmcd.uItemState; + HDC hdc = tbcd->nmcd.hdc; /* draw text */ if (lpText) { @@ -604,12 +605,15 @@ TOOLBAR_DrawString (TOOLBAR_INFO *infoPtr, TBUTTON_INFO *btnPtr, static void -TOOLBAR_DrawPattern (HDC hdc, LPRECT lpRect) +TOOLBAR_DrawPattern (LPRECT lpRect, NMTBCUSTOMDRAW *tbcd) { + HDC hdc = tbcd->nmcd.hdc; HBRUSH hbr = SelectObject (hdc, COMCTL32_hPattern55AABrush); INT cx = lpRect->right - lpRect->left; INT cy = lpRect->bottom - lpRect->top; - PatBlt (hdc, lpRect->left, lpRect->top, cx, cy, 0x00FA0089); + SetTextColor(hdc, tbcd->clrBtnHighlight); + SetBkColor(hdc, tbcd->clrBtnFace); + PatBlt (hdc, lpRect->left, lpRect->top, cx, cy, PATCOPY); SelectObject (hdc, hbr); } @@ -801,9 +805,10 @@ TOOLBAR_DrawButton (HWND hwnd, TBUTTON_INFO *btnPtr, HDC hdc) /* NOTE: applications can and do alter this to customize their */ /* toolbars */ tbcd.nmcd.uItemState = TOOLBAR_TranslateState(btnPtr); + tbcd.nmcd.hdc = hdc; + tbcd.hbrMonoDither = COMCTL32_hPattern55AABrush; /* FIXME: what should these be set to ????? */ - tbcd.hbrMonoDither = 0; tbcd.hbrLines = 0; tbcd.hpenLines = 0; @@ -813,7 +818,6 @@ TOOLBAR_DrawButton (HWND hwnd, TBUTTON_INFO *btnPtr, HDC hdc) if (infoPtr->dwBaseCustDraw & CDRF_NOTIFYITEMDRAW) { tbcd.nmcd.dwDrawStage = CDDS_ITEMPREPAINT; - tbcd.nmcd.hdc = hdc; tbcd.nmcd.rc = rc; tbcd.nmcd.dwItemSpec = btnPtr->idCommand; tbcd.nmcd.lItemlParam = btnPtr->dwData; @@ -896,7 +900,7 @@ TOOLBAR_DrawButton (HWND hwnd, TBUTTON_INFO *btnPtr, HDC hdc) TOOLBAR_DrawMasked (infoPtr, btnPtr, hdc, rcBitmap.left, rcBitmap.top); if (!(infoPtr->dwExStyle & TBSTYLE_EX_MIXEDBUTTONS) || (btnPtr->fsStyle & BTNS_SHOWTEXT)) - TOOLBAR_DrawString (infoPtr, btnPtr, hdc, dwStyle, &rcText, lpText, &tbcd); + TOOLBAR_DrawString (infoPtr, &rcText, lpText, &tbcd); goto FINALNOTIFY; } @@ -927,7 +931,7 @@ TOOLBAR_DrawButton (HWND hwnd, TBUTTON_INFO *btnPtr, HDC hdc) ILD_NORMAL); if (!(infoPtr->dwExStyle & TBSTYLE_EX_MIXEDBUTTONS) || (btnPtr->fsStyle & BTNS_SHOWTEXT)) - TOOLBAR_DrawString (infoPtr, btnPtr, hdc, dwStyle, &rcText, lpText, &tbcd); + TOOLBAR_DrawString (infoPtr, &rcText, lpText, &tbcd); goto FINALNOTIFY; } @@ -944,14 +948,14 @@ TOOLBAR_DrawButton (HWND hwnd, TBUTTON_INFO *btnPtr, HDC hdc) BF_RECT | BF_MIDDLE | BF_ADJUST); } - TOOLBAR_DrawPattern (hdc, &rc); + TOOLBAR_DrawPattern (&rc, &tbcd); TOOLBAR_DrawImageList (infoPtr, btnPtr, IMAGE_LIST_DEFAULT, hdc, rcBitmap.left+1, rcBitmap.top+1, ILD_NORMAL); if (!(infoPtr->dwExStyle & TBSTYLE_EX_MIXEDBUTTONS) || (btnPtr->fsStyle & BTNS_SHOWTEXT)) - TOOLBAR_DrawString (infoPtr, btnPtr, hdc, dwStyle, &rcText, lpText, &tbcd); + TOOLBAR_DrawString (infoPtr, &rcText, lpText, &tbcd); goto FINALNOTIFY; } @@ -961,10 +965,10 @@ TOOLBAR_DrawButton (HWND hwnd, TBUTTON_INFO *btnPtr, HDC hdc) DrawEdge (hdc, &rc, EDGE_RAISED, BF_SOFT | BF_RECT | BF_MIDDLE | BF_ADJUST); - TOOLBAR_DrawPattern (hdc, &rc); + TOOLBAR_DrawPattern (&rc, &tbcd); TOOLBAR_DrawMasked (infoPtr, btnPtr, hdc, rcBitmap.left, rcBitmap.top); if (!(infoPtr->dwExStyle & TBSTYLE_EX_MIXEDBUTTONS) || (btnPtr->fsStyle & BTNS_SHOWTEXT)) - TOOLBAR_DrawString (infoPtr, btnPtr, hdc, dwStyle, &rcText, lpText, &tbcd); + TOOLBAR_DrawString (infoPtr, &rcText, lpText, &tbcd); goto FINALNOTIFY; } @@ -1011,7 +1015,7 @@ TOOLBAR_DrawButton (HWND hwnd, TBUTTON_INFO *btnPtr, HDC hdc) if (!(infoPtr->dwExStyle & TBSTYLE_EX_MIXEDBUTTONS) || (btnPtr->fsStyle & BTNS_SHOWTEXT)) - TOOLBAR_DrawString (infoPtr, btnPtr, hdc, dwStyle, &rcText, lpText, &tbcd); + TOOLBAR_DrawString (infoPtr, &rcText, lpText, &tbcd); FINALNOTIFY: if (infoPtr->dwItemCustDraw & CDRF_NOTIFYPOSTPAINT) @@ -1116,7 +1120,8 @@ TOOLBAR_MeasureString(TOOLBAR_INFO *infoPtr, TBUTTON_INFO *btnPtr, lpSize->cx = 0; lpSize->cy = 0; - if (!(btnPtr->fsState & TBSTATE_HIDDEN) && + if (infoPtr->nMaxTextRows > 0 && + !(btnPtr->fsState & TBSTATE_HIDDEN) && (!(infoPtr->dwExStyle & TBSTYLE_EX_MIXEDBUTTONS) || (btnPtr->fsStyle & BTNS_SHOWTEXT)) ) { @@ -3290,7 +3295,9 @@ TOOLBAR_GetButtonTextW (HWND hwnd, WPARAM wParam, LPARAM lParam) static LRESULT TOOLBAR_GetDisabledImageList (HWND hwnd, WPARAM wParam, LPARAM lParam) { - return (LRESULT)GETDISIMAGELIST(TOOLBAR_GetInfoPtr (hwnd), 0); + TRACE("hwnd=%p, wParam=%d, lParam=0x%lx\n", hwnd, wParam, lParam); + /* UNDOCUMENTED: wParam is actually the ID of the image list to return */ + return (LRESULT)GETDISIMAGELIST(TOOLBAR_GetInfoPtr (hwnd), wParam); } @@ -3308,7 +3315,9 @@ TOOLBAR_GetExtendedStyle (HWND hwnd) static LRESULT TOOLBAR_GetHotImageList (HWND hwnd, WPARAM wParam, LPARAM lParam) { - return (LRESULT)GETHOTIMAGELIST(TOOLBAR_GetInfoPtr (hwnd), 0); + TRACE("hwnd=%p, wParam=%d, lParam=0x%lx\n", hwnd, wParam, lParam); + /* UNDOCUMENTED: wParam is actually the ID of the image list to return */ + return (LRESULT)GETHOTIMAGELIST(TOOLBAR_GetInfoPtr (hwnd), wParam); } @@ -3330,7 +3339,9 @@ TOOLBAR_GetHotItem (HWND hwnd) static LRESULT TOOLBAR_GetDefImageList (HWND hwnd, WPARAM wParam, LPARAM lParam) { - return (LRESULT) GETDEFIMAGELIST(TOOLBAR_GetInfoPtr(hwnd), 0); + TRACE("hwnd=%p, wParam=%d, lParam=0x%lx\n", hwnd, wParam, lParam); + /* UNDOCUMENTED: wParam is actually the ID of the image list to return */ + return (LRESULT) GETDEFIMAGELIST(TOOLBAR_GetInfoPtr(hwnd), wParam); } @@ -4305,6 +4316,12 @@ TOOLBAR_SetDrawTextFlags (HWND hwnd, WPARAM wParam, LPARAM lParam) return (LRESULT)dwTemp; } +/* This function differs a bit from what MSDN says it does: + * 1. lParam contains extended style flags to OR with current style + * (MSDN isn't clear on the OR bit) + * 2. wParam appears to contain extended style flags to be reset + * (MSDN says that this parameter is reserved) + */ static LRESULT TOOLBAR_SetExtendedStyle (HWND hwnd, WPARAM wParam, LPARAM lParam) { @@ -4312,6 +4329,7 @@ TOOLBAR_SetExtendedStyle (HWND hwnd, WPARAM wParam, LPARAM lParam) DWORD dwTemp; dwTemp = infoPtr->dwExStyle; + infoPtr->dwExStyle &= ~wParam; infoPtr->dwExStyle |= (DWORD)lParam; TRACE("new style 0x%08lx\n", infoPtr->dwExStyle); @@ -4653,6 +4671,57 @@ TOOLBAR_SetVersion (HWND hwnd, INT iVersion) return iOldVersion; } + +static LRESULT +TOOLBAR_GetStringA (HWND hwnd, WPARAM wParam, LPARAM lParam) +{ + TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr(hwnd); + WORD iString = HIWORD(wParam); + WORD buffersize = LOWORD(wParam); + LPSTR str = (LPSTR)lParam; + LRESULT ret = -1; + + TRACE("hwnd=%p, iString=%d, buffersize=%d, string=%p\n", hwnd, iString, buffersize, str); + + if (iString < infoPtr->nNumStrings) + { + ret = WideCharToMultiByte(CP_ACP, 0, infoPtr->strings[iString], -1, str, buffersize, NULL, NULL); + + TRACE("returning %s\n", debugstr_a(str)); + } + else + ERR("String index %d out of range (largest is %d)\n", iString, infoPtr->nNumStrings - 1); + + return ret; +} + + +static LRESULT +TOOLBAR_GetStringW (HWND hwnd, WPARAM wParam, LPARAM lParam) +{ + TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr(hwnd); + WORD iString = HIWORD(wParam); + WORD len = LOWORD(wParam)/sizeof(WCHAR) - 1; + LPWSTR str = (LPWSTR)lParam; + LRESULT ret = -1; + + TRACE("hwnd=%p, iString=%d, buffersize=%d, string=%p\n", hwnd, iString, LOWORD(wParam), str); + + if (iString < infoPtr->nNumStrings) + { + len = min(len, strlenW(infoPtr->strings[iString])); + ret = (len+1)*sizeof(WCHAR); + memcpy(str, infoPtr->strings[iString], ret); + str[len] = '\0'; + + TRACE("returning %s\n", debugstr_w(str)); + } + else + ERR("String index %d out of range (largest is %d)\n", iString, infoPtr->nNumStrings - 1); + + return ret; +} + static LRESULT TOOLBAR_Unkwn45D(HWND hwnd, WPARAM wParam, LPARAM lParam) { FIXME("hwnd=%p wParam %08x lParam %08lx stub!\n", hwnd, wParam, lParam); @@ -4713,12 +4782,23 @@ TOOLBAR_Unkwn45E (HWND hwnd, WPARAM wParam, LPARAM lParam) static LRESULT TOOLBAR_Unkwn460(HWND hwnd, WPARAM wParam, LPARAM lParam) { - TRACE("hwnd=%p wParam %08x lParam %08lx\n", hwnd, wParam, lParam); + FIXME("hwnd=%p wParam %08x lParam %08lx\n", hwnd, wParam, lParam); InvalidateRect(hwnd, NULL, TRUE); return 0; } +/* UNDOCUMENTED MESSAGE: This returns the number of maximum number + * of image lists associated with the various states. */ +static LRESULT TOOLBAR_Unkwn462(HWND hwnd, WPARAM wParam, LPARAM lParam) +{ + TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr(hwnd); + + TRACE("hwnd=%p wParam %08x lParam %08lx\n", hwnd, wParam, lParam); + + return max(infoPtr->cimlDef, max(infoPtr->cimlHot, infoPtr->cimlDis)); +} + static LRESULT TOOLBAR_Unkwn463 (HWND hwnd, WPARAM wParam, LPARAM lParam) { @@ -4775,7 +4855,7 @@ TOOLBAR_Unkwn463 (HWND hwnd, WPARAM wParam, LPARAM lParam) static LRESULT TOOLBAR_Unkwn464(HWND hwnd, WPARAM wParam, LPARAM lParam) { - TRACE("hwnd=%p wParam %08x lParam %08lx\n", hwnd, wParam, lParam); + FIXME("hwnd=%p wParam %08x lParam %08lx\n", hwnd, wParam, lParam); InvalidateRect(hwnd, NULL, TRUE); return 1; @@ -4789,6 +4869,8 @@ TOOLBAR_Create (HWND hwnd, WPARAM wParam, LPARAM lParam) DWORD dwStyle = GetWindowLongA (hwnd, GWL_STYLE); LOGFONTA logFont; + TRACE("hwnd = %p\n", hwnd); + /* initialize info structure */ infoPtr->nButtonHeight = 22; infoPtr->nButtonWidth = 24; @@ -4819,6 +4901,7 @@ TOOLBAR_Create (HWND hwnd, WPARAM wParam, LPARAM lParam) infoPtr->clrBtnShadow = CLR_DEFAULT; infoPtr->szPadding.cx = 7; infoPtr->szPadding.cy = 6; + GetClientRect(hwnd, &infoPtr->client_rect); TOOLBAR_NotifyFormat(infoPtr, (WPARAM)hwnd, (LPARAM)NF_REQUERY); SystemParametersInfoA (SPI_GETICONTITLELOGFONT, 0, &logFont, 0); @@ -5701,8 +5784,50 @@ TOOLBAR_Size (HWND hwnd, WPARAM wParam, LPARAM lParam) cx += GetSystemMetrics(SM_CYEDGE); } - SetWindowPos (hwnd, 0, x, y, cx, cy, uPosFlags | SWP_NOZORDER); + 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; + + 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); + } + + if((uPosFlags & (SWP_NOSIZE | SWP_NOMOVE)) == (SWP_NOSIZE | SWP_NOMOVE)) + SetWindowPos (hwnd, 0, x, y, cx, cy, uPosFlags | SWP_NOZORDER); } + GetClientRect(hwnd, &infoPtr->client_rect); return 0; } @@ -5867,6 +5992,12 @@ ToolbarWindowProc (HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam) case TB_GETSTATE: return TOOLBAR_GetState (hwnd, wParam, lParam); + case TB_GETSTRINGA: + return TOOLBAR_GetStringA (hwnd, wParam, lParam); + + case TB_GETSTRINGW: + return TOOLBAR_GetStringW (hwnd, wParam, lParam); + case TB_GETSTYLE: return TOOLBAR_GetStyle (hwnd, wParam, lParam); @@ -6015,6 +6146,9 @@ ToolbarWindowProc (HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam) case TB_UNKWN460: return TOOLBAR_Unkwn460(hwnd, wParam, lParam); + case TB_UNKWN462: + return TOOLBAR_Unkwn462(hwnd, wParam, lParam); + case TB_UNKWN463: return TOOLBAR_Unkwn463 (hwnd, wParam, lParam); diff --git a/reactos/lib/comctl32/tooltips.c b/reactos/lib/comctl32/tooltips.c index 0a7e1466b4f..fa2f8782ce8 100644 --- a/reactos/lib/comctl32/tooltips.c +++ b/reactos/lib/comctl32/tooltips.c @@ -701,7 +701,7 @@ TOOLTIPS_AddToolA (HWND hwnd, WPARAM wParam, LPARAM lParam) toolPtr->rect = lpToolInfo->rect; toolPtr->hinst = lpToolInfo->hinst; - if ((lpToolInfo->hinst) && (HIWORD((INT)lpToolInfo->lpszText) == 0)) { + if (HIWORD(lpToolInfo->lpszText) == 0) { TRACE("add string id %x!\n", (int)lpToolInfo->lpszText); toolPtr->lpszText = (LPWSTR)lpToolInfo->lpszText; } @@ -779,7 +779,7 @@ TOOLTIPS_AddToolW (HWND hwnd, WPARAM wParam, LPARAM lParam) toolPtr->rect = lpToolInfo->rect; toolPtr->hinst = lpToolInfo->hinst; - if ((lpToolInfo->hinst) && (HIWORD((INT)lpToolInfo->lpszText) == 0)) { + if (HIWORD(lpToolInfo->lpszText) == 0) { TRACE("add string id %x!\n", (int)lpToolInfo->lpszText); toolPtr->lpszText = (LPWSTR)lpToolInfo->lpszText; } @@ -842,7 +842,7 @@ TOOLTIPS_DelToolA (HWND hwnd, WPARAM wParam, LPARAM lParam) /* delete text string */ toolPtr = &infoPtr->tools[nTool]; - if ((toolPtr->hinst) && (toolPtr->lpszText)) { + if (toolPtr->lpszText) { if ( (toolPtr->lpszText != LPSTR_TEXTCALLBACKW) && (HIWORD((INT)toolPtr->lpszText) != 0) ) Free (toolPtr->lpszText); @@ -917,7 +917,7 @@ TOOLTIPS_DelToolW (HWND hwnd, WPARAM wParam, LPARAM lParam) /* delete text string */ toolPtr = &infoPtr->tools[nTool]; - if ((toolPtr->hinst) && (toolPtr->lpszText)) { + if (toolPtr->lpszText) { if ( (toolPtr->lpszText != LPSTR_TEXTCALLBACKW) && (HIWORD((INT)toolPtr->lpszText) != 0) ) Free (toolPtr->lpszText); @@ -1632,7 +1632,7 @@ TOOLTIPS_SetToolInfoA (HWND hwnd, WPARAM wParam, LPARAM lParam) toolPtr->rect = lpToolInfo->rect; toolPtr->hinst = lpToolInfo->hinst; - if ((lpToolInfo->hinst) && (HIWORD((INT)lpToolInfo->lpszText) == 0)) { + if (HIWORD(lpToolInfo->lpszText) == 0) { TRACE("set string id %x!\n", (INT)lpToolInfo->lpszText); toolPtr->lpszText = (LPWSTR)lpToolInfo->lpszText; } @@ -1689,7 +1689,7 @@ TOOLTIPS_SetToolInfoW (HWND hwnd, WPARAM wParam, LPARAM lParam) toolPtr->rect = lpToolInfo->rect; toolPtr->hinst = lpToolInfo->hinst; - if ((lpToolInfo->hinst) && (HIWORD((INT)lpToolInfo->lpszText) == 0)) { + if (HIWORD(lpToolInfo->lpszText) == 0) { TRACE("set string id %x!\n", (INT)lpToolInfo->lpszText); toolPtr->lpszText = lpToolInfo->lpszText; } @@ -1805,7 +1805,7 @@ TOOLTIPS_UpdateTipTextA (HWND hwnd, WPARAM wParam, LPARAM lParam) /* copy tool text */ toolPtr->hinst = lpToolInfo->hinst; - if ((lpToolInfo->hinst) && (HIWORD((INT)lpToolInfo->lpszText) == 0)){ + if (HIWORD(lpToolInfo->lpszText) == 0){ toolPtr->lpszText = (LPWSTR)lpToolInfo->lpszText; } else if (lpToolInfo->lpszText) { @@ -1862,7 +1862,7 @@ TOOLTIPS_UpdateTipTextW (HWND hwnd, WPARAM wParam, LPARAM lParam) /* copy tool text */ toolPtr->hinst = lpToolInfo->hinst; - if ((lpToolInfo->hinst) && (HIWORD((INT)lpToolInfo->lpszText) == 0)){ + if (HIWORD(lpToolInfo->lpszText) == 0){ toolPtr->lpszText = lpToolInfo->lpszText; } else if (lpToolInfo->lpszText) { @@ -1958,7 +1958,7 @@ TOOLTIPS_Destroy (HWND hwnd, WPARAM wParam, LPARAM lParam) if (infoPtr->tools) { for (i = 0; i < infoPtr->uNumTools; i++) { toolPtr = &infoPtr->tools[i]; - if ((toolPtr->hinst) && (toolPtr->lpszText)) { + if (toolPtr->lpszText) { if ( (toolPtr->lpszText != LPSTR_TEXTCALLBACKW) && (HIWORD((INT)toolPtr->lpszText) != 0) ) { diff --git a/reactos/lib/comctl32/treeview.c b/reactos/lib/comctl32/treeview.c index 41147d3f4de..b15d1c117c4 100644 --- a/reactos/lib/comctl32/treeview.c +++ b/reactos/lib/comctl32/treeview.c @@ -2289,8 +2289,8 @@ TREEVIEW_DrawItemLines(TREEVIEW_INFO *infoPtr, HDC hdc, TREEVIEW_ITEM *item) HBRUSH hbr = CreateSolidBrush(infoPtr->clrBk); HBRUSH hbrOld = SelectObject(hdc, hbr); - Rectangle(hdc, centerx - rectsize, centery - rectsize, - centerx + rectsize + 1, centery + rectsize + 1); + Rectangle(hdc, centerx - rectsize - 1, centery - rectsize - 1, + centerx + rectsize + 2, centery + rectsize + 2); SelectObject(hdc, hbrOld); DeleteObject(hbr); @@ -2599,7 +2599,7 @@ TREEVIEW_UpdateScrollBars(TREEVIEW_INFO *infoPtr) if (vert) { si.nPage = TREEVIEW_GetVisibleCount(infoPtr); - if ( si.nPage ) + if ( si.nPage && NULL != infoPtr->firstVisible) { si.nPos = infoPtr->firstVisible->visibleOrder; si.nMax = infoPtr->maxVisibleOrder - 1; diff --git a/reactos/lib/comctl32/winehq2ros.patch b/reactos/lib/comctl32/winehq2ros.patch index e69de29bb2d..1ec16ac12d0 100644 --- a/reactos/lib/comctl32/winehq2ros.patch +++ b/reactos/lib/comctl32/winehq2ros.patch @@ -0,0 +1,104 @@ +Index: comctl32.spec +=================================================================== +RCS file: /home/wine/wine/dlls/comctl32/comctl32.spec,v +retrieving revision 1.43 +diff -u -r1.43 comctl32.spec +--- comctl32.spec 20 Feb 2004 05:16:37 -0000 1.43 ++++ comctl32.spec 11 Mar 2004 11:16:16 -0000 +@@ -106,13 +106,13 @@ + 412 stdcall RemoveWindowSubclass(long ptr long) + 413 stdcall DefSubclassProc(long long long long) + 414 stub -noname MirrorIcon +-415 stdcall -noname DrawTextWrap(long wstr long ptr long) user32.DrawTextW +-416 stdcall -noname DrawTextExPrivWrap(long wstr long ptr long ptr) user32.DrawTextExW +-417 stdcall -noname ExtTextOutWrap(long long long long ptr wstr long ptr) gdi32.ExtTextOutW +-418 stdcall -noname GetCharWidthWrap(long long long long) gdi32.GetCharWidthW +-419 stdcall -noname GetTextExtentPointWrap(long wstr long ptr) gdi32.GetTextExtentPointW +-420 stdcall -noname GetTextExtentPoint32Wrap(long wstr long ptr) gdi32.GetTextExtentPoint32W +-421 stdcall -noname TextOutWrap(long long long wstr long) gdi32.TextOutW ++415 stdcall DrawTextWrap(long wstr long ptr long) user32.DrawTextW ++416 stdcall DrawTextExPrivWrap(long wstr long ptr long ptr) user32.DrawTextExW ++417 stdcall ExtTextOutWrap(long long long long ptr wstr long ptr) gdi32.ExtTextOutW ++418 stdcall GetCharWidthWrap(long long long long) gdi32.GetCharWidthW ++419 stdcall GetTextExtentPointWrap(long wstr long ptr) gdi32.GetTextExtentPointW ++420 stdcall GetTextExtentPoint32Wrap(long wstr long ptr) gdi32.GetTextExtentPoint32W ++421 stdcall TextOutWrap(long long long wstr long) gdi32.TextOutW + + # Functions imported by name + +Index: rebar.c +=================================================================== +RCS file: /home/wine/wine/dlls/comctl32/rebar.c,v +retrieving revision 1.85 +diff -u -r1.85 rebar.c +--- rebar.c 27 Feb 2004 04:32:54 -0000 1.85 ++++ rebar.c 11 Mar 2004 11:16:19 -0000 +@@ -985,7 +985,7 @@ + } + + /* text is visible */ +- if (lpBand->fStatus & HAS_TEXT) { ++ if ((lpBand->fStatus & HAS_TEXT) && !(lpBand->fStyle & RBBS_HIDETITLE)) { + lpBand->fDraw |= DRAW_TEXT; + lpBand->rcCapText.right = max(lpBand->rcCapText.left, + lpBand->rcCapText.right-REBAR_POST_TEXT); +@@ -1131,7 +1131,7 @@ + } + + /* text is visible */ +- if (lpBand->fStatus & HAS_TEXT) { ++ if ((lpBand->fStatus & HAS_TEXT) && !(lpBand->fStyle & RBBS_HIDETITLE)) { + lpBand->fDraw |= DRAW_TEXT; + lpBand->rcCapText.bottom = max(lpBand->rcCapText.top, + lpBand->rcCapText.bottom); +@@ -2027,7 +2027,8 @@ + } + + /* text is visible */ +- if ((lpBand->fMask & RBBIM_TEXT) && (lpBand->lpText)) { ++ if ((lpBand->fMask & RBBIM_TEXT) && (lpBand->lpText) && ++ !(lpBand->fStyle & RBBS_HIDETITLE)) { + HDC hdc = GetDC (0); + HFONT hOldFont = SelectObject (hdc, infoPtr->hFont); + SIZE size; +Index: string.c +=================================================================== +RCS file: /home/wine/wine/dlls/comctl32/string.c,v +retrieving revision 1.3 +diff -u -r1.3 string.c +--- string.c 20 Feb 2004 19:58:39 -0000 1.3 ++++ string.c 11 Mar 2004 11:16:19 -0000 +@@ -254,7 +254,7 @@ + { + TRACE("(%s,%s)\n", debugstr_w(lpszStr), debugstr_w(lpszSearch)); + +- return COMCTL32_StrStrHelperW(lpszStr, lpszSearch, strncmpiW); ++ return COMCTL32_StrStrHelperW(lpszStr, lpszSearch, (int (*)(LPCWSTR,LPCWSTR,int)) wcsnicmp); + } + + /************************************************************************** +@@ -503,7 +503,7 @@ + { + TRACE("(%s,%s)\n", debugstr_w(lpszStr), debugstr_w(lpszSearch)); + +- return COMCTL32_StrStrHelperW(lpszStr, lpszSearch, strncmpW); ++ return COMCTL32_StrStrHelperW(lpszStr, lpszSearch, (int (*)(LPCWSTR,LPCWSTR,int)) wcsncmp); + } + + /************************************************************************* +Index: toolbar.c +=================================================================== +RCS file: /home/wine/wine/dlls/comctl32/toolbar.c,v +retrieving revision 1.160 +diff -u -r1.160 toolbar.c +--- toolbar.c 7 Mar 2004 03:13:26 -0000 1.160 ++++ toolbar.c 11 Mar 2004 11:16:21 -0000 +@@ -2299,7 +2299,7 @@ + TRACE ("creating default image list!\n"); + + himlDef = ImageList_Create (infoPtr->nBitmapWidth, infoPtr->nBitmapHeight, +- ILC_COLOR | ILC_MASK, nButtons, 2); ++ ILC_COLORDDB | ILC_MASK, nButtons, 2); + TOOLBAR_InsertImageList(&infoPtr->himlDef, &infoPtr->cimlDef, himlDef, 0); + infoPtr->himlInt = himlDef; + } diff --git a/reactos/w32api/include/commctrl.h b/reactos/w32api/include/commctrl.h index 6917cb26ab3..e60656d192d 100644 --- a/reactos/w32api/include/commctrl.h +++ b/reactos/w32api/include/commctrl.h @@ -605,6 +605,8 @@ extern "C" { #define TB_SETINSERTMARKCOLOR (WM_USER+88) #define TB_GETINSERTMARKCOLOR (WM_USER+89) #define TB_MAPACCELERATORW (WM_USER+90) +#define TB_GETSTRINGW (WM_USER+91) +#define TB_GETSTRINGA (WM_USER+92) #define TB_SETCOLORSCHEME CCM_SETCOLORSCHEME #define TB_GETCOLORSCHEME CCM_GETCOLORSCHEME #define TB_SETUNICODEFORMAT CCM_SETUNICODEFORMAT @@ -3235,6 +3237,7 @@ typedef NMHDDISPINFOW NMHDDISPINFO, *LPNMHDDISPINFO; #define TB_INSERTBUTTON TB_INSERTBUTTONW #define TB_ADDBUTTONS TB_ADDBUTTONSW #define TB_MAPACCELERATOR TB_MAPACCELERATORW +#define TB_GETSTRING TB_GETSTRINGW #define TBBUTTONINFO TBBUTTONINFOW #define LPTBBUTTONINFO LPTBBUTTONINFOW #define TBN_GETDISPINFO TBN_GETDISPINFOW @@ -3372,6 +3375,7 @@ typedef NMHDDISPINFOW NMHDDISPINFO, *LPNMHDDISPINFO; #define TB_INSERTBUTTON TB_INSERTBUTTONA #define TB_ADDBUTTONS TB_ADDBUTTONSA #define TB_MAPACCELERATOR TB_MAPACCELERATORA +#define TB_GETSTRING TB_GETSTRINGA #define NMCOMBOBOXEX NMCOMBOBOXEXA #define PNMCOMBOBOXEX PNMCOMBOBOXEXA #define CBEN_DRAGBEGIN CBEN_DRAGBEGINA