[CMAKE]
authorAmine Khaldi <amine.khaldi@reactos.org>
Sat, 26 Mar 2011 13:00:21 +0000 (13:00 +0000)
committerAmine Khaldi <amine.khaldi@reactos.org>
Sat, 26 Mar 2011 13:00:21 +0000 (13:00 +0000)
- Sync with trunk r51050.

svn path=/branches/cmake-bringup/; revision=51154

469 files changed:
1  2 
base/applications/charmap/charmap.c
base/applications/charmap/charmap.rc
base/applications/charmap/lang/bg-BG.rc
base/applications/charmap/lang/ca-ES.rc
base/applications/charmap/lang/cs-CZ.rc
base/applications/charmap/lang/de-DE.rc
base/applications/charmap/lang/el-GR.rc
base/applications/charmap/lang/en-US.rc
base/applications/charmap/lang/es-ES.rc
base/applications/charmap/lang/fr-FR.rc
base/applications/charmap/lang/id-ID.rc
base/applications/charmap/lang/it-IT.rc
base/applications/charmap/lang/ja-JP.rc
base/applications/charmap/lang/ko-KR.rc
base/applications/charmap/lang/lt-LT.rc
base/applications/charmap/lang/nl-NL.rc
base/applications/charmap/lang/no-NO.rc
base/applications/charmap/lang/pl-PL.rc
base/applications/charmap/lang/pt-BR.rc
base/applications/charmap/lang/ru-RU.rc
base/applications/charmap/lang/sk-SK.rc
base/applications/charmap/lang/uk-UA.rc
base/applications/charmap/lang/zh-CN.rc
base/applications/charmap/lang/zh-TW.rc
base/applications/charmap/map.c
base/applications/charmap/precomp.h
base/applications/cmdutils/xcopy/Es.rc
base/applications/cmdutils/xcopy/rsrc.rc
base/applications/dxdiag/precomp.h
base/applications/games/solitaire/solitaire.h
base/applications/games/spider/spider.h
base/applications/magnify/magnifier.h
base/applications/mplay32/mplay32.c
base/applications/mscutils/eventvwr/eventvwr.c
base/applications/network/ftp/cmds.c
base/applications/network/ftp/domacro.c
base/applications/network/ftp/fake.c
base/applications/network/ftp/ftp.c
base/applications/network/ftp/ftp_var.h
base/applications/network/ftp/main.c
base/applications/network/ftp/prototypes.h
base/applications/network/net/net.h
base/applications/network/ping/lang/uk-UA.rc
base/applications/network/ping/ping.rc
base/applications/notepad/dialog.c
base/applications/notepad/notepad.h
base/applications/notepad/settings.c
base/applications/paint/dialogs.h
base/applications/paint/history.h
base/applications/paint/mouse.h
base/applications/rapps/lang/fr-FR.rc
base/applications/rapps/rapps/7zip.txt
base/applications/rapps/rapps/abiword.txt
base/applications/rapps/rapps/abiword28x.txt
base/applications/rapps/rapps/abyss.txt
base/applications/rapps/rapps/ac97forvirtualbox.txt
base/applications/rapps/rapps/audiograbber.txt
base/applications/rapps/rapps/comctl32ocx.txt
base/applications/rapps/rapps/diablo2.txt
base/applications/rapps/rapps/dosblaster.txt
base/applications/rapps/rapps/dosbox.txt
base/applications/rapps/rapps/fap.txt
base/applications/rapps/rapps/firefox2.txt
base/applications/rapps/rapps/firefox3.txt
base/applications/rapps/rapps/firefox36.txt
base/applications/rapps/rapps/freebasic.txt
base/applications/rapps/rapps/glidewrapzbag.txt
base/applications/rapps/rapps/go-oo.txt
base/applications/rapps/rapps/irfanview.txt
base/applications/rapps/rapps/irfanviewplugins.txt
base/applications/rapps/rapps/kdewin.txt
base/applications/rapps/rapps/lbreakout2.txt
base/applications/rapps/rapps/lgeneral.txt
base/applications/rapps/rapps/libreoffice.txt
base/applications/rapps/rapps/lmarbles.txt
base/applications/rapps/rapps/mfc40.txt
base/applications/rapps/rapps/mingw.txt
base/applications/rapps/rapps/mirandaim.txt
base/applications/rapps/rapps/mirc.txt
base/applications/rapps/rapps/mirc6.txt
base/applications/rapps/rapps/mono2.txt
base/applications/rapps/rapps/mpc.txt
base/applications/rapps/rapps/msxml3.txt
base/applications/rapps/rapps/net11.txt
base/applications/rapps/rapps/net20.txt
base/applications/rapps/rapps/net20sp2.txt
base/applications/rapps/rapps/offbyone.txt
base/applications/rapps/rapps/openoffice2.4.txt
base/applications/rapps/rapps/openoffice3.0.txt
base/applications/rapps/rapps/openttd.txt
base/applications/rapps/rapps/opera.txt
base/applications/rapps/rapps/opera9.txt
base/applications/rapps/rapps/putty.txt
base/applications/rapps/rapps/python.txt
base/applications/rapps/rapps/remood.txt
base/applications/rapps/rapps/rosbe.txt
base/applications/rapps/rapps/rosbeamd64.txt
base/applications/rapps/rapps/rosbearm.txt
base/applications/rapps/rapps/sambatng.txt
base/applications/rapps/rapps/sbforvmware.txt
base/applications/rapps/rapps/scite.txt
base/applications/rapps/rapps/scummvm.txt
base/applications/rapps/rapps/sdl_mixer.txt
base/applications/rapps/rapps/sdl_runtime.txt
base/applications/rapps/rapps/seamonkey.txt
base/applications/rapps/rapps/smplayer.txt
base/applications/rapps/rapps/steam.txt
base/applications/rapps/rapps/sumatrapdf.txt
base/applications/rapps/rapps/superfinder.txt
base/applications/rapps/rapps/tahoma.txt
base/applications/rapps/rapps/thunderbird.txt
base/applications/rapps/rapps/tileworld.txt
base/applications/rapps/rapps/tuxpaint.txt
base/applications/rapps/rapps/ultravnc.txt
base/applications/rapps/rapps/utorrent.txt
base/applications/rapps/rapps/vb5run.txt
base/applications/rapps/rapps/vb6run.txt
base/applications/rapps/rapps/vc2005run.txt
base/applications/rapps/rapps/vc2005sp1run.txt
base/applications/rapps/rapps/vc2008run.txt
base/applications/rapps/rapps/vc2008sp1run.txt
base/applications/rapps/rapps/vc6run.txt
base/applications/rapps/rapps/vlc.txt
base/applications/rapps/rapps/winboard.txt
base/applications/rapps/rapps/wme9.txt
base/applications/rapps/rsrc.rc
base/applications/rapps/winmain.c
base/services/audiosrv/audiosrv.h
base/services/tcpsvcs/tcpsvcs.h
base/services/tftpd/tftpd.h
base/services/umpnpmgr/umpnpmgr.c
base/setup/usetup/cabinet.h
base/setup/usetup/inffile.c
base/setup/usetup/inffile.h
base/setup/usetup/interface/usetup.c
base/setup/usetup/registry.c
base/setup/usetup/settings.c
base/setup/usetup/usetup.h
base/shell/cmd/batch.h
base/shell/explorer-new/trayntfy.c
base/shell/explorer/shell/mainframe.cpp
base/shell/explorer/shell/pane.cpp
base/shell/explorer/shell/shellbrowser.cpp
base/shell/explorer/utility/window.cpp
base/system/runonce/lang/fr-FR.rc
base/system/runonce/rsrc.rc
base/system/services/database.c
base/system/services/services.c
base/system/services/services.h
base/system/winlogon/sas.c
base/system/winlogon/winlogon.c
base/system/winlogon/winlogon.h
boot/bootdata/hivedef_amd64.inf
boot/bootdata/hivedef_arm.inf
boot/bootdata/hivedef_i386.inf
boot/bootdata/hivesys_amd64.inf
boot/bootdata/hivesys_arm.inf
boot/bootdata/hivesys_i386.inf
boot/bootdata/txtsetup.sif
boot/freeldr/freeldr/debug.c
boot/freeldr/freeldr/freeldr.c
dll/cpl/console/lang/fr-Fr.rc
dll/cpl/console/rsrc.rc
dll/cpl/input/input.h
dll/cpl/usrmgr/lang/fr-FR.rc
dll/cpl/usrmgr/rsrc.rc
dll/directx/ddraw/rosdraw.h
dll/directx/msdmo/stubs.c
dll/ntdll/CMakeLists.txt
dll/ntdll/ldr/ldrinit.c
dll/ntdll/ldr/startup.c
dll/ntdll/ldr/utils.c
dll/win32/advapi32/crypt/crypt.c
dll/win32/advapi32/misc/efs.c
dll/win32/advapi32/service/scm.c
dll/win32/atl/stubs.c
dll/win32/cabinet/stubs.c
dll/win32/cfgmgr32/cfgmgr32.spec
dll/win32/comctl32/comboex.c
dll/win32/comctl32/comctl32.h
dll/win32/comctl32/comctl32.spec
dll/win32/comctl32/comctl_Bg.rc
dll/win32/comctl32/comctl_Cs.rc
dll/win32/comctl32/comctl_Da.rc
dll/win32/comctl32/comctl_De.rc
dll/win32/comctl32/comctl_El.rc
dll/win32/comctl32/comctl_En.rc
dll/win32/comctl32/comctl_Eo.rc
dll/win32/comctl32/comctl_Es.rc
dll/win32/comctl32/comctl_Fr.rc
dll/win32/comctl32/comctl_He.rc
dll/win32/comctl32/comctl_Hu.rc
dll/win32/comctl32/comctl_It.rc
dll/win32/comctl32/comctl_Ja.rc
dll/win32/comctl32/comctl_Ko.rc
dll/win32/comctl32/comctl_Lt.rc
dll/win32/comctl32/comctl_Nl.rc
dll/win32/comctl32/comctl_No.rc
dll/win32/comctl32/comctl_Pl.rc
dll/win32/comctl32/comctl_Pt.rc
dll/win32/comctl32/comctl_Ro.rc
dll/win32/comctl32/comctl_Ru.rc
dll/win32/comctl32/comctl_Si.rc
dll/win32/comctl32/comctl_Sk.rc
dll/win32/comctl32/comctl_Sr.rc
dll/win32/comctl32/comctl_Sv.rc
dll/win32/comctl32/comctl_Th.rc
dll/win32/comctl32/comctl_Tr.rc
dll/win32/comctl32/comctl_Uk.rc
dll/win32/comctl32/comctl_Zh.rc
dll/win32/comctl32/commctrl.c
dll/win32/comctl32/datetime.c
dll/win32/comctl32/header.c
dll/win32/comctl32/idb_hist_large.bmp
dll/win32/comctl32/idb_hist_small.bmp
dll/win32/comctl32/idb_std_large.bmp
dll/win32/comctl32/idb_std_small.bmp
dll/win32/comctl32/idb_view_large.bmp
dll/win32/comctl32/idb_view_small.bmp
dll/win32/comctl32/imagelist.c
dll/win32/comctl32/ipaddress.c
dll/win32/comctl32/listview.c
dll/win32/comctl32/monthcal.c
dll/win32/comctl32/pager.c
dll/win32/comctl32/progress.c
dll/win32/comctl32/propsheet.c
dll/win32/comctl32/rebar.c
dll/win32/comctl32/rsrc.rc
dll/win32/comctl32/status.c
dll/win32/comctl32/tab.c
dll/win32/comctl32/toolbar.c
dll/win32/comctl32/tooltips.c
dll/win32/comctl32/treeview.c
dll/win32/cryptdll/stubs.c
dll/win32/dhcpcsvc/include/rosdhcp.h
dll/win32/gdi32/include/gdi32p.h
dll/win32/gdi32/objects/bitmap.c
dll/win32/gdi32/objects/utils.c
dll/win32/imagehlp/integrity.c
dll/win32/iphlpapi/resinfo.h
dll/win32/kernel32/file/bintype.c
dll/win32/kernel32/file/cnotify.c
dll/win32/kernel32/file/copy.c
dll/win32/kernel32/file/file.c
dll/win32/kernel32/file/find.c
dll/win32/kernel32/file/npipe.c
dll/win32/kernel32/include/kernel32.h
dll/win32/kernel32/kernel32.spec
dll/win32/kernel32/mem/local.c
dll/win32/kernel32/misc/console.c
dll/win32/kernel32/misc/env.c
dll/win32/kernel32/misc/error.c
dll/win32/kernel32/misc/ldr.c
dll/win32/kernel32/misc/utils.c
dll/win32/kernel32/process/proc.c
dll/win32/kernel32/process/procsup.c
dll/win32/loadperf/stubs.c
dll/win32/lpk/ros_lpk.h
dll/win32/mapi32/mapi32.spec
dll/win32/msafd/misc/dllmain.c
dll/win32/msafd/msafd.h
dll/win32/netshell/precomp.h
dll/win32/opengl32/icdtable.h
dll/win32/opengl32/opengl32.c
dll/win32/opengl32/wgl.c
dll/win32/rpcrt4/rpc_transport.c
dll/win32/secur32/sspi.c
dll/win32/setupapi/cfgmgr.c
dll/win32/setupapi/devclass.c
dll/win32/setupapi/devinst.c
dll/win32/setupapi/install.c
dll/win32/setupapi/misc.c
dll/win32/setupapi/parser.c
dll/win32/setupapi/rpc.c
dll/win32/setupapi/setupapi.spec
dll/win32/setupapi/stringtable.c
dll/win32/setupapi/stubs.c
dll/win32/sfc/precomp.h
dll/win32/shell32/dialogs.c
dll/win32/shell32/iconcache.c
dll/win32/shell32/she_ocmenu.c
dll/win32/shell32/shlview.c
dll/win32/syssetup/install.c
dll/win32/user32/controls/combo.c
dll/win32/user32/controls/edit.c
dll/win32/user32/include/user32p.h
dll/win32/user32/misc/misc.c
dll/win32/user32/resources/obm_btncorners.bmp
dll/win32/user32/resources/obm_btsize.bmp
dll/win32/user32/resources/obm_check.bmp
dll/win32/user32/resources/obm_dnarrow.bmp
dll/win32/user32/resources/obm_dnarrowd.bmp
dll/win32/user32/resources/obm_dnarrowi.bmp
dll/win32/user32/resources/obm_lfarrow.bmp
dll/win32/user32/resources/obm_lfarrowd.bmp
dll/win32/user32/resources/obm_lfarrowi.bmp
dll/win32/user32/resources/obm_old_close.bmp
dll/win32/user32/resources/obm_old_dnarrow.bmp
dll/win32/user32/resources/obm_old_lfarrow.bmp
dll/win32/user32/resources/obm_old_reduce.bmp
dll/win32/user32/resources/obm_old_restore.bmp
dll/win32/user32/resources/obm_old_rgarrow.bmp
dll/win32/user32/resources/obm_old_uparrow.bmp
dll/win32/user32/resources/obm_old_zoom.bmp
dll/win32/user32/resources/obm_reduce.bmp
dll/win32/user32/resources/obm_reduced.bmp
dll/win32/user32/resources/obm_restore.bmp
dll/win32/user32/resources/obm_restored.bmp
dll/win32/user32/resources/obm_rgarrow.bmp
dll/win32/user32/resources/obm_rgarrowd.bmp
dll/win32/user32/resources/obm_rgarrowi.bmp
dll/win32/user32/resources/obm_size.bmp
dll/win32/user32/resources/obm_trtype.bmp
dll/win32/user32/resources/obm_uparrow.bmp
dll/win32/user32/resources/obm_uparrowd.bmp
dll/win32/user32/resources/obm_uparrowi.bmp
dll/win32/user32/resources/obm_zoom.bmp
dll/win32/user32/resources/obm_zoomd.bmp
dll/win32/user32/user32.rc
dll/win32/user32/windows/defwnd.c
dll/win32/user32/windows/input.c
dll/win32/user32/windows/menu.c
dll/win32/user32/windows/message.c
dll/win32/user32/windows/messagebox.c
dll/win32/user32/windows/nonclient.c
dll/win32/user32/windows/paint.c
dll/win32/user32/windows/window.c
dll/win32/wdmaud.drv/legacy.c
dll/win32/wdmaud.drv/wdmaud.h
dll/win32/wininet/CMakeLists.txt
dll/win32/wininet/urlcache.c
dll/win32/ws2_32_new/inc/ws2_32p.h
drivers/filesystems/fastfat/create.c
drivers/filesystems/fastfat/finfo.c
drivers/filesystems/fastfat_new/dir.c
drivers/filesystems/npfs/fsctrl.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_init.cpp
drivers/storage/ide/uniata/id_probe.cpp
drivers/storage/ide/uniata/id_sata.cpp
drivers/storage/ide/uniata/uata_ctl.h
drivers/storage/ide/uniata/uniata_ver.h
drivers/wdm/audio/backpln/portcls/dma_slave.cpp
drivers/wdm/audio/backpln/portcls/interfaces.hpp
drivers/wdm/audio/backpln/portcls/pin_wavecyclic.cpp
hal/halx86/generic/usage.c
include/crt/_mingw_mac.h
include/crt/_mingw_unicode.h
include/ddk/ioaccess.h
include/ddk/punknown.h
include/ndk/haltypes.h
include/ndk/rtltypes.h
include/psdk/commctrl.h
include/psdk/richedit.h
include/psdk/setupapi.h
include/psdk/windowsx.h
include/psdk/wingdi.h
include/psdk/winuser.h
include/reactos/idl/pnp.idl
include/reactos/libs/sound/mmebuddy.h
include/reactos/subsys/csrss/csrss.h
include/reactos/undocuser.h
include/reactos/win32k/ntuser.h
include/reactos/wine/config.h
include/reactos/winlogon.h
include/xdk/kefuncs.h
lib/drivers/sound/mmebuddy/mmewrap.c
lib/drivers/sound/mmebuddy/wave/header.c
lib/drivers/sound/mmebuddy/wave/streaming.c
lib/inflib/infros.h
lib/rtl/CMakeLists.txt
lib/rtl/avlsupp.c
lib/rtl/avltable.c
lib/rtl/critical.c
lib/rtl/heap.c
lib/rtl/heap.h
lib/rtl/heapdbg.c
lib/rtl/heappage.c
lib/rtl/nls.c
lib/rtl/path.c
lib/rtl/unicode.c
lib/sdk/crt/direct/chdir.c
lib/sdk/crt/direct/getdrive.c
lib/sdk/crt/printf/streamout.c
lib/sdk/crt/string/mbstowcs_nt.c
media/doc/README.WINE
ntoskrnl/CMakeLists.txt
ntoskrnl/ex/init.c
ntoskrnl/fsrtl/dbcsname.c
ntoskrnl/fsrtl/name.c
ntoskrnl/fstub/disksup.c
ntoskrnl/fstub/halstub.c
ntoskrnl/fstub/translate.c
ntoskrnl/include/internal/cm.h
ntoskrnl/include/internal/hal.h
ntoskrnl/include/internal/kd.h
ntoskrnl/io/pnpmgr/pnpres.c
ntoskrnl/kd/kdmain.c
ntoskrnl/kdbg/kdb_cli.c
ntoskrnl/ke/i386/cpu.c
ntoskrnl/ke/i386/traphdlr.c
ntoskrnl/mm/ARM3/miavl.h
ntoskrnl/mm/marea.c
ntoskrnl/ps/query.c
ntoskrnl/ps/state.c
subsystems/win32/csrss/csrsrv/api/process.c
subsystems/win32/csrss/win32csr/CMakeLists.txt
subsystems/win32/csrss/win32csr/dllmain.c
subsystems/win32/csrss/win32csr/file.c
subsystems/win32/csrss/win32csr/file.h
subsystems/win32/csrss/win32csr/harderror.c
subsystems/win32/csrss/win32csr/w32csr.h
subsystems/win32/win32k/CMakeLists.txt
subsystems/win32/win32k/dib/dib.c
subsystems/win32/win32k/dib/dib.h
subsystems/win32/win32k/dib/dib1bpp.c
subsystems/win32/win32k/dib/stretchblt.c
subsystems/win32/win32k/eng/bitblt.c
subsystems/win32/win32k/eng/copybits.c
subsystems/win32/win32k/eng/gradient.c
subsystems/win32/win32k/eng/mouse.c
subsystems/win32/win32k/eng/stretchblt.c
subsystems/win32/win32k/eng/xlate.c
subsystems/win32/win32k/include/color.h
subsystems/win32/win32k/include/dc.h
subsystems/win32/win32k/include/gdidebug.h
subsystems/win32/win32k/include/gdiobj.h
subsystems/win32/win32k/include/inteng.h
subsystems/win32/win32k/include/intgdi.h
subsystems/win32/win32k/include/msgqueue.h
subsystems/win32/win32k/include/palette.h
subsystems/win32/win32k/include/win32.h
subsystems/win32/win32k/include/win32kp.h
subsystems/win32/win32k/include/winpos.h
subsystems/win32/win32k/include/winsta.h
subsystems/win32/win32k/main/dllmain.c
subsystems/win32/win32k/ntuser/desktop.c
subsystems/win32/win32k/ntuser/focus.c
subsystems/win32/win32k/ntuser/hook.c
subsystems/win32/win32k/ntuser/input.c
subsystems/win32/win32k/ntuser/message.c
subsystems/win32/win32k/ntuser/monitor.c
subsystems/win32/win32k/ntuser/msgqueue.c
subsystems/win32/win32k/ntuser/ntstubs.c
subsystems/win32/win32k/ntuser/ntuser.c
subsystems/win32/win32k/ntuser/painting.c
subsystems/win32/win32k/ntuser/simplecall.c
subsystems/win32/win32k/ntuser/windc.c
subsystems/win32/win32k/ntuser/window.c
subsystems/win32/win32k/ntuser/winpos.c
subsystems/win32/win32k/ntuser/winsta.c
subsystems/win32/win32k/objects/bitblt.c
subsystems/win32/win32k/objects/bitmaps.c
subsystems/win32/win32k/objects/brush.c
subsystems/win32/win32k/objects/dclife.c
subsystems/win32/win32k/objects/dcobjs.c
subsystems/win32/win32k/objects/dcutil.c
subsystems/win32/win32k/objects/dibobj.c
subsystems/win32/win32k/objects/drawing.c
subsystems/win32/win32k/objects/fillshap.c
subsystems/win32/win32k/objects/freetype.c
subsystems/win32/win32k/objects/gdidbg.c
subsystems/win32/win32k/objects/gdiobj.c
subsystems/win32/win32k/objects/palette.c
subsystems/win32/win32k/objects/path.c
subsystems/win32/win32k/objects/polyfill.c
subsystems/win32/win32k/objects/region.c

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
Simple merge
Simple merge
Simple merge
Simple merge
Simple merge
Simple merge
index 4be2390,0000000..c1bdae7
mode 100644,000000..100644
--- /dev/null
@@@ -1,12 -1,0 +1,13 @@@
 +#include "lang/bg-BG.rc"
 +#include "lang/cs-CZ.rc"
 +#include "lang/de-DE.rc"
 +#include "lang/en-US.rc"
 +#include "lang/es-ES.rc"
