* Sync up to trunk HEAD (r62502).
authorAmine Khaldi <amine.khaldi@reactos.org>
Sat, 15 Mar 2014 14:56:08 +0000 (14:56 +0000)
committerAmine Khaldi <amine.khaldi@reactos.org>
Sat, 15 Mar 2014 14:56:08 +0000 (14:56 +0000)
svn path=/branches/shell-experiments/; revision=62503

436 files changed:
1  2 
CMakeLists.txt
base/applications/calc/lang/tr-TR.rc
base/applications/charmap/lang/tr-TR.rc
base/applications/cmdutils/help/help.c
base/applications/games/solitaire/lang/tr-TR.rc
base/applications/games/solitaire/rsrc.rc
base/applications/games/spider/lang/tr-TR.rc
base/applications/games/spider/rsrc.rc
base/applications/games/winmine/lang/tr-TR.rc
base/applications/games/winmine/rsrc.rc
base/applications/magnify/lang/tr-TR.rc
base/applications/magnify/magnify.rc
base/applications/msconfig/lang/tr-TR.rc
base/applications/mscutils/devmgmt/lang/tr-TR.rc
base/applications/mscutils/devmgmt_new/lang/tr-TR.rc
base/applications/mscutils/eventvwr/lang/tr-TR.rc
base/applications/mscutils/servman/lang/tr-TR.rc
base/applications/mspaint/lang/tr-TR.rc
base/applications/network/ftp/cmds.c
base/applications/notepad/lang/tr-TR.rc
base/applications/notepad/rsrc.rc
base/applications/rapps/lang/tr-TR.rc
base/applications/rapps/rapps/rosbe.txt
base/applications/regedit/lang/tr-TR.rc
base/applications/winhlp32/lang/Tr.rc
base/applications/wordpad/lang/Tr.rc
base/setup/usetup/interface/usetup.c
base/shell/cmd/console.c
base/system/services/rpcserver.c
boot/bootdata/hivecls.inf
boot/bootdata/hivesys.inf
boot/freeldr/fdebug/lang/tr-TR.rc
cmake/CMakeMacros.cmake
cmake/gcc.cmake
cmake/msvc.cmake
configure.cmd
dll/3rdparty/libxslt/CMakeLists.txt
dll/cpl/desk/lang/tr-TR.rc
dll/cpl/input/lang/tr-TR.rc
dll/cpl/intl/lang/tr-TR.rc
dll/cpl/main/lang/tr-TR.rc
dll/directx/wine/d3d8/CMakeLists.txt
dll/directx/wine/d3d9/CMakeLists.txt
dll/directx/wine/ddraw/CMakeLists.txt
dll/directx/wine/dinput/CMakeLists.txt
dll/directx/wine/dinput8/CMakeLists.txt
dll/ntdll/CMakeLists.txt
dll/ntdll/ldr/ldrapi.c
dll/opengl/opengl32/CMakeLists.txt
dll/opengl/opengl32/wgl.c
dll/win32/advapi32/service/sctrl.c
dll/win32/browseui/browseui.rc
dll/win32/browseui/lang/de-DE.rc
dll/win32/cards/cards.c
dll/win32/cards/cards.h
dll/win32/comctl32/toolbar.c
dll/win32/crypt32/lang/crypt32_Tr.rc
dll/win32/cryptui/lang/cryptui_Tr.rc
dll/win32/devmgr/devmgr.rc
dll/win32/devmgr/lang/tr-TR.rc
dll/win32/hhctrl.ocx/hhctrl.rc
dll/win32/hhctrl.ocx/lang/Tr.rc
dll/win32/iccvid/lang/iccvid_Tr.rc
dll/win32/iccvid/rsrc.rc
dll/win32/iphlpapi/CMakeLists.txt
dll/win32/iphlpapi/iphlpapi_main.c
dll/win32/kernel32/CMakeLists.txt
dll/win32/kernel32/client/console/console.c
dll/win32/kernel32/client/loader.c
dll/win32/kernel32/client/proc.c
dll/win32/kernel32/client/synch.c
dll/win32/kernel32/client/thread.c
dll/win32/msgina/gui.c
dll/win32/msgina/lang/bg-BG.rc
dll/win32/msgina/lang/cs-CZ.rc
dll/win32/msgina/lang/de-DE.rc
dll/win32/msgina/lang/en-US.rc
dll/win32/msgina/lang/es-ES.rc
dll/win32/msgina/lang/fr-FR.rc
dll/win32/msgina/lang/he-IL.rc
dll/win32/msgina/lang/id-ID.rc
dll/win32/msgina/lang/it-IT.rc
dll/win32/msgina/lang/ja-JP.rc
dll/win32/msgina/lang/no-NO.rc
dll/win32/msgina/lang/pl-PL.rc
dll/win32/msgina/lang/ro-RO.rc
dll/win32/msgina/lang/ru-RU.rc
dll/win32/msgina/lang/sk-SK.rc
dll/win32/msgina/lang/sq-AL.rc
dll/win32/msgina/lang/tr-TR.rc
dll/win32/msgina/lang/uk-UA.rc
dll/win32/msgina/lsa.c
dll/win32/msgina/msgina.c
dll/win32/msgina/msgina.h
dll/win32/msgina/resource.h
dll/win32/msgina/tui.c
dll/win32/msv1_0/msv1_0.c
dll/win32/msxml3/CMakeLists.txt
dll/win32/netapi32/user.c
dll/win32/shell32/CMakeLists.txt
dll/win32/shell32/CMenuDeskBar.cpp
dll/win32/shell32/changenotify.cpp
dll/win32/shell32/defcontextmenu.cpp
dll/win32/shell32/dragdrophelper.cpp
dll/win32/shell32/dragdrophelper.h
dll/win32/shell32/droptargets/CexeDropHandler.cpp
dll/win32/shell32/droptargets/CexeDropHandler.h
dll/win32/shell32/folders.cpp
dll/win32/shell32/folders/desktop.cpp
dll/win32/shell32/folders/desktop.h
dll/win32/shell32/folders/fs.cpp
dll/win32/shell32/folders/fs.h
dll/win32/shell32/folders/mydocuments.cpp
dll/win32/shell32/folders/mydocuments.h
dll/win32/shell32/folders/recyclebin.cpp
dll/win32/shell32/precomp.h
dll/win32/shell32/res/rgs/exedrophandler.rgs
dll/win32/shell32/rgs_res.rc
dll/win32/shell32/shell32_main.cpp
dll/win32/shell32/shelllink.cpp
dll/win32/shell32/shelllink.h
dll/win32/shell32/shellord.cpp
dll/win32/shell32/shellpath.cpp
dll/win32/shell32/shfldr.h
dll/win32/shell32/shlexec.cpp
dll/win32/shell32/shlfileop.cpp
dll/win32/shell32/shlview.cpp
dll/win32/shell32/shpolicy.cpp
dll/win32/shell32/shresdef.h
dll/win32/winmm/CMakeLists.txt
dll/win32/winmm/joystick.c
dll/win32/xinput1_3/CMakeLists.txt
dll/win32/xinput1_3/xinput1_3_main.c
drivers/bus/acpi/buspdo.c
drivers/bus/acpi/main.c
drivers/filesystems/ext2/src/ext2init.c
drivers/filesystems/ext2/src/fsctrl.c
drivers/filesystems/fastfat/cleanup.c
drivers/filesystems/fastfat/create.c
drivers/filesystems/fastfat/dir.c
drivers/filesystems/fastfat/fsctl.c
drivers/filesystems/fastfat/rw.c
drivers/filesystems/fastfat/vfat.h
drivers/filesystems/fs_rec/ext2.c
drivers/filesystems/fs_rec/fs_rec.c
drivers/filesystems/npfs/main.c
drivers/storage/ide/uniata/bm_devs.h
drivers/storage/ide/uniata/bsmaster.h
drivers/storage/ide/uniata/id_ata.cpp
drivers/storage/ide/uniata/id_dma.cpp
drivers/storage/ide/uniata/id_init.cpp
drivers/storage/ide/uniata/id_sata.cpp
drivers/storage/ide/uniata/uniata_ver.h
include/crt/_mingw.h
include/crt/mingw32/intrin_x86.h
include/ndk/vffuncs.h
include/psdk/commctrl.h
include/psdk/guiddef.h
include/psdk/intsafe.h
include/psdk/shellapi.h
include/psdk/shlguid_undoc.h
include/psdk/strsafe.h
include/psdk/wincon.h
include/psdk/winternl.h
include/reactos/libs/pseh/pseh3.h
include/reactos/subsys/win/conmsg.h
include/reactos/wine/commctrl.h
include/reactos/wine/config.h
include/reactos/wine/test.h
lib/3rdparty/CMakeLists.txt
lib/3rdparty/cardlib/CMakeLists.txt
lib/3rdparty/freetype/CMakeLists.txt
lib/3rdparty/freetype/ChangeLog
lib/3rdparty/freetype/README
lib/3rdparty/freetype/autogen.sh
lib/3rdparty/freetype/devel/ft2build.h
lib/3rdparty/freetype/devel/ftoption.h
lib/3rdparty/freetype/include/config/ftconfig.h
lib/3rdparty/freetype/include/config/ftheader.h
lib/3rdparty/freetype/include/config/ftmodule.h
lib/3rdparty/freetype/include/config/ftoption.h
lib/3rdparty/freetype/include/config/ftstdlib.h
lib/3rdparty/freetype/include/freetype.h
lib/3rdparty/freetype/include/ft2build.h
lib/3rdparty/freetype/include/ftadvanc.h
lib/3rdparty/freetype/include/ftautoh.h
lib/3rdparty/freetype/include/ftbbox.h
lib/3rdparty/freetype/include/ftbdf.h
lib/3rdparty/freetype/include/ftbitmap.h
lib/3rdparty/freetype/include/ftbzip2.h
lib/3rdparty/freetype/include/ftcache.h
lib/3rdparty/freetype/include/ftcffdrv.h
lib/3rdparty/freetype/include/ftchapters.h
lib/3rdparty/freetype/include/ftcid.h
lib/3rdparty/freetype/include/fterrdef.h
lib/3rdparty/freetype/include/fterrors.h
lib/3rdparty/freetype/include/ftgasp.h
lib/3rdparty/freetype/include/ftglyph.h
lib/3rdparty/freetype/include/ftgxval.h
lib/3rdparty/freetype/include/ftgzip.h
lib/3rdparty/freetype/include/ftimage.h
lib/3rdparty/freetype/include/ftincrem.h
lib/3rdparty/freetype/include/ftlcdfil.h
lib/3rdparty/freetype/include/ftlist.h
lib/3rdparty/freetype/include/ftlzw.h
lib/3rdparty/freetype/include/ftmac.h
lib/3rdparty/freetype/include/ftmm.h
lib/3rdparty/freetype/include/ftmodapi.h
lib/3rdparty/freetype/include/ftmoderr.h
lib/3rdparty/freetype/include/ftotval.h
lib/3rdparty/freetype/include/ftoutln.h
lib/3rdparty/freetype/include/ftpfr.h
lib/3rdparty/freetype/include/ftrender.h
lib/3rdparty/freetype/include/ftsizes.h
lib/3rdparty/freetype/include/ftsnames.h
lib/3rdparty/freetype/include/ftstroke.h
lib/3rdparty/freetype/include/ftsynth.h
lib/3rdparty/freetype/include/ftsystem.h
lib/3rdparty/freetype/include/fttrigon.h
lib/3rdparty/freetype/include/ftttdrv.h
lib/3rdparty/freetype/include/fttypes.h
lib/3rdparty/freetype/include/ftwinfnt.h
lib/3rdparty/freetype/include/ftxf86.h
lib/3rdparty/freetype/include/internal/autohint.h
lib/3rdparty/freetype/include/internal/ftcalc.h
lib/3rdparty/freetype/include/internal/ftdebug.h
lib/3rdparty/freetype/include/internal/ftdriver.h
lib/3rdparty/freetype/include/internal/ftgloadr.h
lib/3rdparty/freetype/include/internal/ftmemory.h
lib/3rdparty/freetype/include/internal/ftobjs.h
lib/3rdparty/freetype/include/internal/ftpic.h
lib/3rdparty/freetype/include/internal/ftrfork.h
lib/3rdparty/freetype/include/internal/ftserv.h
lib/3rdparty/freetype/include/internal/ftstream.h
lib/3rdparty/freetype/include/internal/fttrace.h
lib/3rdparty/freetype/include/internal/ftvalid.h
lib/3rdparty/freetype/include/internal/internal.h
lib/3rdparty/freetype/include/internal/psaux.h
lib/3rdparty/freetype/include/internal/pshints.h
lib/3rdparty/freetype/include/internal/services/svbdf.h
lib/3rdparty/freetype/include/internal/services/svcid.h
lib/3rdparty/freetype/include/internal/services/svgldict.h
lib/3rdparty/freetype/include/internal/services/svgxval.h
lib/3rdparty/freetype/include/internal/services/svkern.h
lib/3rdparty/freetype/include/internal/services/svmm.h
lib/3rdparty/freetype/include/internal/services/svotval.h
lib/3rdparty/freetype/include/internal/services/svpfr.h
lib/3rdparty/freetype/include/internal/services/svpostnm.h
lib/3rdparty/freetype/include/internal/services/svprop.h
lib/3rdparty/freetype/include/internal/services/svpscmap.h
lib/3rdparty/freetype/include/internal/services/svpsinfo.h
lib/3rdparty/freetype/include/internal/services/svsfnt.h
lib/3rdparty/freetype/include/internal/services/svttcmap.h
lib/3rdparty/freetype/include/internal/services/svtteng.h
lib/3rdparty/freetype/include/internal/services/svttglyf.h
lib/3rdparty/freetype/include/internal/services/svwinfnt.h
lib/3rdparty/freetype/include/internal/services/svxf86nm.h
lib/3rdparty/freetype/include/internal/sfnt.h
lib/3rdparty/freetype/include/internal/t1types.h
lib/3rdparty/freetype/include/internal/tttypes.h
lib/3rdparty/freetype/include/t1tables.h
lib/3rdparty/freetype/include/ttnameid.h
lib/3rdparty/freetype/include/tttables.h
lib/3rdparty/freetype/include/tttags.h
lib/3rdparty/freetype/include/ttunpat.h
lib/3rdparty/freetype/modules.cfg
lib/3rdparty/freetype/objs/README
lib/3rdparty/freetype/src/autofit/afblue.c
lib/3rdparty/freetype/src/autofit/afblue.cin
lib/3rdparty/freetype/src/autofit/afblue.dat
lib/3rdparty/freetype/src/autofit/afblue.h
lib/3rdparty/freetype/src/autofit/afblue.hin
lib/3rdparty/freetype/src/autofit/afcjk.c
lib/3rdparty/freetype/src/autofit/afcjk.h
lib/3rdparty/freetype/src/autofit/afdummy.c
lib/3rdparty/freetype/src/autofit/afdummy.h
lib/3rdparty/freetype/src/autofit/afglobal.c
lib/3rdparty/freetype/src/autofit/afglobal.h
lib/3rdparty/freetype/src/autofit/afhints.c
lib/3rdparty/freetype/src/autofit/afhints.h
lib/3rdparty/freetype/src/autofit/afindic.c
lib/3rdparty/freetype/src/autofit/afindic.h
lib/3rdparty/freetype/src/autofit/aflatin.c
lib/3rdparty/freetype/src/autofit/aflatin.h
lib/3rdparty/freetype/src/autofit/aflatin2.c
lib/3rdparty/freetype/src/autofit/aflatin2.h
lib/3rdparty/freetype/src/autofit/afloader.c
lib/3rdparty/freetype/src/autofit/afpic.c
lib/3rdparty/freetype/src/autofit/afpic.h
lib/3rdparty/freetype/src/autofit/afscript.h
lib/3rdparty/freetype/src/autofit/aftypes.h
lib/3rdparty/freetype/src/autofit/afwrtsys.h
lib/3rdparty/freetype/src/autofit/autofit.c
lib/3rdparty/freetype/src/autofit/rules.mk
lib/3rdparty/freetype/src/base/ftbbox.c
lib/3rdparty/freetype/src/base/ftbitmap.c
lib/3rdparty/freetype/src/base/ftcalc.c
lib/3rdparty/freetype/src/base/ftdebug.c
lib/3rdparty/freetype/src/base/ftglyph.c
lib/3rdparty/freetype/src/base/ftinit.c
lib/3rdparty/freetype/src/base/ftmac.c
lib/3rdparty/freetype/src/base/ftobjs.c
lib/3rdparty/freetype/src/base/ftoutln.c
lib/3rdparty/freetype/src/base/ftpic.c
lib/3rdparty/freetype/src/base/ftsynth.c
lib/3rdparty/freetype/src/base/md5.c
lib/3rdparty/freetype/src/base/md5.h
lib/3rdparty/freetype/src/base/rules.mk
lib/3rdparty/freetype/src/bdf/bdfdrivr.c
lib/3rdparty/freetype/src/cff/cf2blues.c
lib/3rdparty/freetype/src/cff/cf2font.c
lib/3rdparty/freetype/src/cff/cf2font.h
lib/3rdparty/freetype/src/cff/cf2ft.c
lib/3rdparty/freetype/src/cff/cf2hints.c
lib/3rdparty/freetype/src/cff/cf2hints.h
lib/3rdparty/freetype/src/cff/cffdrivr.c
lib/3rdparty/freetype/src/cff/cffgload.c
lib/3rdparty/freetype/src/cff/cffload.c
lib/3rdparty/freetype/src/cff/cffobjs.c
lib/3rdparty/freetype/src/cff/cffobjs.h
lib/3rdparty/freetype/src/cid/cidgload.c
lib/3rdparty/freetype/src/cid/cidload.c
lib/3rdparty/freetype/src/gxvalid/gxvcommn.c
lib/3rdparty/freetype/src/gxvalid/gxvcommn.h
lib/3rdparty/freetype/src/gxvalid/gxvmort.c
lib/3rdparty/freetype/src/gxvalid/gxvmorx2.c
lib/3rdparty/freetype/src/gzip/ftgzip.c
lib/3rdparty/freetype/src/gzip/rules.mk
lib/3rdparty/freetype/src/pcf/pcfdrivr.c
lib/3rdparty/freetype/src/pcf/pcfread.c
lib/3rdparty/freetype/src/pcf/pcfutil.c
lib/3rdparty/freetype/src/pfr/pfrcmap.c
lib/3rdparty/freetype/src/pfr/pfrgload.c
lib/3rdparty/freetype/src/pfr/pfrobjs.c
lib/3rdparty/freetype/src/pshinter/pshglob.c
lib/3rdparty/freetype/src/raster/ftraster.c
lib/3rdparty/freetype/src/sfnt/pngshim.c
lib/3rdparty/freetype/src/sfnt/pngshim.h
lib/3rdparty/freetype/src/sfnt/sfdriver.c
lib/3rdparty/freetype/src/sfnt/sfobjs.c
lib/3rdparty/freetype/src/sfnt/ttcmap.c
lib/3rdparty/freetype/src/sfnt/ttkern.c
lib/3rdparty/freetype/src/sfnt/ttload.c
lib/3rdparty/freetype/src/sfnt/ttmtx.c
lib/3rdparty/freetype/src/sfnt/ttsbit.c
lib/3rdparty/freetype/src/sfnt/ttsbit.h
lib/3rdparty/freetype/src/smooth/ftgrays.c
lib/3rdparty/freetype/src/tools/afblue.pl
lib/3rdparty/freetype/src/tools/chktrcmp.py
lib/3rdparty/freetype/src/tools/docmaker/content.py
lib/3rdparty/freetype/src/tools/docmaker/docmaker.py
lib/3rdparty/freetype/src/tools/docmaker/sources.py
lib/3rdparty/freetype/src/tools/docmaker/tohtml.py
lib/3rdparty/freetype/src/truetype/ttdriver.c
lib/3rdparty/freetype/src/truetype/ttgload.c
lib/3rdparty/freetype/src/truetype/ttgload.h
lib/3rdparty/freetype/src/truetype/ttinterp.c
lib/3rdparty/freetype/src/truetype/ttinterp.h
lib/3rdparty/freetype/src/truetype/ttobjs.c
lib/3rdparty/freetype/src/type1/t1gload.c
lib/3rdparty/freetype/src/type1/t1load.c
lib/3rdparty/freetype/src/type42/t42objs.c
lib/3rdparty/freetype/src/winfonts/winfnt.c
lib/3rdparty/libwin-iconv/CMakeLists.txt
lib/3rdparty/libwin-iconv/ChangeLog
lib/3rdparty/libwin-iconv/iconv.def
lib/3rdparty/libwin-iconv/iconv.h
lib/3rdparty/libwin-iconv/mlang.def
lib/3rdparty/libwin-iconv/mlang.h
lib/3rdparty/libwin-iconv/readme.txt
lib/3rdparty/libwin-iconv/win_iconv.c
lib/3rdparty/libwin-iconv/win_iconv_test.c
lib/3rdparty/libxml2/CMakeLists.txt
lib/atl/atlwin.h
lib/fslib/vfatlib/CMakeLists.txt
lib/fslib/vfatlib/check/io.c
lib/fslib/vfatlib/check/lfn.c
lib/fslib/vfatlib/vfatlib.h
lib/lsalib/lsa.c
lib/pseh/i386/pseh3.c
lib/pseh/i386/pseh3_asmdef.h
lib/pseh/i386/pseh3_i386.S
media/doc/3rd Party Files.txt
ntoskrnl/config/cmapi.c
ntoskrnl/fsrtl/notify.c
ntoskrnl/include/internal/fsrtl.h
ntoskrnl/include/internal/mm.h
ntoskrnl/ke/bug.c
ntoskrnl/ke/powerpc/kiinit.c
ntoskrnl/ke/powerpc/stubs.c
ntoskrnl/mm/ARM3/expool.c
ntoskrnl/mm/ARM3/virtual.c
ntoskrnl/mm/amd64/page.c
ntoskrnl/mm/arm/page.c
ntoskrnl/mm/arm/stubs.c
ntoskrnl/mm/freelist.c
ntoskrnl/mm/i386/page.c
ntoskrnl/mm/i386/pagepae.c
ntoskrnl/mm/marea.c
ntoskrnl/mm/pagefile.c
ntoskrnl/mm/powerpc/page.c
toolchain-clang.cmake
win32ss/gdi/ntgdi/freetype.c
win32ss/user/ntuser/focus.c
win32ss/user/ntuser/msgqueue.c
win32ss/user/ntuser/object.c
win32ss/user/ntuser/object.h
win32ss/user/ntuser/window.c
win32ss/user/ntuser/winpos.c
win32ss/user/ntuser/winpos.h
win32ss/user/user32/CMakeLists.txt
win32ss/user/user32/controls/listbox.c
win32ss/user/user32/controls/scrollbar.c
win32ss/user/user32/misc/stubs.c
win32ss/user/user32/windows/class.c
win32ss/user/user32/windows/cursoricon.c
win32ss/user/user32/windows/defwnd.c
win32ss/user/user32/windows/font.c
win32ss/user/user32/windows/input.c
win32ss/user/user32/windows/message.c
win32ss/user/user32/windows/nonclient.c
win32ss/user/user32/windows/window.c
win32ss/user/user32/windows/winpos.c
win32ss/user/winsrv/consrv/condrv/console.c
win32ss/user/winsrv/consrv/condrv/dummyfrontend.c
win32ss/user/winsrv/consrv/condrv/text.c
win32ss/user/winsrv/consrv/conoutput.c
win32ss/user/winsrv/consrv/console.c
win32ss/user/winsrv/consrv/frontendctl.c
win32ss/user/winsrv/consrv/frontends/gui/guisettings.h
win32ss/user/winsrv/consrv/frontends/gui/guiterm.c
win32ss/user/winsrv/consrv/frontends/gui/resource.h
win32ss/user/winsrv/consrv/frontends/tui/tuiterm.c
win32ss/user/winsrv/consrv/handle.c
win32ss/user/winsrv/consrv/include/conio.h
win32ss/user/winsrv/consrv/include/term.h

