Sync to Wine-20040309:

Robert Shearman <R.J.Shearman@warwick.ac.uk>
- 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 <maxime.bellenge@laposte.net>
- Fix a regression in ImageList_Create when creating a dibsection.
Ulrich Czekalla <ulrich@codeweavers.com>
- Use dibsections for the images.
Dimitrie O. Paun <dpaun@rogers.com>
- LVN_BEGINRDRAG is implemented now. Fix typo.
Aric Stewart <aric@codeweavers.com>
- Implemented LISTVIEW_ApproximateViewRect for LVS_REPORT.
Fabian Cenedese <Cenedese@indel.ch>
- 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 <matthewc@cse.unsw.edu.au>
- 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 <wine-patch@kievinfo.com>
- 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 <huw@codeweavers.com>
- 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 <titan.costa@wanadoo.fr>
- Accept null module instance, Loadstring can handle it.
Steve Lustbader <slustbader@verizon.net>
- Handle the firstVisible item being NULL in
Mike Hearn <mike@theoretic.com>
- Grow the treeview control expander button by 1px in each direction to
  match the native look.

svn path=/trunk/; revision=8639
This commit is contained in:
Gé van Geldorp 2004-03-11 11:13:28 +00:00
parent 8e37499a90
commit 6477510568
21 changed files with 2009 additions and 697 deletions

View file

@ -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)

View file

@ -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 \

View file

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

View file

@ -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

View file

@ -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 <stdarg.h>
#include <string.h>
#include <stdlib.h> /* atoi */
#include <ctype.h>
#include <limits.h>
@ -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;
}

View file

@ -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;

View file

@ -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 <ekohl@abo.rhein-zeitung.de>
*
* TODO:
* - Everything.
*/
#include <stdarg.h>
@ -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

View file

@ -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)

View file

@ -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;
}

View file

@ -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)
{

View file

@ -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)
{

View file

@ -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);

View file

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

View file

@ -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;

View file

@ -0,0 +1,853 @@
/*
* String manipulation functions
*
* Copyright 1998 Eric Kohl
* 1998 Juergen Schmied <j.schmied@metronet.de>
* 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 <stdarg.h>
#include <string.h>
#include <stdlib.h> /* 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;
}

View file

@ -33,8 +33,6 @@
* TCM_GETEXTENDEDSTYLE
* TCM_SETEXTENDEDSTYLE
*
* FIXME:
* UpDown control not displayed until after a tab is clicked on
*/
#include <stdarg.h>
@ -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("<left> item=%d, fill=(%ld,%ld)-(%ld,%ld), edge=(%ld,%ld)-(%ld,%ld)\n",
TRACE("<right> 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("<left> 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("<bottom> 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("<top> 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);
}

View file

@ -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);

View file

@ -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) )
{

View file

@ -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;

View file

@ -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;
}

View file

@ -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