++#include "lang/fr-FR.rc"
 +#include "lang/it-IT.rc"
 +//#include "lang/ja-JP.rc" FIXME: iconv issue
 +#include "lang/no-NO.rc"
 +#include "lang/pl-PL.rc"
 +#include "lang/ru-RU.rc"
 +#include "lang/sk-SK.rc"
 +#include "lang/uk-UA.rc"
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,8c5d3bb..8c5d3bb
mode 000000,100644..100644
--- /dev/null
Simple merge
Simple merge
Simple merge
Simple merge
Simple merge
Simple merge
Simple merge
Simple merge
Simple merge
index aeb59c4,b49f1ba..b49f1ba
Binary files differ
Simple merge
Simple merge
Simple merge
Simple merge
index 08f49bd,0000000..daabc67
mode 100644,000000..100644
--- /dev/null
@@@ -1,373 -1,0 +1,360 @@@
- // We need to emulate these, because the original ones don't work in freeldr
- int __cdecl wctomb(char *mbchar, wchar_t wchar)
- {
-     *mbchar = wchar;
-     return 1;
- }
- int __cdecl mbtowc (wchar_t *wchar, const char *mbchar, size_t count)
- {
-     *wchar = *mbchar;
-     return 1;
- }
 +/*
 + *  FreeLoader
 + *  Copyright (C) 1998-2003  Brian Palmer  <brianp@sginet.com>
 + *
 + *  This program is free software; you can redistribute it and/or modify
 + *  it under the terms of the GNU General Public License as published by
 + *  the Free Software Foundation; either version 2 of the License, or
 + *  (at your option) any later version.
 + *
 + *  This program 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 General Public License for more details.
 + *
 + *  You should have received a copy of the GNU General Public License along
 + *  with this program; if not, write to the Free Software Foundation, Inc.,
 + *  51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
 + */
 +
 +#include <freeldr.h>
 +
 +#include <debug.h>
 +
 +#if DBG && !defined(_M_ARM)
 +
 +//#define DEBUG_ALL
 +//#define DEBUG_INIFILE
 +//#define DEBUG_REACTOS
 +//#define DEBUG_CUSTOM
 +#define DEBUG_NONE
 +
 +#if defined (DEBUG_ALL)
 +ULONG         DebugPrintMask = DPRINT_WARNING | DPRINT_MEMORY | DPRINT_FILESYSTEM |
 +                               DPRINT_UI | DPRINT_DISK | DPRINT_CACHE | DPRINT_REACTOS |
 +                               DPRINT_LINUX | DPRINT_HWDETECT;
 +#elif defined (DEBUG_INIFILE)
 +ULONG         DebugPrintMask = DPRINT_INIFILE;
 +#elif defined (DEBUG_REACTOS)
 +ULONG         DebugPrintMask = DPRINT_REACTOS | DPRINT_REGISTRY;
 +#elif defined (DEBUG_CUSTOM)
 +ULONG         DebugPrintMask = DPRINT_WARNING |
 +                               DPRINT_UI | DPRINT_CACHE | DPRINT_REACTOS |
 +                               DPRINT_LINUX;
 +#else //#elif defined (DEBUG_NONE)
 +ULONG         DebugPrintMask = 0;
 +#endif
 +
 +#define       SCREEN                          1
 +#define       RS232                           2
 +#define BOCHS                         4
 +
 +#define       COM1                            1
 +#define       COM2                            2
 +#define       COM3                            3
 +#define       COM4                            4
 +
 +#define BOCHS_OUTPUT_PORT     0xe9
 +
 +ULONG         DebugPort = RS232;
 +//ULONG               DebugPort = SCREEN;
 +//ULONG               DebugPort = BOCHS;
 +//ULONG               DebugPort = SCREEN|BOCHS;
 +ULONG         ComPort = COM1;
 +//ULONG               BaudRate = 19200;
 +ULONG         BaudRate = 115200;
 +
 +BOOLEAN       DebugStartOfLine = TRUE;
 +
 +VOID DebugInit(VOID)
 +{
 +      if (DebugPort & RS232)
 +      {
 +              Rs232PortInitialize(ComPort, BaudRate);
 +      }
 +}
 +
 +VOID DebugPrintChar(UCHAR Character)
 +{
 +      if (Character == '\n')
 +      {
 +              DebugStartOfLine = TRUE;
 +      }
 +
 +      if (DebugPort & RS232)
 +      {
 +              if (Character == '\n')
 +              {
 +                      Rs232PortPutByte('\r');
 +              }
 +              Rs232PortPutByte(Character);
 +      }
 +      if (DebugPort & BOCHS)
 +      {
 +              WRITE_PORT_UCHAR((PUCHAR)BOCHS_OUTPUT_PORT, Character);
 +      }
 +      if (DebugPort & SCREEN)
 +      {
 +              MachConsPutChar(Character);
 +      }
 +}
 +
 +ULONG
 +DbgPrint(const char *Format, ...)
 +{
 +      int i;
 +      int Length;
 +      va_list ap;
 +      CHAR Buffer[512];
 +
 +      va_start(ap, Format);
 +      Length = _vsnprintf(Buffer, sizeof(Buffer), Format, ap);
 +      va_end(ap);
 +
 +      /* Check if we went past the buffer */
 +      if (Length == -1)
 +      {
 +              /* Terminate it if we went over-board */
 +              Buffer[sizeof(Buffer) - 1] = '\n';
 +
 +              /* Put maximum */
 +              Length = sizeof(Buffer);
 +      }
 +
 +      for (i = 0; i < Length; i++)
 +      {
 +              DebugPrintChar(Buffer[i]);
 +      }
 +
 +      return 0;
 +}
 +
 +VOID DebugPrintHeader(ULONG Mask)
 +{
 +  /* No header */
 +  if (Mask == 0)
 +    return;
 +
 +      switch (Mask)
 +      {
 +      case DPRINT_WARNING:
 +          DbgPrint("WARNING: ");
 +              break;
 +      case DPRINT_MEMORY:
 +          DbgPrint("MEMORY: ");
 +              break;
 +      case DPRINT_FILESYSTEM:
 +          DbgPrint("FILESYS: ");
 +              break;
 +      case DPRINT_INIFILE:
 +          DbgPrint("INIFILE: ");
 +              break;
 +      case DPRINT_UI:
 +          DbgPrint("UI: ");
 +              break;
 +      case DPRINT_DISK:
 +          DbgPrint("DISK: ");
 +              break;
 +      case DPRINT_CACHE:
 +          DbgPrint("CACHE: ");
 +              break;
 +      case DPRINT_REGISTRY:
 +          DbgPrint("REGISTRY: ");
 +              break;
 +      case DPRINT_REACTOS:
 +          DbgPrint("REACTOS: ");
 +              break;
 +      case DPRINT_LINUX:
 +          DbgPrint("LINUX: ");
 +              break;
 +      case DPRINT_WINDOWS:
 +          DbgPrint("WINLDR: ");
 +              break;
 +      case DPRINT_HWDETECT:
 +          DbgPrint("HWDETECT: ");
 +              break;
 +      case DPRINT_PELOADER:
 +          DbgPrint("PELOADER: ");
 +              break;
 +      case DPRINT_SCSIPORT:
 +          DbgPrint("SCSIPORT: ");
 +              break;
 +      default:
 +          DbgPrint("UNKNOWN: ");
 +              break;
 +      }
 +}
 +
 +char* g_file;
 +int g_line;
 +
 +VOID DbgPrintMask(ULONG Mask, char *format, ...)
 +{
 +      va_list ap;
 +      char Buffer[2096];
 +      char *ptr = Buffer;
 +
 +      // Mask out unwanted debug messages
 +      if (!(Mask & DebugPrintMask))
 +      {
 +              return;
 +      }
 +
 +      // Disable file/line for scsiport messages
 +      if (Mask & DPRINT_SCSIPORT)
 +      {
 +              DebugStartOfLine = FALSE;
 +      }
 +
 +      // Print the header if we have started a new line
 +      if (DebugStartOfLine)
 +      {
 +              DbgPrint("(%s:%d) ", g_file, g_line);
 +              DebugPrintHeader(Mask);
 +              DebugStartOfLine = FALSE;
 +      }
 +
 +      va_start(ap, format);
 +      vsprintf(Buffer, format, ap);
 +      va_end(ap);
 +
 +      while (*ptr)
 +      {
 +              DebugPrintChar(*ptr++);
 +      }
 +}
 +
 +VOID DebugDumpBuffer(ULONG Mask, PVOID Buffer, ULONG Length)
 +{
 +      PUCHAR  BufPtr = (PUCHAR)Buffer;
 +      ULONG           Idx;
 +      ULONG           Idx2;
 +
 +      // Mask out unwanted debug messages
 +      if (!(Mask & DebugPrintMask))
 +      {
 +              return;
 +      }
 +
 +      DebugStartOfLine = FALSE; // We don't want line headers
 +      DbgPrintMask(Mask, "Dumping buffer at 0x%x with length of %d bytes:\n", Buffer, Length);
 +
 +      for (Idx=0; Idx<Length; )
 +      {
 +              DebugStartOfLine = FALSE; // We don't want line headers
 +
 +              if (Idx < 0x0010)
 +              {
 +                      DbgPrintMask(Mask, "000%x:\t", Idx);
 +              }
 +              else if (Idx < 0x0100)
 +              {
 +                      DbgPrintMask(Mask, "00%x:\t", Idx);
 +              }
 +              else if (Idx < 0x1000)
 +              {
 +                      DbgPrintMask(Mask, "0%x:\t", Idx);
 +              }
 +              else
 +              {
 +                      DbgPrintMask(Mask, "%x:\t", Idx);
 +              }
 +
 +              for (Idx2=0; Idx2<16; Idx2++,Idx++)
 +              {
 +                      if (BufPtr[Idx] < 0x10)
 +                      {
 +                              DbgPrintMask(Mask, "0");
 +                      }
 +                      DbgPrintMask(Mask, "%x", BufPtr[Idx]);
 +
 +                      if (Idx2 == 7)
 +                      {
 +                              DbgPrintMask(Mask, "-");
 +                      }
 +                      else
 +                      {
 +                              DbgPrintMask(Mask, " ");
 +                      }
 +              }
 +
 +              Idx -= 16;
 +              DbgPrintMask(Mask, " ");
 +
 +              for (Idx2=0; Idx2<16; Idx2++,Idx++)
 +              {
 +                      if ((BufPtr[Idx] > 20) && (BufPtr[Idx] < 0x80))
 +                      {
 +                              DbgPrintMask(Mask, "%c", BufPtr[Idx]);
 +                      }
 +                      else
 +                      {
 +                              DbgPrintMask(Mask, ".");
 +                      }
 +              }
 +
 +              DbgPrintMask(Mask, "\n");
 +      }
 +}
 +
 +#else
 +
 +VOID DbgPrintMask(ULONG Mask, char *format, ...)
 +{
 +}
 +
 +ULONG DbgPrint(PCCH Format, ...)
 +{
 +    return 0;
 +}
 +
 +#endif // DBG
 +
 +ULONG
 +MsgBoxPrint(const char *Format, ...)
 +{
 +      va_list ap;
 +      CHAR Buffer[512];
 +      ULONG Length;
 +
 +      va_start(ap, Format);
 +
 +      /* Construct a string */
 +      Length = _vsnprintf(Buffer, 512, Format, ap);
 +
 +      /* Check if we went past the buffer */
 +      if (Length == MAXULONG)
 +      {
 +              /* Terminate it if we went over-board */
 +              Buffer[sizeof(Buffer) - 1] = '\n';
 +
 +              /* Put maximum */
 +              Length = sizeof(Buffer);
 +      }
 +
 +      /* Show it as a message box */
 +      UiMessageBox(Buffer);
 +
 +      /* Cleanup and exit */
 +      va_end(ap);
 +      return 0;
 +}
 +
 +NTKERNELAPI
 +VOID
 +NTAPI
 +KeBugCheckEx(
 +    IN ULONG  BugCheckCode,
 +    IN ULONG_PTR  BugCheckParameter1,
 +    IN ULONG_PTR  BugCheckParameter2,
 +    IN ULONG_PTR  BugCheckParameter3,
 +    IN ULONG_PTR  BugCheckParameter4)
 +{
 +    char Buffer[70];
 +    sprintf(Buffer, "*** STOP: 0x%08lX (0x%08lX, 0x%08lX, 0x%08lX, 0x%08lX)",
 +        BugCheckCode, BugCheckParameter1, BugCheckParameter2,
 +        BugCheckParameter3, BugCheckParameter4);
 +    UiMessageBoxCritical(Buffer);
 +    assert(FALSE);
 +    for (;;);
 +}
index 077f2bb,0000000..98af295
mode 100644,000000..100644
--- /dev/null
@@@ -1,66 -1,0 +1,79 @@@
 +/*
 + *  FreeLoader
 + *  Copyright (C) 1998-2003  Brian Palmer  <brianp@sginet.com>
 + *
 + *  This program is free software; you can redistribute it and/or modify
 + *  it under the terms of the GNU General Public License as published by
 + *  the Free Software Foundation; either version 2 of the License, or
 + *  (at your option) any later version.
 + *
 + *  This program 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 General Public License for more details.
 + *
 + *  You should have received a copy of the GNU General Public License along
 + *  with this program; if not, write to the Free Software Foundation, Inc.,
 + *  51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
 + */
 +
 +#include <freeldr.h>
 +#include <debug.h>
 +
 +VOID NTAPI HalpInitializePciStubs(VOID);
 +VOID NTAPI HalpInitBusHandler(VOID);
 +
 +VOID BootMain(LPSTR CmdLine)
 +{
 +      CmdLineParse(CmdLine);
 +
 +      MachInit(CmdLine);
 +
 +      FsInit();
 +
 +      DebugInit();
 +
 +      DPRINTM(DPRINT_WARNING, "BootMain() called.\n");
 +
 +      if (!UiInitialize(FALSE))
 +      {
 +              UiMessageBoxCritical("Unable to initialize UI.\n");
 +              return;
 +      }
 +
 +      if (!MmInitializeMemoryManager())
 +      {
 +              UiMessageBoxCritical("Unable to initialize memory manager");
 +              return;
 +      }
 +
 +#ifdef _M_IX86
 +      HalpInitializePciStubs();
 +      HalpInitBusHandler();
 +#endif
 +      RunLoader();
 +}
 +
 +#ifdef _MSC_VER
 +long _ftol2(double f)
 +{
 +    return _ftol(f);
 +}
 +long _ftol2_sse(double f)
 +{
 +    return _ftol(f);
 +}
 +#endif
++
++// We need to emulate these, because the original ones don't work in freeldr
++int __cdecl wctomb(char *mbchar, wchar_t wchar)
++{
++    *mbchar = wchar;
++    return 1;
++}
++
++int __cdecl mbtowc (wchar_t *wchar, const char *mbchar, size_t count)
++{
++    *wchar = *mbchar;
++    return 1;
++}
index 0000000,3cc3412..3cc3412
mode 000000,100644..100644
--- /dev/null
Simple merge
Simple merge
index 0000000,d98b04d..d98b04d
mode 000000,100644..100644
--- /dev/null
Simple merge
Simple merge
Simple merge
index d57e5bb,0000000..aab01f1
mode 100644,000000..100644
--- /dev/null
@@@ -1,59 -1,0 +1,60 @@@
-     ldr/actctx.c
 +
 +spec2def(ntdll.dll def/ntdll.spec)
 +
 +add_definitions(
 +    -D__NTDLL__
 +    -D_NTOSKRNL_
 +    -DCRTDLL)
 +
 +include_directories(
 +    BEFORE include
 +    ${REACTOS_SOURCE_DIR}/include/reactos/subsys)
 +
 +list(APPEND SOURCE
 +    csr/api.c
 +    csr/capture.c
 +    csr/connect.c
 +    dbg/dbgui.c
++      ldr/actctx.c
++      ldr/ldrinit.c
 +    ldr/startup.c
 +    ldr/utils.c
 +    rtl/libsupp.c
 +    rtl/version.c
 +    def/ntdll.rc
 +    ${CMAKE_CURRENT_BINARY_DIR}/ntdll.def)
 +    
 +if(ARCH MATCHES i386)
 +list(APPEND SOURCE dispatch/i386/dispatch.S)
 +elseif(ARCH MATCHES amd64)
 +list(APPEND SOURCE dispatch/amd64/stubs.c)
 +elseif(ARCH MATCHES arm)
 +list(APPEND SOURCE dispatch/arm/stubs_asm.s)
 +else()
 +list(APPEND SOURCE dispatch/dispatch.c)
 +endif(ARCH MATCHES i386)
 +
 +add_library(ntdll SHARED
 +    ${CMAKE_CURRENT_BINARY_DIR}/ntdll_ntdll.h.gch
 +    ${SOURCE})
 +
 +set_entrypoint(ntdll 0)
 +
 +if(MSVC)
 +target_link_libraries(ntdll rtl)
 +else()
 +target_link_libraries(ntdll -Wl,--whole-archive rtl -Wl,--no-whole-archive)
 +endif()
 +
 +target_link_libraries(ntdll
 +                      ntdllsys
 +                      libcntpr
 +                      ${PSEH_LIB})
 +
 +set_image_base(ntdll ${baseaddress_ntdll})
 +add_pch(ntdll ${CMAKE_CURRENT_SOURCE_DIR}/include/ntdll.h ${SOURCE})
 +add_dependencies(ntdll ntstatus asm)
 +
 +add_minicd_target(ntdll reactos/system32 ntdll.dll)
 +add_cab_target(ntdll 1)
 +add_importlib_target(def/ntdll.spec)