diff --cc CMakeLists.txt
Simple merge
Simple merge
Simple merge
Simple merge
Simple merge
Simple merge
Simple merge
Simple merge
Simple merge
Simple merge
Simple merge
Simple merge
Simple merge
Simple merge
Simple merge
diff --cc cmake/gcc.cmake
Simple merge
Simple merge
diff --cc configure.cmd
Simple merge
Simple merge
Simple merge
Simple merge
Simple merge
Simple merge
Simple merge
Simple merge
Simple merge
Simple merge
Simple merge
Simple merge
Simple merge
Simple merge
Simple merge
index 0000000,d5bb0fd..d5bb0fd
mode 000000,100644..100644
--- /dev/null
Simple merge
Simple merge
index f2ffab6,0000000..62f7c38
mode 100644,000000..100644
--- /dev/null
@@@ -1,6925 -1,0 +1,6925 @@@
-                         TBSTYLE_EX_UNDOC1 | \
 +/*
 + * Toolbar control
 + *
 + * Copyright 1998,1999 Eric Kohl
 + * Copyright 2000 Eric Kohl for CodeWeavers
 + * 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
 + * 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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
 + *
 + * NOTES
 + *
 + * This code was audited for completeness against the documented features
 + * of Comctl32.dll version 6.0 on Mar. 14, 2004, by Robert Shearman.
 + * 
 + * Unless otherwise noted, we believe this code to be complete, as per
 + * the specification mentioned above.
 + * If you discover missing features or bugs please note them below.
 + * 
 + * TODO:
 + *   - Styles:
 + *     - TBSTYLE_REGISTERDROP
 + *     - TBSTYLE_EX_DOUBLEBUFFER
 + *   - Messages:
 + *     - TB_GETMETRICS
 + *     - TB_GETOBJECT
 + *     - TB_INSERTMARKHITTEST
 + *     - TB_SAVERESTORE
 + *     - TB_SETMETRICS
 + *     - WM_WININICHANGE
 + *   - Notifications:
 + *     - NM_CHAR
 + *     - TBN_GETOBJECT
 + *     - TBN_SAVE
 + *   - Button wrapping (under construction).
 + *   - Fix TB_SETROWS and Separators.
 + *   - iListGap custom draw support.
 + *
 + * Testing:
 + *   - Run tests using Waite Group Windows95 API Bible Volume 2.
 + *     The second cdrom contains executables addstr.exe, btncount.exe,
 + *     btnstate.exe, butstrsz.exe, chkbtn.exe, chngbmp.exe, customiz.exe,
 + *     enablebtn.exe, getbmp.exe, getbtn.exe, getflags.exe, hidebtn.exe,
 + *     indetbtn.exe, insbtn.exe, pressbtn.exe, setbtnsz.exe, setcmdid.exe,
 + *     setparnt.exe, setrows.exe, toolwnd.exe.
 + *   - Microsoft's controlspy examples.
 + *   - Charles Petzold's 'Programming Windows': gadgets.exe
 + *
 + *  Differences between MSDN and actual native control operation:
 + *   1. MSDN says: "TBSTYLE_LIST: Creates a flat toolbar with button text
 + *                  to the right of the bitmap. Otherwise, this style is
 + *                  identical to TBSTYLE_FLAT."
 + *      As implemented by both v4.71 and v5.80 of the native COMCTL32.DLL
 + *      you can create a TBSTYLE_LIST without TBSTYLE_FLAT and the result
 + *      is non-flat non-transparent buttons. Therefore TBSTYLE_LIST does
 + *      *not* imply TBSTYLE_FLAT as documented.  (GA 8/2001)
 + *
 + */
 +
 +#include "comctl32.h"
 +
 +WINE_DEFAULT_DEBUG_CHANNEL(toolbar);
 +
 +static HCURSOR hCursorDrag = NULL;
 +
 +typedef struct
 +{
 +    INT iBitmap;
 +    INT idCommand;
 +    BYTE  fsState;
 +    BYTE  fsStyle;
 +    BYTE  bHot;
 +    BYTE  bDropDownPressed;
 +    DWORD_PTR dwData;
 +    INT_PTR iString;
 +    INT nRow;
 +    RECT rect;
 +    INT cx; /* manually set size */
 +} TBUTTON_INFO;
 +
 +typedef struct
 +{
 +    UINT nButtons;
 +    HINSTANCE hInst;
 +    UINT nID;
 +} TBITMAP_INFO;
 +
 +typedef struct
 +{
 +    HIMAGELIST himl;
 +    INT id;
 +} IMLENTRY, *PIMLENTRY;
 +
 +typedef struct
 +{
 +    DWORD    dwStructSize;    /* size of TBBUTTON struct */
 +    INT      nWidth;          /* width of the toolbar */
 +    RECT     client_rect;
 +    RECT     rcBound;         /* bounding rectangle */
 +    INT      nButtonHeight;
 +    INT      nButtonWidth;
 +    INT      nBitmapHeight;
 +    INT      nBitmapWidth;
 +    INT      nIndent;
 +    INT      nRows;           /* number of button rows */
 +    INT      nMaxTextRows;    /* maximum number of text rows */
 +    INT      cxMin;           /* minimum button width */
 +    INT      cxMax;           /* maximum button width */
 +    INT      nNumButtons;     /* number of buttons */
 +    INT      nNumBitmaps;     /* number of bitmaps */
 +    INT      nNumStrings;     /* number of strings */
 +    INT      nNumBitmapInfos;
 +    INT      nButtonDown;     /* toolbar button being pressed or -1 if none */
 +    INT      nButtonDrag;     /* toolbar button being dragged or -1 if none */
 +    INT      nOldHit;
 +    INT      nHotItem;        /* index of the "hot" item */
 +    SIZE     szPadding;       /* padding values around button */
 +    INT      iTopMargin;      /* the top margin */
 +    INT      iListGap;        /* default gap between text and image for toolbar with list style */
 +    HFONT    hDefaultFont;
 +    HFONT    hFont;           /* text font */
 +    HIMAGELIST himlInt;       /* image list created internally */
 +    PIMLENTRY *himlDef;       /* default image list array */
 +    INT       cimlDef;        /* default image list array count */
 +    PIMLENTRY *himlHot;       /* hot image list array */
 +    INT       cimlHot;        /* hot image list array count */
 +    PIMLENTRY *himlDis;       /* disabled image list array */
 +    INT       cimlDis;        /* disabled image list array count */
 +    HWND     hwndToolTip;     /* handle to tool tip control */
 +    HWND     hwndNotify;      /* handle to the window that gets notifications */
 +    HWND     hwndSelf;        /* my own handle */
 +    BOOL     bAnchor;         /* anchor highlight enabled */
 +    BOOL     bDoRedraw;       /* Redraw status */
 +    BOOL     bDragOutSent;    /* has TBN_DRAGOUT notification been sent for this drag? */
 +    BOOL     bUnicode;        /* Notifications are ASCII (FALSE) or Unicode (TRUE)? */
 +    BOOL     bCaptured;       /* mouse captured? */
 +    DWORD      dwStyle;       /* regular toolbar style */
 +    DWORD      dwExStyle;     /* extended toolbar style */
 +    DWORD      dwDTFlags;     /* DrawText flags */
 +
 +    COLORREF   clrInsertMark;   /* insert mark color */
 +    COLORREF   clrBtnHighlight; /* color for Flat Separator */
 +    COLORREF   clrBtnShadow;    /* color for Flag Separator */
 +    INT      iVersion;
 +    LPWSTR   pszTooltipText;    /* temporary store for a string > 80 characters
 +                                 * for TTN_GETDISPINFOW notification */
 +    TBINSERTMARK  tbim;         /* info on insertion mark */
 +    TBUTTON_INFO *buttons;      /* pointer to button array */
 +    LPWSTR       *strings;      /* pointer to string array */
 +    TBITMAP_INFO *bitmaps;
 +} TOOLBAR_INFO, *PTOOLBAR_INFO;
 +
 +
 +/* used by customization dialog */
 +typedef struct
 +{
 +    PTOOLBAR_INFO tbInfo;
 +    HWND          tbHwnd;
 +} CUSTDLG_INFO, *PCUSTDLG_INFO;
 +
 +typedef struct
 +{
 +    TBBUTTON btn;
 +    BOOL     bVirtual;
 +    BOOL     bRemovable;
 +    WCHAR    text[64];
 +} CUSTOMBUTTON, *PCUSTOMBUTTON;
 +
 +typedef enum
 +{
 +    IMAGE_LIST_DEFAULT,
 +    IMAGE_LIST_HOT,
 +    IMAGE_LIST_DISABLED
 +} IMAGE_LIST_TYPE;
 +
 +#define SEPARATOR_WIDTH    8
 +#define TOP_BORDER         2
 +#define BOTTOM_BORDER      2
 +#define DDARROW_WIDTH      11
 +#define ARROW_HEIGHT       3
 +#define INSERTMARK_WIDTH   2
 +
 +#define DEFPAD_CX 7
 +#define DEFPAD_CY 6
 +#define DEFLISTGAP 4
 +
 +/* vertical padding used in list mode when image is present */
 +#define LISTPAD_CY 9
 +
 +/* how wide to treat the bitmap if it isn't present */
 +#define NONLIST_NOTEXT_OFFSET 2
 +
 +#define TOOLBAR_NOWHERE (-1)
 +
 +/* Used to find undocumented extended styles */
 +#define TBSTYLE_EX_ALL (TBSTYLE_EX_DRAWDDARROWS | \