index 0000000,77baa0a..77baa0a
mode 000000,100644..100644
--- /dev/null
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
Simple merge
Simple merge
index 0000000,5d627aa..5d627aa
mode 000000,100644..100644
--- /dev/null
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
Simple merge
Simple merge
Simple merge
Simple merge
Simple merge
Simple merge
Simple merge
Simple merge
Simple merge
Simple merge
index b7818fb,c6aee0b..c6aee0b
Binary files differ
index c735f54,2ae5001..2ae5001
Binary files differ
index 7e19185,c10dc72..c10dc72
Binary files differ
index 7db2f3c,aedd4a8..aedd4a8
Binary files differ
index 22e4d1d,ce4ea4f..ce4ea4f
Binary files differ
index 6ba3d83,abee9b8..abee9b8
Binary files differ
Simple merge
Simple merge
Simple merge
index 3eb2c32,0000000..2091d88
mode 100644,000000..100644
--- /dev/null
@@@ -1,2749 -1,0 +1,2785 @@@
-     COLORREF  bk;
-     COLORREF  txt;
-     COLORREF  titlebk;
-     COLORREF  titletxt;
-     COLORREF  monthbk;
-     COLORREF  trailingtxt;
 +/*
 + * Month calendar control
 + *
 + * Copyright 1998, 1999 Eric Kohl (ekohl@abo.rhein-zeitung.de)
 + * Copyright 1999 Alex Priem (alexp@sci.kun.nl)
 + * Copyright 1999 Chris Morgan <cmorgan@wpi.edu> and
 + *              James Abbatiello <abbeyj@wpi.edu>
 + * Copyright 2000 Uwe Bonnes <bon@elektron.ikp.physik.tu-darmstadt.de>
 + * Copyright 2009, 2010 Nikolay Sivov
 + *
 + * 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
 + *
 + * NOTE
 + * 
 + * This code was audited for completeness against the documented features
 + * of Comctl32.dll version 6.0 on Oct. 20, 2004, by Dimitrie O. Paun.
 + * 
 + * 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:
 + *    -- MCM_[GS]ETUNICODEFORMAT
 + *    -- MONTHCAL_GetMonthRange
 + *    -- handle resources better (doesn't work now); 
 + *    -- take care of internationalization.
 + *    -- keyboard handling.
 + *    -- search for FIXME
 + */
 +
 +#include <math.h>
 +#include <stdarg.h>
 +#include <stdio.h>
 +#include <stdlib.h>
 +#include <string.h>
 +
 +#include "windef.h"
 +#include "winbase.h"
 +#include "wingdi.h"
 +#include "winuser.h"
 +#include "winnls.h"
 +#include "commctrl.h"
 +#include "comctl32.h"
 +#include "uxtheme.h"
 +#include "tmschema.h"
 +#include "wine/unicode.h"
 +#include "wine/debug.h"
 +
 +WINE_DEFAULT_DEBUG_CHANNEL(monthcal);
 +
 +#define MC_SEL_LBUTUP     1   /* Left button released */
 +#define MC_SEL_LBUTDOWN           2   /* Left button pressed in calendar */
 +#define MC_PREVPRESSED      4   /* Prev month button pressed */
 +#define MC_NEXTPRESSED      8   /* Next month button pressed */
 +#define MC_PREVNEXTMONTHDELAY   350   /* when continuously pressing `next/prev
 +                                         month', wait 350 ms before going
 +                                         to the next/prev month */
 +#define MC_TODAYUPDATEDELAY 120000 /* time between today check for update (2 min) */
 +
 +#define MC_PREVNEXTMONTHTIMER   1     /* Timer ID's */
 +#define MC_TODAYUPDATETIMER     2
 +
 +#define countof(arr) (sizeof(arr)/sizeof(arr[0]))
 +
 +/* convert from days to 100 nanoseconds unit - used as FILETIME unit */
 +#define DAYSTO100NSECS(days) (((ULONGLONG)(days))*24*60*60*10000000)
 +
 +/* single calendar data */
 +typedef struct _CALENDAR_INFO
 +{
 +    RECT title;      /* rect for the header above the calendar */
 +    RECT titlemonth; /* the 'month name' text in the header */
 +    RECT titleyear;  /* the 'year number' text in the header */
 +    RECT wdays;      /* week days at top */
 +    RECT days;       /* calendar area */
 +    RECT weeknums;   /* week numbers at left side */
 +
 +    SYSTEMTIME month;/* contains calendar main month/year */
 +} CALENDAR_INFO;
 +
 +typedef struct
 +{
 +    HWND      hwndSelf;
 +    DWORD     dwStyle; /* cached GWL_STYLE */
-     SYSTEMTIME        minSel;
++
++    COLORREF    colors[MCSC_TRAILINGTEXT+1];
++
 +    HFONT     hFont;
 +    HFONT     hBoldFont;
 +    int               textHeight;
 +    int               textWidth;
 +    int               height_increment;
 +    int               width_increment;
 +    INT               delta;  /* scroll rate; # of months that the */
 +                        /* control moves when user clicks a scroll button */
 +    int               visible;        /* # of months visible */
 +    int               firstDay;       /* Start month calendar with firstDay's day,
 +                                 stored in SYSTEMTIME format */
 +    BOOL      firstDaySet;    /* first week day differs from locale defined */
 +
 +    BOOL      isUnicode;      /* value set with MCM_SETUNICODE format */
 +
 +    int               monthRange;
 +    MONTHDAYSTATE *monthdayState;
 +    SYSTEMTIME        todaysDate;
 +    BOOL      todaySet;       /* Today was forced with MCM_SETTODAY */
 +    int               status;         /* See MC_SEL flags */
 +    SYSTEMTIME        firstSel;       /* first selected day */
 +    INT               maxSelCount;
-     SYSTEMTIME  curSel;         /* contains currently selected year, month and day */
++    SYSTEMTIME        minSel;         /* contains single selection when used without MCS_MULTISELECT */
 +    SYSTEMTIME        maxSel;
- #define MONTHCAL_GetInfoPtr(hwnd) ((MONTHCAL_INFO *)GetWindowLongPtrW(hwnd, 0))
 +    SYSTEMTIME  focusedSel;     /* date currently focused with mouse movement */
 +    DWORD     rangeValid;
 +    SYSTEMTIME        minDate;
 +    SYSTEMTIME        maxDate;
 +
 +    RECT titlebtnnext;        /* the `next month' button in the header */
 +    RECT titlebtnprev;  /* the `prev month' button in the header */
 +    RECT todayrect;   /* `today: xx/xx/xx' text rect */
 +    HWND hwndNotify;    /* Window to receive the notifications */
 +    HWND hWndYearEdit;  /* Window Handle of edit box to handle years */
 +    HWND hWndYearUpDown;/* Window Handle of updown box to handle years */
 +    WNDPROC EditWndProc;  /* original Edit window procedure */
 +
 +    CALENDAR_INFO *calendars;
 +    INT            cal_num;
 +} MONTHCAL_INFO, *LPMONTHCAL_INFO;
 +
 +static const WCHAR themeClass[] = { 'S','c','r','o','l','l','b','a','r',0 };
 +
 +/* empty SYSTEMTIME const */
 +static const SYSTEMTIME st_null;
 +/* valid date limits */
 +static const SYSTEMTIME max_allowed_date = { 9999, 12, 0, 31, 0, 0, 0, 0 };
 +static const SYSTEMTIME min_allowed_date = { 1752, 9, 0, 14, 0, 0, 0, 0 };
 +
-   if(++date->wMonth > 12)
-   {
-     date->wMonth = 1;
-     date->wYear++;
-   }
-   MONTHCAL_CalculateDayOfWeek(date, TRUE);
++/* Prev/Next buttons */
++enum nav_direction
++{
++    DIRECTION_BACKWARD,
++    DIRECTION_FORWARD
++};
 +
 +/* helper functions  */
 +
 +/* send a single MCN_SELCHANGE notification */
 +static inline void MONTHCAL_NotifySelectionChange(const MONTHCAL_INFO *infoPtr)
 +{
 +    NMSELCHANGE nmsc;
 +
 +    nmsc.nmhdr.hwndFrom = infoPtr->hwndSelf;
 +    nmsc.nmhdr.idFrom   = GetWindowLongPtrW(infoPtr->hwndSelf, GWLP_ID);
 +    nmsc.nmhdr.code     = MCN_SELCHANGE;
 +    nmsc.stSelStart     = infoPtr->minSel;
 +    nmsc.stSelEnd       = infoPtr->maxSel;
 +    SendMessageW(infoPtr->hwndNotify, WM_NOTIFY, nmsc.nmhdr.idFrom, (LPARAM)&nmsc);
 +}
 +
 +/* send a single MCN_SELECT notification */
 +static inline void MONTHCAL_NotifySelect(const MONTHCAL_INFO *infoPtr)
 +{
 +    NMSELCHANGE nmsc;
 +
 +    nmsc.nmhdr.hwndFrom = infoPtr->hwndSelf;
 +    nmsc.nmhdr.idFrom   = GetWindowLongPtrW(infoPtr->hwndSelf, GWLP_ID);
 +    nmsc.nmhdr.code     = MCN_SELECT;
 +    nmsc.stSelStart     = infoPtr->minSel;
 +    nmsc.stSelEnd       = infoPtr->maxSel;
 +
 +    SendMessageW(infoPtr->hwndNotify, WM_NOTIFY, nmsc.nmhdr.idFrom, (LPARAM)&nmsc);
 +}
 +
 +/* returns the number of days in any given month, checking for leap days */
 +/* january is 1, december is 12 */
 +int MONTHCAL_MonthLength(int month, int year)
 +{
 +  const int mdays[] = {31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};
 +  /* Wrap around, this eases handling. Getting length only we shouldn't care
 +     about year change here cause January and December have
 +     the same day quantity */
 +  if(month == 0)
 +    month = 12;
 +  else if(month == 13)
 +    month = 1;
 +
 +  /* special case for calendar transition year */
 +  if(month == min_allowed_date.wMonth && year == min_allowed_date.wYear) return 19;
 +
 +  /* if we have a leap year add 1 day to February */
 +  /* a leap year is a year either divisible by 400 */
 +  /* or divisible by 4 and not by 100 */
 +  if(month == 2) { /* February */
 +    return mdays[month - 1] + ((year%400 == 0) ? 1 : ((year%100 != 0) &&
 +     (year%4 == 0)) ? 1 : 0);
 +  }
 +  else {
 +    return mdays[month - 1];
 +  }
 +}
 +
 +/* compares timestamps using date part only */
 +static inline BOOL MONTHCAL_IsDateEqual(const SYSTEMTIME *first, const SYSTEMTIME *second)
 +{
 +  return (first->wYear == second->wYear) && (first->wMonth == second->wMonth) &&
 +         (first->wDay  == second->wDay);
 +}
 +
 +/* make sure that date fields are valid */
 +static BOOL MONTHCAL_ValidateDate(const SYSTEMTIME *time)
 +{
 +  if(time->wMonth < 1 || time->wMonth > 12 ) return FALSE;
 +  if(time->wDayOfWeek > 6) return FALSE;
 +  if(time->wDay > MONTHCAL_MonthLength(time->wMonth, time->wYear))
 +        return FALSE;
 +
 +  return TRUE;
 +}
 +
 +/* Copies timestamp part only.
 + *
 + * PARAMETERS
 + *
 + *  [I] from : source date
 + *  [O] to   : dest date
 + */
 +static void MONTHCAL_CopyTime(const SYSTEMTIME *from, SYSTEMTIME *to)
 +{
 +  to->wHour   = from->wHour;
 +  to->wMinute = from->wMinute;
 +  to->wSecond = from->wSecond;
 +}
 +
 +/* Copies date part only.
 + *
 + * PARAMETERS
 + *
 + *  [I] from : source date
 + *  [O] to   : dest date
 + */
 +static void MONTHCAL_CopyDate(const SYSTEMTIME *from, SYSTEMTIME *to)
 +{
 +  to->wYear  = from->wYear;
 +  to->wMonth = from->wMonth;
 +  to->wDay   = from->wDay;
 +  to->wDayOfWeek = from->wDayOfWeek;
 +}
 +
 +/* Compares two dates in SYSTEMTIME format
 + *
 + * PARAMETERS
 + *
 + *  [I] first  : pointer to valid first date data to compare
 + *  [I] second : pointer to valid second date data to compare
 + *
 + * RETURN VALUE
 + *
 + *  -1 : first <  second
 + *   0 : first == second
 + *   1 : first >  second
 + *
 + *  Note that no date validation performed, alreadt validated values expected.
 + */
 +static LONG MONTHCAL_CompareSystemTime(const SYSTEMTIME *first, const SYSTEMTIME *second)
 +{
 +  FILETIME ft_first, ft_second;
 +
 +  SystemTimeToFileTime(first, &ft_first);
 +  SystemTimeToFileTime(second, &ft_second);
 +
 +  return CompareFileTime(&ft_first, &ft_second);
 +}
 +
 +static LONG MONTHCAL_CompareMonths(const SYSTEMTIME *first, const SYSTEMTIME *second)
 +{
 +  SYSTEMTIME st_first, st_second;
 +
 +  st_first = st_second = st_null;
 +  MONTHCAL_CopyDate(first, &st_first);
 +  MONTHCAL_CopyDate(second, &st_second);
 +  st_first.wDay = st_second.wDay = 1;
 +
 +  return MONTHCAL_CompareSystemTime(&st_first, &st_second);
 +}
 +
 +static LONG MONTHCAL_CompareDate(const SYSTEMTIME *first, const SYSTEMTIME *second)
 +{
 +  SYSTEMTIME st_first, st_second;
 +
 +  st_first = st_second = st_null;
 +  MONTHCAL_CopyDate(first, &st_first);
 +  MONTHCAL_CopyDate(second, &st_second);
 +
 +  return MONTHCAL_CompareSystemTime(&st_first, &st_second);
 +}
 +
 +/* Checks largest possible date range and configured one
 + *
 + * PARAMETERS
 + *
 + *  [I] infoPtr : valid pointer to control data
 + *  [I] date    : pointer to valid date data to check
 + *  [I] fix     : make date fit valid range
 + *
 + * RETURN VALUE
 + *
 + *  TRUE  - date whithin largest and configured range
 + *  FALSE - date is outside largest or configured range
 + */
 +static BOOL MONTHCAL_IsDateInValidRange(const MONTHCAL_INFO *infoPtr,
 +                                        SYSTEMTIME *date, BOOL fix)
 +{
 +  const SYSTEMTIME *fix_st = NULL;
 +
 +  if(MONTHCAL_CompareSystemTime(date, &max_allowed_date) == 1) {
 +     fix_st = &max_allowed_date;
 +  }
 +  else if(MONTHCAL_CompareSystemTime(date, &min_allowed_date) == -1) {
 +     fix_st = &min_allowed_date;
 +  }
 +  else if(infoPtr->rangeValid & GDTR_MAX) {
 +     if((MONTHCAL_CompareSystemTime(date, &infoPtr->maxDate) == 1)) {
 +       fix_st = &infoPtr->maxDate;
 +     }
 +  }
 +  else if(infoPtr->rangeValid & GDTR_MIN) {
 +     if((MONTHCAL_CompareSystemTime(date, &infoPtr->minDate) == -1)) {
 +       fix_st = &infoPtr->minDate;
 +     }
 +  }
 +
 +  if (fix && fix_st) {
 +    date->wYear  = fix_st->wYear;
 +    date->wMonth = fix_st->wMonth;
 +  }
 +
 +  return fix_st ? FALSE : TRUE;
 +}
 +
 +/* Checks passed range width with configured maximum selection count
 + *
 + * PARAMETERS
 + *
 + *  [I] infoPtr : valid pointer to control data
 + *  [I] range0  : pointer to valid date data (requested bound)
 + *  [I] range1  : pointer to valid date data (primary bound)
 + *  [O] adjust  : returns adjusted range bound to fit maximum range (optional)
 + *
 + *  Adjust value computed basing on primary bound and current maximum selection
 + *  count. For simple range check (without adjusted value required) (range0, range1)
 + *  relation means nothing.
 + *
 + * RETURN VALUE
 + *
 + *  TRUE  - range is shorter or equal to maximum
 + *  FALSE - range is larger than maximum
 + */
 +static BOOL MONTHCAL_IsSelRangeValid(const MONTHCAL_INFO *infoPtr,
 +                                     const SYSTEMTIME *range0,
 +                                     const SYSTEMTIME *range1,
 +                                     SYSTEMTIME *adjust)
 +{
 +  ULARGE_INTEGER ul_range0, ul_range1, ul_diff;
 +  FILETIME ft_range0, ft_range1;
 +  LONG cmp;
 +
 +  SystemTimeToFileTime(range0, &ft_range0);
 +  SystemTimeToFileTime(range1, &ft_range1);
 +
 +  ul_range0.u.LowPart  = ft_range0.dwLowDateTime;
 +  ul_range0.u.HighPart = ft_range0.dwHighDateTime;
 +  ul_range1.u.LowPart  = ft_range1.dwLowDateTime;
 +  ul_range1.u.HighPart = ft_range1.dwHighDateTime;
 +
 +  cmp = CompareFileTime(&ft_range0, &ft_range1);
 +
 +  if(cmp == 1)
 +     ul_diff.QuadPart = ul_range0.QuadPart - ul_range1.QuadPart;
 +  else
 +     ul_diff.QuadPart = -ul_range0.QuadPart + ul_range1.QuadPart;
 +
 +  if(ul_diff.QuadPart >= DAYSTO100NSECS(infoPtr->maxSelCount)) {
 +
 +     if(adjust) {
 +       if(cmp == 1)
 +          ul_range0.QuadPart = ul_range1.QuadPart + DAYSTO100NSECS(infoPtr->maxSelCount - 1);
 +       else
 +          ul_range0.QuadPart = ul_range1.QuadPart - DAYSTO100NSECS(infoPtr->maxSelCount - 1);
 +
 +       ft_range0.dwLowDateTime  = ul_range0.u.LowPart;
 +       ft_range0.dwHighDateTime = ul_range0.u.HighPart;
 +       FileTimeToSystemTime(&ft_range0, adjust);
 +     }
 +
 +     return FALSE;
 +  }
 +  else return TRUE;
 +}
 +
 +/* Used in MCM_SETRANGE/MCM_SETSELRANGE to determine resulting time part.
 +   Milliseconds are intentionally not validated. */
 +static BOOL MONTHCAL_ValidateTime(const SYSTEMTIME *time)
 +{
 +  if((time->wHour > 24) || (time->wMinute > 59) || (time->wSecond > 59))
 +    return FALSE;
 +  else
 +    return TRUE;
 +}
 +
 +/* Note:Depending on DST, this may be offset by a day.
 +   Need to find out if we're on a DST place & adjust the clock accordingly.
 +   Above function assumes we have a valid data.
 +   Valid for year>1752;  1 <= d <= 31, 1 <= m <= 12.
 +   0 = Sunday.
 +*/
 +
 +/* Returns the day in the week
 + *
 + * PARAMETERS
 + *  [i] date    : input date
 + *  [I] inplace : set calculated value back to date structure
 + *
 + * RETURN VALUE
 + *   day of week in SYSTEMTIME format: (0 == sunday,..., 6 == saturday)
 + */
 +int MONTHCAL_CalculateDayOfWeek(SYSTEMTIME *date, BOOL inplace)
 +{
 +  SYSTEMTIME st = st_null;
 +  FILETIME ft;
 +
 +  MONTHCAL_CopyDate(date, &st);
 +
 +  SystemTimeToFileTime(&st, &ft);
 +  FileTimeToSystemTime(&ft, &st);
 +
 +  if (inplace) date->wDayOfWeek = st.wDayOfWeek;
 +
 +  return st.wDayOfWeek;
 +}
 +
++/* add/substract 'months' from date */
++static inline void MONTHCAL_GetMonth(SYSTEMTIME *date, INT months)
++{
++  INT length, m = date->wMonth + months;
++
++  date->wYear += m > 0 ? (m - 1) / 12 : m / 12 - 1;
++  date->wMonth = m > 0 ? (m - 1) % 12 + 1 : 12 + m % 12;
++  /* fix moving from last day in a month */
++  length = MONTHCAL_MonthLength(date->wMonth, date->wYear);
++  if(date->wDay > length) date->wDay = length;
++  MONTHCAL_CalculateDayOfWeek(date, TRUE);
++}
++
 +/* properly updates date to point on next month */
 +static inline void MONTHCAL_GetNextMonth(SYSTEMTIME *date)
 +{
-   if(--date->wMonth < 1)
-   {
-     date->wMonth = 12;
-     date->wYear--;
-   }
-   MONTHCAL_CalculateDayOfWeek(date, TRUE);
++  return MONTHCAL_GetMonth(date, 1);
 +}
 +
 +/* properly updates date to point on prev month */
 +static inline void MONTHCAL_GetPrevMonth(SYSTEMTIME *date)
 +{
-   SYSTEMTIME st = infoPtr->curSel;
++  return MONTHCAL_GetMonth(date, -1);
 +}
 +
 +/* Returns full date for a first currently visible day */
 +static void MONTHCAL_GetMinDate(const MONTHCAL_INFO *infoPtr, SYSTEMTIME *date)
 +{
 +  /* zero indexed calendar has the earliest date */
 +  SYSTEMTIME st_first = infoPtr->calendars[0].month;
 +  INT firstDay;
 +
 +  st_first.wDay = 1;
 +  firstDay = MONTHCAL_CalculateDayOfWeek(&st_first, FALSE);
 +
 +  *date = infoPtr->calendars[0].month;
 +  MONTHCAL_GetPrevMonth(date);
 +
 +  date->wDay = MONTHCAL_MonthLength(date->wMonth, date->wYear) +
 +               (infoPtr->firstDay - firstDay) % 7 + 1;
 +
 +  if(date->wDay > MONTHCAL_MonthLength(date->wMonth, date->wYear))
 +    date->wDay -= 7;
 +
 +  /* fix day of week */
 +  MONTHCAL_CalculateDayOfWeek(date, TRUE);
 +}
 +
 +/* Returns full date for a last currently visible day */
 +static void MONTHCAL_GetMaxDate(const MONTHCAL_INFO *infoPtr, SYSTEMTIME *date)
 +{
 +  /* the latest date is in latest calendar */
 +  SYSTEMTIME st, lt_month = infoPtr->calendars[infoPtr->cal_num-1].month;
 +
 +  *date = lt_month;
 +  MONTHCAL_GetNextMonth(date);
 +
 +  MONTHCAL_GetMinDate(infoPtr, &st);
 +  /* Use month length to get max day. 42 means max day count in calendar area */
 +  date->wDay = 42 - (MONTHCAL_MonthLength(st.wMonth, st.wYear) - st.wDay + 1) -
 +                     MONTHCAL_MonthLength(lt_month.wMonth, lt_month.wYear);
 +
 +  /* fix day of week */
 +  MONTHCAL_CalculateDayOfWeek(date, TRUE);
 +}
 +
 +/* From a given point, calculate the row (weekpos), column(daypos)
 +   and day in the calendar. day== 0 mean the last day of tha last month
 +*/
 +static int MONTHCAL_CalcDayFromPos(const MONTHCAL_INFO *infoPtr, int x, int y,
 +                                 int *daypos, int *weekpos)
 +{
 +  int retval, firstDay;
 +  RECT rcClient;
-                                const SYSTEMTIME *date, int *x, int *y)
++  SYSTEMTIME st = infoPtr->minSel;
 +
 +  GetClientRect(infoPtr->hwndSelf, &rcClient);
 +
 +  /* if the point is outside the x bounds of the window put
 +  it at the boundary */
 +  if (x > rcClient.right)
 +    x = rcClient.right;
 +
 +  *daypos  = (x - infoPtr->calendars[0].days.left ) / infoPtr->width_increment;
 +  *weekpos = (y - infoPtr->calendars[0].days.top ) / infoPtr->height_increment;
 +
 +  st.wDay = 1;
 +  firstDay = (MONTHCAL_CalculateDayOfWeek(&st, FALSE) + 6 - infoPtr->firstDay) % 7;
 +  retval = *daypos + (7 * *weekpos) - firstDay;
 +  return retval;
 +}
 +
 +/* Sets the RECT struct r to the rectangle around the date
 + *
 + * PARAMETERS
 + *
 + *  [I] infoPtr : pointer to control data
 + *  [I] date : date value
 + *  [O] x : day column (zero based)
 + *  [O] y : week column (zero based)
 + */
 +static void MONTHCAL_CalcDayXY(const MONTHCAL_INFO *infoPtr,
-   SYSTEMTIME st = infoPtr->curSel;
++                               const SYSTEMTIME *date, INT *x, INT *y)
 +{
-   cmp = MONTHCAL_CompareMonths(date, &infoPtr->curSel);
++  SYSTEMTIME st = infoPtr->minSel;
 +  LONG cmp;
 +  int first;
 +
 +  st.wDay = 1;
 +  first = (MONTHCAL_CalculateDayOfWeek(&st, FALSE) + 6 - infoPtr->firstDay) % 7;
 +
-     *x = (first - MONTHCAL_MonthLength(date->wMonth, infoPtr->curSel.wYear) + date->wDay) % 7;
++  cmp = MONTHCAL_CompareMonths(date, &infoPtr->minSel);
 +
 +  /* previous month */
 +  if(cmp == -1) {
-     first += MONTHCAL_MonthLength(infoPtr->curSel.wMonth, infoPtr->curSel.wYear);
++    *x = (first - MONTHCAL_MonthLength(date->wMonth, infoPtr->minSel.wYear) + date->wDay) % 7;
 +    *y = 0;
 +    return;
 +  }
 +
 +  /* next month calculation is same as for current,
 +     just add current month length */
 +  if(cmp == 1) {
-     oldCol = SetTextColor(hdc, infoPtr->monthbk);
-     oldBk = SetBkColor(hdc, infoPtr->trailingtxt);
++    first += MONTHCAL_MonthLength(infoPtr->minSel.wMonth, infoPtr->minSel.wYear);
 +  }
 +
 +  *x = (date->wDay + first) % 7;
 +  *y = (date->wDay + first - *x) / 7;
 +}
 +
 +
 +/* x: column(day), y: row(week) */
 +static inline void MONTHCAL_CalcDayRect(const MONTHCAL_INFO *infoPtr, RECT *r, int x, int y)
 +{
 +  r->left = infoPtr->calendars[0].days.left + x * infoPtr->width_increment;
 +  r->right = r->left + infoPtr->width_increment;
 +  r->top  = infoPtr->calendars[0].days.top  + y * infoPtr->height_increment;
 +  r->bottom = r->top + infoPtr->textHeight;
 +}
 +
 +
 +/* Sets the RECT struct r to the rectangle around the date */
 +static inline void MONTHCAL_CalcPosFromDay(const MONTHCAL_INFO *infoPtr,
 +                                           const SYSTEMTIME *date, RECT *r)
 +{
 +  int x, y;
 +
 +  MONTHCAL_CalcDayXY(infoPtr, date, &x, &y);
 +  MONTHCAL_CalcDayRect(infoPtr, r, x, y);
 +}
 +
 +/* Focused day helper:
 +
 +   - set focused date to given value;
 +   - reset to zero value if NULL passed;
 +   - invalidate previous and new day rectangle only if needed.
 +
 +   Returns TRUE if focused day changed, FALSE otherwise.
 +*/
 +static BOOL MONTHCAL_SetDayFocus(MONTHCAL_INFO *infoPtr, const SYSTEMTIME *st)
 +{
 +  RECT r;
 +
 +  if(st)
 +  {
 +    /* there's nothing to do if it's the same date,
 +       mouse move within same date rectangle case */
 +    if(MONTHCAL_IsDateEqual(&infoPtr->focusedSel, st)) return FALSE;
 +
 +    /* invalidate old focused day */
 +    MONTHCAL_CalcPosFromDay(infoPtr, &infoPtr->focusedSel, &r);
 +    InvalidateRect(infoPtr->hwndSelf, &r, FALSE);
 +
 +    infoPtr->focusedSel = *st;
 +  }
 +
 +  MONTHCAL_CalcPosFromDay(infoPtr, &infoPtr->focusedSel, &r);
 +
 +  if(!st && MONTHCAL_ValidateDate(&infoPtr->focusedSel))
 +    infoPtr->focusedSel = st_null;
 +
 +  /* on set invalidates new day, on reset clears previous focused day */
 +  InvalidateRect(infoPtr->hwndSelf, &r, FALSE);
 +
 +  return TRUE;
 +}
 +
 +/* Draw today day mark rectangle
 + *
 + * [I] hdc : context to draw in
 + * [I] day : day to mark with rectangle
 + *
 + */
 +static void MONTHCAL_CircleDay(const MONTHCAL_INFO *infoPtr, HDC hdc,
 +                               const SYSTEMTIME *date)
 +{
 +  HPEN hRedPen = CreatePen(PS_SOLID, 1, RGB(255, 0, 0));
 +  HPEN hOldPen2 = SelectObject(hdc, hRedPen);
 +  HBRUSH hOldBrush;
 +  RECT day_rect;
 +
 +  MONTHCAL_CalcPosFromDay(infoPtr, date, &day_rect);
 +
 +  hOldBrush = SelectObject(hdc, GetStockObject(NULL_BRUSH));
 +  Rectangle(hdc, day_rect.left, day_rect.top, day_rect.right, day_rect.bottom);
 +
 +  SelectObject(hdc, hOldBrush);
 +  DeleteObject(hRedPen);
 +  SelectObject(hdc, hOldPen2);
 +}
 +
 +static void MONTHCAL_DrawDay(const MONTHCAL_INFO *infoPtr, HDC hdc, const SYSTEMTIME *st,
 +                             int bold, const PAINTSTRUCT *ps)
 +{
 +  static const WCHAR fmtW[] = { '%','d',0 };
 +  WCHAR buf[10];
 +  RECT r, r_temp;
 +  static BOOL bold_selected;
 +  BOOL selected_day = FALSE;
 +  HBRUSH hbr;
 +  COLORREF oldCol = 0;
 +  COLORREF oldBk  = 0;
 +
 +/* No need to check styles: when selection is not valid, it is set to zero.
 + * 1<day<31, so everything is OK.
 + */
 +
 +  MONTHCAL_CalcPosFromDay(infoPtr, st, &r);
 +  if(!IntersectRect(&r_temp, &(ps->rcPaint), &r)) return;
 +
 +  if ((MONTHCAL_CompareDate(st, &infoPtr->minSel) >= 0) &&
 +      (MONTHCAL_CompareDate(st, &infoPtr->maxSel) <= 0)) {
 +
 +    TRACE("%d %d %d\n", st->wDay, infoPtr->minSel.wDay, infoPtr->maxSel.wDay);
 +    TRACE("%s\n", wine_dbgstr_rect(&r));
- static void MONTHCAL_PaintButton(MONTHCAL_INFO *infoPtr, HDC hdc, BOOL btnNext)
++    oldCol = SetTextColor(hdc, infoPtr->colors[MCSC_MONTHBK]);
++    oldBk = SetBkColor(hdc, infoPtr->colors[MCSC_TRAILINGTEXT]);
 +    hbr = GetSysColorBrush(COLOR_HIGHLIGHT);
 +    FillRect(hdc, &r, hbr);
 +
 +    selected_day = TRUE;
 +  }
 +
 +  if(bold && !bold_selected) {
 +    SelectObject(hdc, infoPtr->hBoldFont);
 +    bold_selected = TRUE;
 +  }
 +  if(!bold && bold_selected) {
 +    SelectObject(hdc, infoPtr->hFont);
 +    bold_selected = FALSE;
 +  }
 +
 +  SetBkMode(hdc,TRANSPARENT);
 +  wsprintfW(buf, fmtW, st->wDay);
 +  DrawTextW(hdc, buf, -1, &r, DT_CENTER | DT_VCENTER | DT_SINGLELINE );
 +
 +  if(selected_day) {
 +    SetTextColor(hdc, oldCol);
 +    SetBkColor(hdc, oldBk);
 +  }
 +}
 +
 +