- * Note: TBSTYLE_WRAPABLE or TBSTYLE_EX_UNDOC1 can be used also to allow
++                        TBSTYLE_EX_VERTICAL | \
 +                        TBSTYLE_EX_MIXEDBUTTONS | \
 +                        TBSTYLE_EX_DOUBLEBUFFER | \
 +                        TBSTYLE_EX_HIDECLIPPEDBUTTONS)
 +
 +/* all of the CCS_ styles */
 +#define COMMON_STYLES (CCS_TOP|CCS_NOMOVEY|CCS_BOTTOM|CCS_NORESIZE| \
 +                       CCS_NOPARENTALIGN|CCS_ADJUSTABLE|CCS_NODIVIDER|CCS_VERT)
 +
 +#define GETIBITMAP(infoPtr, i) (infoPtr->iVersion >= 5 ? LOWORD(i) : i)
 +#define GETHIMLID(infoPtr, i) (infoPtr->iVersion >= 5 ? HIWORD(i) : 0)
 +#define GETDEFIMAGELIST(infoPtr, id) TOOLBAR_GetImageList(infoPtr->himlDef, infoPtr->cimlDef, id)
 +#define GETHOTIMAGELIST(infoPtr, id) TOOLBAR_GetImageList(infoPtr->himlHot, infoPtr->cimlHot, id)
 +#define GETDISIMAGELIST(infoPtr, id) TOOLBAR_GetImageList(infoPtr->himlDis, infoPtr->cimlDis, id)
 +
 +static const WCHAR themeClass[] = { 'T','o','o','l','b','a','r',0 };
 +
 +static BOOL TOOLBAR_GetButtonInfo(const TOOLBAR_INFO *infoPtr, NMTOOLBARW *nmtb);
 +static BOOL TOOLBAR_IsButtonRemovable(const TOOLBAR_INFO *infoPtr, int iItem, const CUSTOMBUTTON *btnInfo);
 +static HIMAGELIST TOOLBAR_GetImageList(const PIMLENTRY *pies, INT cies, INT id);
 +static PIMLENTRY TOOLBAR_GetImageListEntry(const PIMLENTRY *pies, INT cies, INT id);
 +static VOID TOOLBAR_DeleteImageList(PIMLENTRY **pies, INT *cies);
 +static HIMAGELIST TOOLBAR_InsertImageList(PIMLENTRY **pies, INT *cies, HIMAGELIST himl, INT id);
 +static LRESULT TOOLBAR_LButtonDown(TOOLBAR_INFO *infoPtr, WPARAM wParam, LPARAM lParam);
 +static void TOOLBAR_LayoutToolbar(TOOLBAR_INFO *infoPtr);
 +static LRESULT TOOLBAR_AutoSize(TOOLBAR_INFO *infoPtr);
 +static void TOOLBAR_CheckImageListIconSize(TOOLBAR_INFO *infoPtr);
 +static void TOOLBAR_TooltipAddTool(const TOOLBAR_INFO *infoPtr, const TBUTTON_INFO *button);
 +static void TOOLBAR_TooltipSetRect(const TOOLBAR_INFO *infoPtr, const TBUTTON_INFO *button);
 +
 +
 +static inline int default_top_margin(const TOOLBAR_INFO *infoPtr)
 +{
 +    return (infoPtr->dwStyle & TBSTYLE_FLAT ? 0 : TOP_BORDER);
 +}
 +
 +static inline BOOL TOOLBAR_HasDropDownArrows(DWORD exStyle)
 +{
 +    return (exStyle & TBSTYLE_EX_DRAWDDARROWS) != 0;
 +}
 +
 +static LPWSTR
 +TOOLBAR_GetText(const TOOLBAR_INFO *infoPtr, const TBUTTON_INFO *btnPtr)
 +{
 +    LPWSTR lpText = NULL;
 +
 +    /* NOTE: iString == -1 is undocumented */
 +    if (!IS_INTRESOURCE(btnPtr->iString) && (btnPtr->iString != -1))
 +        lpText = (LPWSTR)btnPtr->iString;
 +    else if ((btnPtr->iString >= 0) && (btnPtr->iString < infoPtr->nNumStrings))
 +        lpText = infoPtr->strings[btnPtr->iString];
 +
 +    return lpText;
 +}
 +
 +static void
 +TOOLBAR_DumpTBButton(const TBBUTTON *tbb, BOOL fUnicode)
 +{
 +    TRACE("TBBUTTON: id %d, bitmap=%d, state=%02x, style=%02x, data=%08lx, stringid=0x%08lx (%s)\n",
 +          tbb->idCommand,tbb->iBitmap, tbb->fsState, tbb->fsStyle, tbb->dwData, tbb->iString,
 +          (fUnicode ? wine_dbgstr_w((LPWSTR)tbb->iString) : wine_dbgstr_a((LPSTR)tbb->iString)));
 +}
 +
 +static void
 +TOOLBAR_DumpButton(const TOOLBAR_INFO *infoPtr, const TBUTTON_INFO *bP, INT btn_num)
 +{
 +    if (TRACE_ON(toolbar)){
 +        TRACE("button %d id %d, bitmap=%d, state=%02x, style=%02x, data=%08lx, stringid=0x%08lx\n",
 +              btn_num, bP->idCommand, GETIBITMAP(infoPtr, bP->iBitmap), 
 +              bP->fsState, bP->fsStyle, bP->dwData, bP->iString);
 +      TRACE("string %s\n", debugstr_w(TOOLBAR_GetText(infoPtr,bP)));
 +        TRACE("button %d id %d, hot=%s, row=%d, rect=(%s)\n",
 +              btn_num, bP->idCommand, (bP->bHot) ? "TRUE":"FALSE", bP->nRow,
 +              wine_dbgstr_rect(&bP->rect));
 +    }
 +}
 +
 +
 +static void
 +TOOLBAR_DumpToolbar(const TOOLBAR_INFO *iP, INT line)
 +{
 +    if (TRACE_ON(toolbar)) {
 +      INT i;
 +
 +      TRACE("toolbar %p at line %d, exStyle=%08x, buttons=%d, bitmaps=%d, strings=%d, style=%08x\n",
 +            iP->hwndSelf, line,
 +            iP->dwExStyle, iP->nNumButtons, iP->nNumBitmaps,
 +            iP->nNumStrings, iP->dwStyle);
 +      TRACE("toolbar %p at line %d, himlInt=%p, himlDef=%p, himlHot=%p, himlDis=%p, redrawable=%s\n",
 +            iP->hwndSelf, line,
 +            iP->himlInt, iP->himlDef, iP->himlHot, iP->himlDis,
 +            (iP->bDoRedraw) ? "TRUE" : "FALSE");
 +      for(i=0; i<iP->nNumButtons; i++) {
 +            TOOLBAR_DumpButton(iP, &iP->buttons[i], i);
 +      }
 +    }
 +}
 +
 +static inline BOOL
 +TOOLBAR_ButtonHasString(const TBUTTON_INFO *btnPtr)
 +{
 +    return HIWORD(btnPtr->iString) && btnPtr->iString != -1;
 +}
 +
 +/***********************************************************************
 +*             TOOLBAR_CheckStyle
 +*
 +* This function validates that the styles set are implemented and
 +* issues FIXMEs warning of possible problems. In a perfect world this
 +* function should be null.
 +*/
 +static void
 +TOOLBAR_CheckStyle (const TOOLBAR_INFO *infoPtr)
 +{
 +    if (infoPtr->dwStyle & TBSTYLE_REGISTERDROP)
 +      FIXME("[%p] TBSTYLE_REGISTERDROP not implemented\n", infoPtr->hwndSelf);
 +}
 +
 +
 +static INT
 +TOOLBAR_SendNotify (NMHDR *nmhdr, const TOOLBAR_INFO *infoPtr, UINT code)
 +{
 +      if(!IsWindow(infoPtr->hwndSelf))
 +          return 0;   /* we have just been destroyed */
 +
 +    nmhdr->idFrom = GetDlgCtrlID (infoPtr->hwndSelf);
 +    nmhdr->hwndFrom = infoPtr->hwndSelf;
 +    nmhdr->code = code;
 +
 +    TRACE("to window %p, code=%08x, %s\n", infoPtr->hwndNotify, code,
 +        (infoPtr->bUnicode) ? "via Unicode" : "via ANSI");
 +
 +    return SendMessageW(infoPtr->hwndNotify, WM_NOTIFY, nmhdr->idFrom, (LPARAM)nmhdr);
 +}
 +
 +/***********************************************************************
 +*             TOOLBAR_GetBitmapIndex
 +*
 +* This function returns the bitmap index associated with a button.
 +* If the button specifies I_IMAGECALLBACK, then the TBN_GETDISPINFO
 +* is issued to retrieve the index.
 +*/
 +static INT
 +TOOLBAR_GetBitmapIndex(const TOOLBAR_INFO *infoPtr, TBUTTON_INFO *btnPtr)
 +{
 +    INT ret = btnPtr->iBitmap;
 +
 +    if (ret == I_IMAGECALLBACK)
 +    {
 +        /* issue TBN_GETDISPINFO */
 +        NMTBDISPINFOW nmgd;
 +
 +        memset(&nmgd, 0, sizeof(nmgd));
 +        nmgd.idCommand = btnPtr->idCommand;
 +        nmgd.lParam = btnPtr->dwData;
 +        nmgd.dwMask = TBNF_IMAGE;
 +        nmgd.iImage = -1;
 +        /* Windows also send TBN_GETDISPINFOW even if the control is ANSI */
 +        TOOLBAR_SendNotify(&nmgd.hdr, infoPtr, TBN_GETDISPINFOW);
 +        if (nmgd.dwMask & TBNF_DI_SETITEM)
 +            btnPtr->iBitmap = nmgd.iImage;
 +        ret = nmgd.iImage;
 +        TRACE("TBN_GETDISPINFO returned bitmap id %d, mask=%08x, nNumBitmaps=%d\n",
 +            ret, nmgd.dwMask, infoPtr->nNumBitmaps);
 +    }
 +
 +    if (ret != I_IMAGENONE)
 +        ret = GETIBITMAP(infoPtr, ret);
 +
 +    return ret;
 +}
 +
 +
 +static BOOL
 +TOOLBAR_IsValidBitmapIndex(const TOOLBAR_INFO *infoPtr, INT index)
 +{
 +    HIMAGELIST himl;
 +    INT id = GETHIMLID(infoPtr, index);
 +    INT iBitmap = GETIBITMAP(infoPtr, index);
 +
 +    if (((himl = GETDEFIMAGELIST(infoPtr, id)) &&
 +        iBitmap >= 0 && iBitmap < ImageList_GetImageCount(himl)) ||
 +        (index == I_IMAGECALLBACK))
 +      return TRUE;
 +    else
 +      return FALSE;
 +}
 +
 +
 +static inline BOOL
 +TOOLBAR_IsValidImageList(const TOOLBAR_INFO *infoPtr, INT index)
 +{
 +    HIMAGELIST himl = GETDEFIMAGELIST(infoPtr, GETHIMLID(infoPtr, index));
 +    return (himl != NULL) && (ImageList_GetImageCount(himl) > 0);
 +}
 +
 +
 +/***********************************************************************
 +*             TOOLBAR_GetImageListForDrawing
 +*
 +* This function validates the bitmap index (including I_IMAGECALLBACK
 +* functionality) and returns the corresponding image list.
 +*/
 +static HIMAGELIST
 +TOOLBAR_GetImageListForDrawing (const TOOLBAR_INFO *infoPtr, TBUTTON_INFO *btnPtr,
 +                                IMAGE_LIST_TYPE imagelist, INT * index)
 +{
 +    HIMAGELIST himl;
 +
 +    if (!TOOLBAR_IsValidBitmapIndex(infoPtr,btnPtr->iBitmap)) {
 +      if (btnPtr->iBitmap == I_IMAGENONE) return NULL;
 +      WARN("bitmap for ID %d, index %d is not valid, number of bitmaps in imagelist: %d\n",
 +          HIWORD(btnPtr->iBitmap), LOWORD(btnPtr->iBitmap), infoPtr->nNumBitmaps);
 +      return NULL;
 +    }
 +
 +    if ((*index = TOOLBAR_GetBitmapIndex(infoPtr, btnPtr)) < 0) {
 +      if ((*index == I_IMAGECALLBACK) ||
 +          (*index == I_IMAGENONE)) return NULL;
 +      ERR("TBN_GETDISPINFO returned invalid index %d\n",
 +          *index);
 +      return NULL;
 +    }
 +
 +    switch(imagelist)
 +    {
 +    case IMAGE_LIST_DEFAULT:
 +        himl = GETDEFIMAGELIST(infoPtr, GETHIMLID(infoPtr, btnPtr->iBitmap));
 +        break;
 +    case IMAGE_LIST_HOT:
 +        himl = GETHOTIMAGELIST(infoPtr, GETHIMLID(infoPtr, btnPtr->iBitmap));
 +        break;
 +    case IMAGE_LIST_DISABLED:
 +        himl = GETDISIMAGELIST(infoPtr, GETHIMLID(infoPtr, btnPtr->iBitmap));
 +        break;
 +    default:
 +        himl = NULL;
 +        FIXME("Shouldn't reach here\n");
 +    }
 +
 +    if (!himl)
 +       TRACE("no image list\n");
 +
 +    return himl;
 +}
 +
 +
 +static void
 +TOOLBAR_DrawFlatSeparator (const RECT *lpRect, HDC hdc, const TOOLBAR_INFO *infoPtr)
 +{
 +    RECT myrect;
 +    COLORREF oldcolor, newcolor;
 +
 +    myrect.left = (lpRect->left + lpRect->right) / 2 - 1;
 +    myrect.right = myrect.left + 1;
 +    myrect.top = lpRect->top + 2;
 +    myrect.bottom = lpRect->bottom - 2;
 +
 +    newcolor = (infoPtr->clrBtnShadow == CLR_DEFAULT) ?
 +              comctl32_color.clrBtnShadow : infoPtr->clrBtnShadow;
 +    oldcolor = SetBkColor (hdc, newcolor);
 +    ExtTextOutW (hdc, 0, 0, ETO_OPAQUE, &myrect, 0, 0, 0);
 +
 +    myrect.left = myrect.right;
 +    myrect.right = myrect.left + 1;
 +
 +    newcolor = (infoPtr->clrBtnHighlight == CLR_DEFAULT) ?
 +              comctl32_color.clrBtnHighlight : infoPtr->clrBtnHighlight;
 +    SetBkColor (hdc, newcolor);
 +    ExtTextOutW (hdc, 0, 0, ETO_OPAQUE, &myrect, 0, 0, 0);
 +
 +    SetBkColor (hdc, oldcolor);
 +}
 +
 +
 +/***********************************************************************
 +*             TOOLBAR_DrawFlatHorizontalSeparator
 +*
 +* This function draws horizontal separator for toolbars having CCS_VERT style.
 +* 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
 +* type.
 +*
 +* FIXME: It is possible that the height of each line is really SM_CYBORDER.
 +*/
 +static void
 +TOOLBAR_DrawFlatHorizontalSeparator (const RECT *lpRect, HDC hdc,
 +                             const TOOLBAR_INFO *infoPtr)
 +{
 +    RECT myrect;
 +    COLORREF oldcolor, newcolor;
 +
 +    myrect.left = lpRect->left;
 +    myrect.right = lpRect->right;
 +    myrect.top = lpRect->top + (lpRect->bottom - lpRect->top - 2)/2;
 +    myrect.bottom = myrect.top + 1;
 +
 +    InflateRect (&myrect, -2, 0);
 +
 +    TRACE("rect=(%s)\n", wine_dbgstr_rect(&myrect));
 +
 +    newcolor = (infoPtr->clrBtnShadow == CLR_DEFAULT) ?
 +              comctl32_color.clrBtnShadow : infoPtr->clrBtnShadow;
 +    oldcolor = SetBkColor (hdc, newcolor);
 +    ExtTextOutW (hdc, 0, 0, ETO_OPAQUE, &myrect, 0, 0, 0);
 +
 +    myrect.top = myrect.bottom;
 +    myrect.bottom = myrect.top + 1;
 +
 +    newcolor = (infoPtr->clrBtnHighlight == CLR_DEFAULT) ?
 +              comctl32_color.clrBtnHighlight : infoPtr->clrBtnHighlight;
 +    SetBkColor (hdc, newcolor);
 +    ExtTextOutW (hdc, 0, 0, ETO_OPAQUE, &myrect, 0, 0, 0);
 +
 +    SetBkColor (hdc, oldcolor);
 +}
 +
 +
 +static void
 +TOOLBAR_DrawArrow (HDC hdc, INT left, INT top, COLORREF clr)
 +{
 +    INT x, y;
 +    HPEN hPen, hOldPen;
 +
 +    if (!(hPen = CreatePen( PS_SOLID, 1, clr))) return;
 +    hOldPen = SelectObject ( hdc, hPen );
 +    x = left + 2;
 +    y = top;
 +    MoveToEx (hdc, x, y, NULL);
 +    LineTo (hdc, x+5, y++); x++;
 +    MoveToEx (hdc, x, y, NULL);
 +    LineTo (hdc, x+3, y++); x++;
 +    MoveToEx (hdc, x, y, NULL);
 +    LineTo (hdc, x+1, y);
 +    SelectObject( hdc, hOldPen );
 +    DeleteObject( hPen );
 +}
 +
 +/*
 + * Draw the text string for this button.
 + * note: infoPtr->himlDis *SHOULD* be non-zero when infoPtr->himlDef
 + *    is non-zero, so we can simply check himlDef to see if we have
 + *      an image list
 + */
 +static void
 +TOOLBAR_DrawString (const TOOLBAR_INFO *infoPtr, RECT *rcText, LPCWSTR lpText,
 +                    const NMTBCUSTOMDRAW *tbcd, DWORD dwItemCDFlag)
 +{
 +    HDC hdc = tbcd->nmcd.hdc;
 +    HFONT  hOldFont = 0;
 +    COLORREF clrOld = 0;
 +    COLORREF clrOldBk = 0;
 +    int oldBkMode = 0;
 +    UINT state = tbcd->nmcd.uItemState;
 +
 +    /* draw text */
 +    if (lpText && infoPtr->nMaxTextRows > 0) {
 +        TRACE("string=%s rect=(%s)\n", debugstr_w(lpText),
 +              wine_dbgstr_rect(rcText));
 +
 +      hOldFont = SelectObject (hdc, infoPtr->hFont);
 +      if ((state & CDIS_HOT) && (dwItemCDFlag & TBCDRF_HILITEHOTTRACK )) {
 +          clrOld = SetTextColor (hdc, tbcd->clrTextHighlight);
 +      }
 +      else if (state & CDIS_DISABLED) {
 +          clrOld = SetTextColor (hdc, tbcd->clrBtnHighlight);
 +          OffsetRect (rcText, 1, 1);
 +          DrawTextW (hdc, lpText, -1, rcText, infoPtr->dwDTFlags);
 +          SetTextColor (hdc, comctl32_color.clr3dShadow);
 +          OffsetRect (rcText, -1, -1);
 +      }
 +      else if (state & CDIS_INDETERMINATE) {
 +          clrOld = SetTextColor (hdc, comctl32_color.clr3dShadow);
 +      }
 +      else if ((state & CDIS_MARKED) && !(dwItemCDFlag & TBCDRF_NOMARK)) {
 +          clrOld = SetTextColor (hdc, tbcd->clrTextHighlight);
 +          clrOldBk = SetBkColor (hdc, tbcd->clrMark);
 +          oldBkMode = SetBkMode (hdc, tbcd->nHLStringBkMode);
 +      }
 +      else {
 +          clrOld = SetTextColor (hdc, tbcd->clrText);
 +      }
 +
 +      DrawTextW (hdc, lpText, -1, rcText, infoPtr->dwDTFlags);
 +      SetTextColor (hdc, clrOld);
 +      if ((state & CDIS_MARKED) && !(dwItemCDFlag & TBCDRF_NOMARK))
 +      {
 +          SetBkColor (hdc, clrOldBk);
 +          SetBkMode (hdc, oldBkMode);
 +      }
 +      SelectObject (hdc, hOldFont);
 +    }
 +}
 +
 +
 +static void
 +TOOLBAR_DrawPattern (const RECT *lpRect, const NMTBCUSTOMDRAW *tbcd)
 +{
 +    HDC hdc = tbcd->nmcd.hdc;
 +    HBRUSH hbr = SelectObject (hdc, tbcd->hbrMonoDither);
 +    COLORREF clrTextOld;
 +    COLORREF clrBkOld;
 +    INT cx = lpRect->right - lpRect->left;
 +    INT cy = lpRect->bottom - lpRect->top;
 +    INT cxEdge = GetSystemMetrics(SM_CXEDGE);
 +    INT cyEdge = GetSystemMetrics(SM_CYEDGE);
 +    clrTextOld = SetTextColor(hdc, tbcd->clrBtnHighlight);
 +    clrBkOld = SetBkColor(hdc, tbcd->clrBtnFace);
 +    PatBlt (hdc, lpRect->left + cxEdge, lpRect->top + cyEdge,
 +            cx - (2 * cxEdge), cy - (2 * cyEdge), PATCOPY);
 +    SetBkColor(hdc, clrBkOld);
 +    SetTextColor(hdc, clrTextOld);
 +    SelectObject (hdc, hbr);
 +}
 +
 +
 +static void TOOLBAR_DrawMasked(HIMAGELIST himl, int index, HDC hdc, INT x, INT y, UINT draw_flags)
 +{
 +    INT cx, cy;
 +    HBITMAP hbmMask, hbmImage;
 +    HDC hdcMask, hdcImage;
 +
 +    ImageList_GetIconSize(himl, &cx, &cy);
 +
 +    /* Create src image */
 +    hdcImage = CreateCompatibleDC(hdc);
 +    hbmImage = CreateCompatibleBitmap(hdc, cx, cy);
 +    SelectObject(hdcImage, hbmImage);
 +    ImageList_DrawEx(himl, index, hdcImage, 0, 0, cx, cy,
 +                     RGB(0xff, 0xff, 0xff), RGB(0,0,0), draw_flags);
 +
 +    /* Create Mask */
 +    hdcMask = CreateCompatibleDC(0);
 +    hbmMask = CreateBitmap(cx, cy, 1, 1, NULL);
 +    SelectObject(hdcMask, hbmMask);
 +
 +    /* Remove the background and all white pixels */
 +    ImageList_DrawEx(himl, index, hdcMask, 0, 0, cx, cy,
 +                     RGB(0xff, 0xff, 0xff), RGB(0,0,0), ILD_MASK);
 +    SetBkColor(hdcImage, RGB(0xff, 0xff, 0xff));
 +    BitBlt(hdcMask, 0, 0, cx, cy, hdcImage, 0, 0, NOTSRCERASE);
 +
 +    /* draw the new mask 'etched' to hdc */
 +    SetBkColor(hdc, RGB(255, 255, 255));
 +    SelectObject(hdc, GetSysColorBrush(COLOR_3DHILIGHT));
 +    /* E20746 op code is (Dst ^ (Src & (Pat ^ Dst))) */
 +    BitBlt(hdc, x + 1, y + 1, cx, cy, hdcMask, 0, 0, 0xE20746);
 +    SelectObject(hdc, GetSysColorBrush(COLOR_3DSHADOW));
 +    BitBlt(hdc, x, y, cx, cy, hdcMask, 0, 0, 0xE20746);
 +
 +    /* Cleanup */
 +    DeleteObject(hbmImage);
 +    DeleteDC(hdcImage);
 +    DeleteObject (hbmMask);
 +    DeleteDC(hdcMask);
 +}
 +
 +
 +static UINT
 +TOOLBAR_TranslateState(const TBUTTON_INFO *btnPtr)
 +{
 +    UINT retstate = 0;
 +
 +    retstate |= (btnPtr->fsState & TBSTATE_CHECKED) ? CDIS_CHECKED  : 0;
 +    retstate |= (btnPtr->fsState & TBSTATE_PRESSED) ? CDIS_SELECTED : 0;
 +    retstate |= (btnPtr->fsState & TBSTATE_ENABLED) ? 0 : CDIS_DISABLED;
 +    retstate |= (btnPtr->fsState & TBSTATE_MARKED ) ? CDIS_MARKED   : 0;
 +    retstate |= (btnPtr->bHot                     ) ? CDIS_HOT      : 0;
 +    retstate |= ((btnPtr->fsState & (TBSTATE_ENABLED|TBSTATE_INDETERMINATE)) == (TBSTATE_ENABLED|TBSTATE_INDETERMINATE)) ? CDIS_INDETERMINATE : 0;
 +    /* NOTE: we don't set CDIS_GRAYED, CDIS_FOCUS, CDIS_DEFAULT */
 +    return retstate;
 +}
 +
 +/* draws the image on a toolbar button */
 +static void
 +TOOLBAR_DrawImage(const TOOLBAR_INFO *infoPtr, TBUTTON_INFO *btnPtr, INT left, INT top,
 +                  const NMTBCUSTOMDRAW *tbcd, DWORD dwItemCDFlag)
 +{
 +    HIMAGELIST himl = NULL;
 +    BOOL draw_masked = FALSE;
 +    INT index;
 +    INT offset = 0;
 +    UINT draw_flags = ILD_TRANSPARENT;
 +
 +    if (tbcd->nmcd.uItemState & (CDIS_DISABLED | CDIS_INDETERMINATE))
 +    {
 +        himl = TOOLBAR_GetImageListForDrawing(infoPtr, btnPtr, IMAGE_LIST_DISABLED, &index);
 +        if (!himl)
 +        {
 +            himl = TOOLBAR_GetImageListForDrawing(infoPtr, btnPtr, IMAGE_LIST_DEFAULT, &index);
 +            draw_masked = TRUE;
 +        }
 +    }
 +    else if (tbcd->nmcd.uItemState & CDIS_CHECKED ||
 +      ((tbcd->nmcd.uItemState & CDIS_HOT) 
 +      && ((infoPtr->dwStyle & TBSTYLE_FLAT) || GetWindowTheme (infoPtr->hwndSelf))))
 +    {
 +        /* if hot, attempt to draw with hot image list, if fails, 
 +           use default image list */
 +        himl = TOOLBAR_GetImageListForDrawing(infoPtr, btnPtr, IMAGE_LIST_HOT, &index);
 +        if (!himl)
 +            himl = TOOLBAR_GetImageListForDrawing(infoPtr, btnPtr, IMAGE_LIST_DEFAULT, &index);
 +      }
 +    else
 +        himl = TOOLBAR_GetImageListForDrawing(infoPtr, btnPtr, IMAGE_LIST_DEFAULT, &index);
 +
 +    if (!himl)
 +        return;
 +
 +    if (!(dwItemCDFlag & TBCDRF_NOOFFSET) && 
 +        (tbcd->nmcd.uItemState & (CDIS_SELECTED | CDIS_CHECKED)))
 +        offset = 1;
 +
 +    if (!(dwItemCDFlag & TBCDRF_NOMARK) &&
 +        (tbcd->nmcd.uItemState & CDIS_MARKED))
 +        draw_flags |= ILD_BLEND50;
 +
 +    TRACE("drawing index=%d, himl=%p, left=%d, top=%d, offset=%d\n",
 +      index, himl, left, top, offset);
 +
 +    if (draw_masked)
 +        TOOLBAR_DrawMasked (himl, index, tbcd->nmcd.hdc, left + offset, top + offset, draw_flags);
 +    else
 +        ImageList_Draw (himl, index, tbcd->nmcd.hdc, left + offset, top + offset, draw_flags);
 +}
 +
 +/* draws a blank frame for a toolbar button */
 +static void
 +TOOLBAR_DrawFrame(const TOOLBAR_INFO *infoPtr, const NMTBCUSTOMDRAW *tbcd, DWORD dwItemCDFlag)
 +{
 +    HDC hdc = tbcd->nmcd.hdc;
 +    RECT rc = tbcd->nmcd.rc;
 +    /* if the state is disabled or indeterminate then the button
 +     * cannot have an interactive look like pressed or hot */
 +    BOOL non_interactive_state = (tbcd->nmcd.uItemState & CDIS_DISABLED) ||
 +                                 (tbcd->nmcd.uItemState & CDIS_INDETERMINATE);
 +    BOOL pressed_look = !non_interactive_state &&
 +                        ((tbcd->nmcd.uItemState & CDIS_SELECTED) || 
 +                         (tbcd->nmcd.uItemState & CDIS_CHECKED));
 +
 +    /* app don't want us to draw any edges */
 +    if (dwItemCDFlag & TBCDRF_NOEDGES)
 +        return;
 +
 +    if (infoPtr->dwStyle & TBSTYLE_FLAT)
 +    {
 +        if (pressed_look)
 +            DrawEdge (hdc, &rc, BDR_SUNKENOUTER, BF_RECT);
 +        else if ((tbcd->nmcd.uItemState & CDIS_HOT) && !non_interactive_state)
 +            DrawEdge (hdc, &rc, BDR_RAISEDINNER, BF_RECT);
 +    }
 +    else
 +    {
 +        if (pressed_look)
 +            DrawEdge (hdc, &rc, EDGE_SUNKEN, BF_RECT | BF_MIDDLE);
 +        else
 +            DrawEdge (hdc, &rc, EDGE_RAISED,
 +              BF_SOFT | BF_RECT | BF_MIDDLE);
 +    }
 +}
 +
 +static void
 +TOOLBAR_DrawSepDDArrow(const TOOLBAR_INFO *infoPtr, const NMTBCUSTOMDRAW *tbcd, RECT *rcArrow, BOOL bDropDownPressed, DWORD dwItemCDFlag)
 +{
 +    HDC hdc = tbcd->nmcd.hdc;
 +    int offset = 0;
 +    BOOL pressed = bDropDownPressed ||
 +        (tbcd->nmcd.uItemState & (CDIS_SELECTED | CDIS_CHECKED));
 +
 +    if (infoPtr->dwStyle & TBSTYLE_FLAT)
 +    {
 +        if (pressed)
 +            DrawEdge (hdc, rcArrow, BDR_SUNKENOUTER, BF_RECT);
 +        else if ( (tbcd->nmcd.uItemState & CDIS_HOT) &&
 +                 !(tbcd->nmcd.uItemState & CDIS_DISABLED) &&
 +                 !(tbcd->nmcd.uItemState & CDIS_INDETERMINATE))
 +            DrawEdge (hdc, rcArrow, BDR_RAISEDINNER, BF_RECT);
 +    }
 +    else
 +    {
 +        if (pressed)
 +            DrawEdge (hdc, rcArrow, EDGE_SUNKEN, BF_RECT | BF_MIDDLE);
 +        else
 +            DrawEdge (hdc, rcArrow, EDGE_RAISED,
 +              BF_SOFT | BF_RECT | BF_MIDDLE);
 +    }
 +
 +    if (pressed)
 +        offset = (dwItemCDFlag & TBCDRF_NOOFFSET) ? 0 : 1;
 +
 +    if (tbcd->nmcd.uItemState & (CDIS_DISABLED | CDIS_INDETERMINATE))
 +    {
 +        TOOLBAR_DrawArrow(hdc, rcArrow->left+1, rcArrow->top+1 + (rcArrow->bottom - rcArrow->top - ARROW_HEIGHT) / 2, comctl32_color.clrBtnHighlight);
 +        TOOLBAR_DrawArrow(hdc, rcArrow->left, rcArrow->top + (rcArrow->bottom - rcArrow->top - ARROW_HEIGHT) / 2, comctl32_color.clr3dShadow);
 +    }
 +    else
 +        TOOLBAR_DrawArrow(hdc, rcArrow->left + offset, rcArrow->top + offset + (rcArrow->bottom - rcArrow->top - ARROW_HEIGHT) / 2, comctl32_color.clrBtnText);
 +}
 +
 +/* draws a complete toolbar button */
 +static void
 +TOOLBAR_DrawButton (const TOOLBAR_INFO *infoPtr, TBUTTON_INFO *btnPtr, HDC hdc, DWORD dwBaseCustDraw)
 +{
 +    DWORD dwStyle = infoPtr->dwStyle;
 +    BOOL hasDropDownArrow = (TOOLBAR_HasDropDownArrows(infoPtr->dwExStyle) &&
 +                            (btnPtr->fsStyle & BTNS_DROPDOWN)) ||
 +                            (btnPtr->fsStyle & BTNS_WHOLEDROPDOWN);
 +    BOOL drawSepDropDownArrow = hasDropDownArrow && 
 +                                (~btnPtr->fsStyle & BTNS_WHOLEDROPDOWN);
 +    RECT rc, rcArrow, rcBitmap, rcText;
 +    LPWSTR lpText = NULL;
 +    NMTBCUSTOMDRAW tbcd;
 +    DWORD ntfret;
 +    INT offset;
 +    INT oldBkMode;
 +    DWORD dwItemCustDraw;
 +    DWORD dwItemCDFlag;
 +    HTHEME theme = GetWindowTheme (infoPtr->hwndSelf);
 +
 +    rc = btnPtr->rect;
 +    CopyRect (&rcArrow, &rc);
 +
 +    /* separator - doesn't send NM_CUSTOMDRAW */
 +    if (btnPtr->fsStyle & BTNS_SEP) {
 +        if (theme)
 +        {
 +            DrawThemeBackground (theme, hdc, 
 +                (dwStyle & CCS_VERT) ? TP_SEPARATORVERT : TP_SEPARATOR, 0, 
 +                &rc, NULL);
 +        }
 +        else
 +        /* with the FLAT style, iBitmap is the width and has already */
 +        /* been taken into consideration in calculating the width    */
 +        /* so now we need to draw the vertical separator             */
 +        /* empirical tests show that iBitmap can/will be non-zero    */
 +        /* when drawing the vertical bar...      */
 +        if ((dwStyle & TBSTYLE_FLAT) /* && (btnPtr->iBitmap == 0) */) {
 +            if (dwStyle & CCS_VERT) {
 +                RECT rcsep = rc;
 +                InflateRect(&rcsep, -infoPtr->szPadding.cx, -infoPtr->szPadding.cy);
 +                TOOLBAR_DrawFlatHorizontalSeparator (&rcsep, hdc, infoPtr);
 +            }
 +            else {
 +                TOOLBAR_DrawFlatSeparator (&rc, hdc, infoPtr);
 +            }
 +        }
 +        else if (btnPtr->fsStyle != BTNS_SEP) {
 +            FIXME("Draw some kind of separator: fsStyle=%x\n",
 +              btnPtr->fsStyle);
 +        }
 +        return;
 +    }
 +
 +    /* get a pointer to the text */
 +    lpText = TOOLBAR_GetText(infoPtr, btnPtr);
 +
 +    if (hasDropDownArrow)
 +    {
 +        int right;
 +
 +        if (dwStyle & TBSTYLE_FLAT)
 +            right = max(rc.left, rc.right - DDARROW_WIDTH);
 +        else
 +            right = max(rc.left, rc.right - DDARROW_WIDTH - 2);
 +
 +        if (drawSepDropDownArrow)
 +           rc.right = right;
 +
 +        rcArrow.left = right;
 +    }
 +
 +    /* copy text & bitmap rects after adjusting for drop-down arrow
 +     * so that text & bitmap is centered in the rectangle not containing
 +     * the arrow */
 +    CopyRect(&rcText, &rc);
 +    CopyRect(&rcBitmap, &rc);
 +
 +    /* Center the bitmap horizontally and vertically */
 +    if (dwStyle & TBSTYLE_LIST)
 +    {
 +        if (lpText &&
 +            infoPtr->nMaxTextRows > 0 &&
 +            (!(infoPtr->dwExStyle & TBSTYLE_EX_MIXEDBUTTONS) ||
 +            (btnPtr->fsStyle & BTNS_SHOWTEXT)) )
 +            rcBitmap.left += GetSystemMetrics(SM_CXEDGE) + infoPtr->szPadding.cx / 2;
 +        else
 +            rcBitmap.left += GetSystemMetrics(SM_CXEDGE) + infoPtr->iListGap / 2;
 +    }
 +    else
 +        rcBitmap.left += ((rc.right - rc.left) - infoPtr->nBitmapWidth) / 2;
 +
 +    rcBitmap.top += infoPtr->szPadding.cy / 2;
 +
 +    TRACE("iBitmap=%d, start=(%d,%d) w=%d, h=%d\n",
 +      btnPtr->iBitmap, rcBitmap.left, rcBitmap.top,
 +      infoPtr->nBitmapWidth, infoPtr->nBitmapHeight);
 +    TRACE("Text=%s\n", debugstr_w(lpText));
 +    TRACE("iListGap=%d, padding = { %d, %d }\n", infoPtr->iListGap, infoPtr->szPadding.cx, infoPtr->szPadding.cy);
 +
 +    /* calculate text position */
 +    if (lpText)
 +    {
 +        rcText.left += GetSystemMetrics(SM_CXEDGE);
 +        rcText.right -= GetSystemMetrics(SM_CXEDGE);
 +        if (dwStyle & TBSTYLE_LIST)
 +        {
 +            rcText.left += infoPtr->nBitmapWidth + infoPtr->iListGap + 2;
 +        }
 +        else
 +        {
 +            if (ImageList_GetImageCount(GETDEFIMAGELIST(infoPtr, 0)) > 0)
 +                rcText.top += infoPtr->szPadding.cy/2 + infoPtr->nBitmapHeight + 1;
 +            else
 +                rcText.top += infoPtr->szPadding.cy/2 + 2;
 +        }
 +    }
 +
 +    /* Initialize fields in all cases, because we use these later
 +     * NOTE: applications can and do alter these to customize their
 +     * toolbars */
 +    ZeroMemory (&tbcd, sizeof(NMTBCUSTOMDRAW));
 +    tbcd.clrText = comctl32_color.clrBtnText;
 +    tbcd.clrTextHighlight = comctl32_color.clrHighlightText;
 +    tbcd.clrBtnFace = comctl32_color.clrBtnFace;
 +    tbcd.clrBtnHighlight = comctl32_color.clrBtnHighlight;
 +    tbcd.clrMark = comctl32_color.clrHighlight;
 +    tbcd.clrHighlightHotTrack = 0;
 +    tbcd.nStringBkMode = TRANSPARENT;
 +    tbcd.nHLStringBkMode = OPAQUE;
 +    tbcd.rcText.left = 0;
 +    tbcd.rcText.top = 0;
 +    tbcd.rcText.right = rcText.right - rc.left;
 +    tbcd.rcText.bottom = rcText.bottom - rc.top;
 +    tbcd.nmcd.uItemState = TOOLBAR_TranslateState(btnPtr);
 +    tbcd.nmcd.hdc = hdc;
 +    tbcd.nmcd.rc = rc;
 +    tbcd.hbrMonoDither = COMCTL32_hPattern55AABrush;
 +
 +    /* FIXME: what are these used for? */
 +    tbcd.hbrLines = 0;
 +    tbcd.hpenLines = 0;
 +
 +    /* Issue Item Prepaint notify */
 +    dwItemCustDraw = 0;
 +    dwItemCDFlag = 0;
 +    if (dwBaseCustDraw & CDRF_NOTIFYITEMDRAW)
 +    {
 +      tbcd.nmcd.dwDrawStage = CDDS_ITEMPREPAINT;
 +      tbcd.nmcd.dwItemSpec = btnPtr->idCommand;
 +      tbcd.nmcd.lItemlParam = btnPtr->dwData;
 +      ntfret = TOOLBAR_SendNotify(&tbcd.nmcd.hdr, infoPtr, NM_CUSTOMDRAW);
 +        /* reset these fields so the user can't alter the behaviour like native */
 +        tbcd.nmcd.hdc = hdc;
 +        tbcd.nmcd.rc = rc;
 +
 +      dwItemCustDraw = ntfret & 0xffff;
 +      dwItemCDFlag = ntfret & 0xffff0000;
 +      if (dwItemCustDraw & CDRF_SKIPDEFAULT)
 +          return;
 +      /* save the only part of the rect that the user can change */
 +      rcText.right = tbcd.rcText.right + rc.left;
 +      rcText.bottom = tbcd.rcText.bottom + rc.top;
 +    }
 +
 +    if (!(dwItemCDFlag & TBCDRF_NOOFFSET) &&
 +        (btnPtr->fsState & (TBSTATE_PRESSED | TBSTATE_CHECKED)))
 +        OffsetRect(&rcText, 1, 1);
 +
 +    if (!(tbcd.nmcd.uItemState & CDIS_HOT) && 
 +        ((tbcd.nmcd.uItemState & CDIS_CHECKED) || (tbcd.nmcd.uItemState & CDIS_INDETERMINATE)))
 +        TOOLBAR_DrawPattern (&rc, &tbcd);
 +
 +    if (((infoPtr->dwStyle & TBSTYLE_FLAT) || GetWindowTheme (infoPtr->hwndSelf)) 
 +        && (tbcd.nmcd.uItemState & CDIS_HOT))
 +    {
 +        if ( dwItemCDFlag & TBCDRF_HILITEHOTTRACK )
 +        {
 +            COLORREF oldclr;
 +
 +            oldclr = SetBkColor(hdc, tbcd.clrHighlightHotTrack);
 +            ExtTextOutW(hdc, 0, 0, ETO_OPAQUE, &rc, NULL, 0, 0);
 +            if (hasDropDownArrow)
 +                ExtTextOutW(hdc, 0, 0, ETO_OPAQUE, &rcArrow, NULL, 0, 0);
 +            SetBkColor(hdc, oldclr);
 +        }
 +    }
 +
 +    if (theme)
 +    {
 +        int partId = drawSepDropDownArrow ? TP_SPLITBUTTON : TP_BUTTON;
 +        int stateId = TS_NORMAL;
 +        
 +        if (tbcd.nmcd.uItemState & CDIS_DISABLED)
 +            stateId = TS_DISABLED;
 +        else if (tbcd.nmcd.uItemState & CDIS_SELECTED)
 +            stateId = TS_PRESSED;
 +        else if (tbcd.nmcd.uItemState & CDIS_CHECKED)
 +            stateId = (tbcd.nmcd.uItemState & CDIS_HOT) ? TS_HOTCHECKED : TS_HOT;
 +        else if ((tbcd.nmcd.uItemState & CDIS_HOT)
 +            || (drawSepDropDownArrow && btnPtr->bDropDownPressed))
 +            stateId = TS_HOT;
 +            
 +        DrawThemeBackground (theme, hdc, partId, stateId, &tbcd.nmcd.rc, NULL);
 +    }
 +    else
 +        TOOLBAR_DrawFrame(infoPtr, &tbcd, dwItemCDFlag);
 +
 +    if (drawSepDropDownArrow)
 +    {
 +        if (theme)
 +        {
 +            int stateId = TS_NORMAL;
 +            
 +            if (tbcd.nmcd.uItemState & CDIS_DISABLED)
 +                stateId = TS_DISABLED;
 +            else if (btnPtr->bDropDownPressed || (tbcd.nmcd.uItemState & CDIS_SELECTED))
 +                stateId = TS_PRESSED;
 +            else if (tbcd.nmcd.uItemState & CDIS_CHECKED)
 +                stateId = (tbcd.nmcd.uItemState & CDIS_HOT) ? TS_HOTCHECKED : TS_HOT;
 +            else if (tbcd.nmcd.uItemState & CDIS_HOT)
 +                stateId = TS_HOT;
 +                
 +            DrawThemeBackground (theme, hdc, TP_DROPDOWNBUTTON, stateId, &rcArrow, NULL);
 +            DrawThemeBackground (theme, hdc, TP_SPLITBUTTONDROPDOWN, stateId, &rcArrow, NULL);
 +        }
 +        else
 +            TOOLBAR_DrawSepDDArrow(infoPtr, &tbcd, &rcArrow, btnPtr->bDropDownPressed, dwItemCDFlag);
 +    }
 +
 +    oldBkMode = SetBkMode (hdc, tbcd.nStringBkMode);
 +    if (!(infoPtr->dwExStyle & TBSTYLE_EX_MIXEDBUTTONS) || (btnPtr->fsStyle & BTNS_SHOWTEXT))
 +        TOOLBAR_DrawString (infoPtr, &rcText, lpText, &tbcd, dwItemCDFlag);
 +    SetBkMode (hdc, oldBkMode);
 +
 +    TOOLBAR_DrawImage(infoPtr, btnPtr, rcBitmap.left, rcBitmap.top, &tbcd, dwItemCDFlag);
 +
 +    if (hasDropDownArrow && !drawSepDropDownArrow)
 +    {
 +        if (tbcd.nmcd.uItemState & (CDIS_DISABLED | CDIS_INDETERMINATE))
 +        {
 +            TOOLBAR_DrawArrow(hdc, rcArrow.left+1, rcArrow.top+1 + (rcArrow.bottom - rcArrow.top - ARROW_HEIGHT) / 2, comctl32_color.clrBtnHighlight);
 +            TOOLBAR_DrawArrow(hdc, rcArrow.left, rcArrow.top + (rcArrow.bottom - rcArrow.top - ARROW_HEIGHT) / 2, comctl32_color.clr3dShadow);
 +        }
 +        else if (tbcd.nmcd.uItemState & (CDIS_SELECTED | CDIS_CHECKED))
 +        {
 +            offset = (dwItemCDFlag & TBCDRF_NOOFFSET) ? 0 : 1;
 +            TOOLBAR_DrawArrow(hdc, rcArrow.left + offset, rcArrow.top + offset + (rcArrow.bottom - rcArrow.top - ARROW_HEIGHT) / 2, comctl32_color.clrBtnText);
 +        }
 +        else
 +            TOOLBAR_DrawArrow(hdc, rcArrow.left, rcArrow.top + (rcArrow.bottom - rcArrow.top - ARROW_HEIGHT) / 2, comctl32_color.clrBtnText);
 +    }
 +
 +    if (dwItemCustDraw & CDRF_NOTIFYPOSTPAINT)
 +    {
 +        tbcd.nmcd.dwDrawStage = CDDS_ITEMPOSTPAINT;
 +        TOOLBAR_SendNotify(&tbcd.nmcd.hdr, infoPtr, NM_CUSTOMDRAW);
 +    }
 +
 +}
 +
 +
 +static void
 +TOOLBAR_Refresh (TOOLBAR_INFO *infoPtr, HDC hdc, const PAINTSTRUCT *ps)
 +{
 +    TBUTTON_INFO *btnPtr;
 +    INT i;
 +    RECT rcTemp, rcClient;
 +    NMTBCUSTOMDRAW tbcd;
 +    DWORD ntfret;
 +    DWORD dwBaseCustDraw;
 +
 +    /* the app has told us not to redraw the toolbar */
 +    if (!infoPtr->bDoRedraw)
 +        return;
 +
 +    /* if imagelist belongs to the app, it can be changed
 +       by the app after setting it */
 +    if (GETDEFIMAGELIST(infoPtr, 0) != infoPtr->himlInt)
 +    {
 +        infoPtr->nNumBitmaps = 0;
 +        for (i = 0; i < infoPtr->cimlDef; i++)
 +            infoPtr->nNumBitmaps += ImageList_GetImageCount(infoPtr->himlDef[i]->himl);
 +    }
 +
 +    TOOLBAR_DumpToolbar (infoPtr, __LINE__);
 +
 +    /* change the imagelist icon size if we manage the list and it is necessary */
 +    TOOLBAR_CheckImageListIconSize(infoPtr);
 +
 +    /* Send initial notify */
 +    ZeroMemory (&tbcd, sizeof(NMTBCUSTOMDRAW));
 +    tbcd.nmcd.dwDrawStage = CDDS_PREPAINT;
 +    tbcd.nmcd.hdc = hdc;
 +    tbcd.nmcd.rc = ps->rcPaint;
 +    ntfret = TOOLBAR_SendNotify(&tbcd.nmcd.hdr, infoPtr, NM_CUSTOMDRAW);
 +    dwBaseCustDraw = ntfret & 0xffff;
 +
 +    GetClientRect(infoPtr->hwndSelf, &rcClient);
 +
 +    /* redraw necessary buttons */
 +    btnPtr = infoPtr->buttons;
 +    for (i = 0; i < infoPtr->nNumButtons; i++, btnPtr++)
 +    {
 +        BOOL bDraw;
 +        if (!RectVisible(hdc, &btnPtr->rect))
 +            continue;
 +        if (infoPtr->dwExStyle & TBSTYLE_EX_HIDECLIPPEDBUTTONS)
 +        {
 +            IntersectRect(&rcTemp, &rcClient, &btnPtr->rect);
 +            bDraw = EqualRect(&rcTemp, &btnPtr->rect);
 +        }
 +        else
 +            bDraw = TRUE;
 +        bDraw &= IntersectRect(&rcTemp, &(ps->rcPaint), &(btnPtr->rect));
 +        bDraw = (btnPtr->fsState & TBSTATE_HIDDEN) ? FALSE : bDraw;
 +        if (bDraw)
 +            TOOLBAR_DrawButton(infoPtr, btnPtr, hdc, dwBaseCustDraw);
 +    }
 +
 +    /* draw insert mark if required */
 +    if (infoPtr->tbim.iButton != -1)
 +    {
 +        RECT rcButton = infoPtr->buttons[infoPtr->tbim.iButton].rect;
 +        RECT rcInsertMark;
 +        rcInsertMark.top = rcButton.top;
 +        rcInsertMark.bottom = rcButton.bottom;
 +        if (infoPtr->tbim.dwFlags & TBIMHT_AFTER)
 +            rcInsertMark.left = rcInsertMark.right = rcButton.right;
 +        else
 +            rcInsertMark.left = rcInsertMark.right = rcButton.left - INSERTMARK_WIDTH;
 +        COMCTL32_DrawInsertMark(hdc, &rcInsertMark, infoPtr->clrInsertMark, FALSE);
 +    }
 +
 +    if (dwBaseCustDraw & CDRF_NOTIFYPOSTPAINT)
 +    {
 +      ZeroMemory (&tbcd, sizeof(NMTBCUSTOMDRAW));
 +      tbcd.nmcd.dwDrawStage = CDDS_POSTPAINT;
 +      tbcd.nmcd.hdc = hdc;
 +      tbcd.nmcd.rc = ps->rcPaint;
 +      TOOLBAR_SendNotify(&tbcd.nmcd.hdr, infoPtr, NM_CUSTOMDRAW);
 +    }
 +}
 +
 +/***********************************************************************
 +*             TOOLBAR_MeasureString
 +*
 +* This function gets the width and height of a string in pixels. This
 +* is done first by using GetTextExtentPoint to get the basic width
 +* and height. The DrawText is called with DT_CALCRECT to get the exact
 +* width. The reason is because the text may have more than one "&" (or
 +* prefix characters as M$ likes to call them). The prefix character
 +* indicates where the underline goes, except for the string "&&" which
 +* is reduced to a single "&". GetTextExtentPoint does not process these
 +* only DrawText does. Note that the BTNS_NOPREFIX is handled here.
 +*/
 +static void
 +TOOLBAR_MeasureString(const TOOLBAR_INFO *infoPtr, const TBUTTON_INFO *btnPtr,
 +                    HDC hdc, LPSIZE lpSize)
 +{
 +    RECT myrect;
 +
 +    lpSize->cx = 0;
 +    lpSize->cy = 0;
 +
 +    if (infoPtr->nMaxTextRows > 0 &&
 +        !(btnPtr->fsState & TBSTATE_HIDDEN) &&
 +        (!(infoPtr->dwExStyle & TBSTYLE_EX_MIXEDBUTTONS) ||
 +        (btnPtr->fsStyle & BTNS_SHOWTEXT)) )
 +    {
 +        LPWSTR lpText = TOOLBAR_GetText(infoPtr, btnPtr);
 +
 +      if(lpText != NULL) {
 +          /* first get size of all the text */
 +          GetTextExtentPoint32W (hdc, lpText, strlenW (lpText), lpSize);
 +
 +          /* feed above size into the rectangle for DrawText */
 +          myrect.left = myrect.top = 0;
 +          myrect.right = lpSize->cx;
 +          myrect.bottom = lpSize->cy;
 +
 +          /* Use DrawText to get true size as drawn (less pesky "&") */
 +          DrawTextW (hdc, lpText, -1, &myrect, DT_VCENTER | DT_SINGLELINE |
 +                 DT_CALCRECT | ((btnPtr->fsStyle & BTNS_NOPREFIX) ?
 +                                DT_NOPREFIX : 0));
 +
 +          /* feed back to caller  */
 +          lpSize->cx = myrect.right;
 +          lpSize->cy = myrect.bottom;
 +      }
 +    }
 +
 +    TRACE("string size %d x %d!\n", lpSize->cx, lpSize->cy);
 +}
 +
 +/***********************************************************************
 +*             TOOLBAR_CalcStrings
 +*
 +* This function walks through each string and measures it and returns
 +* the largest height and width to caller.
 +*/
 +static void
 +TOOLBAR_CalcStrings (const TOOLBAR_INFO *infoPtr, LPSIZE lpSize)
 +{
 +    TBUTTON_INFO *btnPtr;
 +    INT i;
 +    SIZE sz;
 +    HDC hdc;
 +    HFONT hOldFont;
 +
 +    lpSize->cx = 0;
 +    lpSize->cy = 0;
 +
 +    if (infoPtr->nMaxTextRows == 0)
 +        return;
 +
 +    hdc = GetDC (infoPtr->hwndSelf);
 +    hOldFont = SelectObject (hdc, infoPtr->hFont);
 +
 +    if (infoPtr->nNumButtons == 0 && infoPtr->nNumStrings > 0)
 +    {
 +        TEXTMETRICW tm;
 +
 +        GetTextMetricsW(hdc, &tm);
 +        lpSize->cy = tm.tmHeight;
 +    }
 +
 +    btnPtr = infoPtr->buttons;
 +    for (i = 0; i < infoPtr->nNumButtons; i++, btnPtr++) {
 +        if(TOOLBAR_GetText(infoPtr, btnPtr))
 +        {
 +            TOOLBAR_MeasureString(infoPtr, btnPtr, hdc, &sz);
 +            if (sz.cx > lpSize->cx)
 +                lpSize->cx = sz.cx;
 +            if (sz.cy > lpSize->cy)
 +                lpSize->cy = sz.cy;
 +        }
 +    }
 +
 +    SelectObject (hdc, hOldFont);
 +    ReleaseDC (infoPtr->hwndSelf, hdc);
 +
 +    TRACE("max string size %d x %d!\n", lpSize->cx, lpSize->cy);
 +}
 +
 +/***********************************************************************
 +*             TOOLBAR_WrapToolbar
 +*
 +* This function walks through the buttons and separators in the
 +* toolbar, and sets the TBSTATE_WRAP flag only on those items where
 +* wrapping should occur based on the width of the toolbar window.
 +* It does *not* calculate button placement itself.  That task
 +* takes place in TOOLBAR_CalcToolbar. If the program wants to manage
 +* the toolbar wrapping on its own, it can use the TBSTYLE_WRAPABLE
 +* flag, and set the TBSTATE_WRAP flags manually on the appropriate items.
 +*
-       !(infoPtr->dwExStyle & TBSTYLE_EX_UNDOC1) )  return;
++* Note: TBSTYLE_WRAPABLE or TBSTYLE_EX_VERTICAL can be used also to allow
 +* vertical toolbar lists.
 +*/
 +
 +static void
 +TOOLBAR_WrapToolbar(TOOLBAR_INFO *infoPtr)
 +{
 +    TBUTTON_INFO *btnPtr;
 +    INT x, cx, i, j;
 +    RECT rc;
 +    BOOL bButtonWrap;
 +
 +    /*        When the toolbar window style is not TBSTYLE_WRAPABLE,  */
 +    /*        no layout is necessary. Applications may use this style */
 +    /*        to perform their own layout on the toolbar.             */
 +    if( !(infoPtr->dwStyle & TBSTYLE_WRAPABLE) &&
-     if ((infoPtr->dwStyle & TBSTYLE_WRAPABLE) || (infoPtr->dwExStyle & TBSTYLE_EX_UNDOC1))
++      !(infoPtr->dwExStyle & TBSTYLE_EX_VERTICAL) )  return;
 +
 +    btnPtr = infoPtr->buttons;
 +    x  = infoPtr->nIndent;
 +
 +    if (GetParent(infoPtr->hwndSelf))
 +    {
 +        /* this can get the parents width, to know how far we can extend
 +         * this toolbar.  We cannot use its height, as there may be multiple
 +         * toolbars in a rebar control
 +         */
 +        GetClientRect( GetParent(infoPtr->hwndSelf), &rc );
 +        infoPtr->nWidth = rc.right - rc.left;
 +    }
 +    else
 +    {
 +        GetWindowRect( infoPtr->hwndSelf, &rc );
 +        infoPtr->nWidth = rc.right - rc.left;
 +    }
 +
 +    bButtonWrap = FALSE;
 +
 +    TRACE("start ButtonWidth=%d, BitmapWidth=%d, nWidth=%d, nIndent=%d\n",
 +        infoPtr->nButtonWidth, infoPtr->nBitmapWidth, infoPtr->nWidth,
 +        infoPtr->nIndent);
 +
 +    for (i = 0; i < infoPtr->nNumButtons; i++ )
 +    {
 +      btnPtr[i].fsState &= ~TBSTATE_WRAP;
 +
 +      if (btnPtr[i].fsState & TBSTATE_HIDDEN)
 +          continue;
 +
 +        if (btnPtr[i].cx > 0)
 +            cx = btnPtr[i].cx;
 +        /* horizontal separators are treated as buttons for width    */
 +      else if ((btnPtr[i].fsStyle & BTNS_SEP) &&
 +            !(infoPtr->dwStyle & CCS_VERT))
 +            cx = (btnPtr[i].iBitmap > 0) ? btnPtr[i].iBitmap : SEPARATOR_WIDTH;
 +      else
 +          cx = infoPtr->nButtonWidth;
 +
 +      /* Two or more adjacent separators form a separator group.   */
 +      /* The first separator in a group should be wrapped to the   */
 +      /* next row if the previous wrapping is on a button.         */
 +      if( bButtonWrap &&
 +              (btnPtr[i].fsStyle & BTNS_SEP) &&
 +              (i + 1 < infoPtr->nNumButtons ) &&
 +              (btnPtr[i + 1].fsStyle & BTNS_SEP) )
 +      {
 +          TRACE("wrap point 1 btn %d style %02x\n", i, btnPtr[i].fsStyle);
 +          btnPtr[i].fsState |= TBSTATE_WRAP;
 +          x = infoPtr->nIndent;
 +          i++;
 +          bButtonWrap = FALSE;
 +          continue;
 +      }
 +
 +      /* The layout makes sure the bitmap is visible, but not the button. */
 +      /* Test added to also wrap after a button that starts a row but     */
 +      /* is bigger than the area.  - GA  8/01                             */
 +      if (( x + cx - (infoPtr->nButtonWidth - infoPtr->nBitmapWidth) / 2
 +         > infoPtr->nWidth ) ||
 +          ((x == infoPtr->nIndent) && (cx > infoPtr->nWidth)))
 +      {
 +          BOOL bFound = FALSE;
 +
 +          /*  If the current button is a separator and not hidden,  */
 +          /*  go to the next until it reaches a non separator.      */
 +          /*  Wrap the last separator if it is before a button.     */
 +          while( ( ((btnPtr[i].fsStyle & BTNS_SEP) &&
 +                    !(btnPtr[i].fsStyle & BTNS_DROPDOWN)) ||
 +                   (btnPtr[i].fsState & TBSTATE_HIDDEN) ) &&
 +                      i < infoPtr->nNumButtons )
 +          {
 +              i++;
 +              bFound = TRUE;
 +          }
 +
 +          if( bFound && i < infoPtr->nNumButtons )
 +          {
 +              i--;
 +              TRACE("wrap point 2 btn %d style %02x, x=%d, cx=%d\n",
 +                    i, btnPtr[i].fsStyle, x, cx);
 +              btnPtr[i].fsState |= TBSTATE_WRAP;
 +              x = infoPtr->nIndent;
 +              bButtonWrap = FALSE;
 +              continue;
 +          }
 +          else if ( i >= infoPtr->nNumButtons)
 +              break;
 +
 +          /*  If the current button is not a separator, find the last  */
 +          /*  separator and wrap it.                                   */
 +          for ( j = i - 1; j >= 0  &&  !(btnPtr[j].fsState & TBSTATE_WRAP); j--)
 +          {
 +              if ((btnPtr[j].fsStyle & BTNS_SEP) &&
 +                      !(btnPtr[j].fsState & TBSTATE_HIDDEN))
 +              {
 +                  bFound = TRUE;
 +                  i = j;
 +                  TRACE("wrap point 3 btn %d style %02x, x=%d, cx=%d\n",
 +                        i, btnPtr[i].fsStyle, x, cx);
 +                  x = infoPtr->nIndent;
 +                  btnPtr[j].fsState |= TBSTATE_WRAP;
 +                  bButtonWrap = FALSE;
 +                  break;
 +              }
 +          }
 +
 +          /*  If no separator available for wrapping, wrap one of     */
 +          /*  non-hidden previous button.                             */
 +          if (!bFound)
 +          {
 +              for ( j = i - 1;
 +                      j >= 0 && !(btnPtr[j].fsState & TBSTATE_WRAP); j--)
 +              {
 +                  if (btnPtr[j].fsState & TBSTATE_HIDDEN)
 +                      continue;
 +
 +                  bFound = TRUE;
 +                  i = j;
 +                  TRACE("wrap point 4 btn %d style %02x, x=%d, cx=%d\n",
 +                        i, btnPtr[i].fsStyle, x, cx);
 +                  x = infoPtr->nIndent;
 +                  btnPtr[j].fsState |= TBSTATE_WRAP;
 +                  bButtonWrap = TRUE;
 +                  break;
 +              }
 +          }
 +
 +          /* If all above failed, wrap the current button. */
 +          if (!bFound)
 +          {
 +              TRACE("wrap point 5 btn %d style %02x, x=%d, cx=%d\n",
 +                    i, btnPtr[i].fsStyle, x, cx);
 +              btnPtr[i].fsState |= TBSTATE_WRAP;
 +              x = infoPtr->nIndent;
 +              if (btnPtr[i].fsStyle & BTNS_SEP )
 +                  bButtonWrap = FALSE;
 +              else
 +                  bButtonWrap = TRUE;
 +          }
 +      }
 +      else {
 +          TRACE("wrap point 6 btn %d style %02x, x=%d, cx=%d\n",
 +                i, btnPtr[i].fsStyle, x, cx);
 +          x += cx;
 +      }
 +    }
 +}
 +
 +
 +/***********************************************************************
 +*             TOOLBAR_MeasureButton
 +*
 +* Calculates the width and height required for a button. Used in
 +* TOOLBAR_CalcToolbar to set the all-button width and height and also for
 +* the width of buttons that are autosized.
 +*
 +* Note that it would have been rather elegant to use one piece of code for
 +* both the laying out of the toolbar and for controlling where button parts
 +* are drawn, but the native control has inconsistencies between the two that
 +* prevent this from being effectively. These inconsistencies can be seen as
 +* artefacts where parts of the button appear outside of the bounding button
 +* rectangle.
 +*
 +* There are several cases for the calculation of the button dimensions and
 +* button part positioning:
 +*
 +* List
 +* ====
 +*
 +* With Bitmap:
 +*
 +* +--------------------------------------------------------+ ^
 +* |                    ^                     ^             | |
 +* |                    | pad.cy / 2          | centered    | |
 +* | pad.cx/2 + cxedge +--------------+     +------------+  | | DEFPAD_CY +
 +* |<----------------->| nBitmapWidth |     | Text       |  | | max(nBitmapHeight, szText.cy)
 +* |                   |<------------>|     |            |  | |
 +* |                   +--------------+     +------------+  | |
 +* |<-------------------------------------->|               | |
 +* |  cxedge + iListGap + nBitmapWidth + 2  |<----------->  | |
 +* |                                           szText.cx    | |
 +* +--------------------------------------------------------+ -
 +* <-------------------------------------------------------->
 +*  2*cxedge + nBitmapWidth + iListGap + szText.cx + pad.cx
 +*
 +* Without Bitmap (I_IMAGENONE):
 +*
 +* +-----------------------------------+ ^
 +* |                     ^             | |
 +* |                     | centered    | | LISTPAD_CY +
 +* |                   +------------+  | | szText.cy
 +* |                   | Text       |  | |
 +* |                   |            |  | |
 +* |                   +------------+  | |
 +* |<----------------->|               | |
 +* |      cxedge       |<----------->  | |
 +* |                      szText.cx    | |
 +* +-----------------------------------+ -
 +* <----------------------------------->
 +*          szText.cx + pad.cx
 +*
 +* Without text:
 +*
 +* +--------------------------------------+ ^
 +* |                       ^              | |
 +* |                       | padding.cy/2 | | DEFPAD_CY +
 +* |                     +------------+   | | nBitmapHeight
 +* |                     | Bitmap     |   | |
 +* |                     |            |   | |
 +* |                     +------------+   | |
 +* |<------------------->|                | |
 +* | cxedge + iListGap/2 |<----------->   | |
 +* |                       nBitmapWidth   | |
 +* +--------------------------------------+ -
 +* <-------------------------------------->
 +*     2*cxedge + nBitmapWidth + iListGap
 +*
 +* Non-List
 +* ========
 +*
 +* With bitmap:
 +*
 +* +-----------------------------------+ ^
 +* |                     ^             | |
 +* |                     | pad.cy / 2  | | nBitmapHeight +
 +* |                     -             | | szText.cy +
 +* |                   +------------+  | | DEFPAD_CY + 1
 +* |    centered       |   Bitmap   |  | |
 +* |<----------------->|            |  | |
 +* |                   +------------+  | |
 +* |                         ^         | |
 +* |                       1 |         | |
 +* |                         -         | |
 +* |     centered    +---------------+ | |
 +* |<--------------->|      Text     | | |
 +* |                 +---------------+ | |
 +* +-----------------------------------+ -
 +* <----------------------------------->
 +* pad.cx + max(nBitmapWidth, szText.cx)
 +*
 +* Without bitmaps (NULL imagelist or ImageList_GetImageCount() = 0):
 +*
 +* +---------------------------------------+ ^
 +* |                     ^                 | |
 +* |                     | 2 + pad.cy / 2  | |
 +* |                     -                 | | szText.cy +
 +* |    centered     +-----------------+   | | pad.cy + 2
 +* |<--------------->|   Text          |   | |
 +* |                 +-----------------+   | |
 +* |                                       | |
 +* +---------------------------------------+ -
 +* <--------------------------------------->
 +*          2*cxedge + pad.cx + szText.cx
 +*
 +* Without text:
 +*   As for with bitmaps, but with szText.cx zero.
 +*/
 +static inline SIZE TOOLBAR_MeasureButton(const TOOLBAR_INFO *infoPtr, SIZE sizeString,
 +                                         BOOL bHasBitmap, BOOL bValidImageList)
 +{
 +    SIZE sizeButton;
 +    if (infoPtr->dwStyle & TBSTYLE_LIST)
 +    {
 +        /* set button height from bitmap / text height... */
 +        sizeButton.cy = max((bHasBitmap ? infoPtr->nBitmapHeight : 0),
 +            sizeString.cy);
 +
 +        /* ... add on the necessary padding */
 +        if (bValidImageList)
 +        {
 +            if (bHasBitmap)
 +                sizeButton.cy += DEFPAD_CY;
 +            else
 +                sizeButton.cy += LISTPAD_CY;
 +        }
 +        else
 +            sizeButton.cy += infoPtr->szPadding.cy;
 +
 +        /* calculate button width */
 +        sizeButton.cx = 2*GetSystemMetrics(SM_CXEDGE) +
 +            infoPtr->nBitmapWidth + infoPtr->iListGap;
 +        if (sizeString.cx > 0)
 +            sizeButton.cx += sizeString.cx + infoPtr->szPadding.cx;
 +
 +    }
 +    else
 +    {
 +        if (bHasBitmap)
 +        {
 +            sizeButton.cy = infoPtr->nBitmapHeight + DEFPAD_CY;
 +            if (sizeString.cy > 0)
 +                sizeButton.cy += 1 + sizeString.cy;
 +            sizeButton.cx = infoPtr->szPadding.cx +
 +                max(sizeString.cx, infoPtr->nBitmapWidth);
 +        }
 +        else
 +        {
 +            sizeButton.cy = sizeString.cy + infoPtr->szPadding.cy +
 +                NONLIST_NOTEXT_OFFSET;
 +            sizeButton.cx = infoPtr->szPadding.cx +
 +                max(2*GetSystemMetrics(SM_CXEDGE) + sizeString.cx, infoPtr->nBitmapWidth);
 +        }
 +    }
 +    return sizeButton;
 +}
 +
 +
 +/***********************************************************************
 +*             TOOLBAR_CalcToolbar
 +*
 +* This function calculates button and separator placement. It first
 +* calculates the button sizes, gets the toolbar window width and then
 +* calls TOOLBAR_WrapToolbar to determine which buttons we need to wrap
 +* on. It assigns a new location to each item and sends this location to
 +* the tooltip window if appropriate. Finally, it updates the rcBound
 +* rect and calculates the new required toolbar window height.
 +*/
 +static void
 +TOOLBAR_CalcToolbar (TOOLBAR_INFO *infoPtr)
 +{
 +    SIZE  sizeString, sizeButton;
 +    BOOL validImageList = FALSE;
 +
 +    TOOLBAR_CalcStrings (infoPtr, &sizeString);
 +
 +    TOOLBAR_DumpToolbar (infoPtr, __LINE__);
 +
 +    if (TOOLBAR_IsValidImageList(infoPtr, 0))
 +        validImageList = TRUE;
 +    sizeButton = TOOLBAR_MeasureButton(infoPtr, sizeString, TRUE, validImageList);
 +    infoPtr->nButtonWidth = sizeButton.cx;
 +    infoPtr->nButtonHeight = sizeButton.cy;
 +    infoPtr->iTopMargin = default_top_margin(infoPtr);
 +
 +    if ( infoPtr->cxMin >= 0 && infoPtr->nButtonWidth < infoPtr->cxMin )
 +        infoPtr->nButtonWidth = infoPtr->cxMin;
 +    if ( infoPtr->cxMax > 0 && infoPtr->nButtonWidth > infoPtr->cxMax )
 +        infoPtr->nButtonWidth = infoPtr->cxMax;
 +
 +    TOOLBAR_LayoutToolbar(infoPtr);
 +}
 +
 +static void
 +TOOLBAR_LayoutToolbar(TOOLBAR_INFO *infoPtr)
 +{
 +    TBUTTON_INFO *btnPtr;
 +    SIZE sizeButton;
 +    INT i, nRows, nSepRows;
 +    INT x, y, cx, cy;
 +    BOOL bWrap;
 +    BOOL validImageList = TOOLBAR_IsValidImageList(infoPtr, 0);
 +    BOOL hasDropDownArrows = TOOLBAR_HasDropDownArrows(infoPtr->dwExStyle);
 +
 +    TOOLBAR_WrapToolbar(infoPtr);
 +
 +    x  = infoPtr->nIndent;
 +    y  = infoPtr->iTopMargin;
 +    cx = infoPtr->nButtonWidth;
 +    cy = infoPtr->nButtonHeight;
 +
 +    nRows = nSepRows = 0;
 +
 +    infoPtr->rcBound.top = y;
 +    infoPtr->rcBound.left = x;
 +    infoPtr->rcBound.bottom = y + cy;
 +    infoPtr->rcBound.right = x;
 +
 +    btnPtr = infoPtr->buttons;
 +
 +    TRACE("cy=%d\n", cy);
 +
 +    for (i = 0; i < infoPtr->nNumButtons; i++, btnPtr++ )
 +    {
 +      bWrap = FALSE;
 +      if (btnPtr->fsState & TBSTATE_HIDDEN)
 +      {
 +          SetRectEmpty (&btnPtr->rect);
 +          continue;
 +      }
 +
 +      cy = infoPtr->nButtonHeight;
 +
 +      if (btnPtr->fsStyle & BTNS_SEP) {
 +          if (infoPtr->dwStyle & CCS_VERT) {
 +                cy = (btnPtr->iBitmap > 0) ? btnPtr->iBitmap : SEPARATOR_WIDTH;
 +                cx = (btnPtr->cx > 0) ? btnPtr->cx : infoPtr->nButtonWidth;
 +          }
 +          else
 +                cx = (btnPtr->cx > 0) ? btnPtr->cx :
 +                    (btnPtr->iBitmap > 0) ? btnPtr->iBitmap : SEPARATOR_WIDTH;
 +      }
 +      else
 +      {
 +            if (btnPtr->cx)
 +              cx = btnPtr->cx;
 +            else if ((infoPtr->dwExStyle & TBSTYLE_EX_MIXEDBUTTONS) || 
 +                (btnPtr->fsStyle & BTNS_AUTOSIZE))
 +            {
 +              SIZE sz;
 +            HDC hdc;
 +            HFONT hOldFont;
 +
 +            hdc = GetDC (infoPtr->hwndSelf);
 +            hOldFont = SelectObject (hdc, infoPtr->hFont);
 +
 +              TOOLBAR_MeasureString(infoPtr, btnPtr, hdc, &sz);
 +
 +            SelectObject (hdc, hOldFont);
 +            ReleaseDC (infoPtr->hwndSelf, hdc);
 +
 +              sizeButton = TOOLBAR_MeasureButton(infoPtr, sz,
 +                  TOOLBAR_IsValidBitmapIndex(infoPtr, infoPtr->buttons[i].iBitmap),
 +                  validImageList);
 +              cx = sizeButton.cx;
 +            }
 +            else
 +            cx = infoPtr->nButtonWidth;
 +
 +            /* if size has been set manually then don't add on extra space
 +             * for the drop down arrow */
 +          if (!btnPtr->cx && hasDropDownArrows && 
 +                ((btnPtr->fsStyle & BTNS_DROPDOWN) || (btnPtr->fsStyle & BTNS_WHOLEDROPDOWN)))
 +            cx += DDARROW_WIDTH;
 +      }
 +      if (btnPtr->fsState & TBSTATE_WRAP )
 +                  bWrap = TRUE;
 +
 +      SetRect (&btnPtr->rect, x, y, x + cx, y + cy);
 +
 +      if (infoPtr->rcBound.left > x)
 +          infoPtr->rcBound.left = x;
 +      if (infoPtr->rcBound.right < x + cx)
 +          infoPtr->rcBound.right = x + cx;
 +      if (infoPtr->rcBound.bottom < y + cy)
 +          infoPtr->rcBound.bottom = y + cy;
 +
 +        TOOLBAR_TooltipSetRect(infoPtr, btnPtr);
 +
 +      /* btnPtr->nRow is zero based. The space between the rows is    */
 +      /* also considered as a row.                                    */
 +      btnPtr->nRow = nRows + nSepRows;
 +
 +      TRACE("button %d style=%x, bWrap=%d, nRows=%d, nSepRows=%d, btnrow=%d, (%d,%d)-(%d,%d)\n",
 +            i, btnPtr->fsStyle, bWrap, nRows, nSepRows, btnPtr->nRow,
 +            x, y, x+cx, y+cy);
 +
 +      if( bWrap )
 +      {
 +          if ( !(btnPtr->fsStyle & BTNS_SEP) )
 +              y += cy;
 +          else
 +          {
 +               if ( !(infoPtr->dwStyle & CCS_VERT))
 +                    y += cy + ( (btnPtr->cx > 0 ) ?
 +                                btnPtr->cx : SEPARATOR_WIDTH) * 2 /3;
 +              else
 +                  y += cy;
 +
 +              /* nSepRows is used to calculate the extra height following  */
 +              /* the last row.                                             */
 +              nSepRows++;
 +          }
 +          x = infoPtr->nIndent;
 +
 +          /* Increment row number unless this is the last button    */
 +          /* and it has Wrap set.                                   */
 +          if (i != infoPtr->nNumButtons-1)
 +              nRows++;
 +      }
 +      else
 +          x += cx;
 +    }
 +
 +    /* infoPtr->nRows is the number of rows on the toolbar */
 +    infoPtr->nRows = nRows + nSepRows + 1;
 +
 +    TRACE("toolbar button width %d\n", infoPtr->nButtonWidth);
 +}
 +
 +
 +static INT
 +TOOLBAR_InternalHitTest (const TOOLBAR_INFO *infoPtr, const POINT *lpPt, BOOL *button)
 +{
 +    TBUTTON_INFO *btnPtr;
 +    INT i;
 +
 +    if (button)
 +        *button = FALSE;
 +
 +    btnPtr = infoPtr->buttons;
 +    for (i = 0; i < infoPtr->nNumButtons; i++, btnPtr++) {
 +      if (btnPtr->fsState & TBSTATE_HIDDEN)
 +          continue;
 +
 +      if (btnPtr->fsStyle & BTNS_SEP) {
 +          if (PtInRect (&btnPtr->rect, *lpPt)) {
 +              TRACE(" ON SEPARATOR %d!\n", i);
 +              return -i;
 +          }
 +      }
 +      else {
 +          if (PtInRect (&btnPtr->rect, *lpPt)) {
 +              TRACE(" ON BUTTON %d!\n", i);
 +                if (button)
 +                    *button = TRUE;
 +              return i;
 +          }
 +      }
 +    }
 +
 +    TRACE(" NOWHERE!\n");
 +    return TOOLBAR_NOWHERE;
 +}
 +
 +
 +/* worker for TB_ADDBUTTONS and TB_INSERTBUTTON */
 +static BOOL
 +TOOLBAR_InternalInsertButtonsT(TOOLBAR_INFO *infoPtr, INT iIndex, UINT nAddButtons, const TBBUTTON *lpTbb, BOOL fUnicode)
 +{
 +    INT nOldButtons, nNewButtons, iButton;
 +    BOOL fHasString = FALSE;
 +
 +    if (iIndex < 0)  /* iIndex can be negative, what means adding at the end */
 +        iIndex = infoPtr->nNumButtons;
 +
 +    nOldButtons = infoPtr->nNumButtons;
 +    nNewButtons = nOldButtons + nAddButtons;
 +
 +    infoPtr->buttons = ReAlloc(infoPtr->buttons, sizeof(TBUTTON_INFO)*nNewButtons);
 +    memmove(&infoPtr->buttons[iIndex + nAddButtons], &infoPtr->buttons[iIndex],
 +            (nOldButtons - iIndex) * sizeof(TBUTTON_INFO));
 +    infoPtr->nNumButtons += nAddButtons;
 +
 +    /* insert new buttons data */
 +    for (iButton = 0; iButton < nAddButtons; iButton++) {
 +        TBUTTON_INFO *btnPtr = &infoPtr->buttons[iIndex + iButton];
 +
 +        TOOLBAR_DumpTBButton(lpTbb + iButton, fUnicode);
 +
 +        ZeroMemory(btnPtr, sizeof(*btnPtr));
 +
 +        btnPtr->iBitmap   = lpTbb[iButton].iBitmap;
 +        btnPtr->idCommand = lpTbb[iButton].idCommand;
 +        btnPtr->fsState   = lpTbb[iButton].fsState;
 +        btnPtr->fsStyle   = lpTbb[iButton].fsStyle;
 +        btnPtr->dwData    = lpTbb[iButton].dwData;
 +        if (btnPtr->fsStyle & BTNS_SEP)
 +            btnPtr->iString = -1;
 +        else if(!IS_INTRESOURCE(lpTbb[iButton].iString) && lpTbb[iButton].iString != -1)
 +        {
 +            if (fUnicode)
 +                Str_SetPtrW((LPWSTR*)&btnPtr->iString, (LPWSTR)lpTbb[iButton].iString );
 +            else
 +                Str_SetPtrAtoW((LPWSTR*)&btnPtr->iString, (LPSTR)lpTbb[iButton].iString);
 +            fHasString = TRUE;
 +        }
 +        else
 +            btnPtr->iString   = lpTbb[iButton].iString;
 +
 +        TOOLBAR_TooltipAddTool(infoPtr, btnPtr);
 +    }
 +
 +    if (infoPtr->nNumStrings > 0 || fHasString)
 +        TOOLBAR_CalcToolbar(infoPtr);
 +    else
 +        TOOLBAR_LayoutToolbar(infoPtr);
 +    TOOLBAR_AutoSize(infoPtr);
 +
 +    TOOLBAR_DumpToolbar(infoPtr, __LINE__);
 +    InvalidateRect(infoPtr->hwndSelf, NULL, TRUE);
 +    return TRUE;
 +}
 +
 +
 +static INT
 +TOOLBAR_GetButtonIndex (const TOOLBAR_INFO *infoPtr, INT idCommand, BOOL CommandIsIndex)
 +{
 +    TBUTTON_INFO *btnPtr;
 +    INT i;
 +
 +    if (CommandIsIndex) {
 +      TRACE("command is really index command=%d\n", idCommand);
 +      if (idCommand >= infoPtr->nNumButtons) return -1;
 +      return idCommand;
 +    }
 +    btnPtr = infoPtr->buttons;
 +    for (i = 0; i < infoPtr->nNumButtons; i++, btnPtr++) {
 +      if (btnPtr->idCommand == idCommand) {
 +          TRACE("command=%d index=%d\n", idCommand, i);
 +          return i;
 +      }
 +    }
 +    TRACE("no index found for command=%d\n", idCommand);
 +    return -1;
 +}
 +
 +
 +static INT
 +TOOLBAR_GetCheckedGroupButtonIndex (const TOOLBAR_INFO *infoPtr, INT nIndex)
 +{
 +    TBUTTON_INFO *btnPtr;
 +    INT nRunIndex;
 +
 +    if ((nIndex < 0) || (nIndex > infoPtr->nNumButtons))
 +      return -1;
 +
 +    /* check index button */
 +    btnPtr = &infoPtr->buttons[nIndex];
 +    if ((btnPtr->fsStyle & BTNS_CHECKGROUP) == BTNS_CHECKGROUP) {
 +      if (btnPtr->fsState & TBSTATE_CHECKED)
 +          return nIndex;
 +    }
 +
 +    /* check previous buttons */
 +    nRunIndex = nIndex - 1;
 +    while (nRunIndex >= 0) {
 +      btnPtr = &infoPtr->buttons[nRunIndex];
 +      if ((btnPtr->fsStyle & BTNS_GROUP) == BTNS_GROUP) {
 +          if (btnPtr->fsState & TBSTATE_CHECKED)
 +              return nRunIndex;
 +      }
 +      else
 +          break;
 +      nRunIndex--;
 +    }
 +
 +    /* check next buttons */
 +    nRunIndex = nIndex + 1;
 +    while (nRunIndex < infoPtr->nNumButtons) {
 +      btnPtr = &infoPtr->buttons[nRunIndex];
 +      if ((btnPtr->fsStyle & BTNS_GROUP) == BTNS_GROUP) {
 +          if (btnPtr->fsState & TBSTATE_CHECKED)
 +              return nRunIndex;
 +      }
 +      else
 +          break;
 +      nRunIndex++;
 +    }
 +
 +    return -1;
 +}
 +
 +
 +static VOID
 +TOOLBAR_RelayEvent (HWND hwndTip, HWND hwndMsg, UINT uMsg,
 +                  WPARAM wParam, LPARAM lParam)
 +{
 +    MSG msg;
 +
 +    msg.hwnd = hwndMsg;
 +    msg.message = uMsg;
 +    msg.wParam = wParam;
 +    msg.lParam = lParam;
 +    msg.time = GetMessageTime ();
 +    msg.pt.x = (short)LOWORD(GetMessagePos ());
 +    msg.pt.y = (short)HIWORD(GetMessagePos ());
 +
 +    SendMessageW (hwndTip, TTM_RELAYEVENT, 0, (LPARAM)&msg);
 +}
 +
 +static void
 +TOOLBAR_TooltipAddTool(const TOOLBAR_INFO *infoPtr, const TBUTTON_INFO *button)
 +{
 +    if (infoPtr->hwndToolTip && !(button->fsStyle & BTNS_SEP)) {
 +        TTTOOLINFOW ti;
 +
 +        ZeroMemory(&ti, sizeof(TTTOOLINFOW));
 +        ti.cbSize   = sizeof (TTTOOLINFOW);
 +        ti.hwnd     = infoPtr->hwndSelf;
 +        ti.uId      = button->idCommand;
 +        ti.hinst    = 0;
 +        ti.lpszText = LPSTR_TEXTCALLBACKW;
 +        /* ti.lParam = random value from the stack? */
 +
 +        SendMessageW(infoPtr->hwndToolTip, TTM_ADDTOOLW,
 +            0, (LPARAM)&ti);
 +    }
 +}
 +
 +static void
 +TOOLBAR_TooltipDelTool(const TOOLBAR_INFO *infoPtr, const TBUTTON_INFO *button)
 +{
 +    if ((infoPtr->hwndToolTip) && !(button->fsStyle & BTNS_SEP)) {
 +        TTTOOLINFOW ti;
 +
 +        ZeroMemory(&ti, sizeof(ti));
 +        ti.cbSize   = sizeof(ti);
 +        ti.hwnd     = infoPtr->hwndSelf;
 +        ti.uId      = button->idCommand;
 +
 +        SendMessageW(infoPtr->hwndToolTip, TTM_DELTOOLW, 0, (LPARAM)&ti);
 +    }
 +}
 +
 +static void TOOLBAR_TooltipSetRect(const TOOLBAR_INFO *infoPtr, const TBUTTON_INFO *button)
 +{
 +    /* Set the toolTip only for non-hidden, non-separator button */
 +    if (infoPtr->hwndToolTip && !(button->fsStyle & BTNS_SEP))
 +    {
 +        TTTOOLINFOW ti;
 +
 +        ZeroMemory(&ti, sizeof(ti));
 +        ti.cbSize = sizeof(ti);
 +        ti.hwnd = infoPtr->hwndSelf;
 +        ti.uId = button->idCommand;
 +        ti.rect = button->rect;
 +        SendMessageW(infoPtr->hwndToolTip, TTM_NEWTOOLRECTW, 0, (LPARAM)&ti);
 +    }
 +}
 +
 +/* Creates the tooltip control */
 +static void
 +TOOLBAR_TooltipCreateControl(TOOLBAR_INFO *infoPtr)
 +{
 +    int i;
 +    NMTOOLTIPSCREATED nmttc;
 +
 +    infoPtr->hwndToolTip = CreateWindowExW(0, TOOLTIPS_CLASSW, NULL, WS_POPUP,
 +            CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT,
 +            infoPtr->hwndSelf, 0, 0, 0);
 +
 +    if (!infoPtr->hwndToolTip)
 +        return;
 +
 +    /* Send NM_TOOLTIPSCREATED notification */
 +    nmttc.hwndToolTips = infoPtr->hwndToolTip;
 +    TOOLBAR_SendNotify(&nmttc.hdr, infoPtr, NM_TOOLTIPSCREATED);
 +
 +    for (i = 0; i < infoPtr->nNumButtons; i++)
 +    {
 +        TOOLBAR_TooltipAddTool(infoPtr, &infoPtr->buttons[i]);
 +        TOOLBAR_TooltipSetRect(infoPtr, &infoPtr->buttons[i]);
 +    }
 +}
 +
 +/* keeps available button list box sorted by button id */
 +static void TOOLBAR_Cust_InsertAvailButton(HWND hwnd, PCUSTOMBUTTON btnInfoNew)
 +{
 +    int i;
 +    int count;
 +    PCUSTOMBUTTON btnInfo;
 +    HWND hwndAvail = GetDlgItem(hwnd, IDC_AVAILBTN_LBOX);
 +
 +    TRACE("button %s, idCommand %d\n", debugstr_w(btnInfoNew->text), btnInfoNew->btn.idCommand);
 +
 +    count = SendMessageW(hwndAvail, LB_GETCOUNT, 0, 0);
 +
 +    /* position 0 is always separator */
 +    for (i = 1; i < count; i++)
 +    {
 +        btnInfo = (PCUSTOMBUTTON)SendMessageW(hwndAvail, LB_GETITEMDATA, i, 0);
 +        if (btnInfoNew->btn.idCommand < btnInfo->btn.idCommand)
 +        {
 +            i = SendMessageW(hwndAvail, LB_INSERTSTRING, i, 0);
 +            SendMessageW(hwndAvail, LB_SETITEMDATA, i, (LPARAM)btnInfoNew);
 +            return;
 +        }
 +    }
 +    /* id higher than all others add to end */
 +    i = SendMessageW(hwndAvail, LB_ADDSTRING, 0, 0);
 +    SendMessageW(hwndAvail, LB_SETITEMDATA, i, (LPARAM)btnInfoNew);
 +}
 +
 +static void TOOLBAR_Cust_MoveButton(const CUSTDLG_INFO *custInfo, HWND hwnd, INT nIndexFrom, INT nIndexTo)
 +{
 +    NMTOOLBARW nmtb;
 +
 +      TRACE("index from %d, index to %d\n", nIndexFrom, nIndexTo);
 +
 +    if (nIndexFrom == nIndexTo)
 +        return;
 +
 +    /* MSDN states that iItem is the index of the button, rather than the
 +     * command ID as used by every other NMTOOLBAR notification */
 +    nmtb.iItem = nIndexFrom;
 +    if (TOOLBAR_SendNotify(&nmtb.hdr, custInfo->tbInfo, TBN_QUERYINSERT))
 +    {
 +        PCUSTOMBUTTON btnInfo;
 +        NMHDR hdr;
 +        HWND hwndList = GetDlgItem(hwnd, IDC_TOOLBARBTN_LBOX);
 +        int count = SendMessageW(hwndList, LB_GETCOUNT, 0, 0);
 +
 +        btnInfo = (PCUSTOMBUTTON)SendMessageW(hwndList, LB_GETITEMDATA, nIndexFrom, 0);
 +
 +        SendMessageW(hwndList, LB_DELETESTRING, nIndexFrom, 0);
 +        SendMessageW(hwndList, LB_INSERTSTRING, nIndexTo, 0);
 +        SendMessageW(hwndList, LB_SETITEMDATA, nIndexTo, (LPARAM)btnInfo);
 +        SendMessageW(hwndList, LB_SETCURSEL, nIndexTo, 0);
 +
 +        if (nIndexTo <= 0)
 +            EnableWindow(GetDlgItem(hwnd,IDC_MOVEUP_BTN), FALSE);
 +        else
 +            EnableWindow(GetDlgItem(hwnd,IDC_MOVEUP_BTN), TRUE);
 +
 +        /* last item is always separator, so -2 instead of -1 */
 +        if (nIndexTo >= (count - 2))
 +            EnableWindow(GetDlgItem(hwnd,IDC_MOVEDN_BTN), FALSE);
 +        else
 +            EnableWindow(GetDlgItem(hwnd,IDC_MOVEDN_BTN), TRUE);
 +
 +        SendMessageW(custInfo->tbHwnd, TB_DELETEBUTTON, nIndexFrom, 0);
 +        SendMessageW(custInfo->tbHwnd, TB_INSERTBUTTONW, nIndexTo, (LPARAM)&(btnInfo->btn));
 +
 +        TOOLBAR_SendNotify(&hdr, custInfo->tbInfo, TBN_TOOLBARCHANGE);
 +    }
 +}
 +
 +static void TOOLBAR_Cust_AddButton(const CUSTDLG_INFO *custInfo, HWND hwnd, INT nIndexAvail, INT nIndexTo)
 +{
 +    NMTOOLBARW nmtb;
 +
 +    TRACE("Add: nIndexAvail %d, nIndexTo %d\n", nIndexAvail, nIndexTo);
 +
 +    /* MSDN states that iItem is the index of the button, rather than the
 +     * command ID as used by every other NMTOOLBAR notification */
 +    nmtb.iItem = nIndexAvail;
 +    if (TOOLBAR_SendNotify(&nmtb.hdr, custInfo->tbInfo, TBN_QUERYINSERT))
 +    {
 +        PCUSTOMBUTTON btnInfo;
 +        NMHDR hdr;
 +        HWND hwndList = GetDlgItem(hwnd, IDC_TOOLBARBTN_LBOX);
 +        HWND hwndAvail = GetDlgItem(hwnd, IDC_AVAILBTN_LBOX);
 +        int count = SendMessageW(hwndAvail, LB_GETCOUNT, 0, 0);
 +
 +        btnInfo = (PCUSTOMBUTTON)SendMessageW(hwndAvail, LB_GETITEMDATA, nIndexAvail, 0);
 +
 +        if (nIndexAvail != 0) /* index == 0 indicates separator */
 +        {
 +            /* remove from 'available buttons' list */
 +            SendMessageW(hwndAvail, LB_DELETESTRING, nIndexAvail, 0);
 +            if (nIndexAvail == count-1)
 +                SendMessageW(hwndAvail, LB_SETCURSEL, nIndexAvail-1 , 0);
 +            else
 +                SendMessageW(hwndAvail, LB_SETCURSEL, nIndexAvail , 0);
 +        }
 +        else
 +        {
 +            PCUSTOMBUTTON btnNew;
 +
 +            /* duplicate 'separator' button */
 +            btnNew = Alloc(sizeof(CUSTOMBUTTON));
 +            *btnNew = *btnInfo;
 +            btnInfo = btnNew;
 +        }
 +
 +        /* insert into 'toolbar button' list */
 +        SendMessageW(hwndList, LB_INSERTSTRING, nIndexTo, 0);
 +        SendMessageW(hwndList, LB_SETITEMDATA, nIndexTo, (LPARAM)btnInfo);
 +
 +        SendMessageW(custInfo->tbHwnd, TB_INSERTBUTTONW, nIndexTo, (LPARAM)&(btnInfo->btn));
 +
 +        TOOLBAR_SendNotify(&hdr, custInfo->tbInfo, TBN_TOOLBARCHANGE);
 +    }
 +}
 +
 +static void TOOLBAR_Cust_RemoveButton(const CUSTDLG_INFO *custInfo, HWND hwnd, INT index)
 +{
 +    PCUSTOMBUTTON btnInfo;
 +    HWND hwndList = GetDlgItem(hwnd, IDC_TOOLBARBTN_LBOX);
 +
 +    TRACE("Remove: index %d\n", index);
 +
 +    btnInfo = (PCUSTOMBUTTON)SendMessageW(hwndList, LB_GETITEMDATA, index, 0);
 +
 +    /* send TBN_QUERYDELETE notification */
 +    if (TOOLBAR_IsButtonRemovable(custInfo->tbInfo, index, btnInfo))
 +    {
 +        NMHDR hdr;
 +
 +        SendMessageW(hwndList, LB_DELETESTRING, index, 0);
 +        SendMessageW(hwndList, LB_SETCURSEL, index , 0);
 +
 +        SendMessageW(custInfo->tbHwnd, TB_DELETEBUTTON, index, 0);
 +
 +        /* insert into 'available button' list */
 +        if (!(btnInfo->btn.fsStyle & BTNS_SEP))
 +            TOOLBAR_Cust_InsertAvailButton(hwnd, btnInfo);
 +        else
 +            Free(btnInfo);
 +
 +        TOOLBAR_SendNotify(&hdr, custInfo->tbInfo, TBN_TOOLBARCHANGE);
 +    }
 +}
 +
 +/* drag list notification function for toolbar buttons list box */
 +static LRESULT TOOLBAR_Cust_ToolbarDragListNotification(const CUSTDLG_INFO *custInfo, HWND hwnd,
 +                                                        const DRAGLISTINFO *pDLI)
 +{
 +    HWND hwndList = GetDlgItem(hwnd, IDC_TOOLBARBTN_LBOX);
 +    switch (pDLI->uNotification)
 +    {
 +    case DL_BEGINDRAG:
 +    {
 +        INT nCurrentItem = LBItemFromPt(hwndList, pDLI->ptCursor, TRUE);
 +        INT nCount = SendMessageW(hwndList, LB_GETCOUNT, 0, 0);
 +        /* no dragging for last item (separator) */
 +        if (nCurrentItem >= (nCount - 1)) return FALSE;
 +        return TRUE;
 +    }
 +    case DL_DRAGGING:
 +    {
 +        INT nCurrentItem = LBItemFromPt(hwndList, pDLI->ptCursor, TRUE);
 +        INT nCount = SendMessageW(hwndList, LB_GETCOUNT, 0, 0);
 +        /* no dragging past last item (separator) */
 +        if ((nCurrentItem >= 0) && (nCurrentItem < (nCount - 1)))
 +        {
 +            DrawInsert(hwnd, hwndList, nCurrentItem);
 +            /* FIXME: native uses "move button" cursor */
 +            return DL_COPYCURSOR;
 +        }
 +
 +        /* not over toolbar buttons list */
 +        if (nCurrentItem < 0)
 +        {
 +            POINT ptWindow = pDLI->ptCursor;
 +            HWND hwndListAvail = GetDlgItem(hwnd, IDC_AVAILBTN_LBOX);
 +            MapWindowPoints(NULL, hwnd, &ptWindow, 1);
 +            /* over available buttons list? */
 +            if (ChildWindowFromPoint(hwnd, ptWindow) == hwndListAvail)
 +                /* FIXME: native uses "move button" cursor */
 +                return DL_COPYCURSOR;
 +        }
 +        /* clear drag arrow */
 +        DrawInsert(hwnd, hwndList, -1);
 +        return DL_STOPCURSOR;
 +    }
 +    case DL_DROPPED:
 +    {
 +        INT nIndexTo = LBItemFromPt(hwndList, pDLI->ptCursor, TRUE);
 +        INT nIndexFrom = SendMessageW(hwndList, LB_GETCURSEL, 0, 0);
 +        INT nCount = SendMessageW(hwndList, LB_GETCOUNT, 0, 0);
 +        if ((nIndexTo >= 0) && (nIndexTo < (nCount - 1)))
 +        {
 +            /* clear drag arrow */
 +            DrawInsert(hwnd, hwndList, -1);
 +            /* move item */
 +            TOOLBAR_Cust_MoveButton(custInfo, hwnd, nIndexFrom, nIndexTo);
 +        }
 +        /* not over toolbar buttons list */
 +        if (nIndexTo < 0)
 +        {
 +            POINT ptWindow = pDLI->ptCursor;
 +            HWND hwndListAvail = GetDlgItem(hwnd, IDC_AVAILBTN_LBOX);
 +            MapWindowPoints(NULL, hwnd, &ptWindow, 1);
 +            /* over available buttons list? */
 +            if (ChildWindowFromPoint(hwnd, ptWindow) == hwndListAvail)
 +                TOOLBAR_Cust_RemoveButton(custInfo, hwnd, nIndexFrom);
 +        }
 +        break;
 +    }
 +    case DL_CANCELDRAG:
 +        /* Clear drag arrow */
 +        DrawInsert(hwnd, hwndList, -1);
 +        break;
 +    }
 +
 +    return 0;
 +}
 +
 +/* drag list notification function for available buttons list box */
 +static LRESULT TOOLBAR_Cust_AvailDragListNotification(const CUSTDLG_INFO *custInfo, HWND hwnd,
 +                                                      const DRAGLISTINFO *pDLI)
 +{
 +    HWND hwndList = GetDlgItem(hwnd, IDC_TOOLBARBTN_LBOX);
 +    switch (pDLI->uNotification)
 +    {
 +    case DL_BEGINDRAG:
 +        return TRUE;
 +    case DL_DRAGGING:
 +    {
 +        INT nCurrentItem = LBItemFromPt(hwndList, pDLI->ptCursor, TRUE);
 +        INT nCount = SendMessageW(hwndList, LB_GETCOUNT, 0, 0);
 +        /* no dragging past last item (separator) */
 +        if ((nCurrentItem >= 0) && (nCurrentItem < nCount))
 +        {
 +            DrawInsert(hwnd, hwndList, nCurrentItem);
 +            /* FIXME: native uses "move button" cursor */
 +            return DL_COPYCURSOR;
 +        }
 +
 +        /* not over toolbar buttons list */
 +        if (nCurrentItem < 0)
 +        {
 +            POINT ptWindow = pDLI->ptCursor;
 +            HWND hwndListAvail = GetDlgItem(hwnd, IDC_AVAILBTN_LBOX);
 +            MapWindowPoints(NULL, hwnd, &ptWindow, 1);
 +            /* over available buttons list? */
 +            if (ChildWindowFromPoint(hwnd, ptWindow) == hwndListAvail)
 +                /* FIXME: native uses "move button" cursor */
 +                return DL_COPYCURSOR;
 +        }
 +        /* clear drag arrow */
 +        DrawInsert(hwnd, hwndList, -1);
 +        return DL_STOPCURSOR;
 +    }
 +    case DL_DROPPED:
 +    {
 +        INT nIndexTo = LBItemFromPt(hwndList, pDLI->ptCursor, TRUE);
 +        INT nCount = SendMessageW(hwndList, LB_GETCOUNT, 0, 0);
 +        INT nIndexFrom = SendDlgItemMessageW(hwnd, IDC_AVAILBTN_LBOX, LB_GETCURSEL, 0, 0);
 +        if ((nIndexTo >= 0) && (nIndexTo < nCount))
 +        {
 +            /* clear drag arrow */
 +            DrawInsert(hwnd, hwndList, -1);
 +            /* add item */
 +            TOOLBAR_Cust_AddButton(custInfo, hwnd, nIndexFrom, nIndexTo);
 +        }
 +    }
 +    case DL_CANCELDRAG:
 +        /* Clear drag arrow */
 +        DrawInsert(hwnd, hwndList, -1);
 +        break;
 +    }
 +    return 0;
 +}
 +
 +extern UINT uDragListMessage DECLSPEC_HIDDEN;
 +
 +/***********************************************************************
 + * TOOLBAR_CustomizeDialogProc
 + * This function implements the toolbar customization dialog.
 + */
 +static INT_PTR CALLBACK
 +TOOLBAR_CustomizeDialogProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
 +{
 +    PCUSTDLG_INFO custInfo = (PCUSTDLG_INFO)GetWindowLongPtrW (hwnd, DWLP_USER);
 +    PCUSTOMBUTTON btnInfo;
 +    NMTOOLBARA nmtb;
 +    TOOLBAR_INFO *infoPtr = custInfo ? custInfo->tbInfo : NULL;
 +
 +    switch (uMsg)
 +    {
 +      case WM_INITDIALOG:
 +          custInfo = (PCUSTDLG_INFO)lParam;
 +          SetWindowLongPtrW (hwnd, DWLP_USER, (LONG_PTR)custInfo);
 +
 +          if (custInfo)
 +          {
 +              WCHAR Buffer[256];
 +              int i = 0;
 +              int index;
 +              NMTBINITCUSTOMIZE nmtbic;
 +
 +              infoPtr = custInfo->tbInfo;
 +
 +              /* send TBN_QUERYINSERT notification */
 +              nmtb.iItem = custInfo->tbInfo->nNumButtons;
 +
 +              if (!TOOLBAR_SendNotify(&nmtb.hdr, infoPtr, TBN_QUERYINSERT))
 +                  return FALSE;
 +
 +              nmtbic.hwndDialog = hwnd;
 +              /* Send TBN_INITCUSTOMIZE notification */
 +              if (TOOLBAR_SendNotify (&nmtbic.hdr, infoPtr, TBN_INITCUSTOMIZE) ==
 +                  TBNRF_HIDEHELP)
 +                {
 +                    TRACE("TBNRF_HIDEHELP requested\n");
 +                    ShowWindow(GetDlgItem(hwnd, IDC_HELP_BTN), SW_HIDE);
 +                }
 +
 +              /* add items to 'toolbar buttons' list and check if removable */
 +              for (i = 0; i < custInfo->tbInfo->nNumButtons; i++)
 +                {
 +                    btnInfo = Alloc(sizeof(CUSTOMBUTTON));
 +                    memset (&btnInfo->btn, 0, sizeof(TBBUTTON));
 +                    btnInfo->btn.fsStyle = BTNS_SEP;
 +                    btnInfo->bVirtual = FALSE;
 +                  LoadStringW (COMCTL32_hModule, IDS_SEPARATOR, btnInfo->text, 64);
 +
 +                  /* send TBN_QUERYDELETE notification */
 +                    btnInfo->bRemovable = TOOLBAR_IsButtonRemovable(infoPtr, i, btnInfo);
 +
 +                  index = (int)SendDlgItemMessageW (hwnd, IDC_TOOLBARBTN_LBOX, LB_ADDSTRING, 0, 0);
 +                  SendDlgItemMessageW (hwnd, IDC_TOOLBARBTN_LBOX, LB_SETITEMDATA, index, (LPARAM)btnInfo);
 +              }
 +
 +              SendDlgItemMessageW (hwnd, IDC_TOOLBARBTN_LBOX, LB_SETITEMHEIGHT, 0, infoPtr->nBitmapHeight + 8);
 +
 +              /* insert separator button into 'available buttons' list */
 +                btnInfo = Alloc(sizeof(CUSTOMBUTTON));
 +              memset (&btnInfo->btn, 0, sizeof(TBBUTTON));
 +              btnInfo->btn.fsStyle = BTNS_SEP;
 +              btnInfo->bVirtual = FALSE;
 +              btnInfo->bRemovable = TRUE;
 +              LoadStringW (COMCTL32_hModule, IDS_SEPARATOR, btnInfo->text, 64);
 +              index = (int)SendDlgItemMessageW (hwnd, IDC_AVAILBTN_LBOX, LB_ADDSTRING, 0, (LPARAM)btnInfo);
 +              SendDlgItemMessageW (hwnd, IDC_AVAILBTN_LBOX, LB_SETITEMDATA, index, (LPARAM)btnInfo);
 +
 +              /* insert all buttons into dsa */
 +              for (i = 0;; i++)
 +              {
 +                  /* send TBN_GETBUTTONINFO notification */
 +                    NMTOOLBARW nmtb;
 +                  nmtb.iItem = i;
 +                  nmtb.pszText = Buffer;
 +                  nmtb.cchText = 256;
 +
 +                    /* Clear previous button's text */
 +                    ZeroMemory(nmtb.pszText, nmtb.cchText * sizeof(WCHAR));
 +
 +                    if (!TOOLBAR_GetButtonInfo(infoPtr, &nmtb))
 +                      break;
 +
 +                  TRACE("WM_INITDIALOG style: %x iItem(%d) idCommand(%d) iString(%ld) %s\n",
 +                        nmtb.tbButton.fsStyle, i, 
 +                        nmtb.tbButton.idCommand,
 +                        nmtb.tbButton.iString,
 +                        nmtb.tbButton.iString >= 0 ? debugstr_w(infoPtr->strings[nmtb.tbButton.iString])
 +                        : "");
 +
 +                  /* insert button into the appropriate list */
 +                  index = TOOLBAR_GetButtonIndex (custInfo->tbInfo, nmtb.tbButton.idCommand, FALSE);
 +                  if (index == -1)
 +                  {
 +                        btnInfo = Alloc(sizeof(CUSTOMBUTTON));
 +                      btnInfo->bVirtual = FALSE;
 +                      btnInfo->bRemovable = TRUE;
 +                  }
 +                  else
 +                  {
 +                        btnInfo = (PCUSTOMBUTTON)SendDlgItemMessageW (hwnd, 
 +                            IDC_TOOLBARBTN_LBOX, LB_GETITEMDATA, index, 0);
 +                    }
 +
 +                    btnInfo->btn = nmtb.tbButton;
 +                    if (!(nmtb.tbButton.fsStyle & BTNS_SEP))
 +                    {
 +                        if (lstrlenW(nmtb.pszText))
 +                            lstrcpyW(btnInfo->text, nmtb.pszText);
 +                        else if (nmtb.tbButton.iString >= 0 && 
 +                            nmtb.tbButton.iString < infoPtr->nNumStrings)
 +                        {
 +                            lstrcpyW(btnInfo->text, 
 +                                infoPtr->strings[nmtb.tbButton.iString]);
 +                        }
 +                  }
 +
 +                  if (index == -1)
 +                      TOOLBAR_Cust_InsertAvailButton(hwnd, btnInfo);
 +              }
 +
 +              SendDlgItemMessageW (hwnd, IDC_AVAILBTN_LBOX, LB_SETITEMHEIGHT, 0, infoPtr->nBitmapHeight + 8);
 +
 +              /* select first item in the 'available' list */
 +              SendDlgItemMessageW (hwnd, IDC_AVAILBTN_LBOX, LB_SETCURSEL, 0, 0);
 +
 +              /* append 'virtual' separator button to the 'toolbar buttons' list */
 +                btnInfo = Alloc(sizeof(CUSTOMBUTTON));
 +              memset (&btnInfo->btn, 0, sizeof(TBBUTTON));
 +              btnInfo->btn.fsStyle = BTNS_SEP;
 +              btnInfo->bVirtual = TRUE;
 +              btnInfo->bRemovable = FALSE;
 +              LoadStringW (COMCTL32_hModule, IDS_SEPARATOR, btnInfo->text, 64);
 +              index = (int)SendDlgItemMessageW (hwnd, IDC_TOOLBARBTN_LBOX, LB_ADDSTRING, 0, (LPARAM)btnInfo);
 +              SendDlgItemMessageW (hwnd, IDC_TOOLBARBTN_LBOX, LB_SETITEMDATA, index, (LPARAM)btnInfo);
 +
 +              /* select last item in the 'toolbar' list */
 +              SendDlgItemMessageW (hwnd, IDC_TOOLBARBTN_LBOX, LB_SETCURSEL, index, 0);
 +              SendDlgItemMessageW (hwnd, IDC_TOOLBARBTN_LBOX, LB_SETTOPINDEX, index, 0);
 +
 +              MakeDragList(GetDlgItem(hwnd, IDC_TOOLBARBTN_LBOX));
 +              MakeDragList(GetDlgItem(hwnd, IDC_AVAILBTN_LBOX));
 +
 +              /* set focus and disable buttons */
 +              PostMessageW (hwnd, WM_USER, 0, 0);
 +          }
 +          return TRUE;
 +
 +      case WM_USER:
 +          EnableWindow (GetDlgItem (hwnd,IDC_MOVEUP_BTN), FALSE);
 +          EnableWindow (GetDlgItem (hwnd,IDC_MOVEDN_BTN), FALSE);
 +          EnableWindow (GetDlgItem (hwnd,IDC_REMOVE_BTN), FALSE);
 +          SetFocus (GetDlgItem (hwnd, IDC_TOOLBARBTN_LBOX));
 +          return TRUE;
 +
 +      case WM_CLOSE:
 +          EndDialog(hwnd, FALSE);
 +          return TRUE;
 +
 +      case WM_COMMAND:
 +          switch (LOWORD(wParam))
 +          {
 +              case IDC_TOOLBARBTN_LBOX:
 +                  if (HIWORD(wParam) == LBN_SELCHANGE)
 +                  {
 +                      PCUSTOMBUTTON btnInfo;
 +                      NMTOOLBARA nmtb;
 +                      int count;
 +                      int index;
 +
 +                      count = SendDlgItemMessageW (hwnd, IDC_TOOLBARBTN_LBOX, LB_GETCOUNT, 0, 0);
 +                      index = SendDlgItemMessageW (hwnd, IDC_TOOLBARBTN_LBOX, LB_GETCURSEL, 0, 0);
 +
 +                      /* send TBN_QUERYINSERT notification */
 +                      nmtb.iItem = index;
 +                      TOOLBAR_SendNotify(&nmtb.hdr, infoPtr, TBN_QUERYINSERT);
 +
 +                      /* get list box item */
 +                      btnInfo = (PCUSTOMBUTTON)SendDlgItemMessageW (hwnd, IDC_TOOLBARBTN_LBOX, LB_GETITEMDATA, index, 0);
 +
 +                      if (index == (count - 1))
 +                      {
 +                          /* last item (virtual separator) */
 +                          EnableWindow (GetDlgItem (hwnd,IDC_MOVEUP_BTN), FALSE);
 +                          EnableWindow (GetDlgItem (hwnd,IDC_MOVEDN_BTN), FALSE);
 +                      }
 +                      else if (index == (count - 2))
 +                      {
 +                          /* second last item (last non-virtual item) */
 +                          EnableWindow (GetDlgItem (hwnd,IDC_MOVEUP_BTN), TRUE);
 +                          EnableWindow (GetDlgItem (hwnd,IDC_MOVEDN_BTN), FALSE);
 +                      }
 +                      else if (index == 0)
 +                      {
 +                          /* first item */
 +                          EnableWindow (GetDlgItem (hwnd,IDC_MOVEUP_BTN), FALSE);
 +                          EnableWindow (GetDlgItem (hwnd,IDC_MOVEDN_BTN), TRUE);
 +                      }
 +                      else
 +                      {
 +                          EnableWindow (GetDlgItem (hwnd,IDC_MOVEUP_BTN), TRUE);
 +                          EnableWindow (GetDlgItem (hwnd,IDC_MOVEDN_BTN), TRUE);
 +                      }
 +
 +                      EnableWindow (GetDlgItem (hwnd,IDC_REMOVE_BTN), btnInfo->bRemovable);
 +                  }
 +                  break;
 +
 +              case IDC_MOVEUP_BTN:
 +                  {
 +                      int index = SendDlgItemMessageW (hwnd, IDC_TOOLBARBTN_LBOX, LB_GETCURSEL, 0, 0);
 +                      TOOLBAR_Cust_MoveButton(custInfo, hwnd, index, index-1);
 +                  }
 +                  break;
 +
 +              case IDC_MOVEDN_BTN: /* move down */
 +                  {
 +                      int index = SendDlgItemMessageW (hwnd, IDC_TOOLBARBTN_LBOX, LB_GETCURSEL, 0, 0);
 +                      TOOLBAR_Cust_MoveButton(custInfo, hwnd, index, index+1);
 +                  }
 +                  break;
 +
 +              case IDC_REMOVE_BTN: /* remove button */
 +                  {
 +                      int index = SendDlgItemMessageW (hwnd, IDC_TOOLBARBTN_LBOX, LB_GETCURSEL, 0, 0);
 +
 +                      if (LB_ERR == index)
 +                              break;
 +
 +                      TOOLBAR_Cust_RemoveButton(custInfo, hwnd, index);
 +                  }
 +                  break;
 +              case IDC_HELP_BTN:
 +                      TOOLBAR_SendNotify(&nmtb.hdr, infoPtr, TBN_CUSTHELP);
 +                      break;
 +              case IDC_RESET_BTN:
 +                      TOOLBAR_SendNotify(&nmtb.hdr, infoPtr, TBN_RESET);
 +                      break;
 +
 +              case IDOK: /* Add button */
 +                  {
 +                      int index;
 +                      int indexto;
 +
 +                      index = SendDlgItemMessageW(hwnd, IDC_AVAILBTN_LBOX, LB_GETCURSEL, 0, 0);
 +                      indexto = SendDlgItemMessageW(hwnd, IDC_TOOLBARBTN_LBOX, LB_GETCURSEL, 0, 0);
 +
 +                      TOOLBAR_Cust_AddButton(custInfo, hwnd, index, indexto);
 +                  }
 +                  break;
 +
 +              case IDCANCEL:
 +                  EndDialog(hwnd, FALSE);
 +                  break;
 +          }
 +          return TRUE;
 +
 +      case WM_DESTROY:
 +          {
 +              int count;
 +              int i;
 +
 +              /* delete items from 'toolbar buttons' listbox*/
 +              count = SendDlgItemMessageW (hwnd, IDC_TOOLBARBTN_LBOX, LB_GETCOUNT, 0, 0);
 +              for (i = 0; i < count; i++)
 +              {
 +                  btnInfo = (PCUSTOMBUTTON)SendDlgItemMessageW (hwnd, IDC_TOOLBARBTN_LBOX, LB_GETITEMDATA, i, 0);
 +                  Free(btnInfo);
 +                  SendDlgItemMessageW (hwnd, IDC_TOOLBARBTN_LBOX, LB_SETITEMDATA, 0, 0);
 +              }
 +              SendDlgItemMessageW (hwnd, IDC_TOOLBARBTN_LBOX, LB_RESETCONTENT, 0, 0);
 +
 +
 +              /* delete items from 'available buttons' listbox*/
 +              count = SendDlgItemMessageW (hwnd, IDC_AVAILBTN_LBOX, LB_GETCOUNT, 0, 0);
 +              for (i = 0; i < count; i++)
 +              {
 +                  btnInfo = (PCUSTOMBUTTON)SendDlgItemMessageW (hwnd, IDC_AVAILBTN_LBOX, LB_GETITEMDATA, i, 0);
 +                  Free(btnInfo);
 +                  SendDlgItemMessageW (hwnd, IDC_AVAILBTN_LBOX, LB_SETITEMDATA, i, 0);
 +              }
 +              SendDlgItemMessageW (hwnd, IDC_AVAILBTN_LBOX, LB_RESETCONTENT, 0, 0);
 +            }
 +          return TRUE;
 +
 +      case WM_DRAWITEM:
 +          if (wParam == IDC_AVAILBTN_LBOX || wParam == IDC_TOOLBARBTN_LBOX)
 +          {
 +              LPDRAWITEMSTRUCT lpdis = (LPDRAWITEMSTRUCT)lParam;
 +              RECT rcButton;
 +              RECT rcText;
 +              HPEN hPen, hOldPen;
 +              HBRUSH hOldBrush;
 +              COLORREF oldText = 0;
 +              COLORREF oldBk = 0;
 +
 +              /* get item data */
 +               btnInfo = (PCUSTOMBUTTON)SendDlgItemMessageW (hwnd, wParam, LB_GETITEMDATA, lpdis->itemID, 0);
 +              if (btnInfo == NULL)
 +              {
 +                  FIXME("btnInfo invalid!\n");
 +                  return TRUE;
 +              }
 +
 +              /* set colors and select objects */
 +              oldBk = SetBkColor (lpdis->hDC, (lpdis->itemState & ODS_FOCUS)?comctl32_color.clrHighlight:comctl32_color.clrWindow);
 +              if (btnInfo->bVirtual)
 +                 oldText = SetTextColor (lpdis->hDC, comctl32_color.clrGrayText);
 +              else
 +                 oldText = SetTextColor (lpdis->hDC, (lpdis->itemState & ODS_FOCUS)?comctl32_color.clrHighlightText:comctl32_color.clrWindowText);
 +                hPen = CreatePen( PS_SOLID, 1,
 +                                 (lpdis->itemState & ODS_SELECTED)?comctl32_color.clrHighlight:comctl32_color.clrWindow);
 +              hOldPen = SelectObject (lpdis->hDC, hPen );
 +              hOldBrush = SelectObject (lpdis->hDC, GetSysColorBrush ((lpdis->itemState & ODS_FOCUS)?COLOR_HIGHLIGHT:COLOR_WINDOW));
 +
 +              /* fill background rectangle */
 +              Rectangle (lpdis->hDC, lpdis->rcItem.left, lpdis->rcItem.top,
 +                         lpdis->rcItem.right, lpdis->rcItem.bottom);
 +
 +              /* calculate button and text rectangles */
 +              CopyRect (&rcButton, &lpdis->rcItem);
 +              InflateRect (&rcButton, -1, -1);
 +              CopyRect (&rcText, &rcButton);
 +              rcButton.right = rcButton.left + custInfo->tbInfo->nBitmapWidth + 6;
 +              rcText.left = rcButton.right + 2;
 +
 +              /* draw focus rectangle */
 +              if (lpdis->itemState & ODS_FOCUS)
 +                  DrawFocusRect (lpdis->hDC, &lpdis->rcItem);
 +
 +              /* draw button */
 +              if (!(infoPtr->dwStyle & TBSTYLE_FLAT))
 +                  DrawEdge (lpdis->hDC, &rcButton, EDGE_RAISED, BF_RECT|BF_MIDDLE|BF_SOFT);
 +
 +              /* draw image and text */
 +              if ((btnInfo->btn.fsStyle & BTNS_SEP) == 0) {
 +                      HIMAGELIST himl = GETDEFIMAGELIST(infoPtr, GETHIMLID(infoPtr, 
 +                              btnInfo->btn.iBitmap));
 +                  ImageList_Draw (himl, GETIBITMAP(infoPtr, btnInfo->btn.iBitmap), 
 +                              lpdis->hDC, rcButton.left+3, rcButton.top+3, ILD_NORMAL);
 +              }
 +              DrawTextW (lpdis->hDC,  btnInfo->text, -1, &rcText,
 +                             DT_LEFT | DT_VCENTER | DT_SINGLELINE);
 +
 +              /* delete objects and reset colors */
 +              SelectObject (lpdis->hDC, hOldBrush);
 +              SelectObject (lpdis->hDC, hOldPen);
 +              SetBkColor (lpdis->hDC, oldBk);
 +              SetTextColor (lpdis->hDC, oldText);
 +                DeleteObject( hPen );
 +              return TRUE;
 +          }
 +          return FALSE;
 +
 +      case WM_MEASUREITEM:
 +          if (wParam == IDC_AVAILBTN_LBOX || wParam == IDC_TOOLBARBTN_LBOX)
 +          {
 +              MEASUREITEMSTRUCT *lpmis = (MEASUREITEMSTRUCT*)lParam;
 +
 +              lpmis->itemHeight = 15 + 8; /* default height */
 +
 +              return TRUE;
 +          }
 +          return FALSE;
 +
 +      default:
 +            if (uDragListMessage && (uMsg == uDragListMessage))
 +            {
 +                if (wParam == IDC_TOOLBARBTN_LBOX)
 +                {
 +                    LRESULT res = TOOLBAR_Cust_ToolbarDragListNotification(
 +                        custInfo, hwnd, (DRAGLISTINFO *)lParam);
 +                    SetWindowLongPtrW(hwnd, DWLP_MSGRESULT, res);
 +                    return TRUE;
 +                }
 +                else if (wParam == IDC_AVAILBTN_LBOX)
 +                {
 +                    LRESULT res = TOOLBAR_Cust_AvailDragListNotification(
 +                        custInfo, hwnd, (DRAGLISTINFO *)lParam);
 +                    SetWindowLongPtrW(hwnd, DWLP_MSGRESULT, res);
 +                    return TRUE;
 +                }
 +            }
 +            return FALSE;
 +    }
 +}
 +
 +static BOOL
 +TOOLBAR_AddBitmapToImageList(TOOLBAR_INFO *infoPtr, HIMAGELIST himlDef, const TBITMAP_INFO *bitmap)
 +{
 +    HBITMAP hbmLoad;
 +    INT nCountBefore = ImageList_GetImageCount(himlDef);
 +    INT nCountAfter;
 +    INT cxIcon, cyIcon;
 +    INT nAdded;
 +    INT nIndex;
 +
 +    TRACE("adding hInst=%p nID=%d nButtons=%d\n", bitmap->hInst, bitmap->nID, bitmap->nButtons);
 +    /* Add bitmaps to the default image list */
 +    if (bitmap->hInst == NULL)         /* a handle was passed */
 +        hbmLoad = CopyImage(ULongToHandle(bitmap->nID), IMAGE_BITMAP, 0, 0, 0);
 +    else if (bitmap->hInst == COMCTL32_hModule)
 +        hbmLoad = LoadImageW( bitmap->hInst, MAKEINTRESOURCEW(bitmap->nID),
 +                              IMAGE_BITMAP, 0, 0, LR_CREATEDIBSECTION );
 +    else
 +        hbmLoad = CreateMappedBitmap(bitmap->hInst, bitmap->nID, 0, NULL, 0);
 +
 +    /* enlarge the bitmap if needed */
 +    ImageList_GetIconSize(himlDef, &cxIcon, &cyIcon);
 +    if (bitmap->hInst != COMCTL32_hModule)
 +        COMCTL32_EnsureBitmapSize(&hbmLoad, cxIcon*(INT)bitmap->nButtons, cyIcon, comctl32_color.clrBtnFace);
 +    
 +    nIndex = ImageList_AddMasked(himlDef, hbmLoad, comctl32_color.clrBtnFace);
 +    DeleteObject(hbmLoad);
 +    if (nIndex == -1)
 +        return FALSE;
 +    
 +    nCountAfter = ImageList_GetImageCount(himlDef);
 +    nAdded =  nCountAfter - nCountBefore;
 +    if (bitmap->nButtons == 0) /* wParam == 0 is special and means add only one image */
 +    {
 +        ImageList_SetImageCount(himlDef, nCountBefore + 1);
 +    } else if (nAdded > (INT)bitmap->nButtons) {
 +        TRACE("Added more images than wParam: Previous image number %i added %i while wParam %i. Images in list %i\n",
 +            nCountBefore, nAdded, bitmap->nButtons, nCountAfter);
 +    }
 +
 +    infoPtr->nNumBitmaps += nAdded;
 +    return TRUE;
 +}
 +
 +static void
 +TOOLBAR_CheckImageListIconSize(TOOLBAR_INFO *infoPtr)
 +{
 +    HIMAGELIST himlDef;
 +    HIMAGELIST himlNew;
 +    INT cx, cy;
 +    INT i;
 +    
 +    himlDef = GETDEFIMAGELIST(infoPtr, 0);
 +    if (himlDef == NULL || himlDef != infoPtr->himlInt)
 +        return;
 +    if (!ImageList_GetIconSize(himlDef, &cx, &cy))
 +        return;
 +    if (cx == infoPtr->nBitmapWidth && cy == infoPtr->nBitmapHeight)
 +        return;
 +
 +    TRACE("Update icon size: %dx%d -> %dx%d\n",
 +        cx, cy, infoPtr->nBitmapWidth, infoPtr->nBitmapHeight);
 +
 +    himlNew = ImageList_Create(infoPtr->nBitmapWidth, infoPtr->nBitmapHeight,
 +                                ILC_COLOR32|ILC_MASK, 8, 2);
 +    for (i = 0; i < infoPtr->nNumBitmapInfos; i++)
 +        TOOLBAR_AddBitmapToImageList(infoPtr, himlNew, &infoPtr->bitmaps[i]);
 +    TOOLBAR_InsertImageList(&infoPtr->himlDef, &infoPtr->cimlDef, himlNew, 0);
 +    infoPtr->himlInt = himlNew;
 +
 +    infoPtr->nNumBitmaps -= ImageList_GetImageCount(himlDef);
 +    ImageList_Destroy(himlDef);
 +}
 +
 +/***********************************************************************
 + * TOOLBAR_AddBitmap:  Add the bitmaps to the default image list.
 + *
 + */
 +static LRESULT
 +TOOLBAR_AddBitmap (TOOLBAR_INFO *infoPtr, INT count, const TBADDBITMAP *lpAddBmp)
 +{
 +    TBITMAP_INFO info;
 +    INT iSumButtons, i;
 +    HIMAGELIST himlDef;
 +
 +    TRACE("hwnd=%p count=%d lpAddBmp=%p\n", infoPtr->hwndSelf, count, lpAddBmp);
 +    if (!lpAddBmp)
 +      return -1;
 +
 +    if (lpAddBmp->hInst == HINST_COMMCTRL)
 +    {
 +        info.hInst = COMCTL32_hModule;
 +        switch (lpAddBmp->nID)
 +        {
 +            case IDB_STD_SMALL_COLOR:
 +              info.nButtons = 15;
 +              info.nID = IDB_STD_SMALL;
 +              break;
 +            case IDB_STD_LARGE_COLOR:
 +              info.nButtons = 15;
 +              info.nID = IDB_STD_LARGE;
 +              break;
 +            case IDB_VIEW_SMALL_COLOR:
 +              info.nButtons = 12;
 +              info.nID = IDB_VIEW_SMALL;
 +              break;
 +            case IDB_VIEW_LARGE_COLOR:
 +              info.nButtons = 12;
 +              info.nID = IDB_VIEW_LARGE;
 +              break;
 +            case IDB_HIST_SMALL_COLOR:
 +              info.nButtons = 5;
 +              info.nID = IDB_HIST_SMALL;
 +              break;
 +            case IDB_HIST_LARGE_COLOR:
 +              info.nButtons = 5;
 +              info.nID = IDB_HIST_LARGE;
 +              break;
 +          default:
 +              return -1;
 +      }
 +
 +      TRACE ("adding %d internal bitmaps!\n", info.nButtons);
 +
 +      /* Windows resize all the buttons to the size of a newly added standard image */
 +      if (lpAddBmp->nID & 1)
 +      {
 +          /* large icons: 24x24. Will make the button 31x30 */
 +          SendMessageW (infoPtr->hwndSelf, TB_SETBITMAPSIZE, 0, MAKELPARAM(24, 24));
 +      }
 +      else
 +      {
 +          /* small icons: 16x16. Will make the buttons 23x22 */
 +          SendMessageW (infoPtr->hwndSelf, TB_SETBITMAPSIZE, 0, MAKELPARAM(16, 16));
 +      }
 +
 +      TOOLBAR_CalcToolbar (infoPtr);
 +    }
 +    else
 +    {
 +      info.nButtons = count;
 +      info.hInst = lpAddBmp->hInst;
 +      info.nID = lpAddBmp->nID;
 +      TRACE("adding %d bitmaps!\n", info.nButtons);
 +    }
 +    
 +    /* check if the bitmap is already loaded and compute iSumButtons */
 +    iSumButtons = 0;
 +    for (i = 0; i < infoPtr->nNumBitmapInfos; i++)
 +    {
 +        if (infoPtr->bitmaps[i].hInst == info.hInst &&
 +            infoPtr->bitmaps[i].nID == info.nID)
 +            return iSumButtons;
 +        iSumButtons += infoPtr->bitmaps[i].nButtons;
 +    }
 +
 +    if (!infoPtr->cimlDef) {
 +      /* create new default image list */
 +      TRACE ("creating default image list!\n");
 +
 +        himlDef = ImageList_Create (infoPtr->nBitmapWidth, infoPtr->nBitmapHeight,
 +                                    ILC_COLOR32 | ILC_MASK, info.nButtons, 2);
 +      TOOLBAR_InsertImageList(&infoPtr->himlDef, &infoPtr->cimlDef, himlDef, 0);
 +        infoPtr->himlInt = himlDef;
 +    }
 +    else {
 +        himlDef = GETDEFIMAGELIST(infoPtr, 0);
 +    }
 +
 +    if (!himlDef) {
 +        WARN("No default image list available\n");
 +        return -1;
 +    }
 +
 +    if (!TOOLBAR_AddBitmapToImageList(infoPtr, himlDef, &info))
 +        return -1;
 +
 +    TRACE("Number of bitmap infos: %d\n", infoPtr->nNumBitmapInfos);
 +    infoPtr->bitmaps = ReAlloc(infoPtr->bitmaps, (infoPtr->nNumBitmapInfos + 1) * sizeof(TBITMAP_INFO));
 +    infoPtr->bitmaps[infoPtr->nNumBitmapInfos] = info;
 +    infoPtr->nNumBitmapInfos++;
 +    TRACE("Number of bitmap infos: %d\n", infoPtr->nNumBitmapInfos);
 +
 +    InvalidateRect(infoPtr->hwndSelf, NULL, TRUE);
 +    return iSumButtons;
 +}
 +
 +
 +static LRESULT
 +TOOLBAR_AddButtonsT(TOOLBAR_INFO *infoPtr, INT nAddButtons, const TBBUTTON* lpTbb, BOOL fUnicode)
 +{
 +    TRACE("adding %d buttons (unicode=%d)!\n", nAddButtons, fUnicode);
 +
 +    return TOOLBAR_InternalInsertButtonsT(infoPtr, -1, nAddButtons, lpTbb, fUnicode);
 +}
 +
 +
 +static LRESULT
 +TOOLBAR_AddStringW (TOOLBAR_INFO *infoPtr, HINSTANCE hInstance, LPARAM lParam)
 +{
 +#define MAX_RESOURCE_STRING_LENGTH 512
 +    BOOL fFirstString = (infoPtr->nNumStrings == 0);
 +    INT nIndex = infoPtr->nNumStrings;
 +
 +    TRACE("%p, %lx\n", hInstance, lParam);
 +
 +    if (IS_INTRESOURCE(lParam)) {
 +      WCHAR szString[MAX_RESOURCE_STRING_LENGTH];
 +      WCHAR delimiter;
 +      WCHAR *next_delim;
 +        HRSRC hrsrc;
 +      WCHAR *p;
 +      INT len;
 +
 +      TRACE("adding string from resource\n");
 +
 +        if (!hInstance) return -1;
 +
 +        hrsrc = FindResourceW( hInstance, MAKEINTRESOURCEW((LOWORD(lParam) >> 4) + 1),
 +                               (LPWSTR)RT_STRING );
 +        if (!hrsrc)
 +        {
 +            TRACE("string not found in resources\n");
 +            return -1;
 +        }
 +
 +        len = LoadStringW (hInstance, (UINT)lParam,
 +                             szString, MAX_RESOURCE_STRING_LENGTH);
 +
 +        TRACE("len=%d %s\n", len, debugstr_w(szString));
 +        if (len == 0 || len == 1)
 +            return nIndex;
 +
 +        TRACE("delimiter: 0x%x\n", *szString);
 +        delimiter = *szString;
 +        p = szString + 1;
 +
 +        while ((next_delim = strchrW(p, delimiter)) != NULL) {
 +            *next_delim = 0;
 +            if (next_delim + 1 >= szString + len)
 +            {
 +                /* this may happen if delimiter == '\0' or if the last char is a
 +                 * delimiter (then it is ignored like the native does) */
 +                break;
 +            }
 +
 +            infoPtr->strings = ReAlloc(infoPtr->strings, sizeof(LPWSTR)*(infoPtr->nNumStrings+1));
 +            Str_SetPtrW(&infoPtr->strings[infoPtr->nNumStrings], p);
 +            infoPtr->nNumStrings++;
 +
 +            p = next_delim + 1;
 +        }
 +    }
 +    else {
 +      LPWSTR p = (LPWSTR)lParam;
 +      INT len;
 +
 +      if (p == NULL)
 +          return -1;
 +      TRACE("adding string(s) from array\n");
 +      while (*p) {
 +            len = strlenW (p);
 +
 +            TRACE("len=%d %s\n", len, debugstr_w(p));
 +            infoPtr->strings = ReAlloc(infoPtr->strings, sizeof(LPWSTR)*(infoPtr->nNumStrings+1));
 +            Str_SetPtrW (&infoPtr->strings[infoPtr->nNumStrings], p);
 +          infoPtr->nNumStrings++;
 +
 +          p += (len+1);
 +      }
 +    }
 +
 +    if (fFirstString)
 +        TOOLBAR_CalcToolbar(infoPtr);
 +    return nIndex;
 +}
 +
 +
 +static LRESULT
 +TOOLBAR_AddStringA (TOOLBAR_INFO *infoPtr, HINSTANCE hInstance, LPARAM lParam)
 +{
 +    BOOL fFirstString = (infoPtr->nNumStrings == 0);
 +    LPSTR p;
 +    INT nIndex;
 +    INT len;
 +
 +    TRACE("%p, %lx\n", hInstance, lParam);
 +
 +    if (IS_INTRESOURCE(lParam))  /* load from resources */
 +        return TOOLBAR_AddStringW(infoPtr, hInstance, lParam);
 +
 +    p = (LPSTR)lParam;
 +    if (p == NULL)
 +        return -1;
 +
 +    TRACE("adding string(s) from array\n");
 +    nIndex = infoPtr->nNumStrings;
 +    while (*p) {
 +        len = strlen (p);
 +        TRACE("len=%d \"%s\"\n", len, p);
 +
 +        infoPtr->strings = ReAlloc(infoPtr->strings, sizeof(LPWSTR)*(infoPtr->nNumStrings+1));
 +        Str_SetPtrAtoW(&infoPtr->strings[infoPtr->nNumStrings], p);
 +        infoPtr->nNumStrings++;
 +
 +        p += (len+1);
 +    }
 +
 +    if (fFirstString)
 +        TOOLBAR_CalcToolbar(infoPtr);
 +    return nIndex;
 +}
 +
 +
 +static LRESULT
 +TOOLBAR_AutoSize (TOOLBAR_INFO *infoPtr)
 +{
 +    RECT parent_rect;
 +    HWND parent;
 +    INT  x, y;
 +    INT  cx, cy;
 +
 +    TRACE("auto sizing, style=%x!\n", infoPtr->dwStyle);
 +
 +    parent = GetParent (infoPtr->hwndSelf);
 +
 +    if (!parent || !infoPtr->bDoRedraw)
 +        return 0;
 +
 +    GetClientRect(parent, &parent_rect);
 +
 +    x = parent_rect.left;
 +    y = parent_rect.top;
 +
 +    TRACE("nRows: %d, infoPtr->nButtonHeight: %d\n", infoPtr->nRows, infoPtr->nButtonHeight);
 +
 +    cy = TOP_BORDER + infoPtr->nRows * infoPtr->nButtonHeight + BOTTOM_BORDER;
 +    cx = parent_rect.right - parent_rect.left;
 +
-     /* MSDN documents a iImageLabel field added in Vista but it is not present in
++    if ((infoPtr->dwStyle & TBSTYLE_WRAPABLE) || (infoPtr->dwExStyle & TBSTYLE_EX_VERTICAL))
 +    {
 +        TOOLBAR_LayoutToolbar(infoPtr);
 +        InvalidateRect( infoPtr->hwndSelf, NULL, TRUE );
 +    }
 +
 +    if (!(infoPtr->dwStyle & CCS_NORESIZE))
 +    {
 +        RECT window_rect;
 +        UINT uPosFlags = SWP_NOZORDER | SWP_NOACTIVATE;
 +
 +        if ((infoPtr->dwStyle & CCS_BOTTOM) == CCS_NOMOVEY)
 +        {
 +            GetWindowRect(infoPtr->hwndSelf, &window_rect);
 +            MapWindowPoints( 0, parent, (POINT *)&window_rect, 2 );
 +            y = window_rect.top;
 +        }
 +        if ((infoPtr->dwStyle & CCS_BOTTOM) == CCS_BOTTOM)
 +        {
 +            GetWindowRect(infoPtr->hwndSelf, &window_rect);
 +            y = parent_rect.bottom - ( window_rect.bottom - window_rect.top);
 +        }
 +
 +        if (infoPtr->dwStyle & CCS_NOPARENTALIGN)
 +            uPosFlags |= SWP_NOMOVE;
 +    
 +        if (!(infoPtr->dwStyle & CCS_NODIVIDER))
 +            cy += GetSystemMetrics(SM_CYEDGE);
 +
 +        if (infoPtr->dwStyle & WS_BORDER)
 +        {
 +            cx += 2 * GetSystemMetrics(SM_CXBORDER);
 +            cy += 2 * GetSystemMetrics(SM_CYBORDER);
 +        }
 +
 +        SetWindowPos(infoPtr->hwndSelf, NULL, x, y, cx, cy, uPosFlags);
 +    }
 +
 +    return 0;
 +}
 +
 +
 +static inline LRESULT
 +TOOLBAR_ButtonCount (const TOOLBAR_INFO *infoPtr)
 +{
 +    return infoPtr->nNumButtons;
 +}
 +
 +
 +static inline LRESULT
 +TOOLBAR_ButtonStructSize (TOOLBAR_INFO *infoPtr, DWORD Size)
 +{
 +    infoPtr->dwStructSize = Size;
 +
 +    return 0;
 +}
 +
 +
 +static LRESULT
 +TOOLBAR_ChangeBitmap (TOOLBAR_INFO *infoPtr, INT Id, INT Index)
 +{
 +    TBUTTON_INFO *btnPtr;
 +    INT nIndex;
 +
 +    TRACE("button %d, iBitmap now %d\n", Id, Index);
 +
 +    nIndex = TOOLBAR_GetButtonIndex (infoPtr, Id, FALSE);
 +    if (nIndex == -1)
 +      return FALSE;
 +
 +    btnPtr = &infoPtr->buttons[nIndex];
 +    btnPtr->iBitmap = Index;
 +
 +    /* we HAVE to erase the background, the new bitmap could be */
 +    /* transparent */
 +    InvalidateRect(infoPtr->hwndSelf, &btnPtr->rect, TRUE);
 +
 +    return TRUE;
 +}
 +
 +
 +static LRESULT
 +TOOLBAR_CheckButton (TOOLBAR_INFO *infoPtr, INT Id, LPARAM lParam)
 +{
 +    TBUTTON_INFO *btnPtr;
 +    INT nIndex;
 +    INT nOldIndex = -1;
 +    BOOL bChecked = FALSE;
 +
 +    nIndex = TOOLBAR_GetButtonIndex (infoPtr, Id, FALSE);
 +
 +    TRACE("hwnd=%p, btn index=%d, lParam=0x%08lx\n", infoPtr->hwndSelf, nIndex, lParam);
 +
 +    if (nIndex == -1)
 +      return FALSE;
 +
 +    btnPtr = &infoPtr->buttons[nIndex];
 +
 +    bChecked = (btnPtr->fsState & TBSTATE_CHECKED) != 0;
 +
 +    if (LOWORD(lParam) == FALSE)
 +      btnPtr->fsState &= ~TBSTATE_CHECKED;
 +    else {
 +      if (btnPtr->fsStyle & BTNS_GROUP) {
 +          nOldIndex =
 +              TOOLBAR_GetCheckedGroupButtonIndex (infoPtr, nIndex);
 +          if (nOldIndex == nIndex)
 +              return 0;
 +          if (nOldIndex != -1)
 +              infoPtr->buttons[nOldIndex].fsState &= ~TBSTATE_CHECKED;
 +      }
 +      btnPtr->fsState |= TBSTATE_CHECKED;
 +    }
 +
 +    if( bChecked != LOWORD(lParam) )
 +    {
 +        if (nOldIndex != -1)
 +            InvalidateRect(infoPtr->hwndSelf, &infoPtr->buttons[nOldIndex].rect, TRUE);
 +        InvalidateRect(infoPtr->hwndSelf, &btnPtr->rect, TRUE);
 +    }
 +
 +    /* FIXME: Send a WM_NOTIFY?? */
 +
 +    return TRUE;
 +}
 +
 +
 +static LRESULT
 +TOOLBAR_CommandToIndex (const TOOLBAR_INFO *infoPtr, INT Id)
 +{
 +    return TOOLBAR_GetButtonIndex (infoPtr, Id, FALSE);
 +}
 +
 +
 +static LRESULT
 +TOOLBAR_Customize (TOOLBAR_INFO *infoPtr)
 +{
 +    CUSTDLG_INFO custInfo;
 +    LRESULT ret;
 +    NMHDR nmhdr;
 +
 +    custInfo.tbInfo = infoPtr;
 +    custInfo.tbHwnd = infoPtr->hwndSelf;
 +
 +    /* send TBN_BEGINADJUST notification */
 +    TOOLBAR_SendNotify (&nmhdr, infoPtr, TBN_BEGINADJUST);
 +
 +    ret = DialogBoxParamW (COMCTL32_hModule, MAKEINTRESOURCEW(IDD_TBCUSTOMIZE),
 +                           infoPtr->hwndSelf, TOOLBAR_CustomizeDialogProc, (LPARAM)&custInfo);
 +
 +    /* send TBN_ENDADJUST notification */
 +    TOOLBAR_SendNotify (&nmhdr, infoPtr, TBN_ENDADJUST);
 +
 +    return ret;
 +}
 +
 +
 +static LRESULT
 +TOOLBAR_DeleteButton (TOOLBAR_INFO *infoPtr, INT nIndex)
 +{
 +    NMTOOLBARW nmtb;
 +    TBUTTON_INFO *btnPtr = &infoPtr->buttons[nIndex];
 +
 +    if ((nIndex < 0) || (nIndex >= infoPtr->nNumButtons))
 +        return FALSE;
 +
 +    memset(&nmtb, 0, sizeof(nmtb));
 +    nmtb.iItem = btnPtr->idCommand;
 +    nmtb.tbButton.iBitmap = btnPtr->iBitmap;
 +    nmtb.tbButton.idCommand = btnPtr->idCommand;
 +    nmtb.tbButton.fsState = btnPtr->fsState;
 +    nmtb.tbButton.fsStyle = btnPtr->fsStyle;
 +    nmtb.tbButton.dwData = btnPtr->dwData;
 +    nmtb.tbButton.iString = btnPtr->iString;
 +    TOOLBAR_SendNotify(&nmtb.hdr, infoPtr, TBN_DELETINGBUTTON);
 +
 +    TOOLBAR_TooltipDelTool(infoPtr, &infoPtr->buttons[nIndex]);
 +
 +    if (infoPtr->nNumButtons == 1) {
 +      TRACE(" simple delete!\n");
 +      if (TOOLBAR_ButtonHasString(infoPtr->buttons))
 +          Free((LPWSTR)infoPtr->buttons[0].iString);
 +      Free (infoPtr->buttons);
 +      infoPtr->buttons = NULL;
 +      infoPtr->nNumButtons = 0;
 +    }
 +    else {
 +      TBUTTON_INFO *oldButtons = infoPtr->buttons;
 +        TRACE("complex delete! [nIndex=%d]\n", nIndex);
 +
 +      infoPtr->nNumButtons--;
 +      infoPtr->buttons = Alloc (sizeof (TBUTTON_INFO) * infoPtr->nNumButtons);
 +        if (nIndex > 0) {
 +            memcpy (&infoPtr->buttons[0], &oldButtons[0],
 +                    nIndex * sizeof(TBUTTON_INFO));
 +        }
 +
 +        if (nIndex < infoPtr->nNumButtons) {
 +            memcpy (&infoPtr->buttons[nIndex], &oldButtons[nIndex+1],
 +                    (infoPtr->nNumButtons - nIndex) * sizeof(TBUTTON_INFO));
 +        }
 +
 +        if (TOOLBAR_ButtonHasString(&oldButtons[nIndex]))
 +            Free((LPWSTR)oldButtons[nIndex].iString);
 +      Free (oldButtons);
 +    }
 +
 +    TOOLBAR_LayoutToolbar(infoPtr);
 +
 +    InvalidateRect (infoPtr->hwndSelf, NULL, TRUE);
 +
 +    return TRUE;
 +}
 +
 +
 +static LRESULT
 +TOOLBAR_EnableButton (TOOLBAR_INFO *infoPtr, INT Id, LPARAM lParam)
 +{
 +    TBUTTON_INFO *btnPtr;
 +    INT nIndex;
 +    DWORD bState;
 +
 +    nIndex = TOOLBAR_GetButtonIndex (infoPtr, Id, FALSE);
 +
 +    TRACE("hwnd=%p, btn id=%d, lParam=0x%08lx\n", infoPtr->hwndSelf, Id, lParam);
 +
 +    if (nIndex == -1)
 +      return FALSE;
 +
 +    btnPtr = &infoPtr->buttons[nIndex];
 +
 +    bState = btnPtr->fsState & TBSTATE_ENABLED;
 +
 +    /* update the toolbar button state */
 +    if(LOWORD(lParam) == FALSE) {
 +      btnPtr->fsState &= ~(TBSTATE_ENABLED | TBSTATE_PRESSED);
 +    } else {
 +      btnPtr->fsState |= TBSTATE_ENABLED;
 +    }
 +
 +    /* redraw the button only if the state of the button changed */
 +    if(bState != (btnPtr->fsState & TBSTATE_ENABLED))
 +        InvalidateRect(infoPtr->hwndSelf, &btnPtr->rect, TRUE);
 +
 +    return TRUE;
 +}
 +
 +
 +static inline LRESULT
 +TOOLBAR_GetAnchorHighlight (const TOOLBAR_INFO *infoPtr)
 +{
 +    return infoPtr->bAnchor;
 +}
 +
 +
 +static LRESULT
 +TOOLBAR_GetBitmap (const TOOLBAR_INFO *infoPtr, INT Id)
 +{
 +    INT nIndex;
 +
 +    nIndex = TOOLBAR_GetButtonIndex (infoPtr, Id, FALSE);
 +    if (nIndex == -1)
 +      return -1;
 +
 +    return infoPtr->buttons[nIndex].iBitmap;
 +}
 +
 +
 +static inline LRESULT
 +TOOLBAR_GetBitmapFlags (void)
 +{
 +    return (GetDeviceCaps (0, LOGPIXELSX) >= 120) ? TBBF_LARGE : 0;
 +}
 +
 +
 +static LRESULT
 +TOOLBAR_GetButton (const TOOLBAR_INFO *infoPtr, INT nIndex, TBBUTTON *lpTbb)
 +{
 +    TBUTTON_INFO *btnPtr;
 +
 +    if (lpTbb == NULL)
 +      return FALSE;
 +
 +    if ((nIndex < 0) || (nIndex >= infoPtr->nNumButtons))
 +      return FALSE;
 +
 +    btnPtr = &infoPtr->buttons[nIndex];
 +    lpTbb->iBitmap   = btnPtr->iBitmap;
 +    lpTbb->idCommand = btnPtr->idCommand;
 +    lpTbb->fsState   = btnPtr->fsState;
 +    lpTbb->fsStyle   = btnPtr->fsStyle;
 +    lpTbb->bReserved[0] = 0;
 +    lpTbb->bReserved[1] = 0;
 +    lpTbb->dwData    = btnPtr->dwData;
 +    lpTbb->iString   = btnPtr->iString;
 +
 +    return TRUE;
 +}
 +
 +
 +static LRESULT
 +TOOLBAR_GetButtonInfoT(const TOOLBAR_INFO *infoPtr, INT Id, LPTBBUTTONINFOW lpTbInfo, BOOL bUnicode)
 +{
 +    /* TBBUTTONINFOW and TBBUTTONINFOA have the same layout*/
 +    TBUTTON_INFO *btnPtr;
 +    INT nIndex;
 +
 +    if (lpTbInfo == NULL)
 +      return -1;
 +
-                     /* when inserting separators, iBitmap controls it's size.
++    /* MSDN documents an iImageLabel field added in Vista but it is not present in
 +     * the headers and tests shows that even with comctl 6 Vista accepts only the
 +     * original TBBUTTONINFO size
 +     */
 +    if (lpTbInfo->cbSize != sizeof(TBBUTTONINFOW))
 +    {
 +        WARN("Invalid button size\n");
 +      return -1;
 +    }
 +
 +    nIndex = TOOLBAR_GetButtonIndex (infoPtr, Id, lpTbInfo->dwMask & TBIF_BYINDEX);
 +    if (nIndex == -1)
 +      return -1;
 +
 +    if (!(btnPtr = &infoPtr->buttons[nIndex])) return -1;
 +
 +    if (lpTbInfo->dwMask & TBIF_COMMAND)
 +      lpTbInfo->idCommand = btnPtr->idCommand;
 +    if (lpTbInfo->dwMask & TBIF_IMAGE)
 +      lpTbInfo->iImage = btnPtr->iBitmap;
 +    if (lpTbInfo->dwMask & TBIF_LPARAM)
 +      lpTbInfo->lParam = btnPtr->dwData;
 +    if (lpTbInfo->dwMask & TBIF_SIZE)
 +        /* tests show that for separators TBIF_SIZE returns not calculated width,
 +           but cx property, that differs from 0 only if application have
 +           specifically set it */
 +        lpTbInfo->cx = (btnPtr->fsStyle & BTNS_SEP)
 +            ? btnPtr->cx : (WORD)(btnPtr->rect.right - btnPtr->rect.left);
 +    if (lpTbInfo->dwMask & TBIF_STATE)
 +      lpTbInfo->fsState = btnPtr->fsState;
 +    if (lpTbInfo->dwMask & TBIF_STYLE)
 +      lpTbInfo->fsStyle = btnPtr->fsStyle;
 +    if (lpTbInfo->dwMask & TBIF_TEXT) {
 +        /* TB_GETBUTTONINFO doesn't retrieve text from the string list, so we
 +           can't use TOOLBAR_GetText here */
 +        if (!IS_INTRESOURCE(btnPtr->iString) && (btnPtr->iString != -1)) {
 +            LPWSTR lpText = (LPWSTR)btnPtr->iString;
 +            if (bUnicode)
 +                Str_GetPtrW(lpText, lpTbInfo->pszText, lpTbInfo->cchText);
 +            else
 +                Str_GetPtrWtoA(lpText, (LPSTR)lpTbInfo->pszText, lpTbInfo->cchText);
 +        } else
 +            lpTbInfo->pszText[0] = '\0';
 +    }
 +    return nIndex;
 +}
 +
 +
 +static inline LRESULT
 +TOOLBAR_GetButtonSize (const TOOLBAR_INFO *infoPtr)
 +{
 +    return MAKELONG((WORD)infoPtr->nButtonWidth,
 +                    (WORD)infoPtr->nButtonHeight);
 +}
 +
 +
 +static LRESULT
 +TOOLBAR_GetButtonText (const TOOLBAR_INFO *infoPtr, INT Id, LPWSTR lpStr, BOOL isW)
 +{
 +    INT nIndex;
 +    LPWSTR lpText;
 +    LRESULT ret = 0;
 +
 +    nIndex = TOOLBAR_GetButtonIndex (infoPtr, Id, FALSE);
 +    if (nIndex == -1)
 +      return -1;
 +
 +    lpText = TOOLBAR_GetText(infoPtr,&infoPtr->buttons[nIndex]);
 +
 +    if (isW)
 +    {
 +        if (lpText)
 +        {
 +            ret = strlenW (lpText);
 +            if (lpStr) strcpyW (lpStr, lpText);
 +        }
 +    }
 +    else
 +        ret = WideCharToMultiByte( CP_ACP, 0, lpText, -1,
 +                                  (LPSTR)lpStr, lpStr ? 0x7fffffff : 0, NULL, NULL ) - 1;
 +    return ret;
 +}
 +
 +
 +static LRESULT
 +TOOLBAR_GetDisabledImageList (const TOOLBAR_INFO *infoPtr, WPARAM wParam)
 +{
 +    TRACE("hwnd=%p, wParam=%ld\n", infoPtr->hwndSelf, wParam);
 +    /* UNDOCUMENTED: wParam is actually the ID of the image list to return */
 +    return (LRESULT)GETDISIMAGELIST(infoPtr, wParam);
 +}
 +
 +
 +static inline LRESULT
 +TOOLBAR_GetExtendedStyle (const TOOLBAR_INFO *infoPtr)
 +{
 +    TRACE("\n");
 +
 +    return infoPtr->dwExStyle;
 +}
 +
 +
 +static LRESULT
 +TOOLBAR_GetHotImageList (const TOOLBAR_INFO *infoPtr, WPARAM wParam)
 +{
 +    TRACE("hwnd=%p, wParam=%ld\n", infoPtr->hwndSelf, wParam);
 +    /* UNDOCUMENTED: wParam is actually the ID of the image list to return */
 +    return (LRESULT)GETHOTIMAGELIST(infoPtr, wParam);
 +}
 +
 +
 +static LRESULT
 +TOOLBAR_GetHotItem (const TOOLBAR_INFO *infoPtr)
 +{
 +    if (!((infoPtr->dwStyle & TBSTYLE_FLAT) || GetWindowTheme (infoPtr->hwndSelf)))
 +      return -1;
 +
 +    if (infoPtr->nHotItem < 0)
 +      return -1;
 +
 +    return (LRESULT)infoPtr->nHotItem;
 +}
 +
 +
 +static LRESULT
 +TOOLBAR_GetDefImageList (const TOOLBAR_INFO *infoPtr, WPARAM wParam)
 +{
 +    TRACE("hwnd=%p, wParam=%ld\n", infoPtr->hwndSelf, wParam);
 +    /* UNDOCUMENTED: wParam is actually the ID of the image list to return */
 +    return (LRESULT) GETDEFIMAGELIST(infoPtr, wParam);
 +}
 +
 +
 +static LRESULT
 +TOOLBAR_GetInsertMark (const TOOLBAR_INFO *infoPtr, TBINSERTMARK *lptbim)
 +{
 +    TRACE("hwnd = %p, lptbim = %p\n", infoPtr->hwndSelf, lptbim);
 +
 +    *lptbim = infoPtr->tbim;
 +
 +    return 0;
 +}
 +
 +
 +static inline LRESULT
 +TOOLBAR_GetInsertMarkColor (const TOOLBAR_INFO *infoPtr)
 +{
 +    TRACE("hwnd = %p\n", infoPtr->hwndSelf);
 +
 +    return (LRESULT)infoPtr->clrInsertMark;
 +}
 +
 +
 +static LRESULT
 +TOOLBAR_GetItemRect (const TOOLBAR_INFO *infoPtr, INT nIndex, LPRECT lpRect)
 +{
 +    TBUTTON_INFO *btnPtr;
 +
 +    btnPtr = &infoPtr->buttons[nIndex];
 +    if ((nIndex < 0) || (nIndex >= infoPtr->nNumButtons))
 +      return FALSE;
 +
 +    if (lpRect == NULL)
 +      return FALSE;
 +    if (btnPtr->fsState & TBSTATE_HIDDEN)
 +      return FALSE;
 +
 +    lpRect->left   = btnPtr->rect.left;
 +    lpRect->right  = btnPtr->rect.right;
 +    lpRect->bottom = btnPtr->rect.bottom;
 +    lpRect->top    = btnPtr->rect.top;
 +
 +    return TRUE;
 +}
 +
 +
 +static LRESULT
 +TOOLBAR_GetMaxSize (const TOOLBAR_INFO *infoPtr, LPSIZE lpSize)
 +{
 +    if (lpSize == NULL)
 +      return FALSE;
 +
 +    lpSize->cx = infoPtr->rcBound.right - infoPtr->rcBound.left;
 +    lpSize->cy = infoPtr->rcBound.bottom - infoPtr->rcBound.top;
 +
 +    TRACE("maximum size %d x %d\n",
 +         infoPtr->rcBound.right - infoPtr->rcBound.left,
 +         infoPtr->rcBound.bottom - infoPtr->rcBound.top);
 +
 +    return TRUE;
 +}
 +
 +
 +/* << TOOLBAR_GetObject >> */
 +
 +
 +static inline LRESULT
 +TOOLBAR_GetPadding (const TOOLBAR_INFO *infoPtr)
 +{
 +    return MAKELONG(infoPtr->szPadding.cx, infoPtr->szPadding.cy);
 +}
 +
 +
 +static LRESULT
 +TOOLBAR_GetRect (const TOOLBAR_INFO *infoPtr, INT Id, LPRECT lpRect)
 +{
 +    TBUTTON_INFO *btnPtr;
 +    INT        nIndex;
 +
 +    nIndex = TOOLBAR_GetButtonIndex (infoPtr, Id, FALSE);
 +    btnPtr = &infoPtr->buttons[nIndex];
 +    if ((nIndex < 0) || (nIndex >= infoPtr->nNumButtons))
 +      return FALSE;
 +
 +    if (lpRect == NULL)
 +      return FALSE;
 +
 +    lpRect->left   = btnPtr->rect.left;
 +    lpRect->right  = btnPtr->rect.right;
 +    lpRect->bottom = btnPtr->rect.bottom;
 +    lpRect->top    = btnPtr->rect.top;
 +
 +    return TRUE;
 +}
 +
 +
 +static inline LRESULT
 +TOOLBAR_GetRows (const TOOLBAR_INFO *infoPtr)
 +{
 +    return infoPtr->nRows;
 +}
 +
 +
 +static LRESULT
 +TOOLBAR_GetState (const TOOLBAR_INFO *infoPtr, INT Id)
 +{
 +    INT nIndex;
 +
 +    nIndex = TOOLBAR_GetButtonIndex (infoPtr, Id, FALSE);
 +    if (nIndex == -1)
 +      return -1;
 +
 +    return infoPtr->buttons[nIndex].fsState;
 +}
 +
 +
 +static inline LRESULT
 +TOOLBAR_GetStyle (const TOOLBAR_INFO *infoPtr)
 +{
 +    return infoPtr->dwStyle;
 +}
 +
 +
 +static inline LRESULT
 +TOOLBAR_GetTextRows (const TOOLBAR_INFO *infoPtr)
 +{
 +    return infoPtr->nMaxTextRows;
 +}
 +
 +
 +static LRESULT
 +TOOLBAR_GetToolTips (TOOLBAR_INFO *infoPtr)
 +{
 +    if ((infoPtr->dwStyle & TBSTYLE_TOOLTIPS) && (infoPtr->hwndToolTip == NULL))
 +        TOOLBAR_TooltipCreateControl(infoPtr);
 +    return (LRESULT)infoPtr->hwndToolTip;
 +}
 +
 +
 +static LRESULT
 +TOOLBAR_GetUnicodeFormat (const TOOLBAR_INFO *infoPtr)
 +{
 +    TRACE("%s hwnd=%p\n",
 +         infoPtr->bUnicode ? "TRUE" : "FALSE", infoPtr->hwndSelf);
 +
 +    return infoPtr->bUnicode;
 +}
 +
 +
 +static inline LRESULT
 +TOOLBAR_GetVersion (const TOOLBAR_INFO *infoPtr)
 +{
 +    return infoPtr->iVersion;
 +}
 +
 +
 +static LRESULT
 +TOOLBAR_HideButton (TOOLBAR_INFO *infoPtr, INT Id, BOOL fHide)
 +{
 +    TBUTTON_INFO *btnPtr;
 +    BYTE oldState;
 +    INT nIndex;
 +
 +    TRACE("\n");
 +
 +    nIndex = TOOLBAR_GetButtonIndex (infoPtr, Id, FALSE);
 +    if (nIndex == -1)
 +      return FALSE;
 +
 +    btnPtr = &infoPtr->buttons[nIndex];
 +    oldState = btnPtr->fsState;
 +
 +    if (fHide)
 +      btnPtr->fsState |= TBSTATE_HIDDEN;
 +    else
 +      btnPtr->fsState &= ~TBSTATE_HIDDEN;
 +
 +    if (oldState != btnPtr->fsState) {
 +        TOOLBAR_LayoutToolbar (infoPtr);
 +        InvalidateRect (infoPtr->hwndSelf, NULL, TRUE);
 +    }
 +
 +    return TRUE;
 +}
 +
 +
 +static inline LRESULT
 +TOOLBAR_HitTest (const TOOLBAR_INFO *infoPtr, const POINT* lpPt)
 +{
 +    return TOOLBAR_InternalHitTest (infoPtr, lpPt, NULL);
 +}
 +
 +
 +static LRESULT
 +TOOLBAR_Indeterminate (const TOOLBAR_INFO *infoPtr, INT Id, BOOL fIndeterminate)
 +{
 +    TBUTTON_INFO *btnPtr;
 +    INT nIndex;
 +    DWORD oldState;
 +
 +    nIndex = TOOLBAR_GetButtonIndex (infoPtr, Id, FALSE);
 +    if (nIndex == -1)
 +      return FALSE;
 +
 +    btnPtr = &infoPtr->buttons[nIndex];
 +    oldState = btnPtr->fsState;
 +
 +    if (fIndeterminate)
 +      btnPtr->fsState |= TBSTATE_INDETERMINATE;
 +    else
 +      btnPtr->fsState &= ~TBSTATE_INDETERMINATE;
 +
 +    if(oldState != btnPtr->fsState)
 +        InvalidateRect(infoPtr->hwndSelf, &btnPtr->rect, TRUE);
 +
 +    return TRUE;
 +}
 +
 +
 +static LRESULT
 +TOOLBAR_InsertButtonT(TOOLBAR_INFO *infoPtr, INT nIndex, const TBBUTTON *lpTbb, BOOL fUnicode)
 +{
 +    if (lpTbb == NULL)
 +      return FALSE;
 +
 +    if (nIndex == -1) {
 +       /* EPP: this seems to be an undocumented call (from my IE4)
 +      * I assume in that case that:
 +      * - index of insertion is at the end of existing buttons
 +      * I only see this happen with nIndex == -1, but it could have a special
 +      * meaning (like -nIndex (or ~nIndex) to get the real position of insertion).
 +      */
 +      nIndex = infoPtr->nNumButtons;
 +
 +    } else if (nIndex < 0)
 +       return FALSE;
 +
 +    TRACE("inserting button index=%d\n", nIndex);
 +    if (nIndex > infoPtr->nNumButtons) {
 +      nIndex = infoPtr->nNumButtons;
 +      TRACE("adjust index=%d\n", nIndex);
 +    }
 +
 +    return TOOLBAR_InternalInsertButtonsT(infoPtr, nIndex, 1, lpTbb, fUnicode);
 +}
 +
 +/* << TOOLBAR_InsertMarkHitTest >> */
 +
 +
 +static LRESULT
 +TOOLBAR_IsButtonChecked (const TOOLBAR_INFO *infoPtr, INT Id)
 +{
 +    INT nIndex;
 +
 +    nIndex = TOOLBAR_GetButtonIndex (infoPtr, Id, FALSE);
 +    if (nIndex == -1)
 +      return -1;
 +
 +    return (infoPtr->buttons[nIndex].fsState & TBSTATE_CHECKED);
 +}
 +
 +
 +static LRESULT
 +TOOLBAR_IsButtonEnabled (const TOOLBAR_INFO *infoPtr, INT Id)
 +{
 +    INT nIndex;
 +
 +    nIndex = TOOLBAR_GetButtonIndex (infoPtr, Id, FALSE);
 +    if (nIndex == -1)
 +      return -1;
 +
 +    return (infoPtr->buttons[nIndex].fsState & TBSTATE_ENABLED);
 +}
 +
 +
 +static LRESULT
 +TOOLBAR_IsButtonHidden (const TOOLBAR_INFO *infoPtr, INT Id)
 +{
 +    INT nIndex;
 +
 +    nIndex = TOOLBAR_GetButtonIndex (infoPtr, Id, FALSE);
 +    if (nIndex == -1)
 +      return -1;
 +
 +    return (infoPtr->buttons[nIndex].fsState & TBSTATE_HIDDEN);
 +}
 +
 +
 +static LRESULT
 +TOOLBAR_IsButtonHighlighted (const TOOLBAR_INFO *infoPtr, INT Id)
 +{
 +    INT nIndex;
 +
 +    nIndex = TOOLBAR_GetButtonIndex (infoPtr, Id, FALSE);
 +    if (nIndex == -1)
 +      return -1;
 +
 +    return (infoPtr->buttons[nIndex].fsState & TBSTATE_MARKED);
 +}
 +
 +
 +static LRESULT
 +TOOLBAR_IsButtonIndeterminate (const TOOLBAR_INFO *infoPtr, INT Id)
 +{
 +    INT nIndex;
 +
 +    nIndex = TOOLBAR_GetButtonIndex (infoPtr, Id, FALSE);
 +    if (nIndex == -1)
 +      return -1;
 +
 +    return (infoPtr->buttons[nIndex].fsState & TBSTATE_INDETERMINATE);
 +}
 +
 +
 +static LRESULT
 +TOOLBAR_IsButtonPressed (const TOOLBAR_INFO *infoPtr, INT Id)
 +{
 +    INT nIndex;
 +
 +    nIndex = TOOLBAR_GetButtonIndex (infoPtr, Id, FALSE);
 +    if (nIndex == -1)
 +      return -1;
 +
 +    return (infoPtr->buttons[nIndex].fsState & TBSTATE_PRESSED);
 +}
 +
 +
 +static LRESULT
 +TOOLBAR_LoadImages (TOOLBAR_INFO *infoPtr, WPARAM wParam, HINSTANCE hInstance)
 +{
 +    TBADDBITMAP tbab;
 +    tbab.hInst = hInstance;
 +    tbab.nID = wParam;
 +
 +    TRACE("hwnd = %p, hInst = %p, nID = %lu\n", infoPtr->hwndSelf, tbab.hInst, tbab.nID);
 +
 +    return TOOLBAR_AddBitmap(infoPtr, 0, &tbab);
 +}
 +
 +
 +static LRESULT
 +TOOLBAR_MapAccelerator (const TOOLBAR_INFO *infoPtr, WCHAR wAccel, UINT *pIDButton)
 +{
 +    WCHAR wszAccel[] = {'&',wAccel,0};
 +    int i;
 +    
 +    TRACE("hwnd = %p, wAccel = %x(%s), pIDButton = %p\n",
 +        infoPtr->hwndSelf, wAccel, debugstr_wn(&wAccel,1), pIDButton);
 +    
 +    for (i = 0; i < infoPtr->nNumButtons; i++)
 +    {
 +        TBUTTON_INFO *btnPtr = infoPtr->buttons+i;
 +        if (!(btnPtr->fsStyle & BTNS_NOPREFIX) &&
 +            !(btnPtr->fsState & TBSTATE_HIDDEN))
 +        {
 +            int iLen = strlenW(wszAccel);
 +            LPCWSTR lpszStr = TOOLBAR_GetText(infoPtr, btnPtr);
 +            
 +            if (!lpszStr)
 +                continue;
 +
 +            while (*lpszStr)
 +            {
 +                if ((lpszStr[0] == '&') && (lpszStr[1] == '&'))
 +                {
 +                    lpszStr += 2;
 +                    continue;
 +                }
 +                if (!strncmpiW(lpszStr, wszAccel, iLen))
 +                {
 +                    *pIDButton = btnPtr->idCommand;
 +                    return TRUE;
 +                }
 +                lpszStr++;
 +            }
 +        }
 +    }
 +    return FALSE;
 +}
 +
 +
 +static LRESULT
 +TOOLBAR_MarkButton (const TOOLBAR_INFO *infoPtr, INT Id, BOOL fMark)
 +{
 +    INT nIndex;
 +    DWORD oldState;
 +    TBUTTON_INFO *btnPtr;
 +
 +    TRACE("hwnd = %p, Id = %d, fMark = 0%d\n", infoPtr->hwndSelf, Id, fMark);
 +
 +    nIndex = TOOLBAR_GetButtonIndex (infoPtr, Id, FALSE);
 +    if (nIndex == -1)
 +        return FALSE;
 +
 +    btnPtr = &infoPtr->buttons[nIndex];
 +    oldState = btnPtr->fsState;
 +
 +    if (fMark)
 +        btnPtr->fsState |= TBSTATE_MARKED;
 +    else
 +        btnPtr->fsState &= ~TBSTATE_MARKED;
 +
 +    if(oldState != btnPtr->fsState)
 +        InvalidateRect(infoPtr->hwndSelf, &btnPtr->rect, TRUE);
 +
 +    return TRUE;
 +}
 +
 +
 +/* fixes up an index of a button affected by a move */
 +static inline void TOOLBAR_MoveFixupIndex(INT* pIndex, INT nIndex, INT nMoveIndex, BOOL bMoveUp)
 +{
 +    if (bMoveUp)
 +    {
 +        if (*pIndex > nIndex && *pIndex <= nMoveIndex)
 +            (*pIndex)--;
 +        else if (*pIndex == nIndex)
 +            *pIndex = nMoveIndex;
 +    }
 +    else
 +    {
 +        if (*pIndex >= nMoveIndex && *pIndex < nIndex)
 +            (*pIndex)++;
 +        else if (*pIndex == nIndex)
 +            *pIndex = nMoveIndex;
 +    }
 +}
 +
 +
 +static LRESULT
 +TOOLBAR_MoveButton (TOOLBAR_INFO *infoPtr, INT Id, INT nMoveIndex)
 +{
 +    INT nIndex;
 +    INT nCount;
 +    TBUTTON_INFO button;
 +
 +    TRACE("hwnd=%p, Id=%d, nMoveIndex=%d\n", infoPtr->hwndSelf, Id, nMoveIndex);
 +
 +    nIndex = TOOLBAR_GetButtonIndex (infoPtr, Id, TRUE);
 +    if ((nIndex == -1) || (nMoveIndex < 0))
 +        return FALSE;
 +
 +    if (nMoveIndex > infoPtr->nNumButtons - 1)
 +        nMoveIndex = infoPtr->nNumButtons - 1;
 +
 +    button = infoPtr->buttons[nIndex];
 +
 +    /* move button right */
 +    if (nIndex < nMoveIndex)
 +    {
 +        nCount = nMoveIndex - nIndex;
 +        memmove(&infoPtr->buttons[nIndex], &infoPtr->buttons[nIndex+1], nCount*sizeof(TBUTTON_INFO));
 +        infoPtr->buttons[nMoveIndex] = button;
 +
 +        TOOLBAR_MoveFixupIndex(&infoPtr->nButtonDown, nIndex, nMoveIndex, TRUE);
 +        TOOLBAR_MoveFixupIndex(&infoPtr->nButtonDrag, nIndex, nMoveIndex, TRUE);
 +        TOOLBAR_MoveFixupIndex(&infoPtr->nOldHit, nIndex, nMoveIndex, TRUE);
 +        TOOLBAR_MoveFixupIndex(&infoPtr->nHotItem, nIndex, nMoveIndex, TRUE);
 +    }
 +    else if (nIndex > nMoveIndex) /* move button left */
 +    {
 +        nCount = nIndex - nMoveIndex;
 +        memmove(&infoPtr->buttons[nMoveIndex+1], &infoPtr->buttons[nMoveIndex], nCount*sizeof(TBUTTON_INFO));
 +        infoPtr->buttons[nMoveIndex] = button;
 +
 +        TOOLBAR_MoveFixupIndex(&infoPtr->nButtonDown, nIndex, nMoveIndex, FALSE);
 +        TOOLBAR_MoveFixupIndex(&infoPtr->nButtonDrag, nIndex, nMoveIndex, FALSE);
 +      &