-     RECT *r = btnNext ? &infoPtr->titlebtnnext : &infoPtr->titlebtnprev;
-     BOOL pressed = btnNext ? (infoPtr->status & MC_NEXTPRESSED) :
-                              (infoPtr->status & MC_PREVPRESSED);
++static void MONTHCAL_PaintButton(MONTHCAL_INFO *infoPtr, HDC hdc, enum nav_direction button)
 +{
 +    HTHEME theme = GetWindowTheme (infoPtr->hwndSelf);
-         int stateNum = btnNext ? 3 : 0;
++    RECT *r = button == DIRECTION_FORWARD ? &infoPtr->titlebtnnext : &infoPtr->titlebtnprev;
++    BOOL pressed = button == DIRECTION_FORWARD ? infoPtr->status & MC_NEXTPRESSED :
++                                                 infoPtr->status & MC_PREVPRESSED;
 +    if (theme)
 +    {
 +        static const int states[] = {
 +            /* Prev button */
 +            ABS_LEFTNORMAL,  ABS_LEFTPRESSED,  ABS_LEFTDISABLED,
 +            /* Next button */
 +            ABS_RIGHTNORMAL, ABS_RIGHTPRESSED, ABS_RIGHTDISABLED
 +        };
-         int style = btnNext ? DFCS_SCROLLRIGHT : DFCS_SCROLLLEFT;
++        int stateNum = button == DIRECTION_FORWARD ? 3 : 0;
 +        if (pressed)
 +            stateNum += 1;
 +        else
 +        {
 +            if (infoPtr->dwStyle & WS_DISABLED) stateNum += 2;
 +        }
 +        DrawThemeBackground (theme, hdc, SBP_ARROWBTN, states[stateNum], r, NULL);
 +    }
 +    else
 +    {
-   hbr = CreateSolidBrush(infoPtr->titlebk);
++        int style = button == DIRECTION_FORWARD ? DFCS_SCROLLRIGHT : DFCS_SCROLLLEFT;
 +        if (pressed)
 +            style |= DFCS_PUSHED;
 +        else
 +        {
 +            if (infoPtr->dwStyle & WS_DISABLED) style |= DFCS_INACTIVE;
 +        }
 +        
 +        DrawFrameControl(hdc, r, DFC_SCROLL, style);
 +    }
 +}
 +/* paint a title with buttons and month/year string */
 +static void MONTHCAL_PaintTitle(MONTHCAL_INFO *infoPtr, HDC hdc, const PAINTSTRUCT *ps, INT calIdx)
 +{
 +  static const WCHAR fmt_monthW[] = { '%','s',' ','%','l','d',0 };
 +  RECT *title = &infoPtr->calendars[calIdx].title;
++  const SYSTEMTIME *st = &infoPtr->calendars[calIdx].month;
 +  WCHAR buf_month[80], buf_fmt[80];
 +  HBRUSH hbr;
 +  SIZE sz;
 +
 +  /* fill header box */
-   SetBkColor(hdc, infoPtr->titlebk);
-   SetTextColor(hdc, infoPtr->titletxt);
++  hbr = CreateSolidBrush(infoPtr->colors[MCSC_TITLEBK]);
 +  FillRect(hdc, title, hbr);
 +  DeleteObject(hbr);
 +
 +  /* month/year string */
-   GetLocaleInfoW(LOCALE_USER_DEFAULT, LOCALE_SMONTHNAME1+infoPtr->curSel.wMonth-1,
++  SetBkColor(hdc, infoPtr->colors[MCSC_TITLEBK]);
++  SetTextColor(hdc, infoPtr->colors[MCSC_TITLETEXT]);
 +  SelectObject(hdc, infoPtr->hBoldFont);
 +
-   wsprintfW(buf_fmt, fmt_monthW, buf_month, infoPtr->curSel.wYear);
++  GetLocaleInfoW(LOCALE_USER_DEFAULT, LOCALE_SMONTHNAME1 + st->wMonth - 1,
 +                 buf_month, countof(buf_month));
 +
-   SYSTEMTIME st = infoPtr->curSel;
-   RECT r;
-   WCHAR buf[80];
++  wsprintfW(buf_fmt, fmt_monthW, buf_month, st->wYear);
 +  DrawTextW(hdc, buf_fmt, strlenW(buf_fmt), title,
 +                      DT_CENTER | DT_VCENTER | DT_SINGLELINE);
 +
 +  /* update title rectangles with current month - used while testing hits */
 +  GetTextExtentPoint32W(hdc, buf_fmt, strlenW(buf_fmt), &sz);
 +  infoPtr->calendars[calIdx].titlemonth.left = title->right / 2 + title->left / 2 - sz.cx / 2;
 +  infoPtr->calendars[calIdx].titleyear.right = title->right / 2 + title->left / 2 + sz.cx / 2;
 +
 +  GetTextExtentPoint32W(hdc, buf_month, strlenW(buf_month), &sz);
 +  infoPtr->calendars[calIdx].titlemonth.right = infoPtr->calendars[calIdx].titlemonth.left + sz.cx;
 +  infoPtr->calendars[calIdx].titleyear.left   = infoPtr->calendars[calIdx].titlemonth.right;
 +}
 +
 +static void MONTHCAL_PaintWeeknumbers(const MONTHCAL_INFO *infoPtr, HDC hdc, const PAINTSTRUCT *ps, INT calIdx)
 +{
++  const SYSTEMTIME *date = &infoPtr->calendars[calIdx].month;
 +  static const WCHAR fmt_weekW[] = { '%','d',0 };
 +  INT mindays, weeknum, weeknum1, startofprescal;
-   st = infoPtr->curSel;
 +  INT i, prev_month;
++  SYSTEMTIME st;
++  WCHAR buf[80];
++  HBRUSH hbr;
++  RECT r;
 +
 +  if (!(infoPtr->dwStyle & MCS_WEEKNUMBERS)) return;
 +
 +  MONTHCAL_GetMinDate(infoPtr, &st);
 +  startofprescal = st.wDay;
-   prev_month = infoPtr->curSel.wMonth - 1;
++  st = *date;
 +
-   if (infoPtr->curSel.wMonth == 1)
++  prev_month = date->wMonth - 1;
 +  if(prev_month == 0) prev_month = 12;
 +
 +  /*
 +     Rules what week to call the first week of a new year:
 +     LOCALE_IFIRSTWEEKOFYEAR == 0 (e.g US?):
 +     The week containing Jan 1 is the first week of year
 +     LOCALE_IFIRSTWEEKOFYEAR == 2 (e.g. Germany):
 +     First week of year must contain 4 days of the new year
 +     LOCALE_IFIRSTWEEKOFYEAR == 1  (what contries?)
 +     The first week of the year must contain only days of the new year
 +  */
 +  GetLocaleInfoW(LOCALE_USER_DEFAULT, LOCALE_IFIRSTWEEKOFYEAR, buf, countof(buf));
 +  weeknum = atoiW(buf);
 +  switch (weeknum)
 +  {
 +    case 1: mindays = 6;
 +      break;
 +    case 2: mindays = 3;
 +      break;
 +    case 0: mindays = 0;
 +        break;
 +    default:
 +        WARN("Unknown LOCALE_IFIRSTWEEKOFYEAR value %d, defaulting to 0\n", weeknum);
 +      mindays = 0;
 +  }
 +
-          weeknum += MONTHCAL_MonthLength(i+1, infoPtr->curSel.wYear - 1);
++  if (date->wMonth == 1)
 +  {
 +    /* calculate all those exceptions for january */
 +    st.wDay = st.wMonth = 1;
 +    weeknum1 = MONTHCAL_CalculateDayOfWeek(&st, FALSE);
 +    if ((infoPtr->firstDay - weeknum1) % 7 > mindays)
 +      weeknum = 1;
 +    else
 +    {
 +      weeknum = 0;
 +      for(i = 0; i < 11; i++)
-       weeknum += MONTHCAL_MonthLength(i+1, infoPtr->curSel.wYear);
++         weeknum += MONTHCAL_MonthLength(i+1, date->wYear - 1);
 +
 +      weeknum  += startofprescal + 7;
 +      weeknum  /= 7;
 +      st.wYear -= 1;
 +      weeknum1  = MONTHCAL_CalculateDayOfWeek(&st, FALSE);
 +      if ((infoPtr->firstDay - weeknum1) % 7 > mindays) weeknum++;
 +    }
 +  }
 +  else
 +  {
 +    weeknum = 0;
 +    for(i = 0; i < prev_month - 1; i++)
-   if((infoPtr->curSel.wMonth == infoPtr->todaysDate.wMonth) &&
-      (infoPtr->curSel.wYear  == infoPtr->todaysDate.wYear) &&
++      weeknum += MONTHCAL_MonthLength(i+1, date->wYear);
 +
 +    weeknum += startofprescal + 7;
 +    weeknum /= 7;
 +    st.wDay = st.wMonth = 1;
 +    weeknum1 = MONTHCAL_CalculateDayOfWeek(&st, FALSE);
 +    if ((infoPtr->firstDay - weeknum1) % 7 > mindays) weeknum++;
 +  }
 +
 +  r = infoPtr->calendars[calIdx].weeknums;
++
++  /* erase whole week numbers area */
++  hbr = CreateSolidBrush(infoPtr->colors[MCSC_MONTHBK]);
++  FillRect(hdc, &r, hbr);
++  DeleteObject(hbr);
++
++  /* reduce rectangle to one week number */
 +  r.bottom = r.top + infoPtr->height_increment;
 +
 +  for(i = 0; i < 6; i++) {
 +    if((i == 0) && (weeknum > 50))
 +    {
 +        wsprintfW(buf, fmt_weekW, weeknum);
 +        weeknum = 0;
 +    }
 +    else if((i == 5) && (weeknum > 47))
 +    {
 +      wsprintfW(buf, fmt_weekW, 1);
 +    }
 +    else
 +      wsprintfW(buf, fmt_weekW, weeknum + i);
 +
 +    DrawTextW(hdc, buf, -1, &r, DT_CENTER | DT_VCENTER | DT_SINGLELINE);
 +    OffsetRect(&r, 0, infoPtr->height_increment);
 +  }
 +
 +  /* line separator for week numbers column */
 +  MoveToEx(hdc, infoPtr->calendars[calIdx].weeknums.right, infoPtr->calendars[calIdx].weeknums.top + 3 , NULL);
 +  LineTo(hdc,   infoPtr->calendars[calIdx].weeknums.right, infoPtr->calendars[calIdx].weeknums.bottom);
 +}
 +
 +/* bottom today date */
 +static void MONTHCAL_PaintTodayTitle(const MONTHCAL_INFO *infoPtr, HDC hdc, const PAINTSTRUCT *ps)
 +{
 +  if(!(infoPtr->dwStyle & MCS_NOTODAY))  {
 +    static const WCHAR todayW[] = { 'T','o','d','a','y',':',0 };
 +    static const WCHAR fmt_todayW[] = { '%','s',' ','%','s',0 };
 +    WCHAR buf_todayW[30], buf_dateW[20], buf[80];
 +    RECT rtoday;
 +
 +    if(!(infoPtr->dwStyle & MCS_NOTODAYCIRCLE)) {
 +      SYSTEMTIME fake_st;
 +
 +      MONTHCAL_GetMaxDate(infoPtr, &fake_st);
 +      /* this is always safe cause next month will never fully fit calendar */
 +      fake_st.wDay += 1;
 +      MONTHCAL_CircleDay(infoPtr, hdc, &fake_st);
 +    }
 +    if (!LoadStringW(COMCTL32_hModule, IDM_TODAY, buf_todayW, countof(buf_todayW)))
 +    {
 +      WARN("Can't load resource\n");
 +      strcpyW(buf_todayW, todayW);
 +    }
 +    MONTHCAL_CalcDayRect(infoPtr, &rtoday, 1, 6);
 +    GetDateFormatW(LOCALE_USER_DEFAULT, DATE_SHORTDATE, &infoPtr->todaysDate, NULL,
 +                                                        buf_dateW, countof(buf_dateW));
 +    SelectObject(hdc, infoPtr->hBoldFont);
 +
 +    wsprintfW(buf, fmt_todayW, buf_todayW, buf_dateW);
 +    DrawTextW(hdc, buf, -1, &rtoday, DT_CALCRECT | DT_LEFT | DT_VCENTER | DT_SINGLELINE);
 +    DrawTextW(hdc, buf, -1, &rtoday, DT_LEFT | DT_VCENTER | DT_SINGLELINE);
 +
 +    SelectObject(hdc, infoPtr->hFont);
 +  }
 +}
 +
 +/* today mark + focus */
 +static void MONTHCAL_PaintFocusAndCircle(const MONTHCAL_INFO *infoPtr, HDC hdc, const PAINTSTRUCT *ps)
 +{
-   INT prev_month, i, j;
++  if((infoPtr->minSel.wMonth == infoPtr->todaysDate.wMonth) &&
++     (infoPtr->minSel.wYear  == infoPtr->todaysDate.wYear) &&
 +    !(infoPtr->dwStyle & MCS_NOTODAYCIRCLE))
 +  {
 +    MONTHCAL_CircleDay(infoPtr, hdc, &infoPtr->todaysDate);
 +  }
 +
 +  if(!MONTHCAL_IsDateEqual(&infoPtr->focusedSel, &st_null))
 +  {
 +    RECT r;
 +    MONTHCAL_CalcPosFromDay(infoPtr, &infoPtr->focusedSel, &r);
 +    DrawFocusRect(hdc, &r);
 +  }
 +}
 +
 +/* paint a calendar area */
 +static void MONTHCAL_PaintCalendar(const MONTHCAL_INFO *infoPtr, HDC hdc, const PAINTSTRUCT *ps, INT calIdx)
 +{
-   RECT r, fill_bk_rect;
++  const SYSTEMTIME *date = &infoPtr->calendars[calIdx].month;
++  INT prev_month, i, j, length;
++  RECT r, fill_bk_rect;
++  SYSTEMTIME st;
 +  WCHAR buf[80];
 +  HBRUSH hbr;
-   SYSTEMTIME st;
 +  int mask;
-   hbr = CreateSolidBrush(infoPtr->monthbk);
 +
 +  /* fill whole days area - from week days area to today note rectangle */
 +  fill_bk_rect = infoPtr->calendars[calIdx].wdays;
 +  fill_bk_rect.bottom = infoPtr->calendars[calIdx].days.bottom +
 +                          (infoPtr->todayrect.bottom - infoPtr->todayrect.top);
 +
-   prev_month = infoPtr->curSel.wMonth - 1;
++  hbr = CreateSolidBrush(infoPtr->colors[MCSC_MONTHBK]);
 +  FillRect(hdc, &fill_bk_rect, hbr);
 +  DeleteObject(hbr);
 +
 +  /* draw line under day abbreviations */
 +  MoveToEx(hdc, infoPtr->calendars[calIdx].days.left + 3,
 +                infoPtr->calendars[calIdx].title.bottom + infoPtr->textHeight + 1, NULL);
 +  LineTo(hdc, infoPtr->calendars[calIdx].days.right - 3,
 +              infoPtr->calendars[calIdx].title.bottom + infoPtr->textHeight + 1);
 +
-   SetBkColor(hdc, infoPtr->monthbk);
-   SetTextColor(hdc, infoPtr->trailingtxt);
++  prev_month = date->wMonth - 1;
 +  if (prev_month == 0) prev_month = 12;
 +
 +  infoPtr->calendars[calIdx].wdays.left = infoPtr->calendars[calIdx].days.left =
 +      infoPtr->calendars[calIdx].weeknums.right;
 +
 +  /* 1. draw day abbreviations */
 +  SelectObject(hdc, infoPtr->hFont);
-     SetTextColor(hdc, infoPtr->trailingtxt);
++  SetBkColor(hdc, infoPtr->colors[MCSC_MONTHBK]);
++  SetTextColor(hdc, infoPtr->colors[MCSC_TRAILINGTEXT]);
 +  /* rectangle to draw a single day abbreviation within */
 +  r = infoPtr->calendars[calIdx].wdays;
 +  r.right = r.left + infoPtr->width_increment;
 +
 +  i = infoPtr->firstDay;
 +  for(j = 0; j < 7; j++) {
 +    GetLocaleInfoW(LOCALE_USER_DEFAULT, LOCALE_SABBREVDAYNAME1 + (i+j+6)%7, buf, countof(buf));
 +    DrawTextW(hdc, buf, strlenW(buf), &r, DT_CENTER | DT_VCENTER | DT_SINGLELINE);
 +    OffsetRect(&r, infoPtr->width_increment, 0);
 +  }
 +
 +  /* 2. previous and next months */
 +  if (!(infoPtr->dwStyle & MCS_NOTRAILINGDATES) && (calIdx == 0 || calIdx == infoPtr->cal_num - 1))
 +  {
 +    SYSTEMTIME st_max;
 +
-       while(st.wDay <= MONTHCAL_MonthLength(prev_month, infoPtr->curSel.wYear))
++    SetTextColor(hdc, infoPtr->colors[MCSC_TRAILINGTEXT]);
 +
 +    /* draw prev month */
 +    if (calIdx == 0)
 +    {
 +      MONTHCAL_GetMinDate(infoPtr, &st);
 +      mask = 1 << (st.wDay-1);
++      length = MONTHCAL_MonthLength(prev_month, date->wYear);
 +
-       st = infoPtr->curSel;
++      while(st.wDay <= length)
 +      {
 +        MONTHCAL_DrawDay(infoPtr, hdc, &st, infoPtr->monthdayState[0] & mask, ps);
 +        mask <<= 1;
 +        st.wDay++;
 +      }
 +    }
 +
 +    /* draw next month */
 +    if (calIdx == infoPtr->cal_num - 1)
 +    {
-   SetTextColor(hdc, infoPtr->txt);
-   st = infoPtr->curSel;
++      st = *date;
 +      st.wDay = 1;
 +      MONTHCAL_GetNextMonth(&st);
 +      MONTHCAL_GetMaxDate(infoPtr, &st_max);
 +      mask = 1;
 +
 +      while(st.wDay <= st_max.wDay)
 +      {
 +        MONTHCAL_DrawDay(infoPtr, hdc, &st, infoPtr->monthdayState[2] & mask, ps);
 +        mask <<= 1;
 +        st.wDay++;
 +      }
 +    }
 +  }
 +
 +  /* 3. current month */
-   while(st.wDay <= MONTHCAL_MonthLength(infoPtr->curSel.wMonth, infoPtr->curSel.wYear)) {
++  SetTextColor(hdc, infoPtr->colors[MCSC_TEXT]);
++  st = *date;
 +  st.wDay = 1;
 +  mask = 1;
-   MONTHCAL_PaintButton(infoPtr, hdc, FALSE);
-   MONTHCAL_PaintButton(infoPtr, hdc, TRUE);
++  length = MONTHCAL_MonthLength(date->wMonth, date->wYear);
++  while(st.wDay <= length)
++  {
 +    MONTHCAL_DrawDay(infoPtr, hdc, &st, infoPtr->monthdayState[1] & mask, ps);
 +    mask <<= 1;
 +    st.wDay++;
 +  }
 +}
 +
 +static void MONTHCAL_Refresh(MONTHCAL_INFO *infoPtr, HDC hdc, const PAINTSTRUCT *ps)
 +{
 +  COLORREF old_text_clr, old_bk_clr;
 +  HFONT old_font;
 +  INT i;
 +
 +  old_text_clr = SetTextColor(hdc, comctl32_color.clrWindowText);
 +  old_bk_clr   = GetBkColor(hdc);
 +  old_font     = GetCurrentObject(hdc, OBJ_FONT);
 +
 +  for (i = 0; i < infoPtr->cal_num; i++)
 +  {
 +    RECT *title = &infoPtr->calendars[i].title;
 +    RECT r;
 +
 +    /* draw title, redraw all its elements */
 +    if (IntersectRect(&r, &(ps->rcPaint), title))
 +        MONTHCAL_PaintTitle(infoPtr, hdc, ps, i);
 +
 +    /* draw calendar area */
 +    UnionRect(&r, &infoPtr->calendars[i].wdays, &infoPtr->todayrect);
 +    if (IntersectRect(&r, &(ps->rcPaint), &r))
 +        MONTHCAL_PaintCalendar(infoPtr, hdc, ps, i);
 +
 +    /* week numbers */
 +    MONTHCAL_PaintWeeknumbers(infoPtr, hdc, ps, i);
 +  }
 +
 +  /* focus and today rectangle */
 +  MONTHCAL_PaintFocusAndCircle(infoPtr, hdc, ps);
 +
 +  /* today at the bottom left */
 +  MONTHCAL_PaintTodayTitle(infoPtr, hdc, ps);
 +
 +  /* navigation buttons */
- MONTHCAL_GetMinReqRect(const MONTHCAL_INFO *infoPtr, LPRECT lpRect)
++  MONTHCAL_PaintButton(infoPtr, hdc, DIRECTION_BACKWARD);
++  MONTHCAL_PaintButton(infoPtr, hdc, DIRECTION_FORWARD);
 +
 +  /* restore context */
 +  SetBkColor(hdc, old_bk_clr);
 +  SelectObject(hdc, old_font);
 +  SetTextColor(hdc, old_text_clr);
 +}
 +
 +static LRESULT
-   TRACE("rect %p\n", lpRect);
++MONTHCAL_GetMinReqRect(const MONTHCAL_INFO *infoPtr, RECT *rect)
 +{
-   if(!lpRect) return FALSE;
++  TRACE("rect %p\n", rect);
 +
-   lpRect->left   = infoPtr->calendars[0].title.left;
-   lpRect->top    = infoPtr->calendars[0].title.top;
-   lpRect->right  = infoPtr->calendars[0].title.right;
-   lpRect->bottom = infoPtr->todayrect.bottom;
++  if(!rect) return FALSE;
 +
-   AdjustWindowRect(lpRect, infoPtr->dwStyle, FALSE);
++  *rect = infoPtr->calendars[0].title;
++  rect->bottom = infoPtr->calendars[0].days.bottom + infoPtr->todayrect.bottom -
++                 infoPtr->todayrect.top;
 +
-   OffsetRect(lpRect, -lpRect->left, -lpRect->top);
++  AdjustWindowRect(rect, infoPtr->dwStyle, FALSE);
 +
 +  /* minimal rectangle is zero based */
-   TRACE("%s\n", wine_dbgstr_rect(lpRect));
++  OffsetRect(rect, -rect->left, -rect->top);
 +
- MONTHCAL_GetColor(const MONTHCAL_INFO *infoPtr, INT index)
++  TRACE("%s\n", wine_dbgstr_rect(rect));
 +
 +  return TRUE;
 +}
 +
++static COLORREF
++MONTHCAL_GetColor(const MONTHCAL_INFO *infoPtr, UINT index)
++{
++  TRACE("%p, %d\n", infoPtr, index);
++
++  if (index > MCSC_TRAILINGTEXT) return -1;
++  return infoPtr->colors[index];
++}
 +
 +static LRESULT
-   TRACE("\n");
++MONTHCAL_SetColor(MONTHCAL_INFO *infoPtr, UINT index, COLORREF color)
 +{
-   switch(index) {
-     case MCSC_BACKGROUND:
-       return infoPtr->bk;
-     case MCSC_TEXT:
-       return infoPtr->txt;
-     case MCSC_TITLEBK:
-       return infoPtr->titlebk;
-     case MCSC_TITLETEXT:
-       return infoPtr->titletxt;
-     case MCSC_MONTHBK:
-       return infoPtr->monthbk;
-     case MCSC_TRAILINGTEXT:
-       return infoPtr->trailingtxt;
-   }
-   return -1;
- }
++  COLORREF prev;
 +
- static LRESULT
- MONTHCAL_SetColor(MONTHCAL_INFO *infoPtr, INT index, COLORREF color)
- {
-   COLORREF prev = -1;
-   TRACE("%d: color %08x\n", index, color);
-   switch(index) {
-     case MCSC_BACKGROUND:
-       prev = infoPtr->bk;
-       infoPtr->bk = color;
-       break;
-     case MCSC_TEXT:
-       prev = infoPtr->txt;
-       infoPtr->txt = color;
-       break;
-     case MCSC_TITLEBK:
-       prev = infoPtr->titlebk;
-       infoPtr->titlebk = color;
-       break;
-     case MCSC_TITLETEXT:
-       prev=infoPtr->titletxt;
-       infoPtr->titletxt = color;
-       break;
-     case MCSC_MONTHBK:
-       prev = infoPtr->monthbk;
-       infoPtr->monthbk = color;
-       break;
-     case MCSC_TRAILINGTEXT:
-       prev = infoPtr->trailingtxt;
-       infoPtr->trailingtxt = color;
-       break;
-   }
++  TRACE("%p, %d: color %08x\n", infoPtr, index, color);
 +
++  if (index > MCSC_TRAILINGTEXT) return -1;
 +
++  prev = infoPtr->colors[index];
++  infoPtr->colors[index] = color;
 +
 +  InvalidateRect(infoPtr->hwndSelf, NULL, index == MCSC_BACKGROUND ? TRUE : FALSE);
 +  return prev;
 +}
 +
-   *curSel = infoPtr->curSel;
 +static LRESULT
 +MONTHCAL_GetMonthDelta(const MONTHCAL_INFO *infoPtr)
 +{
 +  TRACE("\n");
 +
 +  if(infoPtr->delta)
 +    return infoPtr->delta;
 +  else
 +    return infoPtr->visible;
 +}
 +
 +
 +static LRESULT
 +MONTHCAL_SetMonthDelta(MONTHCAL_INFO *infoPtr, INT delta)
 +{
 +  INT prev = infoPtr->delta;
 +
 +  TRACE("delta %d\n", delta);
 +
 +  infoPtr->delta = delta;
 +  return prev;
 +}
 +
 +
 +static inline LRESULT
 +MONTHCAL_GetFirstDayOfWeek(const MONTHCAL_INFO *infoPtr)
 +{
 +  int day;
 +
 +  /* convert from SYSTEMTIME to locale format */
 +  day = (infoPtr->firstDay >= 0) ? (infoPtr->firstDay+6)%7 : infoPtr->firstDay;
 +
 +  return MAKELONG(day, infoPtr->firstDaySet);
 +}
 +
 +
 +/* Sets the first day of the week that will appear in the control
 + *
 + *
 + * PARAMETERS:
 + *  [I] infoPtr : valid pointer to control data
 + *  [I] day : day number to set as new first day (0 == Monday,...,6 == Sunday)
 + *
 + *
 + * RETURN VALUE:
 + *  Low word contains previous first day,
 + *  high word indicates was first day forced with this message before or is
 + *  locale difined (TRUE - was forced, FALSE - wasn't).
 + *
 + * FIXME: this needs to be implemented properly in MONTHCAL_Refresh()
 + * FIXME: we need more error checking here
 + */
 +static LRESULT
 +MONTHCAL_SetFirstDayOfWeek(MONTHCAL_INFO *infoPtr, INT day)
 +{
 +  LRESULT prev = MONTHCAL_GetFirstDayOfWeek(infoPtr);
 +  int new_day;
 +
 +  TRACE("%d\n", day);
 +
 +  if(day == -1)
 +  {
 +    WCHAR buf[80];
 +
 +    GetLocaleInfoW(LOCALE_USER_DEFAULT, LOCALE_IFIRSTDAYOFWEEK, buf, countof(buf));
 +    TRACE("%s %d\n", debugstr_w(buf), strlenW(buf));
 +
 +    new_day = atoiW(buf);
 +
 +    infoPtr->firstDaySet = FALSE;
 +  }
 +  else if(day >= 7)
 +  {
 +    new_day = 6; /* max first day allowed */
 +    infoPtr->firstDaySet = TRUE;
 +  }
 +  else
 +  {
 +    /* Native behaviour for that case is broken: invalid date number >31
 +       got displayed at (0,0) position, current month starts always from
 +       (1,0) position. Should be implemented here as well only if there's
 +       nothing else to do. */
 +    if (day < -1)
 +      FIXME("No bug compatibility for day=%d\n", day);
 +
 +    new_day = day;
 +    infoPtr->firstDaySet = TRUE;
 +  }
 +
 +  /* convert from locale to SYSTEMTIME format */
 +  infoPtr->firstDay = (new_day >= 0) ? (++new_day) % 7 : new_day;
 +
 +  InvalidateRect(infoPtr->hwndSelf, NULL, FALSE);
 +
 +  return prev;
 +}
 +
 +
 +static LRESULT
 +MONTHCAL_GetMonthRange(const MONTHCAL_INFO *infoPtr, DWORD flag, SYSTEMTIME *st)
 +{
 +  TRACE("flag=%d, st=%p\n", flag, st);
 +
 +  if(st)
 +  {
 +    switch (flag) {
 +    case GMR_VISIBLE:
 +    {
 +        st[0] = infoPtr->calendars[0].month;
 +        st[1] = infoPtr->calendars[infoPtr->cal_num-1].month;
 +
 +        if (st[0].wMonth == min_allowed_date.wMonth &&
 +            st[0].wYear  == min_allowed_date.wYear)
 +        {
 +            st[0].wDay = min_allowed_date.wDay;
 +        }
 +        else
 +            st[0].wDay = 1;
 +        MONTHCAL_CalculateDayOfWeek(&st[0], TRUE);
 +
 +        st[1].wDay = MONTHCAL_MonthLength(st[1].wMonth, st[1].wYear);
 +        MONTHCAL_CalculateDayOfWeek(&st[1], TRUE);
 +
 +        return infoPtr->cal_num;
 +    }
 +    case GMR_DAYSTATE:
 +    {
 +        /*FIXME: currently multicalendar feature isn't implemented,
 +                 min date from previous month and max date from next one returned */
 +        MONTHCAL_GetMinDate(infoPtr, &st[0]);
 +        MONTHCAL_GetMaxDate(infoPtr, &st[1]);
 +        break;
 +    }
 +    default:
 +        WARN("Unknown flag value, got %d\n", flag);
 +    }
 +  }
 +
 +  return infoPtr->monthRange;
 +}
 +
 +
 +static LRESULT
 +MONTHCAL_GetMaxTodayWidth(const MONTHCAL_INFO *infoPtr)
 +{
 +  return(infoPtr->todayrect.right - infoPtr->todayrect.left);
 +}
 +
 +
 +static LRESULT
 +MONTHCAL_SetRange(MONTHCAL_INFO *infoPtr, SHORT limits, SYSTEMTIME *range)
 +{
 +    FILETIME ft_min, ft_max;
 +
 +    TRACE("%x %p\n", limits, range);
 +
 +    if ((limits & GDTR_MIN && !MONTHCAL_ValidateDate(&range[0])) ||
 +        (limits & GDTR_MAX && !MONTHCAL_ValidateDate(&range[1])))
 +        return FALSE;
 +
 +    if (limits & GDTR_MIN)
 +    {
 +        if (!MONTHCAL_ValidateTime(&range[0]))
 +            MONTHCAL_CopyTime(&infoPtr->todaysDate, &range[0]);
 +
 +        infoPtr->minDate = range[0];
 +        infoPtr->rangeValid |= GDTR_MIN;
 +    }
 +    if (limits & GDTR_MAX)
 +    {
 +        if (!MONTHCAL_ValidateTime(&range[1]))
 +            MONTHCAL_CopyTime(&infoPtr->todaysDate, &range[1]);
 +
 +        infoPtr->maxDate = range[1];
 +        infoPtr->rangeValid |= GDTR_MAX;
 +    }
 +
 +    /* Only one limit set - we are done */
 +    if ((infoPtr->rangeValid & (GDTR_MIN | GDTR_MAX)) != (GDTR_MIN | GDTR_MAX))
 +        return TRUE;
 +
 +    SystemTimeToFileTime(&infoPtr->maxDate, &ft_max);
 +    SystemTimeToFileTime(&infoPtr->minDate, &ft_min);
 +
 +    if (CompareFileTime(&ft_min, &ft_max) >= 0)
 +    {
 +        if ((limits & (GDTR_MIN | GDTR_MAX)) == (GDTR_MIN | GDTR_MAX))
 +        {
 +            /* Native swaps limits only when both limits are being set. */
 +            SYSTEMTIME st_tmp = infoPtr->minDate;
 +            infoPtr->minDate  = infoPtr->maxDate;
 +            infoPtr->maxDate  = st_tmp;
 +        }
 +        else
 +        {
 +            /* reset the other limit */
 +            if (limits & GDTR_MIN) infoPtr->maxDate = st_null;
 +            if (limits & GDTR_MAX) infoPtr->minDate = st_null;
 +            infoPtr->rangeValid &= limits & GDTR_MIN ? ~GDTR_MAX : ~GDTR_MIN;
 +        }
 +    }
 +
 +    return TRUE;
 +}
 +
 +
 +static LRESULT
 +MONTHCAL_GetRange(const MONTHCAL_INFO *infoPtr, SYSTEMTIME *range)
 +{
 +  TRACE("%p\n", range);
 +
 +  if(!range) return FALSE;
 +
 +  range[1] = infoPtr->maxDate;
 +  range[0] = infoPtr->minDate;
 +
 +  return infoPtr->rangeValid;
 +}
 +
 +
 +static LRESULT
 +MONTHCAL_SetDayState(const MONTHCAL_INFO *infoPtr, INT months, MONTHDAYSTATE *states)
 +{
 +  TRACE("%p %d %p\n", infoPtr, months, states);
 +  if(months != infoPtr->monthRange) return 0;
 +
 +  memcpy(infoPtr->monthdayState, states, months*sizeof(MONTHDAYSTATE));
 +
 +  return 1;
 +}
 +
 +static LRESULT
 +MONTHCAL_GetCurSel(const MONTHCAL_INFO *infoPtr, SYSTEMTIME *curSel)
 +{
 +  TRACE("%p\n", curSel);
 +  if(!curSel) return FALSE;
 +  if(infoPtr->dwStyle & MCS_MULTISELECT) return FALSE;
 +
-   SYSTEMTIME prev = infoPtr->curSel;
++  *curSel = infoPtr->minSel;
 +  TRACE("%d/%d/%d\n", curSel->wYear, curSel->wMonth, curSel->wDay);
 +  return TRUE;
 +}
 +
 +static LRESULT
 +MONTHCAL_SetCurSel(MONTHCAL_INFO *infoPtr, SYSTEMTIME *curSel)
 +{
-   if (MONTHCAL_IsDateEqual(&infoPtr->curSel, curSel)) return TRUE;
++  SYSTEMTIME prev = infoPtr->minSel;
++  WORD day;
 +
 +  TRACE("%p\n", curSel);
 +  if(!curSel) return FALSE;
 +  if(infoPtr->dwStyle & MCS_MULTISELECT) return FALSE;
 +
 +  if(!MONTHCAL_ValidateDate(curSel)) return FALSE;
 +  /* exit earlier if selection equals current */
-     /* note that infoPtr->curSel isn't updated yet */
-     MONTHCAL_CalcPosFromDay(infoPtr, &infoPtr->curSel, &r_prev);
++  if (MONTHCAL_IsDateEqual(&infoPtr->minSel, curSel)) return TRUE;
 +
 +  if(!MONTHCAL_IsDateInValidRange(infoPtr, curSel, FALSE)) return FALSE;
 +
++  infoPtr->calendars[0].month = *curSel;
 +  infoPtr->minSel = *curSel;
 +  infoPtr->maxSel = *curSel;
 +
 +  /* if selection is still in current month, reduce rectangle */
++  day = prev.wDay;
 +  prev.wDay = curSel->wDay;
 +  if (MONTHCAL_IsDateEqual(&prev, curSel))
 +  {
 +    RECT r_prev, r_new;
 +
-   infoPtr->curSel = *curSel;
-   infoPtr->calendars[0].month = *curSel;
++    prev.wDay = day;
++    MONTHCAL_CalcPosFromDay(infoPtr, &prev, &r_prev);
 +    MONTHCAL_CalcPosFromDay(infoPtr, curSel, &r_new);
 +
 +    InvalidateRect(infoPtr->hwndSelf, &r_prev, FALSE);
 +    InvalidateRect(infoPtr->hwndSelf, &r_new,  FALSE);
 +  }
 +  else
 +    InvalidateRect(infoPtr->hwndSelf, NULL, FALSE);
 +
-     infoPtr->curSel = infoPtr->minSel;
 +  return TRUE;
 +}
 +
 +
 +static LRESULT
 +MONTHCAL_GetMaxSelCount(const MONTHCAL_INFO *infoPtr)
 +{
 +  return infoPtr->maxSelCount;
 +}
 +
 +
 +static LRESULT
 +MONTHCAL_SetMaxSelCount(MONTHCAL_INFO *infoPtr, INT max)
 +{
 +  TRACE("%d\n", max);
 +
 +  if(!(infoPtr->dwStyle & MCS_MULTISELECT)) return FALSE;
 +  if(max <= 0) return FALSE;
 +
 +  infoPtr->maxSelCount = max;
 +
 +  return TRUE;
 +}
 +
 +
 +static LRESULT
 +MONTHCAL_GetSelRange(const MONTHCAL_INFO *infoPtr, SYSTEMTIME *range)
 +{
 +  TRACE("%p\n", range);
 +
 +  if(!range) return FALSE;
 +
 +  if(infoPtr->dwStyle & MCS_MULTISELECT)
 +  {
 +    range[1] = infoPtr->maxSel;
 +    range[0] = infoPtr->minSel;
 +    TRACE("[min,max]=[%d %d]\n", infoPtr->minSel.wDay, infoPtr->maxSel.wDay);
 +    return TRUE;
 +  }
 +
 +  return FALSE;
 +}
 +
 +
 +static LRESULT
 +MONTHCAL_SetSelRange(MONTHCAL_INFO *infoPtr, SYSTEMTIME *range)
 +{
 +  TRACE("%p\n", range);
 +
 +  if(!range) return FALSE;
 +
 +  if(infoPtr->dwStyle & MCS_MULTISELECT)
 +  {
 +    SYSTEMTIME old_range[2];
 +
 +    /* adjust timestamps */
 +    if(!MONTHCAL_ValidateTime(&range[0]))
 +      MONTHCAL_CopyTime(&infoPtr->todaysDate, &range[0]);
 +    if(!MONTHCAL_ValidateTime(&range[1]))
 +      MONTHCAL_CopyTime(&infoPtr->todaysDate, &range[1]);
 +
 +    /* maximum range exceeded */
 +    if(!MONTHCAL_IsSelRangeValid(infoPtr, &range[0], &range[1], NULL)) return FALSE;
 +
 +    old_range[0] = infoPtr->minSel;
 +    old_range[1] = infoPtr->maxSel;
 +
 +    /* swap if min > max */
 +    if(MONTHCAL_CompareSystemTime(&range[0], &range[1]) <= 0)
 +    {
 +      infoPtr->minSel = range[0];
 +      infoPtr->maxSel = range[1];
 +    }
 +    else
 +    {
 +      infoPtr->minSel = range[1];
 +      infoPtr->maxSel = range[0];
 +    }
-     MONTHCAL_CalculateDayOfWeek(&infoPtr->curSel, TRUE);
 +    infoPtr->calendars[0].month = infoPtr->minSel;
 +
 +    /* update day of week */
 +    MONTHCAL_CalculateDayOfWeek(&infoPtr->minSel, TRUE);
 +    MONTHCAL_CalculateDayOfWeek(&infoPtr->maxSel, TRUE);
-   memset(&lpht->st, 0, sizeof(lpht->st));
 +
 +    /* redraw if bounds changed */
 +    /* FIXME: no actual need to redraw everything */
 +    if(!MONTHCAL_IsDateEqual(&old_range[0], &range[0]) ||
 +       !MONTHCAL_IsDateEqual(&old_range[1], &range[1]))
 +    {
 +       InvalidateRect(infoPtr->hwndSelf, NULL, FALSE);
 +    }
 +
 +    TRACE("[min,max]=[%d %d]\n", infoPtr->minSel.wDay, infoPtr->maxSel.wDay);
 +    return TRUE;
 +  }
 +
 +  return FALSE;
 +}
 +
 +
 +static LRESULT
 +MONTHCAL_GetToday(const MONTHCAL_INFO *infoPtr, SYSTEMTIME *today)
 +{
 +  TRACE("%p\n", today);
 +
 +  if(!today) return FALSE;
 +  *today = infoPtr->todaysDate;
 +  return TRUE;
 +}
 +
 +/* Internal helper for MCM_SETTODAY handler and auto update timer handler
 + *
 + * RETURN VALUE
 + *
 + *  TRUE  - today date changed
 + *  FALSE - today date isn't changed
 + */
 +static BOOL
 +MONTHCAL_UpdateToday(MONTHCAL_INFO *infoPtr, const SYSTEMTIME *today)
 +{
 +  RECT new_r, old_r;
 +
 +  if(MONTHCAL_IsDateEqual(today, &infoPtr->todaysDate)) return FALSE;
 +
 +  MONTHCAL_CalcPosFromDay(infoPtr, &infoPtr->todaysDate, &old_r);
 +  MONTHCAL_CalcPosFromDay(infoPtr, today, &new_r);
 +
 +  infoPtr->todaysDate = *today;
 +
 +  /* only two days need redrawing */
 +  InvalidateRect(infoPtr->hwndSelf, &old_r, FALSE);
 +  InvalidateRect(infoPtr->hwndSelf, &new_r, FALSE);
 +  return TRUE;
 +}
 +
 +/* MCM_SETTODAT handler */
 +static LRESULT
 +MONTHCAL_SetToday(MONTHCAL_INFO *infoPtr, const SYSTEMTIME *today)
 +{
 +  TRACE("%p\n", today);
 +
 +  if(!today) return FALSE;
 +
 +  /* remember if date was set successfully */
 +  if(MONTHCAL_UpdateToday(infoPtr, today)) infoPtr->todaySet = TRUE;
 +
 +  return TRUE;
 +}
 +
 +/* returns calendar index containing specified point, or -1 if it's background */
 +static INT MONTHCAL_GetCalendarFromPoint(const MONTHCAL_INFO *infoPtr, const POINT *pt)
 +{
 +  RECT r;
 +  INT i;
 +
 +  for (i = 0; i < infoPtr->cal_num; i++)
 +  {
 +     /* whole bounding rectangle allows some optimization to compute */
 +     r.left   = infoPtr->calendars[i].title.left;
 +     r.top    = infoPtr->calendars[i].title.top;
 +     r.bottom = infoPtr->calendars[i].days.bottom;
 +     r.right  = infoPtr->calendars[i].days.right;
 +
 +     if (PtInRect(&r, *pt)) return i;
 +  }
 +
 +  return -1;
 +}
 +
++static inline UINT fill_hittest_info(const MCHITTESTINFO *src, MCHITTESTINFO *dest)
++{
++  dest->uHit = src->uHit;
++  dest->st = src->st;
++
++  if (dest->cbSize == sizeof(MCHITTESTINFO))
++    memcpy(&dest->rc, &src->rc, sizeof(MCHITTESTINFO) - MCHITTESTINFO_V1_SIZE);
++
++  return src->uHit;
++}
++
 +static LRESULT
 +MONTHCAL_HitTest(const MONTHCAL_INFO *infoPtr, MCHITTESTINFO *lpht)
 +{
 +  INT day, wday, wnum, calIdx;
++  MCHITTESTINFO htinfo;
 +  SYSTEMTIME ht_month;
 +  UINT x, y;
 +
 +  if(!lpht || lpht->cbSize < MCHITTESTINFO_V1_SIZE) return -1;
 +
 +  x = lpht->pt.x;
 +  y = lpht->pt.y;
 +
-       lpht->uHit = MCHT_TODAYLINK;
++  htinfo.st = st_null;
++
++  /* we should preserve passed fields if hit area doesn't need them */
++  if (lpht->cbSize == sizeof(MCHITTESTINFO))
++    memcpy(&htinfo.rc, &lpht->rc, sizeof(MCHITTESTINFO) - MCHITTESTINFO_V1_SIZE);
 +
 +  /* Comment in for debugging...
 +  TRACE("%d %d wd[%d %d %d %d] d[%d %d %d %d] t[%d %d %d %d] wn[%d %d %d %d]\n", x, y,
 +      infoPtr->wdays.left, infoPtr->wdays.right,
 +      infoPtr->wdays.top, infoPtr->wdays.bottom,
 +      infoPtr->days.left, infoPtr->days.right,
 +      infoPtr->days.top, infoPtr->days.bottom,
 +      infoPtr->todayrect.left, infoPtr->todayrect.right,
 +      infoPtr->todayrect.top, infoPtr->todayrect.bottom,
 +      infoPtr->weeknums.left, infoPtr->weeknums.right,
 +      infoPtr->weeknums.top, infoPtr->weeknums.bottom);
 +  */
 +
 +  /* guess in what calendar we are */
 +  calIdx = MONTHCAL_GetCalendarFromPoint(infoPtr, &lpht->pt);
 +  if (calIdx == -1)
 +  {
 +    if (PtInRect(&infoPtr->todayrect, lpht->pt))
-       lpht->uHit = MCHT_CALENDARBK;
++    {
++      htinfo.uHit = MCHT_TODAYLINK;
++      htinfo.rc = infoPtr->todayrect;
++    }
 +    else
 +      /* outside of calendar area? What's left must be background :-) */
-     return lpht->uHit;
++      htinfo.uHit = MCHT_CALENDARBK;
 +
-       lpht->uHit = MCHT_TITLEBTNPREV;
++    return fill_hittest_info(&htinfo, lpht);
 +  }
 +
 +  ht_month = infoPtr->calendars[calIdx].month;
 +
 +  /* are we in the header? */
 +  if (PtInRect(&infoPtr->calendars[calIdx].title, lpht->pt)) {
 +    /* FIXME: buttons hittesting could be optimized cause maximum
 +              two calendars have buttons */
 +    if (calIdx == 0 && PtInRect(&infoPtr->titlebtnprev, lpht->pt))
 +    {
-       lpht->uHit = MCHT_TITLEBTNNEXT;
++      htinfo.uHit = MCHT_TITLEBTNPREV;
++      htinfo.rc = infoPtr->titlebtnprev;
 +    }
 +    else if (PtInRect(&infoPtr->titlebtnnext, lpht->pt))
 +    {
-       lpht->uHit = MCHT_TITLEMONTH;
++      htinfo.uHit = MCHT_TITLEBTNNEXT;
++      htinfo.rc = infoPtr->titlebtnnext;
 +    }
 +    else if (PtInRect(&infoPtr->calendars[calIdx].titlemonth, lpht->pt))
 +    {
-       lpht->uHit = MCHT_TITLEYEAR;
++      htinfo.uHit = MCHT_TITLEMONTH;
++      htinfo.rc = infoPtr->calendars[calIdx].titlemonth;
++      htinfo.iOffset = calIdx;
 +    }
 +    else if (PtInRect(&infoPtr->calendars[calIdx].titleyear, lpht->pt))
 +    {
-       lpht->uHit = MCHT_TITLE;
++      htinfo.uHit = MCHT_TITLEYEAR;
++      htinfo.rc = infoPtr->calendars[calIdx].titleyear;
++      htinfo.iOffset = calIdx;
 +    }
 +    else
-     return lpht->uHit;
++    {
++      htinfo.uHit = MCHT_TITLE;
++      htinfo.rc = infoPtr->calendars[calIdx].title;
++      htinfo.iOffset = calIdx;
++    }
 +
-     lpht->uHit = MCHT_CALENDARDAY;
-     lpht->st.wYear  = ht_month.wYear;
-     lpht->st.wMonth = (day < 1) ? ht_month.wMonth -1 : ht_month.wMonth;
-     lpht->st.wDay   = (day < 1) ?
++    return fill_hittest_info(&htinfo, lpht);
 +  }
 +
 +  /* days area (including week days and week numbers */
 +  day = MONTHCAL_CalcDayFromPos(infoPtr, x, y, &wday, &wnum);
 +  if (PtInRect(&infoPtr->calendars[calIdx].wdays, lpht->pt))
 +  {
-     lpht->uHit = MCHT_CALENDARWEEKNUM;
-     lpht->st.wYear  = ht_month.wYear;
++    htinfo.uHit = MCHT_CALENDARDAY;
++    htinfo.iOffset = calIdx;
++    htinfo.st.wYear  = ht_month.wYear;
++    htinfo.st.wMonth = (day < 1) ? ht_month.wMonth -1 : ht_month.wMonth;
++    htinfo.st.wDay   = (day < 1) ?
 +      MONTHCAL_MonthLength(ht_month.wMonth-1, ht_month.wYear) - day : day;
++
++    MONTHCAL_CalcDayXY(infoPtr, &htinfo.st, &htinfo.iCol, &htinfo.iRow);
 +  }
 +  else if(PtInRect(&infoPtr->calendars[calIdx].weeknums, lpht->pt))
 +  {
-     if (day < 1) {
-       lpht->st.wMonth = ht_month.wMonth - 1;
++    htinfo.uHit = MCHT_CALENDARWEEKNUM;
++    htinfo.st.wYear  = ht_month.wYear;
++    htinfo.iOffset = calIdx;
 +
-     else if (day > MONTHCAL_MonthLength(ht_month.wMonth, ht_month.wYear)) {
-       lpht->st.wMonth = ht_month.wMonth + 1;
++    if (day < 1)
++    {
++      htinfo.st.wMonth = ht_month.wMonth - 1;
++      htinfo.st.wDay = MONTHCAL_MonthLength(ht_month.wMonth-1, ht_month.wYear) - day;
 +    }
-       lpht->st.wMonth = ht_month.wMonth;
-     if (day < 1) {
-       lpht->st.wDay = MONTHCAL_MonthLength(ht_month.wMonth-1, ht_month.wYear) - day;
-     }
-     else if (day > MONTHCAL_MonthLength(ht_month.wMonth, ht_month.wYear)) {
-       lpht->st.wDay = day - MONTHCAL_MonthLength(ht_month.wMonth, ht_month.wYear);
++    else if (day > MONTHCAL_MonthLength(ht_month.wMonth, ht_month.wYear))
++    {
++      htinfo.st.wMonth = ht_month.wMonth + 1;
++      htinfo.st.wDay = day - MONTHCAL_MonthLength(ht_month.wMonth, ht_month.wYear);
 +    }
 +    else
-     else
-       lpht->st.wDay = day;
++    {
++      htinfo.st.wMonth = ht_month.wMonth;
++      htinfo.st.wDay = day;
 +    }
-       lpht->st.wYear  = ht_month.wYear;
-       lpht->st.wMonth = ht_month.wMonth;
 +  }
 +  else if(PtInRect(&infoPtr->calendars[calIdx].days, lpht->pt))
 +  {
-         lpht->uHit = MCHT_CALENDARDATEPREV;
-         MONTHCAL_GetPrevMonth(&lpht->st);
-         lpht->st.wDay = MONTHCAL_MonthLength(lpht->st.wMonth, lpht->st.wYear) + day;
++      htinfo.iOffset = calIdx;
++      htinfo.st.wYear  = ht_month.wYear;
++      htinfo.st.wMonth = ht_month.wMonth;
 +      if (day < 1)
 +      {
-         lpht->uHit = MCHT_CALENDARDATENEXT;
-         MONTHCAL_GetNextMonth(&lpht->st);
-         lpht->st.wDay = day - MONTHCAL_MonthLength(ht_month.wMonth, ht_month.wYear);
++        htinfo.uHit = MCHT_CALENDARDATEPREV;
++        MONTHCAL_GetPrevMonth(&htinfo.st);
++        htinfo.st.wDay = MONTHCAL_MonthLength(lpht->st.wMonth, lpht->st.wYear) + day;
 +      }
 +      else if (day > MONTHCAL_MonthLength(ht_month.wMonth, ht_month.wYear))
 +      {
-       else {
-       lpht->uHit = MCHT_CALENDARDATE;
-       lpht->st.wDay = day;
++        htinfo.uHit = MCHT_CALENDARDATENEXT;
++        MONTHCAL_GetNextMonth(&htinfo.st);
++        htinfo.st.wDay = day - MONTHCAL_MonthLength(ht_month.wMonth, ht_month.wYear);
 +      }
-       MONTHCAL_CalculateDayOfWeek(&lpht->st, TRUE);
++      else
++      {
++      htinfo.uHit = MCHT_CALENDARDATE;
++      htinfo.st.wDay = day;
 +      }
 +
++      MONTHCAL_CalcDayXY(infoPtr, &htinfo.st, &htinfo.iCol, &htinfo.iRow);
++      MONTHCAL_CalcDayRect(infoPtr, &htinfo.rc, htinfo.iCol, htinfo.iRow);
 +      /* always update day of week */
-   return lpht->uHit;
++      MONTHCAL_CalculateDayOfWeek(&htinfo.st, TRUE);
 +  }
 +
-     nmds.stStart.wYear  = infoPtr->curSel.wYear;
-     nmds.stStart.wMonth = infoPtr->curSel.wMonth;
++  return fill_hittest_info(&htinfo, lpht);
 +}
 +
 +/* MCN_GETDAYSTATE notification helper */
 +static void MONTHCAL_NotifyDayState(MONTHCAL_INFO *infoPtr)
 +{
 +  if(infoPtr->dwStyle & MCS_DAYSTATE) {
 +    NMDAYSTATE nmds;
 +
 +    nmds.nmhdr.hwndFrom = infoPtr->hwndSelf;
 +    nmds.nmhdr.idFrom   = GetWindowLongPtrW(infoPtr->hwndSelf, GWLP_ID);
 +    nmds.nmhdr.code     = MCN_GETDAYSTATE;
 +    nmds.cDayState    = infoPtr->monthRange;
 +    nmds.prgDayState  = Alloc(infoPtr->monthRange * sizeof(MONTHDAYSTATE));
 +
 +    nmds.stStart = infoPtr->todaysDate;
- static void MONTHCAL_GoToPrevNextMonth(MONTHCAL_INFO *infoPtr, BOOL prev)
++    nmds.stStart.wYear  = infoPtr->minSel.wYear;
++    nmds.stStart.wMonth = infoPtr->minSel.wMonth;
 +    nmds.stStart.wDay = 1;
 +
 +    SendMessageW(infoPtr->hwndNotify, WM_NOTIFY, nmds.nmhdr.idFrom, (LPARAM)&nmds);
 +    memcpy(infoPtr->monthdayState, nmds.prgDayState, infoPtr->monthRange*sizeof(MONTHDAYSTATE));
 +
 +    Free(nmds.prgDayState);
 +  }
 +}
 +
-   SYSTEMTIME st = infoPtr->curSel;
++/* no valid range check performed */
++static void MONTHCAL_Scroll(MONTHCAL_INFO *infoPtr, INT delta)
 +{
-   TRACE("%s\n", prev ? "prev" : "next");
-   if(prev) MONTHCAL_GetPrevMonth(&st); else MONTHCAL_GetNextMonth(&st);
++  INT i, selIdx = -1;
 +
-   if(!MONTHCAL_IsDateInValidRange(infoPtr, &st, FALSE)) return;
++  for(i = 0; i < infoPtr->cal_num; i++)
++  {
++    /* save selection position to shift it later */
++    if (selIdx == -1 && MONTHCAL_CompareMonths(&infoPtr->minSel, &infoPtr->calendars[i].month) == 0)
++      selIdx = i;
 +
-     range[0] = infoPtr->minSel;
-     range[1] = infoPtr->maxSel;
-     if(prev)
-     {
-       MONTHCAL_GetPrevMonth(&range[0]);
-       MONTHCAL_GetPrevMonth(&range[1]);
-     }
-     else
-     {
-       MONTHCAL_GetNextMonth(&range[0]);
-       MONTHCAL_GetNextMonth(&range[1]);
-     }
++    MONTHCAL_GetMonth(&infoPtr->calendars[i].month, delta);
++  }
 +
++  /* selection is always shifted to first calendar */
 +  if(infoPtr->dwStyle & MCS_MULTISELECT)
 +  {
 +    SYSTEMTIME range[2];
 +
-   MONTHCAL_NotifyDayState(infoPtr);
++    MONTHCAL_GetSelRange(infoPtr, range);
++    MONTHCAL_GetMonth(&range[0], delta - selIdx);
++    MONTHCAL_GetMonth(&range[1], delta - selIdx);
 +    MONTHCAL_SetSelRange(infoPtr, range);
 +  }
 +  else
++  {
++    SYSTEMTIME st = infoPtr->minSel;
++
++    MONTHCAL_GetMonth(&st, delta - selIdx);
 +    MONTHCAL_SetCurSel(infoPtr, &st);
++  }
++}
 +
-       infoPtr->curSel = infoPtr->todaysDate;
++static void MONTHCAL_GoToMonth(MONTHCAL_INFO *infoPtr, enum nav_direction direction)
++{
++  INT delta = infoPtr->delta ? infoPtr->delta : infoPtr->cal_num;
++  SYSTEMTIME st;
++
++  TRACE("%s\n", direction == DIRECTION_BACKWARD ? "back" : "fwd");
 +
++  /* check if change allowed by range set */
++  if(direction == DIRECTION_BACKWARD)
++  {
++    st = infoPtr->calendars[0].month;
++    MONTHCAL_GetMonth(&st, -delta);
++  }
++  else
++  {
++    st = infoPtr->calendars[infoPtr->cal_num-1].month;
++    MONTHCAL_GetMonth(&st, delta);
++  }
++
++  if(!MONTHCAL_IsDateInValidRange(infoPtr, &st, FALSE)) return;
++
++  MONTHCAL_Scroll(infoPtr, direction == DIRECTION_BACKWARD ? -delta : delta);
++  MONTHCAL_NotifyDayState(infoPtr);
 +  MONTHCAL_NotifySelectionChange(infoPtr);
 +}
 +
 +static LRESULT
 +MONTHCAL_RButtonUp(MONTHCAL_INFO *infoPtr, LPARAM lParam)
 +{
 +  static const WCHAR todayW[] = { 'G','o',' ','t','o',' ','T','o','d','a','y',':',0 };
 +  HMENU hMenu;
 +  POINT menupoint;
 +  WCHAR buf[32];
 +
 +  hMenu = CreatePopupMenu();
 +  if (!LoadStringW(COMCTL32_hModule, IDM_GOTODAY, buf, countof(buf)))
 +  {
 +      WARN("Can't load resource\n");
 +      strcpyW(buf, todayW);
 +  }
 +  AppendMenuW(hMenu, MF_STRING|MF_ENABLED, 1, buf);
 +  menupoint.x = (short)LOWORD(lParam);
 +  menupoint.y = (short)HIWORD(lParam);
 +  ClientToScreen(infoPtr->hwndSelf, &menupoint);
 +  if( TrackPopupMenu(hMenu, TPM_RIGHTBUTTON | TPM_NONOTIFY | TPM_RETURNCMD,
 +                   menupoint.x, menupoint.y, 0, infoPtr->hwndSelf, NULL))
 +  {
- static void MONTHCAL_EditYear(MONTHCAL_INFO *infoPtr)
 +      infoPtr->calendars[0].month = infoPtr->todaysDate;
 +      infoPtr->minSel = infoPtr->todaysDate;
 +      infoPtr->maxSel = infoPtr->todaysDate;
 +      InvalidateRect(infoPtr->hwndSelf, NULL, FALSE);
 +  }
 +
 +  return 0;
 +}
 +
 +/***
 + * DESCRIPTION:
 + * Subclassed edit control windproc function
 + *
 + * PARAMETER(S):
 + * [I] hwnd : the edit window handle
 + * [I] uMsg : the message that is to be processed
 + * [I] wParam : first message parameter
 + * [I] lParam : second message parameter
 + *
 + */
 +static LRESULT CALLBACK EditWndProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
 +{
 +    MONTHCAL_INFO *infoPtr = (MONTHCAL_INFO *)GetWindowLongPtrW(GetParent(hwnd), 0);
 +
 +    TRACE("(hwnd=%p, uMsg=%x, wParam=%lx, lParam=%lx)\n",
 +        hwnd, uMsg, wParam, lParam);
 +
 +    switch (uMsg)
 +    {
 +      case WM_GETDLGCODE:
 +        return DLGC_WANTARROWS | DLGC_WANTALLKEYS;
 +
 +      case WM_DESTROY:
 +      {
 +          WNDPROC editProc = infoPtr->EditWndProc;
 +          infoPtr->EditWndProc = NULL;
 +          SetWindowLongPtrW(hwnd, GWLP_WNDPROC, (DWORD_PTR)editProc);
 +          return CallWindowProcW(editProc, hwnd, uMsg, wParam, lParam);
 +      }
 +
 +      case WM_KILLFOCUS:
 +          break;
 +
 +      case WM_KEYDOWN:
 +          if ((VK_ESCAPE == (INT)wParam) || (VK_RETURN == (INT)wParam))
 +              break;
 +
 +      default:
 +          return CallWindowProcW(infoPtr->EditWndProc, hwnd, uMsg, wParam, lParam);
 +    }
 +
 +    SendMessageW(infoPtr->hWndYearUpDown, WM_CLOSE, 0, 0);
 +    SendMessageW(hwnd, WM_CLOSE, 0, 0);
 +    return 0;
 +}
 +
 +/* creates updown control and edit box */
-                       infoPtr->calendars[0].titleyear.left + 3, infoPtr->titlebtnnext.top,
-                       infoPtr->calendars[0].titleyear.right - infoPtr->calendars[0].titleyear.left + 4,
++static void MONTHCAL_EditYear(MONTHCAL_INFO *infoPtr, INT calIdx)
 +{
++    RECT *rc = &infoPtr->calendars[calIdx].titleyear;
++    RECT *title = &infoPtr->calendars[calIdx].title;
++
 +    infoPtr->hWndYearEdit =
 +      CreateWindowExW(0, WC_EDITW, 0, WS_VISIBLE | WS_CHILD | ES_READONLY,
-                       infoPtr->calendars[0].titleyear.right + 7, infoPtr->titlebtnnext.top,
++                      rc->left + 3, (title->bottom + title->top - infoPtr->textHeight) / 2,
++                      rc->right - rc->left + 4,
 +                      infoPtr->textHeight, infoPtr->hwndSelf,
 +                      NULL, NULL, NULL);
 +
 +    SendMessageW(infoPtr->hWndYearEdit, WM_SETFONT, (WPARAM)infoPtr->hBoldFont, TRUE);
 +
 +    infoPtr->hWndYearUpDown =
 +      CreateWindowExW(0, UPDOWN_CLASSW, 0,
 +                      WS_VISIBLE | WS_CHILD | UDS_SETBUDDYINT | UDS_NOTHOUSANDS | UDS_ARROWKEYS,
-     SendMessageW(infoPtr->hWndYearUpDown, UDM_SETPOS, 0, infoPtr->curSel.wYear);
++                      rc->right + 7, (title->bottom + title->top - infoPtr->textHeight) / 2,
 +                      18, infoPtr->textHeight, infoPtr->hwndSelf,
 +                      NULL, NULL, NULL);
 +
 +    /* attach edit box */
 +    SendMessageW(infoPtr->hWndYearUpDown, UDM_SETRANGE, 0,
 +                 MAKELONG(max_allowed_date.wYear, min_allowed_date.wYear));
 +    SendMessageW(infoPtr->hWndYearUpDown, UDM_SETBUDDY, (WPARAM)infoPtr->hWndYearEdit, 0);
-     MONTHCAL_GoToPrevNextMonth(infoPtr, FALSE);
++    SendMessageW(infoPtr->hWndYearUpDown, UDM_SETPOS, 0, infoPtr->calendars[calIdx].month.wYear);
 +
 +    /* subclass edit box */
 +    infoPtr->EditWndProc = (WNDPROC)SetWindowLongPtrW(infoPtr->hWndYearEdit,
 +                                  GWLP_WNDPROC, (DWORD_PTR)EditWndProc);
 +
 +    SetFocus(infoPtr->hWndYearEdit);
 +}
 +
 +static LRESULT
 +MONTHCAL_LButtonDown(MONTHCAL_INFO *infoPtr, LPARAM lParam)
 +{
 +  MCHITTESTINFO ht;
 +  DWORD hit;
 +
 +  /* Actually we don't need input focus for calendar, this is used to kill
 +     year updown and its buddy edit box */
 +  if (IsWindow(infoPtr->hWndYearUpDown))
 +  {
 +      SetFocus(infoPtr->hwndSelf);
 +      return 0;
 +  }
 +
 +  SetCapture(infoPtr->hwndSelf);
 +
 +  ht.cbSize = sizeof(MCHITTESTINFO);
 +  ht.pt.x = (short)LOWORD(lParam);
 +  ht.pt.y = (short)HIWORD(lParam);
 +
 +  hit = MONTHCAL_HitTest(infoPtr, &ht);
 +
 +  TRACE("%x at (%d, %d)\n", hit, ht.pt.x, ht.pt.y);
 +
 +  switch(hit)
 +  {
 +  case MCHT_TITLEBTNNEXT:
-     MONTHCAL_GoToPrevNextMonth(infoPtr, TRUE);
++    MONTHCAL_GoToMonth(infoPtr, DIRECTION_FORWARD);
 +    infoPtr->status = MC_NEXTPRESSED;
 +    SetTimer(infoPtr->hwndSelf, MC_PREVNEXTMONTHTIMER, MC_PREVNEXTMONTHDELAY, 0);
 +    InvalidateRect(infoPtr->hwndSelf, NULL, FALSE);
 +    return 0;
 +
 +  case MCHT_TITLEBTNPREV:
-     if ((i > 0) && (i < 13) && infoPtr->curSel.wMonth != i)
++    MONTHCAL_GoToMonth(infoPtr, DIRECTION_BACKWARD);
 +    infoPtr->status = MC_PREVPRESSED;
 +    SetTimer(infoPtr->hwndSelf, MC_PREVNEXTMONTHTIMER, MC_PREVNEXTMONTHDELAY, 0);
 +    InvalidateRect(infoPtr->hwndSelf, NULL, FALSE);
 +    return 0;
 +
 +  case MCHT_TITLEMONTH:
 +  {
 +    HMENU hMenu = CreatePopupMenu();
 +    WCHAR buf[32];
 +    POINT menupoint;
 +    INT i;
 +
 +    for (i = 0; i < 12; i++)
 +    {
 +      GetLocaleInfoW(LOCALE_USER_DEFAULT, LOCALE_SMONTHNAME1+i, buf, countof(buf));
 +      AppendMenuW(hMenu, MF_STRING|MF_ENABLED, i + 1, buf);
 +    }
 +    menupoint.x = ht.pt.x;
 +    menupoint.y = ht.pt.y;
 +    ClientToScreen(infoPtr->hwndSelf, &menupoint);
 +    i = TrackPopupMenu(hMenu,TPM_LEFTALIGN | TPM_NONOTIFY | TPM_RIGHTBUTTON | TPM_RETURNCMD,
 +                     menupoint.x, menupoint.y, 0, infoPtr->hwndSelf, NULL);
 +
-       infoPtr->curSel.wMonth = i;
-       MONTHCAL_IsDateInValidRange(infoPtr, &infoPtr->curSel, TRUE);
-       InvalidateRect(infoPtr->hwndSelf, NULL, FALSE);
++    if ((i > 0) && (i < 13) && infoPtr->calendars[ht.iOffset].month.wMonth != i)
 +    {
-     MONTHCAL_EditYear(infoPtr);
++        INT delta = i - infoPtr->calendars[ht.iOffset].month.wMonth;
++        SYSTEMTIME st;
++
++        /* check if change allowed by range set */
++        st = delta < 0 ? infoPtr->calendars[0].month :
++                         infoPtr->calendars[infoPtr->cal_num-1].month;
++        MONTHCAL_GetMonth(&st, delta);
++
++        if (MONTHCAL_IsDateInValidRange(infoPtr, &st, FALSE))
++        {
++            MONTHCAL_Scroll(infoPtr, delta);
++            MONTHCAL_NotifyDayState(infoPtr);
++            MONTHCAL_NotifySelectionChange(infoPtr);
++            InvalidateRect(infoPtr->hwndSelf, NULL, FALSE);
++        }
 +    }
 +    return 0;
 +  }
 +  case MCHT_TITLEYEAR:
 +  {
-     infoPtr->curSel = infoPtr->todaysDate;
++    MONTHCAL_EditYear(infoPtr, ht.iOffset);
 +    return 0;
 +  }
 +  case MCHT_TODAYLINK:
 +  {
-     SYSTEMTIME sel = infoPtr->curSel;
 +    infoPtr->calendars[0].month = infoPtr->todaysDate;
 +    infoPtr->minSel = infoPtr->todaysDate;
 +    infoPtr->maxSel = infoPtr->todaysDate;
 +    InvalidateRect(infoPtr->hwndSelf, NULL, FALSE);
 +
 +    MONTHCAL_NotifySelectionChange(infoPtr);
 +    MONTHCAL_NotifySelect(infoPtr);
 +    return 0;
 +  }
 +  case MCHT_CALENDARDATENEXT:
 +  case MCHT_CALENDARDATEPREV:
 +  case MCHT_CALENDARDATE:
 +  {
 +    SYSTEMTIME st[2];
 +
 +    MONTHCAL_CopyDate(&ht.st, &infoPtr->firstSel);
 +
 +    st[0] = st[1] = ht.st;
 +    /* clear selection range */
 +    MONTHCAL_SetSelRange(infoPtr, st);
 +
 +    infoPtr->status = MC_SEL_LBUTDOWN;
 +    MONTHCAL_SetDayFocus(infoPtr, &ht.st);
 +    return 0;
 +  }
 +  }
 +
 +  return 1;
 +}
 +
 +
 +static LRESULT
 +MONTHCAL_LButtonUp(MONTHCAL_INFO *infoPtr, LPARAM lParam)
 +{
 +  NMHDR nmhdr;
 +  MCHITTESTINFO ht;
 +  DWORD hit;
 +
 +  TRACE("\n");
 +
 +  if(infoPtr->status & (MC_PREVPRESSED | MC_NEXTPRESSED)) {
 +    RECT *r;
 +
 +    KillTimer(infoPtr->hwndSelf, MC_PREVNEXTMONTHTIMER);
 +    r = infoPtr->status & MC_PREVPRESSED ? &infoPtr->titlebtnprev : &infoPtr->titlebtnnext;
 +    infoPtr->status &= ~(MC_PREVPRESSED | MC_NEXTPRESSED);
 +
 +    InvalidateRect(infoPtr->hwndSelf, r, FALSE);
 +  }
 +
 +  ReleaseCapture();
 +
 +  /* always send NM_RELEASEDCAPTURE notification */
 +  nmhdr.hwndFrom = infoPtr->hwndSelf;
 +  nmhdr.idFrom   = GetWindowLongPtrW(infoPtr->hwndSelf, GWLP_ID);
 +  nmhdr.code     = NM_RELEASEDCAPTURE;
 +  TRACE("Sent notification from %p to %p\n", infoPtr->hwndSelf, infoPtr->hwndNotify);
 +
 +  SendMessageW(infoPtr->hwndNotify, WM_NOTIFY, nmhdr.idFrom, (LPARAM)&nmhdr);
 +
 +  if(!(infoPtr->status & MC_SEL_LBUTDOWN)) return 0;
 +
 +  ht.cbSize = sizeof(MCHITTESTINFO);
 +  ht.pt.x = (short)LOWORD(lParam);
 +  ht.pt.y = (short)HIWORD(lParam);
 +  hit = MONTHCAL_HitTest(infoPtr, &ht);
 +
 +  infoPtr->status = MC_SEL_LBUTUP;
 +  MONTHCAL_SetDayFocus(infoPtr, NULL);
 +
 +  if((hit & MCHT_CALENDARDATE) == MCHT_CALENDARDATE)
 +  {
-     if(infoPtr->status & MC_NEXTPRESSED) MONTHCAL_GoToPrevNextMonth(infoPtr, FALSE);
-     if(infoPtr->status & MC_PREVPRESSED) MONTHCAL_GoToPrevNextMonth(infoPtr, TRUE);
++    SYSTEMTIME sel = infoPtr->minSel;
 +
 +    /* will be invalidated here */
 +    MONTHCAL_SetCurSel(infoPtr, &ht.st);
 +
 +    /* send MCN_SELCHANGE only if new date selected */
 +    if (!MONTHCAL_IsDateEqual(&sel, &ht.st))
 +        MONTHCAL_NotifySelectionChange(infoPtr);
 +
 +    MONTHCAL_NotifySelect(infoPtr);
 +  }
 +
 +  return 0;
 +}
 +
 +
 +static LRESULT
 +MONTHCAL_Timer(MONTHCAL_INFO *infoPtr, WPARAM id)
 +{
 +  TRACE("%ld\n", id);
 +
 +  switch(id) {
 +  case MC_PREVNEXTMONTHTIMER:
-   hbr = CreateSolidBrush (infoPtr->bk);
++    if(infoPtr->status & MC_NEXTPRESSED) MONTHCAL_GoToMonth(infoPtr, DIRECTION_FORWARD);
++    if(infoPtr->status & MC_PREVPRESSED) MONTHCAL_GoToMonth(infoPtr, DIRECTION_BACKWARD);
 +    InvalidateRect(infoPtr->hwndSelf, NULL, FALSE);
 +    break;
 +  case MC_TODAYUPDATETIMER:
 +  {
 +    SYSTEMTIME st;
 +
 +    if(infoPtr->todaySet) return 0;
 +
 +    GetLocalTime(&st);
 +    MONTHCAL_UpdateToday(infoPtr, &st);
 +
 +    /* notification sent anyway */
 +    MONTHCAL_NotifySelectionChange(infoPtr);
 +
 +    return 0;
 +  }
 +  default:
 +    ERR("got unknown timer %ld\n", id);
 +    break;
 +  }
 +
 +  return 0;
 +}
 +
 +
 +static LRESULT
 +MONTHCAL_MouseMove(MONTHCAL_INFO *infoPtr, LPARAM lParam)
 +{
 +  MCHITTESTINFO ht;
 +  SYSTEMTIME st_ht;
 +  INT hit;
 +  RECT r;
 +
 +  if(!(infoPtr->status & MC_SEL_LBUTDOWN)) return 0;
 +
 +  ht.cbSize = sizeof(MCHITTESTINFO);
 +  ht.pt.x = (short)LOWORD(lParam);
 +  ht.pt.y = (short)HIWORD(lParam);
 +
 +  hit = MONTHCAL_HitTest(infoPtr, &ht);
 +
 +  /* not on the calendar date numbers? bail out */
 +  TRACE("hit:%x\n",hit);
 +  if((hit & MCHT_CALENDARDATE) != MCHT_CALENDARDATE)
 +  {
 +    MONTHCAL_SetDayFocus(infoPtr, NULL);
 +    return 0;
 +  }
 +
 +  st_ht = ht.st;
 +
 +  /* if pointer is over focused day still there's nothing to do */
 +  if(!MONTHCAL_SetDayFocus(infoPtr, &ht.st)) return 0;
 +
 +  MONTHCAL_CalcPosFromDay(infoPtr, &ht.st, &r);
 +
 +  if(infoPtr->dwStyle & MCS_MULTISELECT) {
 +    SYSTEMTIME st[2];
 +
 +    MONTHCAL_GetSelRange(infoPtr, st);
 +
 +    /* If we're still at the first selected date and range is empty, return.
 +       If range isn't empty we should change range to a single firstSel */
 +    if(MONTHCAL_IsDateEqual(&infoPtr->firstSel, &st_ht) &&
 +       MONTHCAL_IsDateEqual(&st[0], &st[1])) goto done;
 +
 +    MONTHCAL_IsSelRangeValid(infoPtr, &st_ht, &infoPtr->firstSel, &st_ht);
 +
 +    st[0] = infoPtr->firstSel;
 +    /* we should overwrite timestamp here */
 +    MONTHCAL_CopyDate(&st_ht, &st[1]);
 +
 +    /* bounds will be swapped here if needed */
 +    MONTHCAL_SetSelRange(infoPtr, st);
 +
 +    return 0;
 +  }
 +
 +done:
 +
 +  /* FIXME: this should specify a rectangle containing only the days that changed
 +     using InvalidateRect */
 +  InvalidateRect(infoPtr->hwndSelf, NULL, FALSE);
 +
 +  return 0;
 +}
 +
 +
 +static LRESULT
 +MONTHCAL_Paint(MONTHCAL_INFO *infoPtr, HDC hdc_paint)
 +{
 +  HDC hdc;
 +  PAINTSTRUCT ps;
 +
 +  if (hdc_paint)
 +  {
 +    GetClientRect(infoPtr->hwndSelf, &ps.rcPaint);
 +    hdc = hdc_paint;
 +  }
 +  else
 +    hdc = BeginPaint(infoPtr->hwndSelf, &ps);
 +
 +  MONTHCAL_Refresh(infoPtr, hdc, &ps);
 +  if (!hdc_paint) EndPaint(infoPtr->hwndSelf, &ps);
 +  return 0;
 +}
 +
 +static LRESULT
 +MONTHCAL_EraseBkgnd(const MONTHCAL_INFO *infoPtr, HDC hdc)
 +{
 +  HBRUSH hbr;
 +  RECT rc;
 +
 +  if (!GetClipBox(hdc, &rc)) return FALSE;
 +
 +  /* fill background */
-   /* invalidate client area and erase background */
++  hbr = CreateSolidBrush (infoPtr->colors[MCSC_BACKGROUND]);
 +  FillRect(hdc, &rc, hbr);
 +  DeleteObject(hbr);
 +
 +  return TRUE;
 +}
 +
 +static LRESULT
 +MONTHCAL_PrintClient(MONTHCAL_INFO *infoPtr, HDC hdc, DWORD options)
 +{
 +  FIXME("Partial Stub: (hdc=%p options=0x%08x)\n", hdc, options);
 +
 +  if ((options & PRF_CHECKVISIBLE) && !IsWindowVisible(infoPtr->hwndSelf))
 +      return 0;
 +
 +  if (options & PRF_ERASEBKGND)
 +      MONTHCAL_EraseBkgnd(infoPtr, hdc);
 +
 +  if (options & PRF_CLIENT)
 +      MONTHCAL_Paint(infoPtr, hdc);
 +
 +  return 0;
 +}
 +
 +static LRESULT
 +MONTHCAL_SetFocus(const MONTHCAL_INFO *infoPtr)
 +{
 +  TRACE("\n");
 +
 +  InvalidateRect(infoPtr->hwndSelf, NULL, FALSE);
 +
 +  return 0;
 +}
 +
 +/* sets the size information */
 +static void MONTHCAL_UpdateSize(MONTHCAL_INFO *infoPtr)
 +{
 +  static const WCHAR O0W[] = { '0','0',0 };
 +  HDC hdc = GetDC(infoPtr->hwndSelf);
 +  RECT *title=&infoPtr->calendars[0].title;
 +  RECT *prev=&infoPtr->titlebtnprev;
 +  RECT *next=&infoPtr->titlebtnnext;
 +  RECT *titlemonth=&infoPtr->calendars[0].titlemonth;
 +  RECT *titleyear=&infoPtr->calendars[0].titleyear;
 +  RECT *wdays=&infoPtr->calendars[0].wdays;
 +  RECT *weeknumrect=&infoPtr->calendars[0].weeknums;
 +  RECT *days=&infoPtr->calendars[0].days;
 +  RECT *todayrect=&infoPtr->todayrect;
 +  SIZE size, sz;
 +  TEXTMETRICW tm;
 +  HFONT currentFont;
 +  INT xdiv, dx, dy, i;
 +  RECT rcClient;
 +  WCHAR buff[80];
 +
 +  GetClientRect(infoPtr->hwndSelf, &rcClient);
 +
 +  currentFont = SelectObject(hdc, infoPtr->hFont);
 +
 +  /* get the height and width of each day's text */
 +  GetTextMetricsW(hdc, &tm);
 +  infoPtr->textHeight = tm.tmHeight + tm.tmExternalLeading + tm.tmInternalLeading;
 +
 +  /* find largest abbreviated day name for current locale */
 +  size.cx = sz.cx = 0;
 +  for (i = 0; i < 7; i++)
 +  {
 +      if(GetLocaleInfoW(LOCALE_USER_DEFAULT, LOCALE_SABBREVDAYNAME1 + i,
 +                        buff, countof(buff)))
 +      {
 +          GetTextExtentPoint32W(hdc, buff, lstrlenW(buff), &sz);
 +          if (sz.cx > size.cx) size.cx = sz.cx;
 +      }
 +      else /* locale independent fallback on failure */
 +      {
 +          static const WCHAR SunW[] = { 'S','u','n',0 };
 +
 +          GetTextExtentPoint32W(hdc, SunW, lstrlenW(SunW), &size);
 +          break;
 +      }
 +  }
 +
 +  infoPtr->textWidth = size.cx + 2;
 +
 +  /* recalculate the height and width increments and offsets */
 +  GetTextExtentPoint32W(hdc, O0W, 2, &size);
 +
 +  xdiv = (infoPtr->dwStyle & MCS_WEEKNUMBERS) ? 8 : 7;
 +
 +  infoPtr->width_increment  = size.cx * 2 + 4;
 +  infoPtr->height_increment = infoPtr->textHeight;
 +
 +  /* calculate title area */
 +  title->top    = 0;
 +  title->bottom = 3 * infoPtr->height_increment / 2;
 +  title->left   = 0;
 +  title->right  = infoPtr->width_increment * xdiv;
 +
 +  /* set the dimensions of the next and previous buttons and center */
 +  /* the month text vertically */
 +  prev->top    = next->top    = title->top + 4;
 +  prev->bottom = next->bottom = title->bottom - 4;
 +  prev->left   = title->left + 4;
 +  prev->right  = prev->left + (title->bottom - title->top);
 +  next->right  = title->right - 4;
 +  next->left   = next->right - (title->bottom - title->top);
 +
 +  /* titlemonth->left and right change based upon the current month */
 +  /* and are recalculated in refresh as the current month may change */
 +  /* without the control being resized */
 +  titlemonth->top    = titleyear->top    = title->top    + (infoPtr->height_increment)/2;
 +  titlemonth->bottom = titleyear->bottom = title->bottom - (infoPtr->height_increment)/2;
 +
 +  /* setup the dimensions of the rectangle we draw the names of the */
 +  /* days of the week in */
 +  weeknumrect->left = 0;
 +
 +  if(infoPtr->dwStyle & MCS_WEEKNUMBERS)
 +    weeknumrect->right = prev->right;
 +  else
 +    weeknumrect->right = weeknumrect->left;
 +
 +  wdays->left   = days->left   = weeknumrect->right;
 +  wdays->right  = days->right  = wdays->left + 7 * infoPtr->width_increment;
 +  wdays->top    = title->bottom;
 +  wdays->bottom = wdays->top + infoPtr->height_increment;
 +
 +  days->top    = weeknumrect->top = wdays->bottom;
 +  days->bottom = weeknumrect->bottom = days->top + 6 * infoPtr->height_increment;
 +
 +  todayrect->left   = 0;
 +  todayrect->right  = title->right;
 +  todayrect->top    = days->bottom;
 +  todayrect->bottom = days->bottom + infoPtr->height_increment;
 +
 +  /* offset all rectangles to center in client area */
 +  dx = (rcClient.right  - title->right) / 2;
 +  dy = (rcClient.bottom - todayrect->bottom) / 2;
 +
 +  /* if calendar doesn't fit client area show it at left/top bounds */
 +  if (title->left + dx < 0) dx = 0;
 +  if (title->top  + dy < 0) dy = 0;
 +
 +  if (dx != 0 || dy != 0)
 +  {
 +    OffsetRect(title, dx, dy);
 +    OffsetRect(prev,  dx, dy);
 +    OffsetRect(next,  dx, dy);
 +    OffsetRect(titlemonth, dx, dy);
 +    OffsetRect(titleyear, dx, dy);
 +    OffsetRect(wdays, dx, dy);
 +    OffsetRect(weeknumrect, dx, dy);
 +    OffsetRect(days, dx, dy);
 +    OffsetRect(todayrect, dx, dy);
 +  }
 +
 +  TRACE("dx=%d dy=%d client[%s] title[%s] wdays[%s] days[%s] today[%s]\n",
 +      infoPtr->width_increment,infoPtr->height_increment,
 +        wine_dbgstr_rect(&rcClient),
 +        wine_dbgstr_rect(title),
 +        wine_dbgstr_rect(wdays),
 +        wine_dbgstr_rect(days),
 +        wine_dbgstr_rect(todayrect));
 +
 +  /* restore the originally selected font */
 +  SelectObject(hdc, currentFont);
 +
 +  ReleaseDC(infoPtr->hwndSelf, hdc);
 +}
 +
 +static LRESULT MONTHCAL_Size(MONTHCAL_INFO *infoPtr, int Width, int Height)
 +{
 +  TRACE("(width=%d, height=%d)\n", Width, Height);
 +
 +  MONTHCAL_UpdateSize(infoPtr);
-   infoPtr->titlebk       = comctl32_color.clrActiveCaption;
-   infoPtr->titletxt      = comctl32_color.clrWindow;
-   infoPtr->monthbk       = comctl32_color.clrWindow;
-   infoPtr->trailingtxt   = comctl32_color.clrGrayText;
-   infoPtr->bk            = comctl32_color.clrWindow;
-   infoPtr->txt                 = comctl32_color.clrWindowText;
 +  InvalidateRect(infoPtr->hwndSelf, NULL, TRUE);
 +
 +  return 0;
 +}
 +
 +static LRESULT MONTHCAL_GetFont(const MONTHCAL_INFO *infoPtr)
 +{
 +    return (LRESULT)infoPtr->hFont;
 +}
 +
 +static LRESULT MONTHCAL_SetFont(MONTHCAL_INFO *infoPtr, HFONT hFont, BOOL redraw)
 +{
 +    HFONT hOldFont;
 +    LOGFONTW lf;
 +
 +    if (!hFont) return 0;
 +
 +    hOldFont = infoPtr->hFont;
 +    infoPtr->hFont = hFont;
 +
 +    GetObjectW(infoPtr->hFont, sizeof(lf), &lf);
 +    lf.lfWeight = FW_BOLD;
 +    infoPtr->hBoldFont = CreateFontIndirectW(&lf);
 +
 +    MONTHCAL_UpdateSize(infoPtr);
 +
 +    if (redraw)
 +        InvalidateRect(infoPtr->hwndSelf, NULL, FALSE);
 +
 +    return (LRESULT)hOldFont;
 +}
 +
 +/* update theme after a WM_THEMECHANGED message */
 +static LRESULT theme_changed (const MONTHCAL_INFO* infoPtr)
 +{
 +    HTHEME theme = GetWindowTheme (infoPtr->hwndSelf);
 +    CloseThemeData (theme);
 +    OpenThemeData (infoPtr->hwndSelf, themeClass);
 +    return 0;
 +}
 +
 +static INT MONTHCAL_StyleChanged(MONTHCAL_INFO *infoPtr, WPARAM wStyleType,
 +                                 const STYLESTRUCT *lpss)
 +{
 +    TRACE("(styletype=%lx, styleOld=0x%08x, styleNew=0x%08x)\n",
 +          wStyleType, lpss->styleOld, lpss->styleNew);
 +
 +    if (wStyleType != GWL_STYLE) return 0;
 +
 +    infoPtr->dwStyle = lpss->styleNew;
 +
 +    /* make room for week numbers */
 +    if ((lpss->styleNew ^ lpss->styleOld) & MCS_WEEKNUMBERS)
 +        MONTHCAL_UpdateSize(infoPtr);
 +
 +    return 0;
 +}
 +
 +static INT MONTHCAL_StyleChanging(MONTHCAL_INFO *infoPtr, WPARAM wStyleType,
 +                                  STYLESTRUCT *lpss)
 +{
 +    TRACE("(styletype=%lx, styleOld=0x%08x, styleNew=0x%08x)\n",
 +          wStyleType, lpss->styleOld, lpss->styleNew);
 +
 +    /* block MCS_MULTISELECT change */
 +    if ((lpss->styleNew ^ lpss->styleOld) & MCS_MULTISELECT)
 +    {
 +        if (lpss->styleOld & MCS_MULTISELECT)
 +            lpss->styleNew |= MCS_MULTISELECT;
 +        else
 +            lpss->styleNew &= ~MCS_MULTISELECT;
 +    }
 +
 +    return 0;
 +}
 +
 +/* FIXME: check whether dateMin/dateMax need to be adjusted. */
 +static LRESULT
 +MONTHCAL_Create(HWND hwnd, LPCREATESTRUCTW lpcs)
 +{
 +  MONTHCAL_INFO *infoPtr;
 +
 +  /* allocate memory for info structure */
 +  infoPtr = Alloc(sizeof(MONTHCAL_INFO));
 +  SetWindowLongPtrW(hwnd, 0, (DWORD_PTR)infoPtr);
 +
 +  if (infoPtr == NULL) {
 +    ERR("could not allocate info memory!\n");
 +    return 0;
 +  }
 +
 +  infoPtr->hwndSelf = hwnd;
 +  infoPtr->hwndNotify = lpcs->hwndParent;
 +  infoPtr->dwStyle  = GetWindowLongW(hwnd, GWL_STYLE);
 +  infoPtr->calendars = Alloc(sizeof(CALENDAR_INFO));
 +  if (!infoPtr->calendars) goto fail;
 +
 +  infoPtr->cal_num = 1;
 +
 +  MONTHCAL_SetFont(infoPtr, GetStockObject(DEFAULT_GUI_FONT), FALSE);
 +
 +  /* initialize info structure */
 +  /* FIXME: calculate systemtime ->> localtime(substract timezoneinfo) */
 +
 +  GetLocalTime(&infoPtr->todaysDate);
 +  MONTHCAL_SetFirstDayOfWeek(infoPtr, -1);
 +
 +  infoPtr->maxSelCount   = (infoPtr->dwStyle & MCS_MULTISELECT) ? 7 : 1;
 +  infoPtr->monthRange    = 3;
 +
 +  infoPtr->monthdayState = Alloc(infoPtr->monthRange * sizeof(MONTHDAYSTATE));
 +  if (!infoPtr->monthdayState) goto fail;
 +
-   infoPtr->curSel = infoPtr->todaysDate;
++  infoPtr->colors[MCSC_BACKGROUND]   = comctl32_color.clrWindow;
++  infoPtr->colors[MCSC_TEXT]         = comctl32_color.clrWindowText;
++  infoPtr->colors[MCSC_TITLEBK]      = comctl32_color.clrActiveCaption;
++  infoPtr->colors[MCSC_TITLETEXT]    = comctl32_color.clrWindow;
++  infoPtr->colors[MCSC_MONTHBK]      = comctl32_color.clrWindow;
++  infoPtr->colors[MCSC_TRAILINGTEXT] = comctl32_color.clrGrayText;
 +
 +  infoPtr->minSel = infoPtr->todaysDate;
 +  infoPtr->maxSel = infoPtr->todaysDate;
-     if (hdr->hwndFrom == infoPtr->hWndYearUpDown)
 +  infoPtr->calendars[0].month = infoPtr->todaysDate;
 +  infoPtr->isUnicode = TRUE;
 +
 +  /* call MONTHCAL_UpdateSize to set all of the dimensions */
 +  /* of the control */
 +  MONTHCAL_UpdateSize(infoPtr);
 +
 +  /* today auto update timer, to be freed only on control destruction */
 +  SetTimer(infoPtr->hwndSelf, MC_TODAYUPDATETIMER, MC_TODAYUPDATEDELAY, 0);
 +
 +  OpenThemeData (infoPtr->hwndSelf, themeClass);
 +
 +  return 0;
 +
 +fail:
 +  Free(infoPtr->monthdayState);
 +  Free(infoPtr->calendars);
 +  Free(infoPtr);
 +  return 0;
 +}
 +
 +static LRESULT
 +MONTHCAL_Destroy(MONTHCAL_INFO *infoPtr)
 +{
 +  /* free month calendar info data */
 +  Free(infoPtr->monthdayState);
 +  Free(infoPtr->calendars);
 +  SetWindowLongPtrW(infoPtr->hwndSelf, 0, 0);
 +
 +  CloseThemeData (GetWindowTheme (infoPtr->hwndSelf));
 +  
 +  Free(infoPtr);
 +  return 0;
 +}
 +
 +/*
 + * Handler for WM_NOTIFY messages
 + */
 +static LRESULT
 +MONTHCAL_Notify(MONTHCAL_INFO *infoPtr, NMHDR *hdr)
 +{
 +  /* notification from year edit updown */
 +  if (hdr->code == UDN_DELTAPOS)
 +  {
 +    NMUPDOWN *nmud = (NMUPDOWN*)hdr;
 +
-       if ((nmud->iDelta + nmud->iPos) != infoPtr->curSel.wYear)
-       {
-         SYSTEMTIME new_date = infoPtr->curSel;
-         new_date.wYear = nmud->iDelta + nmud->iPos;
-         MONTHCAL_SetCurSel(infoPtr, &new_date);
-       }
++    if (hdr->hwndFrom == infoPtr->hWndYearUpDown && nmud->iDelta)
 +    {
 +      /* year value limits are set up explicitly after updown creation */
-   MONTHCAL_INFO *infoPtr;
++      MONTHCAL_Scroll(infoPtr, 12 * nmud->iDelta);
++      MONTHCAL_NotifyDayState(infoPtr);
++      MONTHCAL_NotifySelectionChange(infoPtr);
 +    }
 +  }
 +  return 0;
 +}
 +
 +static inline BOOL
 +MONTHCAL_SetUnicodeFormat(MONTHCAL_INFO *infoPtr, BOOL isUnicode)
 +{
 +  BOOL prev = infoPtr->isUnicode;
 +  infoPtr->isUnicode = isUnicode;
 +  return prev;
 +}
 +
 +static inline BOOL
 +MONTHCAL_GetUnicodeFormat(const MONTHCAL_INFO *infoPtr)
 +{
 +  return infoPtr->isUnicode;
 +}
 +
 +static LRESULT WINAPI
 +MONTHCAL_WindowProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
 +{
-   infoPtr = MONTHCAL_GetInfoPtr(hwnd);
++  MONTHCAL_INFO *infoPtr = (MONTHCAL_INFO *)GetWindowLongPtrW(hwnd, 0);
 +
 +  TRACE("hwnd=%p msg=%x wparam=%lx lparam=%lx\n", hwnd, uMsg, wParam, lParam);
 +
 +  if (!infoPtr && (uMsg != WM_CREATE))
 +    return DefWindowProcW(hwnd, uMsg, wParam, lParam);
 +  switch(uMsg)
 +  {
 +  case MCM_GETCURSEL:
 +    return MONTHCAL_GetCurSel(infoPtr, (LPSYSTEMTIME)lParam);
 +
 +  case MCM_SETCURSEL:
 +    return MONTHCAL_SetCurSel(infoPtr, (LPSYSTEMTIME)lParam);
 +
 +  case MCM_GETMAXSELCOUNT:
 +    return MONTHCAL_GetMaxSelCount(infoPtr);
 +
 +  case MCM_SETMAXSELCOUNT:
 +    return MONTHCAL_SetMaxSelCount(infoPtr, wParam);
 +
 +  case MCM_GETSELRANGE:
 +    return MONTHCAL_GetSelRange(infoPtr, (LPSYSTEMTIME)lParam);
 +
 +  case MCM_SETSELRANGE:
 +    return MONTHCAL_SetSelRange(infoPtr, (LPSYSTEMTIME)lParam);
 +
 +  case MCM_GETMONTHRANGE:
 +    return MONTHCAL_GetMonthRange(infoPtr, wParam, (SYSTEMTIME*)lParam);
 +
 +  case MCM_SETDAYSTATE:
 +    return MONTHCAL_SetDayState(infoPtr, (INT)wParam, (LPMONTHDAYSTATE)lParam);
 +
 +  case MCM_GETMINREQRECT:
 +    return MONTHCAL_GetMinReqRect(infoPtr, (LPRECT)lParam);
 +
 +  case MCM_GETCOLOR:
 +    return MONTHCAL_GetColor(infoPtr, wParam);
 +
 +  case MCM_SETCOLOR:
 +    return MONTHCAL_SetColor(infoPtr, wParam, (COLORREF)lParam);
 +
 +  case MCM_GETTODAY:
 +    return MONTHCAL_GetToday(infoPtr, (LPSYSTEMTIME)lParam);
 +
 +  case MCM_SETTODAY:
 +    return MONTHCAL_SetToday(infoPtr, (LPSYSTEMTIME)lParam);
 +
 +  case MCM_HITTEST:
 +    return MONTHCAL_HitTest(infoPtr, (PMCHITTESTINFO)lParam);
 +
 +  case MCM_GETFIRSTDAYOFWEEK:
 +    return MONTHCAL_GetFirstDayOfWeek(infoPtr);
 +
 +  case MCM_SETFIRSTDAYOFWEEK:
 +    return MONTHCAL_SetFirstDayOfWeek(infoPtr, (INT)lParam);
 +
 +  case MCM_GETRANGE:
 +    return MONTHCAL_GetRange(infoPtr, (LPSYSTEMTIME)lParam);
 +
 +  case MCM_SETRANGE:
 +    return MONTHCAL_SetRange(infoPtr, (SHORT)wParam, (LPSYSTEMTIME)lParam);
 +
 +  case MCM_GETMONTHDELTA:
 +    return MONTHCAL_GetMonthDelta(infoPtr);
 +
 +  case MCM_SETMONTHDELTA:
 +    return MONTHCAL_SetMonthDelta(infoPtr, wParam);
 +
 +  case MCM_GETMAXTODAYWIDTH:
 +    return MONTHCAL_GetMaxTodayWidth(infoPtr);
 +
 +  case MCM_SETUNICODEFORMAT:
 +    return MONTHCAL_SetUnicodeFormat(infoPtr, (BOOL)wParam);
 +
 +  case MCM_GETUNICODEFORMAT:
 +    return MONTHCAL_GetUnicodeFormat(infoPtr);
 +
 +  case WM_GETDLGCODE:
 +    return DLGC_WANTARROWS | DLGC_WANTCHARS;
 +
 +  case WM_RBUTTONUP:
 +    return MONTHCAL_RButtonUp(infoPtr, lParam);
 +
 +  case WM_LBUTTONDOWN:
 +    return MONTHCAL_LButtonDown(infoPtr, lParam);
 +
 +  case WM_MOUSEMOVE:
 +    return MONTHCAL_MouseMove(infoPtr, lParam);
 +
 +  case WM_LBUTTONUP:
 +    return MONTHCAL_LButtonUp(infoPtr, lParam);
 +
 +  case WM_PAINT:
 +    return MONTHCAL_Paint(infoPtr, (HDC)wParam);
 +
 +  case WM_PRINTCLIENT:
 +    return MONTHCAL_PrintClient(infoPtr, (HDC)wParam, (DWORD)lParam);
 +
 +  case WM_ERASEBKGND:
 +    return MONTHCAL_EraseBkgnd(infoPtr, (HDC)wParam);
 +
 +  case WM_SETFOCUS:
 +    return MONTHCAL_SetFocus(infoPtr);
 +
 +  case WM_SIZE:
 +    return MONTHCAL_Size(infoPtr, (SHORT)LOWORD(lParam), (SHORT)HIWORD(lParam));
 +
 +  case WM_NOTIFY:
 +    return MONTHCAL_Notify(infoPtr, (NMHDR*)lParam);
 +
 +  case WM_CREATE:
 +    return MONTHCAL_Create(hwnd, (LPCREATESTRUCTW)lParam);
 +
 +  case WM_SETFONT:
 +    return MONTHCAL_SetFont(infoPtr, (HFONT)wParam, (BOOL)lParam);
 +
 +  case WM_GETFONT:
 +    return MONTHCAL_GetFont(infoPtr);
 +
 +  case WM_TIMER:
 +    return MONTHCAL_Timer(infoPtr, wParam);
 +    
 +  case WM_THEMECHANGED:
 +    return theme_changed (infoPtr);
 +
 +  case WM_DESTROY:
 +    return MONTHCAL_Destroy(infoPtr);
 +
 +  case WM_SYSCOLORCHANGE:
 +    COMCTL32_RefreshSysColors();
 +    return 0;
 +
 +  case WM_STYLECHANGED:
 +    return MONTHCAL_StyleChanged(infoPtr, wParam, (LPSTYLESTRUCT)lParam);
 +
 +  case WM_STYLECHANGING:
 +    return MONTHCAL_StyleChanging(infoPtr, wParam, (LPSTYLESTRUCT)lParam);
 +
 +  default:
 +    if ((uMsg >= WM_USER) && (uMsg < WM_APP) && !COMCTL32_IsReflectedMessage(uMsg))
 +      ERR( "unknown msg %04x wp=%08lx lp=%08lx\n", uMsg, wParam, lParam);
 +    return DefWindowProcW(hwnd, uMsg, wParam, lParam);
 +  }
 +}
 +
 +
 +void
 +MONTHCAL_Register(void)
 +{
 +  WNDCLASSW wndClass;
 +
 +  ZeroMemory(&wndClass, sizeof(WNDCLASSW));
 +  wndClass.style         = CS_GLOBALCLASS;
 +  wndClass.lpfnWndProc   = MONTHCAL_WindowProc;
 +  wndClass.cbClsExtra    = 0;
 +  wndClass.cbWndExtra    = sizeof(MONTHCAL_INFO *);
 +  wndClass.hCursor       = LoadCursorW(0, (LPWSTR)IDC_ARROW);
 +  wndClass.hbrBackground = (HBRUSH)(COLOR_WINDOW + 1);
 +  wndClass.lpszClassName = MONTHCAL_CLASSW;
 +
 +  RegisterClassW(&wndClass);
 +}
 +
 +
 +void
 +MONTHCAL_Unregister(void)
 +{
 +    UnregisterClassW(MONTHCAL_CLASSW, NULL);
 +}
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
Simple merge
Simple merge
Simple merge
Simple merge
Simple merge
Simple merge
Simple merge
Simple merge
Simple merge
index e8adc8e,0000000..c0a8bf5
mode 100644,000000..100644
--- /dev/null
@@@ -1,1456 -1,0 +1,1456 @@@<