diff --git a/reactos/lib/comctl32/Makefile.in b/reactos/lib/comctl32/Makefile.in deleted file mode 100644 index d83c626b0d2..00000000000 --- a/reactos/lib/comctl32/Makefile.in +++ /dev/null @@ -1,64 +0,0 @@ -EXTRADEFS = -D_COMCTL32_ -TOPSRCDIR = @top_srcdir@ -TOPOBJDIR = ../.. -SRCDIR = @srcdir@ -VPATH = @srcdir@ -MODULE = comctl32.dll -IMPORTS = user32 gdi32 advapi32 kernel32 -DELAYIMPORTS = winmm -EXTRALIBS = $(LIBUNICODE) - -C_SRCS = \ - animate.c \ - comboex.c \ - comctl32undoc.c \ - commctrl.c \ - datetime.c \ - draglist.c \ - flatsb.c \ - header.c \ - hotkey.c \ - imagelist.c \ - ipaddress.c \ - listview.c \ - monthcal.c \ - nativefont.c \ - pager.c \ - progress.c \ - propsheet.c \ - rebar.c \ - smoothscroll.c \ - string.c \ - status.c \ - syslink.c \ - tab.c \ - toolbar.c \ - tooltips.c \ - trackbar.c \ - treeview.c \ - updown.c - -RC_SRCS = rsrc.rc -RC_BINSRC = rsrc.rc -RC_BINARIES = \ - idb_hist_large.bmp \ - idb_hist_small.bmp \ - idb_std_large.bmp \ - idb_std_small.bmp \ - idb_view_large.bmp \ - idb_view_small.bmp \ - idc_copy.cur \ - idc_divider.cur \ - idc_divideropen.cur \ - idc_movebutton.cur \ - idi_dragarrow.ico \ - idi_tt_error_sm.ico \ - idi_tt_info_sm.ico \ - idi_tt_warn_sm.ico \ - idt_check.bmp - -SUBDIRS = tests - -@MAKE_DLL_RULES@ - -### Dependencies: diff --git a/reactos/lib/comctl32/Makefile.ros-template b/reactos/lib/comctl32/Makefile.ros-template deleted file mode 100644 index ccdfac46e5b..00000000000 --- a/reactos/lib/comctl32/Makefile.ros-template +++ /dev/null @@ -1,21 +0,0 @@ -# $Id: Makefile.ros-template,v 1.4 2004/12/03 23:37:40 blight Exp $ - -TARGET_NAME = comctl32 - -TARGET_OBJECTS = @C_SRCS@ - -TARGET_CFLAGS = @EXTRADEFS@ -D__REACTOS__ - -TARGET_SDKLIBS = @IMPORTS@ winmm.a wine.a wine_uuid.a ntdll.a - -TARGET_BASE = $(TARGET_BASE_LIB_COMCTL32) - -TARGET_RC_SRCS = @RC_SRCS@ -TARGET_RC_BINSRC = @RC_BINSRC@ -TARGET_RC_BINARIES = @RC_BINARIES@ - -default: all - -DEP_OBJECTS = $(TARGET_OBJECTS) - -include $(TOOLS_PATH)/depend.mk diff --git a/reactos/lib/comctl32/animate.c b/reactos/lib/comctl32/animate.c deleted file mode 100644 index 374b3b1111c..00000000000 --- a/reactos/lib/comctl32/animate.c +++ /dev/null @@ -1,972 +0,0 @@ -/* -*- tab-width: 8; c-basic-offset: 4 -*- */ -/* - * Animation control - * - * Copyright 1998, 1999 Eric Kohl - * 1999 Eric Pouech - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2.1 of the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - * - * NOTES - * I will only improve this control once in a while. - * Eric - * - * TODO: - * - check for the 'rec ' list in some AVI files - * - concurrent access to infoPtr - */ - -#define COM_NO_WINDOWS_H -#include -#include -#include "windef.h" -#include "winbase.h" -#include "wingdi.h" -#include "winuser.h" -#include "winnls.h" -#include "commctrl.h" -#include "vfw.h" -#include "mmsystem.h" -#include "comctl32.h" -#include "wine/debug.h" - -WINE_DEFAULT_DEBUG_CHANNEL(animate); - -static struct { - HMODULE hModule; - HIC (WINAPI *fnICOpen)(DWORD, DWORD, UINT); - LRESULT (WINAPI *fnICClose)(HIC); - LRESULT (WINAPI *fnICSendMessage)(HIC, UINT, DWORD, DWORD); - DWORD (WINAPIV *fnICDecompress)(HIC,DWORD,LPBITMAPINFOHEADER,LPVOID,LPBITMAPINFOHEADER,LPVOID); -} fnIC; - -typedef struct -{ - /* reference to input stream (file or resource) */ - HGLOBAL hRes; - HMMIO hMMio; /* handle to mmio stream */ - HWND hwndSelf; - HWND hwndNotify; - /* information on the loaded AVI file */ - MainAVIHeader mah; - AVIStreamHeader ash; - LPBITMAPINFOHEADER inbih; - LPDWORD lpIndex; - /* data for the decompressor */ - HIC hic; - LPBITMAPINFOHEADER outbih; - LPVOID indata; - LPVOID outdata; - /* data for the background mechanism */ - CRITICAL_SECTION cs; - HANDLE hStopEvent; - HANDLE hThread; - DWORD threadId; - UINT uTimer; - /* data for playing the file */ - int nFromFrame; - int nToFrame; - int nLoop; - int currFrame; - /* tranparency info*/ - COLORREF transparentColor; - HBRUSH hbrushBG; - HBITMAP hbmPrevFrame; -} ANIMATE_INFO; - -#define ANIMATE_GetInfoPtr(hWnd) ((ANIMATE_INFO *)GetWindowLongPtrW(hWnd, 0)) -#define ANIMATE_COLOR_NONE 0xffffffff - -static void ANIMATE_Notify(ANIMATE_INFO* infoPtr, UINT notif) -{ - SendMessageA(infoPtr->hwndNotify, WM_COMMAND, - MAKEWPARAM(GetDlgCtrlID(infoPtr->hwndSelf), notif), - (LPARAM)infoPtr->hwndSelf); -} - -static BOOL ANIMATE_LoadResA(ANIMATE_INFO *infoPtr, HINSTANCE hInst, LPSTR lpName) -{ - HRSRC hrsrc; - MMIOINFO mminfo; - LPVOID lpAvi; - - hrsrc = FindResourceA(hInst, lpName, "AVI"); - if (!hrsrc) - return FALSE; - - infoPtr->hRes = LoadResource(hInst, hrsrc); - if (!infoPtr->hRes) - return FALSE; - - lpAvi = LockResource(infoPtr->hRes); - if (!lpAvi) - return FALSE; - - memset(&mminfo, 0, sizeof(mminfo)); - mminfo.fccIOProc = FOURCC_MEM; - mminfo.pchBuffer = (LPSTR)lpAvi; - mminfo.cchBuffer = SizeofResource(hInst, hrsrc); - infoPtr->hMMio = mmioOpenA(NULL, &mminfo, MMIO_READ); - if (!infoPtr->hMMio) { - FreeResource(infoPtr->hRes); - return FALSE; - } - - return TRUE; -} - - -static BOOL ANIMATE_LoadFileA(ANIMATE_INFO *infoPtr, LPSTR lpName) -{ - infoPtr->hMMio = mmioOpenA((LPSTR)lpName, NULL, - MMIO_ALLOCBUF | MMIO_READ | MMIO_DENYWRITE); - - if (!infoPtr->hMMio) - return FALSE; - - return TRUE; -} - - -static LRESULT ANIMATE_DoStop(ANIMATE_INFO *infoPtr) -{ - EnterCriticalSection(&infoPtr->cs); - - /* should stop playing */ - if (infoPtr->hThread) - { - HANDLE handle = infoPtr->hThread; - - TRACE("stopping animation thread\n"); - infoPtr->hThread = 0; - SetEvent( infoPtr->hStopEvent ); - - if (infoPtr->threadId != GetCurrentThreadId()) - { - LeaveCriticalSection(&infoPtr->cs); /* leave it a chance to run */ - WaitForSingleObject( handle, INFINITE ); - TRACE("animation thread stopped\n"); - EnterCriticalSection(&infoPtr->cs); - } - - CloseHandle( handle ); - CloseHandle( infoPtr->hStopEvent ); - infoPtr->hStopEvent = 0; - } - if (infoPtr->uTimer) { - KillTimer(infoPtr->hwndSelf, infoPtr->uTimer); - infoPtr->uTimer = 0; - } - - LeaveCriticalSection(&infoPtr->cs); - - ANIMATE_Notify(infoPtr, ACN_STOP); - - return TRUE; -} - - -static void ANIMATE_Free(ANIMATE_INFO *infoPtr) -{ - if (infoPtr->hMMio) { - ANIMATE_DoStop(infoPtr); - mmioClose(infoPtr->hMMio, 0); - if (infoPtr->hRes) { - FreeResource(infoPtr->hRes); - infoPtr->hRes = 0; - } - if (infoPtr->lpIndex) { - HeapFree(GetProcessHeap(), 0, infoPtr->lpIndex); - infoPtr->lpIndex = NULL; - } - if (infoPtr->hic) { - fnIC.fnICClose(infoPtr->hic); - infoPtr->hic = 0; - } - if (infoPtr->inbih) { - HeapFree(GetProcessHeap(), 0, infoPtr->inbih); - infoPtr->inbih = NULL; - } - if (infoPtr->outbih) { - HeapFree(GetProcessHeap(), 0, infoPtr->outbih); - infoPtr->outbih = NULL; - } - if( infoPtr->indata ) - { - HeapFree(GetProcessHeap(), 0, infoPtr->indata); - infoPtr->indata = NULL; - } - if( infoPtr->outdata ) - { - HeapFree(GetProcessHeap(), 0, infoPtr->outdata); - infoPtr->outdata = NULL; - } - if( infoPtr->hbmPrevFrame ) - { - DeleteObject(infoPtr->hbmPrevFrame); - infoPtr->hbmPrevFrame = 0; - } - infoPtr->indata = infoPtr->outdata = NULL; - infoPtr->hwndSelf = 0; - infoPtr->hMMio = 0; - - memset(&infoPtr->mah, 0, sizeof(infoPtr->mah)); - memset(&infoPtr->ash, 0, sizeof(infoPtr->ash)); - infoPtr->nFromFrame = infoPtr->nToFrame = infoPtr->nLoop = infoPtr->currFrame = 0; - } - infoPtr->transparentColor = ANIMATE_COLOR_NONE; -} - -static void ANIMATE_TransparentBlt(ANIMATE_INFO* infoPtr, HDC hdcDest, HDC hdcSource) -{ - HDC hdcMask; - HBITMAP hbmMask; - HBITMAP hbmOld; - - /* create a transparency mask */ - hdcMask = CreateCompatibleDC(hdcDest); - hbmMask = CreateBitmap(infoPtr->inbih->biWidth, infoPtr->inbih->biHeight, 1,1,NULL); - hbmOld = SelectObject(hdcMask, hbmMask); - - SetBkColor(hdcSource,infoPtr->transparentColor); - BitBlt(hdcMask,0,0,infoPtr->inbih->biWidth, infoPtr->inbih->biHeight,hdcSource,0,0,SRCCOPY); - - /* mask the source bitmap */ - SetBkColor(hdcSource, RGB(0,0,0)); - SetTextColor(hdcSource, RGB(255,255,255)); - BitBlt(hdcSource, 0, 0, infoPtr->inbih->biWidth, infoPtr->inbih->biHeight, hdcMask, 0, 0, SRCAND); - - /* mask the destination bitmap */ - SetBkColor(hdcDest, RGB(255,255,255)); - SetTextColor(hdcDest, RGB(0,0,0)); - BitBlt(hdcDest, 0, 0, infoPtr->inbih->biWidth, infoPtr->inbih->biHeight, hdcMask, 0, 0, SRCAND); - - /* combine source and destination */ - BitBlt(hdcDest,0,0,infoPtr->inbih->biWidth, infoPtr->inbih->biHeight,hdcSource,0,0,SRCPAINT); - - SelectObject(hdcMask, hbmOld); - DeleteObject(hbmMask); - DeleteDC(hdcMask); -} - -static LRESULT ANIMATE_PaintFrame(ANIMATE_INFO* infoPtr, HDC hDC) -{ - void* pBitmapData = NULL; - LPBITMAPINFO pBitmapInfo = NULL; - - HDC hdcMem; - HBITMAP hbmOld; - - int nOffsetX = 0; - int nOffsetY = 0; - - int nWidth; - int nHeight; - - if (!hDC || !infoPtr->inbih) - return TRUE; - - if (infoPtr->hic ) - { - pBitmapData = infoPtr->outdata; - pBitmapInfo = (LPBITMAPINFO)infoPtr->outbih; - - nWidth = infoPtr->outbih->biWidth; - nHeight = infoPtr->outbih->biHeight; - } else - { - pBitmapData = infoPtr->indata; - pBitmapInfo = (LPBITMAPINFO)infoPtr->inbih; - - nWidth = infoPtr->inbih->biWidth; - nHeight = infoPtr->inbih->biHeight; - } - - if(!infoPtr->hbmPrevFrame) - { - infoPtr->hbmPrevFrame=CreateCompatibleBitmap(hDC, nWidth,nHeight ); - } - - SetDIBits(hDC, infoPtr->hbmPrevFrame, 0, nHeight, pBitmapData, (LPBITMAPINFO)pBitmapInfo, DIB_RGB_COLORS); - - hdcMem = CreateCompatibleDC(hDC); - hbmOld = SelectObject(hdcMem, infoPtr->hbmPrevFrame); - - /* - * we need to get the transparent color even without ACS_TRANSPARENT, - * because the style can be changed later on and the color should always - * be obtained in the first frame - */ - if(infoPtr->transparentColor == ANIMATE_COLOR_NONE) - { - infoPtr->transparentColor = GetPixel(hdcMem,0,0); - } - - if(GetWindowLongA(infoPtr->hwndSelf, GWL_STYLE) & ACS_TRANSPARENT) - { - HDC hdcFinal = CreateCompatibleDC(hDC); - HBITMAP hbmFinal = CreateCompatibleBitmap(hDC,nWidth, nHeight); - HBITMAP hbmOld2 = SelectObject(hdcFinal, hbmFinal); - RECT rect; - - rect.left = 0; - rect.top = 0; - rect.right = nWidth; - rect.bottom = nHeight; - - if(!infoPtr->hbrushBG) - infoPtr->hbrushBG = GetCurrentObject(hDC, OBJ_BRUSH); - - FillRect(hdcFinal, &rect, infoPtr->hbrushBG); - ANIMATE_TransparentBlt(infoPtr, hdcFinal, hdcMem); - - SelectObject(hdcFinal, hbmOld2); - SelectObject(hdcMem, hbmFinal); - DeleteDC(hdcFinal); - DeleteObject(infoPtr->hbmPrevFrame); - infoPtr->hbmPrevFrame = hbmFinal; - } - - if (GetWindowLongA(infoPtr->hwndSelf, GWL_STYLE) & ACS_CENTER) - { - RECT rect; - - GetWindowRect(infoPtr->hwndSelf, &rect); - nOffsetX = ((rect.right - rect.left) - nWidth)/2; - nOffsetY = ((rect.bottom - rect.top) - nHeight)/2; - } - BitBlt(hDC, nOffsetX, nOffsetY, nWidth, nHeight, hdcMem, 0, 0, SRCCOPY); - - SelectObject(hdcMem, hbmOld); - DeleteDC(hdcMem); - return TRUE; -} - -static LRESULT ANIMATE_DrawFrame(ANIMATE_INFO* infoPtr) -{ - HDC hDC; - - TRACE("Drawing frame %d (loop %d)\n", infoPtr->currFrame, infoPtr->nLoop); - - EnterCriticalSection(&infoPtr->cs); - - mmioSeek(infoPtr->hMMio, infoPtr->lpIndex[infoPtr->currFrame], SEEK_SET); - mmioRead(infoPtr->hMMio, infoPtr->indata, infoPtr->ash.dwSuggestedBufferSize); - - if (infoPtr->hic && - fnIC.fnICDecompress(infoPtr->hic, 0, infoPtr->inbih, infoPtr->indata, - infoPtr->outbih, infoPtr->outdata) != ICERR_OK) { - LeaveCriticalSection(&infoPtr->cs); - WARN("Decompression error\n"); - return FALSE; - } - - if ((hDC = GetDC(infoPtr->hwndSelf)) != 0) { - ANIMATE_PaintFrame(infoPtr, hDC); - ReleaseDC(infoPtr->hwndSelf, hDC); - } - - if (infoPtr->currFrame++ >= infoPtr->nToFrame) { - infoPtr->currFrame = infoPtr->nFromFrame; - if (infoPtr->nLoop != -1) { - if (--infoPtr->nLoop == 0) { - ANIMATE_DoStop(infoPtr); - } - } - } - LeaveCriticalSection(&infoPtr->cs); - - return TRUE; -} - -static DWORD CALLBACK ANIMATE_AnimationThread(LPVOID ptr_) -{ - ANIMATE_INFO* infoPtr = (ANIMATE_INFO*)ptr_; - HANDLE event; - DWORD timeout; - - while(1) - { - EnterCriticalSection(&infoPtr->cs); - ANIMATE_DrawFrame(infoPtr); - timeout = infoPtr->mah.dwMicroSecPerFrame; - event = infoPtr->hStopEvent; - LeaveCriticalSection(&infoPtr->cs); - - /* time is in microseconds, we should convert it to milliseconds */ - if ((event == 0) || WaitForSingleObject( event, (timeout+500)/1000) == WAIT_OBJECT_0) - break; - } - return TRUE; -} - -static LRESULT ANIMATE_Play(HWND hWnd, WPARAM wParam, LPARAM lParam) -{ - ANIMATE_INFO *infoPtr = ANIMATE_GetInfoPtr(hWnd); - - /* nothing opened */ - if (!infoPtr->hMMio) - return FALSE; - - if (infoPtr->hThread || infoPtr->uTimer) { - TRACE("Already playing\n"); - return TRUE; - } - - infoPtr->nFromFrame = (INT)LOWORD(lParam); - infoPtr->nToFrame = (INT)HIWORD(lParam); - infoPtr->nLoop = (INT)wParam; - - if (infoPtr->nToFrame == 0xFFFF) - infoPtr->nToFrame = infoPtr->mah.dwTotalFrames - 1; - - TRACE("(repeat=%d from=%d to=%d);\n", - infoPtr->nLoop, infoPtr->nFromFrame, infoPtr->nToFrame); - - if (infoPtr->nFromFrame >= infoPtr->nToFrame || - infoPtr->nToFrame >= infoPtr->mah.dwTotalFrames) - return FALSE; - - infoPtr->currFrame = infoPtr->nFromFrame; - - if (GetWindowLongA(hWnd, GWL_STYLE) & ACS_TIMER) { - TRACE("Using a timer\n"); - /* create a timer to display AVI */ - infoPtr->uTimer = SetTimer(hWnd, 1, infoPtr->mah.dwMicroSecPerFrame / 1000, NULL); - } else { - if(GetWindowLongA(hWnd, GWL_STYLE) & ACS_TRANSPARENT) - { - infoPtr->hbrushBG = (HBRUSH)SendMessageA(infoPtr->hwndNotify, - WM_CTLCOLORSTATIC, 0, (LPARAM)hWnd); - } - - TRACE("Using an animation thread\n"); - infoPtr->hStopEvent = CreateEventW( NULL, TRUE, FALSE, NULL ); - infoPtr->hThread = CreateThread(0,0,ANIMATE_AnimationThread,(LPVOID)infoPtr, 0, &infoPtr->threadId); - if(!infoPtr->hThread) - { - ERR("Could not create animation thread!\n"); - return FALSE; - } - - } - - ANIMATE_Notify(infoPtr, ACN_START); - - return TRUE; -} - - -static BOOL ANIMATE_GetAviInfo(ANIMATE_INFO *infoPtr) -{ - MMCKINFO ckMainRIFF; - MMCKINFO mmckHead; - MMCKINFO mmckList; - MMCKINFO mmckInfo; - DWORD numFrame; - DWORD insize; - - if (mmioDescend(infoPtr->hMMio, &ckMainRIFF, NULL, 0) != 0) { - WARN("Can't find 'RIFF' chunk\n"); - return FALSE; - } - - if ((ckMainRIFF.ckid != FOURCC_RIFF) || - (ckMainRIFF.fccType != mmioFOURCC('A', 'V', 'I', ' '))) { - WARN("Can't find 'AVI ' chunk\n"); - return FALSE; - } - - mmckHead.fccType = mmioFOURCC('h', 'd', 'r', 'l'); - if (mmioDescend(infoPtr->hMMio, &mmckHead, &ckMainRIFF, MMIO_FINDLIST) != 0) { - WARN("Can't find 'hdrl' list\n"); - return FALSE; - } - - mmckInfo.ckid = mmioFOURCC('a', 'v', 'i', 'h'); - if (mmioDescend(infoPtr->hMMio, &mmckInfo, &mmckHead, MMIO_FINDCHUNK) != 0) { - WARN("Can't find 'avih' chunk\n"); - return FALSE; - } - - mmioRead(infoPtr->hMMio, (LPSTR)&infoPtr->mah, sizeof(infoPtr->mah)); - - TRACE("mah.dwMicroSecPerFrame=%ld\n", infoPtr->mah.dwMicroSecPerFrame); - TRACE("mah.dwMaxBytesPerSec=%ld\n", infoPtr->mah.dwMaxBytesPerSec); - TRACE("mah.dwPaddingGranularity=%ld\n", infoPtr->mah.dwPaddingGranularity); - TRACE("mah.dwFlags=%ld\n", infoPtr->mah.dwFlags); - TRACE("mah.dwTotalFrames=%ld\n", infoPtr->mah.dwTotalFrames); - TRACE("mah.dwInitialFrames=%ld\n", infoPtr->mah.dwInitialFrames); - TRACE("mah.dwStreams=%ld\n", infoPtr->mah.dwStreams); - TRACE("mah.dwSuggestedBufferSize=%ld\n", infoPtr->mah.dwSuggestedBufferSize); - TRACE("mah.dwWidth=%ld\n", infoPtr->mah.dwWidth); - TRACE("mah.dwHeight=%ld\n", infoPtr->mah.dwHeight); - - mmioAscend(infoPtr->hMMio, &mmckInfo, 0); - - mmckList.fccType = mmioFOURCC('s', 't', 'r', 'l'); - if (mmioDescend(infoPtr->hMMio, &mmckList, &mmckHead, MMIO_FINDLIST) != 0) { - WARN("Can't find 'strl' list\n"); - return FALSE; - } - - mmckInfo.ckid = mmioFOURCC('s', 't', 'r', 'h'); - if (mmioDescend(infoPtr->hMMio, &mmckInfo, &mmckList, MMIO_FINDCHUNK) != 0) { - WARN("Can't find 'strh' chunk\n"); - return FALSE; - } - - mmioRead(infoPtr->hMMio, (LPSTR)&infoPtr->ash, sizeof(infoPtr->ash)); - - TRACE("ash.fccType='%c%c%c%c'\n", LOBYTE(LOWORD(infoPtr->ash.fccType)), - HIBYTE(LOWORD(infoPtr->ash.fccType)), - LOBYTE(HIWORD(infoPtr->ash.fccType)), - HIBYTE(HIWORD(infoPtr->ash.fccType))); - TRACE("ash.fccHandler='%c%c%c%c'\n", LOBYTE(LOWORD(infoPtr->ash.fccHandler)), - HIBYTE(LOWORD(infoPtr->ash.fccHandler)), - LOBYTE(HIWORD(infoPtr->ash.fccHandler)), - HIBYTE(HIWORD(infoPtr->ash.fccHandler))); - TRACE("ash.dwFlags=%ld\n", infoPtr->ash.dwFlags); - TRACE("ash.wPriority=%d\n", infoPtr->ash.wPriority); - TRACE("ash.wLanguage=%d\n", infoPtr->ash.wLanguage); - TRACE("ash.dwInitialFrames=%ld\n", infoPtr->ash.dwInitialFrames); - TRACE("ash.dwScale=%ld\n", infoPtr->ash.dwScale); - TRACE("ash.dwRate=%ld\n", infoPtr->ash.dwRate); - TRACE("ash.dwStart=%ld\n", infoPtr->ash.dwStart); - TRACE("ash.dwLength=%ld\n", infoPtr->ash.dwLength); - TRACE("ash.dwSuggestedBufferSize=%ld\n", infoPtr->ash.dwSuggestedBufferSize); - TRACE("ash.dwQuality=%ld\n", infoPtr->ash.dwQuality); - TRACE("ash.dwSampleSize=%ld\n", infoPtr->ash.dwSampleSize); - TRACE("ash.rcFrame=(%d,%d,%d,%d)\n", infoPtr->ash.rcFrame.top, infoPtr->ash.rcFrame.left, - infoPtr->ash.rcFrame.bottom, infoPtr->ash.rcFrame.right); - - mmioAscend(infoPtr->hMMio, &mmckInfo, 0); - - mmckInfo.ckid = mmioFOURCC('s', 't', 'r', 'f'); - if (mmioDescend(infoPtr->hMMio, &mmckInfo, &mmckList, MMIO_FINDCHUNK) != 0) { - WARN("Can't find 'strh' chunk\n"); - return FALSE; - } - - infoPtr->inbih = HeapAlloc(GetProcessHeap(), 0, mmckInfo.cksize); - if (!infoPtr->inbih) { - WARN("Can't alloc input BIH\n"); - return FALSE; - } - - mmioRead(infoPtr->hMMio, (LPSTR)infoPtr->inbih, mmckInfo.cksize); - - TRACE("bih.biSize=%ld\n", infoPtr->inbih->biSize); - TRACE("bih.biWidth=%ld\n", infoPtr->inbih->biWidth); - TRACE("bih.biHeight=%ld\n", infoPtr->inbih->biHeight); - TRACE("bih.biPlanes=%d\n", infoPtr->inbih->biPlanes); - TRACE("bih.biBitCount=%d\n", infoPtr->inbih->biBitCount); - TRACE("bih.biCompression=%ld\n", infoPtr->inbih->biCompression); - TRACE("bih.biSizeImage=%ld\n", infoPtr->inbih->biSizeImage); - TRACE("bih.biXPelsPerMeter=%ld\n", infoPtr->inbih->biXPelsPerMeter); - TRACE("bih.biYPelsPerMeter=%ld\n", infoPtr->inbih->biYPelsPerMeter); - TRACE("bih.biClrUsed=%ld\n", infoPtr->inbih->biClrUsed); - TRACE("bih.biClrImportant=%ld\n", infoPtr->inbih->biClrImportant); - - mmioAscend(infoPtr->hMMio, &mmckInfo, 0); - - mmioAscend(infoPtr->hMMio, &mmckList, 0); - -#if 0 - /* an AVI has 0 or 1 video stream, and to be animated should not contain - * an audio stream, so only one strl is allowed - */ - mmckList.fccType = mmioFOURCC('s', 't', 'r', 'l'); - if (mmioDescend(infoPtr->hMMio, &mmckList, &mmckHead, MMIO_FINDLIST) == 0) { - WARN("There should be a single 'strl' list\n"); - return FALSE; - } -#endif - - mmioAscend(infoPtr->hMMio, &mmckHead, 0); - - /* no need to read optional JUNK chunk */ - - mmckList.fccType = mmioFOURCC('m', 'o', 'v', 'i'); - if (mmioDescend(infoPtr->hMMio, &mmckList, &ckMainRIFF, MMIO_FINDLIST) != 0) { - WARN("Can't find 'movi' list\n"); - return FALSE; - } - - /* FIXME: should handle the 'rec ' LIST when present */ - - infoPtr->lpIndex = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, - infoPtr->mah.dwTotalFrames * sizeof(DWORD)); - if (!infoPtr->lpIndex) { - WARN("Can't alloc index array\n"); - return FALSE; - } - - numFrame = insize = 0; - while (mmioDescend(infoPtr->hMMio, &mmckInfo, &mmckList, 0) == 0 && - numFrame < infoPtr->mah.dwTotalFrames) { - infoPtr->lpIndex[numFrame] = mmckInfo.dwDataOffset; - if (insize < mmckInfo.cksize) - insize = mmckInfo.cksize; - numFrame++; - mmioAscend(infoPtr->hMMio, &mmckInfo, 0); - } - if (numFrame != infoPtr->mah.dwTotalFrames) { - WARN("Found %ld frames (/%ld)\n", numFrame, infoPtr->mah.dwTotalFrames); - return FALSE; - } - if (insize > infoPtr->ash.dwSuggestedBufferSize) { - WARN("insize=%ld suggestedSize=%ld\n", insize, infoPtr->ash.dwSuggestedBufferSize); - infoPtr->ash.dwSuggestedBufferSize = insize; - } - - infoPtr->indata = HeapAlloc(GetProcessHeap(), 0, infoPtr->ash.dwSuggestedBufferSize); - if (!infoPtr->indata) { - WARN("Can't alloc input buffer\n"); - return FALSE; - } - - return TRUE; -} - - -static BOOL ANIMATE_GetAviCodec(ANIMATE_INFO *infoPtr) -{ - DWORD outSize; - - /* check uncompressed AVI */ - if ((infoPtr->ash.fccHandler == mmioFOURCC('D', 'I', 'B', ' ')) || - (infoPtr->ash.fccHandler == mmioFOURCC('R', 'L', 'E', ' ')) || - (infoPtr->ash.fccHandler == mmioFOURCC(0, 0, 0, 0))) - { - infoPtr->hic = 0; - return TRUE; - } - - /* try to get a decompressor for that type */ - infoPtr->hic = fnIC.fnICOpen(ICTYPE_VIDEO, infoPtr->ash.fccHandler, ICMODE_DECOMPRESS); - if (!infoPtr->hic) { - WARN("Can't load codec for the file\n"); - return FALSE; - } - - outSize = fnIC.fnICSendMessage(infoPtr->hic, ICM_DECOMPRESS_GET_FORMAT, - (DWORD)infoPtr->inbih, 0L); - - infoPtr->outbih = HeapAlloc(GetProcessHeap(), 0, outSize); - if (!infoPtr->outbih) { - WARN("Can't alloc output BIH\n"); - return FALSE; - } - - if (fnIC.fnICSendMessage(infoPtr->hic, ICM_DECOMPRESS_GET_FORMAT, - (DWORD)infoPtr->inbih, (DWORD)infoPtr->outbih) != outSize) { - WARN("Can't get output BIH\n"); - return FALSE; - } - - infoPtr->outdata = HeapAlloc(GetProcessHeap(), 0, infoPtr->outbih->biSizeImage); - if (!infoPtr->outdata) { - WARN("Can't alloc output buffer\n"); - return FALSE; - } - - if (fnIC.fnICSendMessage(infoPtr->hic, ICM_DECOMPRESS_BEGIN, - (DWORD)infoPtr->inbih, (DWORD)infoPtr->outbih) != ICERR_OK) { - WARN("Can't begin decompression\n"); - return FALSE; - } - - return TRUE; -} - -static LRESULT ANIMATE_OpenA(HWND hWnd, WPARAM wParam, LPARAM lParam) -{ - ANIMATE_INFO *infoPtr = ANIMATE_GetInfoPtr(hWnd); - HINSTANCE hInstance = (HINSTANCE)wParam; - - ANIMATE_Free(infoPtr); - infoPtr->hwndSelf = hWnd; - - if (!lParam) { - TRACE("Closing avi!\n"); - /* installer of thebat! v1.62 requires FALSE here */ - return (infoPtr->hMMio != 0); - } - - if (!hInstance) - hInstance = (HINSTANCE)GetWindowLongPtrW(hWnd, GWLP_HINSTANCE); - - if (HIWORD(lParam)) { - TRACE("(\"%s\");\n", (LPSTR)lParam); - - if (!ANIMATE_LoadResA(infoPtr, hInstance, (LPSTR)lParam)) { - TRACE("No AVI resource found!\n"); - if (!ANIMATE_LoadFileA(infoPtr, (LPSTR)lParam)) { - WARN("No AVI file found!\n"); - return FALSE; - } - } - } else { - TRACE("(%u);\n", (WORD)LOWORD(lParam)); - - if (!ANIMATE_LoadResA(infoPtr, hInstance, - MAKEINTRESOURCEA((INT)lParam))) { - WARN("No AVI resource found!\n"); - return FALSE; - } - } - - if (!ANIMATE_GetAviInfo(infoPtr)) { - WARN("Can't get AVI information\n"); - ANIMATE_Free(infoPtr); - return FALSE; - } - - if (!ANIMATE_GetAviCodec(infoPtr)) { - WARN("Can't get AVI Codec\n"); - ANIMATE_Free(infoPtr); - return FALSE; - } - - if (!GetWindowLongA(hWnd, GWL_STYLE) & ACS_CENTER) { - SetWindowPos(hWnd, 0, 0, 0, infoPtr->mah.dwWidth, infoPtr->mah.dwHeight, - SWP_NOACTIVATE | SWP_NOMOVE | SWP_NOZORDER); - } - - if (GetWindowLongA(hWnd, GWL_STYLE) & ACS_AUTOPLAY) { - return ANIMATE_Play(hWnd, -1, (LPARAM)MAKELONG(0, infoPtr->mah.dwTotalFrames-1)); - } - - return TRUE; -} - - -/* << ANIMATE_Open32W >> */ - -static LRESULT ANIMATE_Stop(HWND hWnd, WPARAM wParam, LPARAM lParam) -{ - ANIMATE_INFO *infoPtr = ANIMATE_GetInfoPtr(hWnd); - - /* nothing opened */ - if (!infoPtr->hMMio) - return FALSE; - - ANIMATE_DoStop(infoPtr); - return TRUE; -} - - -static LRESULT ANIMATE_Create(HWND hWnd, WPARAM wParam, LPARAM lParam) -{ - ANIMATE_INFO* infoPtr; - - if (!fnIC.hModule) /* FIXME: not thread safe */ - { - /* since there's a circular dep between msvfw32 and comctl32, we could either: - * - fix the build chain to allow this circular dep - * - handle it by hand - * AJ wants the latter :-( - */ - fnIC.hModule = LoadLibraryA("msvfw32.dll"); - if (!fnIC.hModule) return FALSE; - - fnIC.fnICOpen = (void*)GetProcAddress(fnIC.hModule, "ICOpen"); - fnIC.fnICClose = (void*)GetProcAddress(fnIC.hModule, "ICClose"); - fnIC.fnICSendMessage = (void*)GetProcAddress(fnIC.hModule, "ICSendMessage"); - fnIC.fnICDecompress = (void*)GetProcAddress(fnIC.hModule, "ICDecompress"); - } - - /* allocate memory for info structure */ - infoPtr = (ANIMATE_INFO *)Alloc(sizeof(ANIMATE_INFO)); - if (!infoPtr) { - ERR("could not allocate info memory!\n"); - return 0; - } - - /* store crossref hWnd <-> info structure */ - SetWindowLongPtrW(hWnd, 0, (DWORD_PTR)infoPtr); - infoPtr->hwndSelf = hWnd; - infoPtr->hwndNotify = ((LPCREATESTRUCTA)lParam)->hwndParent; - infoPtr->transparentColor = ANIMATE_COLOR_NONE; - infoPtr->hbmPrevFrame = 0; - - TRACE("Animate style=0x%08lx, parent=%p\n", GetWindowLongA(hWnd, GWL_STYLE), infoPtr->hwndNotify); - - InitializeCriticalSection(&infoPtr->cs); - - return TRUE; -} - - -static LRESULT ANIMATE_Destroy(HWND hWnd, WPARAM wParam, LPARAM lParam) -{ - ANIMATE_INFO *infoPtr = ANIMATE_GetInfoPtr(hWnd); - - - /* free avi data */ - ANIMATE_Free(infoPtr); - - /* free animate info data */ - Free(infoPtr); - SetWindowLongPtrW(hWnd, 0, 0); - - return 0; -} - - -static LRESULT ANIMATE_EraseBackground(HWND hWnd, WPARAM wParam, LPARAM lParam) -{ - ANIMATE_INFO *infoPtr = ANIMATE_GetInfoPtr(hWnd); - RECT rect; - HBRUSH hBrush = 0; - - if(GetWindowLongA(hWnd, GWL_STYLE) & ACS_TRANSPARENT) - { - hBrush = (HBRUSH)SendMessageA(infoPtr->hwndNotify,WM_CTLCOLORSTATIC, - wParam, (LPARAM)hWnd); - } - - GetClientRect(hWnd, &rect); - FillRect((HDC)wParam, &rect, hBrush ? hBrush : GetCurrentObject((HDC)wParam, OBJ_BRUSH)); - - return TRUE; -} - -static LRESULT WINAPI ANIMATE_Size(HWND hWnd, WPARAM wParam, LPARAM lParam) -{ - if (GetWindowLongA(hWnd, GWL_STYLE) & ACS_CENTER) { - InvalidateRect(hWnd, NULL, TRUE); - } - return TRUE; -} - -static LRESULT WINAPI ANIMATE_WindowProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam) -{ - TRACE("hwnd=%p msg=%x wparam=%x lparam=%lx\n", hWnd, uMsg, wParam, lParam); - if (!ANIMATE_GetInfoPtr(hWnd) && (uMsg != WM_NCCREATE)) - return DefWindowProcA(hWnd, uMsg, wParam, lParam); - switch (uMsg) - { - case ACM_OPENA: - return ANIMATE_OpenA(hWnd, wParam, lParam); - - case ACM_OPENW: - FIXME("ACM_OPENW: stub!\n"); - /* return ANIMATE_Open32W(hWnd, wParam, lParam); */ - return 0; - - case ACM_PLAY: - return ANIMATE_Play(hWnd, wParam, lParam); - - case ACM_STOP: - return ANIMATE_Stop(hWnd, wParam, lParam); - - case WM_NCCREATE: - return ANIMATE_Create(hWnd, wParam, lParam); - - case WM_NCHITTEST: - return HTTRANSPARENT; - - case WM_DESTROY: - return ANIMATE_Destroy(hWnd, wParam, lParam); - - case WM_ERASEBKGND: - return ANIMATE_EraseBackground(hWnd, wParam, lParam); - - /* case WM_STYLECHANGED: FIXME shall we do something ?? */ - - case WM_TIMER: - if (GetWindowLongA(hWnd, GWL_STYLE) & ACS_TRANSPARENT) - { - ANIMATE_INFO* infoPtr = ANIMATE_GetInfoPtr(hWnd); - infoPtr->hbrushBG = (HBRUSH)SendMessageA(infoPtr->hwndNotify, - WM_CTLCOLORSTATIC, - wParam, (LPARAM)hWnd); - } - return ANIMATE_DrawFrame(ANIMATE_GetInfoPtr(hWnd)); - - case WM_PAINT: - { - ANIMATE_INFO* infoPtr = ANIMATE_GetInfoPtr(hWnd); - - /* the animation isn't playing, or has not decompressed - * (and displayed) the first frame yet, don't paint - */ - if ((!infoPtr->uTimer && !infoPtr->hThread) || - !infoPtr->hbmPrevFrame) - { - /* default paint handling */ - return DefWindowProcA(hWnd, uMsg, wParam, lParam); - } - - if (GetWindowLongA(hWnd, GWL_STYLE) & ACS_TRANSPARENT) - infoPtr->hbrushBG = (HBRUSH)SendMessageA(infoPtr->hwndNotify, - WM_CTLCOLORSTATIC, - wParam, (LPARAM)hWnd); - - if (wParam) - { - EnterCriticalSection(&infoPtr->cs); - ANIMATE_PaintFrame(infoPtr, (HDC)wParam); - LeaveCriticalSection(&infoPtr->cs); - } - else - { - PAINTSTRUCT ps; - HDC hDC = BeginPaint(hWnd, &ps); - - EnterCriticalSection(&infoPtr->cs); - ANIMATE_PaintFrame(infoPtr, hDC); - LeaveCriticalSection(&infoPtr->cs); - - EndPaint(hWnd, &ps); - } - } - break; - - case WM_SIZE: - return ANIMATE_Size(hWnd, wParam, lParam); - - default: - if ((uMsg >= WM_USER) && (uMsg < WM_APP)) - ERR("unknown msg %04x wp=%08x lp=%08lx\n", uMsg, wParam, lParam); - - return DefWindowProcA(hWnd, uMsg, wParam, lParam); - } - return 0; -} - -void ANIMATE_Register(void) -{ - WNDCLASSA wndClass; - - ZeroMemory(&wndClass, sizeof(WNDCLASSA)); - wndClass.style = CS_GLOBALCLASS | CS_DBLCLKS; - wndClass.lpfnWndProc = ANIMATE_WindowProc; - wndClass.cbClsExtra = 0; - wndClass.cbWndExtra = sizeof(ANIMATE_INFO *); - wndClass.hCursor = LoadCursorA(0, (LPSTR)IDC_ARROW); - wndClass.hbrBackground = (HBRUSH)(COLOR_BTNFACE + 1); - wndClass.lpszClassName = ANIMATE_CLASSA; - - RegisterClassA(&wndClass); -} - - -void ANIMATE_Unregister(void) -{ - UnregisterClassA(ANIMATE_CLASSA, NULL); -} diff --git a/reactos/lib/comctl32/comboex.c b/reactos/lib/comctl32/comboex.c deleted file mode 100644 index 94b5a82679f..00000000000 --- a/reactos/lib/comctl32/comboex.c +++ /dev/null @@ -1,2270 +0,0 @@ -/* - * ComboBoxEx control - * - * Copyright 1998, 1999 Eric Kohl - * Copyright 2000, 2001, 2002 Guy Albertelli - * Copyright 2002 Dimitrie O. Paun - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2.1 of the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - * - * NOTE - * - * This code was audited for completeness against the documented features - * of Comctl32.dll version 6.0 on Sep. 9, 2002, 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. - * - */ - -#include -#include -#include "windef.h" -#include "winbase.h" -#include "wingdi.h" -#include "winuser.h" -#include "winnls.h" -#include "commctrl.h" -#include "comctl32.h" -#include "wine/debug.h" -#include "wine/unicode.h" - -WINE_DEFAULT_DEBUG_CHANNEL(comboex); - -/* Item structure */ -typedef struct _CBE_ITEMDATA -{ - struct _CBE_ITEMDATA *next; - UINT mask; - LPWSTR pszText; - LPWSTR pszTemp; - int cchTextMax; - int iImage; - int iSelectedImage; - int iOverlay; - int iIndent; - LPARAM lParam; -} CBE_ITEMDATA; - -/* ComboBoxEx structure */ -typedef struct -{ - HIMAGELIST himl; - HWND hwndSelf; /* my own hwnd */ - HWND hwndNotify; /* my parent hwnd */ - HWND hwndCombo; - HWND hwndEdit; - WNDPROC prevEditWndProc; /* previous Edit WNDPROC value */ - WNDPROC prevComboWndProc; /* previous Combo WNDPROC value */ - DWORD dwExtStyle; - INT selected; /* index of selected item */ - DWORD flags; /* WINE internal flags */ - HFONT defaultFont; - HFONT font; - INT nb_items; /* Number of items */ - BOOL unicode; /* TRUE if this window is Unicode */ - BOOL NtfUnicode; /* TRUE if parent wants notify in Unicode */ - CBE_ITEMDATA *edit; /* item data for edit item */ - CBE_ITEMDATA *items; /* Array of items */ -} COMBOEX_INFO; - -/* internal flags in the COMBOEX_INFO structure */ -#define WCBE_ACTEDIT 0x00000001 /* Edit active i.e. - * CBEN_BEGINEDIT issued - * but CBEN_ENDEDIT{A|W} - * not yet issued. */ -#define WCBE_EDITCHG 0x00000002 /* Edit issued EN_CHANGE */ -#define WCBE_EDITHASCHANGED (WCBE_ACTEDIT | WCBE_EDITCHG) -#define WCBE_EDITFOCUSED 0x00000004 /* Edit control has focus */ -#define WCBE_MOUSECAPTURED 0x00000008 /* Combo has captured mouse */ -#define WCBE_MOUSEDRAGGED 0x00000010 /* User has dragged in combo */ - -#define ID_CB_EDIT 1001 - - -/* - * Special flag set in DRAWITEMSTRUCT itemState field. It is set by - * the ComboEx version of the Combo Window Proc so that when the - * WM_DRAWITEM message is then passed to ComboEx, we know that this - * particular WM_DRAWITEM message is for listbox only items. Any messasges - * without this flag is then for the Edit control field. - * - * We really cannot use the ODS_COMBOBOXEDIT flag because MSDN states that - * only version 4.0 applications will have ODS_COMBOBOXEDIT set. - */ -#define ODS_COMBOEXLBOX 0x4000 - - - -/* Height in pixels of control over the amount of the selected font */ -#define CBE_EXTRA 3 - -/* Indent amount per MS documentation */ -#define CBE_INDENT 10 - -/* Offset in pixels from left side for start of image or text */ -#define CBE_STARTOFFSET 6 - -/* Offset between image and text */ -#define CBE_SEP 4 - -#define COMBOEX_SUBCLASS_PROP "CCComboEx32SubclassInfo" -#define COMBOEX_GetInfoPtr(hwnd) ((COMBOEX_INFO *)GetWindowLongPtrW (hwnd, 0)) - - -/* Things common to the entire DLL */ -static LRESULT WINAPI COMBOEX_EditWndProc (HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam); -static LRESULT WINAPI COMBOEX_ComboWndProc (HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam); -static LRESULT COMBOEX_Destroy (COMBOEX_INFO *infoPtr); -typedef INT (WINAPI *cmp_func_t)(LPCWSTR, LPCWSTR); - -inline static BOOL is_textW(LPCWSTR str) -{ - return str && str != LPSTR_TEXTCALLBACKW; -} - -inline static BOOL is_textA(LPCSTR str) -{ - return str && str != LPSTR_TEXTCALLBACKA; -} - -inline static LPCSTR debugstr_txt(LPCWSTR str) -{ - if (str == LPSTR_TEXTCALLBACKW) return "(callback)"; - return debugstr_w(str); -} - -static void COMBOEX_DumpItem (CBE_ITEMDATA *item) -{ - TRACE("item %p - mask=%08x, pszText=%p, cchTM=%d, iImage=%d\n", - item, item->mask, item->pszText, item->cchTextMax, item->iImage); - TRACE("item %p - iSelectedImage=%d, iOverlay=%d, iIndent=%d, lParam=%08lx\n", - item, item->iSelectedImage, item->iOverlay, item->iIndent, item->lParam); - if (item->mask & CBEIF_TEXT) - TRACE("item %p - pszText=%s\n", item, debugstr_txt(item->pszText)); -} - - -static void COMBOEX_DumpInput (COMBOBOXEXITEMW *input) -{ - TRACE("input - mask=%08x, iItem=%d, pszText=%p, cchTM=%d, iImage=%d\n", - input->mask, input->iItem, input->pszText, input->cchTextMax, - input->iImage); - if (input->mask & CBEIF_TEXT) - TRACE("input - pszText=<%s>\n", debugstr_txt(input->pszText)); - TRACE("input - iSelectedImage=%d, iOverlay=%d, iIndent=%d, lParam=%08lx\n", - input->iSelectedImage, input->iOverlay, input->iIndent, input->lParam); -} - - -inline static CBE_ITEMDATA *get_item_data(COMBOEX_INFO *infoPtr, INT index) -{ - return (CBE_ITEMDATA *)SendMessageW (infoPtr->hwndCombo, CB_GETITEMDATA, - (WPARAM)index, 0); -} - -inline static cmp_func_t get_cmp_func(COMBOEX_INFO *infoPtr) -{ - return infoPtr->dwExtStyle & CBES_EX_CASESENSITIVE ? lstrcmpW : lstrcmpiW; -} - -static INT COMBOEX_Notify (COMBOEX_INFO *infoPtr, INT code, NMHDR *hdr) -{ - hdr->idFrom = GetDlgCtrlID (infoPtr->hwndSelf); - hdr->hwndFrom = infoPtr->hwndSelf; - hdr->code = code; - if (infoPtr->NtfUnicode) - return SendMessageW (infoPtr->hwndNotify, WM_NOTIFY, 0, (LPARAM)hdr); - else - return SendMessageA (infoPtr->hwndNotify, WM_NOTIFY, 0, (LPARAM)hdr); -} - - -static INT -COMBOEX_NotifyItem (COMBOEX_INFO *infoPtr, INT code, NMCOMBOBOXEXW *hdr) -{ - /* Change the Text item from Unicode to ANSI if necessary for NOTIFY */ - if (infoPtr->NtfUnicode) - return COMBOEX_Notify (infoPtr, code, &hdr->hdr); - else { - LPWSTR wstr = hdr->ceItem.pszText; - LPSTR astr = 0; - INT ret, len = 0; - - if ((hdr->ceItem.mask & CBEIF_TEXT) && is_textW(wstr)) { - len = WideCharToMultiByte (CP_ACP, 0, wstr, -1, 0, 0, NULL, NULL); - if (len > 0) { - astr = (LPSTR)Alloc ((len + 1)*sizeof(CHAR)); - if (!astr) return 0; - WideCharToMultiByte (CP_ACP, 0, wstr, -1, astr, len, 0, 0); - hdr->ceItem.pszText = (LPWSTR)astr; - } - } - - if (code == CBEN_ENDEDITW) code = CBEN_ENDEDITA; - else if (code == CBEN_GETDISPINFOW) code = CBEN_GETDISPINFOA; - else if (code == CBEN_DRAGBEGINW) code = CBEN_DRAGBEGINA; - - ret = COMBOEX_Notify (infoPtr, code, (NMHDR *)hdr); - - if (astr && hdr->ceItem.pszText == (LPWSTR)astr) - hdr->ceItem.pszText = wstr; - - if (astr) Free(astr); - - return ret; - } -} - - -static INT COMBOEX_NotifyEndEdit (COMBOEX_INFO *infoPtr, NMCBEENDEDITW *neew, LPCWSTR wstr) -{ - /* Change the Text item from Unicode to ANSI if necessary for NOTIFY */ - if (infoPtr->NtfUnicode) { - lstrcpynW(neew->szText, wstr, CBEMAXSTRLEN); - return COMBOEX_Notify (infoPtr, CBEN_ENDEDITW, &neew->hdr); - } else { - NMCBEENDEDITA neea; - - memcpy (&neea.hdr, &neew->hdr, sizeof(NMHDR)); - neea.fChanged = neew->fChanged; - neea.iNewSelection = neew->iNewSelection; - WideCharToMultiByte (CP_ACP, 0, wstr, -1, neea.szText, CBEMAXSTRLEN, 0, 0); - neea.iWhy = neew->iWhy; - - return COMBOEX_Notify (infoPtr, CBEN_ENDEDITA, &neea.hdr); - } -} - - -static void COMBOEX_NotifyDragBegin(COMBOEX_INFO *infoPtr, LPCWSTR wstr) -{ - /* Change the Text item from Unicode to ANSI if necessary for NOTIFY */ - if (infoPtr->NtfUnicode) { - NMCBEDRAGBEGINW ndbw; - - ndbw.iItemid = -1; - lstrcpynW(ndbw.szText, wstr, CBEMAXSTRLEN); - COMBOEX_Notify (infoPtr, CBEN_DRAGBEGINW, &ndbw.hdr); - } else { - NMCBEDRAGBEGINA ndba; - - ndba.iItemid = -1; - WideCharToMultiByte (CP_ACP, 0, wstr, -1, ndba.szText, CBEMAXSTRLEN, 0, 0); - - COMBOEX_Notify (infoPtr, CBEN_DRAGBEGINA, &ndba.hdr); - } -} - - -static void COMBOEX_FreeText (CBE_ITEMDATA *item) -{ - if (is_textW(item->pszText)) Free(item->pszText); - item->pszText = 0; - if (item->pszTemp) Free(item->pszTemp); - item->pszTemp = 0; -} - - -static LPCWSTR COMBOEX_GetText(COMBOEX_INFO *infoPtr, CBE_ITEMDATA *item) -{ - NMCOMBOBOXEXW nmce; - LPWSTR text, buf; - INT len; - - if (item->pszText != LPSTR_TEXTCALLBACKW) - return item->pszText; - - ZeroMemory(&nmce, sizeof(nmce)); - nmce.ceItem.mask = CBEIF_TEXT; - nmce.ceItem.lParam = item->lParam; - COMBOEX_NotifyItem(infoPtr, CBEN_GETDISPINFOW, &nmce); - - if (is_textW(nmce.ceItem.pszText)) { - len = MultiByteToWideChar (CP_ACP, 0, (LPSTR)nmce.ceItem.pszText, -1, NULL, 0); - buf = (LPWSTR)Alloc ((len + 1)*sizeof(WCHAR)); - if (buf) - MultiByteToWideChar (CP_ACP, 0, (LPSTR)nmce.ceItem.pszText, -1, buf, len); - if (nmce.ceItem.mask & CBEIF_DI_SETITEM) { - COMBOEX_FreeText(item); - item->pszText = buf; - } else { - if (item->pszTemp) Free(item->pszTemp); - item->pszTemp = buf; - } - text = buf; - } else - text = nmce.ceItem.pszText; - - if (nmce.ceItem.mask & CBEIF_DI_SETITEM) - item->pszText = text; - return text; -} - - -static void COMBOEX_GetComboFontSize (COMBOEX_INFO *infoPtr, SIZE *size) -{ - HFONT nfont, ofont; - HDC mydc; - - mydc = GetDC (0); /* why the entire screen???? */ - nfont = (HFONT)SendMessageW (infoPtr->hwndCombo, WM_GETFONT, 0, 0); - ofont = (HFONT) SelectObject (mydc, nfont); - GetTextExtentPointA (mydc, "A", 1, size); - SelectObject (mydc, ofont); - ReleaseDC (0, mydc); - TRACE("selected font hwnd=%p, height=%ld\n", nfont, size->cy); -} - - -static void COMBOEX_CopyItem (CBE_ITEMDATA *item, COMBOBOXEXITEMW *cit) -{ - if (cit->mask & CBEIF_TEXT) { - /* - * when given a text buffer actually use that buffer - */ - if (cit->pszText) { - if (is_textW(item->pszText)) - lstrcpynW(cit->pszText, item->pszText, cit->cchTextMax); - else - cit->pszText[0] = 0; - } else { - cit->pszText = item->pszText; - cit->cchTextMax = item->cchTextMax; - } - } - if (cit->mask & CBEIF_IMAGE) - cit->iImage = item->iImage; - if (cit->mask & CBEIF_SELECTEDIMAGE) - cit->iSelectedImage = item->iSelectedImage; - if (cit->mask & CBEIF_OVERLAY) - cit->iOverlay = item->iOverlay; - if (cit->mask & CBEIF_INDENT) - cit->iIndent = item->iIndent; - if (cit->mask & CBEIF_LPARAM) - cit->lParam = item->lParam; -} - - -static void COMBOEX_AdjustEditPos (COMBOEX_INFO *infoPtr) -{ - SIZE mysize; - INT x, y, w, h, xioff; - RECT rect; - - if (!infoPtr->hwndEdit) return; - - if (infoPtr->himl && !(infoPtr->dwExtStyle & CBES_EX_NOEDITIMAGEINDENT)) { - IMAGEINFO iinfo; - iinfo.rcImage.left = iinfo.rcImage.right = 0; - ImageList_GetImageInfo(infoPtr->himl, 0, &iinfo); - xioff = iinfo.rcImage.right - iinfo.rcImage.left + CBE_SEP; - } else xioff = 0; - - GetClientRect (infoPtr->hwndCombo, &rect); - InflateRect (&rect, -2, -2); - InvalidateRect (infoPtr->hwndCombo, &rect, TRUE); - - /* reposition the Edit control based on whether icon exists */ - COMBOEX_GetComboFontSize (infoPtr, &mysize); - TRACE("Combo font x=%ld, y=%ld\n", mysize.cx, mysize.cy); - x = xioff + CBE_STARTOFFSET + 1; - w = rect.right-rect.left - x - GetSystemMetrics(SM_CXVSCROLL) - 1; - h = mysize.cy + 1; - y = rect.bottom - h - 1; - - TRACE("Combo client (%ld,%ld)-(%ld,%ld), setting Edit to (%d,%d)-(%d,%d)\n", - rect.left, rect.top, rect.right, rect.bottom, x, y, x + w, y + h); - SetWindowPos(infoPtr->hwndEdit, HWND_TOP, x, y, w, h, - SWP_SHOWWINDOW | SWP_NOACTIVATE | SWP_NOZORDER); -} - - -static void COMBOEX_ReSize (COMBOEX_INFO *infoPtr) -{ - SIZE mysize; - LONG cy; - IMAGEINFO iinfo; - - COMBOEX_GetComboFontSize (infoPtr, &mysize); - cy = mysize.cy + CBE_EXTRA; - if (infoPtr->himl && ImageList_GetImageInfo(infoPtr->himl, 0, &iinfo)) { - cy = max (iinfo.rcImage.bottom - iinfo.rcImage.top, cy); - TRACE("upgraded height due to image: height=%ld\n", cy); - } - SendMessageW (infoPtr->hwndSelf, CB_SETITEMHEIGHT, (WPARAM)-1, (LPARAM)cy); - if (infoPtr->hwndCombo) { - SendMessageW (infoPtr->hwndCombo, CB_SETITEMHEIGHT, - (WPARAM) 0, (LPARAM) cy); - if ( !(infoPtr->flags & CBES_EX_NOSIZELIMIT)) { - RECT comboRect; - if (GetWindowRect(infoPtr->hwndCombo, &comboRect)) { - RECT ourRect; - if (GetWindowRect(infoPtr->hwndSelf, &ourRect)) { - if (comboRect.bottom > ourRect.bottom) { - POINT pt = { ourRect.left, ourRect.top }; - if (ScreenToClient(infoPtr->hwndSelf, &pt)) - MoveWindow( infoPtr->hwndSelf, pt.x, pt.y, ourRect.right - ourRect.left, - comboRect.bottom - comboRect.top, FALSE); - } - } - } - } - } -} - - -static void COMBOEX_SetEditText (COMBOEX_INFO *infoPtr, CBE_ITEMDATA *item) -{ - if (!infoPtr->hwndEdit) return; - /* native issues the following messages to the {Edit} control */ - /* WM_SETTEXT (0,addr) */ - /* EM_SETSEL32 (0,0) */ - /* EM_SETSEL32 (0,-1) */ - if (item->mask & CBEIF_TEXT) { - SendMessageW (infoPtr->hwndEdit, WM_SETTEXT, 0, (LPARAM)COMBOEX_GetText(infoPtr, item)); - SendMessageW (infoPtr->hwndEdit, EM_SETSEL, 0, 0); - SendMessageW (infoPtr->hwndEdit, EM_SETSEL, 0, -1); - } -} - - -static CBE_ITEMDATA * COMBOEX_FindItem(COMBOEX_INFO *infoPtr, INT index) -{ - CBE_ITEMDATA *item; - INT i; - - if ((index > infoPtr->nb_items) || (index < -1)) - return 0; - if (index == -1) - return infoPtr->edit; - item = infoPtr->items; - i = infoPtr->nb_items - 1; - - /* find the item in the list */ - while (item && (i > index)) { - item = item->next; - i--; - } - if (!item || (i != index)) { - ERR("COMBOBOXEX item structures broken. Please report!\n"); - return 0; - } - return item; -} - - -static inline BOOL COMBOEX_HasEdit(COMBOEX_INFO *infoPtr) -{ - return infoPtr->hwndEdit ? TRUE : FALSE; -} - - -/* *** CBEM_xxx message support *** */ - - -static INT COMBOEX_DeleteItem (COMBOEX_INFO *infoPtr, INT index) -{ - CBE_ITEMDATA *item; - - TRACE("(index=%d)\n", index); - - /* if item number requested does not exist then return failure */ - if ((index > infoPtr->nb_items) || (index < 0)) return CB_ERR; - if (!(item = COMBOEX_FindItem(infoPtr, index))) return CB_ERR; - - /* doing this will result in WM_DELETEITEM being issued */ - SendMessageW (infoPtr->hwndCombo, CB_DELETESTRING, (WPARAM)index, 0); - - return infoPtr->nb_items; -} - - -static BOOL COMBOEX_GetItemW (COMBOEX_INFO *infoPtr, COMBOBOXEXITEMW *cit) -{ - INT index = cit->iItem; - CBE_ITEMDATA *item; - - TRACE("(...)\n"); - - /* if item number requested does not exist then return failure */ - if ((index > infoPtr->nb_items) || (index < -1)) return FALSE; - - /* if the item is the edit control and there is no edit control, skip */ - if ((index == -1) && !COMBOEX_HasEdit(infoPtr)) return FALSE; - - if (!(item = COMBOEX_FindItem(infoPtr, index))) return FALSE; - - COMBOEX_CopyItem (item, cit); - - return TRUE; -} - - -static BOOL COMBOEX_GetItemA (COMBOEX_INFO *infoPtr, COMBOBOXEXITEMA *cit) -{ - COMBOBOXEXITEMW tmpcit; - - TRACE("(...)\n"); - - tmpcit.mask = cit->mask; - tmpcit.iItem = cit->iItem; - tmpcit.pszText = 0; - if(!COMBOEX_GetItemW (infoPtr, &tmpcit)) return FALSE; - - if (is_textW(tmpcit.pszText) && cit->pszText) - WideCharToMultiByte (CP_ACP, 0, tmpcit.pszText, -1, - cit->pszText, cit->cchTextMax, NULL, NULL); - else if (cit->pszText) cit->pszText[0] = 0; - else cit->pszText = (LPSTR)tmpcit.pszText; - - cit->iImage = tmpcit.iImage; - cit->iSelectedImage = tmpcit.iSelectedImage; - cit->iOverlay = tmpcit.iOverlay; - cit->iIndent = tmpcit.iIndent; - cit->lParam = tmpcit.lParam; - - return TRUE; -} - - -inline static BOOL COMBOEX_HasEditChanged (COMBOEX_INFO *infoPtr) -{ - return COMBOEX_HasEdit(infoPtr) && - (infoPtr->flags & WCBE_EDITHASCHANGED) == WCBE_EDITHASCHANGED; -} - - -static INT COMBOEX_InsertItemW (COMBOEX_INFO *infoPtr, COMBOBOXEXITEMW *cit) -{ - INT index; - CBE_ITEMDATA *item; - NMCOMBOBOXEXW nmcit; - - TRACE("\n"); - - if (TRACE_ON(comboex)) COMBOEX_DumpInput (cit); - - /* get real index of item to insert */ - index = cit->iItem; - if (index == -1) index = infoPtr->nb_items; - if (index > infoPtr->nb_items) index = infoPtr->nb_items; - - /* get zero-filled space and chain it in */ - if(!(item = (CBE_ITEMDATA *)Alloc (sizeof(*item)))) return -1; - - /* locate position to insert new item in */ - if (index == infoPtr->nb_items) { - /* fast path for iItem = -1 */ - item->next = infoPtr->items; - infoPtr->items = item; - } - else { - INT i = infoPtr->nb_items-1; - CBE_ITEMDATA *moving = infoPtr->items; - - while ((i > index) && moving) { - moving = moving->next; - i--; - } - if (!moving) { - ERR("COMBOBOXEX item structures broken. Please report!\n"); - Free(item); - return -1; - } - item->next = moving->next; - moving->next = item; - } - - /* fill in our hidden item structure */ - item->mask = cit->mask; - if (item->mask & CBEIF_TEXT) { - INT len = 0; - - if (is_textW(cit->pszText)) len = strlenW (cit->pszText); - if (len > 0) { - item->pszText = (LPWSTR)Alloc ((len + 1)*sizeof(WCHAR)); - if (!item->pszText) { - Free(item); - return -1; - } - strcpyW (item->pszText, cit->pszText); - } - else if (cit->pszText == LPSTR_TEXTCALLBACKW) - item->pszText = LPSTR_TEXTCALLBACKW; - item->cchTextMax = cit->cchTextMax; - } - if (item->mask & CBEIF_IMAGE) - item->iImage = cit->iImage; - if (item->mask & CBEIF_SELECTEDIMAGE) - item->iSelectedImage = cit->iSelectedImage; - if (item->mask & CBEIF_OVERLAY) - item->iOverlay = cit->iOverlay; - if (item->mask & CBEIF_INDENT) - item->iIndent = cit->iIndent; - if (item->mask & CBEIF_LPARAM) - item->lParam = cit->lParam; - infoPtr->nb_items++; - - if (TRACE_ON(comboex)) COMBOEX_DumpItem (item); - - SendMessageW (infoPtr->hwndCombo, CB_INSERTSTRING, - (WPARAM)cit->iItem, (LPARAM)item); - - memset (&nmcit.ceItem, 0, sizeof(nmcit.ceItem)); - COMBOEX_CopyItem (item, &nmcit.ceItem); - COMBOEX_NotifyItem (infoPtr, CBEN_INSERTITEM, &nmcit); - - return index; - -} - - -static INT COMBOEX_InsertItemA (COMBOEX_INFO *infoPtr, COMBOBOXEXITEMA *cit) -{ - COMBOBOXEXITEMW citW; - LPWSTR wstr = NULL; - INT ret; - - memcpy(&citW,cit,sizeof(COMBOBOXEXITEMA)); - if (cit->mask & CBEIF_TEXT && is_textA(cit->pszText)) { - INT len = MultiByteToWideChar (CP_ACP, 0, cit->pszText, -1, NULL, 0); - wstr = (LPWSTR)Alloc ((len + 1)*sizeof(WCHAR)); - if (!wstr) return -1; - MultiByteToWideChar (CP_ACP, 0, cit->pszText, -1, wstr, len); - citW.pszText = wstr; - } - ret = COMBOEX_InsertItemW(infoPtr, &citW); - - if (wstr) Free(wstr); - - return ret; -} - - -static DWORD -COMBOEX_SetExtendedStyle (COMBOEX_INFO *infoPtr, DWORD mask, DWORD style) -{ - DWORD dwTemp; - - TRACE("(mask=x%08lx, style=0x%08lx)\n", mask, style); - - dwTemp = infoPtr->dwExtStyle; - - if (mask) - infoPtr->dwExtStyle = (infoPtr->dwExtStyle & ~mask) | style; - else - infoPtr->dwExtStyle = style; - - /* see if we need to change the word break proc on the edit */ - if ((infoPtr->dwExtStyle ^ dwTemp) & CBES_EX_PATHWORDBREAKPROC) - SetPathWordBreakProc(infoPtr->hwndEdit, - (infoPtr->dwExtStyle & CBES_EX_PATHWORDBREAKPROC) ? TRUE : FALSE); - - /* test if the control's appearance has changed */ - mask = CBES_EX_NOEDITIMAGE | CBES_EX_NOEDITIMAGEINDENT; - if ((infoPtr->dwExtStyle & mask) != (dwTemp & mask)) { - /* if state of EX_NOEDITIMAGE changes, invalidate all */ - TRACE("EX_NOEDITIMAGE state changed to %ld\n", - infoPtr->dwExtStyle & CBES_EX_NOEDITIMAGE); - InvalidateRect (infoPtr->hwndSelf, NULL, TRUE); - COMBOEX_AdjustEditPos (infoPtr); - if (infoPtr->hwndEdit) - InvalidateRect (infoPtr->hwndEdit, NULL, TRUE); - } - - return dwTemp; -} - - -static HIMAGELIST COMBOEX_SetImageList (COMBOEX_INFO *infoPtr, HIMAGELIST himl) -{ - HIMAGELIST himlTemp = infoPtr->himl; - - TRACE("(...)\n"); - - infoPtr->himl = himl; - - COMBOEX_ReSize (infoPtr); - InvalidateRect (infoPtr->hwndCombo, NULL, TRUE); - - /* reposition the Edit control based on whether icon exists */ - COMBOEX_AdjustEditPos (infoPtr); - return himlTemp; -} - -static BOOL COMBOEX_SetItemW (COMBOEX_INFO *infoPtr, COMBOBOXEXITEMW *cit) -{ - INT index = cit->iItem; - CBE_ITEMDATA *item; - - if (TRACE_ON(comboex)) COMBOEX_DumpInput (cit); - - /* if item number requested does not exist then return failure */ - if ((index > infoPtr->nb_items) || (index < -1)) return FALSE; - - /* if the item is the edit control and there is no edit control, skip */ - if ((index == -1) && !COMBOEX_HasEdit(infoPtr)) return FALSE; - - if (!(item = COMBOEX_FindItem(infoPtr, index))) return FALSE; - - /* add/change stuff to the internal item structure */ - item->mask |= cit->mask; - if (cit->mask & CBEIF_TEXT) { - INT len = 0; - - COMBOEX_FreeText(item); - if (is_textW(cit->pszText)) len = strlenW(cit->pszText); - if (len > 0) { - item->pszText = (LPWSTR)Alloc ((len + 1)*sizeof(WCHAR)); - if (!item->pszText) return FALSE; - strcpyW(item->pszText, cit->pszText); - } else if (cit->pszText == LPSTR_TEXTCALLBACKW) - item->pszText = LPSTR_TEXTCALLBACKW; - item->cchTextMax = cit->cchTextMax; - } - if (cit->mask & CBEIF_IMAGE) - item->iImage = cit->iImage; - if (cit->mask & CBEIF_SELECTEDIMAGE) - item->iSelectedImage = cit->iSelectedImage; - if (cit->mask & CBEIF_OVERLAY) - item->iOverlay = cit->iOverlay; - if (cit->mask & CBEIF_INDENT) - item->iIndent = cit->iIndent; - if (cit->mask & CBEIF_LPARAM) - cit->lParam = cit->lParam; - - if (TRACE_ON(comboex)) COMBOEX_DumpItem (item); - - /* if original request was to update edit control, do some fast foot work */ - if (cit->iItem == -1) { - COMBOEX_SetEditText (infoPtr, item); - RedrawWindow (infoPtr->hwndCombo, 0, 0, RDW_ERASE | RDW_INVALIDATE); - } - return TRUE; -} - -static BOOL COMBOEX_SetItemA (COMBOEX_INFO *infoPtr, COMBOBOXEXITEMA *cit) -{ - COMBOBOXEXITEMW citW; - LPWSTR wstr = NULL; - BOOL ret; - - memcpy(&citW, cit, sizeof(COMBOBOXEXITEMA)); - if ((cit->mask & CBEIF_TEXT) && is_textA(cit->pszText)) { - INT len = MultiByteToWideChar (CP_ACP, 0, cit->pszText, -1, NULL, 0); - wstr = (LPWSTR)Alloc ((len + 1)*sizeof(WCHAR)); - if (!wstr) return FALSE; - MultiByteToWideChar (CP_ACP, 0, cit->pszText, -1, wstr, len); - citW.pszText = wstr; - } - ret = COMBOEX_SetItemW(infoPtr, &citW); - - if (wstr) Free(wstr); - - return ret; -} - - -static BOOL COMBOEX_SetUnicodeFormat (COMBOEX_INFO *infoPtr, BOOL value) -{ - BOOL bTemp = infoPtr->unicode; - - TRACE("to %s, was %s\n", value ? "TRUE":"FALSE", bTemp ? "TRUE":"FALSE"); - - infoPtr->unicode = value; - - return bTemp; -} - - -/* *** CB_xxx message support *** */ - -static INT -COMBOEX_FindStringExact (COMBOEX_INFO *infoPtr, INT start, LPCWSTR str) -{ - INT i; - cmp_func_t cmptext = get_cmp_func(infoPtr); - INT count = SendMessageW (infoPtr->hwndCombo, CB_GETCOUNT, 0, 0); - - /* now search from after starting loc and wrapping back to start */ - for(i=start+1; imask & CBEIF_LPARAM) ret = item1->lParam; - TRACE("returning 0x%08lx\n", ret); - } else { - ret = (DWORD)item1; - TRACE("non-valid result from combo, returning 0x%08lx\n", ret); - } - return ret; -} - - -static INT COMBOEX_SetCursel (COMBOEX_INFO *infoPtr, INT index) -{ - CBE_ITEMDATA *item; - INT sel; - - if (!(item = COMBOEX_FindItem(infoPtr, index))) - return SendMessageW (infoPtr->hwndCombo, CB_SETCURSEL, index, 0); - - TRACE("selecting item %d text=%s\n", index, debugstr_txt(item->pszText)); - infoPtr->selected = index; - - sel = (INT)SendMessageW (infoPtr->hwndCombo, CB_SETCURSEL, index, 0); - COMBOEX_SetEditText (infoPtr, item); - return sel; -} - - -static DWORD COMBOEX_SetItemData (COMBOEX_INFO *infoPtr, INT index, DWORD data) -{ - CBE_ITEMDATA *item1, *item2; - - item1 = get_item_data(infoPtr, index); - if ((item1 != NULL) && ((LRESULT)item1 != CB_ERR)) { - item2 = COMBOEX_FindItem (infoPtr, index); - if (item2 != item1) { - ERR("data structures damaged!\n"); - return CB_ERR; - } - item1->mask |= CBEIF_LPARAM; - item1->lParam = data; - TRACE("setting lparam to 0x%08lx\n", data); - return 0; - } - TRACE("non-valid result from combo 0x%08lx\n", (DWORD)item1); - return (LRESULT)item1; -} - - -static INT COMBOEX_SetItemHeight (COMBOEX_INFO *infoPtr, INT index, UINT height) -{ - RECT cb_wrect, cbx_wrect, cbx_crect; - - /* First, lets forward the message to the normal combo control - just like Windows. */ - if (infoPtr->hwndCombo) - if (SendMessageW (infoPtr->hwndCombo, CB_SETITEMHEIGHT, - index, height) == CB_ERR) return CB_ERR; - - GetWindowRect (infoPtr->hwndCombo, &cb_wrect); - GetWindowRect (infoPtr->hwndSelf, &cbx_wrect); - GetClientRect (infoPtr->hwndSelf, &cbx_crect); - /* the height of comboex as height of the combo + comboex border */ - height = cb_wrect.bottom-cb_wrect.top - + cbx_wrect.bottom-cbx_wrect.top - - (cbx_crect.bottom-cbx_crect.top); - TRACE("EX window=(%ld,%ld)-(%ld,%ld), client=(%ld,%ld)-(%ld,%ld)\n", - cbx_wrect.left, cbx_wrect.top, cbx_wrect.right, cbx_wrect.bottom, - cbx_crect.left, cbx_crect.top, cbx_crect.right, cbx_crect.bottom); - TRACE("CB window=(%ld,%ld)-(%ld,%ld), EX setting=(0,0)-(%ld,%d)\n", - cb_wrect.left, cb_wrect.top, cb_wrect.right, cb_wrect.bottom, - cbx_wrect.right-cbx_wrect.left, height); - SetWindowPos (infoPtr->hwndSelf, HWND_TOP, 0, 0, - cbx_wrect.right-cbx_wrect.left, height, - SWP_NOACTIVATE | SWP_NOZORDER | SWP_NOMOVE); - - return 0; -} - - -/* *** WM_xxx message support *** */ - - -static LRESULT COMBOEX_Create (HWND hwnd, LPCREATESTRUCTA cs) -{ - static const WCHAR COMBOBOX[] = { 'C', 'o', 'm', 'b', 'o', 'B', 'o', 'x', 0 }; - static const WCHAR EDIT[] = { 'E', 'D', 'I', 'T', 0 }; - static const WCHAR NIL[] = { 0 }; - COMBOEX_INFO *infoPtr; - LOGFONTW mylogfont; - RECT wnrc1, clrc1, cmbwrc; - INT i; - - /* allocate memory for info structure */ - infoPtr = (COMBOEX_INFO *)Alloc (sizeof(COMBOEX_INFO)); - if (!infoPtr) return -1; - - /* initialize info structure */ - /* note that infoPtr is allocated zero-filled */ - - infoPtr->hwndSelf = hwnd; - infoPtr->selected = -1; - - infoPtr->unicode = IsWindowUnicode (hwnd); - infoPtr->hwndNotify = cs->hwndParent; - - i = SendMessageW(infoPtr->hwndNotify, WM_NOTIFYFORMAT, (WPARAM)hwnd, NF_QUERY); - if ((i != NFR_ANSI) && (i != NFR_UNICODE)) { - WARN("wrong response to WM_NOTIFYFORMAT (%d), assuming ANSI\n", i); - i = NFR_ANSI; - } - infoPtr->NtfUnicode = (i == NFR_UNICODE); - - SetWindowLongPtrW (hwnd, 0, (DWORD_PTR)infoPtr); - - /* create combo box */ - GetWindowRect(hwnd, &wnrc1); - GetClientRect(hwnd, &clrc1); - TRACE("EX window=(%ld,%ld)-(%ld,%ld) client=(%ld,%ld)-(%ld,%ld)\n", - wnrc1.left, wnrc1.top, wnrc1.right, wnrc1.bottom, - clrc1.left, clrc1.top, clrc1.right, clrc1.bottom); - - /* Native version of ComboEx creates the ComboBox with DROPDOWNLIST */ - /* specified. It then creates it's own version of the EDIT control */ - /* and makes the ComboBox the parent. This is because a normal */ - /* DROPDOWNLIST does not have a EDIT control, but we need one. */ - /* We also need to place the edit control at the proper location */ - /* (allow space for the icons). */ - - infoPtr->hwndCombo = CreateWindowW (COMBOBOX, NIL, - /* following line added to match native */ - WS_CLIPSIBLINGS | WS_CLIPCHILDREN | WS_VSCROLL | - CBS_NOINTEGRALHEIGHT | CBS_DROPDOWNLIST | - /* was base and is necessary */ - WS_CHILD | WS_VISIBLE | CBS_OWNERDRAWFIXED | - GetWindowLongW (hwnd, GWL_STYLE), - cs->y, cs->x, cs->cx, cs->cy, hwnd, - (HMENU) GetWindowLongPtrW (hwnd, GWLP_ID), - (HINSTANCE)GetWindowLongPtrW (hwnd, GWLP_HINSTANCE), NULL); - - /* - * native does the following at this point according to trace: - * GetWindowThreadProcessId(hwndCombo,0) - * GetCurrentThreadId() - * GetWindowThreadProcessId(hwndCombo, &???) - * GetCurrentProcessId() - */ - - /* - * Setup a property to hold the pointer to the COMBOBOXEX - * data structure. - */ - SetPropA(infoPtr->hwndCombo, COMBOEX_SUBCLASS_PROP, hwnd); - infoPtr->prevComboWndProc = (WNDPROC)SetWindowLongPtrW(infoPtr->hwndCombo, - GWLP_WNDPROC, (DWORD_PTR)COMBOEX_ComboWndProc); - infoPtr->font = (HFONT)SendMessageW (infoPtr->hwndCombo, WM_GETFONT, 0, 0); - - - /* - * Now create our own EDIT control so we can position it. - * It is created only for CBS_DROPDOWN style - */ - if ((cs->style & CBS_DROPDOWNLIST) == CBS_DROPDOWN) { - infoPtr->hwndEdit = CreateWindowExW (0, EDIT, NIL, - WS_CHILD | WS_VISIBLE | WS_CLIPSIBLINGS | ES_AUTOHSCROLL, - 0, 0, 0, 0, /* will set later */ - infoPtr->hwndCombo, - (HMENU) GetWindowLongPtrW (hwnd, GWLP_ID), - (HINSTANCE)GetWindowLongPtrW (hwnd, GWLP_HINSTANCE), NULL); - - /* native does the following at this point according to trace: - * GetWindowThreadProcessId(hwndEdit,0) - * GetCurrentThreadId() - * GetWindowThreadProcessId(hwndEdit, &???) - * GetCurrentProcessId() - */ - - /* - * Setup a property to hold the pointer to the COMBOBOXEX - * data structure. - */ - SetPropA(infoPtr->hwndEdit, COMBOEX_SUBCLASS_PROP, hwnd); - infoPtr->prevEditWndProc = (WNDPROC)SetWindowLongPtrW(infoPtr->hwndEdit, - GWLP_WNDPROC, (DWORD_PTR)COMBOEX_EditWndProc); - infoPtr->font = (HFONT)SendMessageW(infoPtr->hwndCombo, WM_GETFONT, 0, 0); - } - - /* - * Locate the default font if necessary and then set it in - * all associated controls - */ - if (!infoPtr->font) { - SystemParametersInfoW (SPI_GETICONTITLELOGFONT, sizeof(mylogfont), - &mylogfont, 0); - infoPtr->font = infoPtr->defaultFont = CreateFontIndirectW (&mylogfont); - } - SendMessageW (infoPtr->hwndCombo, WM_SETFONT, (WPARAM)infoPtr->font, 0); - if (infoPtr->hwndEdit) { - SendMessageW (infoPtr->hwndEdit, WM_SETFONT, (WPARAM)infoPtr->font, 0); - SendMessageW (infoPtr->hwndEdit, EM_SETMARGINS, (WPARAM)EC_USEFONTINFO, 0); - } - - COMBOEX_ReSize (infoPtr); - - /* Above is fairly certain, below is much less certain. */ - - GetWindowRect(hwnd, &wnrc1); - GetClientRect(hwnd, &clrc1); - GetWindowRect(infoPtr->hwndCombo, &cmbwrc); - TRACE("EX window=(%ld,%ld)-(%ld,%ld) client=(%ld,%ld)-(%ld,%ld) CB wnd=(%ld,%ld)-(%ld,%ld)\n", - wnrc1.left, wnrc1.top, wnrc1.right, wnrc1.bottom, - clrc1.left, clrc1.top, clrc1.right, clrc1.bottom, - cmbwrc.left, cmbwrc.top, cmbwrc.right, cmbwrc.bottom); - SetWindowPos(infoPtr->hwndCombo, HWND_TOP, - 0, 0, wnrc1.right-wnrc1.left, wnrc1.bottom-wnrc1.top, - SWP_NOACTIVATE | SWP_NOREDRAW); - - GetWindowRect(infoPtr->hwndCombo, &cmbwrc); - TRACE("CB window=(%ld,%ld)-(%ld,%ld)\n", - cmbwrc.left, cmbwrc.top, cmbwrc.right, cmbwrc.bottom); - SetWindowPos(hwnd, HWND_TOP, - 0, 0, cmbwrc.right-cmbwrc.left, cmbwrc.bottom-cmbwrc.top, - SWP_NOACTIVATE | SWP_NOZORDER | SWP_NOMOVE); - - COMBOEX_AdjustEditPos (infoPtr); - - /* - * Create an item structure to represent the data in the - * EDIT control. It is allocated zero-filled. - */ - infoPtr->edit = (CBE_ITEMDATA *)Alloc (sizeof (CBE_ITEMDATA)); - if (!infoPtr->edit) { - COMBOEX_Destroy(infoPtr); - return -1; - } - - return 0; -} - - -static LRESULT COMBOEX_Command (COMBOEX_INFO *infoPtr, WPARAM wParam, LPARAM lParam) -{ - LRESULT lret; - INT command = HIWORD(wParam); - CBE_ITEMDATA *item = 0; - WCHAR wintext[520]; - INT cursel, n, oldItem; - NMCBEENDEDITW cbeend; - DWORD oldflags; - HWND parent = infoPtr->hwndNotify; - - TRACE("for command %d\n", command); - - switch (command) - { - case CBN_DROPDOWN: - SetFocus (infoPtr->hwndCombo); - ShowWindow (infoPtr->hwndEdit, SW_HIDE); - return SendMessageW (parent, WM_COMMAND, wParam, (LPARAM)infoPtr->hwndSelf); - - case CBN_CLOSEUP: - SendMessageW (parent, WM_COMMAND, wParam, (LPARAM)infoPtr->hwndSelf); - /* - * from native trace of first dropdown after typing in URL in IE4 - * CB_GETCURSEL(Combo) - * GetWindowText(Edit) - * CB_GETCURSEL(Combo) - * CB_GETCOUNT(Combo) - * CB_GETITEMDATA(Combo, n) - * WM_NOTIFY(parent, CBEN_ENDEDITA|W) - * CB_GETCURSEL(Combo) - * CB_SETCURSEL(COMBOEX, n) - * SetFocus(Combo) - * the rest is supposition - */ - ShowWindow (infoPtr->hwndEdit, SW_SHOW); - InvalidateRect (infoPtr->hwndCombo, 0, TRUE); - InvalidateRect (infoPtr->hwndEdit, 0, TRUE); - cursel = SendMessageW (infoPtr->hwndCombo, CB_GETCURSEL, 0, 0); - if (cursel == -1) { - cmp_func_t cmptext = get_cmp_func(infoPtr); - /* find match from edit against those in Combobox */ - GetWindowTextW (infoPtr->hwndEdit, wintext, 520); - n = SendMessageW (infoPtr->hwndCombo, CB_GETCOUNT, 0, 0); - for (cursel = 0; cursel < n; cursel++){ - item = get_item_data(infoPtr, cursel); - if ((INT)item == CB_ERR) break; - if (!cmptext(COMBOEX_GetText(infoPtr, item), wintext)) break; - } - if ((cursel == n) || ((INT)item == CB_ERR)) { - TRACE("failed to find match??? item=%p cursel=%d\n", - item, cursel); - if (infoPtr->hwndEdit) - SetFocus(infoPtr->hwndEdit); - return 0; - } - } - else { - item = get_item_data(infoPtr, cursel); - if ((INT)item == CB_ERR) { - TRACE("failed to find match??? item=%p cursel=%d\n", - item, cursel); - if (infoPtr->hwndEdit) - SetFocus(infoPtr->hwndEdit); - return 0; - } - } - - /* Save flags for testing and reset them */ - oldflags = infoPtr->flags; - infoPtr->flags &= ~(WCBE_ACTEDIT | WCBE_EDITCHG); - - if (oldflags & WCBE_ACTEDIT) { - cbeend.fChanged = (oldflags & WCBE_EDITCHG); - cbeend.iNewSelection = SendMessageW (infoPtr->hwndCombo, - CB_GETCURSEL, 0, 0); - cbeend.iWhy = CBENF_DROPDOWN; - - if (COMBOEX_NotifyEndEdit (infoPtr, &cbeend, COMBOEX_GetText(infoPtr, item))) return 0; - } - - /* if selection has changed the set the new current selection */ - cursel = SendMessageW (infoPtr->hwndCombo, CB_GETCURSEL, 0, 0); - if ((oldflags & WCBE_EDITCHG) || (cursel != infoPtr->selected)) { - infoPtr->selected = cursel; - SendMessageW (infoPtr->hwndSelf, CB_SETCURSEL, cursel, 0); - SetFocus(infoPtr->hwndCombo); - } - return 0; - - case CBN_SELCHANGE: - /* - * CB_GETCURSEL(Combo) - * CB_GETITEMDATA(Combo) < simulated by COMBOEX_FindItem - * lstrlenA - * WM_SETTEXT(Edit) - * WM_GETTEXTLENGTH(Edit) - * WM_GETTEXT(Edit) - * EM_SETSEL(Edit, 0,0) - * WM_GETTEXTLENGTH(Edit) - * WM_GETTEXT(Edit) - * EM_SETSEL(Edit, 0,len) - * return WM_COMMAND to parent - */ - oldItem = SendMessageW (infoPtr->hwndCombo, CB_GETCURSEL, 0, 0); - if (!(item = COMBOEX_FindItem(infoPtr, oldItem))) { - ERR("item %d not found. Problem!\n", oldItem); - break; - } - infoPtr->selected = oldItem; - COMBOEX_SetEditText (infoPtr, item); - return SendMessageW (parent, WM_COMMAND, wParam, (LPARAM)infoPtr->hwndSelf); - - case CBN_SELENDOK: - /* - * We have to change the handle since we are the control - * issuing the message. IE4 depends on this. - */ - return SendMessageW (parent, WM_COMMAND, wParam, (LPARAM)infoPtr->hwndSelf); - - case CBN_KILLFOCUS: - /* - * from native trace: - * - * pass to parent - * WM_GETTEXT(Edit, 104) - * CB_GETCURSEL(Combo) rets -1 - * WM_NOTIFY(CBEN_ENDEDITA) with CBENF_KILLFOCUS - * CB_GETCURSEL(Combo) - * InvalidateRect(Combo, 0, 0) - * return 0 - */ - SendMessageW (parent, WM_COMMAND, wParam, (LPARAM)infoPtr->hwndSelf); - if (infoPtr->flags & WCBE_ACTEDIT) { - GetWindowTextW (infoPtr->hwndEdit, wintext, 260); - cbeend.fChanged = (infoPtr->flags & WCBE_EDITCHG); - cbeend.iNewSelection = SendMessageW (infoPtr->hwndCombo, - CB_GETCURSEL, 0, 0); - cbeend.iWhy = CBENF_KILLFOCUS; - - infoPtr->flags &= ~(WCBE_ACTEDIT | WCBE_EDITCHG); - if (COMBOEX_NotifyEndEdit (infoPtr, &cbeend, wintext)) return 0; - } - /* possible CB_GETCURSEL */ - InvalidateRect (infoPtr->hwndCombo, 0, 0); - return 0; - - default: - /* - * We have to change the handle since we are the control - * issuing the message. IE4 depends on this. - * We also need to set the focus back to the Edit control - * after passing the command to the parent of the ComboEx. - */ - lret = SendMessageW (parent, WM_COMMAND, wParam, (LPARAM)infoPtr->hwndSelf); - if (infoPtr->hwndEdit) - SetFocus(infoPtr->hwndEdit); - return lret; - } - return 0; -} - - -static BOOL COMBOEX_WM_DeleteItem (COMBOEX_INFO *infoPtr, DELETEITEMSTRUCT *dis) -{ - CBE_ITEMDATA *item, *olditem; - NMCOMBOBOXEXW nmcit; - UINT i; - - TRACE("CtlType=%08x, CtlID=%08x, itemID=%08x, hwnd=%p, data=%08lx\n", - dis->CtlType, dis->CtlID, dis->itemID, dis->hwndItem, dis->itemData); - - if (dis->itemID >= infoPtr->nb_items) return FALSE; - - olditem = infoPtr->items; - i = infoPtr->nb_items - 1; - - if (i == dis->itemID) { - infoPtr->items = infoPtr->items->next; - } - else { - item = olditem; - i--; - - /* find the prior item in the list */ - while (item->next && (i > dis->itemID)) { - item = item->next; - i--; - } - if (!item->next || (i != dis->itemID)) { - ERR("COMBOBOXEX item structures broken. Please report!\n"); - return FALSE; - } - olditem = item->next; - item->next = item->next->next; - } - infoPtr->nb_items--; - - memset (&nmcit.ceItem, 0, sizeof(nmcit.ceItem)); - COMBOEX_CopyItem (olditem, &nmcit.ceItem); - COMBOEX_NotifyItem (infoPtr, CBEN_DELETEITEM, &nmcit); - - COMBOEX_FreeText(olditem); - Free(olditem); - - return TRUE; -} - - -static LRESULT COMBOEX_DrawItem (COMBOEX_INFO *infoPtr, DRAWITEMSTRUCT *dis) -{ - static const WCHAR nil[] = { 0 }; - CBE_ITEMDATA *item = 0; - SIZE txtsize; - RECT rect; - LPCWSTR str = nil; - UINT xbase, x, y; - INT len; - COLORREF nbkc, ntxc, bkc, txc; - int drawimage, drawstate, xioff; - - if (!IsWindowEnabled(infoPtr->hwndCombo)) return 0; - - TRACE("DRAWITEMSTRUCT: CtlType=0x%08x CtlID=0x%08x\n", - dis->CtlType, dis->CtlID); - TRACE("itemID=0x%08x itemAction=0x%08x itemState=0x%08x\n", - dis->itemID, dis->itemAction, dis->itemState); - TRACE("hWnd=%p hDC=%p (%ld,%ld)-(%ld,%ld) itemData=0x%08lx\n", - dis->hwndItem, dis->hDC, dis->rcItem.left, - dis->rcItem.top, dis->rcItem.right, dis->rcItem.bottom, - dis->itemData); - - /* MSDN says: */ - /* "itemID - Specifies the menu item identifier for a menu */ - /* item or the index of the item in a list box or combo box. */ - /* For an empty list box or combo box, this member can be -1. */ - /* This allows the application to draw only the focus */ - /* rectangle at the coordinates specified by the rcItem */ - /* member even though there are no items in the control. */ - /* This indicates to the user whether the list box or combo */ - /* box has the focus. How the bits are set in the itemAction */ - /* member determines whether the rectangle is to be drawn as */ - /* though the list box or combo box has the focus. */ - if (dis->itemID == 0xffffffff) { - if ( ( (dis->itemAction & ODA_FOCUS) && (dis->itemState & ODS_SELECTED)) || - ( (dis->itemAction & (ODA_SELECT | ODA_DRAWENTIRE)) && (dis->itemState & ODS_FOCUS) ) ) { - - TRACE("drawing item -1 special focus, rect=(%ld,%ld)-(%ld,%ld)\n", - dis->rcItem.left, dis->rcItem.top, - dis->rcItem.right, dis->rcItem.bottom); - } - else if ((dis->CtlType == ODT_COMBOBOX) && - (dis->itemAction == ODA_DRAWENTIRE)) { - /* draw of edit control data */ - - /* testing */ - { - RECT exrc, cbrc, edrc; - GetWindowRect (infoPtr->hwndSelf, &exrc); - GetWindowRect (infoPtr->hwndCombo, &cbrc); - edrc.left=edrc.top=edrc.right=edrc.bottom=-1; - if (infoPtr->hwndEdit) - GetWindowRect (infoPtr->hwndEdit, &edrc); - TRACE("window rects ex=(%ld,%ld)-(%ld,%ld), cb=(%ld,%ld)-(%ld,%ld), ed=(%ld,%ld)-(%ld,%ld)\n", - exrc.left, exrc.top, exrc.right, exrc.bottom, - cbrc.left, cbrc.top, cbrc.right, cbrc.bottom, - edrc.left, edrc.top, edrc.right, edrc.bottom); - } - } - else { - ERR("NOT drawing item -1 special focus, rect=(%ld,%ld)-(%ld,%ld), action=%08x, state=%08x\n", - dis->rcItem.left, dis->rcItem.top, - dis->rcItem.right, dis->rcItem.bottom, - dis->itemAction, dis->itemState); - return 0; - } - } - - /* If draw item is -1 (edit control) setup the item pointer */ - if (dis->itemID == 0xffffffff) { - item = infoPtr->edit; - - if (infoPtr->hwndEdit) { - INT len; - - /* free previous text of edit item */ - COMBOEX_FreeText(item); - item->mask &= ~CBEIF_TEXT; - if( (len = GetWindowTextLengthW(infoPtr->hwndEdit)) ) { - item->mask |= CBEIF_TEXT; - item->pszText = (LPWSTR)Alloc ((len + 1)*sizeof(WCHAR)); - if (item->pszText) - GetWindowTextW(infoPtr->hwndEdit, item->pszText, len+1); - - TRACE("edit control hwndEdit=%p, text len=%d str=%s\n", - infoPtr->hwndEdit, len, debugstr_txt(item->pszText)); - } - } - } - - - /* if the item pointer is not set, then get the data and locate it */ - if (!item) { - item = get_item_data(infoPtr, dis->itemID); - if (item == (CBE_ITEMDATA *)CB_ERR) { - ERR("invalid item for id %d \n", dis->itemID); - return 0; - } - } - - if (TRACE_ON(comboex)) COMBOEX_DumpItem (item); - - xbase = CBE_STARTOFFSET; - if ((item->mask & CBEIF_INDENT) && (dis->itemState & ODS_COMBOEXLBOX)) { - INT indent = item->iIndent; - if (indent == I_INDENTCALLBACK) { - NMCOMBOBOXEXW nmce; - ZeroMemory(&nmce, sizeof(nmce)); - nmce.ceItem.mask = CBEIF_INDENT; - nmce.ceItem.lParam = item->lParam; - COMBOEX_NotifyItem(infoPtr, CBEN_GETDISPINFOW, &nmce); - if (nmce.ceItem.mask & CBEIF_DI_SETITEM) - item->iIndent = nmce.ceItem.iIndent; - indent = nmce.ceItem.iIndent; - } - xbase += (indent * CBE_INDENT); - } - - drawimage = -2; - drawstate = ILD_NORMAL; - if (item->mask & CBEIF_IMAGE) - drawimage = item->iImage; - if (dis->itemState & ODS_COMBOEXLBOX) { - /* drawing listbox entry */ - if (dis->itemState & ODS_SELECTED) { - if (item->mask & CBEIF_SELECTEDIMAGE) - drawimage = item->iSelectedImage; - drawstate = ILD_SELECTED; - } - } else { - /* drawing combo/edit entry */ - if (IsWindowVisible(infoPtr->hwndEdit)) { - /* if we have an edit control, the slave the - * selection state to the Edit focus state - */ - if (infoPtr->flags & WCBE_EDITFOCUSED) { - if (item->mask & CBEIF_SELECTEDIMAGE) - drawimage = item->iSelectedImage; - drawstate = ILD_SELECTED; - } - } else { - /* if we don't have an edit control, use - * the requested state. - */ - if (dis->itemState & ODS_SELECTED) { - if (item->mask & CBEIF_SELECTEDIMAGE) - drawimage = item->iSelectedImage; - drawstate = ILD_SELECTED; - } - } - } - - if (infoPtr->himl && !(infoPtr->dwExtStyle & CBES_EX_NOEDITIMAGEINDENT)) { - IMAGEINFO iinfo; - iinfo.rcImage.left = iinfo.rcImage.right = 0; - ImageList_GetImageInfo(infoPtr->himl, 0, &iinfo); - xioff = iinfo.rcImage.right - iinfo.rcImage.left + CBE_SEP; - } else xioff = 0; - - /* setup pointer to text to be drawn */ - str = COMBOEX_GetText(infoPtr, item); - if (!str) str = nil; - - len = strlenW (str); - GetTextExtentPoint32W (dis->hDC, str, len, &txtsize); - - if (dis->itemAction & (ODA_SELECT | ODA_DRAWENTIRE)) { - int overlay = item->iOverlay; - - if (drawimage == I_IMAGECALLBACK) { - NMCOMBOBOXEXW nmce; - ZeroMemory(&nmce, sizeof(nmce)); - nmce.ceItem.mask = (drawstate == ILD_NORMAL) ? CBEIF_IMAGE : CBEIF_SELECTEDIMAGE; - nmce.ceItem.lParam = item->lParam; - COMBOEX_NotifyItem(infoPtr, CBEN_GETDISPINFOW, &nmce); - if (drawstate == ILD_NORMAL) { - if (nmce.ceItem.mask & CBEIF_DI_SETITEM) item->iImage = nmce.ceItem.iImage; - drawimage = nmce.ceItem.iImage; - } else if (drawstate == ILD_SELECTED) { - if (nmce.ceItem.mask & CBEIF_DI_SETITEM) item->iSelectedImage = nmce.ceItem.iSelectedImage; - drawimage = nmce.ceItem.iSelectedImage; - } else ERR("Bad draw state = %d\n", drawstate); - } - - if (overlay == I_IMAGECALLBACK) { - NMCOMBOBOXEXW nmce; - ZeroMemory(&nmce, sizeof(nmce)); - nmce.ceItem.mask = CBEIF_OVERLAY; - nmce.ceItem.lParam = item->lParam; - COMBOEX_NotifyItem(infoPtr, CBEN_GETDISPINFOW, &nmce); - if (nmce.ceItem.mask & CBEIF_DI_SETITEM) - item->iOverlay = nmce.ceItem.iOverlay; - overlay = nmce.ceItem.iOverlay; - } - - if (drawimage >= 0 && - !(infoPtr->dwExtStyle & (CBES_EX_NOEDITIMAGE | CBES_EX_NOEDITIMAGEINDENT))) { - if (overlay > 0) ImageList_SetOverlayImage (infoPtr->himl, overlay, 1); - ImageList_Draw (infoPtr->himl, drawimage, dis->hDC, xbase, dis->rcItem.top, - drawstate | (overlay > 0 ? INDEXTOOVERLAYMASK(1) : 0)); - } - - /* now draw the text */ - if (!IsWindowVisible (infoPtr->hwndEdit)) { - nbkc = GetSysColor ((dis->itemState & ODS_SELECTED) ? - COLOR_HIGHLIGHT : COLOR_WINDOW); - bkc = SetBkColor (dis->hDC, nbkc); - ntxc = GetSysColor ((dis->itemState & ODS_SELECTED) ? - COLOR_HIGHLIGHTTEXT : COLOR_WINDOWTEXT); - txc = SetTextColor (dis->hDC, ntxc); - x = xbase + xioff; - y = dis->rcItem.top + - (dis->rcItem.bottom - dis->rcItem.top - txtsize.cy) / 2; - rect.left = x; - rect.right = x + txtsize.cx; - rect.top = dis->rcItem.top + 1; - rect.bottom = dis->rcItem.bottom - 1; - TRACE("drawing item %d text, rect=(%ld,%ld)-(%ld,%ld)\n", - dis->itemID, rect.left, rect.top, rect.right, rect.bottom); - ExtTextOutW (dis->hDC, x, y, ETO_OPAQUE | ETO_CLIPPED, - &rect, str, len, 0); - SetBkColor (dis->hDC, bkc); - SetTextColor (dis->hDC, txc); - } - } - - if (dis->itemAction & ODA_FOCUS) { - rect.left = xbase + xioff - 1; - rect.right = rect.left + txtsize.cx + 2; - rect.top = dis->rcItem.top; - rect.bottom = dis->rcItem.bottom; - DrawFocusRect(dis->hDC, &rect); - } - - return 0; -} - - -static LRESULT COMBOEX_Destroy (COMBOEX_INFO *infoPtr) -{ - if (infoPtr->hwndCombo) - DestroyWindow (infoPtr->hwndCombo); - - if (infoPtr->edit) { - Free (infoPtr->edit); - infoPtr->edit = 0; - } - - if (infoPtr->items) { - CBE_ITEMDATA *item, *next; - - item = infoPtr->items; - while (item) { - next = item->next; - COMBOEX_FreeText (item); - Free (item); - item = next; - } - infoPtr->items = 0; - } - - if (infoPtr->defaultFont) - DeleteObject (infoPtr->defaultFont); - - /* free comboex info data */ - Free (infoPtr); - SetWindowLongPtrW (infoPtr->hwndSelf, 0, 0); - return 0; -} - - -static LRESULT COMBOEX_MeasureItem (COMBOEX_INFO *infoPtr, MEASUREITEMSTRUCT *mis) -{ - SIZE mysize; - HDC hdc; - - hdc = GetDC (0); - GetTextExtentPointA (hdc, "W", 1, &mysize); - ReleaseDC (0, hdc); - mis->itemHeight = mysize.cy + CBE_EXTRA; - - TRACE("adjusted height hwnd=%p, height=%d\n", - infoPtr->hwndSelf, mis->itemHeight); - - return 0; -} - - -static LRESULT COMBOEX_NCCreate (HWND hwnd) -{ - /* WARNING: The COMBOEX_INFO structure is not yet created */ - DWORD oldstyle, newstyle; - - oldstyle = (DWORD)GetWindowLongW (hwnd, GWL_STYLE); - newstyle = oldstyle & ~(WS_VSCROLL | WS_HSCROLL | WS_BORDER); - if (newstyle != oldstyle) { - TRACE("req style %08lx, reseting style %08lx\n", - oldstyle, newstyle); - SetWindowLongW (hwnd, GWL_STYLE, newstyle); - } - return 1; -} - - -static LRESULT COMBOEX_NotifyFormat (COMBOEX_INFO *infoPtr, LPARAM lParam) -{ - if (lParam == NF_REQUERY) { - INT i = SendMessageW(infoPtr->hwndNotify, - WM_NOTIFYFORMAT, (WPARAM)infoPtr->hwndSelf, NF_QUERY); - infoPtr->NtfUnicode = (i == NFR_UNICODE) ? 1 : 0; - } - return infoPtr->NtfUnicode ? NFR_UNICODE : NFR_ANSI; -} - - -static LRESULT COMBOEX_Size (COMBOEX_INFO *infoPtr, INT width, INT height) -{ - TRACE("(width=%d, height=%d)\n", width, height); - - MoveWindow (infoPtr->hwndCombo, 0, 0, width, height, TRUE); - - COMBOEX_AdjustEditPos (infoPtr); - - return 0; -} - - -static LRESULT COMBOEX_WindowPosChanging (COMBOEX_INFO *infoPtr, WINDOWPOS *wp) -{ - RECT cbx_wrect, cbx_crect, cb_wrect; - INT width, height; - - GetWindowRect (infoPtr->hwndSelf, &cbx_wrect); - GetClientRect (infoPtr->hwndSelf, &cbx_crect); - GetWindowRect (infoPtr->hwndCombo, &cb_wrect); - - /* width is winpos value + border width of comboex */ - width = wp->cx - + (cbx_wrect.right-cbx_wrect.left) - - (cbx_crect.right-cbx_crect.left); - - TRACE("winpos=(%d,%d %dx%d) flags=0x%08x\n", - wp->x, wp->y, wp->cx, wp->cy, wp->flags); - TRACE("EX window=(%ld,%ld)-(%ld,%ld), client=(%ld,%ld)-(%ld,%ld)\n", - cbx_wrect.left, cbx_wrect.top, cbx_wrect.right, cbx_wrect.bottom, - cbx_crect.left, cbx_crect.top, cbx_crect.right, cbx_crect.bottom); - TRACE("CB window=(%ld,%ld)-(%ld,%ld), EX setting=(0,0)-(%d,%ld)\n", - cb_wrect.left, cb_wrect.top, cb_wrect.right, cb_wrect.bottom, - width, cb_wrect.bottom-cb_wrect.top); - - if (width) SetWindowPos (infoPtr->hwndCombo, HWND_TOP, 0, 0, - width, - cb_wrect.bottom-cb_wrect.top, - SWP_NOACTIVATE); - - GetWindowRect (infoPtr->hwndCombo, &cb_wrect); - - /* height is combo window height plus border width of comboex */ - height = (cb_wrect.bottom-cb_wrect.top) - + (cbx_wrect.bottom-cbx_wrect.top) - - (cbx_crect.bottom-cbx_crect.top); - if (wp->cy < height) wp->cy = height; - if (infoPtr->hwndEdit) { - COMBOEX_AdjustEditPos (infoPtr); - InvalidateRect (infoPtr->hwndCombo, 0, TRUE); - } - - return 0; -} - -static LRESULT WINAPI -COMBOEX_EditWndProc (HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam) -{ - HWND hwndComboex = (HWND)GetPropA(hwnd, COMBOEX_SUBCLASS_PROP); - COMBOEX_INFO *infoPtr = COMBOEX_GetInfoPtr (hwndComboex); - NMCBEENDEDITW cbeend; - WCHAR edit_text[260]; - COLORREF obkc; - HDC hDC; - RECT rect; - LRESULT lret; - - TRACE("hwnd=%p msg=%x wparam=%x lParam=%lx, info_ptr=%p\n", - hwnd, uMsg, wParam, lParam, infoPtr); - - if (!infoPtr) return 0; - - switch (uMsg) - { - - case WM_CHAR: - /* handle (ignore) the return character */ - if (wParam == VK_RETURN) return 0; - /* all other characters pass into the real Edit */ - return CallWindowProcW (infoPtr->prevEditWndProc, - hwnd, uMsg, wParam, lParam); - - case WM_ERASEBKGND: - /* - * The following was determined by traces of the native - */ - hDC = (HDC) wParam; - obkc = SetBkColor (hDC, GetSysColor (COLOR_WINDOW)); - GetClientRect (hwnd, &rect); - TRACE("erasing (%ld,%ld)-(%ld,%ld)\n", - rect.left, rect.top, rect.right, rect.bottom); - ExtTextOutW (hDC, 0, 0, ETO_OPAQUE, &rect, 0, 0, 0); - SetBkColor (hDC, obkc); - return CallWindowProcW (infoPtr->prevEditWndProc, - hwnd, uMsg, wParam, lParam); - - case WM_KEYDOWN: { - INT oldItem, selected, step = 1; - CBE_ITEMDATA *item; - - switch ((INT)wParam) - { - case VK_ESCAPE: - /* native version seems to do following for COMBOEX */ - /* - * GetWindowTextA(Edit,&?, 0x104) x - * CB_GETCURSEL to Combo rets -1 x - * WM_NOTIFY to COMBOEX parent (rebar) x - * (CBEN_ENDEDIT{A|W} - * fChanged = FALSE x - * inewSelection = -1 x - * txt="www.hoho" x - * iWhy = 3 x - * CB_GETCURSEL to Combo rets -1 x - * InvalidateRect(Combo, 0) x - * WM_SETTEXT to Edit x - * EM_SETSEL to Edit (0,0) x - * EM_SETSEL to Edit (0,-1) x - * RedrawWindow(Combo, 0, 0, 5) x - */ - TRACE("special code for VK_ESCAPE\n"); - - GetWindowTextW (infoPtr->hwndEdit, edit_text, 260); - - infoPtr->flags &= ~(WCBE_ACTEDIT | WCBE_EDITCHG); - cbeend.fChanged = FALSE; - cbeend.iNewSelection = SendMessageW (infoPtr->hwndCombo, - CB_GETCURSEL, 0, 0); - cbeend.iWhy = CBENF_ESCAPE; - - if (COMBOEX_NotifyEndEdit (infoPtr, &cbeend, edit_text)) return 0; - oldItem = SendMessageW (infoPtr->hwndCombo, CB_GETCURSEL, 0, 0); - InvalidateRect (infoPtr->hwndCombo, 0, 0); - if (!(item = COMBOEX_FindItem(infoPtr, oldItem))) { - ERR("item %d not found. Problem!\n", oldItem); - break; - } - infoPtr->selected = oldItem; - COMBOEX_SetEditText (infoPtr, item); - RedrawWindow (infoPtr->hwndCombo, 0, 0, RDW_ERASE | - RDW_INVALIDATE); - break; - - case VK_RETURN: - /* native version seems to do following for COMBOEX */ - /* - * GetWindowTextA(Edit,&?, 0x104) x - * CB_GETCURSEL to Combo rets -1 x - * CB_GETCOUNT to Combo rets 0 - * if >0 loop - * CB_GETITEMDATA to match - * *** above 3 lines simulated by FindItem x - * WM_NOTIFY to COMBOEX parent (rebar) x - * (CBEN_ENDEDIT{A|W} x - * fChanged = TRUE (-1) x - * iNewSelection = -1 or selected x - * txt= x - * iWhy = 2 (CBENF_RETURN) x - * CB_GETCURSEL to Combo rets -1 x - * if -1 send CB_SETCURSEL to Combo -1 x - * InvalidateRect(Combo, 0, 0) x - * SetFocus(Edit) x - * CallWindowProc(406615a8, Edit, 0x100, 0xd, 0x1c0001) - */ - - TRACE("special code for VK_RETURN\n"); - - GetWindowTextW (infoPtr->hwndEdit, edit_text, 260); - - infoPtr->flags &= ~(WCBE_ACTEDIT | WCBE_EDITCHG); - selected = SendMessageW (infoPtr->hwndCombo, - CB_GETCURSEL, 0, 0); - - if (selected != -1) { - cmp_func_t cmptext = get_cmp_func(infoPtr); - item = COMBOEX_FindItem (infoPtr, selected); - TRACE("handling VK_RETURN, selected = %d, selected_text=%s\n", - selected, debugstr_txt(item->pszText)); - TRACE("handling VK_RETURN, edittext=%s\n", - debugstr_w(edit_text)); - if (cmptext (COMBOEX_GetText(infoPtr, item), edit_text)) { - /* strings not equal -- indicate edit has changed */ - selected = -1; - } - } - - cbeend.iNewSelection = selected; - cbeend.fChanged = TRUE; - cbeend.iWhy = CBENF_RETURN; - if (COMBOEX_NotifyEndEdit (infoPtr, &cbeend, edit_text)) { - /* abort the change, restore previous */ - TRACE("Notify requested abort of change\n"); - COMBOEX_SetEditText (infoPtr, infoPtr->edit); - RedrawWindow (infoPtr->hwndCombo, 0, 0, RDW_ERASE | - RDW_INVALIDATE); - return 0; - } - oldItem = SendMessageW (infoPtr->hwndCombo,CB_GETCURSEL, 0, 0); - if (oldItem != -1) { - /* if something is selected, then deselect it */ - SendMessageW (infoPtr->hwndCombo, CB_SETCURSEL, - (WPARAM)-1, 0); - } - InvalidateRect (infoPtr->hwndCombo, 0, 0); - SetFocus(infoPtr->hwndEdit); - break; - - case VK_UP: - step = -1; - case VK_DOWN: - /* by default, step is 1 */ - oldItem = SendMessageW (infoPtr->hwndSelf, CB_GETCURSEL, 0, 0); - if (oldItem >= 0 && oldItem + step >= 0) - SendMessageW (infoPtr->hwndSelf, CB_SETCURSEL, oldItem + step, 0); - return 0; - default: - return CallWindowProcW (infoPtr->prevEditWndProc, - hwnd, uMsg, wParam, lParam); - } - return 0; - } - - case WM_SETFOCUS: - /* remember the focus to set state of icon */ - lret = CallWindowProcW (infoPtr->prevEditWndProc, - hwnd, uMsg, wParam, lParam); - infoPtr->flags |= WCBE_EDITFOCUSED; - return lret; - - case WM_KILLFOCUS: - /* - * do NOTIFY CBEN_ENDEDIT with CBENF_KILLFOCUS - */ - infoPtr->flags &= ~WCBE_EDITFOCUSED; - if (infoPtr->flags & WCBE_ACTEDIT) { - infoPtr->flags &= ~(WCBE_ACTEDIT | WCBE_EDITCHG); - - GetWindowTextW (infoPtr->hwndEdit, edit_text, 260); - cbeend.fChanged = FALSE; - cbeend.iNewSelection = SendMessageW (infoPtr->hwndCombo, - CB_GETCURSEL, 0, 0); - cbeend.iWhy = CBENF_KILLFOCUS; - - COMBOEX_NotifyEndEdit (infoPtr, &cbeend, edit_text); - } - /* fall through */ - - default: - return CallWindowProcW (infoPtr->prevEditWndProc, - hwnd, uMsg, wParam, lParam); - } - return 0; -} - - -static LRESULT WINAPI -COMBOEX_ComboWndProc (HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam) -{ - HWND hwndComboex = (HWND)GetPropA(hwnd, COMBOEX_SUBCLASS_PROP); - COMBOEX_INFO *infoPtr = COMBOEX_GetInfoPtr (hwndComboex); - NMCBEENDEDITW cbeend; - NMMOUSE nmmse; - COLORREF obkc; - HDC hDC; - HWND focusedhwnd; - RECT rect; - POINT pt; - WCHAR edit_text[260]; - - TRACE("hwnd=%p msg=%x wparam=%x lParam=%lx, info_ptr=%p\n", - hwnd, uMsg, wParam, lParam, infoPtr); - - if (!infoPtr) return 0; - - switch (uMsg) - { - - case WM_DRAWITEM: - /* - * The only way this message should come is from the - * child Listbox issuing the message. Flag this so - * that ComboEx knows this is listbox. - */ - ((DRAWITEMSTRUCT *)lParam)->itemState |= ODS_COMBOEXLBOX; - return CallWindowProcW (infoPtr->prevComboWndProc, - hwnd, uMsg, wParam, lParam); - - case WM_ERASEBKGND: - /* - * The following was determined by traces of the native - */ - hDC = (HDC) wParam; - obkc = SetBkColor (hDC, GetSysColor (COLOR_WINDOW)); - GetClientRect (hwnd, &rect); - TRACE("erasing (%ld,%ld)-(%ld,%ld)\n", - rect.left, rect.top, rect.right, rect.bottom); - ExtTextOutW (hDC, 0, 0, ETO_OPAQUE, &rect, 0, 0, 0); - SetBkColor (hDC, obkc); - return CallWindowProcW (infoPtr->prevComboWndProc, - hwnd, uMsg, wParam, lParam); - - case WM_SETCURSOR: - /* - * WM_NOTIFY to comboex parent (rebar) - * with NM_SETCURSOR with extra words of 0,0,0,0,0x02010001 - * CallWindowProc (previous) - */ - nmmse.dwItemSpec = 0; - nmmse.dwItemData = 0; - nmmse.pt.x = 0; - nmmse.pt.y = 0; - nmmse.dwHitInfo = lParam; - COMBOEX_Notify (infoPtr, NM_SETCURSOR, (NMHDR *)&nmmse); - return CallWindowProcW (infoPtr->prevComboWndProc, - hwnd, uMsg, wParam, lParam); - - case WM_LBUTTONDOWN: - GetClientRect (hwnd, &rect); - rect.bottom = rect.top + SendMessageW(infoPtr->hwndSelf, - CB_GETITEMHEIGHT, -1, 0); - rect.left = rect.right - GetSystemMetrics(SM_CXVSCROLL); - pt.x = (short)LOWORD(lParam); - pt.y = (short)HIWORD(lParam); - if (PtInRect(&rect, pt)) - return CallWindowProcW (infoPtr->prevComboWndProc, - hwnd, uMsg, wParam, lParam); - infoPtr->flags |= WCBE_MOUSECAPTURED; - SetCapture(hwnd); - break; - - case WM_LBUTTONUP: - if (!(infoPtr->flags & WCBE_MOUSECAPTURED)) - return CallWindowProcW (infoPtr->prevComboWndProc, - hwnd, uMsg, wParam, lParam); - ReleaseCapture(); - infoPtr->flags &= ~WCBE_MOUSECAPTURED; - if (infoPtr->flags & WCBE_MOUSEDRAGGED) { - infoPtr->flags &= ~WCBE_MOUSEDRAGGED; - } else { - SendMessageW(hwnd, CB_SHOWDROPDOWN, TRUE, 0); - } - break; - - case WM_MOUSEMOVE: - if ( (infoPtr->flags & WCBE_MOUSECAPTURED) && - !(infoPtr->flags & WCBE_MOUSEDRAGGED)) { - GetWindowTextW (infoPtr->hwndEdit, edit_text, 260); - COMBOEX_NotifyDragBegin(infoPtr, edit_text); - infoPtr->flags |= WCBE_MOUSEDRAGGED; - } - return CallWindowProcW (infoPtr->prevComboWndProc, - hwnd, uMsg, wParam, lParam); - - case WM_COMMAND: - switch (HIWORD(wParam)) { - - case EN_UPDATE: - /* traces show that COMBOEX does not issue CBN_EDITUPDATE - * on the EN_UPDATE - */ - return 0; - - case EN_KILLFOCUS: - /* - * Native does: - * - * GetFocus() retns AA - * GetWindowTextA(Edit) - * CB_GETCURSEL(Combo) (got -1) - * WM_NOTIFY(CBEN_ENDEDITA) with CBENF_KILLFOCUS - * CB_GETCURSEL(Combo) (got -1) - * InvalidateRect(Combo, 0, 0) - * WM_KILLFOCUS(Combo, AA) - * return 0; - */ - focusedhwnd = GetFocus(); - if (infoPtr->flags & WCBE_ACTEDIT) { - GetWindowTextW (infoPtr->hwndEdit, edit_text, 260); - cbeend.fChanged = (infoPtr->flags & WCBE_EDITCHG); - cbeend.iNewSelection = SendMessageW (infoPtr->hwndCombo, - CB_GETCURSEL, 0, 0); - cbeend.iWhy = CBENF_KILLFOCUS; - - infoPtr->flags &= ~(WCBE_ACTEDIT | WCBE_EDITCHG); - if (COMBOEX_NotifyEndEdit (infoPtr, &cbeend, edit_text)) return 0; - } - /* possible CB_GETCURSEL */ - InvalidateRect (infoPtr->hwndCombo, 0, 0); - if (focusedhwnd) - SendMessageW (infoPtr->hwndCombo, WM_KILLFOCUS, - (WPARAM)focusedhwnd, 0); - return 0; - - case EN_SETFOCUS: { - /* - * For EN_SETFOCUS this issues the same calls and messages - * as the native seems to do. - * - * for some cases however native does the following: - * (noticed after SetFocus during LBUTTONDOWN on - * on dropdown arrow) - * WM_GETTEXTLENGTH (Edit); - * WM_GETTEXT (Edit, len+1, str); - * EM_SETSEL (Edit, 0, 0); - * WM_GETTEXTLENGTH (Edit); - * WM_GETTEXT (Edit, len+1, str); - * EM_SETSEL (Edit, 0, len); - * WM_NOTIFY (parent, CBEN_BEGINEDIT) - */ - NMHDR hdr; - - SendMessageW (infoPtr->hwndEdit, EM_SETSEL, 0, 0); - SendMessageW (infoPtr->hwndEdit, EM_SETSEL, 0, -1); - COMBOEX_Notify (infoPtr, CBEN_BEGINEDIT, &hdr); - infoPtr->flags |= WCBE_ACTEDIT; - infoPtr->flags &= ~WCBE_EDITCHG; /* no change yet */ - return 0; - } - - case EN_CHANGE: { - /* - * For EN_CHANGE this issues the same calls and messages - * as the native seems to do. - */ - WCHAR edit_text[260]; - LPCWSTR lastwrk; - cmp_func_t cmptext = get_cmp_func(infoPtr); - - INT selected = SendMessageW (infoPtr->hwndCombo, - CB_GETCURSEL, 0, 0); - - /* lstrlenA( lastworkingURL ) */ - - GetWindowTextW (infoPtr->hwndEdit, edit_text, 260); - if (selected == -1) { - lastwrk = infoPtr->edit->pszText; - } - else { - CBE_ITEMDATA *item = COMBOEX_FindItem (infoPtr, selected); - lastwrk = COMBOEX_GetText(infoPtr, item); - } - - TRACE("handling EN_CHANGE, selected = %d, selected_text=%s\n", - selected, debugstr_w(lastwrk)); - TRACE("handling EN_CHANGE, edittext=%s\n", - debugstr_w(edit_text)); - - /* cmptext is between lastworkingURL and GetWindowText */ - if (cmptext (lastwrk, edit_text)) { - /* strings not equal -- indicate edit has changed */ - infoPtr->flags |= WCBE_EDITCHG; - } - SendMessageW ( infoPtr->hwndNotify, WM_COMMAND, - MAKEWPARAM(GetDlgCtrlID (infoPtr->hwndSelf), - CBN_EDITCHANGE), - (LPARAM)infoPtr->hwndSelf); - return 0; - } - - case LBN_SELCHANGE: - /* - * Therefore from traces there is no additional code here - */ - - /* - * Using native COMCTL32 gets the following: - * 1 == SHDOCVW.DLL issues call/message - * 2 == COMCTL32.DLL issues call/message - * 3 == WINE issues call/message - * - * - * for LBN_SELCHANGE: - * 1 CB_GETCURSEL(ComboEx) - * 1 CB_GETDROPPEDSTATE(ComboEx) - * 1 CallWindowProc( *2* for WM_COMMAND(LBN_SELCHANGE) - * 2 CallWindowProc( *3* for WM_COMMAND(LBN_SELCHANGE) - ** call CBRollUp( xxx, TRUE for LBN_SELCHANGE, TRUE) - * 3 WM_COMMAND(ComboEx, CBN_SELENDOK) - * WM_USER+49(ComboLB, 1,0) <=============!!!!!!!!!!! - * 3 ShowWindow(ComboLB, SW_HIDE) - * 3 RedrawWindow(Combo, RDW_UPDATENOW) - * 3 WM_COMMAND(ComboEX, CBN_CLOSEUP) - ** end of CBRollUp - * 3 WM_COMMAND(ComboEx, CBN_SELCHANGE) (echo to parent) - * ? LB_GETCURSEL <==| - * ? LB_GETTEXTLEN | - * ? LB_GETTEXT | Needs to be added to - * ? WM_CTLCOLOREDIT(ComboEx) | Combo processing - * ? LB_GETITEMDATA | - * ? WM_DRAWITEM(ComboEx) <==| - */ - default: - break; - }/* fall through */ - default: - return CallWindowProcW (infoPtr->prevComboWndProc, - hwnd, uMsg, wParam, lParam); - } - return 0; -} - - -static LRESULT WINAPI -COMBOEX_WindowProc (HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam) -{ - COMBOEX_INFO *infoPtr = COMBOEX_GetInfoPtr (hwnd); - - TRACE("hwnd=%p msg=%x wparam=%x lParam=%lx\n", hwnd, uMsg, wParam, lParam); - - if (!infoPtr) { - if (uMsg == WM_CREATE) - return COMBOEX_Create (hwnd, (LPCREATESTRUCTA)lParam); - if (uMsg == WM_NCCREATE) - COMBOEX_NCCreate (hwnd); - return DefWindowProcW (hwnd, uMsg, wParam, lParam); - } - - switch (uMsg) - { - case CBEM_DELETEITEM: - return COMBOEX_DeleteItem (infoPtr, wParam); - - case CBEM_GETCOMBOCONTROL: - return (LRESULT)infoPtr->hwndCombo; - - case CBEM_GETEDITCONTROL: - return (LRESULT)infoPtr->hwndEdit; - - case CBEM_GETEXTENDEDSTYLE: - return infoPtr->dwExtStyle; - - case CBEM_GETIMAGELIST: - return (LRESULT)infoPtr->himl; - - case CBEM_GETITEMA: - return (LRESULT)COMBOEX_GetItemA (infoPtr, (COMBOBOXEXITEMA *)lParam); - - case CBEM_GETITEMW: - return (LRESULT)COMBOEX_GetItemW (infoPtr, (COMBOBOXEXITEMW *)lParam); - - case CBEM_GETUNICODEFORMAT: - return infoPtr->unicode; - - case CBEM_HASEDITCHANGED: - return COMBOEX_HasEditChanged (infoPtr); - - case CBEM_INSERTITEMA: - return COMBOEX_InsertItemA (infoPtr, (COMBOBOXEXITEMA *)lParam); - - case CBEM_INSERTITEMW: - return COMBOEX_InsertItemW (infoPtr, (COMBOBOXEXITEMW *)lParam); - - case CBEM_SETEXSTYLE: - case CBEM_SETEXTENDEDSTYLE: - return COMBOEX_SetExtendedStyle (infoPtr, (DWORD)wParam, (DWORD)lParam); - - case CBEM_SETIMAGELIST: - return (LRESULT)COMBOEX_SetImageList (infoPtr, (HIMAGELIST)lParam); - - case CBEM_SETITEMA: - return COMBOEX_SetItemA (infoPtr, (COMBOBOXEXITEMA *)lParam); - - case CBEM_SETITEMW: - return COMBOEX_SetItemW (infoPtr, (COMBOBOXEXITEMW *)lParam); - - case CBEM_SETUNICODEFORMAT: - return COMBOEX_SetUnicodeFormat (infoPtr, wParam); - - /*case CBEM_SETWINDOWTHEME: - FIXME("CBEM_SETWINDOWTHEME: stub\n");*/ - - case WM_SETTEXT: - case WM_GETTEXT: - return SendMessageW(infoPtr->hwndEdit, uMsg, wParam, lParam); - -/* Combo messages we are not sure if we need to process or just forward */ - case CB_GETDROPPEDCONTROLRECT: - case CB_GETITEMHEIGHT: - case CB_GETLBTEXT: - case CB_GETLBTEXTLEN: - case CB_GETEXTENDEDUI: - case CB_LIMITTEXT: - case CB_RESETCONTENT: - case CB_SELECTSTRING: - -/* Combo messages OK to just forward to the regular COMBO */ - case CB_GETCOUNT: - case CB_GETCURSEL: - case CB_GETDROPPEDSTATE: - case CB_SETDROPPEDWIDTH: - case CB_SETEXTENDEDUI: - case CB_SHOWDROPDOWN: - return SendMessageW (infoPtr->hwndCombo, uMsg, wParam, lParam); - -/* Combo messages we need to process specially */ - case CB_FINDSTRINGEXACT: - return COMBOEX_FindStringExact (infoPtr, (INT)wParam, (LPCWSTR)lParam); - - case CB_GETITEMDATA: - return COMBOEX_GetItemData (infoPtr, (INT)wParam); - - case CB_SETCURSEL: - return COMBOEX_SetCursel (infoPtr, (INT)wParam); - - case CB_SETITEMDATA: - return COMBOEX_SetItemData (infoPtr, (INT)wParam, (DWORD)lParam); - - case CB_SETITEMHEIGHT: - return COMBOEX_SetItemHeight (infoPtr, (INT)wParam, (UINT)lParam); - - - -/* Window messages passed to parent */ - case WM_COMMAND: - return COMBOEX_Command (infoPtr, wParam, lParam); - - case WM_NOTIFY: - if (infoPtr->NtfUnicode) - return SendMessageW (infoPtr->hwndNotify, uMsg, wParam, lParam); - else - return SendMessageA (infoPtr->hwndNotify, uMsg, wParam, lParam); - - -/* Window messages we need to process */ - case WM_DELETEITEM: - return COMBOEX_WM_DeleteItem (infoPtr, (DELETEITEMSTRUCT *)lParam); - - case WM_DRAWITEM: - return COMBOEX_DrawItem (infoPtr, (DRAWITEMSTRUCT *)lParam); - - case WM_DESTROY: - return COMBOEX_Destroy (infoPtr); - - case WM_MEASUREITEM: - return COMBOEX_MeasureItem (infoPtr, (MEASUREITEMSTRUCT *)lParam); - - case WM_NOTIFYFORMAT: - return COMBOEX_NotifyFormat (infoPtr, lParam); - - case WM_SIZE: - return COMBOEX_Size (infoPtr, LOWORD(lParam), HIWORD(lParam)); - - case WM_WINDOWPOSCHANGING: - return COMBOEX_WindowPosChanging (infoPtr, (WINDOWPOS *)lParam); - - case WM_SETFOCUS: - SetFocus(infoPtr->hwndCombo); - return 0; - - default: - if ((uMsg >= WM_USER) && (uMsg < WM_APP)) - ERR("unknown msg %04x wp=%08x lp=%08lx\n",uMsg,wParam,lParam); - return DefWindowProcW (hwnd, uMsg, wParam, lParam); - } - return 0; -} - - -void COMBOEX_Register (void) -{ - WNDCLASSW wndClass; - - ZeroMemory (&wndClass, sizeof(WNDCLASSW)); - wndClass.style = CS_GLOBALCLASS; - wndClass.lpfnWndProc = COMBOEX_WindowProc; - wndClass.cbClsExtra = 0; - wndClass.cbWndExtra = sizeof(COMBOEX_INFO *); - wndClass.hCursor = LoadCursorW (0, (LPWSTR)IDC_ARROW); - wndClass.hbrBackground = (HBRUSH)(COLOR_WINDOW + 1); - wndClass.lpszClassName = WC_COMBOBOXEXW; - - RegisterClassW (&wndClass); -} - - -void COMBOEX_Unregister (void) -{ - UnregisterClassW (WC_COMBOBOXEXW, NULL); -} diff --git a/reactos/lib/comctl32/comctl32.h b/reactos/lib/comctl32/comctl32.h deleted file mode 100644 index a165ddd5b61..00000000000 --- a/reactos/lib/comctl32/comctl32.h +++ /dev/null @@ -1,194 +0,0 @@ -/****************************************************************************** - * - * Common definitions (resource ids and global variables) - * - * Copyright 1999 Thuy Nguyen - * Copyright 1999 Eric Kohl - * Copyright 2002 Dimitrie O. Paun - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2.1 of the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -#ifndef __WINE_COMCTL32_H -#define __WINE_COMCTL32_H - -#ifndef RC_INVOKED -#include -#endif - -#include "windef.h" -#include "winbase.h" -#include "wingdi.h" -#include "winuser.h" -#include "winnls.h" -#include "commctrl.h" - -extern HMODULE COMCTL32_hModule; -extern HBRUSH COMCTL32_hPattern55AABrush; - -/* Property sheet / Wizard */ -#define IDD_PROPSHEET 1006 -#define IDD_WIZARD 1020 - -#define IDC_TABCONTROL 12320 -#define IDC_APPLY_BUTTON 12321 -#define IDC_BACK_BUTTON 12323 -#define IDC_NEXT_BUTTON 12324 -#define IDC_FINISH_BUTTON 12325 -#define IDC_SUNKEN_LINE 12326 -#define IDC_SUNKEN_LINEHEADER 12327 - -#define IDS_CLOSE 4160 - -/* Toolbar customization dialog */ -#define IDD_TBCUSTOMIZE 200 - -#define IDC_AVAILBTN_LBOX 201 -#define IDC_RESET_BTN 202 -#define IDC_TOOLBARBTN_LBOX 203 -#define IDC_REMOVE_BTN 204 -#define IDC_HELP_BTN 205 -#define IDC_MOVEUP_BTN 206 -#define IDC_MOVEDN_BTN 207 - -#define IDS_SEPARATOR 1024 - -/* Toolbar imagelist bitmaps */ -#define IDB_STD_SMALL 120 -#define IDB_STD_LARGE 121 -#define IDB_VIEW_SMALL 124 -#define IDB_VIEW_LARGE 125 -#define IDB_HIST_SMALL 130 -#define IDB_HIST_LARGE 131 - - -/* Month calendar month menu popup */ -#define IDD_MCMONTHMENU 300 - -#define IDM_JAN 301 -#define IDM_FEB 302 -#define IDM_MAR 303 -#define IDM_APR 304 -#define IDM_MAY 305 -#define IDM_JUN 306 -#define IDM_JUL 307 -#define IDM_AUG 308 -#define IDM_SEP 309 -#define IDM_OCT 310 -#define IDM_NOV 311 -#define IDM_DEC 312 - -#define IDM_TODAY 4163 -#define IDM_GOTODAY 4164 - -/* Treeview Checkboxes */ - -#define IDT_CHECK 401 - - -/* Header cursors */ -#define IDC_DIVIDER 106 -#define IDC_DIVIDEROPEN 107 - - -/* DragList resources */ -#define IDI_DRAGARROW 501 -#define IDC_COPY 502 - -#define IDC_MOVEBUTTON 1 - -/* HOTKEY internal strings */ -#define HKY_NONE 2048 - -/* Tooltip icons */ -#define IDI_TT_INFO_SM 22 -#define IDI_TT_WARN_SM 25 -#define IDI_TT_ERROR_SM 28 - -typedef struct -{ - COLORREF clrBtnHighlight; /* COLOR_BTNHIGHLIGHT */ - COLORREF clrBtnShadow; /* COLOR_BTNSHADOW */ - COLORREF clrBtnText; /* COLOR_BTNTEXT */ - COLORREF clrBtnFace; /* COLOR_BTNFACE */ - COLORREF clrHighlight; /* COLOR_HIGHLIGHT */ - COLORREF clrHighlightText; /* COLOR_HIGHLIGHTTEXT */ - COLORREF clr3dHilight; /* COLOR_3DHILIGHT */ - COLORREF clr3dShadow; /* COLOR_3DSHADOW */ - COLORREF clr3dDkShadow; /* COLOR_3DDKSHADOW */ - COLORREF clr3dFace; /* COLOR_3DFACE */ - COLORREF clrWindow; /* COLOR_WINDOW */ - COLORREF clrWindowText; /* COLOR_WINDOWTEXT */ - COLORREF clrGrayText; /* COLOR_GREYTEXT */ - COLORREF clrActiveCaption; /* COLOR_ACTIVECAPTION */ - COLORREF clrInfoBk; /* COLOR_INFOBK */ - COLORREF clrInfoText; /* COLOR_INFOTEXT */ -} COMCTL32_SysColor; - -extern COMCTL32_SysColor comctl32_color; - -/* Internal function */ -HWND COMCTL32_CreateToolTip (HWND); -VOID COMCTL32_RefreshSysColors(void); -void COMCTL32_DrawInsertMark(HDC hDC, const RECT *lpRect, COLORREF clrInsertMark, BOOL bHorizontal); -INT Str_GetPtrWtoA (LPCWSTR lpSrc, LPSTR lpDest, INT nMaxLen); -BOOL Str_SetPtrAtoW (LPWSTR *lppDest, LPCSTR lpSrc); - -#define COMCTL32_VERSION_MINOR 80 -#define WINE_FILEVERSION 5, COMCTL32_VERSION_MINOR, 0, 0 -#define WINE_FILEVERSIONSTR "5.80" - -/* Our internal stack structure of the window procedures to subclass */ -typedef struct _SUBCLASSPROCS { - SUBCLASSPROC subproc; - UINT_PTR id; - DWORD_PTR ref; - struct _SUBCLASSPROCS *next; -} SUBCLASSPROCS, *LPSUBCLASSPROCS; - -typedef struct -{ - SUBCLASSPROCS *SubclassProcs; - SUBCLASSPROCS *stackpos; - WNDPROC origproc; - int running; -} SUBCLASS_INFO, *LPSUBCLASS_INFO; - -/* undocumented functions */ - -LPVOID WINAPI Alloc (DWORD); -LPVOID WINAPI ReAlloc (LPVOID, DWORD); -BOOL WINAPI Free (LPVOID); -DWORD WINAPI GetSize (LPVOID); - -INT WINAPI Str_GetPtrA (LPCSTR, LPSTR, INT); -INT WINAPI Str_GetPtrW (LPCWSTR, LPWSTR, INT); - -INT WINAPI DPA_GetPtrIndex (const HDPA, LPVOID); -BOOL WINAPI DPA_Grow (const HDPA, INT); - -#define DPAM_NOSORT 0x0001 -#define DPAM_INSERT 0x0004 -#define DPAM_DELETE 0x0008 - -typedef PVOID (CALLBACK *PFNDPAMERGE)(DWORD,PVOID,PVOID,LPARAM); -BOOL WINAPI DPA_Merge (const HDPA, const HDPA, DWORD, PFNDPACOMPARE, PFNDPAMERGE, LPARAM); - -#define DPA_GetPtrCount(hdpa) (*(INT*)(hdpa)) - -LRESULT WINAPI SetPathWordBreakProc(HWND hwnd, BOOL bSet); -BOOL WINAPI MirrorIcon(HICON *phicon1, HICON *phicon2); - -#endif /* __WINE_COMCTL32_H */ diff --git a/reactos/lib/comctl32/comctl32.spec b/reactos/lib/comctl32/comctl32.spec deleted file mode 100644 index 7af1bccea75..00000000000 --- a/reactos/lib/comctl32/comctl32.spec +++ /dev/null @@ -1,188 +0,0 @@ -# Functions exported by the Win95 comctl32.dll -# (these need to have these exact ordinals, because some win95 dlls -# import comctl32.dll by ordinal) -# This list was created from a comctl32.dll v5.81 (IE5.01). - - 2 stdcall MenuHelp(long long long long long long ptr) - 3 stdcall ShowHideMenuCtl(long long ptr) - 4 stdcall GetEffectiveClientRect(long long long) - 5 stdcall DrawStatusTextA(long ptr str long) - 6 stdcall CreateStatusWindowA(long str long long) - 7 stdcall CreateToolbar(long long long long long long ptr long) - 8 stdcall CreateMappedBitmap(long long long ptr long) - 9 stdcall -noname DPA_LoadStream(ptr ptr ptr long) - 10 stdcall -noname DPA_SaveStream(ptr ptr ptr long) - 11 stdcall -noname DPA_Merge(ptr ptr long ptr ptr long) -#12 stub Cctl1632_ThunkData32 - 13 stdcall MakeDragList(long) - 14 stdcall LBItemFromPt(long long long long) - 15 stdcall DrawInsert(long long long) - 16 stdcall CreateUpDownControl(long long long long long long long long long long long long) - 17 stdcall InitCommonControls() - 71 stdcall -noname Alloc(long) - 72 stdcall -noname ReAlloc(ptr long) - 73 stdcall -noname Free(ptr) - 74 stdcall -noname GetSize(ptr) -151 stdcall -noname CreateMRUListA(ptr) -152 stdcall -noname FreeMRUList(long) -153 stdcall -noname AddMRUStringA(long str) -154 stdcall -noname EnumMRUListA(long long ptr long) -155 stdcall -noname FindMRUStringA(long str ptr) -156 stdcall -noname DelMRUString(long long) -157 stdcall -noname CreateMRUListLazyA(ptr long long long) -163 stub -noname CreatePage -164 stub -noname CreateProxyPage -167 stdcall -noname AddMRUData(long ptr long) -169 stdcall -noname FindMRUData(long ptr long ptr) -233 stdcall -noname Str_GetPtrA(str str long) -234 stdcall -noname Str_SetPtrA(str str) -235 stdcall -noname Str_GetPtrW(wstr wstr long) -236 stdcall -noname Str_SetPtrW(wstr wstr) -320 stdcall -noname DSA_Create(long long) -321 stdcall -noname DSA_Destroy(ptr) -322 stdcall -noname DSA_GetItem(ptr long long) -323 stdcall -noname DSA_GetItemPtr(ptr long) -324 stdcall -noname DSA_InsertItem(ptr long long) -325 stdcall -noname DSA_SetItem (ptr long long) -326 stdcall -noname DSA_DeleteItem(ptr long) -327 stdcall -noname DSA_DeleteAllItems(ptr) -328 stdcall -noname DPA_Create(long) -329 stdcall -noname DPA_Destroy(ptr) -330 stdcall -noname DPA_Grow(ptr long) -331 stdcall -noname DPA_Clone(ptr ptr) -332 stdcall -noname DPA_GetPtr(ptr long) -333 stdcall -noname DPA_GetPtrIndex(ptr ptr) -334 stdcall -noname DPA_InsertPtr(ptr long ptr) -335 stdcall -noname DPA_SetPtr(ptr long ptr) -336 stdcall -noname DPA_DeletePtr(ptr long) -337 stdcall -noname DPA_DeleteAllPtrs(ptr) -338 stdcall -noname DPA_Sort(ptr ptr long) -339 stdcall -noname DPA_Search(ptr ptr long ptr long long) -340 stdcall -noname DPA_CreateEx(long long) -341 stdcall -noname SendNotify(long long long ptr) -342 stdcall -noname SendNotifyEx(long long long ptr long) -350 stdcall -noname StrChrA(str str) -351 stdcall -noname StrRChrA(str str long) -352 stdcall -noname StrCmpNA(str str long) -353 stdcall -noname StrCmpNIA(str str long) -354 stdcall -noname StrStrA(str str) -355 stdcall -noname StrStrIA(str str) -356 stdcall -noname StrCSpnA(str str) -357 stdcall -noname StrToIntA(str) -358 stdcall -noname StrChrW(wstr long) -359 stdcall -noname StrRChrW(wstr wstr long) -360 stdcall -noname StrCmpNW(wstr wstr long) -361 stdcall -noname StrCmpNIW(wstr wstr long) -362 stdcall -noname StrStrW(wstr wstr) -363 stdcall -noname StrStrIW(wstr wstr) -364 stdcall -noname StrCSpnW(wstr wstr) -365 stdcall -noname StrToIntW(wstr) -366 stdcall -noname StrChrIA(str long) -367 stdcall -noname StrChrIW(wstr long) -368 stdcall -noname StrRChrIA(str str long) -369 stdcall -noname StrRChrIW(wstr wstr long) -372 stdcall -noname StrRStrIA(str str str) -373 stdcall -noname StrRStrIW(wstr wstr wstr) -374 stdcall -noname StrCSpnIA(str str) -375 stdcall -noname StrCSpnIW(wstr wstr) -376 stdcall -noname IntlStrEqWorkerA(long str str long) -377 stdcall -noname IntlStrEqWorkerW(long wstr wstr long) -382 stdcall -noname SmoothScrollWindow(ptr) -383 stub -noname DoReaderMode -384 stdcall -noname SetPathWordBreakProc(ptr long) -385 stdcall -noname DPA_EnumCallback(long long long) -386 stdcall -noname DPA_DestroyCallback(ptr ptr long) -387 stdcall -noname DSA_EnumCallback(ptr ptr long) -388 stdcall -noname DSA_DestroyCallback(ptr ptr long) -389 stub -noname SHGetProcessDword -390 stdcall -noname ImageList_SetColorTable(ptr long long ptr) -400 stdcall -noname CreateMRUListW(ptr) -401 stdcall -noname AddMRUStringW(long wstr) -402 stdcall -noname FindMRUStringW(long wstr ptr) -403 stdcall -noname EnumMRUListW(long long ptr long) -404 stdcall -noname CreateMRUListLazyW(ptr long long long) -410 stdcall SetWindowSubclass(long ptr long long) -411 stdcall GetWindowSubclass(long ptr long ptr) -412 stdcall RemoveWindowSubclass(long ptr long) -413 stdcall DefSubclassProc(long long long long) -414 stdcall -noname MirrorIcon(ptr ptr) -415 stdcall DrawTextWrap(long wstr long ptr long) user32.DrawTextW -416 stdcall DrawTextExPrivWrap(long wstr long ptr long ptr) user32.DrawTextExW -417 stdcall ExtTextOutWrap(long long long long ptr wstr long ptr) gdi32.ExtTextOutW -418 stdcall GetCharWidthWrap(long long long long) gdi32.GetCharWidthW -419 stdcall GetTextExtentPointWrap(long wstr long ptr) gdi32.GetTextExtentPointW -420 stdcall GetTextExtentPoint32Wrap(long wstr long ptr) gdi32.GetTextExtentPoint32W -421 stdcall TextOutWrap(long long long wstr long) gdi32.TextOutW - -# Functions imported by name - -@ stdcall CreatePropertySheetPage(ptr) CreatePropertySheetPageA -@ stdcall CreatePropertySheetPageA(ptr) -@ stdcall CreatePropertySheetPageW(ptr) -@ stdcall CreateStatusWindow(long str long long) CreateStatusWindowA -@ stdcall CreateStatusWindowW(long wstr long long) -@ stdcall CreateToolbarEx(long long long long long long ptr long long long long long long) -@ stdcall DestroyPropertySheetPage(long) -@ stdcall DllGetVersion(ptr) COMCTL32_DllGetVersion -@ stdcall DllInstall(long ptr) COMCTL32_DllInstall -@ stdcall DrawStatusText(long ptr ptr long) DrawStatusTextA -@ stdcall DrawStatusTextW(long ptr wstr long) -@ stdcall FlatSB_EnableScrollBar (long long long) -@ stdcall FlatSB_GetScrollInfo (long long ptr) -@ stdcall FlatSB_GetScrollPos (long long) -@ stdcall FlatSB_GetScrollProp (long long ptr) -@ stdcall FlatSB_GetScrollRange (long long ptr ptr) -@ stdcall FlatSB_SetScrollInfo (long long ptr long) -@ stdcall FlatSB_SetScrollPos (long long long long) -@ stdcall FlatSB_SetScrollProp (long long long long) -@ stdcall FlatSB_SetScrollRange (long long long long long) -@ stdcall FlatSB_ShowScrollBar (long long long) -@ stdcall GetMUILanguage() -@ stdcall ImageList_Add(ptr long long) -@ stdcall ImageList_AddIcon(ptr long) -@ stdcall ImageList_AddMasked(ptr long long) -@ stdcall ImageList_BeginDrag(ptr long long long) -@ stdcall ImageList_Copy(ptr long ptr long long) -@ stdcall ImageList_Create(long long long long long) -@ stdcall ImageList_Destroy(ptr) -@ stdcall ImageList_DragEnter(long long long) -@ stdcall ImageList_DragLeave(long) -@ stdcall ImageList_DragMove(long long) -@ stdcall ImageList_DragShowNolock(long) -@ stdcall ImageList_Draw(ptr long long long long long) -@ stdcall ImageList_DrawEx(ptr long long long long long long long long long) -@ stdcall ImageList_DrawIndirect(ptr) -@ stdcall ImageList_Duplicate(ptr) -@ stdcall ImageList_EndDrag() -@ stdcall ImageList_GetBkColor(ptr) -@ stdcall ImageList_GetDragImage(ptr ptr) -@ stdcall ImageList_GetFlags(ptr) -@ stdcall ImageList_GetIcon(ptr long long) -@ stdcall ImageList_GetIconSize(ptr ptr ptr) -@ stdcall ImageList_GetImageCount(ptr) -@ stdcall ImageList_GetImageInfo(ptr long ptr) -@ stdcall ImageList_GetImageRect(ptr long ptr) -@ stdcall ImageList_LoadImage(long str long long long long long) ImageList_LoadImageA -@ stdcall ImageList_LoadImageA(long str long long long long long) -@ stdcall ImageList_LoadImageW(long wstr long long long long long) -@ stdcall ImageList_Merge(ptr long ptr long long long) -@ stdcall ImageList_Read(ptr) -@ stdcall ImageList_Remove(ptr long) -@ stdcall ImageList_Replace(ptr long long long) -@ stdcall ImageList_ReplaceIcon(ptr long long) -@ stdcall ImageList_SetBkColor(ptr long) -@ stdcall ImageList_SetDragCursorImage(ptr long long long) -@ stdcall ImageList_SetFilter(ptr long long) -@ stdcall ImageList_SetFlags(ptr long) -@ stdcall ImageList_SetIconSize(ptr long long) -@ stdcall ImageList_SetImageCount(ptr long) -@ stdcall ImageList_SetOverlayImage(ptr long long) -@ stdcall ImageList_Write(ptr ptr) -@ stdcall InitCommonControlsEx(ptr) -@ stdcall InitMUILanguage(long) -@ stdcall InitializeFlatSB(long) -@ stdcall PropertySheet(ptr) PropertySheetA -@ stdcall PropertySheetA(ptr) -@ stdcall PropertySheetW(ptr) -@ stdcall UninitializeFlatSB(long) -@ stdcall _TrackMouseEvent(ptr) diff --git a/reactos/lib/comctl32/comctl32undoc.c b/reactos/lib/comctl32/comctl32undoc.c deleted file mode 100644 index 11060f300c9..00000000000 --- a/reactos/lib/comctl32/comctl32undoc.c +++ /dev/null @@ -1,2542 +0,0 @@ -/* - * Undocumented functions from COMCTL32.DLL - * - * Copyright 1998 Eric Kohl - * 1998 Juergen Schmied - * 2000 Eric Kohl for CodeWeavers - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2.1 of the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - * - * NOTES - * All of these functions are UNDOCUMENTED!! And I mean UNDOCUMENTED!!!! - * Do NOT rely on names or contents of undocumented structures and types!!! - * These functions are used by EXPLORER.EXE, IEXPLORE.EXE and - * COMCTL32.DLL (internally). - * - */ -#include "config.h" -#include "wine/port.h" - -#include -#include -#include -#include - -#define COBJMACROS -#define NONAMELESSUNION -#define NONAMELESSSTRUCT - -#include "windef.h" -#include "winbase.h" -#include "wingdi.h" -#include "winuser.h" -#include "winnls.h" -#include "winreg.h" -#include "commctrl.h" -#include "objbase.h" -#include "winerror.h" - -#include "wine/unicode.h" -#include "comctl32.h" - -#include "wine/debug.h" - -WINE_DEFAULT_DEBUG_CHANNEL(commctrl); - -struct _DSA -{ - INT nItemCount; - LPVOID pData; - INT nMaxCount; - INT nItemSize; - INT nGrow; -}; - -struct _DPA -{ - INT nItemCount; - LPVOID *ptrs; - HANDLE hHeap; - INT nGrow; - INT nMaxCount; -}; - -typedef struct _STREAMDATA -{ - DWORD dwSize; - DWORD dwData2; - DWORD dwItems; -} STREAMDATA, *PSTREAMDATA; - -typedef struct _LOADDATA -{ - INT nCount; - PVOID ptr; -} LOADDATA, *LPLOADDATA; - -typedef HRESULT (CALLBACK *DPALOADPROC)(LPLOADDATA,IStream*,LPARAM); - -/************************************************************************** - * DPA_LoadStream [COMCTL32.9] - * - * Loads a dynamic pointer array from a stream - * - * PARAMS - * phDpa [O] pointer to a handle to a dynamic pointer array - * loadProc [I] pointer to a callback function - * pStream [I] pointer to a stream - * lParam [I] application specific value - * - * RETURNS - * Success: TRUE - * Failure: FALSE - * - * NOTES - * No more information available yet! - */ - -HRESULT WINAPI -DPA_LoadStream (HDPA *phDpa, DPALOADPROC loadProc, IStream *pStream, LPARAM lParam) -{ - HRESULT errCode; - LARGE_INTEGER position; - ULARGE_INTEGER newPosition; - STREAMDATA streamData; - LOADDATA loadData; - ULONG ulRead; - HDPA hDpa; - PVOID *ptr; - - FIXME ("phDpa=%p loadProc=%p pStream=%p lParam=%lx\n", - phDpa, loadProc, pStream, lParam); - - if (!phDpa || !loadProc || !pStream) - return E_INVALIDARG; - - *phDpa = (HDPA)NULL; - - position.QuadPart = 0; - - /* - * Zero out our streamData - */ - memset(&streamData,0,sizeof(STREAMDATA)); - - errCode = IStream_Seek (pStream, position, STREAM_SEEK_CUR, &newPosition); - if (errCode != S_OK) - return errCode; - - errCode = IStream_Read (pStream, &streamData, sizeof(STREAMDATA), &ulRead); - if (errCode != S_OK) - return errCode; - - FIXME ("dwSize=%lu dwData2=%lu dwItems=%lu\n", - streamData.dwSize, streamData.dwData2, streamData.dwItems); - - if ( ulRead < sizeof(STREAMDATA) || - lParam < sizeof(STREAMDATA) || - streamData.dwSize < sizeof(STREAMDATA) || - streamData.dwData2 < 1) { - errCode = E_FAIL; - } - - if (streamData.dwItems > (UINT_MAX / 2 / sizeof(VOID*))) /* 536870911 */ - return E_OUTOFMEMORY; - - /* create the dpa */ - hDpa = DPA_Create (streamData.dwItems); - if (!hDpa) - return E_OUTOFMEMORY; - - if (!DPA_Grow (hDpa, streamData.dwItems)) - return E_OUTOFMEMORY; - - /* load data from the stream into the dpa */ - ptr = hDpa->ptrs; - for (loadData.nCount = 0; loadData.nCount < streamData.dwItems; loadData.nCount++) { - errCode = (loadProc)(&loadData, pStream, lParam); - if (errCode != S_OK) { - errCode = S_FALSE; - break; - } - - *ptr = loadData.ptr; - ptr++; - } - - /* set the number of items */ - hDpa->nItemCount = loadData.nCount; - - /* store the handle to the dpa */ - *phDpa = hDpa; - FIXME ("new hDpa=%p, errorcode=%lx\n", hDpa, errCode); - - return errCode; -} - - -/************************************************************************** - * DPA_SaveStream [COMCTL32.10] - * - * Saves a dynamic pointer array to a stream - * - * PARAMS - * hDpa [I] handle to a dynamic pointer array - * loadProc [I] pointer to a callback function - * pStream [I] pointer to a stream - * lParam [I] application specific value - * - * RETURNS - * Success: TRUE - * Failure: FALSE - * - * NOTES - * No more information available yet! - */ - -HRESULT WINAPI -DPA_SaveStream (const HDPA hDpa, DPALOADPROC loadProc, IStream *pStream, LPARAM lParam) -{ - - FIXME ("hDpa=%p loadProc=%p pStream=%p lParam=%lx\n", - hDpa, loadProc, pStream, lParam); - - return E_FAIL; -} - - -/************************************************************************** - * DPA_Merge [COMCTL32.11] - * - * PARAMS - * hdpa1 [I] handle to a dynamic pointer array - * hdpa2 [I] handle to a dynamic pointer array - * dwFlags [I] flags - * pfnCompare [I] pointer to sort function - * pfnMerge [I] pointer to merge function - * lParam [I] application specific value - * - * RETURNS - * Success: TRUE - * Failure: FALSE - * - * NOTES - * No more information available yet! - */ - -BOOL WINAPI -DPA_Merge (const HDPA hdpa1, const HDPA hdpa2, DWORD dwFlags, - PFNDPACOMPARE pfnCompare, PFNDPAMERGE pfnMerge, LPARAM lParam) -{ - INT nCount; - LPVOID *pWork1, *pWork2; - INT nResult, i; - INT nIndex; - - TRACE("%p %p %08lx %p %p %08lx)\n", - hdpa1, hdpa2, dwFlags, pfnCompare, pfnMerge, lParam); - - if (IsBadWritePtr (hdpa1, sizeof(*hdpa1))) - return FALSE; - - if (IsBadWritePtr (hdpa2, sizeof(*hdpa2))) - return FALSE; - - if (IsBadCodePtr ((FARPROC)pfnCompare)) - return FALSE; - - if (IsBadCodePtr ((FARPROC)pfnMerge)) - return FALSE; - - if (!(dwFlags & DPAM_NOSORT)) { - TRACE("sorting dpa's!\n"); - if (hdpa1->nItemCount > 0) - DPA_Sort (hdpa1, pfnCompare, lParam); - TRACE ("dpa 1 sorted!\n"); - if (hdpa2->nItemCount > 0) - DPA_Sort (hdpa2, pfnCompare, lParam); - TRACE ("dpa 2 sorted!\n"); - } - - if (hdpa2->nItemCount < 1) - return TRUE; - - TRACE("hdpa1->nItemCount=%d hdpa2->nItemCount=%d\n", - hdpa1->nItemCount, hdpa2->nItemCount); - - - /* working but untrusted implementation */ - - pWork1 = &(hdpa1->ptrs[hdpa1->nItemCount - 1]); - pWork2 = &(hdpa2->ptrs[hdpa2->nItemCount - 1]); - - nIndex = hdpa1->nItemCount - 1; - nCount = hdpa2->nItemCount - 1; - - do - { - if (nIndex < 0) { - if ((nCount >= 0) && (dwFlags & DPAM_INSERT)) { - /* Now insert the remaining new items into DPA 1 */ - TRACE("%d items to be inserted at start of DPA 1\n", - nCount+1); - for (i=nCount; i>=0; i--) { - PVOID ptr; - - ptr = (pfnMerge)(3, *pWork2, NULL, lParam); - if (!ptr) - return FALSE; - DPA_InsertPtr (hdpa1, 0, ptr); - pWork2--; - } - } - break; - } - nResult = (pfnCompare)(*pWork1, *pWork2, lParam); - TRACE("compare result=%d, dpa1.cnt=%d, dpa2.cnt=%d\n", - nResult, nIndex, nCount); - - if (nResult == 0) - { - PVOID ptr; - - ptr = (pfnMerge)(1, *pWork1, *pWork2, lParam); - if (!ptr) - return FALSE; - - nCount--; - pWork2--; - *pWork1 = ptr; - nIndex--; - pWork1--; - } - else if (nResult > 0) - { - /* item in DPA 1 missing from DPA 2 */ - if (dwFlags & DPAM_DELETE) - { - /* Now delete the extra item in DPA1 */ - PVOID ptr; - - ptr = DPA_DeletePtr (hdpa1, hdpa1->nItemCount - 1); - - (pfnMerge)(2, ptr, NULL, lParam); - } - nIndex--; - pWork1--; - } - else - { - /* new item in DPA 2 */ - if (dwFlags & DPAM_INSERT) - { - /* Now insert the new item in DPA 1 */ - PVOID ptr; - - ptr = (pfnMerge)(3, *pWork2, NULL, lParam); - if (!ptr) - return FALSE; - DPA_InsertPtr (hdpa1, nIndex+1, ptr); - } - nCount--; - pWork2--; - } - - } - while (nCount >= 0); - - return TRUE; -} - - -/************************************************************************** - * Alloc [COMCTL32.71] - * - * Allocates memory block from the dll's private heap - * - * PARAMS - * dwSize [I] size of the allocated memory block - * - * RETURNS - * Success: pointer to allocated memory block - * Failure: NULL - */ - -LPVOID WINAPI Alloc (DWORD dwSize) -{ - return LocalAlloc( LMEM_ZEROINIT, dwSize ); -} - - -/************************************************************************** - * ReAlloc [COMCTL32.72] - * - * Changes the size of an allocated memory block or allocates a memory - * block using the dll's private heap. - * - * PARAMS - * lpSrc [I] pointer to memory block which will be resized - * dwSize [I] new size of the memory block. - * - * RETURNS - * Success: pointer to the resized memory block - * Failure: NULL - * - * NOTES - * If lpSrc is a NULL-pointer, then ReAlloc allocates a memory - * block like Alloc. - */ - -LPVOID WINAPI ReAlloc (LPVOID lpSrc, DWORD dwSize) -{ - if (lpSrc) - return LocalReAlloc( lpSrc, dwSize, LMEM_ZEROINIT ); - else - return LocalAlloc( LMEM_ZEROINIT, dwSize); -} - - -/************************************************************************** - * Free [COMCTL32.73] - * - * Frees an allocated memory block from the dll's private heap. - * - * PARAMS - * lpMem [I] pointer to memory block which will be freed - * - * RETURNS - * Success: TRUE - * Failure: FALSE - */ - -BOOL WINAPI Free (LPVOID lpMem) -{ - return !LocalFree( lpMem ); -} - - -/************************************************************************** - * GetSize [COMCTL32.74] - * - * Retrieves the size of the specified memory block from the dll's - * private heap. - * - * PARAMS - * lpMem [I] pointer to an allocated memory block - * - * RETURNS - * Success: size of the specified memory block - * Failure: 0 - */ - -DWORD WINAPI GetSize (LPVOID lpMem) -{ - return LocalSize( lpMem ); -} - - -/************************************************************************** - * The MRU-API is a set of functions to manipulate MRU(Most Recently Used) - * lists. - * - * Stored in the reg. as a set of values under a single key. Each item in the - * list has a value name that is a single char. 'a' - 'z', '{', '|' or '}'. - * The order of the list is stored with value name 'MRUList' which is a string - * containing the value names (i.e. 'a', 'b', etc.) in the relevant order. - */ - -typedef struct tagCREATEMRULISTA -{ - DWORD cbSize; /* size of struct */ - DWORD nMaxItems; /* max no. of items in list */ - DWORD dwFlags; /* see below */ - HKEY hKey; /* root reg. key under which list is saved */ - LPCSTR lpszSubKey; /* reg. subkey */ - PROC lpfnCompare; /* item compare proc */ -} CREATEMRULISTA, *LPCREATEMRULISTA; - -typedef struct tagCREATEMRULISTW -{ - DWORD cbSize; /* size of struct */ - DWORD nMaxItems; /* max no. of items in list */ - DWORD dwFlags; /* see below */ - HKEY hKey; /* root reg. key under which list is saved */ - LPCWSTR lpszSubKey; /* reg. subkey */ - PROC lpfnCompare; /* item compare proc */ -} CREATEMRULISTW, *LPCREATEMRULISTW; - -/* dwFlags */ -#define MRUF_STRING_LIST 0 /* list will contain strings */ -#define MRUF_BINARY_LIST 1 /* list will contain binary data */ -#define MRUF_DELAYED_SAVE 2 /* only save list order to reg. is FreeMRUList */ - -/* If list is a string list lpfnCompare has the following prototype - * int CALLBACK MRUCompareString(LPCSTR s1, LPCSTR s2) - * for binary lists the prototype is - * int CALLBACK MRUCompareBinary(LPCVOID data1, LPCVOID data2, DWORD cbData) - * where cbData is the no. of bytes to compare. - * Need to check what return value means identical - 0? - */ - -typedef struct tagWINEMRUITEM -{ - DWORD size; /* size of data stored */ - DWORD itemFlag; /* flags */ - BYTE datastart; -} WINEMRUITEM, *LPWINEMRUITEM; - -/* itemFlag */ -#define WMRUIF_CHANGED 0x0001 /* this dataitem changed */ - -typedef struct tagWINEMRULIST -{ - CREATEMRULISTW extview; /* original create information */ - BOOL isUnicode; /* is compare fn Unicode */ - DWORD wineFlags; /* internal flags */ - DWORD cursize; /* current size of realMRU */ - LPSTR realMRU; /* pointer to string of index names */ - LPWINEMRUITEM *array; /* array of pointers to data */ - /* in 'a' to 'z' order */ -} WINEMRULIST, *LPWINEMRULIST; - -/* wineFlags */ -#define WMRUF_CHANGED 0x0001 /* MRU list has changed */ - -/************************************************************************** - * MRU_SaveChanged (internal) - * - * Localize MRU saving code - */ -VOID MRU_SaveChanged( LPWINEMRULIST mp ) -{ - UINT i, err; - HKEY newkey; - WCHAR realname[2]; - LPWINEMRUITEM witem; - static const WCHAR emptyW[] = {'\0'}; - - /* or should we do the following instead of RegOpenKeyEx: - */ - - /* open the sub key */ - if ((err = RegOpenKeyExW( mp->extview.hKey, mp->extview.lpszSubKey, - 0, KEY_WRITE, &newkey))) { - /* not present - what to do ??? */ - ERR("Can not open key, error=%d, attempting to create\n", - err); - if ((err = RegCreateKeyExW( mp->extview.hKey, mp->extview.lpszSubKey, - 0, - emptyW, - REG_OPTION_NON_VOLATILE, - KEY_READ | KEY_WRITE, - 0, - &newkey, - 0))) { - ERR("failed to create key /%s/, err=%d\n", - debugstr_w(mp->extview.lpszSubKey), err); - return; - } - } - if (mp->wineFlags & WMRUF_CHANGED) { - mp->wineFlags &= ~WMRUF_CHANGED; - err = RegSetValueExA(newkey, "MRUList", 0, REG_SZ, - mp->realMRU, strlen(mp->realMRU) + 1); - if (err) { - ERR("error saving MRUList, err=%d\n", err); - } - TRACE("saving MRUList=/%s/\n", mp->realMRU); - } - realname[1] = 0; - for(i=0; icursize; i++) { - witem = mp->array[i]; - if (witem->itemFlag & WMRUIF_CHANGED) { - witem->itemFlag &= ~WMRUIF_CHANGED; - realname[0] = 'a' + i; - err = RegSetValueExW(newkey, realname, 0, - (mp->extview.dwFlags & MRUF_BINARY_LIST) ? - REG_BINARY : REG_SZ, - &witem->datastart, witem->size); - if (err) { - ERR("error saving /%s/, err=%d\n", debugstr_w(realname), err); - } - TRACE("saving value for name /%s/ size=%ld\n", - debugstr_w(realname), witem->size); - } - } - RegCloseKey( newkey ); -} - -/************************************************************************** - * FreeMRUList [COMCTL32.152] - * - * Frees a most-recently-used items list. - * - * PARAMS - * hMRUList [I] Handle to list. - * - * RETURNS - * Success: TRUE - * Failure: FALSE - */ -BOOL WINAPI -FreeMRUList (HANDLE hMRUList) -{ - LPWINEMRULIST mp = (LPWINEMRULIST)hMRUList; - UINT i; - - TRACE("\n"); - if (mp->wineFlags & WMRUF_CHANGED) { - /* need to open key and then save the info */ - MRU_SaveChanged( mp ); - } - - for(i=0; iextview.nMaxItems; i++) { - if (mp->array[i]) - Free(mp->array[i]); - } - Free(mp->realMRU); - Free(mp->array); - Free((LPWSTR)mp->extview.lpszSubKey); - return Free(mp); -} - - -/************************************************************************** - * FindMRUData [COMCTL32.169] - * - * Searches binary list for item that matches lpData of length cbData. - * Returns position in list order 0 -> MRU and if lpRegNum != NULL then value - * corresponding to item's reg. name will be stored in it ('a' -> 0). - * - * PARAMS - * hList [I] list handle - * lpData [I] data to find - * cbData [I] length of data - * lpRegNum [O] position in registry (maybe NULL) - * - * RETURNS - * Position in list 0 -> MRU. -1 if item not found. - */ -INT WINAPI -FindMRUData (HANDLE hList, LPCVOID lpData, DWORD cbData, LPINT lpRegNum) -{ - LPWINEMRULIST mp = (LPWINEMRULIST)hList; - INT ret; - UINT i; - LPSTR dataA = NULL; - - if (!mp->extview.lpfnCompare) { - ERR("MRU list not properly created. No compare procedure.\n"); - return -1; - } - - if(!(mp->extview.dwFlags & MRUF_BINARY_LIST) && !mp->isUnicode) { - DWORD len = WideCharToMultiByte(CP_ACP, 0, lpData, -1, - NULL, 0, NULL, NULL); - dataA = Alloc(len); - WideCharToMultiByte(CP_ACP, 0, lpData, -1, dataA, len, NULL, NULL); - } - - for(i=0; icursize; i++) { - if (mp->extview.dwFlags & MRUF_BINARY_LIST) { - if (!mp->extview.lpfnCompare(lpData, &mp->array[i]->datastart, - cbData)) - break; - } - else { - if(mp->isUnicode) { - if (!mp->extview.lpfnCompare(lpData, &mp->array[i]->datastart)) - break; - } else { - DWORD len = WideCharToMultiByte(CP_ACP, 0, - (LPWSTR)&mp->array[i]->datastart, -1, - NULL, 0, NULL, NULL); - LPSTR itemA = Alloc(len); - INT cmp; - WideCharToMultiByte(CP_ACP, 0, (LPWSTR)&mp->array[i]->datastart, -1, - itemA, len, NULL, NULL); - - cmp = mp->extview.lpfnCompare(dataA, itemA); - Free(itemA); - if(!cmp) - break; - } - } - } - if(dataA) - Free(dataA); - if (i < mp->cursize) - ret = i; - else - ret = -1; - if (lpRegNum && (ret != -1)) - *lpRegNum = 'a' + i; - - TRACE("(%p, %p, %ld, %p) returning %d\n", - hList, lpData, cbData, lpRegNum, ret); - - return ret; -} - - -/************************************************************************** - * AddMRUData [COMCTL32.167] - * - * Add item to MRU binary list. If item already exists in list then it is - * simply moved up to the top of the list and not added again. If list is - * full then the least recently used item is removed to make room. - * - * PARAMS - * hList [I] Handle to list. - * lpData [I] ptr to data to add. - * cbData [I] no. of bytes of data. - * - * RETURNS - * No. corresponding to registry name where value is stored 'a' -> 0 etc. - * -1 on error. - */ -INT WINAPI -AddMRUData (HANDLE hList, LPCVOID lpData, DWORD cbData) -{ - LPWINEMRULIST mp = (LPWINEMRULIST)hList; - LPWINEMRUITEM witem; - INT i, replace, ret; - - if ((replace = FindMRUData (hList, lpData, cbData, NULL)) < 0) { - /* either add a new entry or replace oldest */ - if (mp->cursize < mp->extview.nMaxItems) { - /* Add in a new item */ - replace = mp->cursize; - mp->cursize++; - } - else { - /* get the oldest entry and replace data */ - replace = mp->realMRU[mp->cursize - 1] - 'a'; - Free(mp->array[replace]); - } - } - else { - /* free up the old data */ - Free(mp->array[replace]); - } - - /* Allocate space for new item and move in the data */ - mp->array[replace] = witem = Alloc(cbData + sizeof(WINEMRUITEM)); - witem->itemFlag |= WMRUIF_CHANGED; - witem->size = cbData; - memcpy( &witem->datastart, lpData, cbData); - - /* now rotate MRU list */ - mp->wineFlags |= WMRUF_CHANGED; - for(i=mp->cursize-1; i>=1; i--) { - mp->realMRU[i] = mp->realMRU[i-1]; - } - mp->realMRU[0] = replace + 'a'; - TRACE("(%p, %p, %ld) adding data, /%c/ now most current\n", - hList, lpData, cbData, replace+'a'); - ret = replace; - - if (!(mp->extview.dwFlags & MRUF_DELAYED_SAVE)) { - /* save changed stuff right now */ - MRU_SaveChanged( mp ); - } - - return ret; -} - -/************************************************************************** - * AddMRUStringW [COMCTL32.401] - * - * Add item to MRU string list. If item already exists in list them it is - * simply moved up to the top of the list and not added again. If list is - * full then the least recently used item is removed to make room. - * - * PARAMS - * hList [I] Handle to list. - * lpszString [I] ptr to string to add. - * - * RETURNS - * No. corresponding to registry name where value is stored 'a' -> 0 etc. - * -1 on error. - */ -INT WINAPI -AddMRUStringW(HANDLE hList, LPCWSTR lpszString) -{ - FIXME("(%p, %s) empty stub!\n", hList, debugstr_w(lpszString)); - - return 0; -} - -/************************************************************************** - * AddMRUStringA [COMCTL32.153] - * - * See AddMRUStringW. - */ -INT WINAPI -AddMRUStringA(HANDLE hList, LPCSTR lpszString) -{ - FIXME("(%p, %s) empty stub!\n", hList, debugstr_a(lpszString)); - - return 0; -} - -/************************************************************************** - * DelMRUString [COMCTL32.156] - * - * Removes item from either string or binary list (despite its name) - * - * PARAMS - * hList [I] list handle - * nItemPos [I] item position to remove 0 -> MRU - * - * RETURNS - * TRUE if successful, FALSE if nItemPos is out of range. - */ -BOOL WINAPI -DelMRUString(HANDLE hList, INT nItemPos) -{ - FIXME("(%p, %d): stub\n", hList, nItemPos); - return TRUE; -} - -/************************************************************************** - * FindMRUStringW [COMCTL32.402] - * - * See FindMRUStringA. - */ -INT WINAPI -FindMRUStringW (HANDLE hList, LPCWSTR lpszString, LPINT lpRegNum) -{ - FIXME("stub\n"); - return -1; -} - -/************************************************************************** - * FindMRUStringA [COMCTL32.155] - * - * Searches string list for item that matches lpszString. - * Returns position in list order 0 -> MRU and if lpRegNum != NULL then value - * corresponding to item's reg. name will be stored in it ('a' -> 0). - * - * PARAMS - * hList [I] list handle - * lpszString [I] string to find - * lpRegNum [O] position in registry (maybe NULL) - * - * RETURNS - * Position in list 0 -> MRU. -1 if item not found. - */ -INT WINAPI -FindMRUStringA (HANDLE hList, LPCSTR lpszString, LPINT lpRegNum) -{ - DWORD len = MultiByteToWideChar(CP_ACP, 0, lpszString, -1, NULL, 0); - LPWSTR stringW = Alloc(len * sizeof(WCHAR)); - INT ret; - - MultiByteToWideChar(CP_ACP, 0, lpszString, -1, stringW, len); - ret = FindMRUData(hList, stringW, len * sizeof(WCHAR), lpRegNum); - Free(stringW); - return ret; -} - -/************************************************************************* - * CreateMRUListLazy_common (internal) - */ -HANDLE CreateMRUListLazy_common(LPWINEMRULIST mp) -{ - UINT i, err; - HKEY newkey; - DWORD datasize, dwdisp; - WCHAR realname[2]; - LPWINEMRUITEM witem; - DWORD type; - static const WCHAR emptyW[] = {'\0'}; - - /* get space to save indices that will turn into names - * but in order of most to least recently used - */ - mp->realMRU = Alloc(mp->extview.nMaxItems + 2); - - /* get space to save pointers to actual data in order of - * 'a' to 'z' (0 to n). - */ - mp->array = Alloc(mp->extview.nMaxItems * sizeof(LPVOID)); - - /* open the sub key */ - if ((err = RegCreateKeyExW( mp->extview.hKey, mp->extview.lpszSubKey, - 0, - emptyW, - REG_OPTION_NON_VOLATILE, - KEY_READ | KEY_WRITE, - 0, - &newkey, - &dwdisp))) { - /* error - what to do ??? */ - ERR("(%lu %lu %lx %lx \"%s\" %p): Can not open key, error=%d\n", - mp->extview.cbSize, mp->extview.nMaxItems, mp->extview.dwFlags, - (DWORD)mp->extview.hKey, debugstr_w(mp->extview.lpszSubKey), - mp->extview.lpfnCompare, err); - return 0; - } - - /* get values from key 'MRUList' */ - if (newkey) { - datasize = mp->extview.nMaxItems + 1; - if((err=RegQueryValueExA( newkey, "MRUList", 0, &type, mp->realMRU, - &datasize))) { - /* not present - set size to 1 (will become 0 later) */ - datasize = 1; - *mp->realMRU = 0; - } - - TRACE("MRU list = %s\n", mp->realMRU); - - mp->cursize = datasize - 1; - /* datasize now has number of items in the MRUList */ - - /* get actual values for each entry */ - realname[1] = 0; - for(i=0; icursize; i++) { - realname[0] = 'a' + i; - if(RegQueryValueExW( newkey, realname, 0, &type, 0, &datasize)) { - /* not present - what to do ??? */ - ERR("Key %s not found 1\n", debugstr_w(realname)); - } - mp->array[i] = witem = Alloc(datasize + sizeof(WINEMRUITEM)); - witem->size = datasize; - if(RegQueryValueExW( newkey, realname, 0, &type, - &witem->datastart, &datasize)) { - /* not present - what to do ??? */ - ERR("Key %s not found 2\n", debugstr_w(realname)); - } - } - RegCloseKey( newkey ); - } - else - mp->cursize = 0; - - TRACE("(%lu %lu %lx %lx \"%s\" %p): Current Size = %ld\n", - mp->extview.cbSize, mp->extview.nMaxItems, mp->extview.dwFlags, - (DWORD)mp->extview.hKey, debugstr_w(mp->extview.lpszSubKey), - mp->extview.lpfnCompare, mp->cursize); - return (HANDLE)mp; -} - -/************************************************************************** - * CreateMRUListLazyW [COMCTL32.404] - * - * See CreateMRUListLazyA. - */ -HANDLE WINAPI -CreateMRUListLazyW (LPCREATEMRULISTW lpcml, DWORD dwParam2, DWORD dwParam3, DWORD dwParam4) -{ - LPWINEMRULIST mp; - - if (lpcml == NULL) - return 0; - - if (lpcml->cbSize < sizeof(CREATEMRULISTW)) - return 0; - - mp = Alloc(sizeof(WINEMRULIST)); - memcpy(&mp->extview, lpcml, sizeof(CREATEMRULISTW)); - mp->extview.lpszSubKey = Alloc((strlenW(lpcml->lpszSubKey) + 1) * sizeof(WCHAR)); - strcpyW((LPWSTR)mp->extview.lpszSubKey, lpcml->lpszSubKey); - mp->isUnicode = TRUE; - - return CreateMRUListLazy_common(mp); -} - -/************************************************************************** - * CreateMRUListLazyA [COMCTL32.157] - * - * Creates a most-recently-used list. - * - * PARAMS - * lpcml [I] ptr to CREATEMRULIST structure. - * dwParam2 [I] Unknown - * dwParam3 [I] Unknown - * dwParam4 [I] Unknown - * - * RETURNS - * Handle to MRU list. - */ -HANDLE WINAPI -CreateMRUListLazyA (LPCREATEMRULISTA lpcml, DWORD dwParam2, DWORD dwParam3, DWORD dwParam4) -{ - LPWINEMRULIST mp; - DWORD len; - - if (lpcml == NULL) - return 0; - - if (lpcml->cbSize < sizeof(CREATEMRULISTA)) - return 0; - - mp = Alloc(sizeof(WINEMRULIST)); - memcpy(&mp->extview, lpcml, sizeof(CREATEMRULISTW)); - len = MultiByteToWideChar(CP_ACP, 0, lpcml->lpszSubKey, -1, NULL, 0); - mp->extview.lpszSubKey = Alloc(len * sizeof(WCHAR)); - MultiByteToWideChar(CP_ACP, 0, lpcml->lpszSubKey, -1, - (LPWSTR)mp->extview.lpszSubKey, len); - mp->isUnicode = FALSE; - return CreateMRUListLazy_common(mp); -} - -/************************************************************************** - * CreateMRUListW [COMCTL32.400] - * - * See CreateMRUListA. - */ -HANDLE WINAPI -CreateMRUListW (LPCREATEMRULISTW lpcml) -{ - return CreateMRUListLazyW(lpcml, 0, 0, 0); -} - -/************************************************************************** - * CreateMRUListA [COMCTL32.151] - * - * Creates a most-recently-used list. - * - * PARAMS - * lpcml [I] ptr to CREATEMRULIST structure. - * - * RETURNS - * Handle to MRU list. - */ -HANDLE WINAPI -CreateMRUListA (LPCREATEMRULISTA lpcml) -{ - return CreateMRUListLazyA (lpcml, 0, 0, 0); -} - - -/************************************************************************** - * EnumMRUListW [COMCTL32.403] - * - * Enumerate item in a most-recenty-used list - * - * PARAMS - * hList [I] list handle - * nItemPos [I] item position to enumerate - * lpBuffer [O] buffer to receive item - * nBufferSize [I] size of buffer - * - * RETURNS - * For binary lists specifies how many bytes were copied to buffer, for - * string lists specifies full length of string. Enumerating past the end - * of list returns -1. - * If lpBuffer == NULL or nItemPos is -ve return value is no. of items in - * the list. - */ -INT WINAPI EnumMRUListW(HANDLE hList, INT nItemPos, LPVOID lpBuffer, -DWORD nBufferSize) -{ - LPWINEMRULIST mp = (LPWINEMRULIST) hList; - LPWINEMRUITEM witem; - INT desired, datasize; - - if (nItemPos >= mp->cursize) return -1; - if ((nItemPos < 0) || !lpBuffer) return mp->cursize; - desired = mp->realMRU[nItemPos]; - desired -= 'a'; - TRACE("nItemPos=%d, desired=%d\n", nItemPos, desired); - witem = mp->array[desired]; - datasize = min( witem->size, nBufferSize ); - memcpy( lpBuffer, &witem->datastart, datasize); - TRACE("(%p, %d, %p, %ld): returning len=%d\n", - hList, nItemPos, lpBuffer, nBufferSize, datasize); - return datasize; -} - -/************************************************************************** - * EnumMRUListA [COMCTL32.154] - * - * See EnumMRUListW. - */ -INT WINAPI EnumMRUListA(HANDLE hList, INT nItemPos, LPVOID lpBuffer, -DWORD nBufferSize) -{ - LPWINEMRULIST mp = (LPWINEMRULIST) hList; - LPWINEMRUITEM witem; - INT desired, datasize; - DWORD lenA; - - if (nItemPos >= mp->cursize) return -1; - if ((nItemPos < 0) || !lpBuffer) return mp->cursize; - desired = mp->realMRU[nItemPos]; - desired -= 'a'; - TRACE("nItemPos=%d, desired=%d\n", nItemPos, desired); - witem = mp->array[desired]; - if(mp->extview.dwFlags & MRUF_BINARY_LIST) { - datasize = min( witem->size, nBufferSize ); - memcpy( lpBuffer, &witem->datastart, datasize); - } else { - lenA = WideCharToMultiByte(CP_ACP, 0, (LPWSTR)&witem->datastart, -1, - NULL, 0, NULL, NULL); - datasize = min( witem->size, nBufferSize ); - WideCharToMultiByte(CP_ACP, 0, (LPWSTR)&witem->datastart, -1, - lpBuffer, datasize, NULL, NULL); - } - TRACE("(%p, %d, %p, %ld): returning len=%d\n", - hList, nItemPos, lpBuffer, nBufferSize, datasize); - return datasize; -} - - -/************************************************************************** - * Str_GetPtrA [COMCTL32.233] - * - * Copies a string into a destination buffer. - * - * PARAMS - * lpSrc [I] Source string - * lpDest [O] Destination buffer - * nMaxLen [I] Size of buffer in characters - * - * RETURNS - * The number of characters copied. - */ - -INT WINAPI -Str_GetPtrA (LPCSTR lpSrc, LPSTR lpDest, INT nMaxLen) -{ - INT len; - - TRACE("(%p %p %d)\n", lpSrc, lpDest, nMaxLen); - - if (!lpDest && lpSrc) - return strlen (lpSrc); - - if (nMaxLen == 0) - return 0; - - if (lpSrc == NULL) { - lpDest[0] = '\0'; - return 0; - } - - len = strlen (lpSrc); - if (len >= nMaxLen) - len = nMaxLen - 1; - - RtlMoveMemory (lpDest, lpSrc, len); - lpDest[len] = '\0'; - - return len; -} - - -/************************************************************************** - * Str_SetPtrA [COMCTL32.234] - * - * Makes a copy of a string, allocating memory if necessary. - * - * PARAMS - * lppDest [O] Pointer to destination string - * lpSrc [I] Source string - * - * RETURNS - * Success: TRUE - * Failure: FALSE - * - * NOTES - * Set lpSrc to NULL to free the memory allocated by a previous call - * to this function. - */ - -BOOL WINAPI -Str_SetPtrA (LPSTR *lppDest, LPCSTR lpSrc) -{ - TRACE("(%p %p)\n", lppDest, lpSrc); - - if (lpSrc) { - LPSTR ptr = ReAlloc (*lppDest, strlen (lpSrc) + 1); - if (!ptr) - return FALSE; - strcpy (ptr, lpSrc); - *lppDest = ptr; - } - else { - if (*lppDest) { - Free (*lppDest); - *lppDest = NULL; - } - } - - return TRUE; -} - - -/************************************************************************** - * Str_GetPtrW [COMCTL32.235] - * - * See Str_GetPtrA. - */ - -INT WINAPI -Str_GetPtrW (LPCWSTR lpSrc, LPWSTR lpDest, INT nMaxLen) -{ - INT len; - - TRACE("(%p %p %d)\n", lpSrc, lpDest, nMaxLen); - - if (!lpDest && lpSrc) - return strlenW (lpSrc); - - if (nMaxLen == 0) - return 0; - - if (lpSrc == NULL) { - lpDest[0] = L'\0'; - return 0; - } - - len = strlenW (lpSrc); - if (len >= nMaxLen) - len = nMaxLen - 1; - - RtlMoveMemory (lpDest, lpSrc, len*sizeof(WCHAR)); - lpDest[len] = L'\0'; - - return len; -} - - -/************************************************************************** - * Str_SetPtrW [COMCTL32.236] - * - * See Str_SetPtrA. - */ - -BOOL WINAPI -Str_SetPtrW (LPWSTR *lppDest, LPCWSTR lpSrc) -{ - TRACE("(%p %p)\n", lppDest, lpSrc); - - if (lpSrc) { - INT len = strlenW (lpSrc) + 1; - LPWSTR ptr = ReAlloc (*lppDest, len * sizeof(WCHAR)); - if (!ptr) - return FALSE; - strcpyW (ptr, lpSrc); - *lppDest = ptr; - } - else { - if (*lppDest) { - Free (*lppDest); - *lppDest = NULL; - } - } - - return TRUE; -} - - -/************************************************************************** - * Str_GetPtrWtoA [internal] - * - * Converts a unicode string into a multi byte string - * - * PARAMS - * lpSrc [I] Pointer to the unicode source string - * lpDest [O] Pointer to caller supplied storage for the multi byte string - * nMaxLen [I] Size, in bytes, of the destination buffer - * - * RETURNS - * Length, in bytes, of the converted string. - */ - -INT -Str_GetPtrWtoA (LPCWSTR lpSrc, LPSTR lpDest, INT nMaxLen) -{ - INT len; - - TRACE("(%s %p %d)\n", debugstr_w(lpSrc), lpDest, nMaxLen); - - if (!lpDest && lpSrc) - return WideCharToMultiByte(CP_ACP, 0, lpSrc, -1, 0, 0, NULL, NULL); - - if (nMaxLen == 0) - return 0; - - if (lpSrc == NULL) { - lpDest[0] = '\0'; - return 0; - } - - len = WideCharToMultiByte(CP_ACP, 0, lpSrc, -1, 0, 0, NULL, NULL); - if (len >= nMaxLen) - len = nMaxLen - 1; - - WideCharToMultiByte(CP_ACP, 0, lpSrc, -1, lpDest, len, NULL, NULL); - lpDest[len] = '\0'; - - return len; -} - - -/************************************************************************** - * Str_SetPtrAtoW [internal] - * - * Converts a multi byte string to a unicode string. - * If the pointer to the destination buffer is NULL a buffer is allocated. - * If the destination buffer is too small to keep the converted multi byte - * string the destination buffer is reallocated. If the source pointer is - * NULL, the destination buffer is freed. - * - * PARAMS - * lppDest [I/O] pointer to a pointer to the destination buffer - * lpSrc [I] pointer to a multi byte string - * - * RETURNS - * TRUE: conversion successful - * FALSE: error - */ - -BOOL -Str_SetPtrAtoW (LPWSTR *lppDest, LPCSTR lpSrc) -{ - TRACE("(%p %s)\n", lppDest, lpSrc); - - if (lpSrc) { - INT len = MultiByteToWideChar(CP_ACP,0,lpSrc,-1,NULL,0); - LPWSTR ptr = ReAlloc (*lppDest, len*sizeof(WCHAR)); - - if (!ptr) - return FALSE; - MultiByteToWideChar(CP_ACP,0,lpSrc,-1,ptr,len); - *lppDest = ptr; - } - else { - if (*lppDest) { - Free (*lppDest); - *lppDest = NULL; - } - } - - return TRUE; -} - - -/************************************************************************** - * DSA_Create [COMCTL32.320] - * - * Creates a dynamic storage array - * - * PARAMS - * nSize [I] size of the array elements - * nGrow [I] number of elements by which the array grows when it is filled - * - * RETURNS - * Success: pointer to an array control structure. Use this like a handle. - * Failure: NULL - * - * NOTES - * The DSA_ functions can be used to create and manipulate arrays of - * fixed-size memory blocks. These arrays can store any kind of data - * (e.g. strings and icons). - */ - -HDSA WINAPI -DSA_Create (INT nSize, INT nGrow) -{ - HDSA hdsa; - - TRACE("(size=%d grow=%d)\n", nSize, nGrow); - - hdsa = Alloc (sizeof(*hdsa)); - if (hdsa) - { - hdsa->nItemCount = 0; - hdsa->pData = NULL; - hdsa->nMaxCount = 0; - hdsa->nItemSize = nSize; - hdsa->nGrow = max(1, nGrow); - } - - return hdsa; -} - - -/************************************************************************** - * DSA_Destroy [COMCTL32.321] - * - * Destroys a dynamic storage array - * - * PARAMS - * hdsa [I] pointer to the array control structure - * - * RETURNS - * Success: TRUE - * Failure: FALSE - */ - -BOOL WINAPI -DSA_Destroy (const HDSA hdsa) -{ - TRACE("(%p)\n", hdsa); - - if (!hdsa) - return FALSE; - - if (hdsa->pData && (!Free (hdsa->pData))) - return FALSE; - - return Free (hdsa); -} - - -/************************************************************************** - * DSA_GetItem [COMCTL32.322] - * - * Copies the specified item into a caller-supplied buffer. - * - * PARAMS - * hdsa [I] pointer to the array control structure - * nIndex [I] number of the Item to get - * pDest [O] destination buffer. Has to be >= dwElementSize. - * - * RETURNS - * Success: TRUE - * Failure: FALSE - */ - -BOOL WINAPI -DSA_GetItem (const HDSA hdsa, INT nIndex, LPVOID pDest) -{ - LPVOID pSrc; - - TRACE("(%p %d %p)\n", hdsa, nIndex, pDest); - - if (!hdsa) - return FALSE; - if ((nIndex < 0) || (nIndex >= hdsa->nItemCount)) - return FALSE; - - pSrc = (char *) hdsa->pData + (hdsa->nItemSize * nIndex); - memmove (pDest, pSrc, hdsa->nItemSize); - - return TRUE; -} - - -/************************************************************************** - * DSA_GetItemPtr [COMCTL32.323] - * - * Retrieves a pointer to the specified item. - * - * PARAMS - * hdsa [I] pointer to the array control structure - * nIndex [I] index of the desired item - * - * RETURNS - * Success: pointer to an item - * Failure: NULL - */ - -LPVOID WINAPI -DSA_GetItemPtr (const HDSA hdsa, INT nIndex) -{ - LPVOID pSrc; - - TRACE("(%p %d)\n", hdsa, nIndex); - - if (!hdsa) - return NULL; - if ((nIndex < 0) || (nIndex >= hdsa->nItemCount)) - return NULL; - - pSrc = (char *) hdsa->pData + (hdsa->nItemSize * nIndex); - - TRACE("-- ret=%p\n", pSrc); - - return pSrc; -} - - -/************************************************************************** - * DSA_SetItem [COMCTL32.325] - * - * Sets the contents of an item in the array. - * - * PARAMS - * hdsa [I] pointer to the array control structure - * nIndex [I] index for the item - * pSrc [I] pointer to the new item data - * - * RETURNS - * Success: TRUE - * Failure: FALSE - */ - -BOOL WINAPI -DSA_SetItem (const HDSA hdsa, INT nIndex, LPVOID pSrc) -{ - INT nSize, nNewItems; - LPVOID pDest, lpTemp; - - TRACE("(%p %d %p)\n", hdsa, nIndex, pSrc); - - if ((!hdsa) || nIndex < 0) - return FALSE; - - if (hdsa->nItemCount <= nIndex) { - /* within the old array */ - if (hdsa->nMaxCount > nIndex) { - /* within the allocated space, set a new boundary */ - hdsa->nItemCount = nIndex + 1; - } - else { - /* resize the block of memory */ - nNewItems = - hdsa->nGrow * ((INT)(((nIndex + 1) - 1) / hdsa->nGrow) + 1); - nSize = hdsa->nItemSize * nNewItems; - - lpTemp = ReAlloc (hdsa->pData, nSize); - if (!lpTemp) - return FALSE; - - hdsa->nMaxCount = nNewItems; - hdsa->nItemCount = nIndex + 1; - hdsa->pData = lpTemp; - } - } - - /* put the new entry in */ - pDest = (char *) hdsa->pData + (hdsa->nItemSize * nIndex); - TRACE("-- move dest=%p src=%p size=%d\n", - pDest, pSrc, hdsa->nItemSize); - memmove (pDest, pSrc, hdsa->nItemSize); - - return TRUE; -} - - -/************************************************************************** - * DSA_InsertItem [COMCTL32.324] - * - * Inserts an item into the array at the specified index. - * - * PARAMS - * hdsa [I] pointer to the array control structure - * nIndex [I] index for the new item - * pSrc [I] pointer to the element - * - * RETURNS - * Success: position of the new item - * Failure: -1 - */ - -INT WINAPI -DSA_InsertItem (const HDSA hdsa, INT nIndex, LPVOID pSrc) -{ - INT nNewItems, nSize; - LPVOID lpTemp, lpDest; - - TRACE("(%p %d %p)\n", hdsa, nIndex, pSrc); - - if ((!hdsa) || nIndex < 0) - return -1; - - /* when nIndex >= nItemCount then append */ - if (nIndex >= hdsa->nItemCount) - nIndex = hdsa->nItemCount; - - /* do we need to resize ? */ - if (hdsa->nItemCount >= hdsa->nMaxCount) { - nNewItems = hdsa->nMaxCount + hdsa->nGrow; - nSize = hdsa->nItemSize * nNewItems; - - lpTemp = ReAlloc (hdsa->pData, nSize); - if (!lpTemp) - return -1; - - hdsa->nMaxCount = nNewItems; - hdsa->pData = lpTemp; - } - - /* do we need to move elements ? */ - if (nIndex < hdsa->nItemCount) { - lpTemp = (char *) hdsa->pData + (hdsa->nItemSize * nIndex); - lpDest = (char *) lpTemp + hdsa->nItemSize; - nSize = (hdsa->nItemCount - nIndex) * hdsa->nItemSize; - TRACE("-- move dest=%p src=%p size=%d\n", - lpDest, lpTemp, nSize); - memmove (lpDest, lpTemp, nSize); - } - - /* ok, we can put the new Item in */ - hdsa->nItemCount++; - lpDest = (char *) hdsa->pData + (hdsa->nItemSize * nIndex); - TRACE("-- move dest=%p src=%p size=%d\n", - lpDest, pSrc, hdsa->nItemSize); - memmove (lpDest, pSrc, hdsa->nItemSize); - - return nIndex; -} - - -/************************************************************************** - * DSA_DeleteItem [COMCTL32.326] - * - * Deletes the specified item from the array. - * - * PARAMS - * hdsa [I] pointer to the array control structure - * nIndex [I] index for the element to delete - * - * RETURNS - * Success: number of the deleted element - * Failure: -1 - */ - -INT WINAPI -DSA_DeleteItem (const HDSA hdsa, INT nIndex) -{ - LPVOID lpDest,lpSrc; - INT nSize; - - TRACE("(%p %d)\n", hdsa, nIndex); - - if (!hdsa) - return -1; - if (nIndex < 0 || nIndex >= hdsa->nItemCount) - return -1; - - /* do we need to move ? */ - if (nIndex < hdsa->nItemCount - 1) { - lpDest = (char *) hdsa->pData + (hdsa->nItemSize * nIndex); - lpSrc = (char *) lpDest + hdsa->nItemSize; - nSize = hdsa->nItemSize * (hdsa->nItemCount - nIndex - 1); - TRACE("-- move dest=%p src=%p size=%d\n", - lpDest, lpSrc, nSize); - memmove (lpDest, lpSrc, nSize); - } - - hdsa->nItemCount--; - - /* free memory ? */ - if ((hdsa->nMaxCount - hdsa->nItemCount) >= hdsa->nGrow) { - nSize = hdsa->nItemSize * hdsa->nItemCount; - - lpDest = ReAlloc (hdsa->pData, nSize); - if (!lpDest) - return -1; - - hdsa->nMaxCount = hdsa->nItemCount; - hdsa->pData = lpDest; - } - - return nIndex; -} - - -/************************************************************************** - * DSA_DeleteAllItems [COMCTL32.327] - * - * Removes all items and reinitializes the array. - * - * PARAMS - * hdsa [I] pointer to the array control structure - * - * RETURNS - * Success: TRUE - * Failure: FALSE - */ - -BOOL WINAPI -DSA_DeleteAllItems (const HDSA hdsa) -{ - TRACE("(%p)\n", hdsa); - - if (!hdsa) - return FALSE; - if (hdsa->pData && (!Free (hdsa->pData))) - return FALSE; - - hdsa->nItemCount = 0; - hdsa->pData = NULL; - hdsa->nMaxCount = 0; - - return TRUE; -} - - -/************************************************************************** - * DPA_Destroy [COMCTL32.329] - * - * Destroys a dynamic pointer array - * - * PARAMS - * hdpa [I] handle (pointer) to the pointer array - * - * RETURNS - * Success: TRUE - * Failure: FALSE - */ - -BOOL WINAPI -DPA_Destroy (const HDPA hdpa) -{ - TRACE("(%p)\n", hdpa); - - if (!hdpa) - return FALSE; - - if (hdpa->ptrs && (!HeapFree (hdpa->hHeap, 0, hdpa->ptrs))) - return FALSE; - - return HeapFree (hdpa->hHeap, 0, hdpa); -} - - -/************************************************************************** - * DPA_Grow [COMCTL32.330] - * - * Sets the growth amount. - * - * PARAMS - * hdpa [I] handle (pointer) to the existing (source) pointer array - * nGrow [I] number of items by which the array grows when it's too small - * - * RETURNS - * Success: TRUE - * Failure: FALSE - */ - -BOOL WINAPI -DPA_Grow (const HDPA hdpa, INT nGrow) -{ - TRACE("(%p %d)\n", hdpa, nGrow); - - if (!hdpa) - return FALSE; - - hdpa->nGrow = max(8, nGrow); - - return TRUE; -} - - -/************************************************************************** - * DPA_Clone [COMCTL32.331] - * - * Copies a pointer array to an other one or creates a copy - * - * PARAMS - * hdpa [I] handle (pointer) to the existing (source) pointer array - * hdpaNew [O] handle (pointer) to the destination pointer array - * - * RETURNS - * Success: pointer to the destination pointer array. - * Failure: NULL - * - * NOTES - * - If the 'hdpaNew' is a NULL-Pointer, a copy of the source pointer - * array will be created and it's handle (pointer) is returned. - * - If 'hdpa' is a NULL-Pointer, the original implementation crashes, - * this implementation just returns NULL. - */ - -HDPA WINAPI -DPA_Clone (const HDPA hdpa, const HDPA hdpaNew) -{ - INT nNewItems, nSize; - HDPA hdpaTemp; - - if (!hdpa) - return NULL; - - TRACE("(%p %p)\n", hdpa, hdpaNew); - - if (!hdpaNew) { - /* create a new DPA */ - hdpaTemp = (HDPA)HeapAlloc (hdpa->hHeap, HEAP_ZERO_MEMORY, - sizeof(*hdpaTemp)); - hdpaTemp->hHeap = hdpa->hHeap; - hdpaTemp->nGrow = hdpa->nGrow; - } - else - hdpaTemp = hdpaNew; - - if (hdpaTemp->ptrs) { - /* remove old pointer array */ - HeapFree (hdpaTemp->hHeap, 0, hdpaTemp->ptrs); - hdpaTemp->ptrs = NULL; - hdpaTemp->nItemCount = 0; - hdpaTemp->nMaxCount = 0; - } - - /* create a new pointer array */ - nNewItems = hdpaTemp->nGrow * - ((INT)((hdpa->nItemCount - 1) / hdpaTemp->nGrow) + 1); - nSize = nNewItems * sizeof(LPVOID); - hdpaTemp->ptrs = - (LPVOID*)HeapAlloc (hdpaTemp->hHeap, HEAP_ZERO_MEMORY, nSize); - hdpaTemp->nMaxCount = nNewItems; - - /* clone the pointer array */ - hdpaTemp->nItemCount = hdpa->nItemCount; - memmove (hdpaTemp->ptrs, hdpa->ptrs, - hdpaTemp->nItemCount * sizeof(LPVOID)); - - return hdpaTemp; -} - - -/************************************************************************** - * DPA_GetPtr [COMCTL32.332] - * - * Retrieves a pointer from a dynamic pointer array - * - * PARAMS - * hdpa [I] handle (pointer) to the pointer array - * nIndex [I] array index of the desired pointer - * - * RETURNS - * Success: pointer - * Failure: NULL - */ - -LPVOID WINAPI -DPA_GetPtr (const HDPA hdpa, INT nIndex) -{ - TRACE("(%p %d)\n", hdpa, nIndex); - - if (!hdpa) - return NULL; - if (!hdpa->ptrs) { - WARN("no pointer array.\n"); - return NULL; - } - if ((nIndex < 0) || (nIndex >= hdpa->nItemCount)) { - WARN("not enough pointers in array (%d vs %d).\n",nIndex,hdpa->nItemCount); - return NULL; - } - - TRACE("-- %p\n", hdpa->ptrs[nIndex]); - - return hdpa->ptrs[nIndex]; -} - - -/************************************************************************** - * DPA_GetPtrIndex [COMCTL32.333] - * - * Retrieves the index of the specified pointer - * - * PARAMS - * hdpa [I] handle (pointer) to the pointer array - * p [I] pointer - * - * RETURNS - * Success: index of the specified pointer - * Failure: -1 - */ - -INT WINAPI -DPA_GetPtrIndex (const HDPA hdpa, LPVOID p) -{ - INT i; - - if (!hdpa || !hdpa->ptrs) - return -1; - - for (i = 0; i < hdpa->nItemCount; i++) { - if (hdpa->ptrs[i] == p) - return i; - } - - return -1; -} - - -/************************************************************************** - * DPA_InsertPtr [COMCTL32.334] - * - * Inserts a pointer into a dynamic pointer array - * - * PARAMS - * hdpa [I] handle (pointer) to the array - * i [I] array index - * p [I] pointer to insert - * - * RETURNS - * Success: index of the inserted pointer - * Failure: -1 - */ - -INT WINAPI -DPA_InsertPtr (const HDPA hdpa, INT i, LPVOID p) -{ - TRACE("(%p %d %p)\n", hdpa, i, p); - - if (!hdpa || i < 0) return -1; - - if (i >= 0x7fff) - i = hdpa->nItemCount; - - if (i >= hdpa->nItemCount) - return DPA_SetPtr(hdpa, i, p) ? i : -1; - - /* create empty spot at the end */ - if (!DPA_SetPtr(hdpa, hdpa->nItemCount, 0)) return -1; - memmove (hdpa->ptrs + i + 1, hdpa->ptrs + i, (hdpa->nItemCount - i - 1) * sizeof(LPVOID)); - hdpa->ptrs[i] = p; - return i; -} - -/************************************************************************** - * DPA_SetPtr [COMCTL32.335] - * - * Sets a pointer in the pointer array - * - * PARAMS - * hdpa [I] handle (pointer) to the pointer array - * i [I] index of the pointer that will be set - * p [I] pointer to be set - * - * RETURNS - * Success: TRUE - * Failure: FALSE - */ - -BOOL WINAPI -DPA_SetPtr (const HDPA hdpa, INT i, LPVOID p) -{ - LPVOID *lpTemp; - - TRACE("(%p %d %p)\n", hdpa, i, p); - - if (!hdpa || i < 0 || i > 0x7fff) - return FALSE; - - if (hdpa->nItemCount <= i) { - /* within the old array */ - if (hdpa->nMaxCount <= i) { - /* resize the block of memory */ - INT nNewItems = - hdpa->nGrow * ((INT)(((i+1) - 1) / hdpa->nGrow) + 1); - INT nSize = nNewItems * sizeof(LPVOID); - - if (hdpa->ptrs) - lpTemp = (LPVOID*)HeapReAlloc (hdpa->hHeap, HEAP_ZERO_MEMORY, hdpa->ptrs, nSize); - else - lpTemp = (LPVOID*)HeapAlloc (hdpa->hHeap, HEAP_ZERO_MEMORY, nSize); - - if (!lpTemp) - return FALSE; - - hdpa->nMaxCount = nNewItems; - hdpa->ptrs = lpTemp; - } - hdpa->nItemCount = i+1; - } - - /* put the new entry in */ - hdpa->ptrs[i] = p; - - return TRUE; -} - - -/************************************************************************** - * DPA_DeletePtr [COMCTL32.336] - * - * Removes a pointer from the pointer array. - * - * PARAMS - * hdpa [I] handle (pointer) to the pointer array - * i [I] index of the pointer that will be deleted - * - * RETURNS - * Success: deleted pointer - * Failure: NULL - */ - -LPVOID WINAPI -DPA_DeletePtr (const HDPA hdpa, INT i) -{ - LPVOID *lpDest, *lpSrc, lpTemp = NULL; - INT nSize; - - TRACE("(%p %d)\n", hdpa, i); - - if ((!hdpa) || i < 0 || i >= hdpa->nItemCount) - return NULL; - - lpTemp = hdpa->ptrs[i]; - - /* do we need to move ?*/ - if (i < hdpa->nItemCount - 1) { - lpDest = hdpa->ptrs + i; - lpSrc = lpDest + 1; - nSize = (hdpa->nItemCount - i - 1) * sizeof(LPVOID); - TRACE("-- move dest=%p src=%p size=%x\n", - lpDest, lpSrc, nSize); - memmove (lpDest, lpSrc, nSize); - } - - hdpa->nItemCount --; - - /* free memory ?*/ - if ((hdpa->nMaxCount - hdpa->nItemCount) >= hdpa->nGrow) { - INT nNewItems = max(hdpa->nGrow * 2, hdpa->nItemCount); - nSize = nNewItems * sizeof(LPVOID); - lpDest = (LPVOID)HeapReAlloc (hdpa->hHeap, HEAP_ZERO_MEMORY, - hdpa->ptrs, nSize); - if (!lpDest) - return NULL; - - hdpa->nMaxCount = nNewItems; - hdpa->ptrs = (LPVOID*)lpDest; - } - - return lpTemp; -} - - -/************************************************************************** - * DPA_DeleteAllPtrs [COMCTL32.337] - * - * Removes all pointers and reinitializes the array. - * - * PARAMS - * hdpa [I] handle (pointer) to the pointer array - * - * RETURNS - * Success: TRUE - * Failure: FALSE - */ - -BOOL WINAPI -DPA_DeleteAllPtrs (const HDPA hdpa) -{ - TRACE("(%p)\n", hdpa); - - if (!hdpa) - return FALSE; - - if (hdpa->ptrs && (!HeapFree (hdpa->hHeap, 0, hdpa->ptrs))) - return FALSE; - - hdpa->nItemCount = 0; - hdpa->nMaxCount = hdpa->nGrow * 2; - hdpa->ptrs = (LPVOID*)HeapAlloc (hdpa->hHeap, HEAP_ZERO_MEMORY, - hdpa->nMaxCount * sizeof(LPVOID)); - - return TRUE; -} - - -/************************************************************************** - * DPA_QuickSort [Internal] - * - * Ordinary quicksort (used by DPA_Sort). - * - * PARAMS - * lpPtrs [I] pointer to the pointer array - * l [I] index of the "left border" of the partition - * r [I] index of the "right border" of the partition - * pfnCompare [I] pointer to the compare function - * lParam [I] user defined value (3rd parameter in compare function) - * - * RETURNS - * NONE - */ - -static VOID -DPA_QuickSort (LPVOID *lpPtrs, INT l, INT r, - PFNDPACOMPARE pfnCompare, LPARAM lParam) -{ - INT m; - LPVOID t; - - TRACE("l=%i r=%i\n", l, r); - - if (l==r) /* one element is always sorted */ - return; - if (r0) - { - t = lpPtrs[m+1]; - memmove(&lpPtrs[l+1],&lpPtrs[l],(m-l+1)*sizeof(lpPtrs[l])); - lpPtrs[l] = t; - - m++; - } - l++; - } -} - - -/************************************************************************** - * DPA_Sort [COMCTL32.338] - * - * Sorts a pointer array using a user defined compare function - * - * PARAMS - * hdpa [I] handle (pointer) to the pointer array - * pfnCompare [I] pointer to the compare function - * lParam [I] user defined value (3rd parameter of compare function) - * - * RETURNS - * Success: TRUE - * Failure: FALSE - */ - -BOOL WINAPI -DPA_Sort (const HDPA hdpa, PFNDPACOMPARE pfnCompare, LPARAM lParam) -{ - if (!hdpa || !pfnCompare) - return FALSE; - - TRACE("(%p %p 0x%lx)\n", hdpa, pfnCompare, lParam); - - if ((hdpa->nItemCount > 1) && (hdpa->ptrs)) - DPA_QuickSort (hdpa->ptrs, 0, hdpa->nItemCount - 1, - pfnCompare, lParam); - - return TRUE; -} - - -/************************************************************************** - * DPA_Search [COMCTL32.339] - * - * Searches a pointer array for a specified pointer - * - * PARAMS - * hdpa [I] handle (pointer) to the pointer array - * pFind [I] pointer to search for - * nStart [I] start index - * pfnCompare [I] pointer to the compare function - * lParam [I] user defined value (3rd parameter of compare function) - * uOptions [I] search options - * - * RETURNS - * Success: index of the pointer in the array. - * Failure: -1 - * - * NOTES - * Binary search taken from R.Sedgewick "Algorithms in C"! - * Function is NOT tested! - * If something goes wrong, blame HIM not ME! (Eric Kohl) - */ - -INT WINAPI -DPA_Search (const HDPA hdpa, LPVOID pFind, INT nStart, - PFNDPACOMPARE pfnCompare, LPARAM lParam, UINT uOptions) -{ - if (!hdpa || !pfnCompare || !pFind) - return -1; - - TRACE("(%p %p %d %p 0x%08lx 0x%08x)\n", - hdpa, pFind, nStart, pfnCompare, lParam, uOptions); - - if (uOptions & DPAS_SORTED) { - /* array is sorted --> use binary search */ - INT l, r, x, n; - LPVOID *lpPtr; - - TRACE("binary search\n"); - - l = (nStart == -1) ? 0 : nStart; - r = hdpa->nItemCount - 1; - lpPtr = hdpa->ptrs; - while (r >= l) { - x = (l + r) / 2; - n = (pfnCompare)(pFind, lpPtr[x], lParam); - if (n < 0) - r = x - 1; - else - l = x + 1; - if (n == 0) { - TRACE("-- ret=%d\n", n); - return n; - } - } - - if (uOptions & DPAS_INSERTBEFORE) { - if (r == -1) r = 0; - TRACE("-- ret=%d\n", r); - return r; - } - - if (uOptions & DPAS_INSERTAFTER) { - TRACE("-- ret=%d\n", l); - return l; - } - } - else { - /* array is not sorted --> use linear search */ - LPVOID *lpPtr; - INT nIndex; - - TRACE("linear search\n"); - - nIndex = (nStart == -1)? 0 : nStart; - lpPtr = hdpa->ptrs; - for (; nIndex < hdpa->nItemCount; nIndex++) { - if ((pfnCompare)(pFind, lpPtr[nIndex], lParam) == 0) { - TRACE("-- ret=%d\n", nIndex); - return nIndex; - } - } - } - - TRACE("-- not found: ret=-1\n"); - return -1; -} - - -/************************************************************************** - * DPA_CreateEx [COMCTL32.340] - * - * Creates a dynamic pointer array using the specified size and heap. - * - * PARAMS - * nGrow [I] number of items by which the array grows when it is filled - * hHeap [I] handle to the heap where the array is stored - * - * RETURNS - * Success: handle (pointer) to the pointer array. - * Failure: NULL - * - * NOTES - * The DPA_ functions can be used to create and manipulate arrays of - * pointers. - */ - -HDPA WINAPI -DPA_CreateEx (INT nGrow, HANDLE hHeap) -{ - HDPA hdpa; - - TRACE("(%d %p)\n", nGrow, hHeap); - - if (hHeap) - hdpa = (HDPA)HeapAlloc (hHeap, HEAP_ZERO_MEMORY, sizeof(*hdpa)); - else - hdpa = Alloc (sizeof(*hdpa)); - - if (hdpa) { - hdpa->nGrow = max(8, nGrow); - hdpa->hHeap = hHeap ? hHeap : GetProcessHeap(); - hdpa->nMaxCount = hdpa->nGrow * 2; - hdpa->ptrs = HeapAlloc (hdpa->hHeap, HEAP_ZERO_MEMORY, - hdpa->nMaxCount * sizeof(LPVOID)); - } - - TRACE("-- %p\n", hdpa); - - return hdpa; -} - - -/************************************************************************** - * DPA_Create [COMCTL32.328] - * - * Creates a dynamic pointer array. - * - * PARAMS - * nGrow [I] number of items by which the array grows when it is filled - * - * RETURNS - * Success: handle (pointer) to the pointer array. - * Failure: NULL - * - * NOTES - * The DPA_ functions can be used to create and manipulate arrays of - * pointers. - */ - -HDPA WINAPI -DPA_Create (INT nGrow) -{ - return DPA_CreateEx( nGrow, 0 ); -} - - -/************************************************************************** - * Notification functions - */ - -typedef struct tagNOTIFYDATA -{ - HWND hwndFrom; - HWND hwndTo; - DWORD dwParam3; - DWORD dwParam4; - DWORD dwParam5; - DWORD dwParam6; -} NOTIFYDATA, *LPNOTIFYDATA; - - -/************************************************************************** - * DoNotify [Internal] - */ - -static LRESULT -DoNotify (LPNOTIFYDATA lpNotify, UINT uCode, LPNMHDR lpHdr) -{ - NMHDR nmhdr; - LPNMHDR lpNmh = NULL; - UINT idFrom = 0; - - TRACE("(%p %p %d %p 0x%08lx)\n", - lpNotify->hwndFrom, lpNotify->hwndTo, uCode, lpHdr, - lpNotify->dwParam5); - - if (!lpNotify->hwndTo) - return 0; - - if (lpNotify->hwndFrom == (HWND)-1) { - lpNmh = lpHdr; - idFrom = lpHdr->idFrom; - } - else { - if (lpNotify->hwndFrom) - idFrom = GetDlgCtrlID (lpNotify->hwndFrom); - - lpNmh = (lpHdr) ? lpHdr : &nmhdr; - - lpNmh->hwndFrom = lpNotify->hwndFrom; - lpNmh->idFrom = idFrom; - lpNmh->code = uCode; - } - - return SendMessageA (lpNotify->hwndTo, WM_NOTIFY, idFrom, (LPARAM)lpNmh); -} - - -/************************************************************************** - * SendNotify [COMCTL32.341] - * - * Sends a WM_NOTIFY message to the specified window. - * - * PARAMS - * hwndTo [I] Window to receive the message - * hwndFrom [I] Window that the message is from (see notes) - * uCode [I] Notification code - * lpHdr [I] The NMHDR and any additional information to send or NULL - * - * RETURNS - * Success: return value from notification - * Failure: 0 - * - * NOTES - * If hwndFrom is -1 then the identifier of the control sending the - * message is taken from the NMHDR structure. - * If hwndFrom is not -1 then lpHdr can be NULL. - */ - -LRESULT WINAPI SendNotify (HWND hwndTo, HWND hwndFrom, UINT uCode, LPNMHDR lpHdr) -{ - NOTIFYDATA notify; - - TRACE("(%p %p %d %p)\n", - hwndTo, hwndFrom, uCode, lpHdr); - - notify.hwndFrom = hwndFrom; - notify.hwndTo = hwndTo; - notify.dwParam5 = 0; - notify.dwParam6 = 0; - - return DoNotify (¬ify, uCode, lpHdr); -} - - -/************************************************************************** - * SendNotifyEx [COMCTL32.342] - * - * Sends a WM_NOTIFY message to the specified window. - * - * PARAMS - * hwndFrom [I] Window to receive the message - * hwndTo [I] Window that the message is from - * uCode [I] Notification code - * lpHdr [I] The NMHDR and any additional information to send or NULL - * dwParam5 [I] Unknown - * - * RETURNS - * Success: return value from notification - * Failure: 0 - * - * NOTES - * If hwndFrom is -1 then the identifier of the control sending the - * message is taken from the NMHDR structure. - * If hwndFrom is not -1 then lpHdr can be NULL. - */ - -LRESULT WINAPI SendNotifyEx (HWND hwndTo, HWND hwndFrom, UINT uCode, - LPNMHDR lpHdr, DWORD dwParam5) -{ - NOTIFYDATA notify; - HWND hwndNotify; - - TRACE("(%p %p %d %p 0x%08lx)\n", - hwndFrom, hwndTo, uCode, lpHdr, dwParam5); - - hwndNotify = hwndTo; - if (!hwndTo) { - if (IsWindow (hwndFrom)) { - hwndNotify = GetParent (hwndFrom); - if (!hwndNotify) - return 0; - } - } - - notify.hwndFrom = hwndFrom; - notify.hwndTo = hwndNotify; - notify.dwParam5 = dwParam5; - notify.dwParam6 = 0; - - return DoNotify (¬ify, uCode, lpHdr); -} - - - - -/************************************************************************** - * DPA_EnumCallback [COMCTL32.385] - * - * Enumerates all items in a dynamic pointer array. - * - * PARAMS - * hdpa [I] handle to the dynamic pointer array - * enumProc [I] - * lParam [I] - * - * RETURNS - * none - */ - -VOID WINAPI -DPA_EnumCallback (HDPA hdpa, PFNDPAENUMCALLBACK enumProc, LPVOID lParam) -{ - INT i; - - TRACE("(%p %p %p)\n", hdpa, enumProc, lParam); - - if (!hdpa) - return; - if (hdpa->nItemCount <= 0) - return; - - for (i = 0; i < hdpa->nItemCount; i++) { - if ((enumProc)(hdpa->ptrs[i], lParam) == 0) - return; - } - - return; -} - - -/************************************************************************** - * DPA_DestroyCallback [COMCTL32.386] - * - * Enumerates all items in a dynamic pointer array and destroys it. - * - * PARAMS - * hdpa [I] handle to the dynamic pointer array - * enumProc [I] - * lParam [I] - * - * RETURNS - * none - */ - -void WINAPI -DPA_DestroyCallback (HDPA hdpa, PFNDPAENUMCALLBACK enumProc, LPVOID lParam) -{ - TRACE("(%p %p %p)\n", hdpa, enumProc, lParam); - - DPA_EnumCallback (hdpa, enumProc, lParam); - DPA_Destroy (hdpa); -} - - -/************************************************************************** - * DSA_EnumCallback [COMCTL32.387] - * - * Enumerates all items in a dynamic storage array. - * - * PARAMS - * hdsa [I] handle to the dynamic storage array - * enumProc [I] - * lParam [I] - * - * RETURNS - * none - */ - -VOID WINAPI -DSA_EnumCallback (HDSA hdsa, PFNDSAENUMCALLBACK enumProc, LPVOID lParam) -{ - INT i; - - TRACE("(%p %p %p)\n", hdsa, enumProc, lParam); - - if (!hdsa) - return; - if (hdsa->nItemCount <= 0) - return; - - for (i = 0; i < hdsa->nItemCount; i++) { - LPVOID lpItem = DSA_GetItemPtr (hdsa, i); - if ((enumProc)(lpItem, lParam) == 0) - return; - } - - return; -} - - -/************************************************************************** - * DSA_DestroyCallback [COMCTL32.388] - * - * Enumerates all items in a dynamic storage array and destroys it. - * - * PARAMS - * hdsa [I] handle to the dynamic storage array - * enumProc [I] - * lParam [I] - * - * RETURNS - * none - */ - -void WINAPI -DSA_DestroyCallback (HDSA hdsa, PFNDSAENUMCALLBACK enumProc, LPVOID lParam) -{ - TRACE("(%p %p %p)\n", hdsa, enumProc, lParam); - - DSA_EnumCallback (hdsa, enumProc, lParam); - DSA_Destroy (hdsa); -} diff --git a/reactos/lib/comctl32/comctl_Cn.rc b/reactos/lib/comctl32/comctl_Cn.rc deleted file mode 100644 index b8272467a8c..00000000000 --- a/reactos/lib/comctl32/comctl_Cn.rc +++ /dev/null @@ -1,90 +0,0 @@ -/* - * Copyright 2002 Tisheng Chen - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2.1 of the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -LANGUAGE LANG_CHINESE, SUBLANG_CHINESE_SIMPLIFIED -#pragma code_page(936) - -IDD_PROPSHEET DIALOG DISCARDABLE 0, 0, 220, 140 -STYLE DS_CONTEXTHELP | DS_MODALFRAME | WS_POPUP | WS_CAPTION | WS_SYSMENU | WS_VISIBLE -CAPTION "ÊôÐÔ " -FONT 8, "MS Shell Dlg" -BEGIN - DEFPUSHBUTTON "È·¶¨", IDOK,4,122,50,14, WS_TABSTOP | WS_GROUP - PUSHBUTTON "È¡Ïû", IDCANCEL,58,122,50,14 - PUSHBUTTON "Ó¦ÓÃ(&A)", IDC_APPLY_BUTTON,112,122,50,14,WS_DISABLED - PUSHBUTTON "°ïÖú", IDHELP,166,122,50,14,WS_TABSTOP|WS_GROUP - CONTROL "Tab", IDC_TABCONTROL,"SysTabControl32",WS_CLIPSIBLINGS|WS_GROUP|WS_TABSTOP|TCS_MULTILINE,4,4,212,114 -END - - -IDD_WIZARD DIALOG DISCARDABLE 0, 0, 290, 159 -STYLE DS_MODALFRAME | WS_POPUP | WS_CAPTION | WS_SYSMENU | WS_VISIBLE -CAPTION "Wizard" -FONT 8, "MS Shell Dlg" -BEGIN - DEFPUSHBUTTON "½áÊø", IDC_FINISH_BUTTON,121,138,50,14 - DEFPUSHBUTTON "ÏÂÒ»²½(&N) >", IDC_NEXT_BUTTON,121,138,50,14 - PUSHBUTTON "< ÉÏÒ»²½(&B)", IDC_BACK_BUTTON,71,138,50,14 - PUSHBUTTON "È¡Ïû", IDCANCEL,178,138,50,14 - PUSHBUTTON "°ïÖú", IDHELP,235,138,50,14,WS_GROUP - LTEXT "", IDC_SUNKEN_LINE,7,129,278,1,SS_SUNKEN - CONTROL "Tab", IDC_TABCONTROL,"SysTabControl32",WS_CLIPSIBLINGS | WS_DISABLED,7,7,258,5 - LTEXT "", IDC_SUNKEN_LINEHEADER,0,35,290,1,SS_LEFT | SS_SUNKEN | WS_CHILD | WS_VISIBLE -END - - -IDD_TBCUSTOMIZE DIALOG DISCARDABLE 10, 20, 357, 125 -STYLE DS_MODALFRAME | WS_POPUP | WS_VISIBLE | WS_CAPTION | WS_SYSMENU -CAPTION "×Ô¶¨Ò幤¾ßÀ¸" -FONT 8, "MS Shell Dlg" -BEGIN - DEFPUSHBUTTON "¹Ø±Õ(&C)", IDCANCEL,308,6,44,14 - PUSHBUTTON "ÖØÖÃ(&e)", IDC_RESET_BTN,308,23,44,14 - PUSHBUTTON "°ïÖú(&H)", IDC_HELP_BTN,308,40,44,14 - PUSHBUTTON "ÉÏÒÆ(&U)", IDC_MOVEUP_BTN,308,74,44,14 - PUSHBUTTON "ÏÂÒÆ(&D)", IDC_MOVEDN_BTN,308,91,44,14 - LTEXT "¿ÉÓù¤¾ßÀ¸°´Å¥(&V):", -1,4,5,84,10 - LISTBOX IDC_AVAILBTN_LBOX,4,17,120,100, LBS_NOTIFY | LBS_OWNERDRAWFIXED | LBS_HASSTRINGS | LBS_NOINTEGRALHEIGHT | LBS_DISABLENOSCROLL | WS_BORDER | WS_VSCROLL | WS_HSCROLL | WS_TABSTOP - PUSHBUTTON "Ìí¼Ó(&A) ->", IDOK, 131, 42, 44, 14 - PUSHBUTTON "<- ɾ³ý(&R)", IDC_REMOVE_BTN,131,62,44,14 - LTEXT "µ±Ç°¹¤¾ßÀ¸°´Å¥(&T):", -1,182,5,78,10 - LISTBOX IDC_TOOLBARBTN_LBOX, 182,17,120,100,LBS_NOTIFY | LBS_OWNERDRAWFIXED | LBS_HASSTRINGS | LBS_NOINTEGRALHEIGHT | LBS_DISABLENOSCROLL | WS_BORDER | WS_VSCROLL | WS_HSCROLL | WS_TABSTOP -END - -STRINGTABLE DISCARDABLE -{ - IDS_CLOSE "¹Ø±Õ" -} - -STRINGTABLE DISCARDABLE -{ - IDM_TODAY "Today:" - IDM_GOTODAY "Go to today" -} - -STRINGTABLE DISCARDABLE -{ - IDS_SEPARATOR "·Ö¸ô·û" -} - -STRINGTABLE DISCARDABLE -{ - HKY_NONE "None" -} - -#pragma code_page(default) diff --git a/reactos/lib/comctl32/comctl_Cs.rc b/reactos/lib/comctl32/comctl_Cs.rc deleted file mode 100644 index 33773babfc9..00000000000 --- a/reactos/lib/comctl32/comctl_Cs.rc +++ /dev/null @@ -1,90 +0,0 @@ -/* - * Copyright 1999 Eric Kohl - * - * Czech resources for comctl32 - * Copyright 2004 David Kredba - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2.1 of the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -LANGUAGE LANG_CZECH, SUBLANG_DEFAULT - -IDD_PROPSHEET DIALOG DISCARDABLE 0, 0, 220, 140 -STYLE DS_CONTEXTHELP | DS_MODALFRAME | WS_POPUP | WS_CAPTION | WS_SYSMENU | WS_VISIBLE -CAPTION "Vlastnosti " -FONT 8, "MS Shell Dlg" -BEGIN - DEFPUSHBUTTON "OK", IDOK,4,122,50,14, WS_TABSTOP | WS_GROUP - PUSHBUTTON "Storno", IDCANCEL,58,122,50,14 - PUSHBUTTON "&Pou¾ít", IDC_APPLY_BUTTON,112,122,50,14,WS_DISABLED - PUSHBUTTON "Nápovìda", IDHELP,166,122,50,14,WS_TABSTOP|WS_GROUP - CONTROL "Tab", IDC_TABCONTROL,"SysTabControl32",WS_CLIPSIBLINGS|WS_GROUP|WS_TABSTOP|TCS_MULTILINE,4,4,212,114 -END - - -IDD_WIZARD DIALOG DISCARDABLE 0, 0, 290, 159 -STYLE DS_MODALFRAME | WS_POPUP | WS_CAPTION | WS_SYSMENU | WS_VISIBLE -CAPTION "Prùvodce" -FONT 8, "MS Shell Dlg" -BEGIN - DEFPUSHBUTTON "Dokonèit", IDC_FINISH_BUTTON,121,138,50,14 - DEFPUSHBUTTON "&Dal¹í >", IDC_NEXT_BUTTON,121,138,50,14 - PUSHBUTTON "< &Zpìt", IDC_BACK_BUTTON,71,138,50,14 - PUSHBUTTON "Storno", IDCANCEL,178,138,50,14 - PUSHBUTTON "Nápovìda", IDHELP,235,138,50,14,WS_GROUP - LTEXT "", IDC_SUNKEN_LINE,7,129,278,1,SS_SUNKEN - CONTROL "Tab", IDC_TABCONTROL,"SysTabControl32",WS_CLIPSIBLINGS | WS_DISABLED,7,7,258,5 - LTEXT "", IDC_SUNKEN_LINEHEADER,0,35,290,1,SS_LEFT | SS_SUNKEN | WS_CHILD | WS_VISIBLE -END - - -IDD_TBCUSTOMIZE DIALOG DISCARDABLE 10, 20, 357, 125 -STYLE DS_MODALFRAME | WS_POPUP | WS_VISIBLE | WS_CAPTION | WS_SYSMENU -CAPTION "Nastavení panelu" -FONT 8, "MS Shell Dlg" -BEGIN - DEFPUSHBUTTON "&Zavøít", IDCANCEL,308,6,44,14 - PUSHBUTTON "&Výchozí", IDC_RESET_BTN,308,23,44,14 - PUSHBUTTON "&Nápovìda", IDC_HELP_BTN,308,40,44,14 - PUSHBUTTON "Nahor&u", IDC_MOVEUP_BTN,308,74,44,14 - PUSHBUTTON "&Dolù", IDC_MOVEDN_BTN,308,91,44,14 - LTEXT "D&ostupná tlaèítka:", -1,4,5,84,10 - LISTBOX IDC_AVAILBTN_LBOX,4,17,120,100, LBS_NOTIFY | LBS_OWNERDRAWFIXED | LBS_HASSTRINGS | LBS_NOINTEGRALHEIGHT | LBS_DISABLENOSCROLL | WS_BORDER | WS_VSCROLL | WS_HSCROLL | WS_TABSTOP - PUSHBUTTON "Pøid&at ->", IDOK, 131, 42, 44, 14 - PUSHBUTTON "<- Odeb&rat", IDC_REMOVE_BTN,131,62,44,14 - LTEXT "&Tlaèítka panelu:", -1,182,5,78,10 - LISTBOX IDC_TOOLBARBTN_LBOX, 182,17,120,100,LBS_NOTIFY | LBS_OWNERDRAWFIXED | LBS_HASSTRINGS | LBS_NOINTEGRALHEIGHT | LBS_DISABLENOSCROLL | WS_BORDER | WS_VSCROLL | WS_HSCROLL | WS_TABSTOP -END - -STRINGTABLE DISCARDABLE -{ - IDS_CLOSE "Zavøít" -} - -STRINGTABLE DISCARDABLE -{ - IDM_TODAY "Dnes:" - IDM_GOTODAY "Jdi na dne¹ek" -} - -STRINGTABLE DISCARDABLE -{ - IDS_SEPARATOR "Oddìlovaè" -} - -STRINGTABLE DISCARDABLE -{ - HKY_NONE "®ádný" -} diff --git a/reactos/lib/comctl32/comctl_De.rc b/reactos/lib/comctl32/comctl_De.rc deleted file mode 100644 index a1073ceb4fb..00000000000 --- a/reactos/lib/comctl32/comctl_De.rc +++ /dev/null @@ -1,87 +0,0 @@ -/* - * Copyright 2000 Uwe Bonnes - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2.1 of the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -LANGUAGE LANG_GERMAN, SUBLANG_DEFAULT - -STRINGTABLE DISCARDABLE -{ - IDS_CLOSE "Schließen" -} - -STRINGTABLE DISCARDABLE -{ - IDM_TODAY "Heute:" - IDM_GOTODAY "Gehe zu Heute" -} - -STRINGTABLE DISCARDABLE -{ - IDS_SEPARATOR "Trennzeichen" -} - -STRINGTABLE DISCARDABLE -{ - HKY_NONE "Keiner" -} - -IDD_PROPSHEET DIALOG DISCARDABLE 0, 0, 220, 140 -STYLE DS_CONTEXTHELP | DS_MODALFRAME | WS_POPUP | WS_CAPTION | WS_SYSMENU | WS_VISIBLE -CAPTION "Eigenschaften für " -FONT 8, "MS Shell Dlg" -BEGIN - DEFPUSHBUTTON "&OK", IDOK,4,122,50,14, WS_TABSTOP | WS_GROUP - PUSHBUTTON "A&bbrechen", IDCANCEL,58,122,50,14 - PUSHBUTTON "&Anwenden", IDC_APPLY_BUTTON,112,122,50,14,WS_DISABLED - PUSHBUTTON "&Hilfe", IDHELP,166,122,50,14,WS_TABSTOP|WS_GROUP - CONTROL "Tab", IDC_TABCONTROL,"SysTabControl32",WS_CLIPSIBLINGS|WS_GROUP|WS_TABSTOP|TCS_MULTILINE,4,4,212,114 -END - - -IDD_WIZARD DIALOG DISCARDABLE 0, 0, 290, 159 -STYLE DS_MODALFRAME | WS_POPUP | WS_CAPTION | WS_SYSMENU | WS_VISIBLE -CAPTION "Wizard" -FONT 8, "MS Shell Dlg" -BEGIN - DEFPUSHBUTTON "&Beenden", IDC_FINISH_BUTTON,121,138,50,14 - DEFPUSHBUTTON "&Weiter >", IDC_NEXT_BUTTON,121,138,50,14 - PUSHBUTTON "< &Zurück", IDC_BACK_BUTTON,71,138,50,14 - PUSHBUTTON "Abbrechen", IDCANCEL,178,138,50,14 - PUSHBUTTON "&Hilfe", IDHELP,235,138,50,14,WS_GROUP - LTEXT "", IDC_SUNKEN_LINE,7,129,278,1,SS_SUNKEN - CONTROL "Tab", IDC_TABCONTROL,"SysTabControl32",WS_CLIPSIBLINGS | WS_DISABLED,7,7,258,5 - LTEXT "", IDC_SUNKEN_LINEHEADER,0,35,290,1,SS_LEFT | SS_SUNKEN | WS_CHILD | WS_VISIBLE -END - - -IDD_TBCUSTOMIZE DIALOG DISCARDABLE 10, 20, 357, 125 -STYLE DS_MODALFRAME | WS_POPUP | WS_VISIBLE | WS_CAPTION | WS_SYSMENU -CAPTION "Toolbar einrichten" -FONT 8, "MS Shell Dlg" -BEGIN - DEFPUSHBUTTON "&Schließen", IDCANCEL,308,6,44,14 - PUSHBUTTON "&Zurücksetzen", IDC_RESET_BTN,308,23,44,14 - PUSHBUTTON "&Hilfe", IDC_HELP_BTN,308,40,44,14 - PUSHBUTTON "Nach &Oben verschieben", IDC_MOVEUP_BTN,308,74,44,14 - PUSHBUTTON "Nach &Unten verschieben", IDC_MOVEDN_BTN,308,91,44,14 - LTEXT "&Vorhandene Knöpfe:", -1,4,5,84,10 - LISTBOX IDC_AVAILBTN_LBOX,4,17,120,100, LBS_NOTIFY | LBS_OWNERDRAWFIXED | LBS_HASSTRINGS | LBS_NOINTEGRALHEIGHT | LBS_DISABLENOSCROLL | WS_BORDER | WS_VSCROLL | WS_HSCROLL | WS_TABSTOP - PUSHBUTTON "H&inzufügen ->", IDOK, 131, 42, 44, 14 - PUSHBUTTON "<- &Löschen", IDC_REMOVE_BTN,131,62,44,14 - LTEXT "&Toolbarknöpfe:", -1,182,5,78,10 - LISTBOX IDC_TOOLBARBTN_LBOX, 182,17,120,100,LBS_NOTIFY | LBS_OWNERDRAWFIXED | LBS_HASSTRINGS | LBS_NOINTEGRALHEIGHT | LBS_DISABLENOSCROLL | WS_BORDER | WS_VSCROLL | WS_HSCROLL | WS_TABSTOP -END diff --git a/reactos/lib/comctl32/comctl_En.rc b/reactos/lib/comctl32/comctl_En.rc deleted file mode 100644 index bcedb1a85d8..00000000000 --- a/reactos/lib/comctl32/comctl_En.rc +++ /dev/null @@ -1,87 +0,0 @@ -/* - * Copyright 1999 Eric Kohl - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2.1 of the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -LANGUAGE LANG_ENGLISH, SUBLANG_DEFAULT - -IDD_PROPSHEET DIALOG DISCARDABLE 0, 0, 220, 140 -STYLE DS_CONTEXTHELP | DS_MODALFRAME | WS_POPUP | WS_CAPTION | WS_SYSMENU | WS_VISIBLE -CAPTION "Properties for " -FONT 8, "MS Shell Dlg" -BEGIN - DEFPUSHBUTTON "OK", IDOK,4,122,50,14, WS_TABSTOP | WS_GROUP - PUSHBUTTON "Cancel", IDCANCEL,58,122,50,14 - PUSHBUTTON "&Apply", IDC_APPLY_BUTTON,112,122,50,14,WS_DISABLED - PUSHBUTTON "Help", IDHELP,166,122,50,14,WS_TABSTOP|WS_GROUP - CONTROL "Tab", IDC_TABCONTROL,"SysTabControl32",WS_CLIPSIBLINGS|WS_GROUP|WS_TABSTOP|TCS_MULTILINE,4,4,212,114 -END - - -IDD_WIZARD DIALOG DISCARDABLE 0, 0, 290, 159 -STYLE DS_MODALFRAME | WS_POPUP | WS_CAPTION | WS_SYSMENU | WS_VISIBLE -CAPTION "Wizard" -FONT 8, "MS Shell Dlg" -BEGIN - DEFPUSHBUTTON "Finish", IDC_FINISH_BUTTON,121,138,50,14 - DEFPUSHBUTTON "&Next >", IDC_NEXT_BUTTON,121,138,50,14 - PUSHBUTTON "< &Back", IDC_BACK_BUTTON,71,138,50,14 - PUSHBUTTON "Cancel", IDCANCEL,178,138,50,14 - PUSHBUTTON "Help", IDHELP,235,138,50,14,WS_GROUP - LTEXT "", IDC_SUNKEN_LINE,7,129,278,1,SS_SUNKEN - CONTROL "Tab", IDC_TABCONTROL,"SysTabControl32",WS_CLIPSIBLINGS | WS_DISABLED,7,7,258,5 - LTEXT "", IDC_SUNKEN_LINEHEADER,0,35,290,1,SS_LEFT | SS_SUNKEN | WS_CHILD | WS_VISIBLE -END - - -IDD_TBCUSTOMIZE DIALOG DISCARDABLE 10, 20, 357, 125 -STYLE DS_MODALFRAME | WS_POPUP | WS_VISIBLE | WS_CAPTION | WS_SYSMENU -CAPTION "Customize Toolbar" -FONT 8, "MS Shell Dlg" -BEGIN - DEFPUSHBUTTON "&Close", IDCANCEL,308,6,44,14 - PUSHBUTTON "R&eset", IDC_RESET_BTN,308,23,44,14 - PUSHBUTTON "&Help", IDC_HELP_BTN,308,40,44,14 - PUSHBUTTON "Move &Up", IDC_MOVEUP_BTN,308,74,44,14 - PUSHBUTTON "Move &Down", IDC_MOVEDN_BTN,308,91,44,14 - LTEXT "A&vailable buttons:", -1,4,5,84,10 - LISTBOX IDC_AVAILBTN_LBOX,4,17,120,100, LBS_NOTIFY | LBS_OWNERDRAWFIXED | LBS_HASSTRINGS | LBS_NOINTEGRALHEIGHT | LBS_DISABLENOSCROLL | WS_BORDER | WS_VSCROLL | WS_HSCROLL | WS_TABSTOP - PUSHBUTTON "&Add ->", IDOK, 131, 42, 44, 14 - PUSHBUTTON "<- &Remove", IDC_REMOVE_BTN,131,62,44,14 - LTEXT "&Toolbar buttons:", -1,182,5,78,10 - LISTBOX IDC_TOOLBARBTN_LBOX, 182,17,120,100,LBS_NOTIFY | LBS_OWNERDRAWFIXED | LBS_HASSTRINGS | LBS_NOINTEGRALHEIGHT | LBS_DISABLENOSCROLL | WS_BORDER | WS_VSCROLL | WS_HSCROLL | WS_TABSTOP -END - -STRINGTABLE DISCARDABLE -{ - IDS_CLOSE "Close" -} - -STRINGTABLE DISCARDABLE -{ - IDM_TODAY "Today:" - IDM_GOTODAY "Go to today" -} - -STRINGTABLE DISCARDABLE -{ - IDS_SEPARATOR "Separator" -} - -STRINGTABLE DISCARDABLE -{ - HKY_NONE "None" -} diff --git a/reactos/lib/comctl32/comctl_Es.rc b/reactos/lib/comctl32/comctl_Es.rc deleted file mode 100644 index 281ec0f71f3..00000000000 --- a/reactos/lib/comctl32/comctl_Es.rc +++ /dev/null @@ -1,87 +0,0 @@ -/* - * Copyright 2003 José Manuel Ferrer Ortiz - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2.1 of the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -LANGUAGE LANG_SPANISH, SUBLANG_DEFAULT - -IDD_PROPSHEET DIALOG DISCARDABLE 0, 0, 220, 140 -STYLE DS_CONTEXTHELP | DS_MODALFRAME | WS_POPUP | WS_CAPTION | WS_SYSMENU | WS_VISIBLE -CAPTION "Propiedades de " -FONT 8, "MS Shell Dlg" -BEGIN - DEFPUSHBUTTON "Aceptar", IDOK,4,122,50,14, WS_TABSTOP | WS_GROUP - PUSHBUTTON "Cancelar", IDCANCEL,58,122,50,14 - PUSHBUTTON "&Aplicar", IDC_APPLY_BUTTON,112,122,50,14,WS_DISABLED - PUSHBUTTON "Ayuda", IDHELP,166,122,50,14,WS_TABSTOP|WS_GROUP - CONTROL "Tab", IDC_TABCONTROL,"SysTabControl32",WS_CLIPSIBLINGS|WS_GROUP|WS_TABSTOP|TCS_MULTILINE,4,4,212,114 -END - - -IDD_WIZARD DIALOG DISCARDABLE 0, 0, 290, 159 -STYLE DS_MODALFRAME | WS_POPUP | WS_CAPTION | WS_SYSMENU | WS_VISIBLE -CAPTION "Ayudante" -FONT 8, "MS Shell Dlg" -BEGIN - DEFPUSHBUTTON "Terminar", IDC_FINISH_BUTTON,121,138,50,14 - DEFPUSHBUTTON "&Siguiente >", IDC_NEXT_BUTTON,121,138,50,14 - PUSHBUTTON "< &Anterior", IDC_BACK_BUTTON,71,138,50,14 - PUSHBUTTON "Cancelar", IDCANCEL,178,138,50,14 - PUSHBUTTON "Ayuda", IDHELP,235,138,50,14,WS_GROUP - LTEXT "", IDC_SUNKEN_LINE,7,129,278,1,SS_SUNKEN - CONTROL "Tab", IDC_TABCONTROL,"SysTabControl32",WS_CLIPSIBLINGS | WS_DISABLED,7,7,258,5 - LTEXT "", IDC_SUNKEN_LINEHEADER,0,35,290,1,SS_LEFT | SS_SUNKEN | WS_CHILD | WS_VISIBLE -END - - -IDD_TBCUSTOMIZE DIALOG DISCARDABLE 10, 20, 357, 125 -STYLE DS_MODALFRAME | WS_POPUP | WS_VISIBLE | WS_CAPTION | WS_SYSMENU -CAPTION "Personalizar barra de herramientas" -FONT 8, "MS Shell Dlg" -BEGIN - DEFPUSHBUTTON "&Cerrar", IDCANCEL,308,6,44,14 - PUSHBUTTON "R&estaurar", IDC_RESET_BTN,308,23,44,14 - PUSHBUTTON "&Ayuda", IDC_HELP_BTN,308,40,44,14 - PUSHBUTTON "Mover A&rriba", IDC_MOVEUP_BTN,308,74,44,14 - PUSHBUTTON "Mover A&bajo", IDC_MOVEDN_BTN,308,91,44,14 - LTEXT "Botones &disponibles:", -1,4,5,84,10 - LISTBOX IDC_AVAILBTN_LBOX,4,17,120,100, LBS_NOTIFY | LBS_OWNERDRAWFIXED | LBS_HASSTRINGS | LBS_NOINTEGRALHEIGHT | LBS_DISABLENOSCROLL | WS_BORDER | WS_VSCROLL | WS_HSCROLL | WS_TABSTOP - PUSHBUTTON "A&ñadir ->", IDOK, 131, 42, 44, 14 - PUSHBUTTON "<- &Eliminar", IDC_REMOVE_BTN,131,62,44,14 - LTEXT "B&otones de la barra:", -1,182,5,78,10 - LISTBOX IDC_TOOLBARBTN_LBOX, 182,17,120,100,LBS_NOTIFY | LBS_OWNERDRAWFIXED | LBS_HASSTRINGS | LBS_NOINTEGRALHEIGHT | LBS_DISABLENOSCROLL | WS_BORDER | WS_VSCROLL | WS_HSCROLL | WS_TABSTOP -END - -STRINGTABLE DISCARDABLE -{ - IDS_CLOSE "Cerrar" -} - -STRINGTABLE DISCARDABLE -{ - IDM_TODAY "Hoy:" - IDM_GOTODAY "Ir a hoy" -} - -STRINGTABLE DISCARDABLE -{ - IDS_SEPARATOR "Separador" -} - -STRINGTABLE DISCARDABLE -{ - HKY_NONE "Ninguno" -} diff --git a/reactos/lib/comctl32/comctl_Fr.rc b/reactos/lib/comctl32/comctl_Fr.rc deleted file mode 100644 index 1dde79f8fd3..00000000000 --- a/reactos/lib/comctl32/comctl_Fr.rc +++ /dev/null @@ -1,91 +0,0 @@ -/* - * Comctl32 - * French language support - * - * Copyright 1999 Eric Kohl - * Copyright 2003 Vincent Béron - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2.1 of the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -LANGUAGE LANG_FRENCH, SUBLANG_NEUTRAL - -IDD_PROPSHEET DIALOG DISCARDABLE 0, 0, 220, 140 -STYLE DS_CONTEXTHELP | DS_MODALFRAME | WS_POPUP | WS_CAPTION | WS_SYSMENU | WS_VISIBLE -CAPTION "Propriétés pour " -FONT 8, "MS Shell Dlg" -BEGIN - DEFPUSHBUTTON "OK", IDOK,4,122,50,14, WS_TABSTOP | WS_GROUP - PUSHBUTTON "Annuler", IDCANCEL,58,122,50,14 - PUSHBUTTON "&Appliquer", IDC_APPLY_BUTTON,112,122,50,14,WS_DISABLED - PUSHBUTTON "Aide", IDHELP,166,122,50,14,WS_TABSTOP|WS_GROUP - CONTROL "onglet", IDC_TABCONTROL,"SysTabControl32",WS_CLIPSIBLINGS|WS_GROUP|WS_TABSTOP|TCS_MULTILINE,4,4,212,114 -END - - -IDD_WIZARD DIALOG DISCARDABLE 0, 0, 290, 159 -STYLE DS_MODALFRAME | WS_POPUP | WS_CAPTION | WS_SYSMENU | WS_VISIBLE -CAPTION "Assistant" -FONT 8, "MS Shell Dlg" -BEGIN - DEFPUSHBUTTON "Terminer", IDC_FINISH_BUTTON,121,138,50,14 - DEFPUSHBUTTON "&Suivant >", IDC_NEXT_BUTTON,121,138,50,14 - PUSHBUTTON "< &Précédent", IDC_BACK_BUTTON,71,138,50,14 - PUSHBUTTON "Annuler", IDCANCEL,178,138,50,14 - PUSHBUTTON "Aide", IDHELP,235,138,50,14,WS_GROUP - LTEXT "", IDC_SUNKEN_LINE,7,129,278,1,SS_SUNKEN - CONTROL "Onglet", IDC_TABCONTROL,"SysTabControl32",WS_CLIPSIBLINGS | WS_DISABLED,7,7,258,5 - LTEXT "", IDC_SUNKEN_LINEHEADER,0,35,290,1,SS_LEFT | SS_SUNKEN | WS_CHILD | WS_VISIBLE -END - - -IDD_TBCUSTOMIZE DIALOG DISCARDABLE 10, 20, 357, 125 -STYLE DS_MODALFRAME | WS_POPUP | WS_VISIBLE | WS_CAPTION | WS_SYSMENU -CAPTION "Personnaliser la barre d'outils" -FONT 8, "MS Shell Dlg" -BEGIN - DEFPUSHBUTTON "&Fermer", IDCANCEL,308,6,44,14 - PUSHBUTTON "&Réinitialiser", IDC_RESET_BTN,308,23,44,14 - PUSHBUTTON "&Aide", IDC_HELP_BTN,308,40,44,14 - PUSHBUTTON "&Monter", IDC_MOVEUP_BTN,308,74,44,14 - PUSHBUTTON "&Descendre", IDC_MOVEDN_BTN,308,91,44,14 - LTEXT "Boutons disponibles :", -1,4,5,84,10 - LISTBOX IDC_AVAILBTN_LBOX,4,17,120,100, LBS_NOTIFY | LBS_OWNERDRAWFIXED | LBS_HASSTRINGS | LBS_NOINTEGRALHEIGHT | LBS_DISABLENOSCROLL | WS_BORDER | WS_VSCROLL | WS_HSCROLL | WS_TABSTOP - PUSHBUTTON "A&jouter ->", IDOK, 131, 42, 44, 14 - PUSHBUTTON "<- &Enlever", IDC_REMOVE_BTN,131,62,44,14 - LTEXT "&Boutons de la barre d'outils :", -1,182,5,78,10 - LISTBOX IDC_TOOLBARBTN_LBOX, 182,17,120,100,LBS_NOTIFY | LBS_OWNERDRAWFIXED | LBS_HASSTRINGS | LBS_NOINTEGRALHEIGHT | LBS_DISABLENOSCROLL | WS_BORDER | WS_VSCROLL | WS_HSCROLL | WS_TABSTOP -END - -STRINGTABLE DISCARDABLE -{ - IDS_CLOSE "Fermer" -} - -STRINGTABLE DISCARDABLE -{ - IDM_TODAY "Aujourd'hui:" - IDM_GOTODAY "Aller à aujourd'hui" -} - -STRINGTABLE DISCARDABLE -{ - IDS_SEPARATOR "Séparateur" -} - -STRINGTABLE DISCARDABLE -{ - HKY_NONE "Aucun" -} diff --git a/reactos/lib/comctl32/comctl_It.rc b/reactos/lib/comctl32/comctl_It.rc deleted file mode 100644 index 92dd3d67368..00000000000 --- a/reactos/lib/comctl32/comctl_It.rc +++ /dev/null @@ -1,88 +0,0 @@ -/* - * Copyright 1999 Eric Kohl - * Copyright 2003 Ivan Leo Puoti - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2.1 of the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -LANGUAGE LANG_ITALIAN, SUBLANG_DEFAULT - -IDD_PROPSHEET DIALOG DISCARDABLE 0, 0, 220, 140 -STYLE DS_CONTEXTHELP | DS_MODALFRAME | WS_POPUP | WS_CAPTION | WS_SYSMENU | WS_VISIBLE -CAPTION "Proprietà per " -FONT 8, "MS Shell Dlg" -BEGIN - DEFPUSHBUTTON "OK", IDOK,4,122,50,14, WS_TABSTOP | WS_GROUP - PUSHBUTTON "Annulla", IDCANCEL,58,122,50,14 - PUSHBUTTON "&Applica", IDC_APPLY_BUTTON,112,122,50,14,WS_DISABLED - PUSHBUTTON "Aiuto", IDHELP,166,122,50,14,WS_TABSTOP|WS_GROUP - CONTROL "Linguetta", IDC_TABCONTROL,"SysTabControl32",WS_CLIPSIBLINGS|WS_GROUP|WS_TABSTOP|TCS_MULTILINE,4,4,212,114 -END - - -IDD_WIZARD DIALOG DISCARDABLE 0, 0, 290, 159 -STYLE DS_MODALFRAME | WS_POPUP | WS_CAPTION | WS_SYSMENU | WS_VISIBLE -CAPTION "Wizard" -FONT 8, "MS Shell Dlg" -BEGIN - DEFPUSHBUTTON "Fine", IDC_FINISH_BUTTON,121,138,50,14 - DEFPUSHBUTTON "&Avanti >", IDC_NEXT_BUTTON,121,138,50,14 - PUSHBUTTON "< &Indietro", IDC_BACK_BUTTON,71,138,50,14 - PUSHBUTTON "Anulla", IDCANCEL,178,138,50,14 - PUSHBUTTON "Aiuto", IDHELP,235,138,50,14,WS_GROUP - LTEXT "", IDC_SUNKEN_LINE,7,129,278,1,SS_SUNKEN - CONTROL "Linguetta", IDC_TABCONTROL,"SysTabControl32",WS_CLIPSIBLINGS | WS_DISABLED,7,7,258,5 - LTEXT "", IDC_SUNKEN_LINEHEADER,0,35,290,1,SS_LEFT | SS_SUNKEN | WS_CHILD | WS_VISIBLE -END - - -IDD_TBCUSTOMIZE DIALOG DISCARDABLE 10, 20, 357, 125 -STYLE DS_MODALFRAME | WS_POPUP | WS_VISIBLE | WS_CAPTION | WS_SYSMENU -CAPTION "Personalitta la barra degli strumenti" -FONT 8, "MS Shell Dlg" -BEGIN - DEFPUSHBUTTON "&Chiudi", IDCANCEL,308,6,44,14 - PUSHBUTTON "R&eimpostare", IDC_RESET_BTN,308,23,44,14 - PUSHBUTTON "&Aiuto", IDC_HELP_BTN,308,40,44,14 - PUSHBUTTON "Muovi &Su", IDC_MOVEUP_BTN,308,74,44,14 - PUSHBUTTON "Muovi &giù", IDC_MOVEDN_BTN,308,91,44,14 - LTEXT "&Tasti disponibili:", -1,4,5,84,10 - LISTBOX IDC_AVAILBTN_LBOX,4,17,120,100, LBS_NOTIFY | LBS_OWNERDRAWFIXED | LBS_HASSTRINGS | LBS_NOINTEGRALHEIGHT | LBS_DISABLENOSCROLL | WS_BORDER | WS_VSCROLL | WS_HSCROLL | WS_TABSTOP - PUSHBUTTON "&Aggiungi ->", IDOK, 131, 42, 44, 14 - PUSHBUTTON "<- &Rimuovi", IDC_REMOVE_BTN,131,62,44,14 - LTEXT "&Tast della barra degli strumenti:", -1,182,5,78,10 - LISTBOX IDC_TOOLBARBTN_LBOX, 182,17,120,100,LBS_NOTIFY | LBS_OWNERDRAWFIXED | LBS_HASSTRINGS | LBS_NOINTEGRALHEIGHT | LBS_DISABLENOSCROLL | WS_BORDER | WS_VSCROLL | WS_HSCROLL | WS_TABSTOP -END - -STRINGTABLE DISCARDABLE -{ - IDS_CLOSE "Chiudi" -} - -STRINGTABLE DISCARDABLE -{ - IDM_TODAY "Oggi:" - IDM_GOTODAY "Vai a oggi" -} - -STRINGTABLE DISCARDABLE -{ - IDS_SEPARATOR "Separatore" -} - -STRINGTABLE DISCARDABLE -{ - HKY_NONE "Nessuno" -} diff --git a/reactos/lib/comctl32/comctl_Ja.rc b/reactos/lib/comctl32/comctl_Ja.rc deleted file mode 100644 index 2ccd2d06c4f..00000000000 --- a/reactos/lib/comctl32/comctl_Ja.rc +++ /dev/null @@ -1,87 +0,0 @@ -/* - * Copyright 2003 Hajime Segawa - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2.1 of the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -LANGUAGE LANG_JAPANESE, SUBLANG_DEFAULT - -IDD_PROPSHEET DIALOG DISCARDABLE 0, 0, 220, 140 -STYLE DS_CONTEXTHELP | DS_MODALFRAME | WS_POPUP | WS_CAPTION | WS_SYSMENU | WS_VISIBLE -CAPTION "Properties for " -FONT 9, "MS UI Gothic" -BEGIN - DEFPUSHBUTTON "OK", IDOK,4,122,50,14, WS_TABSTOP | WS_GROUP - PUSHBUTTON "ƒLƒƒƒ“ƒZƒ‹", IDCANCEL,58,122,50,14 - PUSHBUTTON "“K—p(&A)", IDC_APPLY_BUTTON,112,122,50,14,WS_DISABLED - PUSHBUTTON "ƒwƒ‹ƒv", IDHELP,166,122,50,14,WS_TABSTOP|WS_GROUP - CONTROL "Tab", IDC_TABCONTROL,"SysTabControl32",WS_CLIPSIBLINGS|WS_GROUP|WS_TABSTOP|TCS_MULTILINE,4,4,212,114 -END - - -IDD_WIZARD DIALOG DISCARDABLE 0, 0, 290, 159 -STYLE DS_MODALFRAME | WS_POPUP | WS_CAPTION | WS_SYSMENU | WS_VISIBLE -CAPTION "Wizard" -FONT 9, "MS UI Gothic" -BEGIN - DEFPUSHBUTTON "Š®—¹", IDC_FINISH_BUTTON,121,138,50,14 - DEFPUSHBUTTON "i‚Þ(&N) >", IDC_NEXT_BUTTON,121,138,50,14 - PUSHBUTTON "< –ß‚é(&B)", IDC_BACK_BUTTON,71,138,50,14 - PUSHBUTTON "ƒLƒƒƒ“ƒZƒ‹", IDCANCEL,178,138,50,14 - PUSHBUTTON "ƒwƒ‹ƒv", IDHELP,235,138,50,14,WS_GROUP - LTEXT "", IDC_SUNKEN_LINE,7,129,278,1,SS_SUNKEN - CONTROL "Tab", IDC_TABCONTROL,"SysTabControl32",WS_CLIPSIBLINGS | WS_DISABLED,7,7,258,5 - LTEXT "", IDC_SUNKEN_LINEHEADER,0,35,290,1,SS_LEFT | SS_SUNKEN | WS_CHILD | WS_VISIBLE -END - - -IDD_TBCUSTOMIZE DIALOG DISCARDABLE 10, 20, 357, 125 -STYLE DS_MODALFRAME | WS_POPUP | WS_VISIBLE | WS_CAPTION | WS_SYSMENU -CAPTION "Customize Toolbar" -FONT 9, "MS UI Gothic" -BEGIN - DEFPUSHBUTTON "•‚¶‚é(&C)", IDCANCEL,308,6,44,14 - PUSHBUTTON "ƒŠƒZƒbƒg(R&)", IDC_RESET_BTN,308,23,44,14 - PUSHBUTTON "ƒwƒ‹ƒv(&H)", IDC_HELP_BTN,308,40,44,14 - PUSHBUTTON "ã‚Ö (&U)", IDC_MOVEUP_BTN,308,74,44,14 - PUSHBUTTON "‰º‚Ö (&D)", IDC_MOVEDN_BTN,308,91,44,14 - LTEXT "A&vailable buttons:", -1,4,5,84,10 - LISTBOX IDC_AVAILBTN_LBOX,4,17,120,100, LBS_NOTIFY | LBS_OWNERDRAWFIXED | LBS_HASSTRINGS | LBS_NOINTEGRALHEIGHT | LBS_DISABLENOSCROLL | WS_BORDER | WS_VSCROLL | WS_HSCROLL | WS_TABSTOP - PUSHBUTTON "’ljÁ(&A) ->", IDOK, 131, 42, 44, 14 - PUSHBUTTON "<- íœ(&R)", IDC_REMOVE_BTN,131,62,44,14 - LTEXT "&Toolbar buttons:", -1,182,5,78,10 - LISTBOX IDC_TOOLBARBTN_LBOX, 182,17,120,100,LBS_NOTIFY | LBS_OWNERDRAWFIXED | LBS_HASSTRINGS | LBS_NOINTEGRALHEIGHT | LBS_DISABLENOSCROLL | WS_BORDER | WS_VSCROLL | WS_HSCROLL | WS_TABSTOP -END - -STRINGTABLE DISCARDABLE -{ - IDS_CLOSE "Close" -} - -STRINGTABLE DISCARDABLE -{ - IDM_TODAY "Today:" - IDM_GOTODAY "Go to today" -} - -STRINGTABLE DISCARDABLE -{ - IDS_SEPARATOR "Separator" -} - -STRINGTABLE DISCARDABLE -{ - HKY_NONE "None" -} diff --git a/reactos/lib/comctl32/comctl_Ko.rc b/reactos/lib/comctl32/comctl_Ko.rc deleted file mode 100644 index 65cec0d9f37..00000000000 --- a/reactos/lib/comctl32/comctl_Ko.rc +++ /dev/null @@ -1,82 +0,0 @@ -/* - * Copyright 2002 Won-kyu Park - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2.1 of the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -LANGUAGE LANG_KOREAN, SUBLANG_DEFAULT - -IDD_PROPSHEET DIALOG DISCARDABLE 0, 0, 220, 140 -STYLE DS_CONTEXTHELP | DS_MODALFRAME | WS_POPUP | WS_CAPTION | WS_SYSMENU | WS_VISIBLE -CAPTION "Properties for " -FONT 9, "MS Shell Dlg" -BEGIN - DEFPUSHBUTTON "È®ÀÎ", IDOK,4,122,50,14, WS_TABSTOP | WS_GROUP - PUSHBUTTON "Ãë¼Ò", IDCANCEL,58,122,50,14 - PUSHBUTTON "Àû¿ë(&A)", IDC_APPLY_BUTTON,112,122,50,14,WS_DISABLED - PUSHBUTTON "µµ¿ò¸»", IDHELP,166,122,50,14,WS_TABSTOP|WS_GROUP - CONTROL "Tab", IDC_TABCONTROL,"SysTabControl32",WS_CLIPSIBLINGS|WS_GROUP|WS_TABSTOP|TCS_MULTILINE,4,4,212,114 -END - - -IDD_WIZARD DIALOG DISCARDABLE 0, 0, 290, 159 -STYLE DS_MODALFRAME | WS_POPUP | WS_CAPTION | WS_SYSMENU | WS_VISIBLE -CAPTION "Wizard" -FONT 9, "MS Shell Dlg" -BEGIN - DEFPUSHBUTTON "Á¾·á", IDC_FINISH_BUTTON,121,138,50,14 - DEFPUSHBUTTON "´ÙÀ½(&N) >", IDC_NEXT_BUTTON,121,138,50,14 - PUSHBUTTON "< ÀÌÀü(&B)", IDC_BACK_BUTTON,71,138,50,14 - PUSHBUTTON "Ãë¼Ò", IDCANCEL,178,138,50,14 - PUSHBUTTON "µµ¿ò¸»", IDHELP,235,138,50,14,WS_GROUP - LTEXT "", IDC_SUNKEN_LINE,7,129,278,1,SS_SUNKEN - CONTROL "Tab", IDC_TABCONTROL,"SysTabControl32",WS_CLIPSIBLINGS | WS_DISABLED,7,7,258,5 - LTEXT "", IDC_SUNKEN_LINEHEADER,0,35,290,1,SS_LEFT | SS_SUNKEN | WS_CHILD | WS_VISIBLE -END - - -IDD_TBCUSTOMIZE DIALOG DISCARDABLE 10, 20, 357, 125 -STYLE DS_MODALFRAME | WS_POPUP | WS_VISIBLE | WS_CAPTION | WS_SYSMENU -CAPTION "Customize Toolbar" -FONT 9, "MS Shell Dlg" -BEGIN - DEFPUSHBUTTON "´Ý±â(&C)", IDCANCEL,308,6,44,14 - PUSHBUTTON "´Ù½Ã(&e)", IDC_RESET_BTN,308,23,44,14 - PUSHBUTTON "µµ¿ò¸»(&H)", IDC_HELP_BTN,308,40,44,14 - PUSHBUTTON "Move &Up", IDC_MOVEUP_BTN,308,74,44,14 - PUSHBUTTON "Move &Down", IDC_MOVEDN_BTN,308,91,44,14 - LTEXT "A&vailable buttons:", -1,4,5,84,10 - LISTBOX IDC_AVAILBTN_LBOX,4,17,120,100, LBS_NOTIFY | LBS_OWNERDRAWFIXED | LBS_HASSTRINGS | LBS_NOINTEGRALHEIGHT | LBS_DISABLENOSCROLL | WS_BORDER | WS_VSCROLL | WS_HSCROLL | WS_TABSTOP - PUSHBUTTON "&Add ->", IDOK, 131, 42, 44, 14 - PUSHBUTTON "<- &Remove", IDC_REMOVE_BTN,131,62,44,14 - LTEXT "&Toolbar buttons:", -1,182,5,78,10 - LISTBOX IDC_TOOLBARBTN_LBOX, 182,17,120,100,LBS_NOTIFY | LBS_OWNERDRAWFIXED | LBS_HASSTRINGS | LBS_NOINTEGRALHEIGHT | LBS_DISABLENOSCROLL | WS_BORDER | WS_VSCROLL | WS_HSCROLL | WS_TABSTOP -END - -STRINGTABLE DISCARDABLE -{ - IDS_CLOSE "´Ý±â" -} - -STRINGTABLE DISCARDABLE -{ - IDM_TODAY "¿À´Ã:" - IDM_GOTODAY "Go to today" -} - -STRINGTABLE DISCARDABLE -{ - IDS_SEPARATOR "Separator" -} diff --git a/reactos/lib/comctl32/comctl_Nl.rc b/reactos/lib/comctl32/comctl_Nl.rc deleted file mode 100644 index 0e04b788d02..00000000000 --- a/reactos/lib/comctl32/comctl_Nl.rc +++ /dev/null @@ -1,89 +0,0 @@ -/* - * comctl (Dutch resources) - * - * Copyright 2003 Hans Leidekker - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2.1 of the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -LANGUAGE LANG_DUTCH, SUBLANG_DEFAULT - -IDD_PROPSHEET DIALOG DISCARDABLE 0, 0, 220, 140 -STYLE DS_CONTEXTHELP | DS_MODALFRAME | WS_POPUP | WS_CAPTION | WS_SYSMENU | WS_VISIBLE -CAPTION "Eigenschappen van " -FONT 8, "MS Shell Dlg" -BEGIN - DEFPUSHBUTTON "OK", IDOK,4,122,50,14, WS_TABSTOP | WS_GROUP - PUSHBUTTON "Annuleren", IDCANCEL,58,122,50,14 - PUSHBUTTON "&Toepassen", IDC_APPLY_BUTTON,112,122,50,14,WS_DISABLED - PUSHBUTTON "Help", IDHELP,166,122,50,14,WS_TABSTOP|WS_GROUP - CONTROL "Tabblad", IDC_TABCONTROL,"SysTabControl32",WS_CLIPSIBLINGS|WS_GROUP|WS_TABSTOP|TCS_MULTILINE,4,4,212,114 -END - - -IDD_WIZARD DIALOG DISCARDABLE 0, 0, 290, 159 -STYLE DS_MODALFRAME | WS_POPUP | WS_CAPTION | WS_SYSMENU | WS_VISIBLE -CAPTION "Assistent" -FONT 8, "MS Shell Dlg" -BEGIN - DEFPUSHBUTTON "Beëindigen", IDC_FINISH_BUTTON,121,138,50,14 - DEFPUSHBUTTON "&Volgende >", IDC_NEXT_BUTTON,121,138,50,14 - PUSHBUTTON "< V&orige", IDC_BACK_BUTTON,71,138,50,14 - PUSHBUTTON "Annuleren", IDCANCEL,178,138,50,14 - PUSHBUTTON "Help", IDHELP,235,138,50,14,WS_GROUP - LTEXT "", IDC_SUNKEN_LINE,7,129,278,1,SS_SUNKEN - CONTROL "Tabblad", IDC_TABCONTROL,"SysTabControl32",WS_CLIPSIBLINGS | WS_DISABLED,7,7,258,5 - LTEXT "", IDC_SUNKEN_LINEHEADER,0,35,290,1,SS_LEFT | SS_SUNKEN | WS_CHILD | WS_VISIBLE -END - - -IDD_TBCUSTOMIZE DIALOG DISCARDABLE 10, 20, 357, 125 -STYLE DS_MODALFRAME | WS_POPUP | WS_VISIBLE | WS_CAPTION | WS_SYSMENU -CAPTION "Gereedschappenbalk aanpassen" -FONT 8, "MS Shell Dlg" -BEGIN - DEFPUSHBUTTON "&Afsluiten", IDCANCEL,308,6,44,14 - PUSHBUTTON "&Reset", IDC_RESET_BTN,308,23,44,14 - PUSHBUTTON "&Help", IDC_HELP_BTN,308,40,44,14 - PUSHBUTTON "Verplaats Om&hoog", IDC_MOVEUP_BTN,308,74,44,14 - PUSHBUTTON "Verplaats Om&laag", IDC_MOVEDN_BTN,308,91,44,14 - LTEXT "&Beschikbare knoppen:", -1,4,5,84,10 - LISTBOX IDC_AVAILBTN_LBOX,4,17,120,100, LBS_NOTIFY | LBS_OWNERDRAWFIXED | LBS_HASSTRINGS | LBS_NOINTEGRALHEIGHT | LBS_DISABLENOSCROLL | WS_BORDER | WS_VSCROLL | WS_HSCROLL | WS_TABSTOP - PUSHBUTTON "&Toevoegen ->", IDOK, 131, 42, 44, 14 - PUSHBUTTON "<- &Verwijderen", IDC_REMOVE_BTN,131,62,44,14 - LTEXT "&Knoppen:", -1,182,5,78,10 - LISTBOX IDC_TOOLBARBTN_LBOX, 182,17,120,100,LBS_NOTIFY | LBS_OWNERDRAWFIXED | LBS_HASSTRINGS | LBS_NOINTEGRALHEIGHT | LBS_DISABLENOSCROLL | WS_BORDER | WS_VSCROLL | WS_HSCROLL | WS_TABSTOP -END - -STRINGTABLE DISCARDABLE -{ - IDS_CLOSE "Sluiten" -} - -STRINGTABLE DISCARDABLE -{ - IDM_TODAY "Vandaag:" - IDM_GOTODAY "Ga vandaag naar" -} - -STRINGTABLE DISCARDABLE -{ - IDS_SEPARATOR "Scheidingsteken" -} - -STRINGTABLE DISCARDABLE -{ - HKY_NONE "Geen" -} diff --git a/reactos/lib/comctl32/comctl_Pl.rc b/reactos/lib/comctl32/comctl_Pl.rc deleted file mode 100644 index d404bacbff4..00000000000 --- a/reactos/lib/comctl32/comctl_Pl.rc +++ /dev/null @@ -1,83 +0,0 @@ -/* - * Copyright 1999 Eric Kohl - * Copyright 2002 Jacek Bator - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2.1 of the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -LANGUAGE LANG_POLISH, SUBLANG_DEFAULT - -IDD_PROPSHEET DIALOG DISCARDABLE 0, 0, 220, 140 -STYLE DS_CONTEXTHELP | DS_MODALFRAME | WS_POPUP | WS_CAPTION | WS_SYSMENU | WS_VISIBLE -CAPTION "W³aœciwoœci " -FONT 8, "MS Shell Dlg" -BEGIN - DEFPUSHBUTTON "OK", IDOK,4,122,50,14, WS_TABSTOP | WS_GROUP - PUSHBUTTON "Anuluj", IDCANCEL,58,122,50,14 - PUSHBUTTON "&Zastosuj", IDC_APPLY_BUTTON,112,122,50,14,WS_DISABLED - PUSHBUTTON "Pomoc", IDHELP,166,122,50,14,WS_TABSTOP|WS_GROUP - CONTROL "Tab", IDC_TABCONTROL,"SysTabControl32",WS_CLIPSIBLINGS|WS_GROUP|WS_TABSTOP|TCS_MULTILINE,4,4,212,114 -END - - -IDD_WIZARD DIALOG DISCARDABLE 0, 0, 290, 159 -STYLE DS_MODALFRAME | WS_POPUP | WS_CAPTION | WS_SYSMENU | WS_VISIBLE -CAPTION "Kreator" -FONT 8, "MS Shell Dlg" -BEGIN - DEFPUSHBUTTON "Zakoñcz", IDC_FINISH_BUTTON,121,138,50,14 - DEFPUSHBUTTON "&Dalej >", IDC_NEXT_BUTTON,121,138,50,14 - PUSHBUTTON "< &Wstecz", IDC_BACK_BUTTON,71,138,50,14 - PUSHBUTTON "Anuluj", IDCANCEL,178,138,50,14 - PUSHBUTTON "Pomoc", IDHELP,235,138,50,14,WS_GROUP - LTEXT "", IDC_SUNKEN_LINE,7,129,278,1,SS_SUNKEN - CONTROL "Tab", IDC_TABCONTROL,"SysTabControl32",WS_CLIPSIBLINGS | WS_DISABLED,7,7,258,5 - LTEXT "", IDC_SUNKEN_LINEHEADER,0,35,290,1,SS_LEFT | SS_SUNKEN | WS_CHILD | WS_VISIBLE -END - - -IDD_TBCUSTOMIZE DIALOG DISCARDABLE 10, 20, 357, 125 -STYLE DS_MODALFRAME | WS_POPUP | WS_VISIBLE | WS_CAPTION | WS_SYSMENU -CAPTION "Dostosowywanie paska narzêdzi" -FONT 8, "MS Shell Dlg" -BEGIN - DEFPUSHBUTTON "&Zamknij", IDCANCEL,308,6,44,14 - PUSHBUTTON "Z&resetuj", IDC_RESET_BTN,308,23,44,14 - PUSHBUTTON "&Pomoc", IDC_HELP_BTN,308,40,44,14 - PUSHBUTTON "Przenieœ &w górê", IDC_MOVEUP_BTN,308,74,44,14 - PUSHBUTTON "Przenieœ w &dó³", IDC_MOVEDN_BTN,308,91,44,14 - LTEXT "Do&stêpne przyciski:", -1,4,5,84,10 - LISTBOX IDC_AVAILBTN_LBOX,4,17,120,100, LBS_NOTIFY | LBS_OWNERDRAWFIXED | LBS_HASSTRINGS | LBS_NOINTEGRALHEIGHT | LBS_DISABLENOSCROLL | WS_BORDER | WS_VSCROLL | WS_HSCROLL | WS_TABSTOP - PUSHBUTTON "D&odaj ->", IDOK, 131, 42, 44, 14 - PUSHBUTTON "<- &Usuñ", IDC_REMOVE_BTN,131,62,44,14 - LTEXT "&Przyciski paska narzêdzi:", -1,182,5,78,10 - LISTBOX IDC_TOOLBARBTN_LBOX, 182,17,120,100,LBS_NOTIFY | LBS_OWNERDRAWFIXED | LBS_HASSTRINGS | LBS_NOINTEGRALHEIGHT | LBS_DISABLENOSCROLL | WS_BORDER | WS_VSCROLL | WS_HSCROLL | WS_TABSTOP -END - -STRINGTABLE DISCARDABLE -{ - IDS_CLOSE "Zamknij" -} - -STRINGTABLE DISCARDABLE -{ - IDM_TODAY "Dziœ:" - IDM_GOTODAY "IdŸ do dziœ" -} - -STRINGTABLE DISCARDABLE -{ - IDS_SEPARATOR "Odstêp" -} diff --git a/reactos/lib/comctl32/comctl_Pt.rc b/reactos/lib/comctl32/comctl_Pt.rc deleted file mode 100644 index 737c413b799..00000000000 --- a/reactos/lib/comctl32/comctl_Pt.rc +++ /dev/null @@ -1,87 +0,0 @@ -/* - * Copyright 2003 Marcelo Duarte - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2.1 of the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -LANGUAGE LANG_PORTUGUESE, SUBLANG_DEFAULT - -IDD_PROPSHEET DIALOG DISCARDABLE 0, 0, 220, 140 -STYLE DS_CONTEXTHELP | DS_MODALFRAME | WS_POPUP | WS_CAPTION | WS_SYSMENU | WS_VISIBLE -CAPTION "Propriedades para " -FONT 8, "MS Shell Dlg" -BEGIN - DEFPUSHBUTTON "OK", IDOK,4,122,50,14, WS_TABSTOP | WS_GROUP - PUSHBUTTON "Cancelar", IDCANCEL,58,122,50,14 - PUSHBUTTON "&Aplicar", IDC_APPLY_BUTTON,112,122,50,14,WS_DISABLED - PUSHBUTTON "Ajuda", IDHELP,166,122,50,14,WS_TABSTOP|WS_GROUP - CONTROL "Tab", IDC_TABCONTROL,"SysTabControl32",WS_CLIPSIBLINGS|WS_GROUP|WS_TABSTOP|TCS_MULTILINE,4,4,212,114 -END - - -IDD_WIZARD DIALOG DISCARDABLE 0, 0, 290, 159 -STYLE DS_MODALFRAME | WS_POPUP | WS_CAPTION | WS_SYSMENU | WS_VISIBLE -CAPTION "Assistente" -FONT 8, "MS Shell Dlg" -BEGIN - DEFPUSHBUTTON "Finalizar", IDC_FINISH_BUTTON,121,138,50,14 - DEFPUSHBUTTON "&Avançar >", IDC_NEXT_BUTTON,121,138,50,14 - PUSHBUTTON "< &Voltar", IDC_BACK_BUTTON,71,138,50,14 - PUSHBUTTON "Cancelar", IDCANCEL,178,138,50,14 - PUSHBUTTON "Ajuda", IDHELP,235,138,50,14,WS_GROUP - LTEXT "", IDC_SUNKEN_LINE,7,129,278,1,SS_SUNKEN - CONTROL "Tab", IDC_TABCONTROL,"SysTabControl32",WS_CLIPSIBLINGS | WS_DISABLED,7,7,258,5 - LTEXT "", IDC_SUNKEN_LINEHEADER,0,35,290,1,SS_LEFT | SS_SUNKEN | WS_CHILD | WS_VISIBLE -END - - -IDD_TBCUSTOMIZE DIALOG DISCARDABLE 10, 20, 357, 125 -STYLE DS_MODALFRAME | WS_POPUP | WS_VISIBLE | WS_CAPTION | WS_SYSMENU -CAPTION "Personalizar barra de ferramentas" -FONT 8, "MS Shell Dlg" -BEGIN - DEFPUSHBUTTON "&Fechar", IDCANCEL,308,6,44,14 - PUSHBUTTON "R&estaurar", IDC_RESET_BTN,308,23,44,14 - PUSHBUTTON "&Ajuda", IDC_HELP_BTN,308,40,44,14 - PUSHBUTTON "A&cima", IDC_MOVEUP_BTN,308,74,44,14 - PUSHBUTTON "A&baixo", IDC_MOVEDN_BTN,308,91,44,14 - LTEXT "Botões &disponíveis:", -1,4,5,84,10 - LISTBOX IDC_AVAILBTN_LBOX,4,17,120,100, LBS_NOTIFY | LBS_OWNERDRAWFIXED | LBS_HASSTRINGS | LBS_NOINTEGRALHEIGHT | LBS_DISABLENOSCROLL | WS_BORDER | WS_VSCROLL | WS_HSCROLL | WS_TABSTOP - PUSHBUTTON "&Adicionar ->", IDOK, 131, 42, 44, 14 - PUSHBUTTON "<- &Remover", IDC_REMOVE_BTN,131,62,44,14 - LTEXT "&Botões da barra de ferramentas:", -1,182,5,78,10 - LISTBOX IDC_TOOLBARBTN_LBOX, 182,17,120,100,LBS_NOTIFY | LBS_OWNERDRAWFIXED | LBS_HASSTRINGS | LBS_NOINTEGRALHEIGHT | LBS_DISABLENOSCROLL | WS_BORDER | WS_VSCROLL | WS_HSCROLL | WS_TABSTOP -END - -STRINGTABLE DISCARDABLE -{ - IDS_CLOSE "Fechar" -} - -STRINGTABLE DISCARDABLE -{ - IDM_TODAY "Hoje:" - IDM_GOTODAY "Ir para hoje" -} - -STRINGTABLE DISCARDABLE -{ - IDS_SEPARATOR "Separador" -} - -STRINGTABLE DISCARDABLE -{ - HKY_NONE "Nenhum" -} diff --git a/reactos/lib/comctl32/comctl_Ru.rc b/reactos/lib/comctl32/comctl_Ru.rc deleted file mode 100644 index 2fee57e53f0..00000000000 --- a/reactos/lib/comctl32/comctl_Ru.rc +++ /dev/null @@ -1,89 +0,0 @@ -/* - * comctl (Russian resources) - * - * Copyright 2003 Igor Stepin - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2.1 of the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -LANGUAGE LANG_RUSSIAN, SUBLANG_DEFAULT - -IDD_PROPSHEET DIALOG DISCARDABLE 0, 0, 220, 140 -STYLE DS_CONTEXTHELP | DS_MODALFRAME | WS_POPUP | WS_CAPTION | WS_SYSMENU | WS_VISIBLE -CAPTION "Ñâîéñòâà äëÿ " -FONT 8, "MS Shell Dlg" -BEGIN - DEFPUSHBUTTON "OK", IDOK,4,122,50,14, WS_TABSTOP | WS_GROUP - PUSHBUTTON "Îòìåíà", IDCANCEL,58,122,50,14 - PUSHBUTTON "Ïðè&ìåíèòü", IDC_APPLY_BUTTON,112,122,50,14,WS_DISABLED - PUSHBUTTON "&Ñïðàâêà", IDHELP,166,122,50,14,WS_TABSTOP|WS_GROUP - CONTROL "Tab", IDC_TABCONTROL,"SysTabControl32",WS_CLIPSIBLINGS|WS_GROUP|WS_TABSTOP|TCS_MULTILINE,4,4,212,114 -END - - -IDD_WIZARD DIALOG DISCARDABLE 0, 0, 290, 159 -STYLE DS_MODALFRAME | WS_POPUP | WS_CAPTION | WS_SYSMENU | WS_VISIBLE -CAPTION "Ìàñòåð" -FONT 8, "MS Shell Dlg" -BEGIN - DEFPUSHBUTTON "Çàâåðøèòü", IDC_FINISH_BUTTON,121,138,50,14 - DEFPUSHBUTTON "&Äàëåå >", IDC_NEXT_BUTTON,121,138,50,14 - PUSHBUTTON "< &Íàçàä", IDC_BACK_BUTTON,71,138,50,14 - PUSHBUTTON "Îòìåíà", IDCANCEL,178,138,50,14 - PUSHBUTTON "&Ñïðàâêà", IDHELP,235,138,50,14,WS_GROUP - LTEXT "", IDC_SUNKEN_LINE,7,129,278,1,SS_SUNKEN - CONTROL "Tab", IDC_TABCONTROL,"SysTabControl32",WS_CLIPSIBLINGS | WS_DISABLED,7,7,258,5 - LTEXT "", IDC_SUNKEN_LINEHEADER,0,35,290,1,SS_LEFT | SS_SUNKEN | WS_CHILD | WS_VISIBLE -END - - -IDD_TBCUSTOMIZE DIALOG DISCARDABLE 10, 20, 357, 125 -STYLE DS_MODALFRAME | WS_POPUP | WS_VISIBLE | WS_CAPTION | WS_SYSMENU -CAPTION "Íàñòðîéêà ïàíåëè èíñòðóìåíòîâ" -FONT 8, "MS Shell Dlg" -BEGIN - DEFPUSHBUTTON "&Çàêðûòü", IDCANCEL,308,6,44,14 - PUSHBUTTON "Ñ&áðîñèòü", IDC_RESET_BTN,308,23,44,14 - PUSHBUTTON "&Ñïðàâêà", IDC_HELP_BTN,308,40,44,14 - PUSHBUTTON "Ïåðåìåñòèòü &ââåðõ", IDC_MOVEUP_BTN,308,74,44,14 - PUSHBUTTON "Ïåðåìåñòèòü &âíèç", IDC_MOVEDN_BTN,308,91,44,14 - LTEXT "&Äîñòóïíûå êíîïêè:", -1,4,5,84,10 - LISTBOX IDC_AVAILBTN_LBOX,4,17,120,100, LBS_NOTIFY | LBS_OWNERDRAWFIXED | LBS_HASSTRINGS | LBS_NOINTEGRALHEIGHT | LBS_DISABLENOSCROLL | WS_BORDER | WS_VSCROLL | WS_HSCROLL | WS_TABSTOP - PUSHBUTTON "&Äîáàâèòü ->", IDOK, 131, 42, 44, 14 - PUSHBUTTON "<- &Óäàëèòü", IDC_REMOVE_BTN,131,62,44,14 - LTEXT "&Êíîïêè ïàíåëè èíñòðóìåíòîâ:", -1,182,5,78,10 - LISTBOX IDC_TOOLBARBTN_LBOX, 182,17,120,100,LBS_NOTIFY | LBS_OWNERDRAWFIXED | LBS_HASSTRINGS | LBS_NOINTEGRALHEIGHT | LBS_DISABLENOSCROLL | WS_BORDER | WS_VSCROLL | WS_HSCROLL | WS_TABSTOP -END - -STRINGTABLE DISCARDABLE -{ - IDS_CLOSE "Çàêðûòü" -} - -STRINGTABLE DISCARDABLE -{ - IDM_TODAY "Ñåãîäíÿ:" - IDM_GOTODAY "Òåêóùàÿ äàòà" -} - -STRINGTABLE DISCARDABLE -{ - IDS_SEPARATOR "Ðàçäåëèòåëü" -} - -STRINGTABLE DISCARDABLE -{ - HKY_NONE "Íåò" -} diff --git a/reactos/lib/comctl32/comctl_Si.rc b/reactos/lib/comctl32/comctl_Si.rc deleted file mode 100644 index 2b016840276..00000000000 --- a/reactos/lib/comctl32/comctl_Si.rc +++ /dev/null @@ -1,82 +0,0 @@ -/* - * Copyright 2002-2003 Rok Mandeljc - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2.1 of the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -LANGUAGE LANG_SLOVENIAN, SUBLANG_DEFAULT - -IDD_PROPSHEET DIALOG DISCARDABLE 0, 0, 220, 140 -STYLE DS_CONTEXTHELP | DS_MODALFRAME | WS_POPUP | WS_CAPTION | WS_SYSMENU | WS_VISIBLE -CAPTION "Lastnosti" -FONT 8, "MS Shell Dlg" -BEGIN - DEFPUSHBUTTON "V redu", IDOK,4,122,50,14, WS_TABSTOP | WS_GROUP - PUSHBUTTON "Preklièi", IDCANCEL,58,122,50,14 - PUSHBUTTON "&Uporabi", IDC_APPLY_BUTTON,112,122,50,14,WS_DISABLED - PUSHBUTTON "Pomoè", IDHELP,166,122,50,14,WS_TABSTOP|WS_GROUP - CONTROL "Tab", IDC_TABCONTROL,"SysTabControl32",WS_CLIPSIBLINGS|WS_GROUP|WS_TABSTOP|TCS_MULTILINE,4,4,212,114 -END - - -IDD_WIZARD DIALOG DISCARDABLE 0, 0, 290, 159 -STYLE DS_MODALFRAME | WS_POPUP | WS_CAPTION | WS_SYSMENU | WS_VISIBLE -CAPTION "Èarovnik" -FONT 8, "MS Shell Dlg" -BEGIN - DEFPUSHBUTTON "Dokonèaj", IDC_FINISH_BUTTON,121,138,50,14 - DEFPUSHBUTTON "Naprej >", IDC_NEXT_BUTTON,121,138,50,14 - PUSHBUTTON "< Na&zaj", IDC_BACK_BUTTON,71,138,50,14 - PUSHBUTTON "Preklièi", IDCANCEL,178,138,50,14 - PUSHBUTTON "Pomoè", IDHELP,235,138,50,14,WS_GROUP - LTEXT "", IDC_SUNKEN_LINE,7,129,278,1,SS_SUNKEN - CONTROL "Tab", IDC_TABCONTROL,"SysTabControl32",WS_CLIPSIBLINGS | WS_DISABLED,7,7,258,5 - LTEXT "", IDC_SUNKEN_LINEHEADER,0,35,290,1,SS_LEFT | SS_SUNKEN | WS_CHILD | WS_VISIBLE -END - - -IDD_TBCUSTOMIZE DIALOG DISCARDABLE 10, 20, 357, 125 -STYLE DS_MODALFRAME | WS_POPUP | WS_VISIBLE | WS_CAPTION | WS_SYSMENU -CAPTION "Prilagoditev orodne vrstice" -FONT 8, "MS Shell Dlg" -BEGIN - DEFPUSHBUTTON "&Zapri", IDCANCEL,308,6,44,14 - PUSHBUTTON "Po&nastavi", IDC_RESET_BTN,308,23,44,14 - PUSHBUTTON "&Pomoè", IDC_HELP_BTN,308,40,44,14 - PUSHBUTTON "N&avzgor", IDC_MOVEUP_BTN,308,74,44,14 - PUSHBUTTON "Na&vzdol", IDC_MOVEDN_BTN,308,91,44,14 - LTEXT "&Gumbi na voljo:", -1,4,5,84,10 - LISTBOX IDC_AVAILBTN_LBOX,4,17,120,100, LBS_NOTIFY | LBS_OWNERDRAWFIXED | LBS_HASSTRINGS | LBS_NOINTEGRALHEIGHT | LBS_DISABLENOSCROLL | WS_BORDER | WS_VSCROLL | WS_HSCROLL | WS_TABSTOP - PUSHBUTTON "&Dodaj ->", IDOK, 131, 42, 44, 14 - PUSHBUTTON "<- &Odstrani", IDC_REMOVE_BTN,131,62,44,14 - LTEXT "G&umbi orodne vrstice:", -1,182,5,78,10 - LISTBOX IDC_TOOLBARBTN_LBOX, 182,17,120,100,LBS_NOTIFY | LBS_OWNERDRAWFIXED | LBS_HASSTRINGS | LBS_NOINTEGRALHEIGHT | LBS_DISABLENOSCROLL | WS_BORDER | WS_VSCROLL | WS_HSCROLL | WS_TABSTOP -END - -STRINGTABLE DISCARDABLE -{ - IDS_CLOSE "Zapri" -} - -STRINGTABLE DISCARDABLE -{ - IDM_TODAY "Danes:" - IDM_GOTODAY "&Poglejte danes" -} - -STRINGTABLE DISCARDABLE -{ - IDS_SEPARATOR "Loèilo" -} diff --git a/reactos/lib/comctl32/comctl_Th.rc b/reactos/lib/comctl32/comctl_Th.rc deleted file mode 100644 index 2fd50ca8778..00000000000 --- a/reactos/lib/comctl32/comctl_Th.rc +++ /dev/null @@ -1,87 +0,0 @@ -/* - * Copyright 2003 Jon Griffiths - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2.1 of the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -LANGUAGE LANG_THAI, SUBLANG_DEFAULT - -IDD_PROPSHEET DIALOG DISCARDABLE 0, 0, 220, 140 -STYLE DS_CONTEXTHELP | DS_MODALFRAME | WS_POPUP | WS_CAPTION | WS_SYSMENU | WS_VISIBLE -CAPTION "¤Ø³ÊÁºÑµÔ¢Í§ " -FONT 8, "MS Shell Dlg" -BEGIN - DEFPUSHBUTTON "µ¡Å§", IDOK,4,122,50,14, WS_TABSTOP | WS_GROUP - PUSHBUTTON "¡àÅÔ¡", IDCANCEL,58,122,50,14 - PUSHBUTTON "Áռŷѹ·Õ", IDC_APPLY_BUTTON,112,122,50,14,WS_DISABLED - PUSHBUTTON "ªèÇÂàËÅÕÍ", IDHELP,166,122,50,14,WS_TABSTOP|WS_GROUP - CONTROL "Tab", IDC_TABCONTROL,"SysTabControl32",WS_CLIPSIBLINGS|WS_GROUP|WS_TABSTOP|TCS_MULTILINE,4,4,212,114 -END - - -IDD_WIZARD DIALOG DISCARDABLE 0, 0, 290, 159 -STYLE DS_MODALFRAME | WS_POPUP | WS_CAPTION | WS_SYSMENU | WS_VISIBLE -CAPTION "Wizard" -FONT 8, "MS Shell Dlg" -BEGIN - DEFPUSHBUTTON "·íÒãËéàÊÃç¨", IDC_FINISH_BUTTON,121,138,50,14 - DEFPUSHBUTTON "µèÍä» >", IDC_NEXT_BUTTON,121,138,50,14 - PUSHBUTTON "< Âé͹¡ÅѺ", IDC_BACK_BUTTON,71,138,50,14 - PUSHBUTTON "¡àÅÔ¡", IDCANCEL,178,138,50,14 - PUSHBUTTON "ªèÇÂàËÅÕÍ", IDHELP,235,138,50,14,WS_GROUP - LTEXT "", IDC_SUNKEN_LINE,7,129,278,1,SS_SUNKEN - CONTROL "Tab", IDC_TABCONTROL,"SysTabControl32",WS_CLIPSIBLINGS | WS_DISABLED,7,7,258,5 - LTEXT "", IDC_SUNKEN_LINEHEADER,0,35,290,1,SS_LEFT | SS_SUNKEN | WS_CHILD | WS_VISIBLE -END - - -IDD_TBCUSTOMIZE DIALOG DISCARDABLE 10, 20, 357, 125 -STYLE DS_MODALFRAME | WS_POPUP | WS_VISIBLE | WS_CAPTION | WS_SYSMENU -CAPTION "»ÃѺáµè§á¶ºà¤Ã×èͧÁ×Í" -FONT 8, "MS Shell Dlg" -BEGIN - DEFPUSHBUTTON "»Ô´", IDCANCEL,308,6,44,14 - PUSHBUTTON "á¡éÍÍ¡", IDC_RESET_BTN,308,23,44,14 - PUSHBUTTON "ªèÇÂàËÅÕÍ", IDC_HELP_BTN,308,40,44,14 - PUSHBUTTON "ÂéÒ¢Öé¹", IDC_MOVEUP_BTN,308,74,44,14 - PUSHBUTTON "ÂéÒÂŧ", IDC_MOVEDN_BTN,308,91,44,14 - LTEXT "·ÕàÅ×Í¡ä´é:", -1,4,5,84,10 - LISTBOX IDC_AVAILBTN_LBOX,4,17,120,100, LBS_NOTIFY | LBS_OWNERDRAWFIXED | LBS_HASSTRINGS | LBS_NOINTEGRALHEIGHT | LBS_DISABLENOSCROLL | WS_BORDER | WS_VSCROLL | WS_HSCROLL | WS_TABSTOP - PUSHBUTTON "ºÇ¡ ->", IDOK, 131, 42, 44, 14 - PUSHBUTTON "<- ¶Í´ÍÍ¡", IDC_REMOVE_BTN,131,62,44,14 - LTEXT "¡ÒáÃзíÒᶺà¤Ã×èͧÁ×Í:", -1,182,5,78,10 - LISTBOX IDC_TOOLBARBTN_LBOX, 182,17,120,100,LBS_NOTIFY | LBS_OWNERDRAWFIXED | LBS_HASSTRINGS | LBS_NOINTEGRALHEIGHT | LBS_DISABLENOSCROLL | WS_BORDER | WS_VSCROLL | WS_HSCROLL | WS_TABSTOP -END - -STRINGTABLE DISCARDABLE -{ - IDS_CLOSE "»Õ´" -} - -STRINGTABLE DISCARDABLE -{ - IDM_TODAY "Çѹ¹Õé:" - IDM_GOTODAY "ä»¶Ö§Çѹ¹Õé" -} - -STRINGTABLE DISCARDABLE -{ - IDS_SEPARATOR "Separator" -} - -STRINGTABLE DISCARDABLE -{ - HKY_NONE "äÁèÁÕàÅÂ" -} diff --git a/reactos/lib/comctl32/comctl_Uk.rc b/reactos/lib/comctl32/comctl_Uk.rc deleted file mode 100644 index d1f5326f11b..00000000000 --- a/reactos/lib/comctl32/comctl_Uk.rc +++ /dev/null @@ -1,89 +0,0 @@ -/* - * comctl (Ukrainian resources) - * - * Copyright 2004 Ilya Korniyko - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2.1 of the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -LANGUAGE LANG_UKRAINIAN, SUBLANG_DEFAULT - -IDD_PROPSHEET DIALOG DISCARDABLE 0, 0, 220, 140 -STYLE DS_CONTEXTHELP | DS_MODALFRAME | WS_POPUP | WS_CAPTION | WS_SYSMENU | WS_VISIBLE -CAPTION "Âëàñòèâîñò³ äëÿ " -FONT 8, "MS Shell Dlg" -BEGIN - DEFPUSHBUTTON "OK", IDOK,4,122,50,14, WS_TABSTOP | WS_GROUP - PUSHBUTTON "&³äì³íà", IDCANCEL,58,122,50,14 - PUSHBUTTON "&Çàñòîñóâàòè", IDC_APPLY_BUTTON,112,122,50,14,WS_DISABLED - PUSHBUTTON "&Äîâ³äêà", IDHELP,166,122,50,14,WS_TABSTOP|WS_GROUP - CONTROL "Tab", IDC_TABCONTROL,"SysTabControl32",WS_CLIPSIBLINGS|WS_GROUP|WS_TABSTOP|TCS_MULTILINE,4,4,212,114 -END - - -IDD_WIZARD DIALOG DISCARDABLE 0, 0, 290, 159 -STYLE DS_MODALFRAME | WS_POPUP | WS_CAPTION | WS_SYSMENU | WS_VISIBLE -CAPTION "Ìàñòåð" -FONT 8, "MS Shell Dlg" -BEGIN - DEFPUSHBUTTON "&Çàâåðøèòè", IDC_FINISH_BUTTON,121,138,50,14 - DEFPUSHBUTTON "&Äàë³ >", IDC_NEXT_BUTTON,121,138,50,14 - PUSHBUTTON "< &Íàçàä", IDC_BACK_BUTTON,71,138,50,14 - PUSHBUTTON "&³äì³íà", IDCANCEL,178,138,50,14 - PUSHBUTTON "&Äîâ³äêà", IDHELP,235,138,50,14,WS_GROUP - LTEXT "", IDC_SUNKEN_LINE,7,129,278,1,SS_SUNKEN - CONTROL "Tab", IDC_TABCONTROL,"SysTabControl32",WS_CLIPSIBLINGS | WS_DISABLED,7,7,258,5 - LTEXT "", IDC_SUNKEN_LINEHEADER,0,35,290,1,SS_LEFT | SS_SUNKEN | WS_CHILD | WS_VISIBLE -END - - -IDD_TBCUSTOMIZE DIALOG DISCARDABLE 10, 20, 357, 125 -STYLE DS_MODALFRAME | WS_POPUP | WS_VISIBLE | WS_CAPTION | WS_SYSMENU -CAPTION "Íàñòðîéêà ïàíåë³ ³íñòðóìåíò³â" -FONT 8, "MS Shell Dlg" -BEGIN - DEFPUSHBUTTON "&Çàêðèòè", IDCANCEL,308,6,44,14 - PUSHBUTTON "&Ñêèíóòè", IDC_RESET_BTN,308,23,44,14 - PUSHBUTTON "&Äîâ³äêà", IDC_HELP_BTN,308,40,44,14 - PUSHBUTTON "Ïåðåñóíóòè â&ãîðó", IDC_MOVEUP_BTN,308,74,44,14 - PUSHBUTTON "Ïåðåñóíóòè äî&íèçó", IDC_MOVEDN_BTN,308,91,44,14 - LTEXT "Íà&ÿâí³ êíîïêè:", -1,4,5,84,10 - LISTBOX IDC_AVAILBTN_LBOX,4,17,120,100, LBS_NOTIFY | LBS_OWNERDRAWFIXED | LBS_HASSTRINGS | LBS_NOINTEGRALHEIGHT | LBS_DISABLENOSCROLL | WS_BORDER | WS_VSCROLL | WS_HSCROLL | WS_TABSTOP - PUSHBUTTON "&Äîäàòè ->", IDOK, 131, 42, 44, 14 - PUSHBUTTON "<- &Ïðèáðàòè", IDC_REMOVE_BTN,131,62,44,14 - LTEXT "&Êíîïêè ïàíåë³ ³íñòðóìåíò³â:", -1,182,5,78,10 - LISTBOX IDC_TOOLBARBTN_LBOX, 182,17,120,100,LBS_NOTIFY | LBS_OWNERDRAWFIXED | LBS_HASSTRINGS | LBS_NOINTEGRALHEIGHT | LBS_DISABLENOSCROLL | WS_BORDER | WS_VSCROLL | WS_HSCROLL | WS_TABSTOP -END - -STRINGTABLE DISCARDABLE -{ - IDS_CLOSE "Çàêðèòè" -} - -STRINGTABLE DISCARDABLE -{ - IDM_TODAY "Ñüîãîäí³:" - IDM_GOTODAY "Ïîòî÷íà äàòà" -} - -STRINGTABLE DISCARDABLE -{ - IDS_SEPARATOR "Ðîçä³ëüíèê" -} - -STRINGTABLE DISCARDABLE -{ - HKY_NONE "Íåìà" -} diff --git a/reactos/lib/comctl32/commctrl.c b/reactos/lib/comctl32/commctrl.c deleted file mode 100644 index ab0723de641..00000000000 --- a/reactos/lib/comctl32/commctrl.c +++ /dev/null @@ -1,1551 +0,0 @@ -/* - * Common controls functions - * - * Copyright 1997 Dimitrie O. Paun - * Copyright 1998,2000 Eric Kohl - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2.1 of the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - * - * NOTES - * - * This code was audited for completeness against the documented features - * of Comctl32.dll version 6.0 on Oct. 21, 2002, by Christian Neumair. - * - * 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 - * -- implement GetMUILanguage + InitMUILanguage - * -- LibMain => DLLMain ("DLLMain takes over the functionality of both the - * LibMain and the WEP function.", MSDN) - * -- finish NOTES for MenuHelp, GetEffectiveClientRect and GetStatusTextW - * -- FIXMEs + BUGS (search for them) - * - * Control Classes - * -- ICC_ANIMATE_CLASS - * -- ICC_BAR_CLASSES - * -- ICC_COOL_CLASSES - * -- ICC_DATE_CLASSES - * -- ICC_HOTKEY_CLASS - * -- ICC_INTERNET_CLASSES - * -- ICC_LINK_CLASS - * -- ICC_LISTVIEW_CLASSES - * -- ICC_NATIVEFNTCTL_CLASS - * -- ICC_PAGESCROLLER_CLASS - * -- ICC_PROGRESS_CLASS - * -- ICC_STANDARD_CLASSES (not yet implemented) - * -- ICC_TAB_CLASSES - * -- ICC_TREEVIEW_CLASSES - * -- ICC_UPDOWN_CLASS - * -- ICC_USEREX_CLASSES - * -- ICC_WIN95_CLASSES - */ - -#include -#include -#include - -#include "windef.h" -#include "winbase.h" -#include "wingdi.h" -#include "winuser.h" -#include "winnls.h" -#include "commctrl.h" -#include "winerror.h" -#include "winreg.h" -#define NO_SHLWAPI_STREAM -#include "shlwapi.h" -#include "comctl32.h" -#include "wine/debug.h" - -WINE_DEFAULT_DEBUG_CHANNEL(commctrl); - -extern void ANIMATE_Register(void); -extern void ANIMATE_Unregister(void); -extern void COMBOEX_Register(void); -extern void COMBOEX_Unregister(void); -extern void DATETIME_Register(void); -extern void DATETIME_Unregister(void); -extern void FLATSB_Register(void); -extern void FLATSB_Unregister(void); -extern void HEADER_Register(void); -extern void HEADER_Unregister(void); -extern void HOTKEY_Register(void); -extern void HOTKEY_Unregister(void); -extern void IPADDRESS_Register(void); -extern void IPADDRESS_Unregister(void); -extern void LISTVIEW_Register(void); -extern void LISTVIEW_Unregister(void); -extern void MONTHCAL_Register(void); -extern void MONTHCAL_Unregister(void); -extern void NATIVEFONT_Register(void); -extern void NATIVEFONT_Unregister(void); -extern void PAGER_Register(void); -extern void PAGER_Unregister(void); -extern void PROGRESS_Register(void); -extern void PROGRESS_Unregister(void); -extern void REBAR_Register(void); -extern void REBAR_Unregister(void); -extern void STATUS_Register(void); -extern void STATUS_Unregister(void); -extern void SYSLINK_Register(void); -extern void SYSLINK_Unregister(void); -extern void TAB_Register(void); -extern void TAB_Unregister(void); -extern void TOOLBAR_Register(void); -extern void TOOLBAR_Unregister(void); -extern void TOOLTIPS_Register(void); -extern void TOOLTIPS_Unregister(void); -extern void TRACKBAR_Register(void); -extern void TRACKBAR_Unregister(void); -extern void TREEVIEW_Register(void); -extern void TREEVIEW_Unregister(void); -extern void UPDOWN_Register(void); -extern void UPDOWN_Unregister(void); - -LRESULT WINAPI COMCTL32_SubclassProc (HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam); - -LPSTR COMCTL32_aSubclass = NULL; -HMODULE COMCTL32_hModule = 0; -LANGID COMCTL32_uiLang = MAKELANGID(LANG_NEUTRAL, SUBLANG_NEUTRAL); -HBRUSH COMCTL32_hPattern55AABrush = NULL; -COMCTL32_SysColor comctl32_color; - -static HBITMAP COMCTL32_hPattern55AABitmap = NULL; - -static const WORD wPattern55AA[] = -{ - 0x5555, 0xaaaa, 0x5555, 0xaaaa, - 0x5555, 0xaaaa, 0x5555, 0xaaaa -}; - - -/*********************************************************************** - * DllMain [Internal] - * - * Initializes the internal 'COMCTL32.DLL'. - * - * PARAMS - * hinstDLL [I] handle to the 'dlls' instance - * fdwReason [I] - * lpvReserved [I] reserverd, must be NULL - * - * RETURNS - * Success: TRUE - * Failure: FALSE - */ - -BOOL WINAPI DllMain(HINSTANCE hinstDLL, DWORD fdwReason, LPVOID lpvReserved) -{ - TRACE("%p,%lx,%p\n", hinstDLL, fdwReason, lpvReserved); - - switch (fdwReason) { - case DLL_PROCESS_ATTACH: - DisableThreadLibraryCalls(hinstDLL); - - COMCTL32_hModule = (HMODULE)hinstDLL; - - /* add global subclassing atom (used by 'tooltip' and 'updown') */ - COMCTL32_aSubclass = (LPSTR)(DWORD)GlobalAddAtomA ("CC32SubclassInfo"); - TRACE("Subclassing atom added: %p\n", COMCTL32_aSubclass); - - /* create local pattern brush */ - COMCTL32_hPattern55AABitmap = CreateBitmap (8, 8, 1, 1, wPattern55AA); - COMCTL32_hPattern55AABrush = CreatePatternBrush (COMCTL32_hPattern55AABitmap); - - /* Get all the colors at DLL load */ - COMCTL32_RefreshSysColors(); - - /* register all Win95 common control classes */ - ANIMATE_Register (); - FLATSB_Register (); - HEADER_Register (); - HOTKEY_Register (); - LISTVIEW_Register (); - PROGRESS_Register (); - STATUS_Register (); - SYSLINK_Register (); - TAB_Register (); - TOOLBAR_Register (); - TOOLTIPS_Register (); - TRACKBAR_Register (); - TREEVIEW_Register (); - UPDOWN_Register (); - break; - - case DLL_PROCESS_DETACH: - /* unregister all common control classes */ - ANIMATE_Unregister (); - COMBOEX_Unregister (); - DATETIME_Unregister (); - FLATSB_Unregister (); - HEADER_Unregister (); - HOTKEY_Unregister (); - IPADDRESS_Unregister (); - LISTVIEW_Unregister (); - MONTHCAL_Unregister (); - NATIVEFONT_Unregister (); - PAGER_Unregister (); - PROGRESS_Unregister (); - REBAR_Unregister (); - STATUS_Unregister (); - SYSLINK_Unregister (); - TAB_Unregister (); - TOOLBAR_Unregister (); - TOOLTIPS_Unregister (); - TRACKBAR_Unregister (); - TREEVIEW_Unregister (); - UPDOWN_Unregister (); - - /* delete local pattern brush */ - DeleteObject (COMCTL32_hPattern55AABrush); - COMCTL32_hPattern55AABrush = NULL; - DeleteObject (COMCTL32_hPattern55AABitmap); - COMCTL32_hPattern55AABitmap = NULL; - - /* delete global subclassing atom */ - GlobalDeleteAtom (LOWORD(COMCTL32_aSubclass)); - TRACE("Subclassing atom deleted: %p\n", COMCTL32_aSubclass); - COMCTL32_aSubclass = NULL; - break; - } - - return TRUE; -} - - -/*********************************************************************** - * MenuHelp [COMCTL32.2] - * - * Handles the setting of status bar help messages when the user - * selects menu items. - * - * PARAMS - * uMsg [I] message (WM_MENUSELECT) (see NOTES) - * wParam [I] wParam of the message uMsg - * lParam [I] lParam of the message uMsg - * hMainMenu [I] handle to the application's main menu - * hInst [I] handle to the module that contains string resources - * hwndStatus [I] handle to the status bar window - * lpwIDs [I] pointer to an array of integers (see NOTES) - * - * RETURNS - * No return value - * - * NOTES - * The official documentation is incomplete! - * This is the correct documentation: - * - * uMsg: - * MenuHelp() does NOT handle WM_COMMAND messages! It only handles - * WM_MENUSELECT messages. - * - * lpwIDs: - * (will be written ...) - */ - -VOID WINAPI -MenuHelp (UINT uMsg, WPARAM wParam, LPARAM lParam, HMENU hMainMenu, - HINSTANCE hInst, HWND hwndStatus, UINT* lpwIDs) -{ - UINT uMenuID = 0; - - if (!IsWindow (hwndStatus)) - return; - - switch (uMsg) { - case WM_MENUSELECT: - TRACE("WM_MENUSELECT wParam=0x%X lParam=0x%lX\n", - wParam, lParam); - - if ((HIWORD(wParam) == 0xFFFF) && (lParam == 0)) { - /* menu was closed */ - TRACE("menu was closed!\n"); - SendMessageA (hwndStatus, SB_SIMPLE, FALSE, 0); - } - else { - /* menu item was selected */ - if (HIWORD(wParam) & MF_POPUP) - uMenuID = (UINT)*(lpwIDs+1); - else - uMenuID = (UINT)LOWORD(wParam); - TRACE("uMenuID = %u\n", uMenuID); - - if (uMenuID) { - CHAR szText[256]; - - if (!LoadStringA (hInst, uMenuID, szText, 256)) - szText[0] = '\0'; - - SendMessageA (hwndStatus, SB_SETTEXTA, - 255 | SBT_NOBORDERS, (LPARAM)szText); - SendMessageA (hwndStatus, SB_SIMPLE, TRUE, 0); - } - } - break; - - case WM_COMMAND : - TRACE("WM_COMMAND wParam=0x%X lParam=0x%lX\n", - wParam, lParam); - /* WM_COMMAND is not invalid since it is documented - * in the windows api reference. So don't output - * any FIXME for WM_COMMAND - */ - WARN("We don't care about the WM_COMMAND\n"); - break; - - default: - FIXME("Invalid Message 0x%x!\n", uMsg); - break; - } -} - - -/*********************************************************************** - * ShowHideMenuCtl [COMCTL32.3] - * - * Shows or hides controls and updates the corresponding menu item. - * - * PARAMS - * hwnd [I] handle to the client window. - * uFlags [I] menu command id. - * lpInfo [I] pointer to an array of integers. (See NOTES.) - * - * RETURNS - * Success: TRUE - * Failure: FALSE - * - * NOTES - * The official documentation is incomplete! - * This is the correct documentation: - * - * hwnd - * Handle to the window that contains the menu and controls. - * - * uFlags - * Identifier of the menu item to receive or loose a check mark. - * - * lpInfo - * The array of integers contains pairs of values. BOTH values of - * the first pair must be the handles to the application's main menu. - * Each subsequent pair consists of a menu id and control id. - */ - -BOOL WINAPI -ShowHideMenuCtl (HWND hwnd, UINT uFlags, LPINT lpInfo) -{ - LPINT lpMenuId; - - TRACE("%p, %x, %p\n", hwnd, uFlags, lpInfo); - - if (lpInfo == NULL) - return FALSE; - - if (!(lpInfo[0]) || !(lpInfo[1])) - return FALSE; - - /* search for control */ - lpMenuId = &lpInfo[2]; - while (*lpMenuId != uFlags) - lpMenuId += 2; - - if (GetMenuState ((HMENU)lpInfo[1], uFlags, MF_BYCOMMAND) & MFS_CHECKED) { - /* uncheck menu item */ - CheckMenuItem ((HMENU)lpInfo[0], *lpMenuId, MF_BYCOMMAND | MF_UNCHECKED); - - /* hide control */ - lpMenuId++; - SetWindowPos (GetDlgItem (hwnd, *lpMenuId), 0, 0, 0, 0, 0, - SWP_HIDEWINDOW); - } - else { - /* check menu item */ - CheckMenuItem ((HMENU)lpInfo[0], *lpMenuId, MF_BYCOMMAND | MF_CHECKED); - - /* show control */ - lpMenuId++; - SetWindowPos (GetDlgItem (hwnd, *lpMenuId), 0, 0, 0, 0, 0, - SWP_SHOWWINDOW); - } - - return TRUE; -} - - -/*********************************************************************** - * GetEffectiveClientRect [COMCTL32.4] - * - * Calculates the coordinates of a rectangle in the client area. - * - * PARAMS - * hwnd [I] handle to the client window. - * lpRect [O] pointer to the rectangle of the client window - * lpInfo [I] pointer to an array of integers (see NOTES) - * - * RETURNS - * No return value. - * - * NOTES - * The official documentation is incomplete! - * This is the correct documentation: - * - * lpInfo - * (will be written ...) - */ - -VOID WINAPI -GetEffectiveClientRect (HWND hwnd, LPRECT lpRect, LPINT lpInfo) -{ - RECT rcCtrl; - INT *lpRun; - HWND hwndCtrl; - - TRACE("(0x%08lx 0x%08lx 0x%08lx)\n", - (DWORD)hwnd, (DWORD)lpRect, (DWORD)lpInfo); - - GetClientRect (hwnd, lpRect); - lpRun = lpInfo; - - do { - lpRun += 2; - if (*lpRun == 0) - return; - lpRun++; - hwndCtrl = GetDlgItem (hwnd, *lpRun); - if (GetWindowLongA (hwndCtrl, GWL_STYLE) & WS_VISIBLE) { - TRACE("control id 0x%x\n", *lpRun); - GetWindowRect (hwndCtrl, &rcCtrl); - MapWindowPoints (NULL, hwnd, (LPPOINT)&rcCtrl, 2); - SubtractRect (lpRect, lpRect, &rcCtrl); - } - lpRun++; - } while (*lpRun); -} - - -/*********************************************************************** - * DrawStatusTextW [COMCTL32.@] - * - * Draws text with borders, like in a status bar. - * - * PARAMS - * hdc [I] handle to the window's display context - * lprc [I] pointer to a rectangle - * text [I] pointer to the text - * style [I] drawing style - * - * RETURNS - * No return value. - * - * NOTES - * The style variable can have one of the following values: - * (will be written ...) - */ - -void WINAPI DrawStatusTextW (HDC hdc, LPRECT lprc, LPCWSTR text, UINT style) -{ - RECT r = *lprc; - UINT border = BDR_SUNKENOUTER; - - if (style & SBT_POPOUT) - border = BDR_RAISEDOUTER; - else if (style & SBT_NOBORDERS) - border = 0; - - DrawEdge (hdc, &r, border, BF_RECT|BF_ADJUST); - - /* now draw text */ - if (text) { - int oldbkmode = SetBkMode (hdc, TRANSPARENT); - UINT align = DT_LEFT; - if (*text == L'\t') { - text++; - align = DT_CENTER; - if (*text == L'\t') { - text++; - align = DT_RIGHT; - } - } - r.left += 3; - if (style & SBT_RTLREADING) - FIXME("Unsupported RTL style!\n"); - DrawTextW (hdc, text, -1, &r, align|DT_VCENTER|DT_SINGLELINE|DT_NOPREFIX); - SetBkMode(hdc, oldbkmode); - } -} - - -/*********************************************************************** - * DrawStatusText [COMCTL32.@] - * DrawStatusTextA [COMCTL32.5] - * - * Draws text with borders, like in a status bar. - * - * PARAMS - * hdc [I] handle to the window's display context - * lprc [I] pointer to a rectangle - * text [I] pointer to the text - * style [I] drawing style - * - * RETURNS - * No return value. - */ - -void WINAPI DrawStatusTextA (HDC hdc, LPRECT lprc, LPCSTR text, UINT style) -{ - INT len; - LPWSTR textW = NULL; - - if ( text ) { - if ( (len = MultiByteToWideChar( CP_ACP, 0, text, -1, NULL, 0 )) ) { - if ( (textW = HeapAlloc( GetProcessHeap(), 0, len * sizeof(WCHAR) )) ) - MultiByteToWideChar( CP_ACP, 0, text, -1, textW, len ); - } - } - DrawStatusTextW( hdc, lprc, textW, style ); - HeapFree( GetProcessHeap(), 0, textW ); -} - - -/*********************************************************************** - * CreateStatusWindow [COMCTL32.@] - * CreateStatusWindowA [COMCTL32.6] - * - * Creates a status bar - * - * PARAMS - * style [I] window style - * text [I] pointer to the window text - * parent [I] handle to the parent window - * wid [I] control id of the status bar - * - * RETURNS - * Success: handle to the status window - * Failure: 0 - */ - -HWND WINAPI -CreateStatusWindowA (LONG style, LPCSTR text, HWND parent, UINT wid) -{ - return CreateWindowA(STATUSCLASSNAMEA, text, style, - CW_USEDEFAULT, CW_USEDEFAULT, - CW_USEDEFAULT, CW_USEDEFAULT, - parent, (HMENU)wid, 0, 0); -} - - -/*********************************************************************** - * CreateStatusWindowW [COMCTL32.@] - * - * Creates a status bar control - * - * PARAMS - * style [I] window style - * text [I] pointer to the window text - * parent [I] handle to the parent window - * wid [I] control id of the status bar - * - * RETURNS - * Success: handle to the status window - * Failure: 0 - */ - -HWND WINAPI -CreateStatusWindowW (LONG style, LPCWSTR text, HWND parent, UINT wid) -{ - return CreateWindowW(STATUSCLASSNAMEW, text, style, - CW_USEDEFAULT, CW_USEDEFAULT, - CW_USEDEFAULT, CW_USEDEFAULT, - parent, (HMENU)wid, 0, 0); -} - - -/*********************************************************************** - * CreateUpDownControl [COMCTL32.16] - * - * Creates an up-down control - * - * PARAMS - * style [I] window styles - * x [I] horizontal position of the control - * y [I] vertical position of the control - * cx [I] with of the control - * cy [I] height of the control - * parent [I] handle to the parent window - * id [I] the control's identifier - * inst [I] handle to the application's module instance - * buddy [I] handle to the buddy window, can be NULL - * maxVal [I] upper limit of the control - * minVal [I] lower limit of the control - * curVal [I] current value of the control - * - * RETURNS - * Success: handle to the updown control - * Failure: 0 - */ - -HWND WINAPI -CreateUpDownControl (DWORD style, INT x, INT y, INT cx, INT cy, - HWND parent, INT id, HINSTANCE inst, - HWND buddy, INT maxVal, INT minVal, INT curVal) -{ - HWND hUD = - CreateWindowA (UPDOWN_CLASSA, 0, style, x, y, cx, cy, - parent, (HMENU)id, inst, 0); - if (hUD) { - SendMessageA (hUD, UDM_SETBUDDY, (WPARAM)buddy, 0); - SendMessageA (hUD, UDM_SETRANGE, 0, MAKELONG(maxVal, minVal)); - SendMessageA (hUD, UDM_SETPOS, 0, MAKELONG(curVal, 0)); - } - - return hUD; -} - - -/*********************************************************************** - * InitCommonControls [COMCTL32.17] - * - * Registers the common controls. - * - * PARAMS - * No parameters. - * - * RETURNS - * No return values. - * - * NOTES - * This function is just a dummy. - * The Win95 controls are registered at the DLL's initialization. - * To register other controls InitCommonControlsEx() must be used. - */ - -VOID WINAPI -InitCommonControls (void) -{ -} - - -/*********************************************************************** - * InitCommonControlsEx [COMCTL32.@] - * - * Registers the common controls. - * - * PARAMS - * lpInitCtrls [I] pointer to an INITCOMMONCONTROLS structure. - * - * RETURNS - * Success: TRUE - * Failure: FALSE - * - * NOTES - * Only the additional common controls are registered by this function. - * The Win95 controls are registered at the DLL's initialization. - * - * FIXME - * implement the following control classes: - * ICC_LINK_CLASS - * ICC_STANDARD_CLASSES - */ - -BOOL WINAPI -InitCommonControlsEx (LPINITCOMMONCONTROLSEX lpInitCtrls) -{ - INT cCount; - DWORD dwMask; - - if (!lpInitCtrls) - return FALSE; - if (lpInitCtrls->dwSize != sizeof(INITCOMMONCONTROLSEX)) - return FALSE; - - TRACE("(0x%08lx)\n", lpInitCtrls->dwICC); - - for (cCount = 0; cCount < 32; cCount++) { - dwMask = 1 << cCount; - if (!(lpInitCtrls->dwICC & dwMask)) - continue; - - switch (lpInitCtrls->dwICC & dwMask) { - /* dummy initialization */ - case ICC_ANIMATE_CLASS: - case ICC_BAR_CLASSES: - case ICC_LISTVIEW_CLASSES: - case ICC_TREEVIEW_CLASSES: - case ICC_TAB_CLASSES: - case ICC_UPDOWN_CLASS: - case ICC_PROGRESS_CLASS: - case ICC_HOTKEY_CLASS: - break; - - /* advanced classes - not included in Win95 */ - case ICC_DATE_CLASSES: - MONTHCAL_Register (); - DATETIME_Register (); - break; - - case ICC_USEREX_CLASSES: - COMBOEX_Register (); - break; - - case ICC_COOL_CLASSES: - REBAR_Register (); - break; - - case ICC_INTERNET_CLASSES: - IPADDRESS_Register (); - break; - - case ICC_PAGESCROLLER_CLASS: - PAGER_Register (); - break; - - case ICC_NATIVEFNTCTL_CLASS: - NATIVEFONT_Register (); - break; - - case ICC_LINK_CLASS: - SYSLINK_Register (); - break; - - default: - FIXME("Unknown class! dwICC=0x%lX\n", dwMask); - break; - } - } - - return TRUE; -} - - -/*********************************************************************** - * CreateToolbarEx [COMCTL32.@] - * - * Creates a toolbar window. - * - * PARAMS - * hwnd - * style - * wID - * nBitmaps - * hBMInst - * wBMID - * lpButtons - * iNumButtons - * dxButton - * dyButton - * dxBitmap - * dyBitmap - * uStructSize - * - * RETURNS - * Success: handle to the tool bar control - * Failure: 0 - */ - -HWND WINAPI -CreateToolbarEx (HWND hwnd, DWORD style, UINT wID, INT nBitmaps, - HINSTANCE hBMInst, UINT wBMID, LPCTBBUTTON lpButtons, - INT iNumButtons, INT dxButton, INT dyButton, - INT dxBitmap, INT dyBitmap, UINT uStructSize) -{ - HWND hwndTB; - - hwndTB = - CreateWindowExA(0, TOOLBARCLASSNAMEA, NULL, style|WS_CHILD, 0,0,100,30, - hwnd, (HMENU)wID, COMCTL32_hModule, NULL); - if(hwndTB) { - TBADDBITMAP tbab; - - SendMessageA (hwndTB, TB_BUTTONSTRUCTSIZE, - (WPARAM)uStructSize, 0); - - /* set bitmap and button size */ - /*If CreateToolbarEx receives 0, windows sets default values*/ - if (dxBitmap <= 0) - dxBitmap = 16; - if (dyBitmap <= 0) - dyBitmap = 15; - SendMessageA (hwndTB, TB_SETBITMAPSIZE, 0, - MAKELPARAM((WORD)dxBitmap, (WORD)dyBitmap)); - - if (dxButton <= 0) - dxButton = 24; - if (dyButton <= 0) - dyButton = 22; - SendMessageA (hwndTB, TB_SETBUTTONSIZE, 0, - MAKELPARAM((WORD)dxButton, (WORD)dyButton)); - - - /* add bitmaps */ - if (nBitmaps > 0) - { - tbab.hInst = hBMInst; - tbab.nID = wBMID; - - SendMessageA (hwndTB, TB_ADDBITMAP, - (WPARAM)nBitmaps, (LPARAM)&tbab); - } - /* add buttons */ - if(iNumButtons > 0) - SendMessageA (hwndTB, TB_ADDBUTTONSA, - (WPARAM)iNumButtons, (LPARAM)lpButtons); - } - - return hwndTB; -} - - -/*********************************************************************** - * CreateMappedBitmap [COMCTL32.8] - * - * Loads a bitmap resource using a colour map. - * - * PARAMS - * hInstance [I] Handle to the module containing the bitmap. - * idBitmap [I] The bitmap resource ID. - * wFlags [I] CMB_MASKED for using bitmap as a mask or 0 for normal. - * lpColorMap [I] Colour information needed for the bitmap or NULL (uses system colours). - * iNumMaps [I] Number of COLORMAP's pointed to by lpColorMap. - * - * RETURNS - * Success: handle to the new bitmap - * Failure: 0 - */ - -HBITMAP WINAPI -CreateMappedBitmap (HINSTANCE hInstance, INT idBitmap, UINT wFlags, - LPCOLORMAP lpColorMap, INT iNumMaps) -{ - HGLOBAL hglb; - HRSRC hRsrc; - LPBITMAPINFOHEADER lpBitmap, lpBitmapInfo; - UINT nSize, nColorTableSize, iColor; - RGBQUAD *pColorTable; - INT i, iMaps, nWidth, nHeight; - HDC hdcScreen; - HBITMAP hbm; - LPCOLORMAP sysColorMap; - COLORREF cRef; - COLORMAP internalColorMap[4] = - {{0x000000, 0}, {0x808080, 0}, {0xC0C0C0, 0}, {0xFFFFFF, 0}}; - - /* initialize pointer to colortable and default color table */ - if (lpColorMap) { - iMaps = iNumMaps; - sysColorMap = lpColorMap; - } - else { - internalColorMap[0].to = GetSysColor (COLOR_BTNTEXT); - internalColorMap[1].to = GetSysColor (COLOR_BTNSHADOW); - internalColorMap[2].to = GetSysColor (COLOR_BTNFACE); - internalColorMap[3].to = GetSysColor (COLOR_BTNHIGHLIGHT); - iMaps = 4; - sysColorMap = (LPCOLORMAP)internalColorMap; - } - - hRsrc = FindResourceA (hInstance, (LPSTR)idBitmap, (LPSTR)RT_BITMAP); - if (hRsrc == 0) - return 0; - hglb = LoadResource (hInstance, hRsrc); - if (hglb == 0) - return 0; - lpBitmap = (LPBITMAPINFOHEADER)LockResource (hglb); - if (lpBitmap == NULL) - return 0; - - if (lpBitmap->biSize >= sizeof(BITMAPINFOHEADER) && lpBitmap->biClrUsed) - nColorTableSize = lpBitmap->biClrUsed; - else if (lpBitmap->biBitCount <= 8) - nColorTableSize = (1 << lpBitmap->biBitCount); - else - nColorTableSize = 0; - nSize = lpBitmap->biSize + nColorTableSize * sizeof(RGBQUAD); - lpBitmapInfo = (LPBITMAPINFOHEADER)GlobalAlloc (GMEM_FIXED, nSize); - if (lpBitmapInfo == NULL) - return 0; - RtlMoveMemory (lpBitmapInfo, lpBitmap, nSize); - - pColorTable = (RGBQUAD*)(((LPBYTE)lpBitmapInfo)+(UINT)lpBitmapInfo->biSize); - - for (iColor = 0; iColor < nColorTableSize; iColor++) { - for (i = 0; i < iMaps; i++) { - cRef = RGB(pColorTable[iColor].rgbRed, - pColorTable[iColor].rgbGreen, - pColorTable[iColor].rgbBlue); - if ( cRef == sysColorMap[i].from) { -#if 0 - if (wFlags & CBS_MASKED) { - if (sysColorMap[i].to != COLOR_BTNTEXT) - pColorTable[iColor] = RGB(255, 255, 255); - } - else -#endif - pColorTable[iColor].rgbBlue = GetBValue(sysColorMap[i].to); - pColorTable[iColor].rgbGreen = GetGValue(sysColorMap[i].to); - pColorTable[iColor].rgbRed = GetRValue(sysColorMap[i].to); - break; - } - } - } - nWidth = (INT)lpBitmapInfo->biWidth; - nHeight = (INT)lpBitmapInfo->biHeight; - hdcScreen = GetDC (NULL); - hbm = CreateCompatibleBitmap (hdcScreen, nWidth, nHeight); - if (hbm) { - HDC hdcDst = CreateCompatibleDC (hdcScreen); - HBITMAP hbmOld = SelectObject (hdcDst, hbm); - LPBYTE lpBits = (LPBYTE)(lpBitmap + 1); - lpBits += nColorTableSize * sizeof(RGBQUAD); - StretchDIBits (hdcDst, 0, 0, nWidth, nHeight, 0, 0, nWidth, nHeight, - lpBits, (LPBITMAPINFO)lpBitmapInfo, DIB_RGB_COLORS, - SRCCOPY); - SelectObject (hdcDst, hbmOld); - DeleteDC (hdcDst); - } - ReleaseDC (NULL, hdcScreen); - GlobalFree ((HGLOBAL)lpBitmapInfo); - FreeResource (hglb); - - return hbm; -} - - -/*********************************************************************** - * CreateToolbar [COMCTL32.7] - * - * Creates a toolbar control. - * - * PARAMS - * hwnd - * style - * wID - * nBitmaps - * hBMInst - * wBMID - * lpButtons - * iNumButtons - * - * RETURNS - * Success: handle to the tool bar control - * Failure: 0 - * - * NOTES - * Do not use this functions anymore. Use CreateToolbarEx instead. - */ - -HWND WINAPI -CreateToolbar (HWND hwnd, DWORD style, UINT wID, INT nBitmaps, - HINSTANCE hBMInst, UINT wBMID, - LPCTBBUTTON lpButtons,INT iNumButtons) -{ - return CreateToolbarEx (hwnd, style | CCS_NODIVIDER, wID, nBitmaps, - hBMInst, wBMID, lpButtons, - iNumButtons, 0, 0, 0, 0, CCSIZEOF_STRUCT(TBBUTTON, dwData)); -} - - -/*********************************************************************** - * DllGetVersion [COMCTL32.@] - * - * Retrieves version information of the 'COMCTL32.DLL' - * - * PARAMS - * pdvi [O] pointer to version information structure. - * - * RETURNS - * Success: S_OK - * Failure: E_INVALIDARG - * - * NOTES - * Returns version of a comctl32.dll from IE4.01 SP1. - */ - -HRESULT WINAPI -COMCTL32_DllGetVersion (DLLVERSIONINFO *pdvi) -{ - if (pdvi->cbSize != sizeof(DLLVERSIONINFO)) { - WARN("wrong DLLVERSIONINFO size from app\n"); - return E_INVALIDARG; - } - - pdvi->dwMajorVersion = COMCTL32_VERSION; - pdvi->dwMinorVersion = COMCTL32_VERSION_MINOR; - pdvi->dwBuildNumber = 2919; - pdvi->dwPlatformID = 6304; - - TRACE("%lu.%lu.%lu.%lu\n", - pdvi->dwMajorVersion, pdvi->dwMinorVersion, - pdvi->dwBuildNumber, pdvi->dwPlatformID); - - return S_OK; -} - -/*********************************************************************** - * DllInstall (COMCTL32.@) - * - * Installs the ComCtl32 DLL. - * - * RETURNS - * Success: S_OK - * Failure: A HRESULT error - */ -HRESULT WINAPI COMCTL32_DllInstall(BOOL bInstall, LPCWSTR cmdline) -{ - FIXME("(%s, %s): stub\n", bInstall?"TRUE":"FALSE", - debugstr_w(cmdline)); - - return S_OK; -} - -/*********************************************************************** - * _TrackMouseEvent [COMCTL32.@] - * - * Requests notification of mouse events - * - * During mouse tracking WM_MOUSEHOVER or WM_MOUSELEAVE events are posted - * to the hwnd specified in the ptme structure. After the event message - * is posted to the hwnd, the entry in the queue is removed. - * - * If the current hwnd isn't ptme->hwndTrack the TME_HOVER flag is completely - * ignored. The TME_LEAVE flag results in a WM_MOUSELEAVE message being posted - * immediately and the TME_LEAVE flag being ignored. - * - * PARAMS - * ptme [I,O] pointer to TRACKMOUSEEVENT information structure. - * - * RETURNS - * Success: non-zero - * Failure: zero - * - * IMPLEMENTATION moved to USER32.TrackMouseEvent - * - */ - -BOOL WINAPI -_TrackMouseEvent (TRACKMOUSEEVENT *ptme) -{ - return TrackMouseEvent (ptme); -} - -/************************************************************************* - * GetMUILanguage [COMCTL32.@] - * - * Returns the user interface language in use by the current process. - * - * RETURNS - * Language ID in use by the current process. - */ -LANGID WINAPI GetMUILanguage (VOID) -{ - return COMCTL32_uiLang; -} - - -/************************************************************************* - * InitMUILanguage [COMCTL32.@] - * - * Sets the user interface language to be used by the current process. - * - * RETURNS - * Nothing. - */ -VOID WINAPI InitMUILanguage (LANGID uiLang) -{ - COMCTL32_uiLang = uiLang; -} - - -/*********************************************************************** - * SetWindowSubclass [COMCTL32.410] - * - * Starts a window subclass - * - * PARAMS - * hWnd [in] handle to window subclass. - * pfnSubclass [in] Pointer to new window procedure. - * uIDSubclass [in] Unique identifier of sublass together with pfnSubclass. - * dwRef [in] Reference data to pass to window procedure. - * - * RETURNS - * Success: non-zero - * Failure: zero - * - * BUGS - * If an application manually subclasses a window after subclassing it with - * this API and then with this API again, then none of the previous - * subclasses get called or the origional window procedure. - */ - -BOOL WINAPI SetWindowSubclass (HWND hWnd, SUBCLASSPROC pfnSubclass, - UINT_PTR uIDSubclass, DWORD_PTR dwRef) -{ - LPSUBCLASS_INFO stack; - LPSUBCLASSPROCS proc; - - TRACE ("(%p, %p, %x, %lx)\n", hWnd, pfnSubclass, uIDSubclass, dwRef); - - /* Since the window procedure that we set here has two additional arguments, - * we can't simply set it as the new window procedure of the window. So we - * set our own window procedure and then calculate the other two arguments - * from there. */ - - /* See if we have been called for this window */ - stack = (LPSUBCLASS_INFO)GetPropA (hWnd, COMCTL32_aSubclass); - if (!stack) { - /* allocate stack */ - stack = (LPSUBCLASS_INFO)HeapAlloc (GetProcessHeap(), HEAP_ZERO_MEMORY, - sizeof(SUBCLASS_INFO)); - if (!stack) { - ERR ("Failed to allocate our Subclassing stack\n"); - return FALSE; - } - SetPropA (hWnd, COMCTL32_aSubclass, (HANDLE)stack); - - /* set window procedure to our own and save the current one */ - if (IsWindowUnicode (hWnd)) - stack->origproc = (WNDPROC)SetWindowLongPtrW (hWnd, GWLP_WNDPROC, - (DWORD_PTR)COMCTL32_SubclassProc); - else - stack->origproc = (WNDPROC)SetWindowLongPtrA (hWnd, GWLP_WNDPROC, - (DWORD_PTR)COMCTL32_SubclassProc); - } - else { - /* Check to see if we have called this function with the same uIDSubClass - * and pfnSubclass */ - proc = stack->SubclassProcs; - while (proc) { - if ((proc->id == uIDSubclass) && - (proc->subproc == pfnSubclass)) { - proc->ref = dwRef; - return TRUE; - } - proc = proc->next; - } - } - - proc = HeapAlloc(GetProcessHeap(), 0, sizeof(SUBCLASSPROCS)); - if (!proc) { - ERR ("Failed to allocate subclass entry in stack\n"); - if (IsWindowUnicode (hWnd)) - SetWindowLongPtrW (hWnd, GWLP_WNDPROC, (DWORD_PTR)stack->origproc); - else - SetWindowLongPtrA (hWnd, GWLP_WNDPROC, (DWORD_PTR)stack->origproc); - HeapFree (GetProcessHeap (), 0, stack); - RemovePropA( hWnd, COMCTL32_aSubclass ); - return FALSE; - } - - proc->subproc = pfnSubclass; - proc->ref = dwRef; - proc->id = uIDSubclass; - proc->next = stack->SubclassProcs; - stack->SubclassProcs = proc; - - return TRUE; -} - - -/*********************************************************************** - * GetWindowSubclass [COMCTL32.411] - * - * Gets the Reference data from a subclass. - * - * PARAMS - * hWnd [in] Handle to window which were subclassing - * pfnSubclass [in] Pointer to the subclass procedure - * uID [in] Unique indentifier of the subclassing procedure - * pdwRef [out] Pointer to the reference data - * - * RETURNS - * Success: Non-zero - * Failure: 0 - */ - -BOOL WINAPI GetWindowSubclass (HWND hWnd, SUBCLASSPROC pfnSubclass, - UINT_PTR uID, DWORD_PTR *pdwRef) -{ - LPSUBCLASS_INFO stack; - LPSUBCLASSPROCS proc; - - TRACE ("(%p, %p, %x, %p)\n", hWnd, pfnSubclass, uID, pdwRef); - - /* See if we have been called for this window */ - stack = (LPSUBCLASS_INFO)GetPropA (hWnd, COMCTL32_aSubclass); - if (!stack) - return FALSE; - - proc = stack->SubclassProcs; - while (proc) { - if ((proc->id == uID) && - (proc->subproc == pfnSubclass)) { - *pdwRef = proc->ref; - return TRUE; - } - proc = proc->next; - } - - return FALSE; -} - - -/*********************************************************************** - * RemoveWindowSubclass [COMCTL32.412] - * - * Removes a window subclass. - * - * PARAMS - * hWnd [in] Handle to the window were subclassing - * pfnSubclass [in] Pointer to the subclass procedure - * uID [in] Unique identifier of this subclass - * - * RETURNS - * Success: non-zero - * Failure: zero - */ - -BOOL WINAPI RemoveWindowSubclass(HWND hWnd, SUBCLASSPROC pfnSubclass, UINT_PTR uID) -{ - LPSUBCLASS_INFO stack; - LPSUBCLASSPROCS prevproc = NULL; - LPSUBCLASSPROCS proc; - BOOL ret = FALSE; - - TRACE ("(%p, %p, %x)\n", hWnd, pfnSubclass, uID); - - /* Find the Subclass to remove */ - stack = (LPSUBCLASS_INFO)GetPropA (hWnd, COMCTL32_aSubclass); - if (!stack) - return FALSE; - - proc = stack->SubclassProcs; - while (proc) { - if ((proc->id == uID) && - (proc->subproc == pfnSubclass)) { - - if (!prevproc) - stack->SubclassProcs = proc->next; - else - prevproc->next = proc->next; - - if (stack->stackpos == proc) - stack->stackpos = stack->stackpos->next; - - HeapFree (GetProcessHeap (), 0, proc); - ret = TRUE; - break; - } - prevproc = proc; - proc = proc->next; - } - - if (!stack->SubclassProcs && !stack->running) { - TRACE("Last Subclass removed, cleaning up\n"); - /* clean up our heap and reset the origional window procedure */ - if (IsWindowUnicode (hWnd)) - SetWindowLongPtrW (hWnd, GWLP_WNDPROC, (DWORD_PTR)stack->origproc); - else - SetWindowLongPtrA (hWnd, GWLP_WNDPROC, (DWORD_PTR)stack->origproc); - HeapFree (GetProcessHeap (), 0, stack); - RemovePropA( hWnd, COMCTL32_aSubclass ); - } - - return ret; -} - -/*********************************************************************** - * COMCTL32_SubclassProc (internal) - * - * Window procedure for all subclassed windows. - * Saves the current subclassing stack position to support nested messages - */ -LRESULT WINAPI COMCTL32_SubclassProc (HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam) -{ - LPSUBCLASS_INFO stack; - LPSUBCLASSPROCS proc; - LRESULT ret; - - TRACE ("(%p, 0x%08x, 0x%08x, 0x%08lx)\n", hWnd, uMsg, wParam, lParam); - - stack = (LPSUBCLASS_INFO)GetPropA (hWnd, COMCTL32_aSubclass); - if (!stack) { - ERR ("Our sub classing stack got erased for %p!! Nothing we can do\n", hWnd); - return 0; - } - - /* Save our old stackpos to properly handle nested messages */ - proc = stack->stackpos; - stack->stackpos = stack->SubclassProcs; - stack->running++; - ret = DefSubclassProc(hWnd, uMsg, wParam, lParam); - stack->running--; - stack->stackpos = proc; - - if (!stack->SubclassProcs && !stack->running) { - TRACE("Last Subclass removed, cleaning up\n"); - /* clean up our heap and reset the origional window procedure */ - if (IsWindowUnicode (hWnd)) - SetWindowLongPtrW (hWnd, GWLP_WNDPROC, (DWORD_PTR)stack->origproc); - else - SetWindowLongPtrA (hWnd, GWLP_WNDPROC, (DWORD_PTR)stack->origproc); - HeapFree (GetProcessHeap (), 0, stack); - RemovePropA( hWnd, COMCTL32_aSubclass ); - } - return ret; -} - -/*********************************************************************** - * DefSubclassProc [COMCTL32.413] - * - * Calls the next window procedure (ie. the one before this subclass) - * - * PARAMS - * hWnd [in] The window that we're subclassing - * uMsg [in] Message - * wParam [in] WPARAM - * lParam [in] LPARAM - * - * RETURNS - * Success: non-zero - * Failure: zero - */ - -LRESULT WINAPI DefSubclassProc (HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam) -{ - LPSUBCLASS_INFO stack; - LRESULT ret; - - TRACE ("(%p, 0x%08x, 0x%08x, 0x%08lx)\n", hWnd, uMsg, wParam, lParam); - - /* retrieve our little stack from the Properties */ - stack = (LPSUBCLASS_INFO)GetPropA (hWnd, COMCTL32_aSubclass); - if (!stack) { - ERR ("Our sub classing stack got erased for %p!! Nothing we can do\n", hWnd); - return 0; - } - - /* If we are at the end of stack then we have to call the original - * window procedure */ - if (!stack->stackpos) { - if (IsWindowUnicode (hWnd)) - ret = CallWindowProcW (stack->origproc, hWnd, uMsg, wParam, lParam); - else - ret = CallWindowProcA (stack->origproc, hWnd, uMsg, wParam, lParam); - } else { - LPSUBCLASSPROCS proc = stack->stackpos; - stack->stackpos = stack->stackpos->next; - /* call the Subclass procedure from the stack */ - ret = proc->subproc (hWnd, uMsg, wParam, lParam, - proc->id, proc->ref); - } - - return ret; -} - - -/*********************************************************************** - * COMCTL32_CreateToolTip [NOT AN API] - * - * Creates a tooltip for the control specified in hwnd and does all - * necessary setup and notifications. - * - * PARAMS - * hwndOwner [I] Handle to the window that will own the tool tip. - * - * RETURNS - * Success: Handle of tool tip window. - * Failure: NULL - */ - -HWND -COMCTL32_CreateToolTip(HWND hwndOwner) -{ - HWND hwndToolTip; - - hwndToolTip = CreateWindowExA(0, TOOLTIPS_CLASSA, NULL, 0, - CW_USEDEFAULT, CW_USEDEFAULT, - CW_USEDEFAULT, CW_USEDEFAULT, hwndOwner, - 0, 0, 0); - - /* Send NM_TOOLTIPSCREATED notification */ - if (hwndToolTip) - { - NMTOOLTIPSCREATED nmttc; - /* true owner can be different if hwndOwner is a child window */ - HWND hwndTrueOwner = GetWindow(hwndToolTip, GW_OWNER); - nmttc.hdr.hwndFrom = hwndTrueOwner; - nmttc.hdr.idFrom = GetWindowLongPtrW(hwndTrueOwner, GWLP_ID); - nmttc.hdr.code = NM_TOOLTIPSCREATED; - nmttc.hwndToolTips = hwndToolTip; - - SendMessageA(GetParent(hwndTrueOwner), WM_NOTIFY, - (WPARAM)GetWindowLongPtrW(hwndTrueOwner, GWLP_ID), - (LPARAM)&nmttc); - } - - return hwndToolTip; -} - - -/*********************************************************************** - * COMCTL32_RefreshSysColors [NOT AN API] - * - * Invoked on any control recognizing a WM_SYSCOLORCHANGE message to - * refresh the color values in the color structure - * - * PARAMS - * none - * - * RETURNS - * none - */ - -VOID -COMCTL32_RefreshSysColors(void) -{ - comctl32_color.clrBtnHighlight = GetSysColor (COLOR_BTNHIGHLIGHT); - comctl32_color.clrBtnShadow = GetSysColor (COLOR_BTNSHADOW); - comctl32_color.clrBtnText = GetSysColor (COLOR_BTNTEXT); - comctl32_color.clrBtnFace = GetSysColor (COLOR_BTNFACE); - comctl32_color.clrHighlight = GetSysColor (COLOR_HIGHLIGHT); - comctl32_color.clrHighlightText = GetSysColor (COLOR_HIGHLIGHTTEXT); - comctl32_color.clr3dHilight = GetSysColor (COLOR_3DHILIGHT); - comctl32_color.clr3dShadow = GetSysColor (COLOR_3DSHADOW); - comctl32_color.clr3dDkShadow = GetSysColor (COLOR_3DDKSHADOW); - comctl32_color.clr3dFace = GetSysColor (COLOR_3DFACE); - comctl32_color.clrWindow = GetSysColor (COLOR_WINDOW); - comctl32_color.clrWindowText = GetSysColor (COLOR_WINDOWTEXT); - comctl32_color.clrGrayText = GetSysColor (COLOR_GRAYTEXT); - comctl32_color.clrActiveCaption = GetSysColor (COLOR_ACTIVECAPTION); - comctl32_color.clrInfoBk = GetSysColor (COLOR_INFOBK); - comctl32_color.clrInfoText = GetSysColor (COLOR_INFOTEXT); -} - -/*********************************************************************** - * COMCTL32_DrawInsertMark [NOT AN API] - * - * Draws an insertion mark (which looks similar to an 'I'). - * - * PARAMS - * hDC [I] Device context to draw onto. - * lpRect [I] Co-ordinates of insertion mark. - * clrInsertMark [I] Colour of the insertion mark. - * bHorizontal [I] True if insert mark should be drawn horizontally, - * vertical otherwise. - * - * RETURNS - * none - * - * NOTES - * Draws up to but not including the bottom co-ordinate when drawing - * vertically or the right co-ordinate when horizontal. - */ -void COMCTL32_DrawInsertMark(HDC hDC, const RECT *lpRect, COLORREF clrInsertMark, BOOL bHorizontal) -{ - HPEN hPen = CreatePen(PS_SOLID, 1, clrInsertMark); - HPEN hOldPen; - static const DWORD adwPolyPoints[] = {4,4,4}; - LONG lCentre = (bHorizontal ? - lpRect->top + (lpRect->bottom - lpRect->top)/2 : - lpRect->left + (lpRect->right - lpRect->left)/2); - LONG l1 = (bHorizontal ? lpRect->left : lpRect->top); - LONG l2 = (bHorizontal ? lpRect->right : lpRect->bottom); - const POINT aptInsertMark[] = - { - /* top (V) or left (H) arrow */ - {lCentre , l1 + 2}, - {lCentre - 2, l1 }, - {lCentre + 3, l1 }, - {lCentre + 1, l1 + 2}, - /* middle line */ - {lCentre , l2 - 2}, - {lCentre , l1 - 1}, - {lCentre + 1, l1 - 1}, - {lCentre + 1, l2 - 2}, - /* bottom (V) or right (H) arrow */ - {lCentre , l2 - 3}, - {lCentre - 2, l2 - 1}, - {lCentre + 3, l2 - 1}, - {lCentre + 1, l2 - 3}, - }; - hOldPen = SelectObject(hDC, hPen); - PolyPolyline(hDC, aptInsertMark, adwPolyPoints, sizeof(adwPolyPoints)/sizeof(adwPolyPoints[0])); - SelectObject(hDC, hOldPen); - DeleteObject(hPen); -} - -/*********************************************************************** - * MirrorIcon [COMCTL32.414] - * - * Mirrors an icon so that it will appear correctly on a mirrored DC. - * - * PARAMS - * phicon1 [I/O] Icon. - * phicon2 [I/O] Icon. - * - * RETURNS - * Success: TRUE. - * Failure: FALSE. - */ -BOOL WINAPI MirrorIcon(HICON *phicon1, HICON *phicon2) -{ - FIXME("(%p, %p): stub\n", phicon1, phicon2); - return FALSE; -} - -static inline int IsDelimiter(WCHAR c) -{ - switch(c) - { - case '/': - case '\\': - case '.': - case ' ': - return TRUE; - } - return FALSE; -} - -static int CALLBACK PathWordBreakProc(LPWSTR lpch, int ichCurrent, int cch, int code) -{ - if (code == WB_ISDELIMITER) - return IsDelimiter(lpch[ichCurrent]); - else - { - int dir = (code == WB_LEFT) ? -1 : 1; - for(; 0 <= ichCurrent && ichCurrent < cch; ichCurrent += dir) - if (IsDelimiter(lpch[ichCurrent])) return ichCurrent; - } - return ichCurrent; -} - -/*********************************************************************** - * SetPathWordBreakProc [COMCTL32.384] - * - * Sets the word break procedure for an edit control to one that understands - * paths so that the user can jump over directories. - * - * PARAMS - * hwnd [I] Handle to edit control. - * bSet [I] If this is TRUE then the word break proc is set, otherwise it is removed. - * - * RETURNS - * Result from EM_SETWORDBREAKPROC message. - */ -LRESULT WINAPI SetPathWordBreakProc(HWND hwnd, BOOL bSet) -{ - return SendMessageW(hwnd, EM_SETWORDBREAKPROC, 0, - (LPARAM)(bSet ? PathWordBreakProc : NULL)); -} diff --git a/reactos/lib/comctl32/datetime.c b/reactos/lib/comctl32/datetime.c deleted file mode 100644 index 9a0826c384b..00000000000 --- a/reactos/lib/comctl32/datetime.c +++ /dev/null @@ -1,1059 +0,0 @@ -/* - * Date and time picker control - * - * Copyright 1998, 1999 Eric Kohl - * Copyright 1999, 2000 Alex Priem - * Copyright 2000 Chris Morgan - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2.1 of the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - * - * 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: - * -- DTS_APPCANPARSE - * -- DTS_SHORTDATECENTURYFORMAT - * -- DTN_CLOSEUP - * -- DTN_FORMAT - * -- DTN_FORMATQUERY - * -- DTN_USERSTRING - * -- DTN_WMKEYDOWN - * -- FORMATCALLBACK - */ - -#include -#include -#include -#include -#include - -#include "windef.h" -#include "winbase.h" -#include "wingdi.h" -#include "winuser.h" -#include "winnls.h" -#include "commctrl.h" -#include "comctl32.h" -#include "wine/debug.h" -#include "wine/unicode.h" - -WINE_DEFAULT_DEBUG_CHANNEL(datetime); - -typedef struct -{ - HWND hwndSelf; - HWND hMonthCal; - HWND hwndNotify; - HWND hUpdown; - DWORD dwStyle; - SYSTEMTIME date; - BOOL dateValid; - HWND hwndCheckbut; - RECT rcClient; /* rect around the edge of the window */ - RECT rcDraw; /* rect inside of the border */ - RECT checkbox; /* checkbox allowing the control to be enabled/disabled */ - RECT calbutton; /* button that toggles the dropdown of the monthcal control */ - BOOL bCalDepressed; /* TRUE = cal button is depressed */ - int select; - HFONT hFont; - int nrFieldsAllocated; - int nrFields; - int haveFocus; - int *fieldspec; - RECT *fieldRect; - int *buflen; - WCHAR textbuf[256]; - POINT monthcal_pos; -} DATETIME_INFO, *LPDATETIME_INFO; - -/* in monthcal.c */ -extern int MONTHCAL_MonthLength(int month, int year); - -/* this list of defines is closely related to `allowedformatchars' defined - * in datetime.c; the high nibble indicates the `base type' of the format - * specifier. - * Do not change without first reading DATETIME_UseFormat. - * - */ - -#define DT_END_FORMAT 0 -#define ONEDIGITDAY 0x01 -#define TWODIGITDAY 0x02 -#define THREECHARDAY 0x03 -#define FULLDAY 0x04 -#define ONEDIGIT12HOUR 0x11 -#define TWODIGIT12HOUR 0x12 -#define ONEDIGIT24HOUR 0x21 -#define TWODIGIT24HOUR 0x22 -#define ONEDIGITMINUTE 0x31 -#define TWODIGITMINUTE 0x32 -#define ONEDIGITMONTH 0x41 -#define TWODIGITMONTH 0x42 -#define THREECHARMONTH 0x43 -#define FULLMONTH 0x44 -#define ONEDIGITSECOND 0x51 -#define TWODIGITSECOND 0x52 -#define ONELETTERAMPM 0x61 -#define TWOLETTERAMPM 0x62 -#define ONEDIGITYEAR 0x71 -#define TWODIGITYEAR 0x72 -#define INVALIDFULLYEAR 0x73 /* FIXME - yyy is not valid - we'll treat it as yyyy */ -#define FULLYEAR 0x74 -#define FORMATCALLBACK 0x81 /* -> maximum of 0x80 callbacks possible */ -#define FORMATCALLMASK 0x80 -#define DT_STRING 0x0100 - -#define DTHT_DATEFIELD 0xff /* for hit-testing */ - -#define DTHT_NONE 0 -#define DTHT_CHECKBOX 0x200 /* these should end at '00' , to make */ -#define DTHT_MCPOPUP 0x300 /* & DTHT_DATEFIELD 0 when DATETIME_KeyDown */ -#define DTHT_GOTFOCUS 0x400 /* tests for date-fields */ - -static BOOL DATETIME_SendSimpleNotify (DATETIME_INFO *infoPtr, UINT code); -static BOOL DATETIME_SendDateTimeChangeNotify (DATETIME_INFO *infoPtr); -extern void MONTHCAL_CopyTime(const SYSTEMTIME *from, SYSTEMTIME *to); -static const WCHAR allowedformatchars[] = {'d', 'h', 'H', 'm', 'M', 's', 't', 'y', 'X', '\'', 0}; -static const int maxrepetition [] = {4,2,2,2,4,2,2,4,-1,-1}; - - -static DWORD -DATETIME_GetSystemTime (DATETIME_INFO *infoPtr, SYSTEMTIME *lprgSysTimeArray) -{ - if (!lprgSysTimeArray) return GDT_NONE; - - if ((infoPtr->dwStyle & DTS_SHOWNONE) && - (SendMessageW (infoPtr->hwndCheckbut, BM_GETCHECK, 0, 0) == BST_UNCHECKED)) - return GDT_NONE; - - MONTHCAL_CopyTime (&infoPtr->date, lprgSysTimeArray); - - return GDT_VALID; -} - - -static BOOL -DATETIME_SetSystemTime (DATETIME_INFO *infoPtr, DWORD flag, SYSTEMTIME *lprgSysTimeArray) -{ - if (!lprgSysTimeArray) return 0; - - TRACE("%04d/%02d/%02d %02d:%02d:%02d\n", - lprgSysTimeArray->wYear, lprgSysTimeArray->wMonth, lprgSysTimeArray->wDay, - lprgSysTimeArray->wHour, lprgSysTimeArray->wMinute, lprgSysTimeArray->wSecond); - - if (flag == GDT_VALID) { - infoPtr->dateValid = TRUE; - MONTHCAL_CopyTime (lprgSysTimeArray, &infoPtr->date); - SendMessageW (infoPtr->hMonthCal, MCM_SETCURSEL, 0, (LPARAM)(&infoPtr->date)); - SendMessageW (infoPtr->hwndCheckbut, BM_SETCHECK, BST_CHECKED, 0); - } else if (flag == GDT_NONE) { - infoPtr->dateValid = FALSE; - SendMessageW (infoPtr->hwndCheckbut, BM_SETCHECK, BST_UNCHECKED, 0); - } - - InvalidateRect(infoPtr->hwndSelf, NULL, TRUE); - return TRUE; -} - - -/*** - * Split up a formattxt in actions. - * See ms documentation for the meaning of the letter codes/'specifiers'. - * - * Notes: - * *'dddddd' is handled as 'dddd' plus 'dd'. - * *unrecognized formats are strings (here given the type DT_STRING; - * start of the string is encoded in lower bits of DT_STRING. - * Therefore, 'string' ends finally up as 'tring'. - * - */ -static void -DATETIME_UseFormat (DATETIME_INFO *infoPtr, LPCWSTR formattxt) -{ - unsigned int i; - int j, k, len; - int *nrFields = &infoPtr->nrFields; - - *nrFields = 0; - infoPtr->fieldspec[*nrFields] = 0; - len = strlenW(allowedformatchars); - k = 0; - - for (i = 0; formattxt[i]; i++) { - TRACE ("\n%d %c:", i, formattxt[i]); - for (j = 0; j < len; j++) { - if (allowedformatchars[j]==formattxt[i]) { - TRACE ("%c[%d,%x]", allowedformatchars[j], *nrFields, infoPtr->fieldspec[*nrFields]); - if ((*nrFields==0) && (infoPtr->fieldspec[*nrFields]==0)) { - infoPtr->fieldspec[*nrFields] = (j<<4) + 1; - break; - } - if (infoPtr->fieldspec[*nrFields] >> 4 != j) { - (*nrFields)++; - infoPtr->fieldspec[*nrFields] = (j<<4) + 1; - break; - } - if ((infoPtr->fieldspec[*nrFields] & 0x0f) == maxrepetition[j]) { - (*nrFields)++; - infoPtr->fieldspec[*nrFields] = (j<<4) + 1; - break; - } - infoPtr->fieldspec[*nrFields]++; - break; - } /* if allowedformatchar */ - } /* for j */ - - /* char is not a specifier: handle char like a string */ - if (j == len) { - if ((*nrFields==0) && (infoPtr->fieldspec[*nrFields]==0)) { - infoPtr->fieldspec[*nrFields] = DT_STRING + k; - infoPtr->buflen[*nrFields] = 0; - } else if ((infoPtr->fieldspec[*nrFields] & DT_STRING) != DT_STRING) { - (*nrFields)++; - infoPtr->fieldspec[*nrFields] = DT_STRING + k; - infoPtr->buflen[*nrFields] = 0; - } - infoPtr->textbuf[k] = formattxt[i]; - k++; - infoPtr->buflen[*nrFields]++; - } /* if j=len */ - - if (*nrFields == infoPtr->nrFieldsAllocated) { - FIXME ("out of memory; should reallocate. crash ahead.\n"); - } - } /* for i */ - - TRACE("\n"); - - if (infoPtr->fieldspec[*nrFields] != 0) (*nrFields)++; -} - - -static BOOL -DATETIME_SetFormatW (DATETIME_INFO *infoPtr, LPCWSTR lpszFormat) -{ - if (!lpszFormat) { - WCHAR format_buf[80]; - DWORD format_item; - - if (infoPtr->dwStyle & DTS_LONGDATEFORMAT) - format_item = LOCALE_SLONGDATE; - else if (infoPtr->dwStyle & DTS_TIMEFORMAT) - format_item = LOCALE_STIMEFORMAT; - else /* DTS_SHORTDATEFORMAT */ - format_item = LOCALE_SSHORTDATE; - GetLocaleInfoW( GetSystemDefaultLCID(), format_item, format_buf, sizeof(format_buf)/sizeof(format_buf[0])); - lpszFormat = format_buf; - } - - DATETIME_UseFormat (infoPtr, lpszFormat); - - return infoPtr->nrFields; -} - - -static BOOL -DATETIME_SetFormatA (DATETIME_INFO *infoPtr, LPCSTR lpszFormat) -{ - if (lpszFormat) { - BOOL retval; - INT len = MultiByteToWideChar(CP_ACP, 0, lpszFormat, -1, NULL, 0); - LPWSTR wstr = Alloc(len * sizeof(WCHAR)); - if (wstr) MultiByteToWideChar(CP_ACP, 0, lpszFormat, -1, wstr, len); - retval = DATETIME_SetFormatW (infoPtr, wstr); - Free (wstr); - return retval; - } - else - return DATETIME_SetFormatW (infoPtr, 0); - -} - - -static void -DATETIME_ReturnTxt (DATETIME_INFO *infoPtr, int count, LPWSTR result, int resultSize) -{ - static const WCHAR fmt_dW[] = { '%', 'd', 0 }; - static const WCHAR fmt__2dW[] = { '%', '.', '2', 'd', 0 }; - static const WCHAR fmt__3sW[] = { '%', '.', '3', 's', 0 }; - SYSTEMTIME date = infoPtr->date; - int spec; - WCHAR buffer[80]; - - *result=0; - TRACE ("%d,%d\n", infoPtr->nrFields, count); - if (count>infoPtr->nrFields || count < 0) { - WARN ("buffer overrun, have %d want %d\n", infoPtr->nrFields, count); - return; - } - - if (!infoPtr->fieldspec) return; - - spec = infoPtr->fieldspec[count]; - if (spec & DT_STRING) { - int txtlen = infoPtr->buflen[count]; - - if (txtlen > resultSize) - txtlen = resultSize - 1; - memcpy (result, infoPtr->textbuf + (spec &~ DT_STRING), txtlen * sizeof(WCHAR)); - result[txtlen] = 0; - TRACE ("arg%d=%x->[%s]\n", count, infoPtr->fieldspec[count], debugstr_w(result)); - return; - } - - - switch (spec) { - case DT_END_FORMAT: - *result = 0; - break; - case ONEDIGITDAY: - wsprintfW (result, fmt_dW, date.wDay); - break; - case TWODIGITDAY: - wsprintfW (result, fmt__2dW, date.wDay); - break; - case THREECHARDAY: - GetLocaleInfoW(LOCALE_USER_DEFAULT, LOCALE_SABBREVDAYNAME1+(date.wDayOfWeek+6)%7, result, 4); - /*wsprintfW (result,"%.3s",days[date.wDayOfWeek]);*/ - break; - case FULLDAY: - GetLocaleInfoW(LOCALE_USER_DEFAULT, LOCALE_SDAYNAME1+(date.wDayOfWeek+6)%7, result, resultSize); - break; - case ONEDIGIT12HOUR: - wsprintfW (result, fmt_dW, date.wHour - (date.wHour > 12 ? 12 : 0)); - break; - case TWODIGIT12HOUR: - wsprintfW (result, fmt__2dW, date.wHour - (date.wHour > 12 ? 12 : 0)); - break; - case ONEDIGIT24HOUR: - wsprintfW (result, fmt_dW, date.wHour); - break; - case TWODIGIT24HOUR: - wsprintfW (result, fmt__2dW, date.wHour); - break; - case ONEDIGITSECOND: - wsprintfW (result, fmt_dW, date.wSecond); - break; - case TWODIGITSECOND: - wsprintfW (result, fmt__2dW, date.wSecond); - break; - case ONEDIGITMINUTE: - wsprintfW (result, fmt_dW, date.wMinute); - break; - case TWODIGITMINUTE: - wsprintfW (result, fmt__2dW, date.wMinute); - break; - case ONEDIGITMONTH: - wsprintfW (result, fmt_dW, date.wMonth); - break; - case TWODIGITMONTH: - wsprintfW (result, fmt__2dW, date.wMonth); - break; - case THREECHARMONTH: - GetLocaleInfoW(GetSystemDefaultLCID(), LOCALE_SMONTHNAME1+date.wMonth -1, - buffer, sizeof(buffer)/sizeof(buffer[0])); - wsprintfW (result, fmt__3sW, buffer); - break; - case FULLMONTH: - GetLocaleInfoW(GetSystemDefaultLCID(),LOCALE_SMONTHNAME1+date.wMonth -1, - result, resultSize); - break; - case ONELETTERAMPM: - result[0] = (date.wHour < 12 ? 'A' : 'P'); - result[1] = 0; - break; - case TWOLETTERAMPM: - result[0] = (date.wHour < 12 ? 'A' : 'P'); - result[1] = 'M'; - result[2] = 0; - break; - case FORMATCALLBACK: - FIXME ("Not implemented\n"); - result[0] = 'x'; - result[1] = 0; - break; - case ONEDIGITYEAR: - wsprintfW (result, fmt_dW, date.wYear-10* (int) floor(date.wYear/10)); - break; - case TWODIGITYEAR: - wsprintfW (result, fmt__2dW, date.wYear-100* (int) floor(date.wYear/100)); - break; - case INVALIDFULLYEAR: - case FULLYEAR: - wsprintfW (result, fmt_dW, date.wYear); - break; - } - - TRACE ("arg%d=%x->[%s]\n", count, infoPtr->fieldspec[count], debugstr_w(result)); -} - -static int wrap(int val, int delta, int minVal, int maxVal) -{ - val += delta; - if (delta == INT_MIN || val < minVal) return maxVal; - if (delta == INT_MAX || val > maxVal) return minVal; - return val; -} - -static void -DATETIME_IncreaseField (DATETIME_INFO *infoPtr, int number, int delta) -{ - SYSTEMTIME *date = &infoPtr->date; - - TRACE ("%d\n", number); - if ((number > infoPtr->nrFields) || (number < 0)) return; - - if ((infoPtr->fieldspec[number] & DTHT_DATEFIELD) == 0) return; - - switch (infoPtr->fieldspec[number]) { - case ONEDIGITYEAR: - case TWODIGITYEAR: - case FULLYEAR: - date->wYear = wrap(date->wYear, delta, 1752, 9999); - break; - case ONEDIGITMONTH: - case TWODIGITMONTH: - case THREECHARMONTH: - case FULLMONTH: - date->wMonth = wrap(date->wMonth, delta, 1, 12); - delta = 0; - /* fall through */ - case ONEDIGITDAY: - case TWODIGITDAY: - case THREECHARDAY: - case FULLDAY: - date->wDay = wrap(date->wDay, delta, 1, MONTHCAL_MonthLength(date->wMonth, date->wYear)); - break; - case ONELETTERAMPM: - case TWOLETTERAMPM: - delta *= 12; - /* fall through */ - case ONEDIGIT12HOUR: - case TWODIGIT12HOUR: - case ONEDIGIT24HOUR: - case TWODIGIT24HOUR: - date->wHour = wrap(date->wHour, delta, 0, 23); - break; - case ONEDIGITMINUTE: - case TWODIGITMINUTE: - date->wMinute = wrap(date->wMinute, delta, 0, 59); - break; - case ONEDIGITSECOND: - case TWODIGITSECOND: - date->wSecond = wrap(date->wSecond, delta, 0, 59); - break; - case FORMATCALLBACK: - FIXME ("Not implemented\n"); - break; - } - - /* FYI: On 1752/9/14 the calendar changed and England and the - * American colonies changed to the Gregorian calendar. This change - * involved having September 14th follow September 2nd. So no date - * algorithm works before that date. - */ - if (10000 * date->wYear + 100 * date->wMonth + date->wDay < 17520914) { - date->wYear = 1752; - date->wMonth = 9; - date->wDay = 14; - date->wSecond = 0; - date->wMinute = 0; - date->wHour = 0; - } -} - - -static void -DATETIME_Refresh (DATETIME_INFO *infoPtr, HDC hdc) -{ - int i,prevright; - RECT *field; - RECT *rcDraw = &infoPtr->rcDraw; - RECT *rcClient = &infoPtr->rcClient; - RECT *calbutton = &infoPtr->calbutton; - RECT *checkbox = &infoPtr->checkbox; - HBRUSH hbr; - SIZE size; - COLORREF oldBk, oldTextColor; - - /* draw control edge */ - TRACE("\n"); - hbr = CreateSolidBrush(RGB(255, 255, 255)); - FillRect(hdc, rcClient, hbr); - DrawEdge(hdc, rcClient, EDGE_SUNKEN, BF_RECT); - DeleteObject(hbr); - - if (infoPtr->dateValid) { - HFONT oldFont = SelectObject (hdc, infoPtr->hFont); - WCHAR txt[80]; - - DATETIME_ReturnTxt (infoPtr, 0, txt, sizeof(txt)/sizeof(txt[0])); - GetTextExtentPoint32W (hdc, txt, strlenW(txt), &size); - rcDraw->bottom = size.cy + 2; - - prevright = checkbox->right = ((infoPtr->dwStyle & DTS_SHOWNONE) ? 18 : 2); - - for (i = 0; i < infoPtr->nrFields; i++) { - DATETIME_ReturnTxt (infoPtr, i, txt, sizeof(txt)/sizeof(txt[0])); - GetTextExtentPoint32W (hdc, txt, strlenW(txt), &size); - field = &infoPtr->fieldRect[i]; - field->left = prevright; - field->right = prevright+size.cx; - field->top = rcDraw->top; - field->bottom = rcDraw->bottom; - prevright = field->right; - - if ((infoPtr->haveFocus) && (i == infoPtr->select)) { - hbr = CreateSolidBrush (GetSysColor (COLOR_ACTIVECAPTION)); - FillRect(hdc, field, hbr); - oldBk = SetBkColor (hdc, GetSysColor(COLOR_ACTIVECAPTION)); - oldTextColor = SetTextColor (hdc, GetSysColor(COLOR_WINDOW)); - DeleteObject (hbr); - DrawTextW (hdc, txt, strlenW(txt), field, DT_RIGHT | DT_VCENTER | DT_SINGLELINE); - SetBkColor (hdc, oldBk); - SetTextColor (hdc, oldTextColor); - } else - DrawTextW ( hdc, txt, strlenW(txt), field, DT_RIGHT | DT_VCENTER | DT_SINGLELINE ); - } - SelectObject (hdc, oldFont); - } - - if (!(infoPtr->dwStyle & DTS_UPDOWN)) { - DrawFrameControl(hdc, calbutton, DFC_SCROLL, - DFCS_SCROLLDOWN | (infoPtr->bCalDepressed ? DFCS_PUSHED : 0) | - (infoPtr->dwStyle & WS_DISABLED ? DFCS_INACTIVE : 0) ); - } -} - - -static INT -DATETIME_HitTest (DATETIME_INFO *infoPtr, POINT pt) -{ - int i; - - TRACE ("%ld, %ld\n", pt.x, pt.y); - - if (PtInRect (&infoPtr->calbutton, pt)) return DTHT_MCPOPUP; - if (PtInRect (&infoPtr->checkbox, pt)) return DTHT_CHECKBOX; - - for (i=0; i < infoPtr->nrFields; i++) { - if (PtInRect (&infoPtr->fieldRect[i], pt)) return i; - } - - return DTHT_NONE; -} - - -static LRESULT -DATETIME_LButtonDown (DATETIME_INFO *infoPtr, WORD wKey, INT x, INT y) -{ - POINT pt; - int old, new; - - pt.x = x; - pt.y = y; - old = infoPtr->select; - new = DATETIME_HitTest (infoPtr, pt); - - /* FIXME: might be conditions where we don't want to update infoPtr->select */ - infoPtr->select = new; - - if (infoPtr->select != old) - infoPtr->haveFocus = DTHT_GOTFOCUS; - - if (infoPtr->select == DTHT_MCPOPUP) { - /* FIXME: button actually is only depressed during dropdown of the */ - /* calendar control and when the mouse is over the button window */ - infoPtr->bCalDepressed = TRUE; - - /* recalculate the position of the monthcal popup */ - if(infoPtr->dwStyle & DTS_RIGHTALIGN) - infoPtr->monthcal_pos.x = infoPtr->rcClient.right - - ((infoPtr->calbutton.right - infoPtr->calbutton.left) + 200); - else - infoPtr->monthcal_pos.x = 8; - - infoPtr->monthcal_pos.y = infoPtr->rcClient.bottom; - ClientToScreen (infoPtr->hwndSelf, &(infoPtr->monthcal_pos)); - /* FIXME My Windoze has cx=about 200, but it probably depends on font size etc */ - SetWindowPos(infoPtr->hMonthCal, 0, infoPtr->monthcal_pos.x, infoPtr->monthcal_pos.y, 200, 150, 0); - - if(IsWindowVisible(infoPtr->hMonthCal)) { - ShowWindow(infoPtr->hMonthCal, SW_HIDE); - } else { - SYSTEMTIME *lprgSysTimeArray = &infoPtr->date; - TRACE("update calendar %04d/%02d/%02d\n", - lprgSysTimeArray->wYear, lprgSysTimeArray->wMonth, lprgSysTimeArray->wDay); - SendMessageW(infoPtr->hMonthCal, MCM_SETCURSEL, 0, (LPARAM)(&infoPtr->date)); - ShowWindow(infoPtr->hMonthCal, SW_SHOW); - } - - TRACE ("dt:%p mc:%p mc parent:%p, desktop:%p\n", - infoPtr->hwndSelf, infoPtr->hMonthCal, infoPtr->hwndNotify, GetDesktopWindow ()); - DATETIME_SendSimpleNotify (infoPtr, DTN_DROPDOWN); - } - - InvalidateRect(infoPtr->hwndSelf, NULL, FALSE); - - return 0; -} - - -static LRESULT -DATETIME_LButtonUp (DATETIME_INFO *infoPtr, WORD wKey) -{ - if(infoPtr->bCalDepressed == TRUE) { - infoPtr->bCalDepressed = FALSE; - InvalidateRect(infoPtr->hwndSelf, &(infoPtr->calbutton), TRUE); - } - - return 0; -} - - -static LRESULT -DATETIME_Paint (DATETIME_INFO *infoPtr, HDC hdc) -{ - if (!hdc) { - PAINTSTRUCT ps; - hdc = BeginPaint (infoPtr->hwndSelf, &ps); - DATETIME_Refresh (infoPtr, hdc); - EndPaint (infoPtr->hwndSelf, &ps); - } else { - DATETIME_Refresh (infoPtr, hdc); - } - return 0; -} - - -static LRESULT -DATETIME_Button_Command (DATETIME_INFO *infoPtr, WPARAM wParam, LPARAM lParam) -{ - if( HIWORD(wParam) == BN_CLICKED) { - DWORD state = SendMessageW((HWND)lParam, BM_GETCHECK, 0, 0); - infoPtr->dateValid = (state == BST_CHECKED); - InvalidateRect(infoPtr->hwndSelf, NULL, TRUE); - } - return 0; -} - - - -static LRESULT -DATETIME_Command (DATETIME_INFO *infoPtr, WPARAM wParam, LPARAM lParam) -{ - TRACE("hwndbutton = %p\n", infoPtr->hwndCheckbut); - if(infoPtr->hwndCheckbut == (HWND)lParam) - return DATETIME_Button_Command(infoPtr, wParam, lParam); - return 0; -} - - -static LRESULT -DATETIME_Notify (DATETIME_INFO *infoPtr, int idCtrl, LPNMHDR lpnmh) -{ - TRACE ("Got notification %x from %p\n", lpnmh->code, lpnmh->hwndFrom); - TRACE ("info: %p %p %p\n", infoPtr->hwndSelf, infoPtr->hMonthCal, infoPtr->hUpdown); - - if (lpnmh->code == MCN_SELECT) { - ShowWindow(infoPtr->hMonthCal, SW_HIDE); - infoPtr->dateValid = TRUE; - SendMessageW (infoPtr->hMonthCal, MCM_GETCURSEL, 0, (LPARAM)&infoPtr->date); - TRACE("got from calendar %04d/%02d/%02d\n", - infoPtr->date.wYear, infoPtr->date.wMonth, infoPtr->date.wDay); - SendMessageW (infoPtr->hwndCheckbut, BM_SETCHECK, BST_CHECKED, 0); - InvalidateRect(infoPtr->hwndSelf, NULL, TRUE); - DATETIME_SendDateTimeChangeNotify (infoPtr); - } - return 0; -} - - -static LRESULT -DATETIME_KeyDown (DATETIME_INFO *infoPtr, DWORD vkCode, LPARAM flags) -{ - int fieldNum = infoPtr->select & DTHT_DATEFIELD; - int wrap = 0; - - if (!(infoPtr->haveFocus)) return 0; - if ((fieldNum==0) && (infoPtr->select)) return 0; - - if (infoPtr->select & FORMATCALLMASK) { - FIXME ("Callbacks not implemented yet\n"); - } - - switch (vkCode) { - case VK_ADD: - case VK_UP: - DATETIME_IncreaseField (infoPtr, fieldNum, 1); - DATETIME_SendDateTimeChangeNotify (infoPtr); - break; - case VK_SUBTRACT: - case VK_DOWN: - DATETIME_IncreaseField (infoPtr, fieldNum, -1); - DATETIME_SendDateTimeChangeNotify (infoPtr); - break; - case VK_HOME: - DATETIME_IncreaseField (infoPtr, fieldNum, INT_MIN); - DATETIME_SendDateTimeChangeNotify (infoPtr); - break; - case VK_END: - DATETIME_IncreaseField (infoPtr, fieldNum, INT_MAX); - DATETIME_SendDateTimeChangeNotify (infoPtr); - break; - case VK_LEFT: - do { - if (infoPtr->select == 0) { - infoPtr->select = infoPtr->nrFields - 1; - wrap++; - } else { - infoPtr->select--; - } - } while ((infoPtr->fieldspec[infoPtr->select] & DT_STRING) && (wrap<2)); - break; - case VK_RIGHT: - do { - infoPtr->select++; - if (infoPtr->select==infoPtr->nrFields) { - infoPtr->select = 0; - wrap++; - } - } while ((infoPtr->fieldspec[infoPtr->select] & DT_STRING) && (wrap<2)); - break; - } - - InvalidateRect(infoPtr->hwndSelf, NULL, FALSE); - - return 0; -} - - -static LRESULT -DATETIME_KillFocus (DATETIME_INFO *infoPtr, HWND lostFocus) -{ - if (infoPtr->haveFocus) { - DATETIME_SendSimpleNotify (infoPtr, NM_KILLFOCUS); - infoPtr->haveFocus = 0; - } - - InvalidateRect (infoPtr->hwndSelf, NULL, TRUE); - - return 0; -} - - -static LRESULT -DATETIME_SetFocus (DATETIME_INFO *infoPtr, HWND lostFocus) -{ - if (infoPtr->haveFocus == 0) { - DATETIME_SendSimpleNotify (infoPtr, NM_SETFOCUS); - infoPtr->haveFocus = DTHT_GOTFOCUS; - } - - InvalidateRect(infoPtr->hwndSelf, NULL, FALSE); - - return 0; -} - - -static BOOL -DATETIME_SendDateTimeChangeNotify (DATETIME_INFO *infoPtr) -{ - NMDATETIMECHANGE dtdtc; - - dtdtc.nmhdr.hwndFrom = infoPtr->hwndSelf; - dtdtc.nmhdr.idFrom = GetWindowLongPtrW(infoPtr->hwndSelf, GWLP_ID); - dtdtc.nmhdr.code = DTN_DATETIMECHANGE; - - dtdtc.dwFlags = (infoPtr->dwStyle & DTS_SHOWNONE) ? GDT_NONE : GDT_VALID; - - MONTHCAL_CopyTime (&infoPtr->date, &dtdtc.st); - return (BOOL) SendMessageW (infoPtr->hwndNotify, WM_NOTIFY, - (WPARAM)dtdtc.nmhdr.idFrom, (LPARAM)&dtdtc); -} - - -static BOOL -DATETIME_SendSimpleNotify (DATETIME_INFO *infoPtr, UINT code) -{ - NMHDR nmhdr; - - TRACE("%x\n", code); - nmhdr.hwndFrom = infoPtr->hwndSelf; - nmhdr.idFrom = GetWindowLongPtrW(infoPtr->hwndSelf, GWLP_ID); - nmhdr.code = code; - - return (BOOL) SendMessageW (infoPtr->hwndNotify, WM_NOTIFY, - (WPARAM)nmhdr.idFrom, (LPARAM)&nmhdr); -} - -static LRESULT -DATETIME_Size (DATETIME_INFO *infoPtr, WORD flags, INT width, INT height) -{ - /* set size */ - infoPtr->rcClient.bottom = height; - infoPtr->rcClient.right = width; - - TRACE("Height=%ld, Width=%ld\n", infoPtr->rcClient.bottom, infoPtr->rcClient.right); - - memcpy((&infoPtr->rcDraw), (&infoPtr->rcClient), sizeof(infoPtr->rcDraw)); - - /* subract the size of the edge drawn by DrawEdge */ - InflateRect(&infoPtr->rcDraw, -2, -2); - - /* set the size of the button that drops the calendar down */ - /* FIXME: account for style that allows button on left side */ - infoPtr->calbutton.top = infoPtr->rcDraw.top; - infoPtr->calbutton.bottom= infoPtr->rcDraw.bottom; - infoPtr->calbutton.left = infoPtr->rcDraw.right-15; - infoPtr->calbutton.right = infoPtr->rcDraw.right; - - /* set enable/disable button size for show none style being enabled */ - /* FIXME: these dimensions are completely incorrect */ - infoPtr->checkbox.top = infoPtr->rcDraw.top; - infoPtr->checkbox.bottom = infoPtr->rcDraw.bottom; - infoPtr->checkbox.left = infoPtr->rcDraw.left; - infoPtr->checkbox.right = infoPtr->rcDraw.left + 10; - - /* update the position of the monthcal control */ - if(infoPtr->dwStyle & DTS_RIGHTALIGN) - infoPtr->monthcal_pos.x = infoPtr->rcClient.right - ((infoPtr->calbutton.right - - infoPtr->calbutton.left) + 145); - else - infoPtr->monthcal_pos.x = 8; - - infoPtr->monthcal_pos.y = infoPtr->rcClient.bottom; - ClientToScreen (infoPtr->hwndSelf, &(infoPtr->monthcal_pos)); - SetWindowPos(infoPtr->hMonthCal, 0, infoPtr->monthcal_pos.x, infoPtr->monthcal_pos.y, 145, 150, 0); - - InvalidateRect(infoPtr->hwndSelf, NULL, FALSE); - - return 0; -} - - -static LRESULT -DATETIME_StyleChanged(DATETIME_INFO *infoPtr, WPARAM wStyleType, LPSTYLESTRUCT lpss) -{ - static const WCHAR buttonW[] = { 'b', 'u', 't', 't', 'o', 'n', 0 }; - - TRACE("(styletype=%x, styleOld=0x%08lx, styleNew=0x%08lx)\n", - wStyleType, lpss->styleOld, lpss->styleNew); - - if (wStyleType != GWL_STYLE) return 0; - - infoPtr->dwStyle = lpss->styleNew; - - if ( !(lpss->styleOld & DTS_SHOWNONE) && (lpss->styleNew & DTS_SHOWNONE) ) { - infoPtr->hwndCheckbut = CreateWindowExW (0, buttonW, 0, WS_CHILD | WS_VISIBLE | BS_AUTOCHECKBOX, - 2, 2, 13, 13, infoPtr->hwndSelf, 0, - (HINSTANCE)GetWindowLongPtrW (infoPtr->hwndSelf, GWLP_HINSTANCE), 0); - SendMessageW (infoPtr->hwndCheckbut, BM_SETCHECK, 1, 0); - } - if ( (lpss->styleOld & DTS_SHOWNONE) && !(lpss->styleNew & DTS_SHOWNONE) ) { - DestroyWindow(infoPtr->hwndCheckbut); - infoPtr->hwndCheckbut = 0; - } - if ( !(lpss->styleOld & DTS_UPDOWN) && (lpss->styleNew & DTS_UPDOWN) ) { - infoPtr->hUpdown = CreateUpDownControl (WS_CHILD | WS_BORDER | WS_VISIBLE, 120, 1, 20, 20, - infoPtr->hwndSelf, 1, 0, 0, UD_MAXVAL, UD_MINVAL, 0); - } - if ( (lpss->styleOld & DTS_UPDOWN) && !(lpss->styleNew & DTS_UPDOWN) ) { - DestroyWindow(infoPtr->hUpdown); - infoPtr->hUpdown = 0; - } - - InvalidateRect(infoPtr->hwndSelf, NULL, TRUE); - return 0; -} - - -static LRESULT -DATETIME_Create (HWND hwnd, LPCREATESTRUCTW lpcs) -{ - static const WCHAR SysMonthCal32W[] = { 'S', 'y', 's', 'M', 'o', 'n', 't', 'h', 'C', 'a', 'l', '3', '2', 0 }; - DATETIME_INFO *infoPtr = (DATETIME_INFO *)Alloc (sizeof(DATETIME_INFO)); - STYLESTRUCT ss = { 0, lpcs->style }; - - if (!infoPtr) return -1; - - infoPtr->hwndSelf = hwnd; - infoPtr->dwStyle = lpcs->style; - - infoPtr->nrFieldsAllocated = 32; - infoPtr->fieldspec = (int *) Alloc (infoPtr->nrFieldsAllocated * sizeof(int)); - infoPtr->fieldRect = (RECT *) Alloc (infoPtr->nrFieldsAllocated * sizeof(RECT)); - infoPtr->buflen = (int *) Alloc (infoPtr->nrFieldsAllocated * sizeof(int)); - infoPtr->hwndNotify = lpcs->hwndParent; - - DATETIME_StyleChanged(infoPtr, GWL_STYLE, &ss); - DATETIME_SetFormatW (infoPtr, 0); - - /* create the monthcal control */ - infoPtr->hMonthCal = CreateWindowExW (0, SysMonthCal32W, 0, WS_BORDER | WS_POPUP | WS_CLIPSIBLINGS, - 0, 0, 0, 0, infoPtr->hwndSelf, 0, 0, 0); - - /* initialize info structure */ - GetSystemTime (&infoPtr->date); - infoPtr->dateValid = TRUE; - infoPtr->hFont = GetStockObject(DEFAULT_GUI_FONT); - - SetWindowLongPtrW (hwnd, 0, (DWORD_PTR)infoPtr); - - return 0; -} - - - -static LRESULT -DATETIME_Destroy (DATETIME_INFO *infoPtr) -{ - if (infoPtr->hwndCheckbut) - DestroyWindow(infoPtr->hwndCheckbut); - if (infoPtr->hUpdown) - DestroyWindow(infoPtr->hUpdown); - if (infoPtr->hMonthCal) - DestroyWindow(infoPtr->hMonthCal); - SetWindowLongPtrW( infoPtr->hwndSelf, 0, 0 ); /* clear infoPtr */ - Free (infoPtr); - return 0; -} - - -static LRESULT WINAPI -DATETIME_WindowProc (HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam) -{ - DATETIME_INFO *infoPtr = ((DATETIME_INFO *)GetWindowLongPtrW (hwnd, 0)); - LRESULT ret; - - TRACE ("%x, %x, %lx\n", uMsg, wParam, lParam); - - if (!infoPtr && (uMsg != WM_CREATE)) - return DefWindowProcW( hwnd, uMsg, wParam, lParam ); - - switch (uMsg) { - - case DTM_GETSYSTEMTIME: - return DATETIME_GetSystemTime (infoPtr, (SYSTEMTIME *) lParam); - - case DTM_SETSYSTEMTIME: - return DATETIME_SetSystemTime (infoPtr, wParam, (SYSTEMTIME *) lParam); - - case DTM_GETRANGE: - ret = SendMessageW (infoPtr->hMonthCal, MCM_GETRANGE, wParam, lParam); - return ret ? ret : 1; /* bug emulation */ - - case DTM_SETRANGE: - return SendMessageW (infoPtr->hMonthCal, MCM_SETRANGE, wParam, lParam); - - case DTM_SETFORMATA: - return DATETIME_SetFormatA (infoPtr, (LPCSTR)lParam); - - case DTM_SETFORMATW: - return DATETIME_SetFormatW (infoPtr, (LPCWSTR)lParam); - - case DTM_GETMONTHCAL: - return (LRESULT)infoPtr->hMonthCal; - - case DTM_SETMCCOLOR: - return SendMessageW (infoPtr->hMonthCal, MCM_SETCOLOR, wParam, lParam); - - case DTM_GETMCCOLOR: - return SendMessageW (infoPtr->hMonthCal, MCM_GETCOLOR, wParam, 0); - - case DTM_SETMCFONT: - return SendMessageW (infoPtr->hMonthCal, WM_SETFONT, wParam, lParam); - - case DTM_GETMCFONT: - return SendMessageW (infoPtr->hMonthCal, WM_GETFONT, wParam, lParam); - - case WM_NOTIFY: - return DATETIME_Notify (infoPtr, (int)wParam, (LPNMHDR)lParam); - - case WM_GETDLGCODE: - return DLGC_WANTARROWS | DLGC_WANTCHARS; - - case WM_PAINT: - return DATETIME_Paint (infoPtr, (HDC)wParam); - - case WM_KEYDOWN: - return DATETIME_KeyDown (infoPtr, wParam, lParam); - - case WM_KILLFOCUS: - return DATETIME_KillFocus (infoPtr, (HWND)wParam); - - case WM_SETFOCUS: - return DATETIME_SetFocus (infoPtr, (HWND)wParam); - - case WM_SIZE: - return DATETIME_Size (infoPtr, wParam, (SHORT)LOWORD(lParam), (SHORT)HIWORD(lParam)); - - case WM_LBUTTONDOWN: - return DATETIME_LButtonDown (infoPtr, (WORD)wParam, (SHORT)LOWORD(lParam), (SHORT)HIWORD(lParam)); - - case WM_LBUTTONUP: - return DATETIME_LButtonUp (infoPtr, (WORD)wParam); - - case WM_CREATE: - return DATETIME_Create (hwnd, (LPCREATESTRUCTW)lParam); - - case WM_DESTROY: - return DATETIME_Destroy (infoPtr); - - case WM_COMMAND: - return DATETIME_Command (infoPtr, wParam, lParam); - - case WM_STYLECHANGED: - return DATETIME_StyleChanged(infoPtr, wParam, (LPSTYLESTRUCT)lParam); - - default: - if ((uMsg >= WM_USER) && (uMsg < WM_APP)) - ERR("unknown msg %04x wp=%08x lp=%08lx\n", - uMsg, wParam, lParam); - return DefWindowProcW (hwnd, uMsg, wParam, lParam); - } - return 0; -} - - -void -DATETIME_Register (void) -{ - WNDCLASSW wndClass; - - ZeroMemory (&wndClass, sizeof(WNDCLASSW)); - wndClass.style = CS_GLOBALCLASS; - wndClass.lpfnWndProc = DATETIME_WindowProc; - wndClass.cbClsExtra = 0; - wndClass.cbWndExtra = sizeof(DATETIME_INFO *); - wndClass.hCursor = LoadCursorW (0, (LPCWSTR)IDC_ARROW); - wndClass.hbrBackground = (HBRUSH)(COLOR_WINDOW + 1); - wndClass.lpszClassName = DATETIMEPICK_CLASSW; - - RegisterClassW (&wndClass); -} - - -void -DATETIME_Unregister (void) -{ - UnregisterClassW (DATETIMEPICK_CLASSW, NULL); -} diff --git a/reactos/lib/comctl32/draglist.c b/reactos/lib/comctl32/draglist.c deleted file mode 100644 index ca1fcc64edf..00000000000 --- a/reactos/lib/comctl32/draglist.c +++ /dev/null @@ -1,345 +0,0 @@ -/* - * Drag List control - * - * Copyright 1999 Eric Kohl - * Copyright 2004 Robert Shearman - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2.1 of the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - * - * NOTES - * - * This code was audited for completeness against the documented features - * of Comctl32.dll version 6.0 on Mar. 10, 2004, by Robert Shearman. - * - * Unless otherwise noted, we believe this code to be complete, as per - * the specification mentioned above. - * If you discover missing features or bugs please note them below. - * - */ - -#include - -#include "windef.h" -#include "winbase.h" -#include "wingdi.h" -#include "winuser.h" -#include "winnls.h" -#include "commctrl.h" -#include "comctl32.h" -#include "wine/debug.h" - -WINE_DEFAULT_DEBUG_CHANNEL(commctrl); - -/* for compiler compatibility we only accept literal ASCII strings */ -#undef TEXT -#define TEXT(string) string - -#define DRAGLIST_SUBCLASSID 0 -#define DRAGLIST_SCROLLPERIOD 200 -#define DRAGLIST_TIMERID 666 - -/* properties relating to IDI_DRAGICON */ -#define DRAGICON_HOTSPOT_X 17 -#define DRAGICON_HOTSPOT_Y 7 -#define DRAGICON_HEIGHT 32 - -/* internal Wine specific data for the drag list control */ -typedef struct _DRAGLISTDATA -{ - /* are we currently in dragging mode? */ - BOOL dragging; - - /* cursor to use as determined by DL_DRAGGING notification. - * NOTE: as we use LoadCursor we don't have to use DeleteCursor - * when we are finished with it */ - HCURSOR cursor; - - /* optimisation so that we don't have to load the cursor - * all of the time whilst dragging */ - LRESULT last_dragging_response; - - /* prevents flicker with drawing drag arrow */ - RECT last_drag_icon_rect; -} DRAGLISTDATA; - -UINT uDragListMessage = 0; /* registered window message code */ -static DWORD dwLastScrollTime = 0; -static HICON hDragArrow = NULL; - -/*********************************************************************** - * DragList_Notify (internal) - * - * Sends notification messages to the parent control. Note that it - * does not use WM_NOTIFY like the rest of the controls, but a registered - * window message. - */ -static LRESULT DragList_Notify(HWND hwndLB, UINT uNotification) -{ - DRAGLISTINFO dli; - dli.hWnd = hwndLB; - dli.uNotification = uNotification; - GetCursorPos(&dli.ptCursor); - return SendMessageW(GetParent(hwndLB), uDragListMessage, GetDlgCtrlID(hwndLB), (LPARAM)&dli); -} - -/* cleans up after dragging */ -static inline void DragList_EndDrag(HWND hwnd, DRAGLISTDATA * data) -{ - KillTimer(hwnd, DRAGLIST_TIMERID); - ReleaseCapture(); - /* clear any drag insert icon present */ - InvalidateRect(GetParent(hwnd), &data->last_drag_icon_rect, TRUE); - /* clear data for next use */ - memset(data, 0, sizeof(*data)); -} - -/*********************************************************************** - * DragList_SubclassWindowProc (internal) - * - * Handles certain messages to enable dragging for the ListBox and forwards - * the rest to the ListBox. - */ -static LRESULT CALLBACK -DragList_SubclassWindowProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam, UINT_PTR uIdSubclass, DWORD_PTR dwRefData) -{ - DRAGLISTDATA * data = (DRAGLISTDATA*)dwRefData; - switch (uMsg) - { - case WM_LBUTTONDOWN: - SetFocus(hwnd); - data->dragging = DragList_Notify(hwnd, DL_BEGINDRAG); - if (data->dragging) - { - SetCapture(hwnd); - SetTimer(hwnd, DRAGLIST_TIMERID, DRAGLIST_SCROLLPERIOD, NULL); - } - /* note that we don't absorb this message to let the list box - * do its thing (normally selecting an item) */ - break; - - case WM_KEYDOWN: - case WM_RBUTTONDOWN: - /* user cancelled drag by either right clicking or - * by pressing the escape key */ - if ((data->dragging) && - ((uMsg == WM_RBUTTONDOWN) || (wParam == VK_ESCAPE))) - { - /* clean up and absorb message */ - DragList_EndDrag(hwnd, data); - DragList_Notify(hwnd, DL_CANCELDRAG); - return 0; - } - break; - - case WM_MOUSEMOVE: - case WM_TIMER: - if (data->dragging) - { - LRESULT cursor = DragList_Notify(hwnd, DL_DRAGGING); - /* optimisation so that we don't have to load the cursor - * all of the time whilst dragging */ - if (data->last_dragging_response != cursor) - { - switch (cursor) - { - case DL_STOPCURSOR: - data->cursor = LoadCursorW(NULL, (LPCWSTR)IDC_NO); - SetCursor(data->cursor); - break; - case DL_COPYCURSOR: - data->cursor = LoadCursorW(COMCTL32_hModule, (LPCWSTR)IDC_COPY); - SetCursor(data->cursor); - break; - case DL_MOVECURSOR: - data->cursor = LoadCursorW(NULL, (LPCWSTR)IDC_ARROW); - SetCursor(data->cursor); - break; - } - data->last_dragging_response = cursor; - } - /* don't pass this message on to List Box */ - return 0; - } - break; - - case WM_LBUTTONUP: - if (data->dragging) - { - DragList_EndDrag(hwnd, data); - DragList_Notify(hwnd, DL_DROPPED); - } - break; - - case WM_GETDLGCODE: - /* tell dialog boxes that we want to receive WM_KEYDOWN events - * for keys like VK_ESCAPE */ - if (data->dragging) - return DLGC_WANTALLKEYS; - break; - case WM_NCDESTROY: - RemoveWindowSubclass(hwnd, DragList_SubclassWindowProc, DRAGLIST_SUBCLASSID); - Free(data); - break; - } - return DefSubclassProc(hwnd, uMsg, wParam, lParam); -} - -/*********************************************************************** - * MakeDragList (COMCTL32.13) - * - * Makes a normal ListBox into a DragList by subclassing it. - * - * RETURNS - * Success: Non-zero - * Failure: Zero - */ -BOOL WINAPI MakeDragList (HWND hwndLB) -{ - DRAGLISTDATA * data = Alloc(sizeof(DRAGLISTDATA)); - - TRACE("(%p)\n", hwndLB); - - if (!uDragListMessage) - uDragListMessage = RegisterWindowMessageA(DRAGLISTMSGSTRING); - - return SetWindowSubclass(hwndLB, DragList_SubclassWindowProc, DRAGLIST_SUBCLASSID, (DWORD_PTR)data); -} - -/*********************************************************************** - * DrawInsert (COMCTL32.15) - * - * Draws insert arrow by the side of the ListBox item in the parent window. - * - * RETURNS - * Nothing. - */ -VOID WINAPI DrawInsert (HWND hwndParent, HWND hwndLB, INT nItem) -{ - RECT rcItem, rcListBox, rcDragIcon; - HDC hdc; - DRAGLISTDATA * data; - - TRACE("(%p %p %d)\n", hwndParent, hwndLB, nItem); - - if (!hDragArrow) - hDragArrow = LoadIconW(COMCTL32_hModule, (LPCWSTR)IDI_DRAGARROW); - - if (LB_ERR == SendMessageW(hwndLB, LB_GETITEMRECT, nItem, (LPARAM)&rcItem)) - return; - - if (!GetWindowRect(hwndLB, &rcListBox)) - return; - - /* convert item rect to parent co-ordinates */ - if (!MapWindowPoints(hwndLB, hwndParent, (LPPOINT)&rcItem, 2)) - return; - - /* convert list box rect to parent co-ordinates */ - if (!MapWindowPoints(HWND_DESKTOP, hwndParent, (LPPOINT)&rcListBox, 2)) - return; - - rcDragIcon.left = rcListBox.left - DRAGICON_HOTSPOT_X; - rcDragIcon.top = rcItem.top - DRAGICON_HOTSPOT_Y; - rcDragIcon.right = rcListBox.left; - rcDragIcon.bottom = rcDragIcon.top + DRAGICON_HEIGHT; - - if (!GetWindowSubclass(hwndLB, DragList_SubclassWindowProc, DRAGLIST_SUBCLASSID, (DWORD_PTR*)&data)) - return; - - if (nItem < 0) - SetRectEmpty(&rcDragIcon); - - /* prevent flicker by only redrawing when necessary */ - if (!EqualRect(&rcDragIcon, &data->last_drag_icon_rect)) - { - /* get rid of any previous inserts drawn */ - RedrawWindow(hwndParent, &data->last_drag_icon_rect, NULL, - RDW_INTERNALPAINT | RDW_ERASE | RDW_INVALIDATE | RDW_UPDATENOW); - - CopyRect(&data->last_drag_icon_rect, &rcDragIcon); - - if (nItem >= 0) - { - hdc = GetDC(hwndParent); - - DrawIcon(hdc, rcDragIcon.left, rcDragIcon.top, hDragArrow); - - ReleaseDC(hwndParent, hdc); - } - } -} - -/*********************************************************************** - * LBItemFromPt (COMCTL32.14) - * - * Gets the index of the ListBox item under the specified point, - * scrolling if bAutoScroll is TRUE and pt is outside of the ListBox. - * - * RETURNS - * The ListBox item ID if pt is over a list item or -1 otherwise. - */ -INT WINAPI LBItemFromPt (HWND hwndLB, POINT pt, BOOL bAutoScroll) -{ - RECT rcClient; - INT nIndex; - DWORD dwScrollTime; - - TRACE("(%p %ld x %ld %s)\n", - hwndLB, pt.x, pt.y, bAutoScroll ? "TRUE" : "FALSE"); - - ScreenToClient (hwndLB, &pt); - GetClientRect (hwndLB, &rcClient); - nIndex = (INT)SendMessageA (hwndLB, LB_GETTOPINDEX, 0, 0); - - if (PtInRect (&rcClient, pt)) - { - /* point is inside -- get the item index */ - while (TRUE) - { - if (SendMessageA (hwndLB, LB_GETITEMRECT, nIndex, (LPARAM)&rcClient) == LB_ERR) - return -1; - - if (PtInRect (&rcClient, pt)) - return nIndex; - - nIndex++; - } - } - else - { - /* point is outside */ - if (!bAutoScroll) - return -1; - - if ((pt.x > rcClient.right) || (pt.x < rcClient.left)) - return -1; - - if (pt.y < 0) - nIndex--; - else - nIndex++; - - dwScrollTime = GetTickCount (); - - if ((dwScrollTime - dwLastScrollTime) < DRAGLIST_SCROLLPERIOD) - return -1; - - dwLastScrollTime = dwScrollTime; - - SendMessageA (hwndLB, LB_SETTOPINDEX, (WPARAM)nIndex, 0); - } - - return -1; -} diff --git a/reactos/lib/comctl32/flatsb.c b/reactos/lib/comctl32/flatsb.c deleted file mode 100644 index cd15e3e1e5a..00000000000 --- a/reactos/lib/comctl32/flatsb.c +++ /dev/null @@ -1,292 +0,0 @@ -/* - * Flat Scrollbar control - * - * Copyright 1998, 1999 Eric Kohl - * Copyright 1998 Alex Priem - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2.1 of the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - * - * NOTES - * This is just a dummy control. An author is needed! Any volunteers? - * I will only improve this control once in a while. - * Eric - * - * TODO: - * - All messages. - * - All notifications. - * - */ - -#include -#include -#include "windef.h" -#include "winbase.h" -#include "winerror.h" -#include "wingdi.h" -#include "winuser.h" -#include "winnls.h" -#include "commctrl.h" -#include "wine/debug.h" - -WINE_DEFAULT_DEBUG_CHANNEL(commctrl); - -typedef struct -{ - DWORD dwDummy; /* just to keep the compiler happy ;-) */ -} FLATSB_INFO, *LPFLATSB_INFO; - -#define FlatSB_GetInfoPtr(hwnd) ((FLATSB_INFO*)GetWindowLongPtrW (hwnd, 0)) - - -/*********************************************************************** - * InitializeFlatSB (COMCTL32.@) - * - * Initializes flat scroll bars for the specified window. - * - * RETURNS - * Success: Non-zero - * Failure: Zero - * - * NOTES - * Subclasses specified window so that flat scroll bars may be drawn - * and used. - */ -BOOL WINAPI InitializeFlatSB(HWND hwnd) -{ - TRACE("[%p]\n", hwnd); - return FALSE; -} - -/*********************************************************************** - * UninitializeFlatSB (COMCTL32.@) - * - * Uninitializes flat scroll bars for the specified window. - * - * RETURNS - * E_FAIL if one of the scroll bars is currently in use - * S_FALSE if InitializeFlatSB() was never called on this hwnd - * S_OK otherwise - * - * NOTES - * Removes any subclassing on the specified window so that regular - * scroll bars are drawn and used. - */ -HRESULT WINAPI UninitializeFlatSB(HWND hwnd) -{ - TRACE("[%p]\n", hwnd); - return S_FALSE; -} - -/*********************************************************************** - * FlatSB_GetScrollProp (COMCTL32.@) - * - * Retrieves flat-scroll-bar-specific properties for the specified window. - * - * RETURNS - * nonzero if successful, or zero otherwise. If index is WSB_PROP_HSTYLE, - * the return is nonzero if InitializeFlatSB has been called for this window, or - * zero otherwise. - */ -BOOL WINAPI -FlatSB_GetScrollProp(HWND hwnd, INT propIndex, LPINT prop) -{ - TRACE("[%p] propIndex=%d\n", hwnd, propIndex); - return FALSE; -} - -/*********************************************************************** - * FlatSB_SetScrollProp (COMCTL32.@) - * - * Sets flat-scroll-bar-specific properties for the specified window. - * - * RETURNS - * Success: Non-zero - * Failure: Zero - */ -BOOL WINAPI -FlatSB_SetScrollProp(HWND hwnd, UINT index, INT newValue, BOOL flag) -{ - TRACE("[%p] index=%u newValue=%d flag=%d\n", hwnd, index, newValue, flag); - return FALSE; -} - -/*********************************************************************** - * From the Microsoft docs: - * "If flat scroll bars haven't been initialized for the - * window, the flat scroll bar APIs will defer to the corresponding - * standard APIs. This allows the developer to turn flat scroll - * bars on and off without having to write conditional code." - * - * So, if we just call the standard functions until we implement - * the flat scroll bar functions, flat scroll bars will show up and - * behave properly, as though they had simply not been setup to - * have flat properties. - * - * Susan - * - */ - -/*********************************************************************** - * FlatSB_EnableScrollBar (COMCTL32.@) - * - * See EnableScrollBar. - */ -BOOL WINAPI -FlatSB_EnableScrollBar(HWND hwnd, int nBar, UINT flags) -{ - return EnableScrollBar(hwnd, nBar, flags); -} - -/*********************************************************************** - * FlatSB_ShowScrollBar (COMCTL32.@) - * - * See ShowScrollBar. - */ -BOOL WINAPI -FlatSB_ShowScrollBar(HWND hwnd, int nBar, BOOL fShow) -{ - return ShowScrollBar(hwnd, nBar, fShow); -} - -/*********************************************************************** - * FlatSB_GetScrollRange (COMCTL32.@) - * - * See GetScrollRange. - */ -BOOL WINAPI -FlatSB_GetScrollRange(HWND hwnd, int nBar, LPINT min, LPINT max) -{ - return GetScrollRange(hwnd, nBar, min, max); -} - -/*********************************************************************** - * FlatSB_GetScrollInfo (COMCTL32.@) - * - * See GetScrollInfo. - */ -BOOL WINAPI -FlatSB_GetScrollInfo(HWND hwnd, int nBar, LPSCROLLINFO info) -{ - return GetScrollInfo(hwnd, nBar, info); -} - -/*********************************************************************** - * FlatSB_GetScrollPos (COMCTL32.@) - * - * See GetScrollPos. - */ -INT WINAPI -FlatSB_GetScrollPos(HWND hwnd, int nBar) -{ - return GetScrollPos(hwnd, nBar); -} - -/*********************************************************************** - * FlatSB_SetScrollPos (COMCTL32.@) - * - * See SetScrollPos. - */ -INT WINAPI -FlatSB_SetScrollPos(HWND hwnd, int nBar, INT pos, BOOL bRedraw) -{ - return SetScrollPos(hwnd, nBar, pos, bRedraw); -} - -/*********************************************************************** - * FlatSB_SetScrollInfo (COMCTL32.@) - * - * See SetScrollInfo. - */ -INT WINAPI -FlatSB_SetScrollInfo(HWND hwnd, int nBar, LPSCROLLINFO info, BOOL bRedraw) -{ - return SetScrollInfo(hwnd, nBar, info, bRedraw); -} - -/*********************************************************************** - * FlatSB_SetScrollRange (COMCTL32.@) - * - * See SetScrollRange. - */ -INT WINAPI -FlatSB_SetScrollRange(HWND hwnd, int nBar, INT min, INT max, BOOL bRedraw) -{ - return SetScrollRange(hwnd, nBar, min, max, bRedraw); -} - - -static LRESULT -FlatSB_Create (HWND hwnd, WPARAM wParam, LPARAM lParam) -{ - TRACE("[%p] wParam=%04x lParam=%08lx\n", hwnd, wParam, lParam); - return 0; -} - - -static LRESULT -FlatSB_Destroy (HWND hwnd, WPARAM wParam, LPARAM lParam) -{ - TRACE("[%p] wParam=%04x lParam=%08lx\n", hwnd, wParam, lParam); - return 0; -} - - -static LRESULT WINAPI -FlatSB_WindowProc (HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam) -{ - if (!FlatSB_GetInfoPtr(hwnd) && (uMsg != WM_CREATE)) - return DefWindowProcA( hwnd, uMsg, wParam, lParam ); - - switch (uMsg) - { - case WM_CREATE: - return FlatSB_Create (hwnd, wParam, lParam); - - case WM_DESTROY: - return FlatSB_Destroy (hwnd, wParam, lParam); - - default: - if ((uMsg >= WM_USER) && (uMsg < WM_APP)) - ERR("unknown msg %04x wp=%08x lp=%08lx\n", - uMsg, wParam, lParam); - return DefWindowProcA (hwnd, uMsg, wParam, lParam); - } - return 0; -} - - -VOID -FLATSB_Register (void) -{ - WNDCLASSA wndClass; - - ZeroMemory (&wndClass, sizeof(WNDCLASSA)); - wndClass.style = CS_GLOBALCLASS; - wndClass.lpfnWndProc = FlatSB_WindowProc; - wndClass.cbClsExtra = 0; - wndClass.cbWndExtra = sizeof(FLATSB_INFO *); - wndClass.hCursor = LoadCursorA (0, (LPSTR)IDC_ARROW); - wndClass.hbrBackground = (HBRUSH)(COLOR_WINDOW + 1); - wndClass.lpszClassName = FLATSB_CLASSA; - - RegisterClassA (&wndClass); -} - - -VOID -FLATSB_Unregister (void) -{ - UnregisterClassA (FLATSB_CLASSA, NULL); -} diff --git a/reactos/lib/comctl32/header.c b/reactos/lib/comctl32/header.c deleted file mode 100644 index 743725c7609..00000000000 --- a/reactos/lib/comctl32/header.c +++ /dev/null @@ -1,1859 +0,0 @@ -/* - * Header control - * - * Copyright 1998 Eric Kohl - * Copyright 2000 Eric Kohl for CodeWeavers - * Copyright 2003 Maxime Bellenge - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2.1 of the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - * - * TODO: - * - Imagelist support (partially). - * - Callback items (under construction). - * - Hottrack support (partially). - * - Custom draw support (including Notifications). - * - Drag and Drop support (including Notifications). - * - New messages. - * - Use notification format - * - Correct the order maintenance code to preserve valid order - * - */ - -#include -#include - -#include "windef.h" -#include "winbase.h" -#include "wine/unicode.h" -#include "wingdi.h" -#include "winuser.h" -#include "winnls.h" -#include "commctrl.h" -#include "comctl32.h" -#include "imagelist.h" -#include "wine/debug.h" - -WINE_DEFAULT_DEBUG_CHANNEL(header); - -typedef struct -{ - INT cxy; - HBITMAP hbm; - LPWSTR pszText; - INT fmt; - LPARAM lParam; - INT iImage; - INT iOrder; /* see documentation of HD_ITEM */ - - BOOL bDown; /* is item pressed? (used for drawing) */ - RECT rect; /* bounding rectangle of the item */ -} HEADER_ITEM; - - -typedef struct -{ - HWND hwndNotify; /* Owner window to send notifications to */ - INT nNotifyFormat; /* format used for WM_NOTIFY messages */ - UINT uNumItem; /* number of items (columns) */ - INT nHeight; /* height of the header (pixels) */ - HFONT hFont; /* handle to the current font */ - HCURSOR hcurArrow; /* handle to the arrow cursor */ - HCURSOR hcurDivider; /* handle to a cursor (used over dividers) <-|-> */ - HCURSOR hcurDivopen; /* handle to a cursor (used over dividers) <-||-> */ - BOOL bCaptured; /* Is the mouse captured? */ - BOOL bPressed; /* Is a header item pressed (down)? */ - BOOL bTracking; /* Is in tracking mode? */ - BOOL bUnicode; /* Unicode flag */ - INT iMoveItem; /* index of tracked item. (Tracking mode) */ - INT xTrackOffset; /* distance between the right side of the tracked item and the cursor */ - INT xOldTrack; /* track offset (see above) after the last WM_MOUSEMOVE */ - INT nOldWidth; /* width of a sizing item after the last WM_MOUSEMOVE */ - INT iHotItem; /* index of hot item (cursor is over this item) */ - INT iMargin; /* width of the margin that surrounds a bitmap */ - - HIMAGELIST himl; /* handle to a image list (may be 0) */ - HEADER_ITEM *items; /* pointer to array of HEADER_ITEM's */ - BOOL bRectsValid; /* validity flag for bounding rectangles */ -} HEADER_INFO; - - -#define VERT_BORDER 3 -#define DIVIDER_WIDTH 10 - -#define HEADER_GetInfoPtr(hwnd) ((HEADER_INFO *)GetWindowLongPtrW(hwnd,0)) - - -inline static LRESULT -HEADER_IndexToOrder (HWND hwnd, INT iItem) -{ - HEADER_INFO *infoPtr = HEADER_GetInfoPtr (hwnd); - HEADER_ITEM *lpItem = &infoPtr->items[iItem]; - return lpItem->iOrder; -} - - -static INT -HEADER_OrderToIndex(HWND hwnd, WPARAM wParam) -{ - HEADER_INFO *infoPtr = HEADER_GetInfoPtr (hwnd); - INT iorder = (INT)wParam; - UINT i; - - if ((iorder <0) || iorder >infoPtr->uNumItem) - return iorder; - for (i=0; iuNumItem; i++) - if (HEADER_IndexToOrder(hwnd,i) == iorder) - return i; - return iorder; -} - -static void -HEADER_SetItemBounds (HWND hwnd) -{ - HEADER_INFO *infoPtr = HEADER_GetInfoPtr (hwnd); - HEADER_ITEM *phdi; - RECT rect; - unsigned int i; - int x; - - infoPtr->bRectsValid = TRUE; - - if (infoPtr->uNumItem == 0) - return; - - GetClientRect (hwnd, &rect); - - x = rect.left; - for (i = 0; i < infoPtr->uNumItem; i++) { - phdi = &infoPtr->items[HEADER_OrderToIndex(hwnd,i)]; - phdi->rect.top = rect.top; - phdi->rect.bottom = rect.bottom; - phdi->rect.left = x; - phdi->rect.right = phdi->rect.left + ((phdi->cxy>0)?phdi->cxy:0); - x = phdi->rect.right; - } -} - -static LRESULT -HEADER_Size (HWND hwnd, WPARAM wParam) -{ - HEADER_INFO *infoPtr = HEADER_GetInfoPtr (hwnd); - - infoPtr->bRectsValid = FALSE; - - return 0; -} - - -static INT -HEADER_DrawItem (HWND hwnd, HDC hdc, INT iItem, BOOL bHotTrack) -{ - HEADER_INFO *infoPtr = HEADER_GetInfoPtr (hwnd); - HEADER_ITEM *phdi = &infoPtr->items[iItem]; - RECT r; - INT oldBkMode; - - TRACE("DrawItem(iItem %d bHotTrack %d unicode flag %d)\n", iItem, bHotTrack, infoPtr->bUnicode); - - if (!infoPtr->bRectsValid) - HEADER_SetItemBounds(hwnd); - - r = phdi->rect; - if (r.right - r.left == 0) - return phdi->rect.right; - - if (GetWindowLongA (hwnd, GWL_STYLE) & HDS_BUTTONS) { - if (phdi->bDown) { - DrawEdge (hdc, &r, BDR_RAISEDOUTER, - BF_RECT | BF_FLAT | BF_MIDDLE | BF_ADJUST); - r.left += 2; - r.top += 2; - } - else - DrawEdge (hdc, &r, EDGE_RAISED, - BF_RECT | BF_SOFT | BF_MIDDLE | BF_ADJUST); - } - else - DrawEdge (hdc, &r, EDGE_ETCHED, BF_BOTTOM | BF_RIGHT | BF_ADJUST); - - if (phdi->fmt & HDF_OWNERDRAW) { - DRAWITEMSTRUCT dis; - dis.CtlType = ODT_HEADER; - dis.CtlID = GetWindowLongPtrW (hwnd, GWLP_ID); - dis.itemID = iItem; - dis.itemAction = ODA_DRAWENTIRE; - dis.itemState = phdi->bDown ? ODS_SELECTED : 0; - dis.hwndItem = hwnd; - dis.hDC = hdc; - dis.rcItem = r; - dis.itemData = phdi->lParam; - oldBkMode = SetBkMode(hdc, TRANSPARENT); - SendMessageA (infoPtr->hwndNotify, WM_DRAWITEM, - (WPARAM)dis.CtlID, (LPARAM)&dis); - if (oldBkMode != TRANSPARENT) - SetBkMode(hdc, oldBkMode); - } - else { - UINT uTextJustify = DT_LEFT; - - if ((phdi->fmt & HDF_JUSTIFYMASK) == HDF_CENTER) - uTextJustify = DT_CENTER; - else if ((phdi->fmt & HDF_JUSTIFYMASK) == HDF_RIGHT) - uTextJustify = DT_RIGHT; - - if ((phdi->fmt & HDF_BITMAP) && !(phdi->fmt & HDF_BITMAP_ON_RIGHT) && (phdi->hbm)) { - BITMAP bmp; - HDC hdcBitmap; - INT yD, yS, cx, cy, rx, ry; - - GetObjectA (phdi->hbm, sizeof(BITMAP), (LPVOID)&bmp); - - ry = r.bottom - r.top; - rx = r.right - r.left; - - if (ry >= bmp.bmHeight) { - cy = bmp.bmHeight; - yD = r.top + (ry - bmp.bmHeight) / 2; - yS = 0; - } - else { - cy = ry; - yD = r.top; - yS = (bmp.bmHeight - ry) / 2; - - } - - if (rx >= bmp.bmWidth + infoPtr->iMargin) { - cx = bmp.bmWidth; - } - else { - cx = rx - infoPtr->iMargin; - } - - hdcBitmap = CreateCompatibleDC (hdc); - SelectObject (hdcBitmap, phdi->hbm); - BitBlt (hdc, r.left + infoPtr->iMargin, yD, cx, cy, hdcBitmap, 0, yS, SRCCOPY); - DeleteDC (hdcBitmap); - - r.left += (bmp.bmWidth + infoPtr->iMargin); - } - - - if ((phdi->fmt & HDF_BITMAP) && (phdi->fmt & HDF_BITMAP_ON_RIGHT) && (phdi->hbm)) { - BITMAP bmp; - HDC hdcBitmap; - INT xD, yD, yS, cx, cy, rx, ry, tx; - RECT textRect; - - GetObjectA (phdi->hbm, sizeof(BITMAP), (LPVOID)&bmp); - - textRect = r; - if (phdi->fmt & HDF_STRING) { - DrawTextW (hdc, phdi->pszText, -1, - &textRect, DT_LEFT|DT_VCENTER|DT_SINGLELINE|DT_CALCRECT); - tx = textRect.right - textRect.left; - } - else - tx = 0; - ry = r.bottom - r.top; - rx = r.right - r.left; - - if (ry >= bmp.bmHeight) { - cy = bmp.bmHeight; - yD = r.top + (ry - bmp.bmHeight) / 2; - yS = 0; - } - else { - cy = ry; - yD = r.top; - yS = (bmp.bmHeight - ry) / 2; - - } - - if (r.left + tx + bmp.bmWidth + 2*infoPtr->iMargin <= r.right) { - cx = bmp.bmWidth; - xD = r.left + tx + infoPtr->iMargin; - } - else { - if (rx >= bmp.bmWidth + infoPtr->iMargin ) { - cx = bmp.bmWidth; - xD = r.right - bmp.bmWidth - infoPtr->iMargin; - r.right = xD - infoPtr->iMargin; - } - else { - cx = rx - infoPtr->iMargin; - xD = r.left; - r.right = r.left; - } - } - - hdcBitmap = CreateCompatibleDC (hdc); - SelectObject (hdcBitmap, phdi->hbm); - BitBlt (hdc, xD, yD, cx, cy, hdcBitmap, 0, yS, SRCCOPY); - DeleteDC (hdcBitmap); - } - - if ((phdi->fmt & HDF_IMAGE) && !(phdi->fmt & HDF_BITMAP_ON_RIGHT) && (infoPtr->himl)) { - r.left += infoPtr->iMargin; - ImageList_DrawEx(infoPtr->himl, phdi->iImage, hdc, r.left, r.top + (r.bottom-r.top- infoPtr->himl->cy)/2, - infoPtr->himl->cx, r.bottom-r.top, CLR_DEFAULT, CLR_DEFAULT, 0); - r.left += infoPtr->himl->cx; - } - - if ((phdi->fmt & HDF_IMAGE) && (phdi->fmt & HDF_BITMAP_ON_RIGHT) && (infoPtr->himl)) { - RECT textRect; - INT tx; - - textRect = r; - if (phdi->fmt & HDF_STRING) { - DrawTextW (hdc, phdi->pszText, -1, - &textRect, DT_LEFT|DT_VCENTER|DT_SINGLELINE|DT_CALCRECT); - tx = textRect.right - textRect.left; - } - else - tx = 0; - ImageList_DrawEx(infoPtr->himl, phdi->iImage, hdc, r.left + tx + 2*infoPtr->iMargin, - r.top + (r.bottom-r.top-infoPtr->himl->cy)/2, infoPtr->himl->cx, r.bottom-r.top, - CLR_DEFAULT, CLR_DEFAULT, 0); - } - - if (((phdi->fmt & HDF_STRING) - || (!(phdi->fmt & (HDF_OWNERDRAW|HDF_STRING|HDF_BITMAP| - HDF_BITMAP_ON_RIGHT|HDF_IMAGE)))) /* no explicit format specified? */ - && (phdi->pszText)) { - oldBkMode = SetBkMode(hdc, TRANSPARENT); - r.left += infoPtr->iMargin; - r.right -= infoPtr->iMargin; - SetTextColor (hdc, (bHotTrack) ? COLOR_HIGHLIGHT : COLOR_BTNTEXT); - DrawTextW (hdc, phdi->pszText, -1, - &r, uTextJustify|DT_END_ELLIPSIS|DT_VCENTER|DT_SINGLELINE); - if (oldBkMode != TRANSPARENT) - SetBkMode(hdc, oldBkMode); - } - }/*Ownerdrawn*/ - - return phdi->rect.right; -} - - -static void -HEADER_Refresh (HWND hwnd, HDC hdc) -{ - HEADER_INFO *infoPtr = HEADER_GetInfoPtr (hwnd); - HFONT hFont, hOldFont; - RECT rect; - HBRUSH hbrBk; - UINT i; - INT x; - - /* get rect for the bar, adjusted for the border */ - GetClientRect (hwnd, &rect); - - hFont = infoPtr->hFont ? infoPtr->hFont : GetStockObject (SYSTEM_FONT); - hOldFont = SelectObject (hdc, hFont); - - /* draw Background */ - hbrBk = GetSysColorBrush(COLOR_3DFACE); - FillRect(hdc, &rect, hbrBk); - - x = rect.left; - for (i = 0; i < infoPtr->uNumItem; i++) { - x = HEADER_DrawItem (hwnd, hdc, HEADER_OrderToIndex(hwnd,i), FALSE); - } - - if ((x <= rect.right) && (infoPtr->uNumItem > 0)) { - rect.left = x; - if (GetWindowLongA (hwnd, GWL_STYLE) & HDS_BUTTONS) - DrawEdge (hdc, &rect, EDGE_RAISED, BF_TOP|BF_LEFT|BF_BOTTOM|BF_SOFT); - else - DrawEdge (hdc, &rect, EDGE_ETCHED, BF_BOTTOM); - } - - SelectObject (hdc, hOldFont); -} - - -static void -HEADER_RefreshItem (HWND hwnd, HDC hdc, INT iItem) -{ - HEADER_INFO *infoPtr = HEADER_GetInfoPtr (hwnd); - HFONT hFont, hOldFont; - - hFont = infoPtr->hFont ? infoPtr->hFont : GetStockObject (SYSTEM_FONT); - hOldFont = SelectObject (hdc, hFont); - HEADER_DrawItem (hwnd, hdc, iItem, FALSE); - SelectObject (hdc, hOldFont); -} - - -static void -HEADER_InternalHitTest (HWND hwnd, LPPOINT lpPt, UINT *pFlags, INT *pItem) -{ - HEADER_INFO *infoPtr = HEADER_GetInfoPtr (hwnd); - RECT rect, rcTest; - UINT iCount; - INT width; - BOOL bNoWidth; - - GetClientRect (hwnd, &rect); - - *pFlags = 0; - bNoWidth = FALSE; - if (PtInRect (&rect, *lpPt)) - { - if (infoPtr->uNumItem == 0) { - *pFlags |= HHT_NOWHERE; - *pItem = 1; - TRACE("NOWHERE\n"); - return; - } - else { - /* somewhere inside */ - for (iCount = 0; iCount < infoPtr->uNumItem; iCount++) { - rect = infoPtr->items[iCount].rect; - width = rect.right - rect.left; - if (width == 0) { - bNoWidth = TRUE; - continue; - } - if (PtInRect (&rect, *lpPt)) { - if (width <= 2 * DIVIDER_WIDTH) { - *pFlags |= HHT_ONHEADER; - *pItem = iCount; - TRACE("ON HEADER %d\n", iCount); - return; - } - if (iCount > 0) { - rcTest = rect; - rcTest.right = rcTest.left + DIVIDER_WIDTH; - if (PtInRect (&rcTest, *lpPt)) { - if (bNoWidth) { - *pFlags |= HHT_ONDIVOPEN; - *pItem = iCount - 1; - TRACE("ON DIVOPEN %d\n", *pItem); - return; - } - else { - *pFlags |= HHT_ONDIVIDER; - *pItem = iCount - 1; - TRACE("ON DIVIDER %d\n", *pItem); - return; - } - } - } - rcTest = rect; - rcTest.left = rcTest.right - DIVIDER_WIDTH; - if (PtInRect (&rcTest, *lpPt)) { - *pFlags |= HHT_ONDIVIDER; - *pItem = iCount; - TRACE("ON DIVIDER %d\n", *pItem); - return; - } - - *pFlags |= HHT_ONHEADER; - *pItem = iCount; - TRACE("ON HEADER %d\n", iCount); - return; - } - } - - /* check for last divider part (on nowhere) */ - rect = infoPtr->items[infoPtr->uNumItem-1].rect; - rect.left = rect.right; - rect.right += DIVIDER_WIDTH; - if (PtInRect (&rect, *lpPt)) { - if (bNoWidth) { - *pFlags |= HHT_ONDIVOPEN; - *pItem = infoPtr->uNumItem - 1; - TRACE("ON DIVOPEN %d\n", *pItem); - return; - } - else { - *pFlags |= HHT_ONDIVIDER; - *pItem = infoPtr->uNumItem-1; - TRACE("ON DIVIDER %d\n", *pItem); - return; - } - } - - *pFlags |= HHT_NOWHERE; - *pItem = 1; - TRACE("NOWHERE\n"); - return; - } - } - else { - if (lpPt->x < rect.left) { - TRACE("TO LEFT\n"); - *pFlags |= HHT_TOLEFT; - } - else if (lpPt->x > rect.right) { - TRACE("TO RIGHT\n"); - *pFlags |= HHT_TORIGHT; - } - - if (lpPt->y < rect.top) { - TRACE("ABOVE\n"); - *pFlags |= HHT_ABOVE; - } - else if (lpPt->y > rect.bottom) { - TRACE("BELOW\n"); - *pFlags |= HHT_BELOW; - } - } - - *pItem = 1; - TRACE("flags=0x%X\n", *pFlags); - return; -} - - -static void -HEADER_DrawTrackLine (HWND hwnd, HDC hdc, INT x) -{ - RECT rect; - HPEN hOldPen; - INT oldRop; - - GetClientRect (hwnd, &rect); - - hOldPen = SelectObject (hdc, GetStockObject (BLACK_PEN)); - oldRop = SetROP2 (hdc, R2_XORPEN); - MoveToEx (hdc, x, rect.top, NULL); - LineTo (hdc, x, rect.bottom); - SetROP2 (hdc, oldRop); - SelectObject (hdc, hOldPen); -} - - -static BOOL -HEADER_SendSimpleNotify (HWND hwnd, UINT code) -{ - HEADER_INFO *infoPtr = HEADER_GetInfoPtr (hwnd); - NMHDR nmhdr; - - nmhdr.hwndFrom = hwnd; - nmhdr.idFrom = GetWindowLongPtrW (hwnd, GWLP_ID); - nmhdr.code = code; - - return (BOOL)SendMessageA (infoPtr->hwndNotify, WM_NOTIFY, - (WPARAM)nmhdr.idFrom, (LPARAM)&nmhdr); -} - -static BOOL -HEADER_SendHeaderNotify (HWND hwnd, UINT code, INT iItem, INT mask) -{ - HEADER_INFO *infoPtr = HEADER_GetInfoPtr (hwnd); - NMHEADERA nmhdr; - HDITEMA nmitem; - - nmhdr.hdr.hwndFrom = hwnd; - nmhdr.hdr.idFrom = GetWindowLongPtrW (hwnd, GWLP_ID); - nmhdr.hdr.code = code; - nmhdr.iItem = iItem; - nmhdr.iButton = 0; - nmhdr.pitem = &nmitem; - nmitem.mask = mask; - nmitem.cxy = infoPtr->items[iItem].cxy; - nmitem.hbm = infoPtr->items[iItem].hbm; - nmitem.pszText = NULL; - nmitem.cchTextMax = 0; -/* nmitem.pszText = infoPtr->items[iItem].pszText; */ -/* nmitem.cchTextMax = infoPtr->items[iItem].cchTextMax; */ - nmitem.fmt = infoPtr->items[iItem].fmt; - nmitem.lParam = infoPtr->items[iItem].lParam; - nmitem.iOrder = infoPtr->items[iItem].iOrder; - nmitem.iImage = infoPtr->items[iItem].iImage; - - return (BOOL)SendMessageA (infoPtr->hwndNotify, WM_NOTIFY, - (WPARAM)nmhdr.hdr.idFrom, (LPARAM)&nmhdr); -} - - -static BOOL -HEADER_SendClickNotify (HWND hwnd, UINT code, INT iItem) -{ - HEADER_INFO *infoPtr = HEADER_GetInfoPtr (hwnd); - NMHEADERA nmhdr; - - nmhdr.hdr.hwndFrom = hwnd; - nmhdr.hdr.idFrom = GetWindowLongPtrW (hwnd, GWLP_ID); - nmhdr.hdr.code = code; - nmhdr.iItem = iItem; - nmhdr.iButton = 0; - nmhdr.pitem = NULL; - - return (BOOL)SendMessageA (infoPtr->hwndNotify, WM_NOTIFY, - (WPARAM)nmhdr.hdr.idFrom, (LPARAM)&nmhdr); -} - - -static LRESULT -HEADER_CreateDragImage (HWND hwnd, WPARAM wParam) -{ - FIXME("empty stub!\n"); - return 0; -} - - -static LRESULT -HEADER_DeleteItem (HWND hwnd, WPARAM wParam) -{ - HEADER_INFO *infoPtr = HEADER_GetInfoPtr(hwnd); - INT iItem = (INT)wParam; - - TRACE("[iItem=%d]\n", iItem); - - if ((iItem < 0) || (iItem >= (INT)infoPtr->uNumItem)) - return FALSE; - - if (infoPtr->uNumItem == 1) { - TRACE("Simple delete!\n"); - if (infoPtr->items[0].pszText) - Free (infoPtr->items[0].pszText); - Free (infoPtr->items); - infoPtr->items = 0; - infoPtr->uNumItem = 0; - } - else { - HEADER_ITEM *oldItems = infoPtr->items; - HEADER_ITEM *pItem; - INT i; - INT iOrder; - TRACE("Complex delete! [iItem=%d]\n", iItem); - - if (infoPtr->items[iItem].pszText) - Free (infoPtr->items[iItem].pszText); - iOrder = infoPtr->items[iItem].iOrder; - - infoPtr->uNumItem--; - infoPtr->items = Alloc (sizeof (HEADER_ITEM) * infoPtr->uNumItem); - /* pre delete copy */ - if (iItem > 0) { - memcpy (&infoPtr->items[0], &oldItems[0], - iItem * sizeof(HEADER_ITEM)); - } - - /* post delete copy */ - if (iItem < infoPtr->uNumItem) { - memcpy (&infoPtr->items[iItem], &oldItems[iItem+1], - (infoPtr->uNumItem - iItem) * sizeof(HEADER_ITEM)); - } - - /* Correct the orders */ - for (i=infoPtr->uNumItem, pItem = infoPtr->items; i; i--, pItem++) - { - if (pItem->iOrder > iOrder) - pItem->iOrder--; - } - Free (oldItems); - } - - HEADER_SetItemBounds (hwnd); - - InvalidateRect(hwnd, NULL, FALSE); - - return TRUE; -} - - -static LRESULT -HEADER_GetImageList (HWND hwnd) -{ - HEADER_INFO *infoPtr = HEADER_GetInfoPtr (hwnd); - - return (LRESULT)infoPtr->himl; -} - - -static LRESULT -HEADER_GetItemA (HWND hwnd, WPARAM wParam, LPARAM lParam) -{ - HEADER_INFO *infoPtr = HEADER_GetInfoPtr (hwnd); - HDITEMA *phdi = (HDITEMA*)lParam; - INT nItem = (INT)wParam; - HEADER_ITEM *lpItem; - - if (!phdi) - return FALSE; - if ((nItem < 0) || (nItem >= (INT)infoPtr->uNumItem)) - return FALSE; - - TRACE("[nItem=%d]\n", nItem); - - if (phdi->mask == 0) - return TRUE; - - lpItem = &infoPtr->items[nItem]; - if (phdi->mask & HDI_BITMAP) - phdi->hbm = lpItem->hbm; - - if (phdi->mask & HDI_FORMAT) - phdi->fmt = lpItem->fmt; - - if (phdi->mask & HDI_WIDTH) - phdi->cxy = lpItem->cxy; - - if (phdi->mask & HDI_LPARAM) - phdi->lParam = lpItem->lParam; - - if (phdi->mask & HDI_TEXT) { - if (lpItem->pszText != LPSTR_TEXTCALLBACKW) { - if (lpItem->pszText) - WideCharToMultiByte (CP_ACP, 0, lpItem->pszText, -1, - phdi->pszText, phdi->cchTextMax, NULL, NULL); - else - *phdi->pszText = 0; - } - else - phdi->pszText = LPSTR_TEXTCALLBACKA; - } - - if (phdi->mask & HDI_IMAGE) - phdi->iImage = lpItem->iImage; - - if (phdi->mask & HDI_ORDER) - phdi->iOrder = lpItem->iOrder; - - return TRUE; -} - - -static LRESULT -HEADER_GetItemW (HWND hwnd, WPARAM wParam, LPARAM lParam) -{ - HEADER_INFO *infoPtr = HEADER_GetInfoPtr (hwnd); - HDITEMW *phdi = (HDITEMW*)lParam; - INT nItem = (INT)wParam; - HEADER_ITEM *lpItem; - - if (!phdi) - return FALSE; - if ((nItem < 0) || (nItem >= (INT)infoPtr->uNumItem)) - return FALSE; - - TRACE("[nItem=%d]\n", nItem); - - if (phdi->mask == 0) - return TRUE; - - lpItem = &infoPtr->items[nItem]; - if (phdi->mask & HDI_BITMAP) - phdi->hbm = lpItem->hbm; - - if (phdi->mask & HDI_FORMAT) - phdi->fmt = lpItem->fmt; - - if (phdi->mask & HDI_WIDTH) - phdi->cxy = lpItem->cxy; - - if (phdi->mask & HDI_LPARAM) - phdi->lParam = lpItem->lParam; - - if (phdi->mask & HDI_TEXT) { - if (lpItem->pszText != LPSTR_TEXTCALLBACKW) { - if (lpItem->pszText) - lstrcpynW (phdi->pszText, lpItem->pszText, phdi->cchTextMax); - else - *phdi->pszText = 0; - } - else - phdi->pszText = LPSTR_TEXTCALLBACKW; - } - - if (phdi->mask & HDI_IMAGE) - phdi->iImage = lpItem->iImage; - - if (phdi->mask & HDI_ORDER) - phdi->iOrder = lpItem->iOrder; - - return TRUE; -} - - -inline static LRESULT -HEADER_GetItemCount (HWND hwnd) -{ - HEADER_INFO *infoPtr = HEADER_GetInfoPtr (hwnd); - return infoPtr->uNumItem; -} - - -static LRESULT -HEADER_GetItemRect (HWND hwnd, WPARAM wParam, LPARAM lParam) -{ - HEADER_INFO *infoPtr = HEADER_GetInfoPtr (hwnd); - INT iItem = (INT)wParam; - LPRECT lpRect = (LPRECT)lParam; - - if ((iItem < 0) || (iItem >= (INT)infoPtr->uNumItem)) - return FALSE; - - lpRect->left = infoPtr->items[iItem].rect.left; - lpRect->right = infoPtr->items[iItem].rect.right; - lpRect->top = infoPtr->items[iItem].rect.top; - lpRect->bottom = infoPtr->items[iItem].rect.bottom; - - return TRUE; -} - - -static LRESULT -HEADER_GetOrderArray(HWND hwnd, WPARAM wParam, LPARAM lParam) -{ - int i; - LPINT order = (LPINT) lParam; - HEADER_INFO *infoPtr = HEADER_GetInfoPtr (hwnd); - - if ((unsigned int)wParam uNumItem) - return FALSE; - for (i=0; i<(int)wParam; i++) - *order++=HEADER_OrderToIndex(hwnd,i); - return TRUE; -} - -static LRESULT -HEADER_SetOrderArray(HWND hwnd, WPARAM wParam, LPARAM lParam) -{ - int i; - LPINT order = (LPINT) lParam; - HEADER_INFO *infoPtr = HEADER_GetInfoPtr (hwnd); - HEADER_ITEM *lpItem; - - if ((unsigned int)wParam uNumItem) - return FALSE; - for (i=0; i<(int)wParam; i++) - { - lpItem = &infoPtr->items[*order++]; - lpItem->iOrder=i; - } - infoPtr->bRectsValid=0; - InvalidateRect(hwnd, NULL, FALSE); - return TRUE; -} - -inline static LRESULT -HEADER_GetUnicodeFormat (HWND hwnd) -{ - HEADER_INFO *infoPtr = HEADER_GetInfoPtr (hwnd); - return infoPtr->bUnicode; -} - - -static LRESULT -HEADER_HitTest (HWND hwnd, WPARAM wParam, LPARAM lParam) -{ - LPHDHITTESTINFO phti = (LPHDHITTESTINFO)lParam; - - HEADER_InternalHitTest (hwnd, &phti->pt, &phti->flags, &phti->iItem); - - if (phti->flags == HHT_NOWHERE) - return -1; - else - return phti->iItem; -} - - -static LRESULT -HEADER_InsertItemA (HWND hwnd, WPARAM wParam, LPARAM lParam) -{ - HEADER_INFO *infoPtr = HEADER_GetInfoPtr (hwnd); - HDITEMA *phdi = (HDITEMA*)lParam; - INT nItem = (INT)wParam; - HEADER_ITEM *lpItem; - INT len, iOrder; - UINT i; - - if ((phdi == NULL) || (nItem < 0)) - return -1; - - if (nItem > infoPtr->uNumItem) - nItem = infoPtr->uNumItem; - - iOrder = (phdi->mask & HDI_ORDER) ? phdi->iOrder : nItem; - - if (infoPtr->uNumItem == 0) { - infoPtr->items = Alloc (sizeof (HEADER_ITEM)); - infoPtr->uNumItem++; - } - else { - HEADER_ITEM *oldItems = infoPtr->items; - - infoPtr->uNumItem++; - infoPtr->items = Alloc (sizeof (HEADER_ITEM) * infoPtr->uNumItem); - if (nItem == 0) { - memcpy (&infoPtr->items[1], &oldItems[0], - (infoPtr->uNumItem-1) * sizeof(HEADER_ITEM)); - } - else - { - /* pre insert copy */ - if (nItem > 0) { - memcpy (&infoPtr->items[0], &oldItems[0], - nItem * sizeof(HEADER_ITEM)); - } - - /* post insert copy */ - if (nItem < infoPtr->uNumItem - 1) { - memcpy (&infoPtr->items[nItem+1], &oldItems[nItem], - (infoPtr->uNumItem - nItem - 1) * sizeof(HEADER_ITEM)); - } - } - - Free (oldItems); - } - - for (i=0; i < infoPtr->uNumItem; i++) - { - if (infoPtr->items[i].iOrder >= iOrder) - infoPtr->items[i].iOrder++; - } - - lpItem = &infoPtr->items[nItem]; - lpItem->bDown = FALSE; - - if (phdi->mask & HDI_WIDTH) - lpItem->cxy = phdi->cxy; - - if (phdi->mask & HDI_TEXT) { - if (!phdi->pszText) /* null pointer check */ - phdi->pszText = ""; - if (phdi->pszText != LPSTR_TEXTCALLBACKA) { - len = MultiByteToWideChar(CP_ACP, 0, phdi->pszText, -1, NULL, 0); - lpItem->pszText = Alloc( len*sizeof(WCHAR) ); - MultiByteToWideChar(CP_ACP, 0, phdi->pszText, -1, lpItem->pszText, len); - } - else - lpItem->pszText = LPSTR_TEXTCALLBACKW; - } - - if (phdi->mask & HDI_FORMAT) - lpItem->fmt = phdi->fmt; - - if (lpItem->fmt == 0) - lpItem->fmt = HDF_LEFT; - - if (!(lpItem->fmt & HDF_STRING) && (phdi->mask & HDI_TEXT)) - { - lpItem->fmt |= HDF_STRING; - } - if (phdi->mask & HDI_BITMAP) - lpItem->hbm = phdi->hbm; - - if (phdi->mask & HDI_LPARAM) - lpItem->lParam = phdi->lParam; - - if (phdi->mask & HDI_IMAGE) - lpItem->iImage = phdi->iImage; - - lpItem->iOrder = iOrder; - - HEADER_SetItemBounds (hwnd); - - InvalidateRect(hwnd, NULL, FALSE); - - return nItem; -} - - -static LRESULT -HEADER_InsertItemW (HWND hwnd, WPARAM wParam, LPARAM lParam) -{ - HEADER_INFO *infoPtr = HEADER_GetInfoPtr (hwnd); - HDITEMW *phdi = (HDITEMW*)lParam; - INT nItem = (INT)wParam; - HEADER_ITEM *lpItem; - INT len, iOrder; - UINT i; - - if ((phdi == NULL) || (nItem < 0)) - return -1; - - if (nItem > infoPtr->uNumItem) - nItem = infoPtr->uNumItem; - - iOrder = (phdi->mask & HDI_ORDER) ? phdi->iOrder : nItem; - - if (infoPtr->uNumItem == 0) { - infoPtr->items = Alloc (sizeof (HEADER_ITEM)); - infoPtr->uNumItem++; - } - else { - HEADER_ITEM *oldItems = infoPtr->items; - - infoPtr->uNumItem++; - infoPtr->items = Alloc (sizeof (HEADER_ITEM) * infoPtr->uNumItem); - if (nItem == 0) { - memcpy (&infoPtr->items[1], &oldItems[0], - (infoPtr->uNumItem-1) * sizeof(HEADER_ITEM)); - } - else - { - /* pre insert copy */ - if (nItem > 0) { - memcpy (&infoPtr->items[0], &oldItems[0], - nItem * sizeof(HEADER_ITEM)); - } - - /* post insert copy */ - if (nItem < infoPtr->uNumItem - 1) { - memcpy (&infoPtr->items[nItem+1], &oldItems[nItem], - (infoPtr->uNumItem - nItem - 1) * sizeof(HEADER_ITEM)); - } - } - - Free (oldItems); - } - - for (i=0; i < infoPtr->uNumItem; i++) - { - if (infoPtr->items[i].iOrder >= iOrder) - infoPtr->items[i].iOrder++; - } - - lpItem = &infoPtr->items[nItem]; - lpItem->bDown = FALSE; - - if (phdi->mask & HDI_WIDTH) - lpItem->cxy = phdi->cxy; - - if (phdi->mask & HDI_TEXT) { - WCHAR wide_null_char = 0; - if (!phdi->pszText) /* null pointer check */ - phdi->pszText = &wide_null_char; - if (phdi->pszText != LPSTR_TEXTCALLBACKW) { - len = strlenW (phdi->pszText); - lpItem->pszText = Alloc ((len+1)*sizeof(WCHAR)); - strcpyW (lpItem->pszText, phdi->pszText); - } - else - lpItem->pszText = LPSTR_TEXTCALLBACKW; - } - - if (phdi->mask & HDI_FORMAT) - lpItem->fmt = phdi->fmt; - - if (lpItem->fmt == 0) - lpItem->fmt = HDF_LEFT; - - if (!(lpItem->fmt &HDF_STRING) && (phdi->mask & HDI_TEXT)) - { - lpItem->fmt |= HDF_STRING; - } - if (phdi->mask & HDI_BITMAP) - lpItem->hbm = phdi->hbm; - - if (phdi->mask & HDI_LPARAM) - lpItem->lParam = phdi->lParam; - - if (phdi->mask & HDI_IMAGE) - lpItem->iImage = phdi->iImage; - - lpItem->iOrder = iOrder; - - HEADER_SetItemBounds (hwnd); - - InvalidateRect(hwnd, NULL, FALSE); - - return nItem; -} - - -static LRESULT -HEADER_Layout (HWND hwnd, WPARAM wParam, LPARAM lParam) -{ - HEADER_INFO *infoPtr = HEADER_GetInfoPtr (hwnd); - LPHDLAYOUT lpLayout = (LPHDLAYOUT)lParam; - - lpLayout->pwpos->hwnd = hwnd; - lpLayout->pwpos->hwndInsertAfter = 0; - lpLayout->pwpos->x = lpLayout->prc->left; - lpLayout->pwpos->y = lpLayout->prc->top; - lpLayout->pwpos->cx = lpLayout->prc->right - lpLayout->prc->left; - if (GetWindowLongA (hwnd, GWL_STYLE) & HDS_HIDDEN) - lpLayout->pwpos->cy = 0; - else { - lpLayout->pwpos->cy = infoPtr->nHeight; - lpLayout->prc->top += infoPtr->nHeight; - } - lpLayout->pwpos->flags = SWP_NOZORDER; - - TRACE("Layout x=%d y=%d cx=%d cy=%d\n", - lpLayout->pwpos->x, lpLayout->pwpos->y, - lpLayout->pwpos->cx, lpLayout->pwpos->cy); - - infoPtr->bRectsValid = FALSE; - - return TRUE; -} - - -static LRESULT -HEADER_SetImageList (HWND hwnd, HIMAGELIST himl) -{ - HEADER_INFO *infoPtr = HEADER_GetInfoPtr (hwnd); - HIMAGELIST himlOld; - - TRACE("(himl 0x%x)\n", (int)himl); - himlOld = infoPtr->himl; - infoPtr->himl = himl; - - /* FIXME: Refresh needed??? */ - - return (LRESULT)himlOld; -} - - -static LRESULT -HEADER_GetBitmapMargin(HWND hwnd) -{ - HEADER_INFO *infoPtr = HEADER_GetInfoPtr(hwnd); - - return infoPtr->iMargin; -} - -static LRESULT -HEADER_SetBitmapMargin(HWND hwnd, WPARAM wParam) -{ - HEADER_INFO *infoPtr = HEADER_GetInfoPtr (hwnd); - INT oldMargin = infoPtr->iMargin; - - infoPtr->iMargin = (INT)wParam; - - return oldMargin; -} - -static LRESULT -HEADER_SetItemA (HWND hwnd, WPARAM wParam, LPARAM lParam) -{ - HEADER_INFO *infoPtr = HEADER_GetInfoPtr (hwnd); - HDITEMA *phdi = (HDITEMA*)lParam; - INT nItem = (INT)wParam; - HEADER_ITEM *lpItem; - - if (phdi == NULL) - return FALSE; - if ((nItem < 0) || (nItem >= (INT)infoPtr->uNumItem)) - return FALSE; - - TRACE("[nItem=%d]\n", nItem); - - if (HEADER_SendHeaderNotify (hwnd, HDN_ITEMCHANGINGA, nItem, phdi->mask)) - return FALSE; - - lpItem = &infoPtr->items[nItem]; - if (phdi->mask & HDI_BITMAP) - lpItem->hbm = phdi->hbm; - - if (phdi->mask & HDI_FORMAT) - lpItem->fmt = phdi->fmt; - - if (phdi->mask & HDI_LPARAM) - lpItem->lParam = phdi->lParam; - - if (phdi->mask & HDI_TEXT) { - if (phdi->pszText != LPSTR_TEXTCALLBACKA) { - if (lpItem->pszText) { - Free (lpItem->pszText); - lpItem->pszText = NULL; - } - if (phdi->pszText) { - INT len = MultiByteToWideChar (CP_ACP,0,phdi->pszText,-1,NULL,0); - lpItem->pszText = Alloc( len*sizeof(WCHAR) ); - MultiByteToWideChar (CP_ACP,0,phdi->pszText,-1,lpItem->pszText,len); - } - } - else - lpItem->pszText = LPSTR_TEXTCALLBACKW; - } - - if (phdi->mask & HDI_WIDTH) - lpItem->cxy = phdi->cxy; - - if (phdi->mask & HDI_IMAGE) - lpItem->iImage = phdi->iImage; - - if (phdi->mask & HDI_ORDER) - { - lpItem->iOrder = phdi->iOrder; - } - else - lpItem->iOrder = nItem; - - HEADER_SendHeaderNotify (hwnd, HDN_ITEMCHANGEDA, nItem, phdi->mask); - - HEADER_SetItemBounds (hwnd); - - InvalidateRect(hwnd, NULL, FALSE); - - return TRUE; -} - - -static LRESULT -HEADER_SetItemW (HWND hwnd, WPARAM wParam, LPARAM lParam) -{ - HEADER_INFO *infoPtr = HEADER_GetInfoPtr (hwnd); - HDITEMW *phdi = (HDITEMW*)lParam; - INT nItem = (INT)wParam; - HEADER_ITEM *lpItem; - - if (phdi == NULL) - return FALSE; - if ((nItem < 0) || (nItem >= (INT)infoPtr->uNumItem)) - return FALSE; - - TRACE("[nItem=%d]\n", nItem); - - if (HEADER_SendHeaderNotify (hwnd, HDN_ITEMCHANGINGW, nItem, phdi->mask)) - return FALSE; - - lpItem = &infoPtr->items[nItem]; - if (phdi->mask & HDI_BITMAP) - lpItem->hbm = phdi->hbm; - - if (phdi->mask & HDI_FORMAT) - lpItem->fmt = phdi->fmt; - - if (phdi->mask & HDI_LPARAM) - lpItem->lParam = phdi->lParam; - - if (phdi->mask & HDI_TEXT) { - if (phdi->pszText != LPSTR_TEXTCALLBACKW) { - if (lpItem->pszText) { - Free (lpItem->pszText); - lpItem->pszText = NULL; - } - if (phdi->pszText) { - INT len = strlenW (phdi->pszText); - lpItem->pszText = Alloc ((len+1)*sizeof(WCHAR)); - strcpyW (lpItem->pszText, phdi->pszText); - } - } - else - lpItem->pszText = LPSTR_TEXTCALLBACKW; - } - - if (phdi->mask & HDI_WIDTH) - lpItem->cxy = phdi->cxy; - - if (phdi->mask & HDI_IMAGE) - lpItem->iImage = phdi->iImage; - - if (phdi->mask & HDI_ORDER) - { - lpItem->iOrder = phdi->iOrder; - } - else - lpItem->iOrder = nItem; - - HEADER_SendHeaderNotify(hwnd, HDN_ITEMCHANGEDW, nItem, phdi->mask); - - HEADER_SetItemBounds (hwnd); - - InvalidateRect(hwnd, NULL, FALSE); - - return TRUE; -} - -inline static LRESULT -HEADER_SetUnicodeFormat (HWND hwnd, WPARAM wParam) -{ - HEADER_INFO *infoPtr = HEADER_GetInfoPtr (hwnd); - BOOL bTemp = infoPtr->bUnicode; - - infoPtr->bUnicode = (BOOL)wParam; - - return bTemp; -} - - -static LRESULT -HEADER_Create (HWND hwnd, WPARAM wParam, LPARAM lParam) -{ - HEADER_INFO *infoPtr; - TEXTMETRICA tm; - HFONT hOldFont; - HDC hdc; - - infoPtr = (HEADER_INFO *)Alloc (sizeof(HEADER_INFO)); - SetWindowLongPtrA (hwnd, 0, (DWORD_PTR)infoPtr); - - infoPtr->hwndNotify = ((LPCREATESTRUCTA)lParam)->hwndParent; - infoPtr->uNumItem = 0; - infoPtr->hFont = 0; - infoPtr->items = 0; - infoPtr->bRectsValid = FALSE; - infoPtr->hcurArrow = LoadCursorA (0, (LPSTR)IDC_ARROW); - infoPtr->hcurDivider = LoadCursorA (COMCTL32_hModule, MAKEINTRESOURCEA(IDC_DIVIDER)); - infoPtr->hcurDivopen = LoadCursorA (COMCTL32_hModule, MAKEINTRESOURCEA(IDC_DIVIDEROPEN)); - infoPtr->bPressed = FALSE; - infoPtr->bTracking = FALSE; - infoPtr->iMoveItem = 0; - infoPtr->himl = 0; - infoPtr->iHotItem = -1; - infoPtr->bUnicode = IsWindowUnicode (hwnd); - infoPtr->iMargin = 3*GetSystemMetrics(SM_CXEDGE); - infoPtr->nNotifyFormat = - SendMessageA (infoPtr->hwndNotify, WM_NOTIFYFORMAT, (WPARAM)hwnd, NF_QUERY); - - hdc = GetDC (0); - hOldFont = SelectObject (hdc, GetStockObject (SYSTEM_FONT)); - GetTextMetricsA (hdc, &tm); - infoPtr->nHeight = tm.tmHeight + VERT_BORDER; - SelectObject (hdc, hOldFont); - ReleaseDC (0, hdc); - - return 0; -} - - -static LRESULT -HEADER_Destroy (HWND hwnd, WPARAM wParam, LPARAM lParam) -{ - HEADER_INFO *infoPtr = HEADER_GetInfoPtr (hwnd); - HEADER_ITEM *lpItem; - INT nItem; - - if (infoPtr->items) { - lpItem = infoPtr->items; - for (nItem = 0; nItem < infoPtr->uNumItem; nItem++, lpItem++) { - if ((lpItem->pszText) && (lpItem->pszText != LPSTR_TEXTCALLBACKW)) - Free (lpItem->pszText); - } - Free (infoPtr->items); - } - - if (infoPtr->himl) - ImageList_Destroy (infoPtr->himl); - - Free (infoPtr); - SetWindowLongPtrA (hwnd, 0, 0); - return 0; -} - - -static inline LRESULT -HEADER_GetFont (HWND hwnd) -{ - HEADER_INFO *infoPtr = HEADER_GetInfoPtr (hwnd); - - return (LRESULT)infoPtr->hFont; -} - - -static LRESULT -HEADER_LButtonDblClk (HWND hwnd, WPARAM wParam, LPARAM lParam) -{ - POINT pt; - UINT flags; - INT nItem; - - pt.x = (INT)LOWORD(lParam); - pt.y = (INT)HIWORD(lParam); - HEADER_InternalHitTest (hwnd, &pt, &flags, &nItem); - - if ((GetWindowLongA (hwnd, GWL_STYLE) & HDS_BUTTONS) && (flags == HHT_ONHEADER)) - HEADER_SendHeaderNotify (hwnd, HDN_ITEMDBLCLICKA, nItem,0); - else if ((flags == HHT_ONDIVIDER) || (flags == HHT_ONDIVOPEN)) - HEADER_SendHeaderNotify (hwnd, HDN_DIVIDERDBLCLICKA, nItem,0); - - return 0; -} - - -static LRESULT -HEADER_LButtonDown (HWND hwnd, WPARAM wParam, LPARAM lParam) -{ - HEADER_INFO *infoPtr = HEADER_GetInfoPtr (hwnd); - DWORD dwStyle = GetWindowLongA (hwnd, GWL_STYLE); - POINT pt; - UINT flags; - INT nItem; - HDC hdc; - - pt.x = (INT)LOWORD(lParam); - pt.y = (INT)HIWORD(lParam); - HEADER_InternalHitTest (hwnd, &pt, &flags, &nItem); - - if ((dwStyle & HDS_BUTTONS) && (flags == HHT_ONHEADER)) { - SetCapture (hwnd); - infoPtr->bCaptured = TRUE; - infoPtr->bPressed = TRUE; - infoPtr->iMoveItem = nItem; - - infoPtr->items[nItem].bDown = TRUE; - - /* Send WM_CUSTOMDRAW */ - hdc = GetDC (hwnd); - HEADER_RefreshItem (hwnd, hdc, nItem); - ReleaseDC (hwnd, hdc); - - TRACE("Pressed item %d!\n", nItem); - } - else if ((flags == HHT_ONDIVIDER) || (flags == HHT_ONDIVOPEN)) { - if (!(HEADER_SendHeaderNotify (hwnd, HDN_BEGINTRACKA, nItem,0))) { - SetCapture (hwnd); - infoPtr->bCaptured = TRUE; - infoPtr->bTracking = TRUE; - infoPtr->iMoveItem = nItem; - infoPtr->nOldWidth = infoPtr->items[nItem].cxy; - infoPtr->xTrackOffset = infoPtr->items[nItem].rect.right - pt.x; - - if (!(dwStyle & HDS_FULLDRAG)) { - infoPtr->xOldTrack = infoPtr->items[nItem].rect.right; - hdc = GetDC (hwnd); - HEADER_DrawTrackLine (hwnd, hdc, infoPtr->xOldTrack); - ReleaseDC (hwnd, hdc); - } - - TRACE("Begin tracking item %d!\n", nItem); - } - } - - return 0; -} - - -static LRESULT -HEADER_LButtonUp (HWND hwnd, WPARAM wParam, LPARAM lParam) -{ - HEADER_INFO *infoPtr = HEADER_GetInfoPtr (hwnd); - /* - *DWORD dwStyle = GetWindowLongA (hwnd, GWL_STYLE); - */ - POINT pt; - UINT flags; - INT nItem, nWidth; - HDC hdc; - - pt.x = (INT)(SHORT)LOWORD(lParam); - pt.y = (INT)(SHORT)HIWORD(lParam); - HEADER_InternalHitTest (hwnd, &pt, &flags, &nItem); - - if (infoPtr->bPressed) { - if ((nItem == infoPtr->iMoveItem) && (flags == HHT_ONHEADER)) { - infoPtr->items[infoPtr->iMoveItem].bDown = FALSE; - hdc = GetDC (hwnd); - HEADER_RefreshItem (hwnd, hdc, infoPtr->iMoveItem); - ReleaseDC (hwnd, hdc); - - HEADER_SendClickNotify (hwnd, HDN_ITEMCLICKA, infoPtr->iMoveItem); - } - else if (flags == HHT_ONHEADER) - { - HEADER_ITEM *lpItem; - INT newindex = HEADER_IndexToOrder(hwnd,nItem); - INT oldindex = HEADER_IndexToOrder(hwnd,infoPtr->iMoveItem); - - TRACE("Exchanging [index:order] [%d:%d] [%d:%d]\n", - infoPtr->iMoveItem,oldindex,nItem,newindex); - lpItem= &infoPtr->items[nItem]; - lpItem->iOrder=oldindex; - - lpItem= &infoPtr->items[infoPtr->iMoveItem]; - lpItem->iOrder = newindex; - - infoPtr->bRectsValid = FALSE; - InvalidateRect(hwnd, NULL, FALSE); - /* FIXME: Should some WM_NOTIFY be sent */ - } - - TRACE("Released item %d!\n", infoPtr->iMoveItem); - infoPtr->bPressed = FALSE; - } - else if (infoPtr->bTracking) { - TRACE("End tracking item %d!\n", infoPtr->iMoveItem); - infoPtr->bTracking = FALSE; - - HEADER_SendHeaderNotify (hwnd, HDN_ENDTRACKA, infoPtr->iMoveItem,HDI_WIDTH); - - /* - * we want to do this even for HDS_FULLDRAG because this is where - * we send the HDN_ITEMCHANGING and HDN_ITEMCHANGED notifications - * - * if (!(dwStyle & HDS_FULLDRAG)) { - */ - - hdc = GetDC (hwnd); - HEADER_DrawTrackLine (hwnd, hdc, infoPtr->xOldTrack); - ReleaseDC (hwnd, hdc); - if (HEADER_SendHeaderNotify(hwnd, HDN_ITEMCHANGINGA, infoPtr->iMoveItem, HDI_WIDTH)) - { - infoPtr->items[infoPtr->iMoveItem].cxy = infoPtr->nOldWidth; - } - else { - nWidth = pt.x - infoPtr->items[infoPtr->iMoveItem].rect.left + infoPtr->xTrackOffset; - if (nWidth < 0) - nWidth = 0; - infoPtr->items[infoPtr->iMoveItem].cxy = nWidth; - } - - HEADER_SetItemBounds (hwnd); - InvalidateRect(hwnd, NULL, TRUE); - HEADER_SendHeaderNotify(hwnd, HDN_ITEMCHANGEDA, infoPtr->iMoveItem, HDI_WIDTH); - /* - * } - */ - } - - if (infoPtr->bCaptured) { - infoPtr->bCaptured = FALSE; - ReleaseCapture (); - HEADER_SendSimpleNotify (hwnd, NM_RELEASEDCAPTURE); - } - - return 0; -} - - -static LRESULT -HEADER_NotifyFormat (HWND hwnd, WPARAM wParam, LPARAM lParam) -{ - HEADER_INFO *infoPtr = HEADER_GetInfoPtr (hwnd); - - switch (lParam) - { - case NF_QUERY: - return infoPtr->nNotifyFormat; - - case NF_REQUERY: - infoPtr->nNotifyFormat = - SendMessageA ((HWND)wParam, WM_NOTIFYFORMAT, - (WPARAM)hwnd, (LPARAM)NF_QUERY); - return infoPtr->nNotifyFormat; - } - - return 0; -} - - -static LRESULT -HEADER_MouseMove (HWND hwnd, WPARAM wParam, LPARAM lParam) -{ - HEADER_INFO *infoPtr = HEADER_GetInfoPtr (hwnd); - DWORD dwStyle = GetWindowLongA (hwnd, GWL_STYLE); - POINT pt; - UINT flags; - INT nItem, nWidth; - HDC hdc; - - pt.x = (INT)(SHORT)LOWORD(lParam); - pt.y = (INT)(SHORT)HIWORD(lParam); - HEADER_InternalHitTest (hwnd, &pt, &flags, &nItem); - - if ((dwStyle & HDS_BUTTONS) && (dwStyle & HDS_HOTTRACK)) { - if (flags & (HHT_ONHEADER | HHT_ONDIVIDER | HHT_ONDIVOPEN)) - infoPtr->iHotItem = nItem; - else - infoPtr->iHotItem = -1; - InvalidateRect(hwnd, NULL, FALSE); - } - - if (infoPtr->bCaptured) { - if (infoPtr->bPressed) { - if ((nItem == infoPtr->iMoveItem) && (flags == HHT_ONHEADER)) - infoPtr->items[infoPtr->iMoveItem].bDown = TRUE; - else - infoPtr->items[infoPtr->iMoveItem].bDown = FALSE; - hdc = GetDC (hwnd); - HEADER_RefreshItem (hwnd, hdc, infoPtr->iMoveItem); - ReleaseDC (hwnd, hdc); - - TRACE("Moving pressed item %d!\n", infoPtr->iMoveItem); - } - else if (infoPtr->bTracking) { - if (dwStyle & HDS_FULLDRAG) { - if (HEADER_SendHeaderNotify (hwnd, HDN_TRACKA, infoPtr->iMoveItem, HDI_WIDTH)) - { - nWidth = pt.x - infoPtr->items[infoPtr->iMoveItem].rect.left + infoPtr->xTrackOffset; - if (nWidth < 0) - nWidth = 0; - infoPtr->items[infoPtr->iMoveItem].cxy = nWidth; - HEADER_SendHeaderNotify(hwnd, HDN_ITEMCHANGEDA, infoPtr->iMoveItem, HDI_WIDTH); - } - HEADER_SetItemBounds (hwnd); - } - else { - hdc = GetDC (hwnd); - HEADER_DrawTrackLine (hwnd, hdc, infoPtr->xOldTrack); - infoPtr->xOldTrack = pt.x + infoPtr->xTrackOffset; - if (infoPtr->xOldTrack < infoPtr->items[infoPtr->iMoveItem].rect.left) - infoPtr->xOldTrack = infoPtr->items[infoPtr->iMoveItem].rect.left; - infoPtr->items[infoPtr->iMoveItem].cxy = - infoPtr->xOldTrack - infoPtr->items[infoPtr->iMoveItem].rect.left; - HEADER_DrawTrackLine (hwnd, hdc, infoPtr->xOldTrack); - ReleaseDC (hwnd, hdc); - HEADER_SendHeaderNotify (hwnd, HDN_TRACKA, infoPtr->iMoveItem, HDI_WIDTH); - } - - TRACE("Tracking item %d!\n", infoPtr->iMoveItem); - } - } - - if ((dwStyle & HDS_BUTTONS) && (dwStyle & HDS_HOTTRACK)) { - FIXME("hot track support!\n"); - } - - return 0; -} - - -static LRESULT -HEADER_Paint (HWND hwnd, WPARAM wParam) -{ - HDC hdc; - PAINTSTRUCT ps; - - hdc = wParam==0 ? BeginPaint (hwnd, &ps) : (HDC)wParam; - HEADER_Refresh (hwnd, hdc); - if(!wParam) - EndPaint (hwnd, &ps); - return 0; -} - - -static LRESULT -HEADER_RButtonUp (HWND hwnd, WPARAM wParam, LPARAM lParam) -{ - BOOL bRet; - POINT pt; - - pt.x = LOWORD(lParam); - pt.y = HIWORD(lParam); - - /* Send a Notify message */ - bRet = HEADER_SendSimpleNotify (hwnd, NM_RCLICK); - - /* Change to screen coordinate for WM_CONTEXTMENU */ - ClientToScreen(hwnd, &pt); - - /* Send a WM_CONTEXTMENU message in response to the RBUTTONUP */ - SendMessageA( hwnd, WM_CONTEXTMENU, (WPARAM) hwnd, MAKELPARAM(pt.x, pt.y)); - - return bRet; -} - - -static LRESULT -HEADER_SetCursor (HWND hwnd, WPARAM wParam, LPARAM lParam) -{ - HEADER_INFO *infoPtr = HEADER_GetInfoPtr (hwnd); - POINT pt; - UINT flags; - INT nItem; - - TRACE("code=0x%X id=0x%X\n", LOWORD(lParam), HIWORD(lParam)); - - GetCursorPos (&pt); - ScreenToClient (hwnd, &pt); - - HEADER_InternalHitTest (hwnd, &pt, &flags, &nItem); - - if (flags == HHT_ONDIVIDER) - SetCursor (infoPtr->hcurDivider); - else if (flags == HHT_ONDIVOPEN) - SetCursor (infoPtr->hcurDivopen); - else - SetCursor (infoPtr->hcurArrow); - - return 0; -} - - -static LRESULT -HEADER_SetFont (HWND hwnd, WPARAM wParam, LPARAM lParam) -{ - HEADER_INFO *infoPtr = HEADER_GetInfoPtr (hwnd); - TEXTMETRICA tm; - HFONT hFont, hOldFont; - HDC hdc; - - infoPtr->hFont = (HFONT)wParam; - - hFont = infoPtr->hFont ? infoPtr->hFont : GetStockObject (SYSTEM_FONT); - - hdc = GetDC (0); - hOldFont = SelectObject (hdc, hFont); - GetTextMetricsA (hdc, &tm); - infoPtr->nHeight = tm.tmHeight + VERT_BORDER; - SelectObject (hdc, hOldFont); - ReleaseDC (0, hdc); - - infoPtr->bRectsValid = FALSE; - - if (lParam) { - InvalidateRect(hwnd, NULL, FALSE); - } - - return 0; -} - - -static LRESULT WINAPI -HEADER_WindowProc (HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam) -{ - TRACE("hwnd=%p msg=%x wparam=%x lParam=%lx\n", hwnd, msg, wParam, lParam); - if (!HEADER_GetInfoPtr (hwnd) && (msg != WM_CREATE)) - return DefWindowProcA (hwnd, msg, wParam, lParam); - switch (msg) { -/* case HDM_CLEARFILTER: */ - - case HDM_CREATEDRAGIMAGE: - return HEADER_CreateDragImage (hwnd, wParam); - - case HDM_DELETEITEM: - return HEADER_DeleteItem (hwnd, wParam); - -/* case HDM_EDITFILTER: */ - - case HDM_GETBITMAPMARGIN: - return HEADER_GetBitmapMargin(hwnd); - - case HDM_GETIMAGELIST: - return HEADER_GetImageList (hwnd); - - case HDM_GETITEMA: - return HEADER_GetItemA (hwnd, wParam, lParam); - - case HDM_GETITEMW: - return HEADER_GetItemW (hwnd, wParam, lParam); - - case HDM_GETITEMCOUNT: - return HEADER_GetItemCount (hwnd); - - case HDM_GETITEMRECT: - return HEADER_GetItemRect (hwnd, wParam, lParam); - - case HDM_GETORDERARRAY: - return HEADER_GetOrderArray(hwnd, wParam, lParam); - - case HDM_GETUNICODEFORMAT: - return HEADER_GetUnicodeFormat (hwnd); - - case HDM_HITTEST: - return HEADER_HitTest (hwnd, wParam, lParam); - - case HDM_INSERTITEMA: - return HEADER_InsertItemA (hwnd, wParam, lParam); - - case HDM_INSERTITEMW: - return HEADER_InsertItemW (hwnd, wParam, lParam); - - case HDM_LAYOUT: - return HEADER_Layout (hwnd, wParam, lParam); - - case HDM_ORDERTOINDEX: - return HEADER_OrderToIndex(hwnd, wParam); - - case HDM_SETBITMAPMARGIN: - return HEADER_SetBitmapMargin(hwnd, wParam); - -/* case HDM_SETFILTERCHANGETIMEOUT: */ - -/* case HDM_SETHOTDIVIDER: */ - - case HDM_SETIMAGELIST: - return HEADER_SetImageList (hwnd, (HIMAGELIST)lParam); - - case HDM_SETITEMA: - return HEADER_SetItemA (hwnd, wParam, lParam); - - case HDM_SETITEMW: - return HEADER_SetItemW (hwnd, wParam, lParam); - - case HDM_SETORDERARRAY: - return HEADER_SetOrderArray(hwnd, wParam, lParam); - - case HDM_SETUNICODEFORMAT: - return HEADER_SetUnicodeFormat (hwnd, wParam); - - case WM_CREATE: - return HEADER_Create (hwnd, wParam, lParam); - - case WM_DESTROY: - return HEADER_Destroy (hwnd, wParam, lParam); - - case WM_ERASEBKGND: - return 1; - - case WM_GETDLGCODE: - return DLGC_WANTTAB | DLGC_WANTARROWS; - - case WM_GETFONT: - return HEADER_GetFont (hwnd); - - case WM_LBUTTONDBLCLK: - return HEADER_LButtonDblClk (hwnd, wParam, lParam); - - case WM_LBUTTONDOWN: - return HEADER_LButtonDown (hwnd, wParam, lParam); - - case WM_LBUTTONUP: - return HEADER_LButtonUp (hwnd, wParam, lParam); - - case WM_MOUSEMOVE: - return HEADER_MouseMove (hwnd, wParam, lParam); - - case WM_NOTIFYFORMAT: - return HEADER_NotifyFormat (hwnd, wParam, lParam); - - case WM_SIZE: - return HEADER_Size (hwnd, wParam); - - case WM_PAINT: - return HEADER_Paint (hwnd, wParam); - - case WM_RBUTTONUP: - return HEADER_RButtonUp (hwnd, wParam, lParam); - - case WM_SETCURSOR: - return HEADER_SetCursor (hwnd, wParam, lParam); - - case WM_SETFONT: - return HEADER_SetFont (hwnd, wParam, lParam); - - default: - if ((msg >= WM_USER) && (msg < WM_APP)) - ERR("unknown msg %04x wp=%04x lp=%08lx\n", - msg, wParam, lParam ); - return DefWindowProcA (hwnd, msg, wParam, lParam); - } - return 0; -} - - -VOID -HEADER_Register (void) -{ - WNDCLASSA wndClass; - - ZeroMemory (&wndClass, sizeof(WNDCLASSA)); - wndClass.style = CS_GLOBALCLASS | CS_DBLCLKS; - wndClass.lpfnWndProc = HEADER_WindowProc; - wndClass.cbClsExtra = 0; - wndClass.cbWndExtra = sizeof(HEADER_INFO *); - wndClass.hCursor = LoadCursorA (0, (LPSTR)IDC_ARROW); - wndClass.lpszClassName = WC_HEADERA; - - RegisterClassA (&wndClass); -} - - -VOID -HEADER_Unregister (void) -{ - UnregisterClassA (WC_HEADERA, NULL); -} diff --git a/reactos/lib/comctl32/hotkey.c b/reactos/lib/comctl32/hotkey.c deleted file mode 100644 index aeb39c4d614..00000000000 --- a/reactos/lib/comctl32/hotkey.c +++ /dev/null @@ -1,561 +0,0 @@ -/* - * Hotkey control - * - * Copyright 1998, 1999 Eric Kohl - * Copyright 2002 Gyorgy 'Nog' Jeney - * Copyright 2004 Robert Shearman - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2.1 of the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - * - * This code was audited for completeness against the documented features - * of Comctl32.dll version 6.0 on Sep. 21, 2004, by Robert Shearman. - * - * Unless otherwise noted, we believe this code to be complete, as per - * the specification mentioned above. - * If you discover missing features or bugs please note them below. - * - */ - -#include -#include -#include "windef.h" -#include "winbase.h" -#include "wingdi.h" -#include "winuser.h" -#include "winnls.h" -#include "commctrl.h" -#include "comctl32.h" -#include "wine/debug.h" - -WINE_DEFAULT_DEBUG_CHANNEL(hotkey); - -typedef struct tagHOTKEY_INFO -{ - HWND hwndSelf; - HWND hwndNotify; - HFONT hFont; - BOOL bFocus; - INT nHeight; - WORD HotKey; - WORD InvComb; - WORD InvMod; - BYTE CurrMod; - INT CaretPos; - DWORD ScanCode; - WCHAR strNone[15]; /* hope its long enough ... */ -} HOTKEY_INFO; - -static const WCHAR HOTKEY_plussep[] = { ' ', '+', ' ' }; -static LRESULT HOTKEY_SetFont (HOTKEY_INFO *infoPtr, HFONT hFont, BOOL redraw); - -#define IsOnlySet(flags) (infoPtr->CurrMod == (flags)) - -static BOOL -HOTKEY_IsCombInv(HOTKEY_INFO *infoPtr) -{ - TRACE("(infoPtr=%p)\n", infoPtr); - if((infoPtr->InvComb & HKCOMB_NONE) && !infoPtr->CurrMod) - return TRUE; - if((infoPtr->InvComb & HKCOMB_S) && IsOnlySet(HOTKEYF_SHIFT)) - return TRUE; - if((infoPtr->InvComb & HKCOMB_C) && IsOnlySet(HOTKEYF_CONTROL)) - return TRUE; - if((infoPtr->InvComb & HKCOMB_A) && IsOnlySet(HOTKEYF_ALT)) - return TRUE; - if((infoPtr->InvComb & HKCOMB_SC) && - IsOnlySet(HOTKEYF_SHIFT | HOTKEYF_CONTROL)) - return TRUE; - if((infoPtr->InvComb & HKCOMB_SA) && IsOnlySet(HOTKEYF_SHIFT | HOTKEYF_ALT)) - return TRUE; - if((infoPtr->InvComb & HKCOMB_CA) && - IsOnlySet(HOTKEYF_CONTROL | HOTKEYF_ALT)) - return TRUE; - if((infoPtr->InvComb & HKCOMB_SCA) && - IsOnlySet(HOTKEYF_SHIFT | HOTKEYF_CONTROL | HOTKEYF_ALT)) - return TRUE; - - TRACE("() Modifiers are valid\n"); - return FALSE; -} -#undef IsOnlySet - -static void -HOTKEY_DrawHotKey(HOTKEY_INFO *infoPtr, HDC hdc, LPCWSTR KeyName, WORD NameLen) -{ - SIZE TextSize; - INT nXStart, nYStart; - COLORREF clrOldText, clrOldBk; - HFONT hFontOld; - - /* Make a gap from the frame */ - nXStart = GetSystemMetrics(SM_CXBORDER); - nYStart = GetSystemMetrics(SM_CYBORDER); - - hFontOld = SelectObject(hdc, infoPtr->hFont); - if (GetWindowLongW(infoPtr->hwndSelf, GWL_STYLE) & WS_DISABLED) - { - clrOldText = SetTextColor(hdc, comctl32_color.clrGrayText); - clrOldBk = SetBkColor(hdc, comctl32_color.clrBtnFace); - } - else - { - clrOldText = SetTextColor(hdc, comctl32_color.clrWindowText); - clrOldBk = SetBkColor(hdc, comctl32_color.clrWindow); - } - - TextOutW(hdc, nXStart, nYStart, KeyName, NameLen); - - /* Get the text width for the caret */ - GetTextExtentPoint32W(hdc, KeyName, NameLen, &TextSize); - infoPtr->CaretPos = nXStart + TextSize.cx; - - SetBkColor(hdc, clrOldBk); - SetTextColor(hdc, clrOldText); - SelectObject(hdc, hFontOld); - - /* position the caret */ - SetCaretPos(infoPtr->CaretPos, nYStart); -} - -/* Draw the names of the keys in the control */ -static void -HOTKEY_Refresh(HOTKEY_INFO *infoPtr, HDC hdc) -{ - WCHAR KeyName[64]; - WORD NameLen = 0; - BYTE Modifier; - - TRACE("(infoPtr=%p hdc=%p)\n", infoPtr, hdc); - - if(!infoPtr->CurrMod && !infoPtr->HotKey) { - HOTKEY_DrawHotKey (infoPtr, hdc, infoPtr->strNone, 4); - return; - } - - if(infoPtr->HotKey) - Modifier = HIBYTE(infoPtr->HotKey); - else if(HOTKEY_IsCombInv(infoPtr)) - Modifier = infoPtr->InvMod; - else - Modifier = infoPtr->CurrMod; - - if(Modifier & HOTKEYF_CONTROL) { - GetKeyNameTextW(MAKELPARAM(0, MapVirtualKeyW(VK_CONTROL, 0)), - KeyName, 64); - NameLen = lstrlenW(KeyName); - memcpy(&KeyName[NameLen], HOTKEY_plussep, sizeof(HOTKEY_plussep)); - NameLen += 3; - } - if(Modifier & HOTKEYF_SHIFT) { - GetKeyNameTextW(MAKELPARAM(0, MapVirtualKeyW(VK_SHIFT, 0)), - &KeyName[NameLen], 64 - NameLen); - NameLen = lstrlenW(KeyName); - memcpy(&KeyName[NameLen], HOTKEY_plussep, sizeof(HOTKEY_plussep)); - NameLen += 3; - } - if(Modifier & HOTKEYF_ALT) { - GetKeyNameTextW(MAKELPARAM(0, MapVirtualKeyW(VK_MENU, 0)), - &KeyName[NameLen], 64 - NameLen); - NameLen = lstrlenW(KeyName); - memcpy(&KeyName[NameLen], HOTKEY_plussep, sizeof(HOTKEY_plussep)); - NameLen += 3; - } - - if(infoPtr->HotKey) { - GetKeyNameTextW(infoPtr->ScanCode, &KeyName[NameLen], 64 - NameLen); - NameLen = lstrlenW(KeyName); - } - else - KeyName[NameLen] = 0; - - HOTKEY_DrawHotKey (infoPtr, hdc, KeyName, NameLen); -} - -static void -HOTKEY_Paint(HOTKEY_INFO *infoPtr, HDC hdc) -{ - if (hdc) - HOTKEY_Refresh(infoPtr, hdc); - else { - PAINTSTRUCT ps; - hdc = BeginPaint (infoPtr->hwndSelf, &ps); - HOTKEY_Refresh (infoPtr, hdc); - EndPaint (infoPtr->hwndSelf, &ps); - } -} - -static LRESULT -HOTKEY_GetHotKey(HOTKEY_INFO *infoPtr) -{ - TRACE("(infoPtr=%p) Modifiers: 0x%x, Virtual Key: %d\n", infoPtr, - HIBYTE(infoPtr->HotKey), LOBYTE(infoPtr->HotKey)); - return (LRESULT)infoPtr->HotKey; -} - -static void -HOTKEY_SetHotKey(HOTKEY_INFO *infoPtr, WORD hotKey) -{ - infoPtr->HotKey = hotKey; - infoPtr->ScanCode = - MAKELPARAM(0, MapVirtualKeyW(LOBYTE(infoPtr->HotKey), 0)); - TRACE("(infoPtr=%p hotKey=%x) Modifiers: 0x%x, Virtual Key: %d\n", infoPtr, - hotKey, HIBYTE(infoPtr->HotKey), LOBYTE(infoPtr->HotKey)); - InvalidateRect(infoPtr->hwndSelf, NULL, TRUE); -} - -static void -HOTKEY_SetRules(HOTKEY_INFO *infoPtr, WORD invComb, WORD invMod) -{ - infoPtr->InvComb = invComb; - infoPtr->InvMod = invMod; - TRACE("(infoPtr=%p) Invalid Modifers: 0x%x, If Invalid: 0x%x\n", infoPtr, - infoPtr->InvComb, infoPtr->InvMod); -} - - -static LRESULT -HOTKEY_Create (HOTKEY_INFO *infoPtr, LPCREATESTRUCTW lpcs) -{ - infoPtr->hwndNotify = lpcs->hwndParent; - - HOTKEY_SetFont(infoPtr, GetStockObject(SYSTEM_FONT), 0); - - return 0; -} - - -static LRESULT -HOTKEY_Destroy (HOTKEY_INFO *infoPtr) -{ - HWND hwnd = infoPtr->hwndSelf; - /* free hotkey info data */ - Free (infoPtr); - SetWindowLongPtrW (hwnd, 0, 0); - return 0; -} - - -static LRESULT -HOTKEY_EraseBackground (HOTKEY_INFO *infoPtr, HDC hdc) -{ - HBRUSH hBrush, hSolidBrush = NULL; - RECT rc; - - if (GetWindowLongW(infoPtr->hwndSelf, GWL_STYLE) & WS_DISABLED) - hBrush = hSolidBrush = CreateSolidBrush(comctl32_color.clrBtnFace); - else - { - hBrush = (HBRUSH)SendMessageW(infoPtr->hwndNotify, WM_CTLCOLOREDIT, - (WPARAM)hdc, (LPARAM)infoPtr->hwndSelf); - if (!hBrush) - hBrush = hSolidBrush = CreateSolidBrush(comctl32_color.clrWindow); - } - - GetClientRect (infoPtr->hwndSelf, &rc); - - FillRect (hdc, &rc, hBrush); - - if (hSolidBrush) - DeleteObject(hSolidBrush); - - return -1; -} - - -inline static LRESULT -HOTKEY_GetFont (HOTKEY_INFO *infoPtr) -{ - return (LRESULT)infoPtr->hFont; -} - -static LRESULT -HOTKEY_KeyDown (HOTKEY_INFO *infoPtr, DWORD key, DWORD flags) -{ - WORD wOldHotKey; - BYTE bOldMod; - - if (GetWindowLongW(infoPtr->hwndSelf, GWL_STYLE) & WS_DISABLED) - return 0; - - TRACE("() Key: %ld\n", key); - - wOldHotKey = infoPtr->HotKey; - bOldMod = infoPtr->CurrMod; - - /* If any key is Pressed, we have to reset the hotkey in the control */ - infoPtr->HotKey = 0; - - switch (key) - { - case VK_RETURN: - case VK_TAB: - case VK_SPACE: - case VK_DELETE: - case VK_ESCAPE: - case VK_BACK: - InvalidateRect(infoPtr->hwndSelf, NULL, TRUE); - return DefWindowProcW (infoPtr->hwndSelf, WM_KEYDOWN, key, flags); - - case VK_SHIFT: - infoPtr->CurrMod |= HOTKEYF_SHIFT; - break; - case VK_CONTROL: - infoPtr->CurrMod |= HOTKEYF_CONTROL; - break; - case VK_MENU: - infoPtr->CurrMod |= HOTKEYF_ALT; - break; - - default: - if(HOTKEY_IsCombInv(infoPtr)) - infoPtr->HotKey = MAKEWORD(key, infoPtr->InvMod); - else - infoPtr->HotKey = MAKEWORD(key, infoPtr->CurrMod); - infoPtr->ScanCode = flags; - break; - } - - if ((wOldHotKey != infoPtr->HotKey) || (bOldMod != infoPtr->CurrMod)) - { - InvalidateRect(infoPtr->hwndSelf, NULL, TRUE); - - /* send EN_CHANGE notification */ - SendMessageW(infoPtr->hwndNotify, WM_COMMAND, - MAKEWPARAM(GetDlgCtrlID(infoPtr->hwndSelf), EN_CHANGE), - (LPARAM)infoPtr->hwndSelf); - } - - return 0; -} - - -static LRESULT -HOTKEY_KeyUp (HOTKEY_INFO *infoPtr, DWORD key, DWORD flags) -{ - BYTE bOldMod; - - if (GetWindowLongW(infoPtr->hwndSelf, GWL_STYLE) & WS_DISABLED) - return 0; - - TRACE("() Key: %ld\n", key); - - bOldMod = infoPtr->CurrMod; - - switch (key) - { - case VK_SHIFT: - infoPtr->CurrMod &= ~HOTKEYF_SHIFT; - break; - case VK_CONTROL: - infoPtr->CurrMod &= ~HOTKEYF_CONTROL; - break; - case VK_MENU: - infoPtr->CurrMod &= ~HOTKEYF_ALT; - break; - default: - return 1; - } - - if (bOldMod != infoPtr->CurrMod) - { - InvalidateRect(infoPtr->hwndSelf, NULL, TRUE); - - /* send EN_CHANGE notification */ - SendMessageW(infoPtr->hwndNotify, WM_COMMAND, - MAKEWPARAM(GetDlgCtrlID(infoPtr->hwndSelf), EN_CHANGE), - (LPARAM)infoPtr->hwndSelf); - } - - return 0; -} - - -static LRESULT -HOTKEY_KillFocus (HOTKEY_INFO *infoPtr, HWND receiveFocus) -{ - infoPtr->bFocus = FALSE; - DestroyCaret (); - - return 0; -} - - -static LRESULT -HOTKEY_LButtonDown (HOTKEY_INFO *infoPtr) -{ - if (!(GetWindowLongW(infoPtr->hwndSelf, GWL_STYLE) & WS_DISABLED)) - SetFocus (infoPtr->hwndSelf); - - return 0; -} - - -inline static LRESULT -HOTKEY_NCCreate (HWND hwnd, LPCREATESTRUCTW lpcs) -{ - HOTKEY_INFO *infoPtr; - DWORD dwExStyle = GetWindowLongW (hwnd, GWL_EXSTYLE); - SetWindowLongW (hwnd, GWL_EXSTYLE, - dwExStyle | WS_EX_CLIENTEDGE); - - /* allocate memory for info structure */ - infoPtr = (HOTKEY_INFO *)Alloc (sizeof(HOTKEY_INFO)); - SetWindowLongPtrW(hwnd, 0, (DWORD_PTR)infoPtr); - - /* initialize info structure */ - infoPtr->HotKey = infoPtr->InvComb = infoPtr->InvMod = infoPtr->CurrMod = 0; - infoPtr->CaretPos = GetSystemMetrics(SM_CXBORDER); - infoPtr->hwndSelf = hwnd; - LoadStringW(COMCTL32_hModule, HKY_NONE, infoPtr->strNone, 15); - - return DefWindowProcW (infoPtr->hwndSelf, WM_NCCREATE, 0, (LPARAM)lpcs); -} - -static LRESULT -HOTKEY_SetFocus (HOTKEY_INFO *infoPtr, HWND lostFocus) -{ - infoPtr->bFocus = TRUE; - - CreateCaret (infoPtr->hwndSelf, NULL, 1, infoPtr->nHeight); - SetCaretPos (infoPtr->CaretPos, GetSystemMetrics(SM_CYBORDER)); - ShowCaret (infoPtr->hwndSelf); - - return 0; -} - - -static LRESULT -HOTKEY_SetFont (HOTKEY_INFO *infoPtr, HFONT hFont, BOOL redraw) -{ - TEXTMETRICW tm; - HDC hdc; - HFONT hOldFont = 0; - - infoPtr->hFont = hFont; - - hdc = GetDC (infoPtr->hwndSelf); - if (infoPtr->hFont) - hOldFont = SelectObject (hdc, infoPtr->hFont); - - GetTextMetricsW (hdc, &tm); - infoPtr->nHeight = tm.tmHeight; - - if (infoPtr->hFont) - SelectObject (hdc, hOldFont); - ReleaseDC (infoPtr->hwndSelf, hdc); - - if (redraw) - InvalidateRect (infoPtr->hwndSelf, NULL, TRUE); - - return 0; -} - -static LRESULT WINAPI -HOTKEY_WindowProc (HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam) -{ - HOTKEY_INFO *infoPtr = (HOTKEY_INFO *)GetWindowLongPtrW (hwnd, 0); - TRACE("hwnd=%p msg=%x wparam=%x lparam=%lx\n", hwnd, uMsg, wParam, lParam); - if (!infoPtr && (uMsg != WM_NCCREATE)) - return DefWindowProcW (hwnd, uMsg, wParam, lParam); - switch (uMsg) - { - case HKM_GETHOTKEY: - return HOTKEY_GetHotKey (infoPtr); - case HKM_SETHOTKEY: - HOTKEY_SetHotKey (infoPtr, (WORD)wParam); - break; - case HKM_SETRULES: - HOTKEY_SetRules (infoPtr, (WORD)wParam, (WORD)lParam); - break; - - case WM_CHAR: - case WM_SYSCHAR: - return HOTKEY_KeyDown (infoPtr, MapVirtualKeyW(LOBYTE(HIWORD(lParam)), 1), lParam); - - case WM_CREATE: - return HOTKEY_Create (infoPtr, (LPCREATESTRUCTW)lParam); - - case WM_DESTROY: - return HOTKEY_Destroy (infoPtr); - - case WM_ERASEBKGND: - return HOTKEY_EraseBackground (infoPtr, (HDC)wParam); - - case WM_GETDLGCODE: - return DLGC_WANTCHARS | DLGC_WANTARROWS; - - case WM_GETFONT: - return HOTKEY_GetFont (infoPtr); - - case WM_KEYDOWN: - case WM_SYSKEYDOWN: - return HOTKEY_KeyDown (infoPtr, wParam, lParam); - - case WM_KEYUP: - case WM_SYSKEYUP: - return HOTKEY_KeyUp (infoPtr, wParam, lParam); - - case WM_KILLFOCUS: - return HOTKEY_KillFocus (infoPtr, (HWND)wParam); - - case WM_LBUTTONDOWN: - return HOTKEY_LButtonDown (infoPtr); - - case WM_NCCREATE: - return HOTKEY_NCCreate (hwnd, (LPCREATESTRUCTW)lParam); - - case WM_PAINT: - HOTKEY_Paint(infoPtr, (HDC)wParam); - return 0; - - case WM_SETFOCUS: - return HOTKEY_SetFocus (infoPtr, (HWND)wParam); - - case WM_SETFONT: - return HOTKEY_SetFont (infoPtr, (HFONT)wParam, LOWORD(lParam)); - - default: - if ((uMsg >= WM_USER) && (uMsg < WM_APP)) - ERR("unknown msg %04x wp=%08x lp=%08lx\n", - uMsg, wParam, lParam); - return DefWindowProcW (hwnd, uMsg, wParam, lParam); - } - return 0; -} - - -void -HOTKEY_Register (void) -{ - WNDCLASSW wndClass; - - ZeroMemory (&wndClass, sizeof(WNDCLASSW)); - wndClass.style = CS_GLOBALCLASS; - wndClass.lpfnWndProc = HOTKEY_WindowProc; - wndClass.cbClsExtra = 0; - wndClass.cbWndExtra = sizeof(HOTKEY_INFO *); - wndClass.hCursor = 0; - wndClass.hbrBackground = 0; - wndClass.lpszClassName = HOTKEY_CLASSW; - - RegisterClassW (&wndClass); -} - - -void -HOTKEY_Unregister (void) -{ - UnregisterClassW (HOTKEY_CLASSW, NULL); -} diff --git a/reactos/lib/comctl32/imagelist.c b/reactos/lib/comctl32/imagelist.c deleted file mode 100644 index b586c7a574c..00000000000 --- a/reactos/lib/comctl32/imagelist.c +++ /dev/null @@ -1,2884 +0,0 @@ -/* - * ImageList implementation - * - * Copyright 1998 Eric Kohl - * Copyright 2000 Jason Mawdsley - * Copyright 2001, 2004 Michael Stefaniuc - * Copyright 2001 Charles Loep for CodeWeavers - * Copyright 2002 Dimitrie O. Paun - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2.1 of the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - * - * NOTE - * - * This code was audited for completeness against the documented features - * of Comctl32.dll version 6.0 on Sep. 12, 2002, 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: - * - Add support for ILD_PRESERVEALPHA, ILD_SCALE, ILD_DPISCALE - * - Add support for ILS_GLOW, ILS_SHADOW, ILS_SATURATE, ILS_ALPHA - * - Thread-safe locking - */ - -#include -#include -#include - -#define COBJMACROS - -#include "winerror.h" -#include "windef.h" -#include "winbase.h" -#include "objbase.h" -#include "wingdi.h" -#include "winuser.h" -#include "commctrl.h" -#include "comctl32.h" -#include "imagelist.h" -#include "wine/debug.h" - -WINE_DEFAULT_DEBUG_CHANNEL(imagelist); - - -#define MAX_OVERLAYIMAGE 15 - -/* internal image list data used for Drag & Drop operations */ -typedef struct -{ - HWND hwnd; - HIMAGELIST himl; - /* position of the drag image relative to the window */ - INT x; - INT y; - /* offset of the hotspot relative to the origin of the image */ - INT dxHotspot; - INT dyHotspot; - /* is the drag image visible */ - BOOL bShow; - /* saved background */ - HBITMAP hbmBg; -} INTERNALDRAG; - -static INTERNALDRAG InternalDrag = { 0, 0, 0, 0, 0, 0, FALSE, 0 }; - -static HBITMAP ImageList_CreateImage(HDC hdc, HIMAGELIST himl, UINT width, UINT height); - -static inline BOOL is_valid(HIMAGELIST himl) -{ - return himl && himl->magic == IMAGELIST_MAGIC; -} - - -/************************************************************************* - * IMAGELIST_InternalExpandBitmaps [Internal] - * - * Expands the bitmaps of an image list by the given number of images. - * - * PARAMS - * himl [I] handle to image list - * nImageCount [I] number of images to add - * - * RETURNS - * nothing - * - * NOTES - * This function can NOT be used to reduce the number of images. - */ -static void -IMAGELIST_InternalExpandBitmaps (HIMAGELIST himl, INT nImageCount, INT cx, INT cy) -{ - HDC hdcBitmap; - HBITMAP hbmNewBitmap, hbmNull; - INT nNewWidth, nNewCount; - - if ((himl->cCurImage + nImageCount <= himl->cMaxImage) - && (himl->cy >= cy)) - return; - - if (cy == 0) cy = himl->cy; - nNewCount = himl->cCurImage + nImageCount + himl->cGrow; - nNewWidth = nNewCount * himl->cx; - - TRACE("Create expanded bitmaps : himl=%p x=%d y=%d count=%d\n", himl, nNewWidth, cy, nNewCount); - hdcBitmap = CreateCompatibleDC (0); - - hbmNewBitmap = ImageList_CreateImage(hdcBitmap, himl, nNewWidth, cy); - - if (hbmNewBitmap == 0) - ERR("creating new image bitmap (x=%d y=%d)!\n", nNewWidth, cy); - - if(himl->cCurImage) - { - hbmNull = SelectObject (hdcBitmap, hbmNewBitmap); - BitBlt (hdcBitmap, 0, 0, himl->cCurImage * himl->cx, cy, - himl->hdcImage, 0, 0, SRCCOPY); - SelectObject (hdcBitmap, hbmNull); - } - SelectObject (himl->hdcImage, hbmNewBitmap); - DeleteObject (himl->hbmImage); - himl->hbmImage = hbmNewBitmap; - - if (himl->flags & ILC_MASK) - { - hbmNewBitmap = CreateBitmap (nNewWidth, cy, 1, 1, NULL); - - if (hbmNewBitmap == 0) - ERR("creating new mask bitmap!\n"); - - if(himl->cCurImage) - { - hbmNull = SelectObject (hdcBitmap, hbmNewBitmap); - BitBlt (hdcBitmap, 0, 0, himl->cCurImage * himl->cx, cy, - himl->hdcMask, 0, 0, SRCCOPY); - SelectObject (hdcBitmap, hbmNull); - } - SelectObject (himl->hdcMask, hbmNewBitmap); - DeleteObject (himl->hbmMask); - himl->hbmMask = hbmNewBitmap; - } - - himl->cMaxImage = nNewCount; - - DeleteDC (hdcBitmap); -} - - -/************************************************************************* - * ImageList_Add [COMCTL32.@] - * - * Add an image or images to an image list. - * - * PARAMS - * himl [I] handle to image list - * hbmImage [I] handle to image bitmap - * hbmMask [I] handle to mask bitmap - * - * RETURNS - * Success: Index of the first new image. - * Failure: -1 - */ - -INT WINAPI -ImageList_Add (HIMAGELIST himl, HBITMAP hbmImage, HBITMAP hbmMask) -{ - HDC hdcBitmap; - INT nFirstIndex, nImageCount; - INT nStartX; - BITMAP bmp; - HBITMAP hOldBitmap; - - TRACE("himl=%p hbmimage=%p hbmmask=%p\n", himl, hbmImage, hbmMask); - if (!is_valid(himl)) - return -1; - - GetObjectA (hbmImage, sizeof(BITMAP), (LPVOID)&bmp); - nImageCount = bmp.bmWidth / himl->cx; - - IMAGELIST_InternalExpandBitmaps (himl, nImageCount, bmp.bmWidth, bmp.bmHeight); - - nStartX = himl->cCurImage * himl->cx; - - hdcBitmap = CreateCompatibleDC(0); - - hOldBitmap = SelectObject(hdcBitmap, hbmImage); - - /* Copy result to the imagelist - */ - BitBlt (himl->hdcImage, nStartX, 0, bmp.bmWidth, bmp.bmHeight, - hdcBitmap, 0, 0, SRCCOPY); - - if(himl->hbmMask) - { - HDC hdcTemp; - HBITMAP hOldBitmapTemp; - - hdcTemp = CreateCompatibleDC(0); - hOldBitmapTemp = SelectObject(hdcTemp, hbmMask); - - BitBlt (himl->hdcMask, - nStartX, 0, bmp.bmWidth, bmp.bmHeight, - hdcTemp, - 0, 0, - SRCCOPY); - - SelectObject(hdcTemp, hOldBitmapTemp); - DeleteDC(hdcTemp); - - /* Remove the background from the image - */ - BitBlt (himl->hdcImage, - nStartX, 0, bmp.bmWidth, bmp.bmHeight, - himl->hdcMask, - nStartX, 0, - 0x220326); /* NOTSRCAND */ - } - - SelectObject(hdcBitmap, hOldBitmap); - DeleteDC(hdcBitmap); - - nFirstIndex = himl->cCurImage; - himl->cCurImage += nImageCount; - - return nFirstIndex; -} - - -/************************************************************************* - * ImageList_AddIcon [COMCTL32.@] - * - * Adds an icon to an image list. - * - * PARAMS - * himl [I] handle to image list - * hIcon [I] handle to icon - * - * RETURNS - * Success: index of the new image - * Failure: -1 - */ -#undef ImageList_AddIcon -INT WINAPI ImageList_AddIcon (HIMAGELIST himl, HICON hIcon) -{ - return ImageList_ReplaceIcon (himl, -1, hIcon); -} - - -/************************************************************************* - * ImageList_AddMasked [COMCTL32.@] - * - * Adds an image or images to an image list and creates a mask from the - * specified bitmap using the mask color. - * - * PARAMS - * himl [I] handle to image list. - * hBitmap [I] handle to bitmap - * clrMask [I] mask color. - * - * RETURNS - * Success: Index of the first new image. - * Failure: -1 - */ - -INT WINAPI -ImageList_AddMasked (HIMAGELIST himl, HBITMAP hBitmap, COLORREF clrMask) -{ - HDC hdcMask, hdcBitmap; - INT nIndex, nImageCount, nMaskXOffset=0; - BITMAP bmp; - HBITMAP hOldBitmap; - HBITMAP hMaskBitmap=0; - COLORREF bkColor; - - TRACE("himl=%p hbitmap=%p clrmask=%lx\n", himl, hBitmap, clrMask); - if (!is_valid(himl)) - return -1; - - if (!GetObjectA (hBitmap, sizeof(BITMAP), &bmp)) - return -1; - - if (himl->cx > 0) - nImageCount = bmp.bmWidth / himl->cx; - else - nImageCount = 0; - - IMAGELIST_InternalExpandBitmaps (himl, nImageCount, bmp.bmWidth, bmp.bmHeight); - - nIndex = himl->cCurImage; - himl->cCurImage += nImageCount; - - hdcBitmap = CreateCompatibleDC(0); - - - hOldBitmap = SelectObject(hdcBitmap, hBitmap); - if(himl->hbmMask) - { - hdcMask = himl->hdcMask; - nMaskXOffset = nIndex * himl->cx; - } - else - { - /* - Create a temp Mask so we can remove the background of - the Image (Windows does this even if there is no mask) - */ - hdcMask = CreateCompatibleDC(0); - hMaskBitmap = CreateBitmap(bmp.bmWidth, bmp.bmHeight, 1, 1, NULL); - SelectObject(hdcMask, hMaskBitmap); - nMaskXOffset = 0; - } - /* create monochrome image to the mask bitmap */ - bkColor = (clrMask != CLR_DEFAULT) ? clrMask : - GetPixel (hdcBitmap, 0, 0); - SetBkColor (hdcBitmap, bkColor); - BitBlt (hdcMask, - nMaskXOffset, 0, bmp.bmWidth, bmp.bmHeight, - hdcBitmap, 0, 0, - SRCCOPY); - - SetBkColor(hdcBitmap, RGB(255,255,255)); - /*Remove the background from the image - */ - /* - WINDOWS BUG ALERT!!!!!! - The statement below should not be done in common practice - but this is how ImageList_AddMasked works in Windows. - It overwrites the original bitmap passed, this was discovered - by using the same bitmap to iterate the different styles - on windows where it failed (BUT ImageList_Add is OK) - This is here in case some apps rely on this bug - */ - BitBlt(hdcBitmap, - 0, 0, bmp.bmWidth, bmp.bmHeight, - hdcMask, - nMaskXOffset, 0, - 0x220326); /* NOTSRCAND */ - /* Copy result to the imagelist - */ - BitBlt (himl->hdcImage, - nIndex * himl->cx, 0, bmp.bmWidth, bmp.bmHeight, - hdcBitmap, - 0, 0, - SRCCOPY); - /* Clean up - */ - SelectObject(hdcBitmap, hOldBitmap); - DeleteDC(hdcBitmap); - if(!himl->hbmMask) - { - DeleteObject(hMaskBitmap); - DeleteDC(hdcMask); - } - - return nIndex; -} - - -/************************************************************************* - * ImageList_BeginDrag [COMCTL32.@] - * - * Creates a temporary image list that contains one image. It will be used - * as a drag image. - * - * PARAMS - * himlTrack [I] handle to the source image list - * iTrack [I] index of the drag image in the source image list - * dxHotspot [I] X position of the hot spot of the drag image - * dyHotspot [I] Y position of the hot spot of the drag image - * - * RETURNS - * Success: TRUE - * Failure: FALSE - */ - -BOOL WINAPI -ImageList_BeginDrag (HIMAGELIST himlTrack, INT iTrack, - INT dxHotspot, INT dyHotspot) -{ - INT cx, cy; - - TRACE("(himlTrack=%p iTrack=%d dx=%d dy=%d)\n", himlTrack, iTrack, - dxHotspot, dyHotspot); - - if (!is_valid(himlTrack)) - return FALSE; - - if (InternalDrag.himl) - ImageList_EndDrag (); - - cx = himlTrack->cx; - cy = himlTrack->cy; - - InternalDrag.himl = ImageList_Create (cx, cy, himlTrack->flags, 1, 1); - if (InternalDrag.himl == NULL) { - WARN("Error creating drag image list!\n"); - return FALSE; - } - - InternalDrag.dxHotspot = dxHotspot; - InternalDrag.dyHotspot = dyHotspot; - - /* copy image */ - BitBlt (InternalDrag.himl->hdcImage, 0, 0, cx, cy, himlTrack->hdcImage, iTrack * cx, 0, SRCCOPY); - - /* copy mask */ - BitBlt (InternalDrag.himl->hdcMask, 0, 0, cx, cy, himlTrack->hdcMask, iTrack * cx, 0, SRCCOPY); - - InternalDrag.himl->cCurImage = 1; - - return TRUE; -} - - -/************************************************************************* - * ImageList_Copy [COMCTL32.@] - * - * Copies an image of the source image list to an image of the - * destination image list. Images can be copied or swapped. - * - * PARAMS - * himlDst [I] handle to the destination image list - * iDst [I] destination image index. - * himlSrc [I] handle to the source image list - * iSrc [I] source image index - * uFlags [I] flags for the copy operation - * - * RETURNS - * Success: TRUE - * Failure: FALSE - * - * NOTES - * Copying from one image list to another is possible. The original - * implementation just copies or swaps within one image list. - * Could this feature become a bug??? ;-) - */ - -BOOL WINAPI -ImageList_Copy (HIMAGELIST himlDst, INT iDst, HIMAGELIST himlSrc, - INT iSrc, UINT uFlags) -{ - TRACE("himlDst=%p iDst=%d himlSrc=%p iSrc=%d\n", himlDst, iDst, himlSrc, iSrc); - - if (!is_valid(himlSrc) || !is_valid(himlDst)) - return FALSE; - if ((iDst < 0) || (iDst >= himlDst->cCurImage)) - return FALSE; - if ((iSrc < 0) || (iSrc >= himlSrc->cCurImage)) - return FALSE; - - if (uFlags & ILCF_SWAP) { - /* swap */ - HDC hdcBmp; - HBITMAP hbmTempImage, hbmTempMask; - - hdcBmp = CreateCompatibleDC (0); - - /* create temporary bitmaps */ - hbmTempImage = CreateBitmap (himlSrc->cx, himlSrc->cy, 1, - himlSrc->uBitsPixel, NULL); - hbmTempMask = CreateBitmap (himlSrc->cx, himlSrc->cy, 1, - 1, NULL); - - /* copy (and stretch) destination to temporary bitmaps.(save) */ - /* image */ - SelectObject (hdcBmp, hbmTempImage); - StretchBlt (hdcBmp, 0, 0, himlSrc->cx, himlSrc->cy, - himlDst->hdcImage, iDst * himlDst->cx, 0, himlDst->cx, himlDst->cy, - SRCCOPY); - /* mask */ - SelectObject (hdcBmp, hbmTempMask); - StretchBlt (hdcBmp, 0, 0, himlSrc->cx, himlSrc->cy, - himlDst->hdcMask, iDst * himlDst->cx, 0, himlDst->cx, himlDst->cy, - SRCCOPY); - - /* copy (and stretch) source to destination */ - /* image */ - StretchBlt (himlDst->hdcImage, iDst * himlDst->cx, 0, himlDst->cx, himlDst->cy, - himlSrc->hdcImage, iSrc * himlSrc->cx, 0, himlSrc->cx, himlSrc->cy, - SRCCOPY); - /* mask */ - StretchBlt (himlDst->hdcMask, iDst * himlDst->cx, 0, himlDst->cx, himlDst->cy, - himlSrc->hdcMask, iSrc * himlSrc->cx, 0, himlSrc->cx, himlSrc->cy, - SRCCOPY); - - /* copy (without stretching) temporary bitmaps to source (restore) */ - /* mask */ - BitBlt (himlSrc->hdcMask, iSrc * himlSrc->cx, 0, himlSrc->cx, himlSrc->cy, - hdcBmp, 0, 0, SRCCOPY); - - /* image */ - BitBlt (himlSrc->hdcImage, iSrc * himlSrc->cx, 0, himlSrc->cx, himlSrc->cy, - hdcBmp, 0, 0, SRCCOPY); - /* delete temporary bitmaps */ - DeleteObject (hbmTempMask); - DeleteObject (hbmTempImage); - DeleteDC(hdcBmp); - } - else { - /* copy image */ - StretchBlt (himlDst->hdcImage, iDst * himlDst->cx, 0, himlDst->cx, himlDst->cy, - himlSrc->hdcImage, iSrc * himlSrc->cx, 0, himlSrc->cx, himlSrc->cy, - SRCCOPY); - - /* copy mask */ - StretchBlt (himlDst->hdcMask, iDst * himlDst->cx, 0, himlDst->cx, himlDst->cy, - himlSrc->hdcMask, iSrc * himlSrc->cx, 0, himlSrc->cx, himlSrc->cy, - SRCCOPY); - } - - return TRUE; -} - - -/************************************************************************* - * ImageList_Create [COMCTL32.@] - * - * Creates a new image list. - * - * PARAMS - * cx [I] image height - * cy [I] image width - * flags [I] creation flags - * cInitial [I] initial number of images in the image list - * cGrow [I] number of images by which image list grows - * - * RETURNS - * Success: Handle to the created image list - * Failure: NULL - */ -HIMAGELIST WINAPI -ImageList_Create (INT cx, INT cy, UINT flags, - INT cInitial, INT cGrow) -{ - HIMAGELIST himl; - INT nCount; - HBITMAP hbmTemp; - UINT ilc = (flags & 0xFE); - static const WORD aBitBlend25[] = - {0xAA, 0x00, 0x55, 0x00, 0xAA, 0x00, 0x55, 0x00}; - - static const WORD aBitBlend50[] = - {0x55, 0xAA, 0x55, 0xAA, 0x55, 0xAA, 0x55, 0xAA}; - - TRACE("(%d %d 0x%x %d %d)\n", cx, cy, flags, cInitial, cGrow); - - himl = (HIMAGELIST)Alloc (sizeof(struct _IMAGELIST)); - if (!himl) - return NULL; - - cGrow = (cGrow < 4) ? 4 : (cGrow + 3) & ~3; - - himl->magic = IMAGELIST_MAGIC; - himl->cx = cx; - himl->cy = cy; - himl->flags = flags; - himl->cMaxImage = cInitial + cGrow; - himl->cInitial = cInitial; - himl->cGrow = cGrow; - himl->clrFg = CLR_DEFAULT; - himl->clrBk = CLR_NONE; - - /* initialize overlay mask indices */ - for (nCount = 0; nCount < MAX_OVERLAYIMAGE; nCount++) - himl->nOvlIdx[nCount] = -1; - - /* Create Image & Mask DCs */ - himl->hdcImage = CreateCompatibleDC (0); - if (!himl->hdcImage) - goto cleanup; - if (himl->flags & ILC_MASK){ - himl->hdcMask = CreateCompatibleDC(0); - if (!himl->hdcMask) - goto cleanup; - } - - /* Default to ILC_COLOR4 if none of the ILC_COLOR* flags are specified */ - if (ilc == ILC_COLOR) - ilc = ILC_COLOR4; - - if (ilc >= ILC_COLOR4 && ilc <= ILC_COLOR32) - himl->uBitsPixel = ilc; - else - himl->uBitsPixel = (UINT)GetDeviceCaps (himl->hdcImage, BITSPIXEL); - - if (himl->cMaxImage > 0) { - himl->hbmImage = ImageList_CreateImage(himl->hdcImage, himl, cx * himl->cMaxImage, cy); - SelectObject(himl->hdcImage, himl->hbmImage); - } else - himl->hbmImage = 0; - - if ((himl->cMaxImage > 0) && (himl->flags & ILC_MASK)) { - himl->hbmMask = - CreateBitmap (himl->cx * himl->cMaxImage, himl->cy, - 1, 1, NULL); - if (himl->hbmMask == 0) { - ERR("Error creating mask bitmap!\n"); - goto cleanup; - } - SelectObject(himl->hdcMask, himl->hbmMask); - } - - /* create blending brushes */ - hbmTemp = CreateBitmap (8, 8, 1, 1, &aBitBlend25); - himl->hbrBlend25 = CreatePatternBrush (hbmTemp); - DeleteObject (hbmTemp); - - hbmTemp = CreateBitmap (8, 8, 1, 1, &aBitBlend50); - himl->hbrBlend50 = CreatePatternBrush (hbmTemp); - DeleteObject (hbmTemp); - - TRACE("created imagelist %p\n", himl); - return himl; - -cleanup: - if (himl) ImageList_Destroy(himl); - return NULL; -} - - -/************************************************************************* - * ImageList_Destroy [COMCTL32.@] - * - * Destroys an image list. - * - * PARAMS - * himl [I] handle to image list - * - * RETURNS - * Success: TRUE - * Failure: FALSE - */ - -BOOL WINAPI -ImageList_Destroy (HIMAGELIST himl) -{ - if (!is_valid(himl)) - return FALSE; - - /* delete image bitmaps */ - if (himl->hbmImage) - DeleteObject (himl->hbmImage); - if (himl->hbmMask) - DeleteObject (himl->hbmMask); - - /* delete image & mask DCs */ - if (himl->hdcImage) - DeleteDC(himl->hdcImage); - if (himl->hdcMask) - DeleteDC(himl->hdcMask); - - /* delete blending brushes */ - if (himl->hbrBlend25) - DeleteObject (himl->hbrBlend25); - if (himl->hbrBlend50) - DeleteObject (himl->hbrBlend50); - - ZeroMemory(himl, sizeof(*himl)); - Free (himl); - - return TRUE; -} - - -/************************************************************************* - * ImageList_DragEnter [COMCTL32.@] - * - * Locks window update and displays the drag image at the given position. - * - * PARAMS - * hwndLock [I] handle of the window that owns the drag image. - * x [I] X position of the drag image. - * y [I] Y position of the drag image. - * - * RETURNS - * Success: TRUE - * Failure: FALSE - * - * NOTES - * The position of the drag image is relative to the window, not - * the client area. - */ - -BOOL WINAPI -ImageList_DragEnter (HWND hwndLock, INT x, INT y) -{ - TRACE("(hwnd=%p x=%d y=%d)\n", hwndLock, x, y); - - if (!is_valid(InternalDrag.himl)) - return FALSE; - - if (hwndLock) - InternalDrag.hwnd = hwndLock; - else - InternalDrag.hwnd = GetDesktopWindow (); - - InternalDrag.x = x; - InternalDrag.y = y; - - /* draw the drag image and save the background */ - if (!ImageList_DragShowNolock(TRUE)) { - return FALSE; - } - - return TRUE; -} - - -/************************************************************************* - * ImageList_DragLeave [COMCTL32.@] - * - * Unlocks window update and hides the drag image. - * - * PARAMS - * hwndLock [I] handle of the window that owns the drag image. - * - * RETURNS - * Success: TRUE - * Failure: FALSE - */ - -BOOL WINAPI -ImageList_DragLeave (HWND hwndLock) -{ - /* As we don't save drag info in the window this can lead to problems if - an app does not supply the same window as DragEnter */ - /* if (hwndLock) - InternalDrag.hwnd = hwndLock; - else - InternalDrag.hwnd = GetDesktopWindow (); */ - if(!hwndLock) - hwndLock = GetDesktopWindow(); - if(InternalDrag.hwnd != hwndLock) - FIXME("DragLeave hWnd != DragEnter hWnd\n"); - - ImageList_DragShowNolock (FALSE); - - return TRUE; -} - - -/************************************************************************* - * ImageList_InternalDragDraw [Internal] - * - * Draws the drag image. - * - * PARAMS - * hdc [I] device context to draw into. - * x [I] X position of the drag image. - * y [I] Y position of the drag image. - * - * RETURNS - * Success: TRUE - * Failure: FALSE - * - * NOTES - * The position of the drag image is relative to the window, not - * the client area. - * - */ - -static inline void -ImageList_InternalDragDraw (HDC hdc, INT x, INT y) -{ - IMAGELISTDRAWPARAMS imldp; - - ZeroMemory (&imldp, sizeof(imldp)); - imldp.cbSize = sizeof(imldp); - imldp.himl = InternalDrag.himl; - imldp.i = 0; - imldp.hdcDst = hdc, - imldp.x = x; - imldp.y = y; - imldp.rgbBk = CLR_DEFAULT; - imldp.rgbFg = CLR_DEFAULT; - imldp.fStyle = ILD_NORMAL; - imldp.fState = ILS_ALPHA; - imldp.Frame = 128; - - /* FIXME: instead of using the alpha blending, we should - * create a 50% mask, and draw it semitransparantly that way */ - ImageList_DrawIndirect (&imldp); -} - -/************************************************************************* - * ImageList_DragMove [COMCTL32.@] - * - * Moves the drag image. - * - * PARAMS - * x [I] X position of the drag image. - * y [I] Y position of the drag image. - * - * RETURNS - * Success: TRUE - * Failure: FALSE - * - * NOTES - * The position of the drag image is relative to the window, not - * the client area. - * - * BUGS - * The drag image should be drawn semitransparent. - */ - -BOOL WINAPI -ImageList_DragMove (INT x, INT y) -{ - TRACE("(x=%d y=%d)\n", x, y); - - if (!is_valid(InternalDrag.himl)) - return FALSE; - - /* draw/update the drag image */ - if (InternalDrag.bShow) { - HDC hdcDrag; - HDC hdcOffScreen; - HDC hdcBg; - HBITMAP hbmOffScreen; - INT origNewX, origNewY; - INT origOldX, origOldY; - INT origRegX, origRegY; - INT sizeRegX, sizeRegY; - - - /* calculate the update region */ - origNewX = x - InternalDrag.dxHotspot; - origNewY = y - InternalDrag.dyHotspot; - origOldX = InternalDrag.x - InternalDrag.dxHotspot; - origOldY = InternalDrag.y - InternalDrag.dyHotspot; - origRegX = min(origNewX, origOldX); - origRegY = min(origNewY, origOldY); - sizeRegX = InternalDrag.himl->cx + abs(x - InternalDrag.x); - sizeRegY = InternalDrag.himl->cy + abs(y - InternalDrag.y); - - hdcDrag = GetDCEx(InternalDrag.hwnd, 0, - DCX_WINDOW | DCX_CACHE | DCX_LOCKWINDOWUPDATE); - hdcOffScreen = CreateCompatibleDC(hdcDrag); - hdcBg = CreateCompatibleDC(hdcDrag); - - hbmOffScreen = CreateCompatibleBitmap(hdcDrag, sizeRegX, sizeRegY); - SelectObject(hdcOffScreen, hbmOffScreen); - SelectObject(hdcBg, InternalDrag.hbmBg); - - /* get the actual background of the update region */ - BitBlt(hdcOffScreen, 0, 0, sizeRegX, sizeRegY, hdcDrag, - origRegX, origRegY, SRCCOPY); - /* erase the old image */ - BitBlt(hdcOffScreen, origOldX - origRegX, origOldY - origRegY, - InternalDrag.himl->cx, InternalDrag.himl->cy, hdcBg, 0, 0, - SRCCOPY); - /* save the background */ - BitBlt(hdcBg, 0, 0, InternalDrag.himl->cx, InternalDrag.himl->cy, - hdcOffScreen, origNewX - origRegX, origNewY - origRegY, SRCCOPY); - /* draw the image */ - ImageList_InternalDragDraw(hdcOffScreen, origNewX - origRegX, - origNewY - origRegY); - /* draw the update region to the screen */ - BitBlt(hdcDrag, origRegX, origRegY, sizeRegX, sizeRegY, - hdcOffScreen, 0, 0, SRCCOPY); - - DeleteDC(hdcBg); - DeleteDC(hdcOffScreen); - DeleteObject(hbmOffScreen); - ReleaseDC(InternalDrag.hwnd, hdcDrag); - } - - /* update the image position */ - InternalDrag.x = x; - InternalDrag.y = y; - - return TRUE; -} - - -/************************************************************************* - * ImageList_DragShowNolock [COMCTL32.@] - * - * Shows or hides the drag image. - * - * PARAMS - * bShow [I] TRUE shows the drag image, FALSE hides it. - * - * RETURNS - * Success: TRUE - * Failure: FALSE - * - * BUGS - * The drag image should be drawn semitransparent. - */ - -BOOL WINAPI -ImageList_DragShowNolock (BOOL bShow) -{ - HDC hdcDrag; - HDC hdcBg; - INT x, y; - - if (!is_valid(InternalDrag.himl)) - return FALSE; - - TRACE("bShow=0x%X!\n", bShow); - - /* DragImage is already visible/hidden */ - if ((InternalDrag.bShow && bShow) || (!InternalDrag.bShow && !bShow)) { - return FALSE; - } - - /* position of the origin of the DragImage */ - x = InternalDrag.x - InternalDrag.dxHotspot; - y = InternalDrag.y - InternalDrag.dyHotspot; - - hdcDrag = GetDCEx (InternalDrag.hwnd, 0, - DCX_WINDOW | DCX_CACHE | DCX_LOCKWINDOWUPDATE); - if (!hdcDrag) { - return FALSE; - } - - hdcBg = CreateCompatibleDC(hdcDrag); - if (!InternalDrag.hbmBg) { - InternalDrag.hbmBg = CreateCompatibleBitmap(hdcDrag, - InternalDrag.himl->cx, InternalDrag.himl->cy); - } - SelectObject(hdcBg, InternalDrag.hbmBg); - - if (bShow) { - /* save the background */ - BitBlt(hdcBg, 0, 0, InternalDrag.himl->cx, InternalDrag.himl->cy, - hdcDrag, x, y, SRCCOPY); - /* show the image */ - ImageList_InternalDragDraw(hdcDrag, x, y); - } else { - /* hide the image */ - BitBlt(hdcDrag, x, y, InternalDrag.himl->cx, InternalDrag.himl->cy, - hdcBg, 0, 0, SRCCOPY); - } - - InternalDrag.bShow = !InternalDrag.bShow; - - DeleteDC(hdcBg); - ReleaseDC (InternalDrag.hwnd, hdcDrag); - return TRUE; -} - - -/************************************************************************* - * ImageList_Draw [COMCTL32.@] - * - * Draws an image. - * - * PARAMS - * himl [I] handle to image list - * i [I] image index - * hdc [I] handle to device context - * x [I] x position - * y [I] y position - * fStyle [I] drawing flags - * - * RETURNS - * Success: TRUE - * Failure: FALSE - * - * SEE - * ImageList_DrawEx. - */ - -BOOL WINAPI -ImageList_Draw (HIMAGELIST himl, INT i, HDC hdc, INT x, INT y, UINT fStyle) -{ - return ImageList_DrawEx (himl, i, hdc, x, y, 0, 0, - CLR_DEFAULT, CLR_DEFAULT, fStyle); -} - - -/************************************************************************* - * ImageList_DrawEx [COMCTL32.@] - * - * Draws an image and allows to use extended drawing features. - * - * PARAMS - * himl [I] handle to image list - * i [I] image index - * hdc [I] handle to device context - * x [I] X position - * y [I] Y position - * dx [I] X offset - * dy [I] Y offset - * rgbBk [I] background color - * rgbFg [I] foreground color - * fStyle [I] drawing flags - * - * RETURNS - * Success: TRUE - * Failure: FALSE - * - * NOTES - * Calls ImageList_DrawIndirect. - * - * SEE - * ImageList_DrawIndirect. - */ - -BOOL WINAPI -ImageList_DrawEx (HIMAGELIST himl, INT i, HDC hdc, INT x, INT y, - INT dx, INT dy, COLORREF rgbBk, COLORREF rgbFg, - UINT fStyle) -{ - IMAGELISTDRAWPARAMS imldp; - - ZeroMemory (&imldp, sizeof(imldp)); - imldp.cbSize = sizeof(imldp); - imldp.himl = himl; - imldp.i = i; - imldp.hdcDst = hdc, - imldp.x = x; - imldp.y = y; - imldp.cx = dx; - imldp.cy = dy; - imldp.rgbBk = rgbBk; - imldp.rgbFg = rgbFg; - imldp.fStyle = fStyle; - - return ImageList_DrawIndirect (&imldp); -} - - -/************************************************************************* - * ImageList_DrawIndirect [COMCTL32.@] - * - * Draws an image using various parameters specified in pimldp. - * - * PARAMS - * pimldp [I] pointer to IMAGELISTDRAWPARAMS structure. - * - * RETURNS - * Success: TRUE - * Failure: FALSE - */ - -BOOL WINAPI -ImageList_DrawIndirect (IMAGELISTDRAWPARAMS *pimldp) -{ - INT cx, cy, lx, ly, nOvlIdx; - DWORD fState, dwRop; - UINT fStyle; - COLORREF clrBk, oldImageBk, oldImageFg; - HDC hImageDC, hImageListDC, hMaskListDC; - HBITMAP hImageBmp, hOldImageBmp, hBlendMaskBmp; - BOOL bIsTransparent, bBlend, bResult = FALSE; - HIMAGELIST himl; - - if (!pimldp || !(himl = pimldp->himl)) return FALSE; - if (!is_valid(himl)) return FALSE; - if ((pimldp->i < 0) || (pimldp->i >= himl->cCurImage)) return FALSE; - - lx = himl->cx * pimldp->i + pimldp->xBitmap; - ly = pimldp->yBitmap; - - fState = pimldp->cbSize < sizeof(IMAGELISTDRAWPARAMS) ? ILS_NORMAL : pimldp->fState; - fStyle = pimldp->fStyle & ~ILD_OVERLAYMASK; - cx = (pimldp->cx == 0) ? himl->cx : pimldp->cx; - cy = (pimldp->cy == 0) ? himl->cy : pimldp->cy; - clrBk = (pimldp->rgbBk == CLR_DEFAULT) ? himl->clrBk : pimldp->rgbBk; - bIsTransparent = (fStyle & ILD_TRANSPARENT) || clrBk == CLR_NONE; - bBlend = fStyle & (ILD_BLEND25 | ILD_BLEND50); - - TRACE("himl(0x%lx) hbmMask(%p) iImage(%d) x(%d) y(%d) cx(%d) cy(%d)\n", - (DWORD)himl, himl->hbmMask, pimldp->i, pimldp->x, pimldp->y, cx, cy); - - /* we will use these DCs to access the images and masks in the ImageList */ - hImageListDC = himl->hdcImage; - hMaskListDC = himl->hdcMask; - - /* these will accumulate the image and mask for the image we're drawing */ - hImageDC = CreateCompatibleDC( pimldp->hdcDst ); - hImageBmp = CreateCompatibleBitmap( pimldp->hdcDst, cx, cy ); - hBlendMaskBmp = bBlend ? CreateBitmap(cx, cy, 1, 1, NULL) : 0; - - /* Create a compatible DC. */ - if (!hImageListDC || !hImageDC || !hImageBmp || - (bBlend && !hBlendMaskBmp) || (himl->hbmMask && !hMaskListDC)) - goto cleanup; - - hOldImageBmp = SelectObject(hImageDC, hImageBmp); - - /* - * To obtain a transparent look, background color should be set - * to white and foreground color to black when blting the - * monochrome mask. - */ - oldImageFg = SetTextColor( hImageDC, RGB( 0, 0, 0 ) ); - oldImageBk = SetBkColor( hImageDC, RGB( 0xff, 0xff, 0xff ) ); - - /* - * Draw the initial image - */ - if (fStyle & ILD_MASK) { - if (himl->hbmMask) { - BitBlt(hImageDC, 0, 0, cx, cy, hMaskListDC, lx, ly, SRCCOPY); - } else { - HBRUSH hOldBrush = SelectObject (hImageDC, GetStockObject(BLACK_BRUSH)); - PatBlt( hImageDC, 0, 0, cx, cy, PATCOPY); - SelectObject(hImageDC, hOldBrush); - } - } else if (himl->hbmMask && !bIsTransparent) { - /* blend the image with the needed solid background */ - HBRUSH hOldBrush = SelectObject (hImageDC, CreateSolidBrush (clrBk)); - PatBlt( hImageDC, 0, 0, cx, cy, PATCOPY ); - BitBlt( hImageDC, 0, 0, cx, cy, hMaskListDC, lx, ly, SRCAND ); - BitBlt( hImageDC, 0, 0, cx, cy, hImageListDC, lx, ly, SRCPAINT ); - DeleteObject (SelectObject (hImageDC, hOldBrush)); - } else { - /* start off with the image, if we have a mask, we'll use it later */ - BitBlt( hImageDC, 0, 0, cx, cy, hImageListDC, lx, ly, SRCCOPY); - } - - /* Time for blending, if required */ - if (bBlend) { - HBRUSH hBlendBrush, hOldBrush; - COLORREF clrBlend = pimldp->rgbFg; - HDC hBlendMaskDC = hImageListDC; - HBITMAP hOldBitmap; - - /* Create the blend Mask */ - hOldBitmap = SelectObject(hBlendMaskDC, hBlendMaskBmp); - hBlendBrush = fStyle & ILD_BLEND50 ? himl->hbrBlend50 : himl->hbrBlend25; - hOldBrush = (HBRUSH) SelectObject(hBlendMaskDC, hBlendBrush); - PatBlt(hBlendMaskDC, 0, 0, cx, cy, PATCOPY); - SelectObject(hBlendMaskDC, hOldBrush); - - /* Modify the blend mask if an Image Mask exist */ - if(himl->hbmMask) { - BitBlt(hBlendMaskDC, 0, 0, cx, cy, hMaskListDC, lx, ly, 0x220326); /* NOTSRCAND */ - BitBlt(hBlendMaskDC, 0, 0, cx, cy, hBlendMaskDC, 0, 0, NOTSRCCOPY); - } - - /* now apply blend to the current image given the BlendMask */ - if (clrBlend == CLR_DEFAULT) clrBlend = GetSysColor (COLOR_HIGHLIGHT); - else if (clrBlend == CLR_NONE) clrBlend = GetTextColor (pimldp->hdcDst); - hOldBrush = (HBRUSH) SelectObject (hImageDC, CreateSolidBrush(clrBlend)); - BitBlt (hImageDC, 0, 0, cx, cy, hBlendMaskDC, 0, 0, 0xB8074A); /* PSDPxax */ - DeleteObject(SelectObject(hImageDC, hOldBrush)); - SelectObject(hBlendMaskDC, hOldBitmap); - } - - /* Now do the overlay image, if any */ - nOvlIdx = (pimldp->fStyle & ILD_OVERLAYMASK) >> 8; - if ( (nOvlIdx >= 1) && (nOvlIdx <= MAX_OVERLAYIMAGE)) { - nOvlIdx = himl->nOvlIdx[nOvlIdx - 1]; - if ((nOvlIdx >= 0) && (nOvlIdx < himl->cCurImage)) { - const INT ox = himl->cx * nOvlIdx + pimldp->xBitmap; - if (himl->hbmMask && !(fStyle & ILD_IMAGE)) - BitBlt (hImageDC, 0, 0, cx, cy, hMaskListDC, ox, ly, SRCAND); - BitBlt (hImageDC, 0, 0, cx, cy, hImageListDC, ox, ly, SRCPAINT); - } - } - - if (fState & ILS_SATURATE) FIXME("ILS_SATURATE: unimplemented!\n"); - if (fState & ILS_GLOW) FIXME("ILS_GLOW: unimplemented!\n"); - if (fState & ILS_SHADOW) FIXME("ILS_SHADOW: unimplemented!\n"); - if (fState & ILS_ALPHA) FIXME("ILS_ALPHA: unimplemented!\n"); - - if (fStyle & ILD_PRESERVEALPHA) FIXME("ILD_PRESERVEALPHA: unimplemented!\n"); - if (fStyle & ILD_SCALE) FIXME("ILD_SCALE: unimplemented!\n"); - if (fStyle & ILD_DPISCALE) FIXME("ILD_DPISCALE: unimplemented!\n"); - - /* now copy the image to the screen */ - dwRop = SRCCOPY; - if (himl->hbmMask && bIsTransparent && !(fStyle & ILD_MASK)) { - COLORREF oldDstFg = SetTextColor(pimldp->hdcDst, RGB( 0, 0, 0 ) ); - COLORREF oldDstBk = SetBkColor(pimldp->hdcDst, RGB( 0xff, 0xff, 0xff )); - BitBlt (pimldp->hdcDst, pimldp->x, pimldp->y, cx, cy, hMaskListDC, lx, ly, SRCAND); - SetBkColor(pimldp->hdcDst, oldDstBk); - SetTextColor(pimldp->hdcDst, oldDstFg); - dwRop = SRCPAINT; - } - if (fStyle & ILD_ROP) dwRop = pimldp->dwRop; - BitBlt (pimldp->hdcDst, pimldp->x, pimldp->y, cx, cy, hImageDC, 0, 0, dwRop); - - bResult = TRUE; - - /* cleanup the mess */ - SetBkColor(hImageDC, oldImageBk); - SetTextColor(hImageDC, oldImageFg); - SelectObject(hImageDC, hOldImageBmp); -cleanup: - DeleteObject(hBlendMaskBmp); - DeleteObject(hImageBmp); - DeleteDC(hImageDC); - - return bResult; -} - - -/************************************************************************* - * ImageList_Duplicate [COMCTL32.@] - * - * Duplicates an image list. - * - * PARAMS - * himlSrc [I] source image list handle - * - * RETURNS - * Success: Handle of duplicated image list. - * Failure: NULL - */ - -HIMAGELIST WINAPI -ImageList_Duplicate (HIMAGELIST himlSrc) -{ - HIMAGELIST himlDst; - - if (!is_valid(himlSrc)) { - ERR("Invalid image list handle!\n"); - return NULL; - } - - himlDst = ImageList_Create (himlSrc->cx, himlSrc->cy, himlSrc->flags, - himlSrc->cInitial, himlSrc->cGrow); - - if (himlDst) - { - BitBlt (himlDst->hdcImage, 0, 0, himlSrc->cCurImage * himlSrc->cx, himlSrc->cy, - himlSrc->hdcImage, 0, 0, SRCCOPY); - - if (himlDst->hbmMask) - BitBlt (himlDst->hdcMask, 0, 0, himlSrc->cCurImage * himlSrc->cx, himlSrc->cy, - himlSrc->hdcMask, 0, 0, SRCCOPY); - - himlDst->cCurImage = himlSrc->cCurImage; - himlDst->cMaxImage = himlSrc->cMaxImage; - } - return himlDst; -} - - -/************************************************************************* - * ImageList_EndDrag [COMCTL32.@] - * - * Finishes a drag operation. - * - * PARAMS - * no Parameters - * - * RETURNS - * Success: TRUE - * Failure: FALSE - */ - -VOID WINAPI -ImageList_EndDrag (void) -{ - /* cleanup the InternalDrag struct */ - InternalDrag.hwnd = 0; - ImageList_Destroy (InternalDrag.himl); - InternalDrag.himl = 0; - InternalDrag.x= 0; - InternalDrag.y= 0; - InternalDrag.dxHotspot = 0; - InternalDrag.dyHotspot = 0; - InternalDrag.bShow = FALSE; - DeleteObject(InternalDrag.hbmBg); - InternalDrag.hbmBg = 0; -} - - -/************************************************************************* - * ImageList_GetBkColor [COMCTL32.@] - * - * Returns the background color of an image list. - * - * PARAMS - * himl [I] Image list handle. - * - * RETURNS - * Success: background color - * Failure: CLR_NONE - */ - -COLORREF WINAPI -ImageList_GetBkColor (HIMAGELIST himl) -{ - return himl ? himl->clrBk : CLR_NONE; -} - - -/************************************************************************* - * ImageList_GetDragImage [COMCTL32.@] - * - * Returns the handle to the internal drag image list. - * - * PARAMS - * ppt [O] Pointer to the drag position. Can be NULL. - * pptHotspot [O] Pointer to the position of the hot spot. Can be NULL. - * - * RETURNS - * Success: Handle of the drag image list. - * Failure: NULL. - */ - -HIMAGELIST WINAPI -ImageList_GetDragImage (POINT *ppt, POINT *pptHotspot) -{ - if (is_valid(InternalDrag.himl)) { - if (ppt) { - ppt->x = InternalDrag.x; - ppt->y = InternalDrag.y; - } - if (pptHotspot) { - pptHotspot->x = InternalDrag.dxHotspot; - pptHotspot->y = InternalDrag.dyHotspot; - } - return (InternalDrag.himl); - } - - return NULL; -} - - -/************************************************************************* - * ImageList_GetFlags [COMCTL32.@] - * - * Gets the flags of the specified image list. - * - * PARAMS - * himl [I] Handle to image list - * - * RETURNS - * Image list flags. - * - * BUGS - * Stub. - */ - -DWORD WINAPI -ImageList_GetFlags(HIMAGELIST himl) -{ - FIXME("(%p):empty stub\n", himl); - return 0; -} - - -/************************************************************************* - * ImageList_GetIcon [COMCTL32.@] - * - * Creates an icon from a masked image of an image list. - * - * PARAMS - * himl [I] handle to image list - * i [I] image index - * flags [I] drawing style flags - * - * RETURNS - * Success: icon handle - * Failure: NULL - */ - -HICON WINAPI -ImageList_GetIcon (HIMAGELIST himl, INT i, UINT fStyle) -{ - ICONINFO ii; - HICON hIcon; - HBITMAP hOldDstBitmap; - HDC hdcDst; - - TRACE("%p %d %d\n", himl, i, fStyle); - if (!is_valid(himl) || (i < 0) || (i >= himl->cCurImage)) return NULL; - - hdcDst = CreateCompatibleDC(0); - - ii.fIcon = TRUE; - ii.xHotspot = 0; - ii.yHotspot = 0; - - /* draw mask*/ - ii.hbmMask = CreateCompatibleBitmap (hdcDst, himl->cx, himl->cy); - hOldDstBitmap = SelectObject (hdcDst, ii.hbmMask); - PatBlt (hdcDst, 0, 0, himl->cx, himl->cy, WHITENESS); - ImageList_Draw(himl, i, hdcDst, 0, 0, fStyle | ILD_MASK); - - /* draw image*/ - ii.hbmColor = CreateCompatibleBitmap (himl->hdcImage, himl->cx, himl->cy); - SelectObject (hdcDst, ii.hbmColor); - PatBlt (hdcDst, 0, 0, himl->cx, himl->cy, BLACKNESS); - ImageList_Draw(himl, i, hdcDst, 0, 0, fStyle | ILD_TRANSPARENT); - - /* - * CreateIconIndirect requires us to deselect the bitmaps from - * the DCs before calling - */ - SelectObject(hdcDst, hOldDstBitmap); - - hIcon = CreateIconIndirect (&ii); - - DeleteObject (ii.hbmMask); - DeleteObject (ii.hbmColor); - DeleteDC (hdcDst); - - return hIcon; -} - - -/************************************************************************* - * ImageList_GetIconSize [COMCTL32.@] - * - * Retrieves the size of an image in an image list. - * - * PARAMS - * himl [I] handle to image list - * cx [O] pointer to the image width. - * cy [O] pointer to the image height. - * - * RETURNS - * Success: TRUE - * Failure: FALSE - * - * NOTES - * All images in an image list have the same size. - */ - -BOOL WINAPI -ImageList_GetIconSize (HIMAGELIST himl, INT *cx, INT *cy) -{ - if (!is_valid(himl)) - return FALSE; - if ((himl->cx <= 0) || (himl->cy <= 0)) - return FALSE; - - if (cx) - *cx = himl->cx; - if (cy) - *cy = himl->cy; - - return TRUE; -} - - -/************************************************************************* - * ImageList_GetImageCount [COMCTL32.@] - * - * Returns the number of images in an image list. - * - * PARAMS - * himl [I] handle to image list - * - * RETURNS - * Success: Number of images. - * Failure: 0 - */ - -INT WINAPI -ImageList_GetImageCount (HIMAGELIST himl) -{ - if (!is_valid(himl)) - return 0; - - return himl->cCurImage; -} - - -/************************************************************************* - * ImageList_GetImageInfo [COMCTL32.@] - * - * Returns information about an image in an image list. - * - * PARAMS - * himl [I] handle to image list - * i [I] image index - * pImageInfo [O] pointer to the image information - * - * RETURNS - * Success: TRUE - * Failure: FALSE - */ - -BOOL WINAPI -ImageList_GetImageInfo (HIMAGELIST himl, INT i, IMAGEINFO *pImageInfo) -{ - if (!is_valid(himl) || (pImageInfo == NULL)) - return FALSE; - if ((i < 0) || (i >= himl->cCurImage)) - return FALSE; - - pImageInfo->hbmImage = himl->hbmImage; - pImageInfo->hbmMask = himl->hbmMask; - - pImageInfo->rcImage.top = 0; - pImageInfo->rcImage.bottom = himl->cy; - pImageInfo->rcImage.left = i * himl->cx; - pImageInfo->rcImage.right = (i+1) * himl->cx; - - return TRUE; -} - - -/************************************************************************* - * ImageList_GetImageRect [COMCTL32.@] - * - * Retrieves the rectangle of the specified image in an image list. - * - * PARAMS - * himl [I] handle to image list - * i [I] image index - * lpRect [O] pointer to the image rectangle - * - * RETURNS - * Success: TRUE - * Failure: FALSE - * - * NOTES - * This is an UNDOCUMENTED function!!! - */ - -BOOL WINAPI -ImageList_GetImageRect (HIMAGELIST himl, INT i, LPRECT lpRect) -{ - if (!is_valid(himl) || (lpRect == NULL)) - return FALSE; - if ((i < 0) || (i >= himl->cCurImage)) - return FALSE; - - lpRect->left = i * himl->cx; - lpRect->top = 0; - lpRect->right = lpRect->left + himl->cx; - lpRect->bottom = himl->cy; - - return TRUE; -} - - -/************************************************************************* - * ImageList_LoadImage [COMCTL32.@] - * ImageList_LoadImageA [COMCTL32.@] - * - * Creates an image list from a bitmap, icon or cursor. - * - * PARAMS - * hi [I] instance handle - * lpbmp [I] name or id of the image - * cx [I] width of each image - * cGrow [I] number of images to expand - * clrMask [I] mask color - * uType [I] type of image to load - * uFlags [I] loading flags - * - * RETURNS - * Success: handle to the loaded image list - * Failure: NULL - * - * SEE - * LoadImage () - */ - -HIMAGELIST WINAPI -ImageList_LoadImageA (HINSTANCE hi, LPCSTR lpbmp, INT cx, INT cGrow, - COLORREF clrMask, UINT uType, UINT uFlags) -{ - HIMAGELIST himl = NULL; - HANDLE handle; - INT nImageCount; - - handle = LoadImageA (hi, lpbmp, uType, 0, 0, uFlags); - if (!handle) { - ERR("Error loading image!\n"); - return NULL; - } - - if (uType == IMAGE_BITMAP) { - BITMAP bmp; - GetObjectA (handle, sizeof(BITMAP), &bmp); - - /* To match windows behavior, if cx is set to zero and - the flag DI_DEFAULTSIZE is specified, cx becomes the - system metric value for icons. If the flag is not specified - the function sets the size to the height of the bitmap */ - if (cx == 0) - { - if (uFlags & DI_DEFAULTSIZE) - cx = GetSystemMetrics (SM_CXICON); - else - cx = bmp.bmHeight; - } - - nImageCount = bmp.bmWidth / cx; - - himl = ImageList_Create (cx, bmp.bmHeight, ILC_MASK | ILC_COLOR, - nImageCount, cGrow); - if (!himl) { - DeleteObject (handle); - return NULL; - } - ImageList_AddMasked (himl, (HBITMAP)handle, clrMask); - } - else if ((uType == IMAGE_ICON) || (uType == IMAGE_CURSOR)) { - ICONINFO ii; - BITMAP bmp; - - GetIconInfo (handle, &ii); - GetObjectA (ii.hbmColor, sizeof(BITMAP), (LPVOID)&bmp); - himl = ImageList_Create (bmp.bmWidth, bmp.bmHeight, - ILC_MASK | ILC_COLOR, 1, cGrow); - if (!himl) { - DeleteObject (ii.hbmColor); - DeleteObject (ii.hbmMask); - DeleteObject (handle); - return NULL; - } - ImageList_Add (himl, ii.hbmColor, ii.hbmMask); - DeleteObject (ii.hbmColor); - DeleteObject (ii.hbmMask); - } - - DeleteObject (handle); - - return himl; -} - - -/************************************************************************* - * ImageList_LoadImageW [COMCTL32.@] - * - * Creates an image list from a bitmap, icon or cursor. - * - * PARAMS - * hi [I] instance handle - * lpbmp [I] name or id of the image - * cx [I] width of each image - * cGrow [I] number of images to expand - * clrMask [I] mask color - * uType [I] type of image to load - * uFlags [I] loading flags - * - * RETURNS - * Success: handle to the loaded image list - * Failure: NULL - * - * SEE - * LoadImage () - */ - -HIMAGELIST WINAPI -ImageList_LoadImageW (HINSTANCE hi, LPCWSTR lpbmp, INT cx, INT cGrow, - COLORREF clrMask, UINT uType, UINT uFlags) -{ - HIMAGELIST himl = NULL; - HANDLE handle; - INT nImageCount; - - handle = LoadImageW (hi, lpbmp, uType, 0, 0, uFlags); - if (!handle) { - ERR("Error loading image!\n"); - return NULL; - } - - if (uType == IMAGE_BITMAP) { - BITMAP bmp; - GetObjectW (handle, sizeof(BITMAP), &bmp); - - /* To match windows behavior, if cx is set to zero and - the flag DI_DEFAULTSIZE is specified, cx becomes the - system metric value for icons. If the flag is not specified - the function sets the size to the height of the bitmap */ - if (cx == 0) - { - if (uFlags & DI_DEFAULTSIZE) - cx = GetSystemMetrics (SM_CXICON); - else - cx = bmp.bmHeight; - } - - nImageCount = bmp.bmWidth / cx; - - himl = ImageList_Create (cx, bmp.bmHeight, ILC_MASK | ILC_COLOR, - nImageCount, cGrow); - if (!himl) { - DeleteObject (handle); - return NULL; - } - ImageList_AddMasked (himl, (HBITMAP)handle, clrMask); - } - else if ((uType == IMAGE_ICON) || (uType == IMAGE_CURSOR)) { - ICONINFO ii; - BITMAP bmp; - - GetIconInfo (handle, &ii); - GetObjectW (ii.hbmMask, sizeof(BITMAP), (LPVOID)&bmp); - himl = ImageList_Create (bmp.bmWidth, bmp.bmHeight, - ILC_MASK | ILC_COLOR, 1, cGrow); - if (!himl) { - DeleteObject (ii.hbmColor); - DeleteObject (ii.hbmMask); - DeleteObject (handle); - return NULL; - } - ImageList_Add (himl, ii.hbmColor, ii.hbmMask); - DeleteObject (ii.hbmColor); - DeleteObject (ii.hbmMask); - } - - DeleteObject (handle); - - return himl; -} - - -/************************************************************************* - * ImageList_Merge [COMCTL32.@] - * - * Create an image list containing a merged image from two image lists. - * - * PARAMS - * himl1 [I] handle to first image list - * i1 [I] first image index - * himl2 [I] handle to second image list - * i2 [I] second image index - * dx [I] X offset of the second image relative to the first. - * dy [I] Y offset of the second image relative to the first. - * - * RETURNS - * Success: The newly created image list. It contains a single image - * consisting of the second image merged with the first. - * Failure: NULL, if either himl1 or himl2 are invalid. - * - * NOTES - * - The returned image list should be deleted by the caller using - * ImageList_Destroy() when it is no longer required. - * - If either i1 or i2 are not valid image indices they will be treated - * as a blank image. - */ -HIMAGELIST WINAPI -ImageList_Merge (HIMAGELIST himl1, INT i1, HIMAGELIST himl2, INT i2, - INT dx, INT dy) -{ - HIMAGELIST himlDst = NULL; - INT cxDst, cyDst; - INT xOff1, yOff1, xOff2, yOff2; - INT nX1, nX2; - - TRACE("(himl1=%p i1=%d himl2=%p i2=%d dx=%d dy=%d)\n", himl1, i1, himl2, - i2, dx, dy); - - if (!is_valid(himl1) || !is_valid(himl2)) - return NULL; - - if (dx > 0) { - cxDst = max (himl1->cx, dx + himl2->cx); - xOff1 = 0; - xOff2 = dx; - } - else if (dx < 0) { - cxDst = max (himl2->cx, himl1->cx - dx); - xOff1 = -dx; - xOff2 = 0; - } - else { - cxDst = max (himl1->cx, himl2->cx); - xOff1 = 0; - xOff2 = 0; - } - - if (dy > 0) { - cyDst = max (himl1->cy, dy + himl2->cy); - yOff1 = 0; - yOff2 = dy; - } - else if (dy < 0) { - cyDst = max (himl2->cy, himl1->cy - dy); - yOff1 = -dy; - yOff2 = 0; - } - else { - cyDst = max (himl1->cy, himl2->cy); - yOff1 = 0; - yOff2 = 0; - } - - himlDst = ImageList_Create (cxDst, cyDst, ILC_MASK | ILC_COLOR, 1, 1); - - if (himlDst) - { - nX1 = i1 * himl1->cx; - nX2 = i2 * himl2->cx; - - /* copy image */ - BitBlt (himlDst->hdcImage, 0, 0, cxDst, cyDst, himl1->hdcImage, 0, 0, BLACKNESS); - if (i1 >= 0 && i1 < himl1->cCurImage) - BitBlt (himlDst->hdcImage, xOff1, yOff1, himl1->cx, himl1->cy, himl1->hdcImage, nX1, 0, SRCCOPY); - if (i2 >= 0 && i2 < himl2->cCurImage) - { - BitBlt (himlDst->hdcImage, xOff2, yOff2, himl2->cx, himl2->cy, himl2->hdcMask , nX2, 0, SRCAND); - BitBlt (himlDst->hdcImage, xOff2, yOff2, himl2->cx, himl2->cy, himl2->hdcImage, nX2, 0, SRCPAINT); - } - - /* copy mask */ - BitBlt (himlDst->hdcMask, 0, 0, cxDst, cyDst, himl1->hdcMask, 0, 0, WHITENESS); - if (i1 >= 0 && i1 < himl1->cCurImage) - BitBlt (himlDst->hdcMask, xOff1, yOff1, himl1->cx, himl1->cy, himl1->hdcMask, nX1, 0, SRCCOPY); - if (i2 >= 0 && i2 < himl2->cCurImage) - BitBlt (himlDst->hdcMask, xOff2, yOff2, himl2->cx, himl2->cy, himl2->hdcMask, nX2, 0, SRCAND); - - himlDst->cCurImage = 1; - } - - return himlDst; -} - - -/* helper for _read_bitmap currently unused */ -#if 0 -static int may_use_dibsection(HDC hdc) { - int bitspixel = GetDeviceCaps(hdc,BITSPIXEL)*GetDeviceCaps(hdc,PLANES); - if (bitspixel>8) - return TRUE; - if (bitspixel<=4) - return FALSE; - return GetDeviceCaps(hdc,CAPS1) & C1_DIBENGINE; -} -#endif - -/* helper for ImageList_Read, see comments below */ -static HBITMAP _read_bitmap(LPSTREAM pstm,int ilcFlag,int cx,int cy) { - HDC xdc = 0, hBitmapDC =0; - BITMAPFILEHEADER bmfh; - BITMAPINFOHEADER bmih; - int bitsperpixel,palspace,longsperline,width,height; - LPBITMAPINFOHEADER bmihc = NULL; - int result = 0; - HBITMAP hbitmap = 0, hDIB = 0; - LPBYTE bits = NULL; - - if (!SUCCEEDED(IStream_Read ( pstm, &bmfh, sizeof(bmfh), NULL)) || - (bmfh.bfType != (('M'<<8)|'B')) || - !SUCCEEDED(IStream_Read ( pstm, &bmih, sizeof(bmih), NULL)) || - (bmih.biSize != sizeof(bmih)) - ) - return 0; - - bitsperpixel = bmih.biPlanes * bmih.biBitCount; - if (bitsperpixel<=8) - palspace = (1<>5; - bmihc->biSizeImage = (longsperline*height)<<2; - - /* read the palette right after the end of the bitmapinfoheader */ - if (palspace) - if (!SUCCEEDED(IStream_Read ( pstm, bmihc+1, palspace, NULL))) - goto ret1; - - xdc = GetDC(0); -#if 0 /* Magic for NxM -> 1x(N*M) not implemented for DIB Sections */ - if ((bitsperpixel>1) && - ((ilcFlag!=ILC_COLORDDB) && (!ilcFlag || may_use_dibsection(xdc))) - ) { - hbitmap = CreateDIBSection(xdc,(BITMAPINFO*)bmihc,0,(LPVOID*)&bits,0,0); - if (!hbitmap) - goto ret1; - if (!SUCCEEDED(IStream_Read( pstm, bits, bmihc->biSizeImage, NULL))) - goto ret1; - result = 1; - } else -#endif - { - int i,nwidth,nheight,nRows; - - nwidth = width*(height/cy); - nheight = cy; - nRows = (height/cy); - - if (bitsperpixel==1) - hbitmap = CreateBitmap(nwidth,nheight,1,1,NULL); - else - hbitmap = CreateCompatibleBitmap(xdc,nwidth,nheight); - - hDIB = CreateDIBSection(xdc,(BITMAPINFO*)bmihc,0,(LPVOID*)&bits,0,0); - if (!hDIB) - goto ret1; - if (!SUCCEEDED(IStream_Read( pstm, bits, bmihc->biSizeImage, NULL))) - goto ret1; - - hBitmapDC = CreateCompatibleDC(0); - SelectObject(hBitmapDC, hbitmap); - - /* Copy the NxM bitmap into a 1x(N*M) bitmap we need, linewise */ - /* Do not forget that windows bitmaps are bottom->top */ - TRACE("nRows=%d\n", nRows); - for (i=0; i < nRows; i++){ - StretchDIBits(hBitmapDC, width*i, 0, width, cy, 0, cy*(nRows-1-i), width, cy, bits, - (BITMAPINFO*)bmihc, DIB_RGB_COLORS, SRCCOPY); - } - - result = 1; - } -ret1: - if (xdc) ReleaseDC(0,xdc); - if (bmihc) LocalFree((HLOCAL)bmihc); - if (hDIB) DeleteObject(hDIB); - if (hBitmapDC) DeleteDC(hBitmapDC); - if (!result) { - if (hbitmap) { - DeleteObject(hbitmap); - hbitmap = 0; - } - } - return hbitmap; -} - -/************************************************************************* - * ImageList_Read [COMCTL32.@] - * - * Reads an image list from a stream. - * - * PARAMS - * pstm [I] pointer to a stream - * - * RETURNS - * Success: handle to image list - * Failure: NULL - * - * The format is like this: - * ILHEAD ilheadstruct; - * - * for the color image part: - * BITMAPFILEHEADER bmfh; - * BITMAPINFOHEADER bmih; - * only if it has a palette: - * RGBQUAD rgbs[nr_of_paletted_colors]; - * - * BYTE colorbits[imagesize]; - * - * the following only if the ILC_MASK bit is set in ILHEAD.ilFlags: - * BITMAPFILEHEADER bmfh_mask; - * BITMAPINFOHEADER bmih_mask; - * only if it has a palette (it usually does not): - * RGBQUAD rgbs[nr_of_paletted_colors]; - * - * BYTE maskbits[imagesize]; - * - * CAVEAT: Those images are within a NxM bitmap, not the 1xN we expect. - * _read_bitmap needs to convert them. - */ -HIMAGELIST WINAPI ImageList_Read (LPSTREAM pstm) -{ - ILHEAD ilHead; - HIMAGELIST himl; - HBITMAP hbmColor=0,hbmMask=0; - int i; - - if (!SUCCEEDED(IStream_Read (pstm, &ilHead, sizeof(ILHEAD), NULL))) - return NULL; - if (ilHead.usMagic != (('L' << 8) | 'I')) - return NULL; - if (ilHead.usVersion != 0x101) /* probably version? */ - return NULL; - -#if 0 - FIXME(" ilHead.cCurImage = %d\n",ilHead.cCurImage); - FIXME(" ilHead.cMaxImage = %d\n",ilHead.cMaxImage); - FIXME(" ilHead.cGrow = %d\n",ilHead.cGrow); - FIXME(" ilHead.cx = %d\n",ilHead.cx); - FIXME(" ilHead.cy = %d\n",ilHead.cy); - FIXME(" ilHead.flags = %x\n",ilHead.flags); - FIXME(" ilHead.ovls[0] = %d\n",ilHead.ovls[0]); - FIXME(" ilHead.ovls[1] = %d\n",ilHead.ovls[1]); - FIXME(" ilHead.ovls[2] = %d\n",ilHead.ovls[2]); - FIXME(" ilHead.ovls[3] = %d\n",ilHead.ovls[3]); -#endif - - hbmColor = _read_bitmap(pstm,ilHead.flags & ~ILC_MASK,ilHead.cx,ilHead.cy); - if (!hbmColor) - return NULL; - if (ilHead.flags & ILC_MASK) { - hbmMask = _read_bitmap(pstm,0,ilHead.cx,ilHead.cy); - if (!hbmMask) { - DeleteObject(hbmColor); - return NULL; - } - } - - himl = ImageList_Create ( - ilHead.cx, - ilHead.cy, - ilHead.flags, - 1, /* initial */ - ilHead.cGrow - ); - if (!himl) { - DeleteObject(hbmColor); - DeleteObject(hbmMask); - return NULL; - } - SelectObject(himl->hdcImage, hbmColor); - DeleteObject(himl->hbmImage); - himl->hbmImage = hbmColor; - if (hbmMask){ - SelectObject(himl->hdcMask, hbmMask); - DeleteObject(himl->hbmMask); - himl->hbmMask = hbmMask; - } - himl->cCurImage = ilHead.cCurImage; - himl->cMaxImage = ilHead.cMaxImage; - - ImageList_SetBkColor(himl,ilHead.bkcolor); - for (i=0;i<4;i++) - ImageList_SetOverlayImage(himl,ilHead.ovls[i],i+1); - return himl; -} - - -/************************************************************************* - * ImageList_Remove [COMCTL32.@] - * - * Removes an image from an image list - * - * PARAMS - * himl [I] image list handle - * i [I] image index - * - * RETURNS - * Success: TRUE - * Failure: FALSE - */ - -BOOL WINAPI -ImageList_Remove (HIMAGELIST himl, INT i) -{ - HBITMAP hbmNewImage, hbmNewMask; - HDC hdcBmp; - INT cxNew, nCount; - - TRACE("(himl=%p i=%d)\n", himl, i); - - if (!is_valid(himl)) { - ERR("Invalid image list handle!\n"); - return FALSE; - } - - if ((i < -1) || (i >= himl->cCurImage)) { - TRACE("index out of range! %d\n", i); - return FALSE; - } - - if (i == -1) { - /* remove all */ - if (himl->cCurImage == 0) { - /* remove all on empty ImageList is allowed */ - TRACE("remove all on empty ImageList!\n"); - return TRUE; - } - - himl->cMaxImage = himl->cInitial + himl->cGrow; - himl->cCurImage = 0; - for (nCount = 0; nCount < MAX_OVERLAYIMAGE; nCount++) - himl->nOvlIdx[nCount] = -1; - - hbmNewImage = ImageList_CreateImage(himl->hdcImage, himl, himl->cMaxImage * himl->cx, himl->cy); - SelectObject (himl->hdcImage, hbmNewImage); - DeleteObject (himl->hbmImage); - himl->hbmImage = hbmNewImage; - - if (himl->hbmMask) { - hbmNewMask = CreateBitmap (himl->cMaxImage * himl->cx, himl->cy, - 1, 1, NULL); - SelectObject (himl->hdcMask, hbmNewMask); - DeleteObject (himl->hbmMask); - himl->hbmMask = hbmNewMask; - } - } - else { - /* delete one image */ - TRACE("Remove single image! %d\n", i); - - /* create new bitmap(s) */ - nCount = (himl->cCurImage + himl->cGrow - 1); - cxNew = nCount * himl->cx; - - TRACE(" - Number of images: %d / %d (Old/New)\n", - himl->cCurImage, himl->cCurImage - 1); - TRACE(" - Max. number of images: %d / %d (Old/New)\n", - himl->cMaxImage, himl->cCurImage + himl->cGrow - 1); - - hbmNewImage = ImageList_CreateImage(himl->hdcImage, himl, cxNew, himl->cy); - - if (himl->hbmMask) - hbmNewMask = CreateBitmap (cxNew, himl->cy, 1, 1, NULL); - else - hbmNewMask = 0; /* Just to keep compiler happy! */ - - hdcBmp = CreateCompatibleDC (0); - - /* copy all images and masks prior to the "removed" image */ - if (i > 0) { - TRACE("Pre image copy: Copy %d images\n", i); - - SelectObject (hdcBmp, hbmNewImage); - BitBlt (hdcBmp, 0, 0, i * himl->cx, himl->cy, - himl->hdcImage, 0, 0, SRCCOPY); - - if (himl->hbmMask) { - SelectObject (hdcBmp, hbmNewMask); - BitBlt (hdcBmp, 0, 0, i * himl->cx, himl->cy, - himl->hdcMask, 0, 0, SRCCOPY); - } - } - - /* copy all images and masks behind the removed image */ - if (i < himl->cCurImage - 1) { - TRACE("Post image copy!\n"); - SelectObject (hdcBmp, hbmNewImage); - BitBlt (hdcBmp, i * himl->cx, 0, (himl->cCurImage - i - 1) * himl->cx, - himl->cy, himl->hdcImage, (i + 1) * himl->cx, 0, SRCCOPY); - - if (himl->hbmMask) { - SelectObject (hdcBmp, hbmNewMask); - BitBlt (hdcBmp, i * himl->cx, 0, - (himl->cCurImage - i - 1) * himl->cx, - himl->cy, himl->hdcMask, (i + 1) * himl->cx, 0, SRCCOPY); - } - } - - DeleteDC (hdcBmp); - - /* delete old images and insert new ones */ - SelectObject (himl->hdcImage, hbmNewImage); - DeleteObject (himl->hbmImage); - himl->hbmImage = hbmNewImage; - if (himl->hbmMask) { - SelectObject (himl->hdcMask, hbmNewMask); - DeleteObject (himl->hbmMask); - himl->hbmMask = hbmNewMask; - } - - himl->cCurImage--; - himl->cMaxImage = himl->cCurImage + himl->cGrow; - } - - return TRUE; -} - - -/************************************************************************* - * ImageList_Replace [COMCTL32.@] - * - * Replaces an image in an image list with a new image. - * - * PARAMS - * himl [I] handle to image list - * i [I] image index - * hbmImage [I] handle to image bitmap - * hbmMask [I] handle to mask bitmap. Can be NULL. - * - * RETURNS - * Success: TRUE - * Failure: FALSE - */ - -BOOL WINAPI -ImageList_Replace (HIMAGELIST himl, INT i, HBITMAP hbmImage, - HBITMAP hbmMask) -{ - HDC hdcImage; - BITMAP bmp; - - TRACE("%p %d %p %p\n", himl, i, hbmImage, hbmMask); - - if (!is_valid(himl)) { - ERR("Invalid image list handle!\n"); - return FALSE; - } - - if ((i >= himl->cMaxImage) || (i < 0)) { - ERR("Invalid image index!\n"); - return FALSE; - } - - hdcImage = CreateCompatibleDC (0); - GetObjectA (hbmImage, sizeof(BITMAP), (LPVOID)&bmp); - - /* Replace Image */ - SelectObject (hdcImage, hbmImage); - - StretchBlt (himl->hdcImage, i * himl->cx, 0, himl->cx, himl->cy, - hdcImage, 0, 0, bmp.bmWidth, bmp.bmHeight, SRCCOPY); - - if (himl->hbmMask) - { - /* Replace Mask */ - SelectObject (hdcImage, hbmMask); - - StretchBlt (himl->hdcMask, i * himl->cx, 0, himl->cx, himl->cy, - hdcImage, 0, 0, bmp.bmWidth, bmp.bmHeight, SRCCOPY); - - - /* Remove the background from the image - */ - StretchBlt (himl->hdcImage, - i*himl->cx, 0, himl->cx, himl->cy, - hdcImage, - 0, 0, bmp.bmWidth, bmp.bmHeight, - 0x220326); /* NOTSRCAND */ - } - - DeleteDC (hdcImage); - - return TRUE; -} - - -/************************************************************************* - * ImageList_ReplaceIcon [COMCTL32.@] - * - * Replaces an image in an image list using an icon. - * - * PARAMS - * himl [I] handle to image list - * i [I] image index - * hIcon [I] handle to icon - * - * RETURNS - * Success: index of the replaced image - * Failure: -1 - */ - -INT WINAPI -ImageList_ReplaceIcon (HIMAGELIST himl, INT i, HICON hIcon) -{ - HDC hdcImage; - INT nIndex; - HICON hBestFitIcon; - HBITMAP hbmOldSrc; - ICONINFO ii; - BITMAP bmp; - - TRACE("(%p %d %p)\n", himl, i, hIcon); - - if (!is_valid(himl)) - return -1; - if ((i >= himl->cMaxImage) || (i < -1)) - return -1; - - hBestFitIcon = CopyImage( - hIcon, IMAGE_ICON, - himl->cx, himl->cy, - LR_COPYFROMRESOURCE); - - GetIconInfo (hBestFitIcon, &ii); - if (ii.hbmMask == 0) - ERR("no mask!\n"); - if (ii.hbmColor == 0) - ERR("no color!\n"); - GetObjectA (ii.hbmMask, sizeof(BITMAP), (LPVOID)&bmp); - - if (i == -1) { - if (himl->cCurImage + 1 > himl->cMaxImage) - IMAGELIST_InternalExpandBitmaps (himl, 1, 0, 0); - - nIndex = himl->cCurImage; - himl->cCurImage++; - } - else - nIndex = i; - - hdcImage = CreateCompatibleDC (0); - TRACE("hdcImage=%p\n", hdcImage); - if (hdcImage == 0) - ERR("invalid hdcImage!\n"); - - SetTextColor(himl->hdcImage, RGB(0,0,0)); - SetBkColor (himl->hdcImage, RGB(255,255,255)); - hbmOldSrc = SelectObject (hdcImage, ii.hbmColor); - - StretchBlt (himl->hdcImage, nIndex * himl->cx, 0, himl->cx, himl->cy, - hdcImage, 0, 0, bmp.bmWidth, bmp.bmHeight, SRCCOPY); - - if (himl->hbmMask) { - SelectObject (hdcImage, ii.hbmMask); - StretchBlt (himl->hdcMask, nIndex * himl->cx, 0, himl->cx, himl->cy, - hdcImage, 0, 0, bmp.bmWidth, bmp.bmHeight, SRCCOPY); - } - - SelectObject (hdcImage, hbmOldSrc); - - if(hBestFitIcon) - DestroyIcon(hBestFitIcon); - if (hdcImage) - DeleteDC (hdcImage); - if (ii.hbmColor) - DeleteObject (ii.hbmColor); - if (ii.hbmMask) - DeleteObject (ii.hbmMask); - - TRACE("Insert index = %d, himl->cCurImage = %d\n", nIndex, himl->cCurImage); - return nIndex; -} - - -/************************************************************************* - * ImageList_SetBkColor [COMCTL32.@] - * - * Sets the background color of an image list. - * - * PARAMS - * himl [I] handle to image list - * clrBk [I] background color - * - * RETURNS - * Success: previous background color - * Failure: CLR_NONE - */ - -COLORREF WINAPI -ImageList_SetBkColor (HIMAGELIST himl, COLORREF clrBk) -{ - COLORREF clrOldBk; - - if (!is_valid(himl)) - return CLR_NONE; - - clrOldBk = himl->clrBk; - himl->clrBk = clrBk; - return clrOldBk; -} - - -/************************************************************************* - * ImageList_SetDragCursorImage [COMCTL32.@] - * - * Combines the specified image with the current drag image - * - * PARAMS - * himlDrag [I] handle to drag image list - * iDrag [I] drag image index - * dxHotspot [I] X position of the hot spot - * dyHotspot [I] Y position of the hot spot - * - * RETURNS - * Success: TRUE - * Failure: FALSE - * - * NOTES - * - The names dxHotspot, dyHotspot are misleading because they have nothing - * to do with a hotspot but are only the offset of the origin of the new - * image relative to the origin of the old image. - * - * - When this function is called and the drag image is visible, a - * short flickering occurs but this matches the Win9x behavior. It is - * possible to fix the flickering using code like in ImageList_DragMove. - */ - -BOOL WINAPI -ImageList_SetDragCursorImage (HIMAGELIST himlDrag, INT iDrag, - INT dxHotspot, INT dyHotspot) -{ - HIMAGELIST himlTemp; - BOOL visible; - - if (!is_valid(InternalDrag.himl) || !is_valid(himlDrag)) - return FALSE; - - TRACE(" dxH=%d dyH=%d nX=%d nY=%d\n", - dxHotspot, dyHotspot, InternalDrag.dxHotspot, InternalDrag.dyHotspot); - - visible = InternalDrag.bShow; - - himlTemp = ImageList_Merge (InternalDrag.himl, 0, himlDrag, iDrag, - dxHotspot, dyHotspot); - - if (visible) { - /* hide the drag image */ - ImageList_DragShowNolock(FALSE); - } - if ((InternalDrag.himl->cx != himlTemp->cx) || - (InternalDrag.himl->cy != himlTemp->cy)) { - /* the size of the drag image changed, invalidate the buffer */ - DeleteObject(InternalDrag.hbmBg); - InternalDrag.hbmBg = 0; - } - - ImageList_Destroy (InternalDrag.himl); - InternalDrag.himl = himlTemp; - - if (visible) { - /* show the drag image */ - ImageList_DragShowNolock(TRUE); - } - - return TRUE; -} - - -/************************************************************************* - * ImageList_SetFilter [COMCTL32.@] - * - * Sets a filter (or does something completely different)!!??? - * It removes 12 Bytes from the stack (3 Parameters). - * - * PARAMS - * himl [I] SHOULD be a handle to image list - * i [I] COULD be an index? - * dwFilter [I] ??? - * - * RETURNS - * Success: TRUE ??? - * Failure: FALSE ??? - * - * BUGS - * This is an UNDOCUMENTED function!!!! - * empty stub. - */ - -BOOL WINAPI -ImageList_SetFilter (HIMAGELIST himl, INT i, DWORD dwFilter) -{ - FIXME("(%p 0x%x 0x%lx):empty stub!\n", himl, i, dwFilter); - - return FALSE; -} - - -/************************************************************************* - * ImageList_SetFlags [COMCTL32.@] - * - * Sets the image list flags. - * - * PARAMS - * himl [I] Handle to image list - * flags [I] Flags to set - * - * RETURNS - * Old flags? - * - * BUGS - * Stub. - */ - -DWORD WINAPI -ImageList_SetFlags(HIMAGELIST himl, DWORD flags) -{ - FIXME("(%p %08lx):empty stub\n", himl, flags); - return 0; -} - - -/************************************************************************* - * ImageList_SetIconSize [COMCTL32.@] - * - * Sets the image size of the bitmap and deletes all images. - * - * PARAMS - * himl [I] handle to image list - * cx [I] image width - * cy [I] image height - * - * RETURNS - * Success: TRUE - * Failure: FALSE - */ - -BOOL WINAPI -ImageList_SetIconSize (HIMAGELIST himl, INT cx, INT cy) -{ - INT nCount; - HBITMAP hbmNew; - - if (!is_valid(himl)) - return FALSE; - - /* remove all images */ - himl->cMaxImage = himl->cInitial + himl->cGrow; - himl->cCurImage = 0; - himl->cx = cx; - himl->cy = cy; - - /* initialize overlay mask indices */ - for (nCount = 0; nCount < MAX_OVERLAYIMAGE; nCount++) - himl->nOvlIdx[nCount] = -1; - - hbmNew = ImageList_CreateImage(himl->hdcImage, himl, himl->cMaxImage * himl->cx, himl->cy); - SelectObject (himl->hdcImage, hbmNew); - DeleteObject (himl->hbmImage); - himl->hbmImage = hbmNew; - - if (himl->hbmMask) { - hbmNew = CreateBitmap (himl->cMaxImage * himl->cx, himl->cy, - 1, 1, NULL); - SelectObject (himl->hdcMask, hbmNew); - DeleteObject (himl->hbmMask); - himl->hbmMask = hbmNew; - } - - return TRUE; -} - - -/************************************************************************* - * ImageList_SetImageCount [COMCTL32.@] - * - * Resizes an image list to the specified number of images. - * - * PARAMS - * himl [I] handle to image list - * iImageCount [I] number of images in the image list - * - * RETURNS - * Success: TRUE - * Failure: FALSE - */ - -BOOL WINAPI -ImageList_SetImageCount (HIMAGELIST himl, UINT iImageCount) -{ - HDC hdcBitmap; - HBITMAP hbmNewBitmap; - INT nNewCount, nCopyCount; - - TRACE("%p %d\n",himl,iImageCount); - - if (!is_valid(himl)) - return FALSE; - if (himl->cCurImage >= iImageCount) - return FALSE; - if (himl->cMaxImage > iImageCount) - { - himl->cCurImage = iImageCount; - return TRUE; - } - - nNewCount = iImageCount + himl->cGrow; - nCopyCount = min(himl->cCurImage, iImageCount); - - hdcBitmap = CreateCompatibleDC (0); - - hbmNewBitmap = ImageList_CreateImage(hdcBitmap, himl, nNewCount * himl->cx, himl->cy); - - if (hbmNewBitmap != 0) - { - SelectObject (hdcBitmap, hbmNewBitmap); - - /* copy images */ - BitBlt (hdcBitmap, 0, 0, nCopyCount * himl->cx, himl->cy, - himl->hdcImage, 0, 0, SRCCOPY); -#if 0 - /* delete 'empty' image space */ - SetBkColor (hdcBitmap, RGB(255, 255, 255)); - SetTextColor (hdcBitmap, RGB(0, 0, 0)); - PatBlt (hdcBitmap, nCopyCount * himl->cx, 0, - (nNewCount - nCopyCount) * himl->cx, himl->cy, BLACKNESS); -#endif - SelectObject (himl->hdcImage, hbmNewBitmap); - DeleteObject (himl->hbmImage); - himl->hbmImage = hbmNewBitmap; - } - else - ERR("Could not create new image bitmap !\n"); - - if (himl->hbmMask) - { - hbmNewBitmap = CreateBitmap (nNewCount * himl->cx, himl->cy, - 1, 1, NULL); - if (hbmNewBitmap != 0) - { - SelectObject (hdcBitmap, hbmNewBitmap); - - /* copy images */ - BitBlt (hdcBitmap, 0, 0, nCopyCount * himl->cx, himl->cy, - himl->hdcMask, 0, 0, SRCCOPY); -#if 0 - /* delete 'empty' image space */ - SetBkColor (hdcBitmap, RGB(255, 255, 255)); - SetTextColor (hdcBitmap, RGB(0, 0, 0)); - PatBlt (hdcBitmap, nCopyCount * himl->cx, 0, - (nNewCount - nCopyCount) * himl->cx, himl->cy, BLACKNESS); -#endif - SelectObject (himl->hdcMask, hbmNewBitmap); - DeleteObject (himl->hbmMask); - himl->hbmMask = hbmNewBitmap; - } - else - ERR("Could not create new mask bitmap!\n"); - } - - DeleteDC (hdcBitmap); - - /* Update max image count and current image count */ - himl->cMaxImage = nNewCount; - himl->cCurImage = iImageCount; - - return TRUE; -} - - -/************************************************************************* - * ImageList_SetOverlayImage [COMCTL32.@] - * - * Assigns an overlay mask index to an existing image in an image list. - * - * PARAMS - * himl [I] handle to image list - * iImage [I] image index - * iOverlay [I] overlay mask index - * - * RETURNS - * Success: TRUE - * Failure: FALSE - */ - -BOOL WINAPI -ImageList_SetOverlayImage (HIMAGELIST himl, INT iImage, INT iOverlay) -{ - if (!is_valid(himl)) - return FALSE; - if ((iOverlay < 1) || (iOverlay > MAX_OVERLAYIMAGE)) - return FALSE; - if ((iImage!=-1) && ((iImage < 0) || (iImage > himl->cCurImage))) - return FALSE; - himl->nOvlIdx[iOverlay - 1] = iImage; - return TRUE; -} - - - -/* helper for ImageList_Write - write bitmap to pstm - * currently everything is written as 24 bit RGB, except masks - */ -static BOOL -_write_bitmap(HBITMAP hBitmap, LPSTREAM pstm, int cx, int cy) -{ - LPBITMAPFILEHEADER bmfh; - LPBITMAPINFOHEADER bmih; - LPBYTE data, lpBits, lpBitsOrg; - BITMAP bm; - INT bitCount, sizeImage, offBits, totalSize; - INT nwidth, nheight, nsizeImage, icount; - HDC xdc; - BOOL result = FALSE; - - - xdc = GetDC(0); - GetObjectA(hBitmap, sizeof(BITMAP), (LPVOID)&bm); - - /* XXX is this always correct? */ - icount = bm.bmWidth / cx; - nwidth = cx; - nheight = cy * icount; - - bitCount = bm.bmBitsPixel == 1 ? 1 : 24; - sizeImage = ((((bm.bmWidth * bitCount)+31) & ~31) >> 3) * bm.bmHeight; - nsizeImage = ((((nwidth * bitCount)+31) & ~31) >> 3) * nheight; - - totalSize = sizeof(BITMAPFILEHEADER) + sizeof(BITMAPINFOHEADER); - if(bitCount != 24) - totalSize += (1 << bitCount) * sizeof(RGBQUAD); - offBits = totalSize; - totalSize += nsizeImage; - - data = (LPBYTE)LocalAlloc(LMEM_ZEROINIT, totalSize); - bmfh = (LPBITMAPFILEHEADER)data; - bmih = (LPBITMAPINFOHEADER)(data + sizeof(BITMAPFILEHEADER)); - lpBits = data + offBits; - - /* setup BITMAPFILEHEADER */ - bmfh->bfType = (('M' << 8) | 'B'); - bmfh->bfSize = 0; - bmfh->bfReserved1 = 0; - bmfh->bfReserved2 = 0; - bmfh->bfOffBits = offBits; - - /* setup BITMAPINFOHEADER */ - bmih->biSize = sizeof(BITMAPINFOHEADER); - bmih->biWidth = bm.bmWidth; - bmih->biHeight = bm.bmHeight; - bmih->biPlanes = 1; - bmih->biBitCount = bitCount; - bmih->biCompression = BI_RGB; - bmih->biSizeImage = sizeImage; - bmih->biXPelsPerMeter = 0; - bmih->biYPelsPerMeter = 0; - bmih->biClrUsed = 0; - bmih->biClrImportant = 0; - - lpBitsOrg = (LPBYTE)LocalAlloc(LMEM_ZEROINIT, sizeImage); - if(!GetDIBits(xdc, hBitmap, 0, bm.bmHeight, lpBitsOrg, - (BITMAPINFO *)bmih, DIB_RGB_COLORS)) - goto failed; - else { - int i; - int obpl = (((bm.bmWidth*bitCount+31) & ~31)>>3); - int nbpl = (((nwidth*bitCount+31) & ~31)>>3); - - for(i = 0; i < nheight; i++) { - int ooff = ((nheight-1-i)%cy) * obpl + ((i/cy) * nbpl); - int noff = (nbpl * (nheight-1-i)); - memcpy(lpBits + noff, lpBitsOrg + ooff, nbpl); - } - } - - bmih->biWidth = nwidth; - bmih->biHeight = nheight; - bmih->biSizeImage = nsizeImage; - - if(bitCount == 1) { - /* Hack. */ - LPBITMAPINFO inf = (LPBITMAPINFO)bmih; - inf->bmiColors[0].rgbRed = inf->bmiColors[0].rgbGreen = inf->bmiColors[0].rgbBlue = 0; - inf->bmiColors[1].rgbRed = inf->bmiColors[1].rgbGreen = inf->bmiColors[1].rgbBlue = 0xff; - } - - if(!SUCCEEDED(IStream_Write(pstm, data, totalSize, NULL))) - goto failed; - - result = TRUE; - - failed: - ReleaseDC(0, xdc); - LocalFree((HLOCAL)lpBitsOrg); - LocalFree((HLOCAL)data); - - return result; -} - - -/************************************************************************* - * ImageList_Write [COMCTL32.@] - * - * Writes an image list to a stream. - * - * PARAMS - * himl [I] handle to image list - * pstm [O] Pointer to a stream. - * - * RETURNS - * Success: TRUE - * Failure: FALSE - * - * BUGS - * probably. - */ - -BOOL WINAPI -ImageList_Write (HIMAGELIST himl, LPSTREAM pstm) -{ - ILHEAD ilHead; - int i; - - if (!is_valid(himl)) - return FALSE; - - ilHead.usMagic = (('L' << 8) | 'I'); - ilHead.usVersion = 0x101; - ilHead.cCurImage = himl->cCurImage; - ilHead.cMaxImage = himl->cMaxImage; - ilHead.cGrow = himl->cGrow; - ilHead.cx = himl->cx; - ilHead.cy = himl->cy; - ilHead.bkcolor = himl->clrBk; - ilHead.flags = himl->flags; - for(i = 0; i < 4; i++) { - ilHead.ovls[i] = himl->nOvlIdx[i]; - } - - if(!SUCCEEDED(IStream_Write(pstm, &ilHead, sizeof(ILHEAD), NULL))) - return FALSE; - - /* write the bitmap */ - if(!_write_bitmap(himl->hbmImage, pstm, himl->cx, himl->cy)) - return FALSE; - - /* write the mask if we have one */ - if(himl->flags & ILC_MASK) { - if(!_write_bitmap(himl->hbmMask, pstm, himl->cx, himl->cy)) - return FALSE; - } - - return TRUE; -} - - -static HBITMAP ImageList_CreateImage(HDC hdc, HIMAGELIST himl, UINT width, UINT height) -{ - HBITMAP hbmNewBitmap; - UINT ilc = (himl->flags & 0xFE); - - if ((ilc >= ILC_COLOR4 && ilc <= ILC_COLOR32) || ilc == ILC_COLOR) - { - VOID* bits; - BITMAPINFO *bmi; - - TRACE("Creating DIBSection: %d Bits per Pixel\n", himl->uBitsPixel); - - if (himl->uBitsPixel <= ILC_COLOR8) - { - LPPALETTEENTRY pal; - ULONG i, colors; - BYTE temp; - - colors = 1 << himl->uBitsPixel; - bmi = HeapAlloc(GetProcessHeap(), 0, sizeof(BITMAPINFOHEADER) + - sizeof(PALETTEENTRY) * colors); - - pal = (LPPALETTEENTRY)bmi->bmiColors; - GetPaletteEntries(GetStockObject(DEFAULT_PALETTE), 0, colors, pal); - - /* Swap colors returned by GetPaletteEntries so we can use them for - * CreateDIBSection call. */ - for (i = 0; i < colors; i++) - { - temp = pal[i].peBlue; - bmi->bmiColors[i].rgbRed = pal[i].peRed; - bmi->bmiColors[i].rgbBlue = temp; - } - } - else - { - bmi = HeapAlloc(GetProcessHeap(), 0, sizeof(BITMAPINFOHEADER)); - } - - bmi->bmiHeader.biSize = sizeof(BITMAPINFOHEADER); - bmi->bmiHeader.biWidth = width; - bmi->bmiHeader.biHeight = height; - bmi->bmiHeader.biPlanes = 1; - bmi->bmiHeader.biBitCount = himl->uBitsPixel; - bmi->bmiHeader.biCompression = BI_RGB; - bmi->bmiHeader.biSizeImage = 0; - bmi->bmiHeader.biXPelsPerMeter = 0; - bmi->bmiHeader.biYPelsPerMeter = 0; - bmi->bmiHeader.biClrUsed = 0; - bmi->bmiHeader.biClrImportant = 0; - - hbmNewBitmap = CreateDIBSection(hdc, bmi, DIB_RGB_COLORS, &bits, 0, 0); - - HeapFree(GetProcessHeap(), 0, bmi); - } - else /*if (ilc == ILC_COLORDDB)*/ - { - TRACE("Creating Bitmap: %d Bits per Pixel\n", himl->uBitsPixel); - - hbmNewBitmap = CreateBitmap (width, height, 1, himl->uBitsPixel, NULL); - } - TRACE("returning %p\n", hbmNewBitmap); - return hbmNewBitmap; -} - -/************************************************************************* - * ImageList_SetColorTable [COMCTL32.@] - * - * Sets the color table of an image list. - * - * PARAMS - * himl [I] Handle to the image list. - * uStartIndex [I] The first index to set. - * cEntries [I] Number of entries to set. - * prgb [I] New color information for color table for the image list. - * - * RETURNS - * Success: Number of entries in the table that were set. - * Failure: Zero. - * - * SEE - * ImageList_Create(), SetDIBColorTable() - */ - -UINT WINAPI -ImageList_SetColorTable (HIMAGELIST himl, UINT uStartIndex, UINT cEntries, CONST RGBQUAD * prgb) -{ - return SetDIBColorTable(himl->hdcImage, uStartIndex, cEntries, prgb); -} diff --git a/reactos/lib/comctl32/imagelist.h b/reactos/lib/comctl32/imagelist.h deleted file mode 100644 index 5c5ab6998d3..00000000000 --- a/reactos/lib/comctl32/imagelist.h +++ /dev/null @@ -1,78 +0,0 @@ -/* - * ImageList definitions - * - * Copyright 1998 Eric Kohl - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2.1 of the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -#ifndef __WINE_IMAGELIST_H -#define __WINE_IMAGELIST_H - -#include - -#include "windef.h" -#include "winbase.h" -#include "wingdi.h" - -#include "pshpack1.h" - -/* the ones with offsets at the end are the same as in Windows */ -struct _IMAGELIST -{ - DWORD magic; /* 00: 'SAMX' */ - INT cCurImage; /* 04: ImageCount */ - INT cMaxImage; /* 08: maximages */ - INT cGrow; /* 0c: cGrow */ - INT cx; /* 10: cx */ - INT cy; /* 14: cy */ - DWORD x4; - UINT flags; /* 1c: flags */ - COLORREF clrFg; /* 20: foreground color */ - COLORREF clrBk; /* 24: backgournd color */ - - - HBITMAP hbmImage; /* 30: images Bitmap */ - HBITMAP hbmMask; /* 34: masks Bitmap */ - HDC hdcImage; /* 38: images MemDC */ - HDC hdcMask; /* 3C: masks MemDC */ - INT nOvlIdx[15]; /* 40: overlay images index */ - - /* not yet found out */ - HBRUSH hbrBlend25; - HBRUSH hbrBlend50; - INT cInitial; - UINT uBitsPixel; -}; - -#define IMAGELIST_MAGIC 0x53414D58 - -/* Header used by ImageList_Read() and ImageList_Write() */ -typedef struct _ILHEAD -{ - USHORT usMagic; - USHORT usVersion; - WORD cCurImage; - WORD cMaxImage; - WORD cGrow; - WORD cx; - WORD cy; - COLORREF bkcolor; - WORD flags; - SHORT ovls[4]; -} ILHEAD; - -#include "poppack.h" -#endif /* __WINE_IMAGELIST_H */ diff --git a/reactos/lib/comctl32/ipaddress.c b/reactos/lib/comctl32/ipaddress.c deleted file mode 100644 index 3a2abf6ac3d..00000000000 --- a/reactos/lib/comctl32/ipaddress.c +++ /dev/null @@ -1,583 +0,0 @@ -/* - * IP Address control - * - * Copyright 2002 Dimitrie O. Paun - * Copyright 1999 Chris Morgan - * Copyright 1999 James Abbatiello - * Copyright 1998, 1999 Eric Kohl - * Copyright 1998 Alex Priem - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2.1 of the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - * - * NOTE - * - * This code was audited for completeness against the documented features - * of Comctl32.dll version 6.0 on Sep. 9, 2002, 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. - * - */ - -#include -#include -#include -#include -#include - -#include "windef.h" -#include "winbase.h" -#include "wingdi.h" -#include "winuser.h" -#include "winnls.h" -#include "commctrl.h" -#include "comctl32.h" -#include "wine/unicode.h" -#include "wine/debug.h" - -WINE_DEFAULT_DEBUG_CHANNEL(ipaddress); - -typedef struct -{ - HWND EditHwnd; - INT LowerLimit; - INT UpperLimit; - WNDPROC OrigProc; -} IPPART_INFO; - -typedef struct -{ - HWND Self; - HWND Notify; - IPPART_INFO Part[4]; -} IPADDRESS_INFO; - -static const WCHAR IP_SUBCLASS_PROP[] = - { 'C', 'C', 'I', 'P', '3', '2', 'S', 'u', 'b', 'c', 'l', 'a', 's', 's', 'I', 'n', 'f', 'o', 0 }; - -#define POS_DEFAULT 0 -#define POS_LEFT 1 -#define POS_RIGHT 2 -#define POS_SELALL 3 - -static LRESULT CALLBACK -IPADDRESS_SubclassProc (HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam); - -static LRESULT IPADDRESS_Notify (IPADDRESS_INFO *infoPtr, UINT command) -{ - HWND hwnd = infoPtr->Self; - - TRACE("(command=%x)\n", command); - - return SendMessageW (infoPtr->Notify, WM_COMMAND, - MAKEWPARAM (GetWindowLongPtrW (hwnd, GWLP_ID), command), (LPARAM)hwnd); -} - -static INT IPADDRESS_IPNotify (IPADDRESS_INFO *infoPtr, INT field, INT value) -{ - NMIPADDRESS nmip; - - TRACE("(field=%x, value=%d)\n", field, value); - - nmip.hdr.hwndFrom = infoPtr->Self; - nmip.hdr.idFrom = GetWindowLongPtrW (infoPtr->Self, GWLP_ID); - nmip.hdr.code = IPN_FIELDCHANGED; - - nmip.iField = field; - nmip.iValue = value; - - SendMessageW (infoPtr->Notify, WM_NOTIFY, - (WPARAM)nmip.hdr.idFrom, (LPARAM)&nmip); - - TRACE("<-- %d\n", nmip.iValue); - - return nmip.iValue; -} - - -static int IPADDRESS_GetPartIndex(IPADDRESS_INFO *infoPtr, HWND hwnd) -{ - int i; - - TRACE("(hwnd=%p)\n", hwnd); - - for (i = 0; i < 4; i++) - if (infoPtr->Part[i].EditHwnd == hwnd) return i; - - ERR("We subclassed the wrong window! (hwnd=%p)\n", hwnd); - return -1; -} - - -static LRESULT IPADDRESS_Draw (IPADDRESS_INFO *infoPtr, HDC hdc) -{ - static const WCHAR dotW[] = { '.', 0 }; - RECT rect, rcPart; - POINT pt; - int i; - - TRACE("\n"); - - GetClientRect (infoPtr->Self, &rect); - DrawEdge (hdc, &rect, EDGE_SUNKEN, BF_RECT | BF_ADJUST); - - for (i = 0; i < 3; i++) { - GetWindowRect (infoPtr->Part[i].EditHwnd, &rcPart); - pt.x = rcPart.right; - ScreenToClient(infoPtr->Self, &pt); - rect.left = pt.x; - GetWindowRect (infoPtr->Part[i+1].EditHwnd, &rcPart); - pt.x = rcPart.left; - ScreenToClient(infoPtr->Self, &pt); - rect.right = pt.x; - DrawTextW(hdc, dotW, 1, &rect, DT_SINGLELINE | DT_CENTER | DT_BOTTOM); - } - - return 0; -} - - -static LRESULT IPADDRESS_Create (HWND hwnd, LPCREATESTRUCTA lpCreate) -{ - static const WCHAR EDIT[] = { 'E', 'd', 'i', 't', 0 }; - IPADDRESS_INFO *infoPtr; - RECT rcClient, edit; - int i, fieldsize; - - TRACE("\n"); - - SetWindowLongW (hwnd, GWL_STYLE, - GetWindowLongW(hwnd, GWL_STYLE) & ~WS_BORDER); - - infoPtr = (IPADDRESS_INFO *)Alloc (sizeof(IPADDRESS_INFO)); - if (!infoPtr) return -1; - SetWindowLongPtrW (hwnd, 0, (DWORD_PTR)infoPtr); - - GetClientRect (hwnd, &rcClient); - - fieldsize = (rcClient.right - rcClient.left) / 4; - - edit.top = rcClient.top + 2; - edit.bottom = rcClient.bottom - 2; - - infoPtr->Self = hwnd; - infoPtr->Notify = lpCreate->hwndParent; - - for (i = 0; i < 4; i++) { - IPPART_INFO* part = &infoPtr->Part[i]; - - part->LowerLimit = 0; - part->UpperLimit = 255; - edit.left = rcClient.left + i*fieldsize + 6; - edit.right = rcClient.left + (i+1)*fieldsize - 2; - part->EditHwnd = - CreateWindowW (EDIT, NULL, WS_CHILD | WS_VISIBLE | ES_CENTER, - edit.left, edit.top, edit.right - edit.left, - edit.bottom - edit.top, hwnd, (HMENU) 1, - (HINSTANCE)GetWindowLongPtrW(hwnd, GWLP_HINSTANCE), NULL); - SetPropW(part->EditHwnd, IP_SUBCLASS_PROP, hwnd); - part->OrigProc = (WNDPROC) - SetWindowLongPtrW (part->EditHwnd, GWLP_WNDPROC, - (DWORD_PTR)IPADDRESS_SubclassProc); - } - - return 0; -} - - -static LRESULT IPADDRESS_Destroy (IPADDRESS_INFO *infoPtr) -{ - int i; - - TRACE("\n"); - - for (i = 0; i < 4; i++) { - IPPART_INFO* part = &infoPtr->Part[i]; - SetWindowLongPtrW (part->EditHwnd, GWLP_WNDPROC, (DWORD_PTR)part->OrigProc); - } - - SetWindowLongPtrW (infoPtr->Self, 0, 0); - Free (infoPtr); - return 0; -} - - -static LRESULT IPADDRESS_Paint (IPADDRESS_INFO *infoPtr, HDC hdc) -{ - PAINTSTRUCT ps; - - TRACE("\n"); - - if (hdc) return IPADDRESS_Draw (infoPtr, hdc); - - hdc = BeginPaint (infoPtr->Self, &ps); - IPADDRESS_Draw (infoPtr, hdc); - EndPaint (infoPtr->Self, &ps); - return 0; -} - - -static BOOL IPADDRESS_IsBlank (IPADDRESS_INFO *infoPtr) -{ - int i; - - TRACE("\n"); - - for (i = 0; i < 4; i++) - if (GetWindowTextLengthW (infoPtr->Part[i].EditHwnd)) return FALSE; - - return TRUE; -} - - -static int IPADDRESS_GetAddress (IPADDRESS_INFO *infoPtr, LPDWORD ip_address) -{ - WCHAR field[5]; - int i, invalid = 0; - DWORD ip_addr = 0; - - TRACE("\n"); - - for (i = 0; i < 4; i++) { - ip_addr *= 256; - if (GetWindowTextW (infoPtr->Part[i].EditHwnd, field, 4)) - ip_addr += atolW(field); - else - invalid++; - } - *ip_address = ip_addr; - - return 4 - invalid; -} - - -static BOOL IPADDRESS_SetRange (IPADDRESS_INFO *infoPtr, int index, WORD range) -{ - TRACE("\n"); - - if ( (index < 0) || (index > 3) ) return FALSE; - - infoPtr->Part[index].LowerLimit = range & 0xFF; - infoPtr->Part[index].UpperLimit = (range >> 8) & 0xFF; - - return TRUE; -} - - -static void IPADDRESS_ClearAddress (IPADDRESS_INFO *infoPtr) -{ - WCHAR nil[1] = { 0 }; - int i; - - TRACE("\n"); - - for (i = 0; i < 4; i++) - SetWindowTextW (infoPtr->Part[i].EditHwnd, nil); -} - - -static LRESULT IPADDRESS_SetAddress (IPADDRESS_INFO *infoPtr, DWORD ip_address) -{ - WCHAR buf[20]; - static const WCHAR fmt[] = { '%', 'd', 0 }; - int i; - - TRACE("\n"); - - for (i = 3; i >= 0; i--) { - IPPART_INFO* part = &infoPtr->Part[i]; - int value = ip_address & 0xff; - if ( (value >= part->LowerLimit) && (value <= part->UpperLimit) ) { - wsprintfW (buf, fmt, value); - SetWindowTextW (part->EditHwnd, buf); - IPADDRESS_Notify (infoPtr, EN_CHANGE); - } - ip_address >>= 8; - } - - return TRUE; -} - - -static void IPADDRESS_SetFocusToField (IPADDRESS_INFO *infoPtr, INT index) -{ - TRACE("(index=%d)\n", index); - - if (index > 3) { - for (index = 0; index < 4; index++) - if (!GetWindowTextLengthW(infoPtr->Part[index].EditHwnd)) break; - } - if (index < 9 || index > 3) index = 0; - - SetFocus (infoPtr->Part[index].EditHwnd); -} - - -static BOOL IPADDRESS_ConstrainField (IPADDRESS_INFO *infoPtr, int currentfield) -{ - IPPART_INFO *part = &infoPtr->Part[currentfield]; - WCHAR field[10]; - static const WCHAR fmt[] = { '%', 'd', 0 }; - int curValue, newValue; - - TRACE("(currentfield=%d)\n", currentfield); - - if (currentfield < 0 || currentfield > 3) return FALSE; - - if (!GetWindowTextW (part->EditHwnd, field, 4)) return FALSE; - - curValue = atoiW(field); - TRACE(" curValue=%d\n", curValue); - - newValue = IPADDRESS_IPNotify(infoPtr, currentfield, curValue); - TRACE(" newValue=%d\n", newValue); - - if (newValue < part->LowerLimit) newValue = part->LowerLimit; - if (newValue > part->UpperLimit) newValue = part->UpperLimit; - - if (newValue == curValue) return FALSE; - - wsprintfW (field, fmt, newValue); - TRACE(" field='%s'\n", debugstr_w(field)); - return SetWindowTextW (part->EditHwnd, field); -} - - -static BOOL IPADDRESS_GotoNextField (IPADDRESS_INFO *infoPtr, int cur, int sel) -{ - TRACE("\n"); - - if(cur >= -1 && cur < 4) { - IPADDRESS_ConstrainField(infoPtr, cur); - - if(cur < 3) { - IPPART_INFO *next = &infoPtr->Part[cur + 1]; - int start = 0, end = 0; - SetFocus (next->EditHwnd); - if (sel != POS_DEFAULT) { - if (sel == POS_RIGHT) - start = end = GetWindowTextLengthW(next->EditHwnd); - else if (sel == POS_SELALL) - end = -1; - SendMessageW(next->EditHwnd, EM_SETSEL, start, end); - } - return TRUE; - } - - } - return FALSE; -} - - -/* - * period: move and select the text in the next field to the right if - * the current field is not empty(l!=0), we are not in the - * left most position, and nothing is selected(startsel==endsel) - * - * spacebar: same behavior as period - * - * alpha characters: completely ignored - * - * digits: accepted when field text length < 2 ignored otherwise. - * when 3 numbers have been entered into the field the value - * of the field is checked, if the field value exceeds the - * maximum value and is changed the field remains the current - * field, otherwise focus moves to the field to the right - * - * tab: change focus from the current ipaddress control to the next - * control in the tab order - * - * right arrow: move to the field on the right to the left most - * position in that field if no text is selected, - * we are in the right most position in the field, - * we are not in the right most field - * - * left arrow: move to the field on the left to the right most - * position in that field if no text is selected, - * we are in the left most position in the current field - * and we are not in the left most field - * - * backspace: delete the character to the left of the cursor position, - * if none are present move to the field on the left if - * we are not in the left most field and delete the right - * most digit in that field while keeping the cursor - * on the right side of the field - */ -LRESULT CALLBACK -IPADDRESS_SubclassProc (HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam) -{ - HWND Self = (HWND)GetPropW (hwnd, IP_SUBCLASS_PROP); - IPADDRESS_INFO *infoPtr = (IPADDRESS_INFO *)GetWindowLongPtrW (Self, 0); - CHAR c = (CHAR)wParam; - INT index, len = 0, startsel, endsel; - IPPART_INFO *part; - - TRACE("(hwnd=%p msg=0x%x wparam=0x%x lparam=0x%lx)\n", hwnd, uMsg, wParam, lParam); - - if ( (index = IPADDRESS_GetPartIndex(infoPtr, hwnd)) < 0) return 0; - part = &infoPtr->Part[index]; - - if (uMsg == WM_CHAR || uMsg == WM_KEYDOWN) { - len = GetWindowTextLengthW (hwnd); - SendMessageW(hwnd, EM_GETSEL, (WPARAM)&startsel, (LPARAM)&endsel); - } - switch (uMsg) { - case WM_CHAR: - if(isdigit(c)) { - if(len == 2 && startsel==endsel && endsel==len) { - /* process the digit press before we check the field */ - int return_val = CallWindowProcW (part->OrigProc, hwnd, uMsg, wParam, lParam); - - /* if the field value was changed stay at the current field */ - if(!IPADDRESS_ConstrainField(infoPtr, index)) - IPADDRESS_GotoNextField (infoPtr, index, POS_DEFAULT); - - return return_val; - } else if (len == 3 && startsel==endsel && endsel==len) - IPADDRESS_GotoNextField (infoPtr, index, POS_SELALL); - else if (len < 3) break; - } else if(c == '.' || c == ' ') { - if(len && startsel==endsel && startsel != 0) { - IPADDRESS_GotoNextField(infoPtr, index, POS_SELALL); - } - } else if (c == VK_BACK) break; - return 0; - - case WM_KEYDOWN: - switch(c) { - case VK_RIGHT: - if(startsel==endsel && startsel==len) { - IPADDRESS_GotoNextField(infoPtr, index, POS_LEFT); - return 0; - } - break; - case VK_LEFT: - if(startsel==0 && startsel==endsel && index > 0) { - IPADDRESS_GotoNextField(infoPtr, index - 2, POS_RIGHT); - return 0; - } - break; - case VK_BACK: - if(startsel==endsel && startsel==0 && index > 0) { - IPPART_INFO *prev = &infoPtr->Part[index-1]; - WCHAR val[10]; - - if(GetWindowTextW(prev->EditHwnd, val, 5)) { - val[lstrlenW(val) - 1] = 0; - SetWindowTextW(prev->EditHwnd, val); - } - - IPADDRESS_GotoNextField(infoPtr, index - 2, POS_RIGHT); - return 0; - } - break; - } - break; - case WM_KILLFOCUS: - if (IPADDRESS_GetPartIndex(infoPtr, (HWND)wParam) < 0) - IPADDRESS_Notify(infoPtr, EN_KILLFOCUS); - break; - case WM_SETFOCUS: - if (IPADDRESS_GetPartIndex(infoPtr, (HWND)wParam) < 0) - IPADDRESS_Notify(infoPtr, EN_SETFOCUS); - break; - } - return CallWindowProcW (part->OrigProc, hwnd, uMsg, wParam, lParam); -} - - -static LRESULT WINAPI -IPADDRESS_WindowProc (HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam) -{ - IPADDRESS_INFO *infoPtr = (IPADDRESS_INFO *)GetWindowLongPtrW (hwnd, 0); - - TRACE("(hwnd=%p msg=0x%x wparam=0x%x lparam=0x%lx)\n", hwnd, uMsg, wParam, lParam); - - if (!infoPtr && (uMsg != WM_CREATE)) - return DefWindowProcW (hwnd, uMsg, wParam, lParam); - - switch (uMsg) - { - case WM_CREATE: - return IPADDRESS_Create (hwnd, (LPCREATESTRUCTA)lParam); - - case WM_DESTROY: - return IPADDRESS_Destroy (infoPtr); - - case WM_PAINT: - return IPADDRESS_Paint (infoPtr, (HDC)wParam); - - case WM_COMMAND: - switch(wParam >> 16) { - case EN_CHANGE: - IPADDRESS_Notify(infoPtr, EN_CHANGE); - break; - case EN_KILLFOCUS: - IPADDRESS_ConstrainField(infoPtr, IPADDRESS_GetPartIndex(infoPtr, (HWND)lParam)); - break; - } - break; - - case IPM_CLEARADDRESS: - IPADDRESS_ClearAddress (infoPtr); - break; - - case IPM_SETADDRESS: - return IPADDRESS_SetAddress (infoPtr, (DWORD)lParam); - - case IPM_GETADDRESS: - return IPADDRESS_GetAddress (infoPtr, (LPDWORD)lParam); - - case IPM_SETRANGE: - return IPADDRESS_SetRange (infoPtr, (int)wParam, (WORD)lParam); - - case IPM_SETFOCUS: - IPADDRESS_SetFocusToField (infoPtr, (int)wParam); - break; - - case IPM_ISBLANK: - return IPADDRESS_IsBlank (infoPtr); - - default: - if ((uMsg >= WM_USER) && (uMsg < WM_APP)) - ERR("unknown msg %04x wp=%08x lp=%08lx\n", uMsg, wParam, lParam); - return DefWindowProcW (hwnd, uMsg, wParam, lParam); - } - return 0; -} - - -void IPADDRESS_Register (void) -{ - WNDCLASSW wndClass; - - ZeroMemory (&wndClass, sizeof(WNDCLASSW)); - wndClass.style = CS_GLOBALCLASS | CS_DBLCLKS | CS_HREDRAW | CS_VREDRAW; - wndClass.lpfnWndProc = IPADDRESS_WindowProc; - wndClass.cbClsExtra = 0; - wndClass.cbWndExtra = sizeof(IPADDRESS_INFO *); - wndClass.hCursor = LoadCursorW (0, (LPWSTR)IDC_IBEAM); - wndClass.hbrBackground = (HBRUSH)(COLOR_WINDOW+1); - wndClass.lpszClassName = WC_IPADDRESSW; - - RegisterClassW (&wndClass); -} - - -void IPADDRESS_Unregister (void) -{ - UnregisterClassW (WC_IPADDRESSW, NULL); -} diff --git a/reactos/lib/comctl32/listview.c b/reactos/lib/comctl32/listview.c deleted file mode 100644 index 64532dd8577..00000000000 --- a/reactos/lib/comctl32/listview.c +++ /dev/null @@ -1,9552 +0,0 @@ -/* - * Listview control - * - * Copyright 1998, 1999 Eric Kohl - * Copyright 1999 Luc Tourangeau - * Copyright 2000 Jason Mawdsley - * Copyright 2001 CodeWeavers Inc. - * Copyright 2002 Dimitrie O. Paun - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2.1 of the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - * - * NOTES - * - * This code was audited for completeness against the documented features - * of Comctl32.dll version 6.0 on Oct. 21, 2002, 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: - * - * Features - * -- Hot item handling, mouse hovering - * -- Workareas support - * -- Tilemode support - * -- Groups support - * - * Bugs - * -- Expand large item in ICON mode when the cursor is flying over the icon or text. - * -- Support CustonDraw options for _WIN32_IE >= 0x560 (see NMLVCUSTOMDRAW docs. - * -- in LISTVIEW_AddGroupSelection, we would send LVN_ODSTATECHANGED - * -- LVA_SNAPTOGRID not implemented - * -- LISTVIEW_ApproximateViewRect partially implemented - * -- LISTVIEW_[GS]etColumnOrderArray stubs - * -- LISTVIEW_SetColumnWidth ignores header images & bitmap - * -- LISTVIEW_SetIconSpacing is incomplete - * -- LISTVIEW_SortItems is broken - * -- LISTVIEW_StyleChanged doesn't handle some changes too well - * - * Speedups - * -- LISTVIEW_GetNextItem needs to be rewritten. It is currently - * linear in the number of items in the list, and this is - * unacceptable for large lists. - * -- in sorted mode, LISTVIEW_InsertItemT sorts the array, - * instead of inserting in the right spot - * -- we should keep an ordered array of coordinates in iconic mode - * this would allow to frame items (iterator_frameditems), - * and find nearest item (LVFI_NEARESTXY) a lot more efficiently - * - * Flags - * -- LVIF_COLUMNS - * -- LVIF_GROUPID - * -- LVIF_NORECOMPUTE - * - * States - * -- LVIS_ACTIVATING (not currently supported by comctl32.dll version 6.0) - * -- LVIS_CUT - * -- LVIS_DROPHILITED - * -- LVIS_OVERLAYMASK - * - * Styles - * -- LVS_NOLABELWRAP - * -- LVS_NOSCROLL (see Q137520) - * -- LVS_SORTASCENDING, LVS_SORTDESCENDING - * - * Extended Styles - * -- LVS_EX_BORDERSELECT - * -- LVS_EX_FLATSB - * -- LVS_EX_GRIDLINES - * -- LVS_EX_HEADERDRAGDROP - * -- LVS_EX_INFOTIP - * -- LVS_EX_LABELTIP - * -- LVS_EX_MULTIWORKAREAS - * -- LVS_EX_ONECLICKACTIVATE - * -- LVS_EX_REGIONAL - * -- LVS_EX_SIMPLESELECT - * -- LVS_EX_TRACKSELECT - * -- LVS_EX_TWOCLICKACTIVATE - * -- LVS_EX_UNDERLINECOLD - * -- LVS_EX_UNDERLINEHOT - * - * Notifications: - * -- LVN_BEGINSCROLL, LVN_ENDSCROLL - * -- LVN_GETINFOTIP - * -- LVN_HOTTRACK - * -- LVN_MARQUEEBEGIN - * -- LVN_ODFINDITEM - * -- LVN_ODSTATECHANGED - * -- LVN_SETDISPINFO - * -- NM_HOVER - * - * Messages: - * -- LVM_CANCELEDITLABEL - * -- LVM_ENABLEGROUPVIEW - * -- LVM_GETBKIMAGE, LVM_SETBKIMAGE - * -- LVM_GETGROUPINFO, LVM_SETGROUPINFO - * -- LVM_GETGROUPMETRICS, LVM_SETGROUPMETRICS - * -- LVM_GETINSERTMARK, LVM_SETINSERTMARK - * -- LVM_GETINSERTMARKCOLOR, LVM_SETINSERTMARKCOLOR - * -- LVM_GETINSERTMARKRECT - * -- LVM_GETNUMBEROFWORKAREAS - * -- LVM_GETOUTLINECOLOR, LVM_SETOUTLINECOLOR - * -- LVM_GETSELECTEDCOLUMN, LVM_SETSELECTEDCOLUMN - * -- LVM_GETISEARCHSTRINGW, LVM_GETISEARCHSTRINGA - * -- LVM_GETTILEINFO, LVM_SETTILEINFO - * -- LVM_GETTILEVIEWINFO, LVM_SETTILEVIEWINFO - * -- LVM_GETUNICODEFORMAT, LVM_SETUNICODEFORMAT - * -- LVM_GETVIEW, LVM_SETVIEW - * -- LVM_GETWORKAREAS, LVM_SETWORKAREAS - * -- LVM_HASGROUP, LVM_INSERTGROUP, LVM_REMOVEGROUP, LVM_REMOVEALLGROUPS - * -- LVM_INSERTGROUPSORTED - * -- LVM_INSERTMARKHITTEST - * -- LVM_ISGROUPVIEWENABLED - * -- LVM_MAPIDTOINDEX, LVM_MAPINDEXTOID - * -- LVM_MOVEGROUP - * -- LVM_MOVEITEMTOGROUP - * -- LVM_SETINFOTIP - * -- LVM_SETTILEWIDTH - * -- LVM_SORTGROUPS - * -- LVM_SORTITEMSEX - * - * Known differences in message stream from native control (not known if - * these differences cause problems): - * LVM_INSERTITEM issues LVM_SETITEMSTATE and LVM_SETITEM in certain cases. - * LVM_SETITEM does not always issue LVN_ITEMCHANGING/LVN_ITEMCHANGED. - * WM_CREATE does not issue WM_QUERYUISTATE and associated registry - * processing for "USEDOUBLECLICKTIME". - */ - -#include "config.h" -#include "wine/port.h" - -#include -#include -#include -#include -#include -#include -#include - -#include "windef.h" -#include "winbase.h" -#include "winnt.h" -#include "wingdi.h" -#include "winuser.h" -#include "winnls.h" -#include "commctrl.h" -#include "comctl32.h" - -#include "wine/debug.h" -#include "wine/unicode.h" - -WINE_DEFAULT_DEBUG_CHANNEL(listview); - -/* make sure you set this to 0 for production use! */ -#define DEBUG_RANGES 1 - -typedef struct tagCOLUMN_INFO -{ - RECT rcHeader; /* tracks the header's rectangle */ - int fmt; /* same as LVCOLUMN.fmt */ -} COLUMN_INFO; - -typedef struct tagITEMHDR -{ - LPWSTR pszText; - INT iImage; -} ITEMHDR, *LPITEMHDR; - -typedef struct tagSUBITEM_INFO -{ - ITEMHDR hdr; - INT iSubItem; -} SUBITEM_INFO; - -typedef struct tagITEM_INFO -{ - ITEMHDR hdr; - UINT state; - LPARAM lParam; - INT iIndent; -} ITEM_INFO; - -typedef struct tagRANGE -{ - INT lower; - INT upper; -} RANGE; - -typedef struct tagRANGES -{ - HDPA hdpa; -} *RANGES; - -typedef struct tagITERATOR -{ - INT nItem; - INT nSpecial; - RANGE range; - RANGES ranges; - INT index; -} ITERATOR; - -typedef struct tagLISTVIEW_INFO -{ - HWND hwndSelf; - HBRUSH hBkBrush; - COLORREF clrBk; - COLORREF clrText; - COLORREF clrTextBk; - COLORREF clrTextBkDefault; - HIMAGELIST himlNormal; - HIMAGELIST himlSmall; - HIMAGELIST himlState; - BOOL bLButtonDown; - BOOL bRButtonDown; - BOOL bNoItemMetrics; /* flags if item metrics are not yet computed */ - INT nItemHeight; - INT nItemWidth; - RANGES selectionRanges; - INT nSelectionMark; - INT nHotItem; - SHORT notifyFormat; - HWND hwndNotify; - RECT rcList; /* This rectangle is really the window - * client rectangle possibly reduced by the - * horizontal scroll bar and/or header - see - * LISTVIEW_UpdateSize. This rectangle offset - * by the LISTVIEW_GetOrigin value is in - * client coordinates */ - SIZE iconSize; - SIZE iconSpacing; - SIZE iconStateSize; - UINT uCallbackMask; - HWND hwndHeader; - HCURSOR hHotCursor; - HFONT hDefaultFont; - HFONT hFont; - INT ntmHeight; /* Some cached metrics of the font used */ - INT ntmAveCharWidth; /* by the listview to draw items */ - BOOL bRedraw; /* Turns on/off repaints & invalidations */ - BOOL bAutoarrange; /* Autoarrange flag when NOT in LVS_AUTOARRANGE */ - BOOL bFocus; - BOOL bDoChangeNotify; /* send change notification messages? */ - INT nFocusedItem; - RECT rcFocus; - DWORD dwStyle; /* the cached window GWL_STYLE */ - DWORD dwLvExStyle; /* extended listview style */ - INT nItemCount; /* the number of items in the list */ - HDPA hdpaItems; /* array ITEM_INFO pointers */ - HDPA hdpaPosX; /* maintains the (X, Y) coordinates of the */ - HDPA hdpaPosY; /* items in LVS_ICON, and LVS_SMALLICON modes */ - HDPA hdpaColumns; /* array of COLUMN_INFO pointers */ - POINT currIconPos; /* this is the position next icon will be placed */ - PFNLVCOMPARE pfnCompare; - LPARAM lParamSort; - HWND hwndEdit; - WNDPROC EditWndProc; - INT nEditLabelItem; - DWORD dwHoverTime; - HWND hwndToolTip; - - DWORD cditemmode; /* Keep the custom draw flags for an item/row */ - - DWORD lastKeyPressTimestamp; - WPARAM charCode; - INT nSearchParamLength; - WCHAR szSearchParam[ MAX_PATH ]; - BOOL bIsDrawing; -} LISTVIEW_INFO; - -/* - * constants - */ -/* How many we debug buffer to allocate */ -#define DEBUG_BUFFERS 20 -/* The size of a single debug bbuffer */ -#define DEBUG_BUFFER_SIZE 256 - -/* Internal interface to LISTVIEW_HScroll and LISTVIEW_VScroll */ -#define SB_INTERNAL -1 - -/* maximum size of a label */ -#define DISP_TEXT_SIZE 512 - -/* padding for items in list and small icon display modes */ -#define WIDTH_PADDING 12 - -/* padding for items in list, report and small icon display modes */ -#define HEIGHT_PADDING 1 - -/* offset of items in report display mode */ -#define REPORT_MARGINX 2 - -/* padding for icon in large icon display mode - * ICON_TOP_PADDING_NOTHITABLE - space between top of box and area - * that HITTEST will see. - * ICON_TOP_PADDING_HITABLE - spacing between above and icon. - * ICON_TOP_PADDING - sum of the two above. - * ICON_BOTTOM_PADDING - between bottom of icon and top of text - * LABEL_HOR_PADDING - between text and sides of box - * LABEL_VERT_PADDING - between bottom of text and end of box - * - * ICON_LR_PADDING - additional width above icon size. - * ICON_LR_HALF - half of the above value - */ -#define ICON_TOP_PADDING_NOTHITABLE 2 -#define ICON_TOP_PADDING_HITABLE 2 -#define ICON_TOP_PADDING (ICON_TOP_PADDING_NOTHITABLE + ICON_TOP_PADDING_HITABLE) -#define ICON_BOTTOM_PADDING 4 -#define LABEL_HOR_PADDING 5 -#define LABEL_VERT_PADDING 7 -#define ICON_LR_PADDING 16 -#define ICON_LR_HALF (ICON_LR_PADDING/2) - -/* default label width for items in list and small icon display modes */ -#define DEFAULT_LABEL_WIDTH 40 - -/* default column width for items in list display mode */ -#define DEFAULT_COLUMN_WIDTH 128 - -/* Size of "line" scroll for V & H scrolls */ -#define LISTVIEW_SCROLL_ICON_LINE_SIZE 37 - -/* Padding betwen image and label */ -#define IMAGE_PADDING 2 - -/* Padding behind the label */ -#define TRAILING_LABEL_PADDING 12 -#define TRAILING_HEADER_PADDING 11 - -/* Border for the icon caption */ -#define CAPTION_BORDER 2 - -/* Standard DrawText flags */ -#define LV_ML_DT_FLAGS (DT_TOP | DT_NOPREFIX | DT_EDITCONTROL | DT_CENTER | DT_WORDBREAK | DT_WORD_ELLIPSIS | DT_END_ELLIPSIS) -#define LV_FL_DT_FLAGS (DT_TOP | DT_NOPREFIX | DT_EDITCONTROL | DT_CENTER | DT_WORDBREAK | DT_NOCLIP) -#define LV_SL_DT_FLAGS (DT_VCENTER | DT_NOPREFIX | DT_EDITCONTROL | DT_SINGLELINE | DT_WORD_ELLIPSIS | DT_END_ELLIPSIS) - -/* The time in milliseconds to reset the search in the list */ -#define KEY_DELAY 450 - -/* Dump the LISTVIEW_INFO structure to the debug channel */ -#define LISTVIEW_DUMP(iP) do { \ - TRACE("hwndSelf=%p, clrBk=0x%06lx, clrText=0x%06lx, clrTextBk=0x%06lx, ItemHeight=%d, ItemWidth=%d, Style=0x%08lx\n", \ - iP->hwndSelf, iP->clrBk, iP->clrText, iP->clrTextBk, \ - iP->nItemHeight, iP->nItemWidth, infoPtr->dwStyle); \ - TRACE("hwndSelf=%p, himlNor=%p, himlSml=%p, himlState=%p, Focused=%d, Hot=%d, exStyle=0x%08lx, Focus=%d\n", \ - iP->hwndSelf, iP->himlNormal, iP->himlSmall, iP->himlState, \ - iP->nFocusedItem, iP->nHotItem, iP->dwLvExStyle, iP->bFocus ); \ - TRACE("hwndSelf=%p, ntmH=%d, icSz.cx=%ld, icSz.cy=%ld, icSp.cx=%ld, icSp.cy=%ld, notifyFmt=%d\n", \ - iP->hwndSelf, iP->ntmHeight, iP->iconSize.cx, iP->iconSize.cy, \ - iP->iconSpacing.cx, iP->iconSpacing.cy, iP->notifyFormat); \ - TRACE("hwndSelf=%p, rcList=%s\n", iP->hwndSelf, debugrect(&iP->rcList)); \ -} while(0) - -/* - * forward declarations - */ -static BOOL LISTVIEW_GetItemT(LISTVIEW_INFO *, LPLVITEMW, BOOL); -static void LISTVIEW_GetItemBox(LISTVIEW_INFO *, INT, LPRECT); -static void LISTVIEW_GetItemOrigin(LISTVIEW_INFO *, INT, LPPOINT); -static BOOL LISTVIEW_GetItemPosition(LISTVIEW_INFO *, INT, LPPOINT); -static BOOL LISTVIEW_GetItemRect(LISTVIEW_INFO *, INT, LPRECT); -static INT LISTVIEW_GetLabelWidth(LISTVIEW_INFO *, INT); -static void LISTVIEW_GetOrigin(LISTVIEW_INFO *, LPPOINT); -static BOOL LISTVIEW_GetViewRect(LISTVIEW_INFO *, LPRECT); -static void LISTVIEW_SetGroupSelection(LISTVIEW_INFO *, INT); -static BOOL LISTVIEW_SetItemT(LISTVIEW_INFO *, const LVITEMW *, BOOL); -static void LISTVIEW_UpdateScroll(LISTVIEW_INFO *); -static void LISTVIEW_SetSelection(LISTVIEW_INFO *, INT); -static void LISTVIEW_UpdateSize(LISTVIEW_INFO *); -static HWND LISTVIEW_EditLabelT(LISTVIEW_INFO *, INT, BOOL); -static LRESULT LISTVIEW_Command(LISTVIEW_INFO *, WPARAM, LPARAM); -static BOOL LISTVIEW_SortItems(LISTVIEW_INFO *, PFNLVCOMPARE, LPARAM); -static INT LISTVIEW_GetStringWidthT(LISTVIEW_INFO *, LPCWSTR, BOOL); -static BOOL LISTVIEW_KeySelection(LISTVIEW_INFO *, INT); -static UINT LISTVIEW_GetItemState(LISTVIEW_INFO *, INT, UINT); -static BOOL LISTVIEW_SetItemState(LISTVIEW_INFO *, INT, const LVITEMW *); -static LRESULT LISTVIEW_VScroll(LISTVIEW_INFO *, INT, INT, HWND); -static LRESULT LISTVIEW_HScroll(LISTVIEW_INFO *, INT, INT, HWND); -static INT LISTVIEW_GetTopIndex(LISTVIEW_INFO *); -static BOOL LISTVIEW_EnsureVisible(LISTVIEW_INFO *, INT, BOOL); -static HWND CreateEditLabelT(LISTVIEW_INFO *, LPCWSTR, DWORD, INT, INT, INT, INT, BOOL); -static HIMAGELIST LISTVIEW_SetImageList(LISTVIEW_INFO *, INT, HIMAGELIST); - -/******** Text handling functions *************************************/ - -/* A text pointer is either NULL, LPSTR_TEXTCALLBACK, or points to a - * text string. The string may be ANSI or Unicode, in which case - * the boolean isW tells us the type of the string. - * - * The name of the function tell what type of strings it expects: - * W: Unicode, T: ANSI/Unicode - function of isW - */ - -static inline BOOL is_textW(LPCWSTR text) -{ - return text != NULL && text != LPSTR_TEXTCALLBACKW; -} - -static inline BOOL is_textT(LPCWSTR text, BOOL isW) -{ - /* we can ignore isW since LPSTR_TEXTCALLBACKW == LPSTR_TEXTCALLBACKA */ - return is_textW(text); -} - -static inline int textlenT(LPCWSTR text, BOOL isW) -{ - return !is_textT(text, isW) ? 0 : - isW ? lstrlenW(text) : lstrlenA((LPCSTR)text); -} - -static inline void textcpynT(LPWSTR dest, BOOL isDestW, LPCWSTR src, BOOL isSrcW, INT max) -{ - if (isDestW) - if (isSrcW) lstrcpynW(dest, src, max); - else MultiByteToWideChar(CP_ACP, 0, (LPCSTR)src, -1, dest, max); - else - if (isSrcW) WideCharToMultiByte(CP_ACP, 0, src, -1, (LPSTR)dest, max, NULL, NULL); - else lstrcpynA((LPSTR)dest, (LPCSTR)src, max); -} - -static inline LPWSTR textdupTtoW(LPCWSTR text, BOOL isW) -{ - LPWSTR wstr = (LPWSTR)text; - - if (!isW && is_textT(text, isW)) - { - INT len = MultiByteToWideChar(CP_ACP, 0, (LPCSTR)text, -1, NULL, 0); - wstr = HeapAlloc(GetProcessHeap(), 0, len * sizeof(WCHAR)); - if (wstr) MultiByteToWideChar(CP_ACP, 0, (LPCSTR)text, -1, wstr, len); - } - TRACE(" wstr=%s\n", text == LPSTR_TEXTCALLBACKW ? "(callback)" : debugstr_w(wstr)); - return wstr; -} - -static inline void textfreeT(LPWSTR wstr, BOOL isW) -{ - if (!isW && is_textT(wstr, isW)) HeapFree(GetProcessHeap(), 0, wstr); -} - -/* - * dest is a pointer to a Unicode string - * src is a pointer to a string (Unicode if isW, ANSI if !isW) - */ -static BOOL textsetptrT(LPWSTR *dest, LPWSTR src, BOOL isW) -{ - BOOL bResult = TRUE; - - if (src == LPSTR_TEXTCALLBACKW) - { - if (is_textW(*dest)) Free(*dest); - *dest = LPSTR_TEXTCALLBACKW; - } - else - { - LPWSTR pszText = textdupTtoW(src, isW); - if (*dest == LPSTR_TEXTCALLBACKW) *dest = NULL; - bResult = Str_SetPtrW(dest, pszText); - textfreeT(pszText, isW); - } - return bResult; -} - -/* - * compares a Unicode to a Unicode/ANSI text string - */ -static inline int textcmpWT(LPCWSTR aw, LPCWSTR bt, BOOL isW) -{ - if (!aw) return bt ? -1 : 0; - if (!bt) return aw ? 1 : 0; - if (aw == LPSTR_TEXTCALLBACKW) - return bt == LPSTR_TEXTCALLBACKW ? 0 : -1; - if (bt != LPSTR_TEXTCALLBACKW) - { - LPWSTR bw = textdupTtoW(bt, isW); - int r = bw ? lstrcmpW(aw, bw) : 1; - textfreeT(bw, isW); - return r; - } - - return 1; -} - -static inline int lstrncmpiW(LPCWSTR s1, LPCWSTR s2, int n) -{ - int res; - - n = min(min(n, strlenW(s1)), strlenW(s2)); - res = CompareStringW(LOCALE_USER_DEFAULT, NORM_IGNORECASE, s1, n, s2, n); - return res ? res - sizeof(WCHAR) : res; -} - -/******** Debugging functions *****************************************/ - -static inline LPCSTR debugtext_t(LPCWSTR text, BOOL isW) -{ - if (text == LPSTR_TEXTCALLBACKW) return "(callback)"; - return isW ? debugstr_w(text) : debugstr_a((LPCSTR)text); -} - -static inline LPCSTR debugtext_tn(LPCWSTR text, BOOL isW, INT n) -{ - if (text == LPSTR_TEXTCALLBACKW) return "(callback)"; - n = min(textlenT(text, isW), n); - return isW ? debugstr_wn(text, n) : debugstr_an((LPCSTR)text, n); -} - -static char* debug_getbuf() -{ - static int index = 0; - static char buffers[DEBUG_BUFFERS][DEBUG_BUFFER_SIZE]; - return buffers[index++ % DEBUG_BUFFERS]; -} - -static inline const char* debugrange(const RANGE *lprng) -{ - if (lprng) - { - char* buf = debug_getbuf(); - snprintf(buf, DEBUG_BUFFER_SIZE, "[%d, %d)", lprng->lower, lprng->upper); - return buf; - } else return "(null)"; -} - -static inline const char* debugpoint(const POINT *lppt) -{ - if (lppt) - { - char* buf = debug_getbuf(); - snprintf(buf, DEBUG_BUFFER_SIZE, "(%ld, %ld)", lppt->x, lppt->y); - return buf; - } else return "(null)"; -} - -static inline const char* debugrect(const RECT *rect) -{ - if (rect) - { - char* buf = debug_getbuf(); - snprintf(buf, DEBUG_BUFFER_SIZE, "[(%ld, %ld);(%ld, %ld)]", - rect->left, rect->top, rect->right, rect->bottom); - return buf; - } else return "(null)"; -} - -static const char * debugscrollinfo(const SCROLLINFO *pScrollInfo) -{ - char* buf = debug_getbuf(), *text = buf; - int len, size = DEBUG_BUFFER_SIZE; - - if (pScrollInfo == NULL) return "(null)"; - len = snprintf(buf, size, "{cbSize=%d, ", pScrollInfo->cbSize); - if (len == -1) goto end; buf += len; size -= len; - if (pScrollInfo->fMask & SIF_RANGE) - len = snprintf(buf, size, "nMin=%d, nMax=%d, ", pScrollInfo->nMin, pScrollInfo->nMax); - else len = 0; - if (len == -1) goto end; buf += len; size -= len; - if (pScrollInfo->fMask & SIF_PAGE) - len = snprintf(buf, size, "nPage=%u, ", pScrollInfo->nPage); - else len = 0; - if (len == -1) goto end; buf += len; size -= len; - if (pScrollInfo->fMask & SIF_POS) - len = snprintf(buf, size, "nPos=%d, ", pScrollInfo->nPos); - else len = 0; - if (len == -1) goto end; buf += len; size -= len; - if (pScrollInfo->fMask & SIF_TRACKPOS) - len = snprintf(buf, size, "nTrackPos=%d, ", pScrollInfo->nTrackPos); - else len = 0; - if (len == -1) goto end; buf += len; size -= len; - goto undo; -end: - buf = text + strlen(text); -undo: - if (buf - text > 2) { buf[-2] = '}'; buf[-1] = 0; } - return text; -} - -static const char* debugnmlistview(const NMLISTVIEW *plvnm) -{ - if (plvnm) - { - char* buf = debug_getbuf(); - snprintf(buf, DEBUG_BUFFER_SIZE, "iItem=%d, iSubItem=%d, uNewState=0x%x," - " uOldState=0x%x, uChanged=0x%x, ptAction=%s, lParam=%ld\n", - plvnm->iItem, plvnm->iSubItem, plvnm->uNewState, plvnm->uOldState, - plvnm->uChanged, debugpoint(&plvnm->ptAction), plvnm->lParam); - return buf; - } else return "(null)"; -} - -static const char* debuglvitem_t(const LVITEMW *lpLVItem, BOOL isW) -{ - char* buf = debug_getbuf(), *text = buf; - int len, size = DEBUG_BUFFER_SIZE; - - if (lpLVItem == NULL) return "(null)"; - len = snprintf(buf, size, "{iItem=%d, iSubItem=%d, ", lpLVItem->iItem, lpLVItem->iSubItem); - if (len == -1) goto end; buf += len; size -= len; - if (lpLVItem->mask & LVIF_STATE) - len = snprintf(buf, size, "state=%x, stateMask=%x, ", lpLVItem->state, lpLVItem->stateMask); - else len = 0; - if (len == -1) goto end; buf += len; size -= len; - if (lpLVItem->mask & LVIF_TEXT) - len = snprintf(buf, size, "pszText=%s, cchTextMax=%d, ", debugtext_tn(lpLVItem->pszText, isW, 80), lpLVItem->cchTextMax); - else len = 0; - if (len == -1) goto end; buf += len; size -= len; - if (lpLVItem->mask & LVIF_IMAGE) - len = snprintf(buf, size, "iImage=%d, ", lpLVItem->iImage); - else len = 0; - if (len == -1) goto end; buf += len; size -= len; - if (lpLVItem->mask & LVIF_PARAM) - len = snprintf(buf, size, "lParam=%lx, ", lpLVItem->lParam); - else len = 0; - if (len == -1) goto end; buf += len; size -= len; - if (lpLVItem->mask & LVIF_INDENT) - len = snprintf(buf, size, "iIndent=%d, ", lpLVItem->iIndent); - else len = 0; - if (len == -1) goto end; buf += len; size -= len; - goto undo; -end: - buf = text + strlen(text); -undo: - if (buf - text > 2) { buf[-2] = '}'; buf[-1] = 0; } - return text; -} - -static const char* debuglvcolumn_t(const LVCOLUMNW *lpColumn, BOOL isW) -{ - char* buf = debug_getbuf(), *text = buf; - int len, size = DEBUG_BUFFER_SIZE; - - if (lpColumn == NULL) return "(null)"; - len = snprintf(buf, size, "{"); - if (len == -1) goto end; buf += len; size -= len; - if (lpColumn->mask & LVCF_SUBITEM) - len = snprintf(buf, size, "iSubItem=%d, ", lpColumn->iSubItem); - else len = 0; - if (len == -1) goto end; buf += len; size -= len; - if (lpColumn->mask & LVCF_FMT) - len = snprintf(buf, size, "fmt=%x, ", lpColumn->fmt); - else len = 0; - if (len == -1) goto end; buf += len; size -= len; - if (lpColumn->mask & LVCF_WIDTH) - len = snprintf(buf, size, "cx=%d, ", lpColumn->cx); - else len = 0; - if (len == -1) goto end; buf += len; size -= len; - if (lpColumn->mask & LVCF_TEXT) - len = snprintf(buf, size, "pszText=%s, cchTextMax=%d, ", debugtext_tn(lpColumn->pszText, isW, 80), lpColumn->cchTextMax); - else len = 0; - if (len == -1) goto end; buf += len; size -= len; - if (lpColumn->mask & LVCF_IMAGE) - len = snprintf(buf, size, "iImage=%d, ", lpColumn->iImage); - else len = 0; - if (len == -1) goto end; buf += len; size -= len; - if (lpColumn->mask & LVCF_ORDER) - len = snprintf(buf, size, "iOrder=%d, ", lpColumn->iOrder); - else len = 0; - if (len == -1) goto end; buf += len; size -= len; - goto undo; -end: - buf = text + strlen(text); -undo: - if (buf - text > 2) { buf[-2] = '}'; buf[-1] = 0; } - return text; -} - -static const char* debuglvhittestinfo(const LVHITTESTINFO *lpht) -{ - if (lpht) - { - char* buf = debug_getbuf(); - snprintf(buf, DEBUG_BUFFER_SIZE, "{pt=%s, flags=0x%x, iItem=%d, iSubItem=%d}", - debugpoint(&lpht->pt), lpht->flags, lpht->iItem, lpht->iSubItem); - return buf; - } else return "(null)"; -} - -/* Return the corresponding text for a given scroll value */ -static inline LPCSTR debugscrollcode(int nScrollCode) -{ - switch(nScrollCode) - { - case SB_LINELEFT: return "SB_LINELEFT"; - case SB_LINERIGHT: return "SB_LINERIGHT"; - case SB_PAGELEFT: return "SB_PAGELEFT"; - case SB_PAGERIGHT: return "SB_PAGERIGHT"; - case SB_THUMBPOSITION: return "SB_THUMBPOSITION"; - case SB_THUMBTRACK: return "SB_THUMBTRACK"; - case SB_ENDSCROLL: return "SB_ENDSCROLL"; - case SB_INTERNAL: return "SB_INTERNAL"; - default: return "unknown"; - } -} - - -/******** Notification functions i************************************/ - -static LRESULT notify_hdr(LISTVIEW_INFO *infoPtr, INT code, LPNMHDR pnmh) -{ - LRESULT result; - - TRACE("(code=%d)\n", code); - - pnmh->hwndFrom = infoPtr->hwndSelf; - pnmh->idFrom = GetWindowLongPtrW(infoPtr->hwndSelf, GWLP_ID); - pnmh->code = code; - result = SendMessageW(infoPtr->hwndNotify, WM_NOTIFY, - (WPARAM)pnmh->idFrom, (LPARAM)pnmh); - - TRACE(" <= %ld\n", result); - - return result; -} - -static inline LRESULT notify(LISTVIEW_INFO *infoPtr, INT code) -{ - NMHDR nmh; - return notify_hdr(infoPtr, code, &nmh); -} - -static inline void notify_itemactivate(LISTVIEW_INFO *infoPtr, LVHITTESTINFO *htInfo) -{ - NMITEMACTIVATE nmia; - LVITEMW item; - - if (htInfo) { - nmia.uNewState = 0; - nmia.uOldState = 0; - nmia.uChanged = 0; - nmia.uKeyFlags = 0; - - item.mask = LVIF_PARAM|LVIF_STATE; - item.iItem = htInfo->iItem; - item.iSubItem = 0; - if (LISTVIEW_GetItemT(infoPtr, &item, TRUE)) { - nmia.lParam = item.lParam; - nmia.uOldState = item.state; - nmia.uNewState = item.state | LVIS_ACTIVATING; - nmia.uChanged = LVIF_STATE; - } - - nmia.iItem = htInfo->iItem; - nmia.iSubItem = htInfo->iSubItem; - nmia.ptAction = htInfo->pt; - - if (GetKeyState(VK_SHIFT) & 0x8000) nmia.uKeyFlags |= LVKF_SHIFT; - if (GetKeyState(VK_CONTROL) & 0x8000) nmia.uKeyFlags |= LVKF_CONTROL; - if (GetKeyState(VK_MENU) & 0x8000) nmia.uKeyFlags |= LVKF_ALT; - } - notify_hdr(infoPtr, LVN_ITEMACTIVATE, (LPNMHDR)&nmia); -} - -static inline LRESULT notify_listview(LISTVIEW_INFO *infoPtr, INT code, LPNMLISTVIEW plvnm) -{ - TRACE("(code=%d, plvnm=%s)\n", code, debugnmlistview(plvnm)); - return notify_hdr(infoPtr, code, (LPNMHDR)plvnm); -} - -static LRESULT notify_click(LISTVIEW_INFO *infoPtr, INT code, LVHITTESTINFO *lvht) -{ - NMLISTVIEW nmlv; - LVITEMW item; - - TRACE("code=%d, lvht=%s\n", code, debuglvhittestinfo(lvht)); - ZeroMemory(&nmlv, sizeof(nmlv)); - nmlv.iItem = lvht->iItem; - nmlv.iSubItem = lvht->iSubItem; - nmlv.ptAction = lvht->pt; - item.mask = LVIF_PARAM; - item.iItem = lvht->iItem; - item.iSubItem = 0; - if (LISTVIEW_GetItemT(infoPtr, &item, TRUE)) nmlv.lParam = item.lParam; - return notify_listview(infoPtr, code, &nmlv); -} - -static void notify_deleteitem(LISTVIEW_INFO *infoPtr, INT nItem) -{ - NMLISTVIEW nmlv; - LVITEMW item; - - ZeroMemory(&nmlv, sizeof (NMLISTVIEW)); - nmlv.iItem = nItem; - item.mask = LVIF_PARAM; - item.iItem = nItem; - item.iSubItem = 0; - if (LISTVIEW_GetItemT(infoPtr, &item, TRUE)) nmlv.lParam = item.lParam; - notify_listview(infoPtr, LVN_DELETEITEM, &nmlv); -} - -static int get_ansi_notification(INT unicodeNotificationCode) -{ - switch (unicodeNotificationCode) - { - case LVN_BEGINLABELEDITW: return LVN_BEGINLABELEDITA; - case LVN_ENDLABELEDITW: return LVN_ENDLABELEDITA; - case LVN_GETDISPINFOW: return LVN_GETDISPINFOA; - case LVN_SETDISPINFOW: return LVN_SETDISPINFOA; - case LVN_ODFINDITEMW: return LVN_ODFINDITEMA; - case LVN_GETINFOTIPW: return LVN_GETINFOTIPA; - } - ERR("unknown notification %x\n", unicodeNotificationCode); - assert(FALSE); - return 0; -} - -/* - Send notification. depends on dispinfoW having same - structure as dispinfoA. - infoPtr : listview struct - notificationCode : *Unicode* notification code - pdi : dispinfo structure (can be unicode or ansi) - isW : TRUE if dispinfo is Unicode -*/ -static BOOL notify_dispinfoT(LISTVIEW_INFO *infoPtr, INT notificationCode, LPNMLVDISPINFOW pdi, BOOL isW) -{ - BOOL bResult = FALSE; - BOOL convertToAnsi = FALSE, convertToUnicode = FALSE; - INT cchTempBufMax = 0, savCchTextMax = 0, realNotifCode; - LPWSTR pszTempBuf = NULL, savPszText = NULL; - - if ((pdi->item.mask & LVIF_TEXT) && is_textT(pdi->item.pszText, isW)) - { - convertToAnsi = (isW && infoPtr->notifyFormat == NFR_ANSI); - convertToUnicode = (!isW && infoPtr->notifyFormat == NFR_UNICODE); - } - - if (convertToAnsi || convertToUnicode) - { - if (notificationCode != LVN_GETDISPINFOW) - { - cchTempBufMax = convertToUnicode ? - MultiByteToWideChar(CP_ACP, 0, (LPCSTR)pdi->item.pszText, -1, NULL, 0): - WideCharToMultiByte(CP_ACP, 0, pdi->item.pszText, -1, NULL, 0, NULL, NULL); - } - else - { - cchTempBufMax = pdi->item.cchTextMax; - *pdi->item.pszText = 0; /* make sure we don't process garbage */ - } - - pszTempBuf = HeapAlloc(GetProcessHeap(), 0, - (convertToUnicode ? sizeof(WCHAR) : sizeof(CHAR)) * cchTempBufMax); - if (!pszTempBuf) return FALSE; - - if (convertToUnicode) - MultiByteToWideChar(CP_ACP, 0, (LPCSTR)pdi->item.pszText, -1, - pszTempBuf, cchTempBufMax); - else - WideCharToMultiByte(CP_ACP, 0, pdi->item.pszText, -1, (LPSTR) pszTempBuf, - cchTempBufMax, NULL, NULL); - - savCchTextMax = pdi->item.cchTextMax; - savPszText = pdi->item.pszText; - pdi->item.pszText = pszTempBuf; - pdi->item.cchTextMax = cchTempBufMax; - } - - if (infoPtr->notifyFormat == NFR_ANSI) - realNotifCode = get_ansi_notification(notificationCode); - else - realNotifCode = notificationCode; - TRACE(" pdi->item=%s\n", debuglvitem_t(&pdi->item, infoPtr->notifyFormat != NFR_ANSI)); - bResult = notify_hdr(infoPtr, realNotifCode, &pdi->hdr); - - if (convertToUnicode || convertToAnsi) - { - if (convertToUnicode) /* note : pointer can be changed by app ! */ - WideCharToMultiByte(CP_ACP, 0, pdi->item.pszText, -1, (LPSTR) savPszText, - savCchTextMax, NULL, NULL); - else - MultiByteToWideChar(CP_ACP, 0, (LPSTR) pdi->item.pszText, -1, - savPszText, savCchTextMax); - pdi->item.pszText = savPszText; /* restores our buffer */ - pdi->item.cchTextMax = savCchTextMax; - HeapFree(GetProcessHeap(), 0, pszTempBuf); - } - return bResult; -} - -static void customdraw_fill(NMLVCUSTOMDRAW *lpnmlvcd, LISTVIEW_INFO *infoPtr, HDC hdc, - const RECT *rcBounds, const LVITEMW *lplvItem) -{ - ZeroMemory(lpnmlvcd, sizeof(NMLVCUSTOMDRAW)); - lpnmlvcd->nmcd.hdc = hdc; - lpnmlvcd->nmcd.rc = *rcBounds; - lpnmlvcd->clrTextBk = infoPtr->clrTextBk; - lpnmlvcd->clrText = infoPtr->clrText; - if (!lplvItem) return; - lpnmlvcd->nmcd.dwItemSpec = lplvItem->iItem + 1; - lpnmlvcd->iSubItem = lplvItem->iSubItem; - if (lplvItem->state & LVIS_SELECTED) lpnmlvcd->nmcd.uItemState |= CDIS_SELECTED; - if (lplvItem->state & LVIS_FOCUSED) lpnmlvcd->nmcd.uItemState |= CDIS_FOCUS; - if (lplvItem->iItem == infoPtr->nHotItem) lpnmlvcd->nmcd.uItemState |= CDIS_HOT; - lpnmlvcd->nmcd.lItemlParam = lplvItem->lParam; -} - -static inline DWORD notify_customdraw (LISTVIEW_INFO *infoPtr, DWORD dwDrawStage, NMLVCUSTOMDRAW *lpnmlvcd) -{ - BOOL isForItem = (lpnmlvcd->nmcd.dwItemSpec != 0); - DWORD result; - - lpnmlvcd->nmcd.dwDrawStage = dwDrawStage; - if (isForItem) lpnmlvcd->nmcd.dwDrawStage |= CDDS_ITEM; - if (lpnmlvcd->iSubItem) lpnmlvcd->nmcd.dwDrawStage |= CDDS_SUBITEM; - if (isForItem) lpnmlvcd->nmcd.dwItemSpec--; - result = notify_hdr(infoPtr, NM_CUSTOMDRAW, &lpnmlvcd->nmcd.hdr); - if (isForItem) lpnmlvcd->nmcd.dwItemSpec++; - return result; -} - -static void prepaint_setup (LISTVIEW_INFO *infoPtr, HDC hdc, NMLVCUSTOMDRAW *lpnmlvcd) -{ - /* apprently, for selected items, we have to override the returned values */ - if (lpnmlvcd->nmcd.uItemState & CDIS_SELECTED) - { - if (infoPtr->bFocus) - { - lpnmlvcd->clrTextBk = comctl32_color.clrHighlight; - lpnmlvcd->clrText = comctl32_color.clrHighlightText; - } - else if (infoPtr->dwStyle & LVS_SHOWSELALWAYS) - { - lpnmlvcd->clrTextBk = comctl32_color.clr3dFace; - lpnmlvcd->clrText = comctl32_color.clrBtnText; - } - } - - /* Set the text attributes */ - if (lpnmlvcd->clrTextBk != CLR_NONE) - { - SetBkMode(hdc, OPAQUE); - if (lpnmlvcd->clrTextBk == CLR_DEFAULT) - SetBkColor(hdc, infoPtr->clrTextBkDefault); - else - SetBkColor(hdc,lpnmlvcd->clrTextBk); - } - else - SetBkMode(hdc, TRANSPARENT); - SetTextColor(hdc, lpnmlvcd->clrText); -} - -static inline DWORD notify_postpaint (LISTVIEW_INFO *infoPtr, NMLVCUSTOMDRAW *lpnmlvcd) -{ - return notify_customdraw(infoPtr, CDDS_POSTPAINT, lpnmlvcd); -} - -/******** Item iterator functions **********************************/ - -static RANGES ranges_create(int count); -static void ranges_destroy(RANGES ranges); -static BOOL ranges_add(RANGES ranges, RANGE range); -static BOOL ranges_del(RANGES ranges, RANGE range); -static void ranges_dump(RANGES ranges); - -static inline BOOL ranges_additem(RANGES ranges, INT nItem) -{ - RANGE range = { nItem, nItem + 1 }; - - return ranges_add(ranges, range); -} - -static inline BOOL ranges_delitem(RANGES ranges, INT nItem) -{ - RANGE range = { nItem, nItem + 1 }; - - return ranges_del(ranges, range); -} - -/*** - * ITERATOR DOCUMENTATION - * - * The iterator functions allow for easy, and convenient iteration - * over items of iterest in the list. Typically, you create a - * iterator, use it, and destroy it, as such: - * ITERATOR i; - * - * iterator_xxxitems(&i, ...); - * while (iterator_{prev,next}(&i) - * { - * //code which uses i.nItem - * } - * iterator_destroy(&i); - * - * where xxx is either: framed, or visible. - * Note that it is important that the code destroys the iterator - * after it's done with it, as the creation of the iterator may - * allocate memory, which thus needs to be freed. - * - * You can iterate both forwards, and backwards through the list, - * by using iterator_next or iterator_prev respectively. - * - * Lower numbered items are draw on top of higher number items in - * LVS_ICON, and LVS_SMALLICON (which are the only modes where - * items may overlap). So, to test items, you should use - * iterator_next - * which lists the items top to bottom (in Z-order). - * For drawing items, you should use - * iterator_prev - * which lists the items bottom to top (in Z-order). - * If you keep iterating over the items after the end-of-items - * marker (-1) is returned, the iterator will start from the - * beginning. Typically, you don't need to test for -1, - * because iterator_{next,prev} will return TRUE if more items - * are to be iterated over, or FALSE otherwise. - * - * Note: the iterator is defined to be bidirectional. That is, - * any number of prev followed by any number of next, or - * five versa, should leave the iterator at the same item: - * prev * n, next * n = next * n, prev * n - * - * The iterator has a notion of a out-of-order, special item, - * which sits at the start of the list. This is used in - * LVS_ICON, and LVS_SMALLICON mode to handle the focused item, - * which needs to be first, as it may overlap other items. - * - * The code is a bit messy because we have: - * - a special item to deal with - * - simple range, or composite range - * - empty range. - * If you find bugs, or want to add features, please make sure you - * always check/modify *both* iterator_prev, and iterator_next. - */ - -/**** - * This function iterates through the items in increasing order, - * but prefixed by the special item, then -1. That is: - * special, 1, 2, 3, ..., n, -1. - * Each item is listed only once. - */ -static inline BOOL iterator_next(ITERATOR* i) -{ - if (i->nItem == -1) - { - i->nItem = i->nSpecial; - if (i->nItem != -1) return TRUE; - } - if (i->nItem == i->nSpecial) - { - if (i->ranges) i->index = 0; - goto pickarange; - } - - i->nItem++; -testitem: - if (i->nItem == i->nSpecial) i->nItem++; - if (i->nItem < i->range.upper) return TRUE; - -pickarange: - if (i->ranges) - { - if (i->index < DPA_GetPtrCount(i->ranges->hdpa)) - i->range = *(RANGE*)DPA_GetPtr(i->ranges->hdpa, i->index++); - else goto end; - } - else if (i->nItem >= i->range.upper) goto end; - - i->nItem = i->range.lower; - if (i->nItem >= 0) goto testitem; -end: - i->nItem = -1; - return FALSE; -} - -/**** - * This function iterates through the items in decreasing order, - * followed by the special item, then -1. That is: - * n, n-1, ..., 3, 2, 1, special, -1. - * Each item is listed only once. - */ -static inline BOOL iterator_prev(ITERATOR* i) -{ - BOOL start = FALSE; - - if (i->nItem == -1) - { - start = TRUE; - if (i->ranges) i->index = DPA_GetPtrCount(i->ranges->hdpa); - goto pickarange; - } - if (i->nItem == i->nSpecial) - { - i->nItem = -1; - return FALSE; - } - -testitem: - i->nItem--; - if (i->nItem == i->nSpecial) i->nItem--; - if (i->nItem >= i->range.lower) return TRUE; - -pickarange: - if (i->ranges) - { - if (i->index > 0) - i->range = *(RANGE*)DPA_GetPtr(i->ranges->hdpa, --i->index); - else goto end; - } - else if (!start && i->nItem < i->range.lower) goto end; - - i->nItem = i->range.upper; - if (i->nItem > 0) goto testitem; -end: - return (i->nItem = i->nSpecial) != -1; -} - -static RANGE iterator_range(ITERATOR* i) -{ - RANGE range; - - if (!i->ranges) return i->range; - - if (DPA_GetPtrCount(i->ranges->hdpa) > 0) - { - range.lower = (*(RANGE*)DPA_GetPtr(i->ranges->hdpa, 0)).lower; - range.upper = (*(RANGE*)DPA_GetPtr(i->ranges->hdpa, DPA_GetPtrCount(i->ranges->hdpa) - 1)).upper; - } - else range.lower = range.upper = 0; - - return range; -} - -/*** - * Releases resources associated with this ierator. - */ -static inline void iterator_destroy(ITERATOR* i) -{ - ranges_destroy(i->ranges); -} - -/*** - * Create an empty iterator. - */ -static inline BOOL iterator_empty(ITERATOR* i) -{ - ZeroMemory(i, sizeof(*i)); - i->nItem = i->nSpecial = i->range.lower = i->range.upper = -1; - return TRUE; -} - -/*** - * Create an iterator over a range. - */ -static inline BOOL iterator_rangeitems(ITERATOR* i, RANGE range) -{ - iterator_empty(i); - i->range = range; - return TRUE; -} - -/*** - * Create an iterator over a bunch of ranges. - * Please note that the iterator will take ownership of the ranges, - * and will free them upon destruction. - */ -static inline BOOL iterator_rangesitems(ITERATOR* i, RANGES ranges) -{ - iterator_empty(i); - i->ranges = ranges; - return TRUE; -} - -/*** - * Creates an iterator over the items which intersect lprc. - */ -static BOOL iterator_frameditems(ITERATOR* i, LISTVIEW_INFO* infoPtr, const RECT *lprc) -{ - UINT uView = infoPtr->dwStyle & LVS_TYPEMASK; - RECT frame = *lprc, rcItem, rcTemp; - POINT Origin; - - /* in case we fail, we want to return an empty iterator */ - if (!iterator_empty(i)) return FALSE; - - LISTVIEW_GetOrigin(infoPtr, &Origin); - - TRACE("(lprc=%s)\n", debugrect(lprc)); - OffsetRect(&frame, -Origin.x, -Origin.y); - - if (uView == LVS_ICON || uView == LVS_SMALLICON) - { - INT nItem; - - if (uView == LVS_ICON && infoPtr->nFocusedItem != -1) - { - LISTVIEW_GetItemBox(infoPtr, infoPtr->nFocusedItem, &rcItem); - if (IntersectRect(&rcTemp, &rcItem, lprc)) - i->nSpecial = infoPtr->nFocusedItem; - } - if (!(iterator_rangesitems(i, ranges_create(50)))) return FALSE; - /* to do better here, we need to have PosX, and PosY sorted */ - TRACE("building icon ranges:\n"); - for (nItem = 0; nItem < infoPtr->nItemCount; nItem++) - { - rcItem.left = (LONG)DPA_GetPtr(infoPtr->hdpaPosX, nItem); - rcItem.top = (LONG)DPA_GetPtr(infoPtr->hdpaPosY, nItem); - rcItem.right = rcItem.left + infoPtr->nItemWidth; - rcItem.bottom = rcItem.top + infoPtr->nItemHeight; - if (IntersectRect(&rcTemp, &rcItem, &frame)) - ranges_additem(i->ranges, nItem); - } - return TRUE; - } - else if (uView == LVS_REPORT) - { - RANGE range; - - if (frame.left >= infoPtr->nItemWidth) return TRUE; - if (frame.top >= infoPtr->nItemHeight * infoPtr->nItemCount) return TRUE; - - range.lower = max(frame.top / infoPtr->nItemHeight, 0); - range.upper = min((frame.bottom - 1) / infoPtr->nItemHeight, infoPtr->nItemCount - 1) + 1; - if (range.upper <= range.lower) return TRUE; - if (!iterator_rangeitems(i, range)) return FALSE; - TRACE(" report=%s\n", debugrange(&i->range)); - } - else - { - INT nPerCol = max((infoPtr->rcList.bottom - infoPtr->rcList.top) / infoPtr->nItemHeight, 1); - INT nFirstRow = max(frame.top / infoPtr->nItemHeight, 0); - INT nLastRow = min((frame.bottom - 1) / infoPtr->nItemHeight, nPerCol - 1); - INT nFirstCol = max(frame.left / infoPtr->nItemWidth, 0); - INT nLastCol = min((frame.right - 1) / infoPtr->nItemWidth, (infoPtr->nItemCount + nPerCol - 1) / nPerCol); - INT lower = nFirstCol * nPerCol + nFirstRow; - RANGE item_range; - INT nCol; - - TRACE("nPerCol=%d, nFirstRow=%d, nLastRow=%d, nFirstCol=%d, nLastCol=%d, lower=%d\n", - nPerCol, nFirstRow, nLastRow, nFirstCol, nLastCol, lower); - - if (nLastCol < nFirstCol || nLastRow < nFirstRow) return TRUE; - - if (!(iterator_rangesitems(i, ranges_create(nLastCol - nFirstCol + 1)))) return FALSE; - TRACE("building list ranges:\n"); - for (nCol = nFirstCol; nCol <= nLastCol; nCol++) - { - item_range.lower = nCol * nPerCol + nFirstRow; - if(item_range.lower >= infoPtr->nItemCount) break; - item_range.upper = min(nCol * nPerCol + nLastRow + 1, infoPtr->nItemCount); - TRACE(" list=%s\n", debugrange(&item_range)); - ranges_add(i->ranges, item_range); - } - } - - return TRUE; -} - -/*** - * Creates an iterator over the items which intersect the visible region of hdc. - */ -static BOOL iterator_visibleitems(ITERATOR *i, LISTVIEW_INFO *infoPtr, HDC hdc) -{ - POINT Origin, Position; - RECT rcItem, rcClip; - INT rgntype; - - rgntype = GetClipBox(hdc, &rcClip); - if (rgntype == NULLREGION) return iterator_empty(i); - if (!iterator_frameditems(i, infoPtr, &rcClip)) return FALSE; - if (rgntype == SIMPLEREGION) return TRUE; - - /* first deal with the special item */ - if (i->nSpecial != -1) - { - LISTVIEW_GetItemBox(infoPtr, i->nSpecial, &rcItem); - if (!RectVisible(hdc, &rcItem)) i->nSpecial = -1; - } - - /* if we can't deal with the region, we'll just go with the simple range */ - LISTVIEW_GetOrigin(infoPtr, &Origin); - TRACE("building visible range:\n"); - if (!i->ranges && i->range.lower < i->range.upper) - { - if (!(i->ranges = ranges_create(50))) return TRUE; - if (!ranges_add(i->ranges, i->range)) - { - ranges_destroy(i->ranges); - i->ranges = 0; - return TRUE; - } - } - - /* now delete the invisible items from the list */ - while(iterator_next(i)) - { - LISTVIEW_GetItemOrigin(infoPtr, i->nItem, &Position); - rcItem.left = Position.x + Origin.x; - rcItem.top = Position.y + Origin.y; - rcItem.right = rcItem.left + infoPtr->nItemWidth; - rcItem.bottom = rcItem.top + infoPtr->nItemHeight; - if (!RectVisible(hdc, &rcItem)) - ranges_delitem(i->ranges, i->nItem); - } - /* the iterator should restart on the next iterator_next */ - TRACE("done\n"); - - return TRUE; -} - -/******** Misc helper functions ************************************/ - -static inline LRESULT CallWindowProcT(WNDPROC proc, HWND hwnd, UINT uMsg, - WPARAM wParam, LPARAM lParam, BOOL isW) -{ - if (isW) return CallWindowProcW(proc, hwnd, uMsg, wParam, lParam); - else return CallWindowProcA(proc, hwnd, uMsg, wParam, lParam); -} - -static inline BOOL is_autoarrange(LISTVIEW_INFO *infoPtr) -{ - UINT uView = infoPtr->dwStyle & LVS_TYPEMASK; - - return ((infoPtr->dwStyle & LVS_AUTOARRANGE) || infoPtr->bAutoarrange) && - (uView == LVS_ICON || uView == LVS_SMALLICON); -} - -/******** Internal API functions ************************************/ - -static inline COLUMN_INFO * LISTVIEW_GetColumnInfo(LISTVIEW_INFO *infoPtr, INT nSubItem) -{ - static COLUMN_INFO mainItem; - - if (nSubItem == 0 && DPA_GetPtrCount(infoPtr->hdpaColumns) == 0) return &mainItem; - assert (nSubItem >= 0 && nSubItem < DPA_GetPtrCount(infoPtr->hdpaColumns)); - return (COLUMN_INFO *)DPA_GetPtr(infoPtr->hdpaColumns, nSubItem); -} - -static inline void LISTVIEW_GetHeaderRect(LISTVIEW_INFO *infoPtr, INT nSubItem, RECT *lprc) -{ - *lprc = LISTVIEW_GetColumnInfo(infoPtr, nSubItem)->rcHeader; -} - -static inline BOOL LISTVIEW_GetItemW(LISTVIEW_INFO *infoPtr, LPLVITEMW lpLVItem) -{ - return LISTVIEW_GetItemT(infoPtr, lpLVItem, TRUE); -} - -/* Listview invalidation functions: use _only_ these functions to invalidate */ - -static inline BOOL is_redrawing(LISTVIEW_INFO *infoPtr) -{ - return infoPtr->bRedraw; -} - -static inline void LISTVIEW_InvalidateRect(LISTVIEW_INFO *infoPtr, const RECT* rect) -{ - if(!is_redrawing(infoPtr)) return; - TRACE(" invalidating rect=%s\n", debugrect(rect)); - InvalidateRect(infoPtr->hwndSelf, rect, TRUE); -} - -static inline void LISTVIEW_InvalidateItem(LISTVIEW_INFO *infoPtr, INT nItem) -{ - RECT rcBox; - - if(!is_redrawing(infoPtr)) return; - LISTVIEW_GetItemBox(infoPtr, nItem, &rcBox); - LISTVIEW_InvalidateRect(infoPtr, &rcBox); -} - -static inline void LISTVIEW_InvalidateSubItem(LISTVIEW_INFO *infoPtr, INT nItem, INT nSubItem) -{ - POINT Origin, Position; - RECT rcBox; - - if(!is_redrawing(infoPtr)) return; - assert ((infoPtr->dwStyle & LVS_TYPEMASK) == LVS_REPORT); - LISTVIEW_GetOrigin(infoPtr, &Origin); - LISTVIEW_GetItemOrigin(infoPtr, nItem, &Position); - LISTVIEW_GetHeaderRect(infoPtr, nSubItem, &rcBox); - rcBox.top = 0; - rcBox.bottom = infoPtr->nItemHeight; - OffsetRect(&rcBox, Origin.x + Position.x, Origin.y + Position.y); - LISTVIEW_InvalidateRect(infoPtr, &rcBox); -} - -static inline void LISTVIEW_InvalidateList(LISTVIEW_INFO *infoPtr) -{ - LISTVIEW_InvalidateRect(infoPtr, NULL); -} - -static inline void LISTVIEW_InvalidateColumn(LISTVIEW_INFO *infoPtr, INT nColumn) -{ - RECT rcCol; - - if(!is_redrawing(infoPtr)) return; - LISTVIEW_GetHeaderRect(infoPtr, nColumn, &rcCol); - rcCol.top = infoPtr->rcList.top; - rcCol.bottom = infoPtr->rcList.bottom; - LISTVIEW_InvalidateRect(infoPtr, &rcCol); -} - -/*** - * DESCRIPTION: - * Retrieves the number of items that can fit vertically in the client area. - * - * PARAMETER(S): - * [I] infoPtr : valid pointer to the listview structure - * - * RETURN: - * Number of items per row. - */ -static inline INT LISTVIEW_GetCountPerRow(LISTVIEW_INFO *infoPtr) -{ - INT nListWidth = infoPtr->rcList.right - infoPtr->rcList.left; - - return max(nListWidth/infoPtr->nItemWidth, 1); -} - -/*** - * DESCRIPTION: - * Retrieves the number of items that can fit horizontally in the client - * area. - * - * PARAMETER(S): - * [I] infoPtr : valid pointer to the listview structure - * - * RETURN: - * Number of items per column. - */ -static inline INT LISTVIEW_GetCountPerColumn(LISTVIEW_INFO *infoPtr) -{ - INT nListHeight = infoPtr->rcList.bottom - infoPtr->rcList.top; - - return max(nListHeight / infoPtr->nItemHeight, 1); -} - - -/************************************************************************* - * LISTVIEW_ProcessLetterKeys - * - * Processes keyboard messages generated by pressing the letter keys - * on the keyboard. - * What this does is perform a case insensitive search from the - * current position with the following quirks: - * - If two chars or more are pressed in quick succession we search - * for the corresponding string (e.g. 'abc'). - * - If there is a delay we wipe away the current search string and - * restart with just that char. - * - If the user keeps pressing the same character, whether slowly or - * fast, so that the search string is entirely composed of this - * character ('aaaaa' for instance), then we search for first item - * that starting with that character. - * - If the user types the above character in quick succession, then - * we must also search for the corresponding string ('aaaaa'), and - * go to that string if there is a match. - * - * PARAMETERS - * [I] hwnd : handle to the window - * [I] charCode : the character code, the actual character - * [I] keyData : key data - * - * RETURNS - * - * Zero. - * - * BUGS - * - * - The current implementation has a list of characters it will - * accept and it ignores averything else. In particular it will - * ignore accentuated characters which seems to match what - * Windows does. But I'm not sure it makes sense to follow - * Windows there. - * - We don't sound a beep when the search fails. - * - * SEE ALSO - * - * TREEVIEW_ProcessLetterKeys - */ -static INT LISTVIEW_ProcessLetterKeys(LISTVIEW_INFO *infoPtr, WPARAM charCode, LPARAM keyData) -{ - INT nItem; - INT endidx,idx; - LVITEMW item; - WCHAR buffer[MAX_PATH]; - DWORD lastKeyPressTimestamp = infoPtr->lastKeyPressTimestamp; - - /* simple parameter checking */ - if (!charCode || !keyData) return 0; - - /* only allow the valid WM_CHARs through */ - if (!isalnum(charCode) && - charCode != '.' && charCode != '`' && charCode != '!' && - charCode != '@' && charCode != '#' && charCode != '$' && - charCode != '%' && charCode != '^' && charCode != '&' && - charCode != '*' && charCode != '(' && charCode != ')' && - charCode != '-' && charCode != '_' && charCode != '+' && - charCode != '=' && charCode != '\\'&& charCode != ']' && - charCode != '}' && charCode != '[' && charCode != '{' && - charCode != '/' && charCode != '?' && charCode != '>' && - charCode != '<' && charCode != ',' && charCode != '~') - return 0; - - /* if there's one item or less, there is no where to go */ - if (infoPtr->nItemCount <= 1) return 0; - - /* update the search parameters */ - infoPtr->lastKeyPressTimestamp = GetTickCount(); - if (infoPtr->lastKeyPressTimestamp - lastKeyPressTimestamp < KEY_DELAY) { - if (infoPtr->nSearchParamLength < MAX_PATH) - infoPtr->szSearchParam[infoPtr->nSearchParamLength++]=charCode; - if (infoPtr->charCode != charCode) - infoPtr->charCode = charCode = 0; - } else { - infoPtr->charCode=charCode; - infoPtr->szSearchParam[0]=charCode; - infoPtr->nSearchParamLength=1; - /* Redundant with the 1 char string */ - charCode=0; - } - - /* and search from the current position */ - nItem=-1; - if (infoPtr->nFocusedItem >= 0) { - endidx=infoPtr->nFocusedItem; - idx=endidx; - /* if looking for single character match, - * then we must always move forward - */ - if (infoPtr->nSearchParamLength == 1) - idx++; - } else { - endidx=infoPtr->nItemCount; - idx=0; - } - do { - if (idx == infoPtr->nItemCount) { - if (endidx == infoPtr->nItemCount || endidx == 0) - break; - idx=0; - } - - /* get item */ - item.mask = LVIF_TEXT; - item.iItem = idx; - item.iSubItem = 0; - item.pszText = buffer; - item.cchTextMax = MAX_PATH; - if (!LISTVIEW_GetItemW(infoPtr, &item)) return 0; - - /* check for a match */ - if (lstrncmpiW(item.pszText,infoPtr->szSearchParam,infoPtr->nSearchParamLength) == 0) { - nItem=idx; - break; - } else if ( (charCode != 0) && (nItem == -1) && (nItem != infoPtr->nFocusedItem) && - (lstrncmpiW(item.pszText,infoPtr->szSearchParam,1) == 0) ) { - /* This would work but we must keep looking for a longer match */ - nItem=idx; - } - idx++; - } while (idx != endidx); - - if (nItem != -1) - LISTVIEW_KeySelection(infoPtr, nItem); - - return 0; -} - -/************************************************************************* - * LISTVIEW_UpdateHeaderSize [Internal] - * - * Function to resize the header control - * - * PARAMS - * [I] hwnd : handle to a window - * [I] nNewScrollPos : scroll pos to set - * - * RETURNS - * None. - */ -static void LISTVIEW_UpdateHeaderSize(LISTVIEW_INFO *infoPtr, INT nNewScrollPos) -{ - RECT winRect; - POINT point[2]; - - TRACE("nNewScrollPos=%d\n", nNewScrollPos); - - GetWindowRect(infoPtr->hwndHeader, &winRect); - point[0].x = winRect.left; - point[0].y = winRect.top; - point[1].x = winRect.right; - point[1].y = winRect.bottom; - - MapWindowPoints(HWND_DESKTOP, infoPtr->hwndSelf, point, 2); - point[0].x = -nNewScrollPos; - point[1].x += nNewScrollPos; - - SetWindowPos(infoPtr->hwndHeader,0, - point[0].x,point[0].y,point[1].x,point[1].y, - SWP_NOZORDER | SWP_NOACTIVATE); -} - -/*** - * DESCRIPTION: - * Update the scrollbars. This functions should be called whenever - * the content, size or view changes. - * - * PARAMETER(S): - * [I] infoPtr : valid pointer to the listview structure - * - * RETURN: - * None - */ -static void LISTVIEW_UpdateScroll(LISTVIEW_INFO *infoPtr) -{ - UINT uView = infoPtr->dwStyle & LVS_TYPEMASK; - SCROLLINFO horzInfo, vertInfo; - - if ((infoPtr->dwStyle & LVS_NOSCROLL) || !is_redrawing(infoPtr)) return; - - ZeroMemory(&horzInfo, sizeof(SCROLLINFO)); - horzInfo.cbSize = sizeof(SCROLLINFO); - horzInfo.nPage = infoPtr->rcList.right - infoPtr->rcList.left; - - /* for now, we'll set info.nMax to the _count_, and adjust it later */ - if (uView == LVS_LIST) - { - INT nPerCol = LISTVIEW_GetCountPerColumn(infoPtr); - horzInfo.nMax = (infoPtr->nItemCount + nPerCol - 1) / nPerCol; - - /* scroll by at least one column per page */ - if(horzInfo.nPage < infoPtr->nItemWidth) - horzInfo.nPage = infoPtr->nItemWidth; - - horzInfo.nPage /= infoPtr->nItemWidth; - } - else if (uView == LVS_REPORT) - { - horzInfo.nMax = infoPtr->nItemWidth; - } - else /* LVS_ICON, or LVS_SMALLICON */ - { - RECT rcView; - - if (LISTVIEW_GetViewRect(infoPtr, &rcView)) horzInfo.nMax = rcView.right - rcView.left; - } - - horzInfo.fMask = SIF_RANGE | SIF_PAGE; - horzInfo.nMax = max(horzInfo.nMax - 1, 0); - SetScrollInfo(infoPtr->hwndSelf, SB_HORZ, &horzInfo, TRUE); - TRACE("horzInfo=%s\n", debugscrollinfo(&horzInfo)); - - /* Setting the horizontal scroll can change the listview size - * (and potentially everything else) so we need to recompute - * everything again for the vertical scroll - */ - - ZeroMemory(&vertInfo, sizeof(SCROLLINFO)); - vertInfo.cbSize = sizeof(SCROLLINFO); - vertInfo.nPage = infoPtr->rcList.bottom - infoPtr->rcList.top; - - if (uView == LVS_REPORT) - { - vertInfo.nMax = infoPtr->nItemCount; - - /* scroll by at least one page */ - if(vertInfo.nPage < infoPtr->nItemHeight) - vertInfo.nPage = infoPtr->nItemHeight; - - vertInfo.nPage /= infoPtr->nItemHeight; - } - else if (uView != LVS_LIST) /* LVS_ICON, or LVS_SMALLICON */ - { - RECT rcView; - - if (LISTVIEW_GetViewRect(infoPtr, &rcView)) vertInfo.nMax = rcView.bottom - rcView.top; - } - - vertInfo.fMask = SIF_RANGE | SIF_PAGE; - vertInfo.nMax = max(vertInfo.nMax - 1, 0); - SetScrollInfo(infoPtr->hwndSelf, SB_VERT, &vertInfo, TRUE); - TRACE("vertInfo=%s\n", debugscrollinfo(&vertInfo)); - - /* Update the Header Control */ - if (uView == LVS_REPORT) - { - horzInfo.fMask = SIF_POS; - GetScrollInfo(infoPtr->hwndSelf, SB_HORZ, &horzInfo); - LISTVIEW_UpdateHeaderSize(infoPtr, horzInfo.nPos); - } -} - - -/*** - * DESCRIPTION: - * Shows/hides the focus rectangle. - * - * PARAMETER(S): - * [I] infoPtr : valid pointer to the listview structure - * [I] fShow : TRUE to show the focus, FALSE to hide it. - * - * RETURN: - * None - */ -static void LISTVIEW_ShowFocusRect(LISTVIEW_INFO *infoPtr, BOOL fShow) -{ - UINT uView = infoPtr->dwStyle & LVS_TYPEMASK; - HDC hdc; - - TRACE("fShow=%d, nItem=%d\n", fShow, infoPtr->nFocusedItem); - - if (infoPtr->nFocusedItem < 0) return; - - /* we need some gymnastics in ICON mode to handle large items */ - if ( (infoPtr->dwStyle & LVS_TYPEMASK) == LVS_ICON ) - { - RECT rcBox; - - LISTVIEW_GetItemBox(infoPtr, infoPtr->nFocusedItem, &rcBox); - if ((rcBox.bottom - rcBox.top) > infoPtr->nItemHeight) - { - LISTVIEW_InvalidateRect(infoPtr, &rcBox); - return; - } - } - - if (!(hdc = GetDC(infoPtr->hwndSelf))) return; - - /* for some reason, owner draw should work only in report mode */ - if ((infoPtr->dwStyle & LVS_OWNERDRAWFIXED) && (uView == LVS_REPORT)) - { - DRAWITEMSTRUCT dis; - LVITEMW item; - - item.iItem = infoPtr->nFocusedItem; - item.iSubItem = 0; - item.mask = LVIF_PARAM; - if (!LISTVIEW_GetItemW(infoPtr, &item)) goto done; - - ZeroMemory(&dis, sizeof(dis)); - dis.CtlType = ODT_LISTVIEW; - dis.CtlID = (UINT)GetWindowLongPtrW(infoPtr->hwndSelf, GWLP_ID); - dis.itemID = item.iItem; - dis.itemAction = ODA_FOCUS; - if (fShow) dis.itemState |= ODS_FOCUS; - dis.hwndItem = infoPtr->hwndSelf; - dis.hDC = hdc; - LISTVIEW_GetItemBox(infoPtr, dis.itemID, &dis.rcItem); - dis.itemData = item.lParam; - - SendMessageW(infoPtr->hwndNotify, WM_DRAWITEM, dis.CtlID, (LPARAM)&dis); - } - else - { - DrawFocusRect(hdc, &infoPtr->rcFocus); - } -done: - ReleaseDC(infoPtr->hwndSelf, hdc); -} - -/*** - * Invalidates all visible selected items. - */ -static void LISTVIEW_InvalidateSelectedItems(LISTVIEW_INFO *infoPtr) -{ - ITERATOR i; - - iterator_frameditems(&i, infoPtr, &infoPtr->rcList); - while(iterator_next(&i)) - { - if (LISTVIEW_GetItemState(infoPtr, i.nItem, LVIS_SELECTED)) - LISTVIEW_InvalidateItem(infoPtr, i.nItem); - } - iterator_destroy(&i); -} - - -/*** - * DESCRIPTION: [INTERNAL] - * Computes an item's (left,top) corner, relative to rcView. - * That is, the position has NOT been made relative to the Origin. - * This is deliberate, to avoid computing the Origin over, and - * over again, when this function is call in a loop. Instead, - * one ca factor the computation of the Origin before the loop, - * and offset the value retured by this function, on every iteration. - * - * PARAMETER(S): - * [I] infoPtr : valid pointer to the listview structure - * [I] nItem : item number - * [O] lpptOrig : item top, left corner - * - * RETURN: - * None. - */ -static void LISTVIEW_GetItemOrigin(LISTVIEW_INFO *infoPtr, INT nItem, LPPOINT lpptPosition) -{ - UINT uView = infoPtr->dwStyle & LVS_TYPEMASK; - - assert(nItem >= 0 && nItem < infoPtr->nItemCount); - - if ((uView == LVS_SMALLICON) || (uView == LVS_ICON)) - { - lpptPosition->x = (LONG)DPA_GetPtr(infoPtr->hdpaPosX, nItem); - lpptPosition->y = (LONG)DPA_GetPtr(infoPtr->hdpaPosY, nItem); - } - else if (uView == LVS_LIST) - { - INT nCountPerColumn = LISTVIEW_GetCountPerColumn(infoPtr); - lpptPosition->x = nItem / nCountPerColumn * infoPtr->nItemWidth; - lpptPosition->y = nItem % nCountPerColumn * infoPtr->nItemHeight; - } - else /* LVS_REPORT */ - { - lpptPosition->x = 0; - lpptPosition->y = nItem * infoPtr->nItemHeight; - } -} - -/*** - * DESCRIPTION: [INTERNAL] - * Compute the rectangles of an item. This is to localize all - * the computations in one place. If you are not interested in some - * of these values, simply pass in a NULL -- the fucntion is smart - * enough to compute only what's necessary. The function computes - * the standard rectangles (BOUNDS, ICON, LABEL) plus a non-standard - * one, the BOX rectangle. This rectangle is very cheap to compute, - * and is guaranteed to contain all the other rectangles. Computing - * the ICON rect is also cheap, but all the others are potentaily - * expensive. This gives an easy and effective optimization when - * searching (like point inclusion, or rectangle intersection): - * first test against the BOX, and if TRUE, test agains the desired - * rectangle. - * If the function does not have all the necessary information - * to computed the requested rectangles, will crash with a - * failed assertion. This is done so we catch all programming - * errors, given that the function is called only from our code. - * - * We have the following 'special' meanings for a few fields: - * * If LVIS_FOCUSED is set, we assume the item has the focus - * This is important in ICON mode, where it might get a larger - * then usual rectange - * - * Please note that subitem support works only in REPORT mode. - * - * PARAMETER(S): - * [I] infoPtr : valid pointer to the listview structure - * [I] lpLVItem : item to compute the measures for - * [O] lprcBox : ptr to Box rectangle - * The internal LVIR_BOX rectangle - * [0] lprcState : ptr to State icon rectangle - * The internal LVIR_STATE rectangle - * [O] lprcIcon : ptr to Icon rectangle - * Same as LVM_GETITEMRECT with LVIR_ICON - * [O] lprcLabel : ptr to Label rectangle - * Same as LVM_GETITEMRECT with LVIR_LABEL - * - * RETURN: - * None. - */ -static void LISTVIEW_GetItemMetrics(LISTVIEW_INFO *infoPtr, const LVITEMW *lpLVItem, - LPRECT lprcBox, LPRECT lprcState, - LPRECT lprcIcon, LPRECT lprcLabel) -{ - UINT uView = infoPtr->dwStyle & LVS_TYPEMASK; - BOOL doState = FALSE, doIcon = FALSE, doLabel = FALSE, oversizedBox = FALSE; - RECT Box, State, Icon, Label; - COLUMN_INFO *lpColumnInfo = NULL; - - TRACE("(lpLVItem=%s)\n", debuglvitem_t(lpLVItem, TRUE)); - - /* Be smart and try to figure out the minimum we have to do */ - if (lpLVItem->iSubItem) assert(uView == LVS_REPORT); - if (uView == LVS_ICON && (lprcBox || lprcLabel)) - { - assert((lpLVItem->mask & LVIF_STATE) && (lpLVItem->stateMask & LVIS_FOCUSED)); - if (lpLVItem->state & LVIS_FOCUSED) oversizedBox = doLabel = TRUE; - } - if (lprcLabel) doLabel = TRUE; - if (doLabel || lprcIcon) doIcon = TRUE; - if (doIcon || lprcState) doState = TRUE; - - /************************************************************/ - /* compute the box rectangle (it should be cheap to do) */ - /************************************************************/ - if (lpLVItem->iSubItem || uView == LVS_REPORT) - lpColumnInfo = LISTVIEW_GetColumnInfo(infoPtr, lpLVItem->iSubItem); - - if (lpLVItem->iSubItem) - { - Box = lpColumnInfo->rcHeader; - } - else - { - Box.left = 0; - Box.right = infoPtr->nItemWidth; - } - Box.top = 0; - Box.bottom = infoPtr->nItemHeight; - - /************************************************************/ - /* compute STATEICON bounding box */ - /************************************************************/ - if (doState) - { - if (uView == LVS_ICON) - { - State.left = Box.left - infoPtr->iconStateSize.cx - 2; - if (infoPtr->himlNormal) - State.left += (infoPtr->nItemWidth - infoPtr->iconSize.cx) / 2; - State.top = Box.top + infoPtr->iconSize.cy - infoPtr->iconStateSize.cy + 4; - } - else - { - /* we need the ident in report mode, if we don't have it, we fail */ - State.left = Box.left; - if (uView == LVS_REPORT) - { - if (lpLVItem->iSubItem == 0) - { - State.left += REPORT_MARGINX; - assert(lpLVItem->mask & LVIF_INDENT); - State.left += infoPtr->iconSize.cx * lpLVItem->iIndent; - } - } - State.top = Box.top; - } - State.right = State.left; - State.bottom = State.top; - if (infoPtr->himlState && lpLVItem->iSubItem == 0) - { - State.right += infoPtr->iconStateSize.cx; - State.bottom += infoPtr->iconStateSize.cy; - } - if (lprcState) *lprcState = State; - TRACE(" - state=%s\n", debugrect(&State)); - } - - /************************************************************/ - /* compute ICON bounding box (ala LVM_GETITEMRECT) */ - /************************************************************/ - if (doIcon) - { - if (uView == LVS_ICON) - { - Icon.left = Box.left; - if (infoPtr->himlNormal) - Icon.left += (infoPtr->nItemWidth - infoPtr->iconSize.cx) / 2; - Icon.top = Box.top + ICON_TOP_PADDING; - Icon.right = Icon.left; - Icon.bottom = Icon.top; - if (infoPtr->himlNormal) - { - Icon.right += infoPtr->iconSize.cx; - Icon.bottom += infoPtr->iconSize.cy; - } - } - else /* LVS_SMALLICON, LVS_LIST or LVS_REPORT */ - { - Icon.left = State.right; - Icon.top = Box.top; - Icon.right = Icon.left; - if (infoPtr->himlSmall && - (!lpColumnInfo || lpLVItem->iSubItem == 0 || (lpColumnInfo->fmt & LVCFMT_IMAGE) || - ((infoPtr->dwLvExStyle & LVS_EX_SUBITEMIMAGES) && lpLVItem->iImage != I_IMAGECALLBACK))) - Icon.right += infoPtr->iconSize.cx; - Icon.bottom = Icon.top + infoPtr->nItemHeight; - } - if(lprcIcon) *lprcIcon = Icon; - TRACE(" - icon=%s\n", debugrect(&Icon)); - } - - /************************************************************/ - /* compute LABEL bounding box (ala LVM_GETITEMRECT) */ - /************************************************************/ - if (doLabel) - { - SIZE labelSize = { 0, 0 }; - - /* calculate how far to the right can the label strech */ - Label.right = Box.right; - if (uView == LVS_REPORT) - { - if (lpLVItem->iSubItem == 0) Label = lpColumnInfo->rcHeader; - } - - if (lpLVItem->iSubItem || ((infoPtr->dwStyle & LVS_OWNERDRAWFIXED) && uView == LVS_REPORT)) - { - labelSize.cx = infoPtr->nItemWidth; - labelSize.cy = infoPtr->nItemHeight; - goto calc_label; - } - - /* we need the text in non owner draw mode */ - assert(lpLVItem->mask & LVIF_TEXT); - if (is_textT(lpLVItem->pszText, TRUE)) - { - HFONT hFont = infoPtr->hFont ? infoPtr->hFont : infoPtr->hDefaultFont; - HDC hdc = GetDC(infoPtr->hwndSelf); - HFONT hOldFont = SelectObject(hdc, hFont); - UINT uFormat; - RECT rcText; - - /* compute rough rectangle where the label will go */ - SetRectEmpty(&rcText); - rcText.right = infoPtr->nItemWidth - TRAILING_LABEL_PADDING; - rcText.bottom = infoPtr->nItemHeight; - if (uView == LVS_ICON) - rcText.bottom -= ICON_TOP_PADDING + infoPtr->iconSize.cy + ICON_BOTTOM_PADDING; - - /* now figure out the flags */ - if (uView == LVS_ICON) - uFormat = oversizedBox ? LV_FL_DT_FLAGS : LV_ML_DT_FLAGS; - else - uFormat = LV_SL_DT_FLAGS; - - DrawTextW (hdc, lpLVItem->pszText, -1, &rcText, uFormat | DT_CALCRECT); - - labelSize.cx = min(rcText.right - rcText.left + TRAILING_LABEL_PADDING, infoPtr->nItemWidth); - labelSize.cy = rcText.bottom - rcText.top; - - SelectObject(hdc, hOldFont); - ReleaseDC(infoPtr->hwndSelf, hdc); - } - -calc_label: - if (uView == LVS_ICON) - { - Label.left = Box.left + (infoPtr->nItemWidth - labelSize.cx) / 2; - Label.top = Box.top + ICON_TOP_PADDING_HITABLE + - infoPtr->iconSize.cy + ICON_BOTTOM_PADDING; - Label.right = Label.left + labelSize.cx; - Label.bottom = Label.top + infoPtr->nItemHeight; - if (!oversizedBox && labelSize.cy > infoPtr->ntmHeight && - infoPtr->ntmHeight) - { - labelSize.cy = min(Box.bottom - Label.top, labelSize.cy); - labelSize.cy /= infoPtr->ntmHeight; - labelSize.cy = max(labelSize.cy, 1); - labelSize.cy *= infoPtr->ntmHeight; - } - Label.bottom = Label.top + labelSize.cy + HEIGHT_PADDING; - } - else /* LVS_SMALLICON, LVS_LIST or LVS_REPORT */ - { - Label.left = Icon.right; - Label.top = Box.top; - Label.right = min(Label.left + labelSize.cx, Label.right); - Label.bottom = Label.top + infoPtr->nItemHeight; - } - - if (lprcLabel) *lprcLabel = Label; - TRACE(" - label=%s\n", debugrect(&Label)); - } - - /* Fix the Box if necessary */ - if (lprcBox) - { - if (oversizedBox) UnionRect(lprcBox, &Box, &Label); - else *lprcBox = Box; - } - TRACE(" - box=%s\n", debugrect(&Box)); -} - -/*** - * DESCRIPTION: [INTERNAL] - * - * PARAMETER(S): - * [I] infoPtr : valid pointer to the listview structure - * [I] nItem : item number - * [O] lprcBox : ptr to Box rectangle - * - * RETURN: - * None. - */ -static void LISTVIEW_GetItemBox(LISTVIEW_INFO *infoPtr, INT nItem, LPRECT lprcBox) -{ - UINT uView = infoPtr->dwStyle & LVS_TYPEMASK; - WCHAR szDispText[DISP_TEXT_SIZE] = { '\0' }; - POINT Position, Origin; - LVITEMW lvItem; - - LISTVIEW_GetOrigin(infoPtr, &Origin); - LISTVIEW_GetItemOrigin(infoPtr, nItem, &Position); - - /* Be smart and try to figure out the minimum we have to do */ - lvItem.mask = 0; - if (uView == LVS_ICON && infoPtr->bFocus && LISTVIEW_GetItemState(infoPtr, nItem, LVIS_FOCUSED)) - lvItem.mask |= LVIF_TEXT; - lvItem.iItem = nItem; - lvItem.iSubItem = 0; - lvItem.pszText = szDispText; - lvItem.cchTextMax = DISP_TEXT_SIZE; - if (lvItem.mask) LISTVIEW_GetItemW(infoPtr, &lvItem); - if (uView == LVS_ICON) - { - lvItem.mask |= LVIF_STATE; - lvItem.stateMask = LVIS_FOCUSED; - lvItem.state = (lvItem.mask & LVIF_TEXT ? LVIS_FOCUSED : 0); - } - LISTVIEW_GetItemMetrics(infoPtr, &lvItem, lprcBox, 0, 0, 0); - - OffsetRect(lprcBox, Position.x + Origin.x, Position.y + Origin.y); -} - - -/*** - * DESCRIPTION: - * Returns the current icon position, and advances it along the top. - * The returned position is not offset by Origin. - * - * PARAMETER(S): - * [I] infoPtr : valid pointer to the listview structure - * [O] lpPos : will get the current icon position - * - * RETURN: - * None - */ -static void LISTVIEW_NextIconPosTop(LISTVIEW_INFO *infoPtr, LPPOINT lpPos) -{ - INT nListWidth = infoPtr->rcList.right - infoPtr->rcList.left; - - *lpPos = infoPtr->currIconPos; - - infoPtr->currIconPos.x += infoPtr->nItemWidth; - if (infoPtr->currIconPos.x + infoPtr->nItemWidth <= nListWidth) return; - - infoPtr->currIconPos.x = 0; - infoPtr->currIconPos.y += infoPtr->nItemHeight; -} - - -/*** - * DESCRIPTION: - * Returns the current icon position, and advances it down the left edge. - * The returned position is not offset by Origin. - * - * PARAMETER(S): - * [I] infoPtr : valid pointer to the listview structure - * [O] lpPos : will get the current icon position - * - * RETURN: - * None - */ -static void LISTVIEW_NextIconPosLeft(LISTVIEW_INFO *infoPtr, LPPOINT lpPos) -{ - INT nListHeight = infoPtr->rcList.bottom - infoPtr->rcList.top; - - *lpPos = infoPtr->currIconPos; - - infoPtr->currIconPos.y += infoPtr->nItemHeight; - if (infoPtr->currIconPos.y + infoPtr->nItemHeight <= nListHeight) return; - - infoPtr->currIconPos.x += infoPtr->nItemWidth; - infoPtr->currIconPos.y = 0; -} - - -/*** - * DESCRIPTION: - * Moves an icon to the specified position. - * It takes care of invalidating the item, etc. - * - * PARAMETER(S): - * [I] infoPtr : valid pointer to the listview structure - * [I] nItem : the item to move - * [I] lpPos : the new icon position - * [I] isNew : flags the item as being new - * - * RETURN: - * Success: TRUE - * Failure: FALSE - */ -static BOOL LISTVIEW_MoveIconTo(LISTVIEW_INFO *infoPtr, INT nItem, const POINT *lppt, BOOL isNew) -{ - POINT old; - - if (!isNew) - { - old.x = (LONG)DPA_GetPtr(infoPtr->hdpaPosX, nItem); - old.y = (LONG)DPA_GetPtr(infoPtr->hdpaPosY, nItem); - - if (lppt->x == old.x && lppt->y == old.y) return TRUE; - LISTVIEW_InvalidateItem(infoPtr, nItem); - } - - /* Allocating a POINTER for every item is too resource intensive, - * so we'll keep the (x,y) in different arrays */ - if (!DPA_SetPtr(infoPtr->hdpaPosX, nItem, (void *)lppt->x)) return FALSE; - if (!DPA_SetPtr(infoPtr->hdpaPosY, nItem, (void *)lppt->y)) return FALSE; - - LISTVIEW_InvalidateItem(infoPtr, nItem); - - return TRUE; -} - -/*** - * DESCRIPTION: - * Arranges listview items in icon display mode. - * - * PARAMETER(S): - * [I] infoPtr : valid pointer to the listview structure - * [I] nAlignCode : alignment code - * - * RETURN: - * SUCCESS : TRUE - * FAILURE : FALSE - */ -static BOOL LISTVIEW_Arrange(LISTVIEW_INFO *infoPtr, INT nAlignCode) -{ - UINT uView = infoPtr->dwStyle & LVS_TYPEMASK; - void (*next_pos)(LISTVIEW_INFO *, LPPOINT); - POINT pos; - INT i; - - if (uView != LVS_ICON && uView != LVS_SMALLICON) return FALSE; - - TRACE("nAlignCode=%d\n", nAlignCode); - - if (nAlignCode == LVA_DEFAULT) - { - if (infoPtr->dwStyle & LVS_ALIGNLEFT) nAlignCode = LVA_ALIGNLEFT; - else nAlignCode = LVA_ALIGNTOP; - } - - switch (nAlignCode) - { - case LVA_ALIGNLEFT: next_pos = LISTVIEW_NextIconPosLeft; break; - case LVA_ALIGNTOP: next_pos = LISTVIEW_NextIconPosTop; break; - case LVA_SNAPTOGRID: next_pos = LISTVIEW_NextIconPosTop; break; /* FIXME */ - default: return FALSE; - } - - infoPtr->bAutoarrange = TRUE; - infoPtr->currIconPos.x = infoPtr->currIconPos.y = 0; - for (i = 0; i < infoPtr->nItemCount; i++) - { - next_pos(infoPtr, &pos); - LISTVIEW_MoveIconTo(infoPtr, i, &pos, FALSE); - } - - return TRUE; -} - -/*** - * DESCRIPTION: - * Retrieves the bounding rectangle of all the items, not offset by Origin. - * - * PARAMETER(S): - * [I] infoPtr : valid pointer to the listview structure - * [O] lprcView : bounding rectangle - * - * RETURN: - * SUCCESS : TRUE - * FAILURE : FALSE - */ -static void LISTVIEW_GetAreaRect(LISTVIEW_INFO *infoPtr, LPRECT lprcView) -{ - INT i, x, y; - - SetRectEmpty(lprcView); - - switch (infoPtr->dwStyle & LVS_TYPEMASK) - { - case LVS_ICON: - case LVS_SMALLICON: - for (i = 0; i < infoPtr->nItemCount; i++) - { - x = (LONG)DPA_GetPtr(infoPtr->hdpaPosX, i); - y = (LONG)DPA_GetPtr(infoPtr->hdpaPosY, i); - lprcView->right = max(lprcView->right, x); - lprcView->bottom = max(lprcView->bottom, y); - } - if (infoPtr->nItemCount > 0) - { - lprcView->right += infoPtr->nItemWidth; - lprcView->bottom += infoPtr->nItemHeight; - } - break; - - case LVS_LIST: - y = LISTVIEW_GetCountPerColumn(infoPtr); - x = infoPtr->nItemCount / y; - if (infoPtr->nItemCount % y) x++; - lprcView->right = x * infoPtr->nItemWidth; - lprcView->bottom = y * infoPtr->nItemHeight; - break; - - case LVS_REPORT: - lprcView->right = infoPtr->nItemWidth; - lprcView->bottom = infoPtr->nItemCount * infoPtr->nItemHeight; - break; - } -} - -/*** - * DESCRIPTION: - * Retrieves the bounding rectangle of all the items. - * - * PARAMETER(S): - * [I] infoPtr : valid pointer to the listview structure - * [O] lprcView : bounding rectangle - * - * RETURN: - * SUCCESS : TRUE - * FAILURE : FALSE - */ -static BOOL LISTVIEW_GetViewRect(LISTVIEW_INFO *infoPtr, LPRECT lprcView) -{ - POINT ptOrigin; - - TRACE("(lprcView=%p)\n", lprcView); - - if (!lprcView) return FALSE; - - LISTVIEW_GetOrigin(infoPtr, &ptOrigin); - LISTVIEW_GetAreaRect(infoPtr, lprcView); - OffsetRect(lprcView, ptOrigin.x, ptOrigin.y); - - TRACE("lprcView=%s\n", debugrect(lprcView)); - - return TRUE; -} - -/*** - * DESCRIPTION: - * Retrieves the subitem pointer associated with the subitem index. - * - * PARAMETER(S): - * [I] hdpaSubItems : DPA handle for a specific item - * [I] nSubItem : index of subitem - * - * RETURN: - * SUCCESS : subitem pointer - * FAILURE : NULL - */ -static SUBITEM_INFO* LISTVIEW_GetSubItemPtr(HDPA hdpaSubItems, INT nSubItem) -{ - SUBITEM_INFO *lpSubItem; - INT i; - - /* we should binary search here if need be */ - for (i = 1; i < DPA_GetPtrCount(hdpaSubItems); i++) - { - lpSubItem = (SUBITEM_INFO *)DPA_GetPtr(hdpaSubItems, i); - if (lpSubItem->iSubItem == nSubItem) - return lpSubItem; - } - - return NULL; -} - - -/*** - * DESCRIPTION: - * Caclulates the desired item width. - * - * PARAMETER(S): - * [I] infoPtr : valid pointer to the listview structure - * - * RETURN: - * The desired item width. - */ -static INT LISTVIEW_CalculateItemWidth(LISTVIEW_INFO *infoPtr) -{ - UINT uView = infoPtr->dwStyle & LVS_TYPEMASK; - INT nItemWidth = 0; - - TRACE("uView=%d\n", uView); - - if (uView == LVS_ICON) - nItemWidth = infoPtr->iconSpacing.cx; - else if (uView == LVS_REPORT) - { - RECT rcHeader; - - if (DPA_GetPtrCount(infoPtr->hdpaColumns) > 0) - { - LISTVIEW_GetHeaderRect(infoPtr, DPA_GetPtrCount(infoPtr->hdpaColumns) - 1, &rcHeader); - nItemWidth = rcHeader.right; - } - } - else /* LVS_SMALLICON, or LVS_LIST */ - { - INT i; - - for (i = 0; i < infoPtr->nItemCount; i++) - nItemWidth = max(LISTVIEW_GetLabelWidth(infoPtr, i), nItemWidth); - - if (infoPtr->himlSmall) nItemWidth += infoPtr->iconSize.cx; - if (infoPtr->himlState) nItemWidth += infoPtr->iconStateSize.cx; - - nItemWidth = max(DEFAULT_COLUMN_WIDTH, nItemWidth + WIDTH_PADDING); - } - - return max(nItemWidth, 1); -} - -/*** - * DESCRIPTION: - * Caclulates the desired item height. - * - * PARAMETER(S): - * [I] infoPtr : valid pointer to the listview structure - * - * RETURN: - * The desired item height. - */ -static INT LISTVIEW_CalculateItemHeight(LISTVIEW_INFO *infoPtr) -{ - UINT uView = infoPtr->dwStyle & LVS_TYPEMASK; - INT nItemHeight; - - TRACE("uView=%d\n", uView); - - if (uView == LVS_ICON) - nItemHeight = infoPtr->iconSpacing.cy; - else - { - nItemHeight = infoPtr->ntmHeight; - if (infoPtr->himlState) - nItemHeight = max(nItemHeight, infoPtr->iconStateSize.cy); - if (infoPtr->himlSmall) - nItemHeight = max(nItemHeight, infoPtr->iconSize.cy); - if (infoPtr->himlState || infoPtr->himlSmall) - nItemHeight += HEIGHT_PADDING; - } - - return max(nItemHeight, 1); -} - -/*** - * DESCRIPTION: - * Updates the width, and height of an item. - * - * PARAMETER(S): - * [I] infoPtr : valid pointer to the listview structure - * - * RETURN: - * None. - */ -static inline void LISTVIEW_UpdateItemSize(LISTVIEW_INFO *infoPtr) -{ - infoPtr->nItemWidth = LISTVIEW_CalculateItemWidth(infoPtr); - infoPtr->nItemHeight = LISTVIEW_CalculateItemHeight(infoPtr); -} - - -/*** - * DESCRIPTION: - * Retrieves and saves important text metrics info for the current - * Listview font. - * - * PARAMETER(S): - * [I] infoPtr : valid pointer to the listview structure - * - */ -static void LISTVIEW_SaveTextMetrics(LISTVIEW_INFO *infoPtr) -{ - HDC hdc = GetDC(infoPtr->hwndSelf); - HFONT hFont = infoPtr->hFont ? infoPtr->hFont : infoPtr->hDefaultFont; - HFONT hOldFont = SelectObject(hdc, hFont); - TEXTMETRICW tm; - - if (GetTextMetricsW(hdc, &tm)) - { - infoPtr->ntmHeight = tm.tmHeight; - infoPtr->ntmAveCharWidth = tm.tmAveCharWidth; - } - SelectObject(hdc, hOldFont); - ReleaseDC(infoPtr->hwndSelf, hdc); - - TRACE("tmHeight=%d\n", infoPtr->ntmHeight); -} - -/*** - * DESCRIPTION: - * A compare function for ranges - * - * PARAMETER(S) - * [I] range1 : pointer to range 1; - * [I] range2 : pointer to range 2; - * [I] flags : flags - * - * RETURNS: - * > 0 : if range 1 > range 2 - * < 0 : if range 2 > range 1 - * = 0 : if range intersects range 2 - */ -static INT CALLBACK ranges_cmp(LPVOID range1, LPVOID range2, LPARAM flags) -{ - INT cmp; - - if (((RANGE*)range1)->upper <= ((RANGE*)range2)->lower) - cmp = -1; - else if (((RANGE*)range2)->upper <= ((RANGE*)range1)->lower) - cmp = 1; - else - cmp = 0; - - TRACE("range1=%s, range2=%s, cmp=%d\n", debugrange((RANGE*)range1), debugrange((RANGE*)range2), cmp); - - return cmp; -} - -#if DEBUG_RANGES -#define ranges_check(ranges, desc) ranges_assert(ranges, desc, __FUNCTION__, __LINE__) -#else -#define ranges_check(ranges, desc) do { } while(0) -#endif - -static void ranges_assert(RANGES ranges, LPCSTR desc, const char *func, int line) -{ - INT i; - RANGE *prev, *curr; - - TRACE("*** Checking %s:%d:%s ***\n", func, line, desc); - assert (ranges); - assert (DPA_GetPtrCount(ranges->hdpa) >= 0); - ranges_dump(ranges); - prev = (RANGE *)DPA_GetPtr(ranges->hdpa, 0); - if (DPA_GetPtrCount(ranges->hdpa) > 0) - assert (prev->lower >= 0 && prev->lower < prev->upper); - for (i = 1; i < DPA_GetPtrCount(ranges->hdpa); i++) - { - curr = (RANGE *)DPA_GetPtr(ranges->hdpa, i); - assert (prev->upper <= curr->lower); - assert (curr->lower < curr->upper); - prev = curr; - } - TRACE("--- Done checking---\n"); -} - -static RANGES ranges_create(int count) -{ - RANGES ranges = (RANGES)Alloc(sizeof(struct tagRANGES)); - if (!ranges) return NULL; - ranges->hdpa = DPA_Create(count); - if (ranges->hdpa) return ranges; - Free(ranges); - return NULL; -} - -static void ranges_clear(RANGES ranges) -{ - INT i; - - for(i = 0; i < DPA_GetPtrCount(ranges->hdpa); i++) - Free(DPA_GetPtr(ranges->hdpa, i)); - DPA_DeleteAllPtrs(ranges->hdpa); -} - - -static void ranges_destroy(RANGES ranges) -{ - if (!ranges) return; - ranges_clear(ranges); - DPA_Destroy(ranges->hdpa); - Free(ranges); -} - -static RANGES ranges_clone(RANGES ranges) -{ - RANGES clone; - INT i; - - if (!(clone = ranges_create(DPA_GetPtrCount(ranges->hdpa)))) goto fail; - - for (i = 0; i < DPA_GetPtrCount(ranges->hdpa); i++) - { - RANGE *newrng = (RANGE *)Alloc(sizeof(RANGE)); - if (!newrng) goto fail; - *newrng = *((RANGE*)DPA_GetPtr(ranges->hdpa, i)); - DPA_SetPtr(clone->hdpa, i, newrng); - } - return clone; - -fail: - TRACE ("clone failed\n"); - ranges_destroy(clone); - return NULL; -} - -static RANGES ranges_diff(RANGES ranges, RANGES sub) -{ - INT i; - - for (i = 0; i < DPA_GetPtrCount(sub->hdpa); i++) - ranges_del(ranges, *((RANGE *)DPA_GetPtr(sub->hdpa, i))); - - return ranges; -} - -static void ranges_dump(RANGES ranges) -{ - INT i; - - for (i = 0; i < DPA_GetPtrCount(ranges->hdpa); i++) - TRACE(" %s\n", debugrange(DPA_GetPtr(ranges->hdpa, i))); -} - -static inline BOOL ranges_contain(RANGES ranges, INT nItem) -{ - RANGE srchrng = { nItem, nItem + 1 }; - - TRACE("(nItem=%d)\n", nItem); - ranges_check(ranges, "before contain"); - return DPA_Search(ranges->hdpa, &srchrng, 0, ranges_cmp, 0, DPAS_SORTED) != -1; -} - -static INT ranges_itemcount(RANGES ranges) -{ - INT i, count = 0; - - for (i = 0; i < DPA_GetPtrCount(ranges->hdpa); i++) - { - RANGE *sel = DPA_GetPtr(ranges->hdpa, i); - count += sel->upper - sel->lower; - } - - return count; -} - -static BOOL ranges_shift(RANGES ranges, INT nItem, INT delta, INT nUpper) -{ - RANGE srchrng = { nItem, nItem + 1 }, *chkrng; - INT index; - - index = DPA_Search(ranges->hdpa, &srchrng, 0, ranges_cmp, 0, DPAS_SORTED | DPAS_INSERTAFTER); - if (index == -1) return TRUE; - - for (; index < DPA_GetPtrCount(ranges->hdpa); index++) - { - chkrng = DPA_GetPtr(ranges->hdpa, index); - if (chkrng->lower >= nItem) - chkrng->lower = max(min(chkrng->lower + delta, nUpper - 1), 0); - if (chkrng->upper > nItem) - chkrng->upper = max(min(chkrng->upper + delta, nUpper), 0); - } - return TRUE; -} - -static BOOL ranges_add(RANGES ranges, RANGE range) -{ - RANGE srchrgn; - INT index; - - TRACE("(%s)\n", debugrange(&range)); - ranges_check(ranges, "before add"); - - /* try find overlapping regions first */ - srchrgn.lower = range.lower - 1; - srchrgn.upper = range.upper + 1; - index = DPA_Search(ranges->hdpa, &srchrgn, 0, ranges_cmp, 0, DPAS_SORTED); - - if (index == -1) - { - RANGE *newrgn; - - TRACE("Adding new range\n"); - - /* create the brand new range to insert */ - newrgn = (RANGE *)Alloc(sizeof(RANGE)); - if(!newrgn) goto fail; - *newrgn = range; - - /* figure out where to insert it */ - index = DPA_Search(ranges->hdpa, newrgn, 0, ranges_cmp, 0, DPAS_SORTED | DPAS_INSERTAFTER); - TRACE("index=%d\n", index); - if (index == -1) index = 0; - - /* and get it over with */ - if (DPA_InsertPtr(ranges->hdpa, index, newrgn) == -1) - { - Free(newrgn); - goto fail; - } - } - else - { - RANGE *chkrgn, *mrgrgn; - INT fromindex, mergeindex; - - chkrgn = DPA_GetPtr(ranges->hdpa, index); - TRACE("Merge with %s @%d\n", debugrange(chkrgn), index); - - chkrgn->lower = min(range.lower, chkrgn->lower); - chkrgn->upper = max(range.upper, chkrgn->upper); - - TRACE("New range %s @%d\n", debugrange(chkrgn), index); - - /* merge now common anges */ - fromindex = 0; - srchrgn.lower = chkrgn->lower - 1; - srchrgn.upper = chkrgn->upper + 1; - - do - { - mergeindex = DPA_Search(ranges->hdpa, &srchrgn, fromindex, ranges_cmp, 0, 0); - if (mergeindex == -1) break; - if (mergeindex == index) - { - fromindex = index + 1; - continue; - } - - TRACE("Merge with index %i\n", mergeindex); - - mrgrgn = DPA_GetPtr(ranges->hdpa, mergeindex); - chkrgn->lower = min(chkrgn->lower, mrgrgn->lower); - chkrgn->upper = max(chkrgn->upper, mrgrgn->upper); - Free(mrgrgn); - DPA_DeletePtr(ranges->hdpa, mergeindex); - if (mergeindex < index) index --; - } while(1); - } - - ranges_check(ranges, "after add"); - return TRUE; - -fail: - ranges_check(ranges, "failed add"); - return FALSE; -} - -static BOOL ranges_del(RANGES ranges, RANGE range) -{ - RANGE *chkrgn; - INT index; - - TRACE("(%s)\n", debugrange(&range)); - ranges_check(ranges, "before del"); - - /* we don't use DPAS_SORTED here, since we need * - * to find the first overlapping range */ - index = DPA_Search(ranges->hdpa, &range, 0, ranges_cmp, 0, 0); - while(index != -1) - { - chkrgn = DPA_GetPtr(ranges->hdpa, index); - - TRACE("Matches range %s @%d\n", debugrange(chkrgn), index); - - /* case 1: Same range */ - if ( (chkrgn->upper == range.upper) && - (chkrgn->lower == range.lower) ) - { - DPA_DeletePtr(ranges->hdpa, index); - break; - } - /* case 2: engulf */ - else if ( (chkrgn->upper <= range.upper) && - (chkrgn->lower >= range.lower) ) - { - DPA_DeletePtr(ranges->hdpa, index); - } - /* case 3: overlap upper */ - else if ( (chkrgn->upper <= range.upper) && - (chkrgn->lower < range.lower) ) - { - chkrgn->upper = range.lower; - } - /* case 4: overlap lower */ - else if ( (chkrgn->upper > range.upper) && - (chkrgn->lower >= range.lower) ) - { - chkrgn->lower = range.upper; - break; - } - /* case 5: fully internal */ - else - { - RANGE tmprgn = *chkrgn, *newrgn; - - if (!(newrgn = (RANGE *)Alloc(sizeof(RANGE)))) goto fail; - newrgn->lower = chkrgn->lower; - newrgn->upper = range.lower; - chkrgn->lower = range.upper; - if (DPA_InsertPtr(ranges->hdpa, index, newrgn) == -1) - { - Free(newrgn); - goto fail; - } - chkrgn = &tmprgn; - break; - } - - index = DPA_Search(ranges->hdpa, &range, index, ranges_cmp, 0, 0); - } - - ranges_check(ranges, "after del"); - return TRUE; - -fail: - ranges_check(ranges, "failed del"); - return FALSE; -} - -/*** -* DESCRIPTION: -* Removes all selection ranges -* -* Parameters(s): -* [I] infoPtr : valid pointer to the listview structure -* [I] toSkip : item range to skip removing the selection -* -* RETURNS: -* SUCCESS : TRUE -* FAILURE : TRUE -*/ -static BOOL LISTVIEW_DeselectAllSkipItems(LISTVIEW_INFO *infoPtr, RANGES toSkip) -{ - LVITEMW lvItem; - ITERATOR i; - RANGES clone; - - TRACE("()\n"); - - lvItem.state = 0; - lvItem.stateMask = LVIS_SELECTED; - - /* need to clone the DPA because callbacks can change it */ - if (!(clone = ranges_clone(infoPtr->selectionRanges))) return FALSE; - iterator_rangesitems(&i, ranges_diff(clone, toSkip)); - while(iterator_next(&i)) - LISTVIEW_SetItemState(infoPtr, i.nItem, &lvItem); - /* note that the iterator destructor will free the cloned range */ - iterator_destroy(&i); - - return TRUE; -} - -static inline BOOL LISTVIEW_DeselectAllSkipItem(LISTVIEW_INFO *infoPtr, INT nItem) -{ - RANGES toSkip; - - if (!(toSkip = ranges_create(1))) return FALSE; - if (nItem != -1) ranges_additem(toSkip, nItem); - LISTVIEW_DeselectAllSkipItems(infoPtr, toSkip); - ranges_destroy(toSkip); - return TRUE; -} - -static inline BOOL LISTVIEW_DeselectAll(LISTVIEW_INFO *infoPtr) -{ - return LISTVIEW_DeselectAllSkipItem(infoPtr, -1); -} - -/*** - * DESCRIPTION: - * Retrieves the number of items that are marked as selected. - * - * PARAMETER(S): - * [I] infoPtr : valid pointer to the listview structure - * - * RETURN: - * Number of items selected. - */ -static INT LISTVIEW_GetSelectedCount(LISTVIEW_INFO *infoPtr) -{ - INT nSelectedCount = 0; - - if (infoPtr->uCallbackMask & LVIS_SELECTED) - { - INT i; - for (i = 0; i < infoPtr->nItemCount; i++) - { - if (LISTVIEW_GetItemState(infoPtr, i, LVIS_SELECTED)) - nSelectedCount++; - } - } - else - nSelectedCount = ranges_itemcount(infoPtr->selectionRanges); - - TRACE("nSelectedCount=%d\n", nSelectedCount); - return nSelectedCount; -} - -/*** - * DESCRIPTION: - * Manages the item focus. - * - * PARAMETER(S): - * [I] infoPtr : valid pointer to the listview structure - * [I] nItem : item index - * - * RETURN: - * TRUE : focused item changed - * FALSE : focused item has NOT changed - */ -static inline BOOL LISTVIEW_SetItemFocus(LISTVIEW_INFO *infoPtr, INT nItem) -{ - INT oldFocus = infoPtr->nFocusedItem; - LVITEMW lvItem; - - if (nItem == infoPtr->nFocusedItem) return FALSE; - - lvItem.state = nItem == -1 ? 0 : LVIS_FOCUSED; - lvItem.stateMask = LVIS_FOCUSED; - LISTVIEW_SetItemState(infoPtr, nItem == -1 ? infoPtr->nFocusedItem : nItem, &lvItem); - - return oldFocus != infoPtr->nFocusedItem; -} - -/* Helper function for LISTVIEW_ShiftIndices *only* */ -static INT shift_item(LISTVIEW_INFO *infoPtr, INT nShiftItem, INT nItem, INT direction) -{ - if (nShiftItem < nItem) return nShiftItem; - - if (nShiftItem > nItem) return nShiftItem + direction; - - if (direction > 0) return nShiftItem + direction; - - return min(nShiftItem, infoPtr->nItemCount - 1); -} - -/** -* DESCRIPTION: -* Updates the various indices after an item has been inserted or deleted. -* -* PARAMETER(S): -* [I] infoPtr : valid pointer to the listview structure -* [I] nItem : item index -* [I] direction : Direction of shift, +1 or -1. -* -* RETURN: -* None -*/ -static void LISTVIEW_ShiftIndices(LISTVIEW_INFO *infoPtr, INT nItem, INT direction) -{ - INT nNewFocus; - BOOL bOldChange; - - /* temporarily disable change notification while shifting items */ - bOldChange = infoPtr->bDoChangeNotify; - infoPtr->bDoChangeNotify = FALSE; - - TRACE("Shifting %iu, %i steps\n", nItem, direction); - - ranges_shift(infoPtr->selectionRanges, nItem, direction, infoPtr->nItemCount); - - assert(abs(direction) == 1); - - infoPtr->nSelectionMark = shift_item(infoPtr, infoPtr->nSelectionMark, nItem, direction); - - nNewFocus = shift_item(infoPtr, infoPtr->nFocusedItem, nItem, direction); - if (nNewFocus != infoPtr->nFocusedItem) - LISTVIEW_SetItemFocus(infoPtr, nNewFocus); - - /* But we are not supposed to modify nHotItem! */ - - infoPtr->bDoChangeNotify = bOldChange; -} - - -/** - * DESCRIPTION: - * Adds a block of selections. - * - * PARAMETER(S): - * [I] infoPtr : valid pointer to the listview structure - * [I] nItem : item index - * - * RETURN: - * None - */ -static void LISTVIEW_AddGroupSelection(LISTVIEW_INFO *infoPtr, INT nItem) -{ - INT nFirst = min(infoPtr->nSelectionMark, nItem); - INT nLast = max(infoPtr->nSelectionMark, nItem); - INT i; - LVITEMW item; - - if (nFirst == -1) nFirst = nItem; - - item.state = LVIS_SELECTED; - item.stateMask = LVIS_SELECTED; - - /* FIXME: this is not correct LVS_OWNERDATA - * setting the item states individually will generate - * a LVN_ITEMCHANGED notification for each one. Instead, - * we have to send a LVN_ODSTATECHANGED notification. - * See MSDN documentation for LVN_ITEMCHANGED. - */ - for (i = nFirst; i <= nLast; i++) - LISTVIEW_SetItemState(infoPtr,i,&item); -} - - -/*** - * DESCRIPTION: - * Sets a single group selection. - * - * PARAMETER(S): - * [I] infoPtr : valid pointer to the listview structure - * [I] nItem : item index - * - * RETURN: - * None - */ -static void LISTVIEW_SetGroupSelection(LISTVIEW_INFO *infoPtr, INT nItem) -{ - UINT uView = infoPtr->dwStyle & LVS_TYPEMASK; - RANGES selection; - LVITEMW item; - ITERATOR i; - - if (!(selection = ranges_create(100))) return; - - item.state = LVIS_SELECTED; - item.stateMask = LVIS_SELECTED; - - if ((uView == LVS_LIST) || (uView == LVS_REPORT)) - { - if (infoPtr->nSelectionMark == -1) - { - infoPtr->nSelectionMark = nItem; - ranges_additem(selection, nItem); - } - else - { - RANGE sel; - - sel.lower = min(infoPtr->nSelectionMark, nItem); - sel.upper = max(infoPtr->nSelectionMark, nItem) + 1; - ranges_add(selection, sel); - } - } - else - { - RECT rcItem, rcSel, rcSelMark; - POINT ptItem; - - rcItem.left = LVIR_BOUNDS; - if (!LISTVIEW_GetItemRect(infoPtr, nItem, &rcItem)) return; - rcSelMark.left = LVIR_BOUNDS; - if (!LISTVIEW_GetItemRect(infoPtr, infoPtr->nSelectionMark, &rcSelMark)) return; - UnionRect(&rcSel, &rcItem, &rcSelMark); - iterator_frameditems(&i, infoPtr, &rcSel); - while(iterator_next(&i)) - { - LISTVIEW_GetItemPosition(infoPtr, i.nItem, &ptItem); - if (PtInRect(&rcSel, ptItem)) ranges_additem(selection, i.nItem); - } - iterator_destroy(&i); - } - - LISTVIEW_DeselectAllSkipItems(infoPtr, selection); - iterator_rangesitems(&i, selection); - while(iterator_next(&i)) - LISTVIEW_SetItemState(infoPtr, i.nItem, &item); - /* this will also destroy the selection */ - iterator_destroy(&i); - - LISTVIEW_SetItemFocus(infoPtr, nItem); -} - -/*** - * DESCRIPTION: - * Sets a single selection. - * - * PARAMETER(S): - * [I] infoPtr : valid pointer to the listview structure - * [I] nItem : item index - * - * RETURN: - * None - */ -static void LISTVIEW_SetSelection(LISTVIEW_INFO *infoPtr, INT nItem) -{ - LVITEMW lvItem; - - TRACE("nItem=%d\n", nItem); - - LISTVIEW_DeselectAllSkipItem(infoPtr, nItem); - - lvItem.state = LVIS_FOCUSED | LVIS_SELECTED; - lvItem.stateMask = LVIS_FOCUSED | LVIS_SELECTED; - LISTVIEW_SetItemState(infoPtr, nItem, &lvItem); - - infoPtr->nSelectionMark = nItem; -} - -/*** - * DESCRIPTION: - * Set selection(s) with keyboard. - * - * PARAMETER(S): - * [I] infoPtr : valid pointer to the listview structure - * [I] nItem : item index - * - * RETURN: - * SUCCESS : TRUE (needs to be repainted) - * FAILURE : FALSE (nothing has changed) - */ -static BOOL LISTVIEW_KeySelection(LISTVIEW_INFO *infoPtr, INT nItem) -{ - /* FIXME: pass in the state */ - WORD wShift = HIWORD(GetKeyState(VK_SHIFT)); - WORD wCtrl = HIWORD(GetKeyState(VK_CONTROL)); - BOOL bResult = FALSE; - - if ((nItem >= 0) && (nItem < infoPtr->nItemCount)) - { - if (infoPtr->dwStyle & LVS_SINGLESEL) - { - bResult = TRUE; - LISTVIEW_SetSelection(infoPtr, nItem); - } - else - { - if (wShift) - { - bResult = TRUE; - LISTVIEW_SetGroupSelection(infoPtr, nItem); - } - else if (wCtrl) - { - bResult = LISTVIEW_SetItemFocus(infoPtr, nItem); - } - else - { - bResult = TRUE; - LISTVIEW_SetSelection(infoPtr, nItem); - } - } - LISTVIEW_EnsureVisible(infoPtr, nItem, FALSE); - } - - UpdateWindow(infoPtr->hwndSelf); /* update client area */ - return bResult; -} - - -/*** - * DESCRIPTION: - * Called when the mouse is being actively tracked and has hovered for a specified - * amount of time - * - * PARAMETER(S): - * [I] infoPtr : valid pointer to the listview structure - * [I] fwKeys : key indicator - * [I] x,y : mouse position - * - * RETURN: - * 0 if the message was processed, non-zero if there was an error - * - * INFO: - * LVS_EX_TRACKSELECT: An item is automatically selected when the cursor remains - * over the item for a certain period of time. - * - */ -static LRESULT LISTVIEW_MouseHover(LISTVIEW_INFO *infoPtr, WORD fwKyes, INT x, INT y) -{ - if(infoPtr->dwLvExStyle & LVS_EX_TRACKSELECT) - /* FIXME: select the item!!! */ - /*LISTVIEW_GetItemAtPt(infoPtr, pt)*/; - - return 0; -} - -/*** - * DESCRIPTION: - * Called whenever WM_MOUSEMOVE is received. - * - * PARAMETER(S): - * [I] infoPtr : valid pointer to the listview structure - * [I] fwKeys : key indicator - * [I] x,y : mouse position - * - * RETURN: - * 0 if the message is processed, non-zero if there was an error - */ -static LRESULT LISTVIEW_MouseMove(LISTVIEW_INFO *infoPtr, WORD fwKeys, INT x, INT y) -{ - TRACKMOUSEEVENT trackinfo; - - /* see if we are supposed to be tracking mouse hovering */ - if(infoPtr->dwLvExStyle & LVS_EX_TRACKSELECT) { - /* fill in the trackinfo struct */ - trackinfo.cbSize = sizeof(TRACKMOUSEEVENT); - trackinfo.dwFlags = TME_QUERY; - trackinfo.hwndTrack = infoPtr->hwndSelf; - trackinfo.dwHoverTime = infoPtr->dwHoverTime; - - /* see if we are already tracking this hwnd */ - _TrackMouseEvent(&trackinfo); - - if(!(trackinfo.dwFlags & TME_HOVER)) { - trackinfo.dwFlags = TME_HOVER; - - /* call TRACKMOUSEEVENT so we receive WM_MOUSEHOVER messages */ - _TrackMouseEvent(&trackinfo); - } - } - - return 0; -} - - -/*** - * Tests wheather the item is assignable to a list with style lStyle - */ -static inline BOOL is_assignable_item(const LVITEMW *lpLVItem, LONG lStyle) -{ - if ( (lpLVItem->mask & LVIF_TEXT) && - (lpLVItem->pszText == LPSTR_TEXTCALLBACKW) && - (lStyle & (LVS_SORTASCENDING | LVS_SORTDESCENDING)) ) return FALSE; - - return TRUE; -} - - -/*** - * DESCRIPTION: - * Helper for LISTVIEW_SetItemT *only*: sets item attributes. - * - * PARAMETER(S): - * [I] infoPtr : valid pointer to the listview structure - * [I] lpLVItem : valid pointer to new item atttributes - * [I] isNew : the item being set is being inserted - * [I] isW : TRUE if lpLVItem is Unicode, FALSE if it's ANSI - * [O] bChanged : will be set to TRUE if the item really changed - * - * RETURN: - * SUCCESS : TRUE - * FAILURE : FALSE - */ -static BOOL set_main_item(LISTVIEW_INFO *infoPtr, const LVITEMW *lpLVItem, BOOL isNew, BOOL isW, BOOL *bChanged) -{ - UINT uView = infoPtr->dwStyle & LVS_TYPEMASK; - ITEM_INFO *lpItem; - NMLISTVIEW nmlv; - UINT uChanged = 0; - LVITEMW item; - - TRACE("()\n"); - - assert(lpLVItem->iItem >= 0 && lpLVItem->iItem < infoPtr->nItemCount); - - if (lpLVItem->mask == 0) return TRUE; - - if (infoPtr->dwStyle & LVS_OWNERDATA) - { - /* a virtual listview we stores only selection and focus */ - if (lpLVItem->mask & ~LVIF_STATE) - return FALSE; - lpItem = NULL; - } - else - { - HDPA hdpaSubItems = (HDPA)DPA_GetPtr(infoPtr->hdpaItems, lpLVItem->iItem); - lpItem = (ITEM_INFO *)DPA_GetPtr(hdpaSubItems, 0); - assert (lpItem); - } - - /* we need to get the lParam and state of the item */ - item.iItem = lpLVItem->iItem; - item.iSubItem = lpLVItem->iSubItem; - item.mask = LVIF_STATE | LVIF_PARAM; - item.stateMask = ~0; - item.state = 0; - item.lParam = 0; - if (!isNew && !LISTVIEW_GetItemW(infoPtr, &item)) return FALSE; - - TRACE("oldState=%x, newState=%x\n", item.state, lpLVItem->state); - /* determine what fields will change */ - if ((lpLVItem->mask & LVIF_STATE) && ((item.state ^ lpLVItem->state) & lpLVItem->stateMask & ~infoPtr->uCallbackMask)) - uChanged |= LVIF_STATE; - - if ((lpLVItem->mask & LVIF_IMAGE) && (lpItem->hdr.iImage != lpLVItem->iImage)) - uChanged |= LVIF_IMAGE; - - if ((lpLVItem->mask & LVIF_PARAM) && (lpItem->lParam != lpLVItem->lParam)) - uChanged |= LVIF_PARAM; - - if ((lpLVItem->mask & LVIF_INDENT) && (lpItem->iIndent != lpLVItem->iIndent)) - uChanged |= LVIF_INDENT; - - if ((lpLVItem->mask & LVIF_TEXT) && textcmpWT(lpItem->hdr.pszText, lpLVItem->pszText, isW)) - uChanged |= LVIF_TEXT; - - TRACE("uChanged=0x%x\n", uChanged); - if (!uChanged) return TRUE; - *bChanged = TRUE; - - ZeroMemory(&nmlv, sizeof(NMLISTVIEW)); - nmlv.iItem = lpLVItem->iItem; - nmlv.uNewState = (item.state & ~lpLVItem->stateMask) | (lpLVItem->state & lpLVItem->stateMask); - nmlv.uOldState = item.state; - nmlv.uChanged = uChanged; - nmlv.lParam = item.lParam; - - /* send LVN_ITEMCHANGING notification, if the item is not being inserted */ - /* and we are _NOT_ virtual (LVS_OWERNDATA), and change notifications */ - /* are enabled */ - if(lpItem && !isNew && infoPtr->bDoChangeNotify && - notify_listview(infoPtr, LVN_ITEMCHANGING, &nmlv)) - return FALSE; - - /* copy information */ - if (lpLVItem->mask & LVIF_TEXT) - textsetptrT(&lpItem->hdr.pszText, lpLVItem->pszText, isW); - - if (lpLVItem->mask & LVIF_IMAGE) - lpItem->hdr.iImage = lpLVItem->iImage; - - if (lpLVItem->mask & LVIF_PARAM) - lpItem->lParam = lpLVItem->lParam; - - if (lpLVItem->mask & LVIF_INDENT) - lpItem->iIndent = lpLVItem->iIndent; - - if (uChanged & LVIF_STATE) - { - if (lpItem && (lpLVItem->stateMask & ~infoPtr->uCallbackMask & ~(LVIS_FOCUSED | LVIS_SELECTED))) - { - lpItem->state &= ~lpLVItem->stateMask; - lpItem->state |= (lpLVItem->state & lpLVItem->stateMask); - } - if (lpLVItem->state & lpLVItem->stateMask & ~infoPtr->uCallbackMask & LVIS_SELECTED) - { - if (infoPtr->dwStyle & LVS_SINGLESEL) LISTVIEW_DeselectAllSkipItem(infoPtr, lpLVItem->iItem); - ranges_additem(infoPtr->selectionRanges, lpLVItem->iItem); - } - else if (lpLVItem->stateMask & LVIS_SELECTED) - ranges_delitem(infoPtr->selectionRanges, lpLVItem->iItem); - - /* if we are asked to change focus, and we manage it, do it */ - if (lpLVItem->stateMask & ~infoPtr->uCallbackMask & LVIS_FOCUSED) - { - if (lpLVItem->state & LVIS_FOCUSED) - { - LISTVIEW_SetItemFocus(infoPtr, -1); - infoPtr->nFocusedItem = lpLVItem->iItem; - LISTVIEW_EnsureVisible(infoPtr, lpLVItem->iItem, uView == LVS_LIST); - } - else if (infoPtr->nFocusedItem == lpLVItem->iItem) - infoPtr->nFocusedItem = -1; - } - } - - /* if we're inserting the item, we're done */ - if (isNew) return TRUE; - - /* send LVN_ITEMCHANGED notification */ - if (lpLVItem->mask & LVIF_PARAM) nmlv.lParam = lpLVItem->lParam; - if (infoPtr->bDoChangeNotify) notify_listview(infoPtr, LVN_ITEMCHANGED, &nmlv); - - return TRUE; -} - -/*** - * DESCRIPTION: - * Helper for LISTVIEW_{Set,Insert}ItemT *only*: sets subitem attributes. - * - * PARAMETER(S): - * [I] infoPtr : valid pointer to the listview structure - * [I] lpLVItem : valid pointer to new subitem atttributes - * [I] isW : TRUE if lpLVItem is Unicode, FALSE if it's ANSI - * [O] bChanged : will be set to TRUE if the item really changed - * - * RETURN: - * SUCCESS : TRUE - * FAILURE : FALSE - */ -static BOOL set_sub_item(LISTVIEW_INFO *infoPtr, const LVITEMW *lpLVItem, BOOL isW, BOOL *bChanged) -{ - HDPA hdpaSubItems; - SUBITEM_INFO *lpSubItem; - - /* we do not support subitems for virtual listviews */ - if (infoPtr->dwStyle & LVS_OWNERDATA) return FALSE; - - /* set subitem only if column is present */ - if (lpLVItem->iSubItem >= DPA_GetPtrCount(infoPtr->hdpaColumns)) return FALSE; - - /* First do some sanity checks */ - if (lpLVItem->mask & ~(LVIF_TEXT | LVIF_IMAGE)) return FALSE; - if (!(lpLVItem->mask & (LVIF_TEXT | LVIF_IMAGE))) return TRUE; - - /* get the subitem structure, and create it if not there */ - hdpaSubItems = (HDPA)DPA_GetPtr(infoPtr->hdpaItems, lpLVItem->iItem); - assert (hdpaSubItems); - - lpSubItem = LISTVIEW_GetSubItemPtr(hdpaSubItems, lpLVItem->iSubItem); - if (!lpSubItem) - { - SUBITEM_INFO *tmpSubItem; - INT i; - - lpSubItem = (SUBITEM_INFO *)Alloc(sizeof(SUBITEM_INFO)); - if (!lpSubItem) return FALSE; - /* we could binary search here, if need be...*/ - for (i = 1; i < DPA_GetPtrCount(hdpaSubItems); i++) - { - tmpSubItem = (SUBITEM_INFO *)DPA_GetPtr(hdpaSubItems, i); - if (tmpSubItem->iSubItem > lpLVItem->iSubItem) break; - } - if (DPA_InsertPtr(hdpaSubItems, i, lpSubItem) == -1) - { - Free(lpSubItem); - return FALSE; - } - lpSubItem->iSubItem = lpLVItem->iSubItem; - lpSubItem->hdr.iImage = I_IMAGECALLBACK; - *bChanged = TRUE; - } - - if (lpLVItem->mask & LVIF_IMAGE) - if (lpSubItem->hdr.iImage != lpLVItem->iImage) - { - lpSubItem->hdr.iImage = lpLVItem->iImage; - *bChanged = TRUE; - } - - if (lpLVItem->mask & LVIF_TEXT) - if (lpSubItem->hdr.pszText != lpLVItem->pszText) - { - textsetptrT(&lpSubItem->hdr.pszText, lpLVItem->pszText, isW); - *bChanged = TRUE; - } - - return TRUE; -} - -/*** - * DESCRIPTION: - * Sets item attributes. - * - * PARAMETER(S): - * [I] infoPtr : valid pointer to the listview structure - * [I] lpLVItem : new item atttributes - * [I] isW : TRUE if lpLVItem is Unicode, FALSE if it's ANSI - * - * RETURN: - * SUCCESS : TRUE - * FAILURE : FALSE - */ -static BOOL LISTVIEW_SetItemT(LISTVIEW_INFO *infoPtr, const LVITEMW *lpLVItem, BOOL isW) -{ - UINT uView = infoPtr->dwStyle & LVS_TYPEMASK; - LPWSTR pszText = NULL; - BOOL bResult, bChanged = FALSE; - - TRACE("(lpLVItem=%s, isW=%d)\n", debuglvitem_t(lpLVItem, isW), isW); - - if (!lpLVItem || lpLVItem->iItem < 0 || lpLVItem->iItem >= infoPtr->nItemCount) - return FALSE; - - /* For efficiency, we transform the lpLVItem->pszText to Unicode here */ - if ((lpLVItem->mask & LVIF_TEXT) && is_textW(lpLVItem->pszText)) - { - pszText = lpLVItem->pszText; - ((LVITEMW *)lpLVItem)->pszText = textdupTtoW(lpLVItem->pszText, isW); - } - - /* actually set the fields */ - if (!is_assignable_item(lpLVItem, infoPtr->dwStyle)) return FALSE; - - if (lpLVItem->iSubItem) - bResult = set_sub_item(infoPtr, lpLVItem, TRUE, &bChanged); - else - bResult = set_main_item(infoPtr, lpLVItem, FALSE, TRUE, &bChanged); - - /* redraw item, if necessary */ - if (bChanged && !infoPtr->bIsDrawing) - { - /* this little optimization eliminates some nasty flicker */ - if ( uView == LVS_REPORT && !(infoPtr->dwStyle & LVS_OWNERDRAWFIXED) && - (!(infoPtr->dwLvExStyle & LVS_EX_FULLROWSELECT) || lpLVItem->iSubItem) ) - LISTVIEW_InvalidateSubItem(infoPtr, lpLVItem->iItem, lpLVItem->iSubItem); - else - LISTVIEW_InvalidateItem(infoPtr, lpLVItem->iItem); - } - /* restore text */ - if (pszText) - { - textfreeT(lpLVItem->pszText, isW); - ((LVITEMW *)lpLVItem)->pszText = pszText; - } - - return bResult; -} - -/*** - * DESCRIPTION: - * Retrieves the index of the item at coordinate (0, 0) of the client area. - * - * PARAMETER(S): - * [I] infoPtr : valid pointer to the listview structure - * - * RETURN: - * item index - */ -static INT LISTVIEW_GetTopIndex(LISTVIEW_INFO *infoPtr) -{ - UINT uView = infoPtr->dwStyle & LVS_TYPEMASK; - INT nItem = 0; - SCROLLINFO scrollInfo; - - scrollInfo.cbSize = sizeof(SCROLLINFO); - scrollInfo.fMask = SIF_POS; - - if (uView == LVS_LIST) - { - if (GetScrollInfo(infoPtr->hwndSelf, SB_HORZ, &scrollInfo)) - nItem = scrollInfo.nPos * LISTVIEW_GetCountPerColumn(infoPtr); - } - else if (uView == LVS_REPORT) - { - if (GetScrollInfo(infoPtr->hwndSelf, SB_VERT, &scrollInfo)) - nItem = scrollInfo.nPos; - } - else - { - if (GetScrollInfo(infoPtr->hwndSelf, SB_VERT, &scrollInfo)) - nItem = LISTVIEW_GetCountPerRow(infoPtr) * (scrollInfo.nPos / infoPtr->nItemHeight); - } - - TRACE("nItem=%d\n", nItem); - - return nItem; -} - - -/*** - * DESCRIPTION: - * Erases the background of the given rectangle - * - * PARAMETER(S): - * [I] infoPtr : valid pointer to the listview structure - * [I] hdc : device context handle - * [I] lprcBox : clipping rectangle - * - * RETURN: - * Success: TRUE - * Failure: FALSE - */ -static inline BOOL LISTVIEW_FillBkgnd(LISTVIEW_INFO *infoPtr, HDC hdc, const RECT *lprcBox) -{ - if (!infoPtr->hBkBrush) return FALSE; - - TRACE("(hdc=%p, lprcBox=%s, hBkBrush=%p)\n", hdc, debugrect(lprcBox), infoPtr->hBkBrush); - - return FillRect(hdc, lprcBox, infoPtr->hBkBrush); -} - -/*** - * DESCRIPTION: - * Draws an item. - * - * PARAMETER(S): - * [I] infoPtr : valid pointer to the listview structure - * [I] hdc : device context handle - * [I] nItem : item index - * [I] nSubItem : subitem index - * [I] pos : item position in client coordinates - * [I] cdmode : custom draw mode - * - * RETURN: - * Success: TRUE - * Failure: FALSE - */ -static BOOL LISTVIEW_DrawItem(LISTVIEW_INFO *infoPtr, HDC hdc, INT nItem, INT nSubItem, POINT pos, DWORD cdmode) -{ - UINT uFormat, uView = infoPtr->dwStyle & LVS_TYPEMASK; - WCHAR szDispText[DISP_TEXT_SIZE] = { '\0' }; - static const WCHAR szCallback[] = { '(', 'c', 'a', 'l', 'l', 'b', 'a', 'c', 'k', ')', 0 }; - DWORD cdsubitemmode = CDRF_DODEFAULT; - RECT* lprcFocus, rcSelect, rcBox, rcState, rcIcon, rcLabel; - NMLVCUSTOMDRAW nmlvcd; - HIMAGELIST himl; - LVITEMW lvItem; - - TRACE("(hdc=%p, nItem=%d, nSubItem=%d, pos=%s)\n", hdc, nItem, nSubItem, debugpoint(&pos)); - - /* get information needed for drawing the item */ - lvItem.mask = LVIF_TEXT | LVIF_IMAGE; - if (nSubItem == 0) lvItem.mask |= LVIF_STATE | LVIF_PARAM; - if (uView == LVS_REPORT) lvItem.mask |= LVIF_INDENT; - lvItem.stateMask = LVIS_SELECTED | LVIS_FOCUSED | LVIS_STATEIMAGEMASK; - lvItem.iItem = nItem; - lvItem.iSubItem = nSubItem; - lvItem.state = 0; - lvItem.lParam = 0; - lvItem.cchTextMax = DISP_TEXT_SIZE; - lvItem.pszText = szDispText; - if (!LISTVIEW_GetItemW(infoPtr, &lvItem)) return FALSE; - if (nSubItem > 0 && (infoPtr->dwLvExStyle & LVS_EX_FULLROWSELECT)) - lvItem.state = LISTVIEW_GetItemState(infoPtr, nItem, LVIS_SELECTED); - if (lvItem.pszText == LPSTR_TEXTCALLBACKW) lvItem.pszText = (LPWSTR)szCallback; - TRACE(" lvItem=%s\n", debuglvitem_t(&lvItem, TRUE)); - - /* now check if we need to update the focus rectangle */ - lprcFocus = infoPtr->bFocus && (lvItem.state & LVIS_FOCUSED) ? &infoPtr->rcFocus : 0; - - if (!lprcFocus) lvItem.state &= ~LVIS_FOCUSED; - LISTVIEW_GetItemMetrics(infoPtr, &lvItem, &rcBox, &rcState, &rcIcon, &rcLabel); - OffsetRect(&rcBox, pos.x, pos.y); - OffsetRect(&rcState, pos.x, pos.y); - OffsetRect(&rcIcon, pos.x, pos.y); - OffsetRect(&rcLabel, pos.x, pos.y); - TRACE(" rcBox=%s, rcState=%s, rcIcon=%s. rcLabel=%s\n", - debugrect(&rcBox), debugrect(&rcState), debugrect(&rcIcon), debugrect(&rcLabel)); - - /* fill in the custom draw structure */ - customdraw_fill(&nmlvcd, infoPtr, hdc, &rcBox, &lvItem); - - if (nSubItem > 0) cdmode = infoPtr->cditemmode; - if (cdmode & CDRF_NOTIFYITEMDRAW) - cdsubitemmode = notify_customdraw(infoPtr, CDDS_PREPAINT, &nmlvcd); - if (nSubItem == 0) infoPtr->cditemmode = cdsubitemmode; - if (cdsubitemmode & CDRF_SKIPDEFAULT) goto postpaint; - /* we have to send a CDDS_SUBITEM customdraw explicitly for subitem 0 */ - if (nSubItem == 0 && cdsubitemmode == CDRF_NOTIFYITEMDRAW) - { - cdsubitemmode = notify_customdraw(infoPtr, CDDS_SUBITEM | CDDS_ITEMPREPAINT, &nmlvcd); - if (cdsubitemmode & CDRF_SKIPDEFAULT) goto postpaint; - } - if (nSubItem == 0 || (cdmode & CDRF_NOTIFYITEMDRAW)) - prepaint_setup(infoPtr, hdc, &nmlvcd); - - /* in full row select, subitems, will just use main item's colors */ - if (nSubItem && uView == LVS_REPORT && (infoPtr->dwLvExStyle & LVS_EX_FULLROWSELECT)) - nmlvcd.clrTextBk = CLR_NONE; - - /* state icons */ - if (infoPtr->himlState && !IsRectEmpty(&rcState)) - { - UINT uStateImage = (lvItem.state & LVIS_STATEIMAGEMASK) >> 12; - if (uStateImage) - { - TRACE("uStateImage=%d\n", uStateImage); - ImageList_Draw(infoPtr->himlState, uStateImage - 1, hdc, rcState.left, rcState.top, ILD_NORMAL); - } - } - - /* small icons */ - himl = (uView == LVS_ICON ? infoPtr->himlNormal : infoPtr->himlSmall); - if (himl && lvItem.iImage >= 0 && !IsRectEmpty(&rcIcon)) - { - TRACE("iImage=%d\n", lvItem.iImage); - ImageList_Draw(himl, lvItem.iImage, hdc, rcIcon.left, rcIcon.top, - (lvItem.state & LVIS_SELECTED) && (infoPtr->bFocus) ? ILD_SELECTED : ILD_NORMAL); - } - - /* Don't bother painting item being edited */ - if (infoPtr->hwndEdit && nItem == infoPtr->nEditLabelItem && nSubItem == 0) goto postpaint; - - /* draw the selection background, if we're drawing the main item */ - if (nSubItem == 0) - { - rcSelect = rcLabel; - if (uView == LVS_REPORT && (infoPtr->dwLvExStyle & LVS_EX_FULLROWSELECT)) - rcSelect.right = rcBox.right; - - if (nmlvcd.clrTextBk != CLR_NONE) - ExtTextOutW(hdc, rcSelect.left, rcSelect.top, ETO_OPAQUE, &rcSelect, 0, 0, 0); - if(lprcFocus) *lprcFocus = rcSelect; - } - - /* figure out the text drawing flags */ - uFormat = (uView == LVS_ICON ? (lprcFocus ? LV_FL_DT_FLAGS : LV_ML_DT_FLAGS) : LV_SL_DT_FLAGS); - if (uView == LVS_ICON) - uFormat = (lprcFocus ? LV_FL_DT_FLAGS : LV_ML_DT_FLAGS); - else if (nSubItem) - { - switch (LISTVIEW_GetColumnInfo(infoPtr, nSubItem)->fmt & LVCFMT_JUSTIFYMASK) - { - case LVCFMT_RIGHT: uFormat |= DT_RIGHT; break; - case LVCFMT_CENTER: uFormat |= DT_CENTER; break; - default: uFormat |= DT_LEFT; - } - } - if (!(uFormat & (DT_RIGHT | DT_CENTER))) - { - if (himl && lvItem.iImage >= 0 && !IsRectEmpty(&rcIcon)) rcLabel.left += IMAGE_PADDING; - else rcLabel.left += LABEL_HOR_PADDING; - } - else if (uFormat & DT_RIGHT) rcLabel.right -= LABEL_HOR_PADDING; - DrawTextW(hdc, lvItem.pszText, -1, &rcLabel, uFormat); - -postpaint: - if (cdsubitemmode & CDRF_NOTIFYPOSTPAINT) - notify_postpaint(infoPtr, &nmlvcd); - return TRUE; -} - -/*** - * DESCRIPTION: - * Draws listview items when in owner draw mode. - * - * PARAMETER(S): - * [I] infoPtr : valid pointer to the listview structure - * [I] hdc : device context handle - * - * RETURN: - * None - */ -static void LISTVIEW_RefreshOwnerDraw(LISTVIEW_INFO *infoPtr, ITERATOR *i, HDC hdc, DWORD cdmode) -{ - UINT uID = (UINT)GetWindowLongPtrW(infoPtr->hwndSelf, GWLP_ID); - DWORD cditemmode = CDRF_DODEFAULT; - NMLVCUSTOMDRAW nmlvcd; - POINT Origin, Position; - DRAWITEMSTRUCT dis; - LVITEMW item; - - TRACE("()\n"); - - ZeroMemory(&dis, sizeof(dis)); - - /* Get scroll info once before loop */ - LISTVIEW_GetOrigin(infoPtr, &Origin); - - /* iterate through the invalidated rows */ - while(iterator_next(i)) - { - item.iItem = i->nItem; - item.iSubItem = 0; - item.mask = LVIF_PARAM | LVIF_STATE; - item.stateMask = LVIS_SELECTED | LVIS_FOCUSED; - if (!LISTVIEW_GetItemW(infoPtr, &item)) continue; - - dis.CtlType = ODT_LISTVIEW; - dis.CtlID = uID; - dis.itemID = item.iItem; - dis.itemAction = ODA_DRAWENTIRE; - dis.itemState = 0; - if (item.state & LVIS_SELECTED) dis.itemState |= ODS_SELECTED; - if (infoPtr->bFocus && (item.state & LVIS_FOCUSED)) dis.itemState |= ODS_FOCUS; - dis.hwndItem = infoPtr->hwndSelf; - dis.hDC = hdc; - LISTVIEW_GetItemOrigin(infoPtr, dis.itemID, &Position); - dis.rcItem.left = Position.x + Origin.x; - dis.rcItem.right = dis.rcItem.left + infoPtr->nItemWidth; - dis.rcItem.top = Position.y + Origin.y; - dis.rcItem.bottom = dis.rcItem.top + infoPtr->nItemHeight; - dis.itemData = item.lParam; - - TRACE("item=%s, rcItem=%s\n", debuglvitem_t(&item, TRUE), debugrect(&dis.rcItem)); - - /* - * Even if we do not send the CDRF_NOTIFYITEMDRAW we need to fill the nmlvcd - * structure for the rest. of the paint cycle - */ - customdraw_fill(&nmlvcd, infoPtr, hdc, &dis.rcItem, &item); - if (cdmode & CDRF_NOTIFYITEMDRAW) - cditemmode = notify_customdraw(infoPtr, CDDS_PREPAINT, &nmlvcd); - - if (!(cditemmode & CDRF_SKIPDEFAULT)) - { - prepaint_setup (infoPtr, hdc, &nmlvcd); - SendMessageW(infoPtr->hwndNotify, WM_DRAWITEM, dis.CtlID, (LPARAM)&dis); - } - - if (cditemmode & CDRF_NOTIFYPOSTPAINT) - notify_postpaint(infoPtr, &nmlvcd); - } -} - -/*** - * DESCRIPTION: - * Draws listview items when in report display mode. - * - * PARAMETER(S): - * [I] infoPtr : valid pointer to the listview structure - * [I] hdc : device context handle - * [I] cdmode : custom draw mode - * - * RETURN: - * None - */ -static void LISTVIEW_RefreshReport(LISTVIEW_INFO *infoPtr, ITERATOR *i, HDC hdc, DWORD cdmode) -{ - INT rgntype; - RECT rcClip, rcItem; - POINT Origin, Position; - RANGE colRange; - ITERATOR j; - - TRACE("()\n"); - - /* figure out what to draw */ - rgntype = GetClipBox(hdc, &rcClip); - if (rgntype == NULLREGION) return; - - /* Get scroll info once before loop */ - LISTVIEW_GetOrigin(infoPtr, &Origin); - - /* narrow down the columns we need to paint */ - for(colRange.lower = 0; colRange.lower < DPA_GetPtrCount(infoPtr->hdpaColumns); colRange.lower++) - { - LISTVIEW_GetHeaderRect(infoPtr, colRange.lower, &rcItem); - if (rcItem.right + Origin.x >= rcClip.left) break; - } - for(colRange.upper = DPA_GetPtrCount(infoPtr->hdpaColumns); colRange.upper > 0; colRange.upper--) - { - LISTVIEW_GetHeaderRect(infoPtr, colRange.upper - 1, &rcItem); - if (rcItem.left + Origin.x < rcClip.right) break; - } - iterator_rangeitems(&j, colRange); - - /* in full row select, we _have_ to draw the main item */ - if (infoPtr->dwLvExStyle & LVS_EX_FULLROWSELECT) - j.nSpecial = 0; - - /* iterate through the invalidated rows */ - while(iterator_next(i)) - { - /* iterate through the invalidated columns */ - while(iterator_next(&j)) - { - LISTVIEW_GetItemOrigin(infoPtr, i->nItem, &Position); - Position.x += Origin.x; - Position.y += Origin.y; - - if (rgntype == COMPLEXREGION && !((infoPtr->dwLvExStyle & LVS_EX_FULLROWSELECT) && j.nItem == 0)) - { - LISTVIEW_GetHeaderRect(infoPtr, j.nItem, &rcItem); - rcItem.top = 0; - rcItem.bottom = infoPtr->nItemHeight; - OffsetRect(&rcItem, Position.x, Position.y); - if (!RectVisible(hdc, &rcItem)) continue; - } - - LISTVIEW_DrawItem(infoPtr, hdc, i->nItem, j.nItem, Position, cdmode); - } - } - iterator_destroy(&j); -} - -/*** - * DESCRIPTION: - * Draws listview items when in list display mode. - * - * PARAMETER(S): - * [I] infoPtr : valid pointer to the listview structure - * [I] hdc : device context handle - * [I] cdmode : custom draw mode - * - * RETURN: - * None - */ -static void LISTVIEW_RefreshList(LISTVIEW_INFO *infoPtr, ITERATOR *i, HDC hdc, DWORD cdmode) -{ - POINT Origin, Position; - - /* Get scroll info once before loop */ - LISTVIEW_GetOrigin(infoPtr, &Origin); - - while(iterator_prev(i)) - { - LISTVIEW_GetItemOrigin(infoPtr, i->nItem, &Position); - Position.x += Origin.x; - Position.y += Origin.y; - - LISTVIEW_DrawItem(infoPtr, hdc, i->nItem, 0, Position, cdmode); - } -} - - -/*** - * DESCRIPTION: - * Draws listview items. - * - * PARAMETER(S): - * [I] infoPtr : valid pointer to the listview structure - * [I] hdc : device context handle - * - * RETURN: - * NoneX - */ -static void LISTVIEW_Refresh(LISTVIEW_INFO *infoPtr, HDC hdc) -{ - UINT uView = infoPtr->dwStyle & LVS_TYPEMASK; - COLORREF oldTextColor, oldClrTextBk, oldClrText; - NMLVCUSTOMDRAW nmlvcd; - HFONT hOldFont; - DWORD cdmode; - INT oldBkMode; - RECT rcClient; - ITERATOR i; - - LISTVIEW_DUMP(infoPtr); - - infoPtr->bIsDrawing = TRUE; - - /* save dc values we're gonna trash while drawing */ - hOldFont = SelectObject(hdc, infoPtr->hFont); - oldBkMode = GetBkMode(hdc); - infoPtr->clrTextBkDefault = GetBkColor(hdc); - oldTextColor = GetTextColor(hdc); - - oldClrTextBk = infoPtr->clrTextBk; - oldClrText = infoPtr->clrText; - - infoPtr->cditemmode = CDRF_DODEFAULT; - - GetClientRect(infoPtr->hwndSelf, &rcClient); - customdraw_fill(&nmlvcd, infoPtr, hdc, &rcClient, 0); - cdmode = notify_customdraw(infoPtr, CDDS_PREPAINT, &nmlvcd); - if (cdmode & CDRF_SKIPDEFAULT) goto enddraw; - prepaint_setup(infoPtr, hdc, &nmlvcd); - - /* Use these colors to draw the items */ - infoPtr->clrTextBk = nmlvcd.clrTextBk; - infoPtr->clrText = nmlvcd.clrText; - - /* nothing to draw */ - if(infoPtr->nItemCount == 0) goto enddraw; - - /* figure out what we need to draw */ - iterator_visibleitems(&i, infoPtr, hdc); - - /* send cache hint notification */ - if (infoPtr->dwStyle & LVS_OWNERDATA) - { - RANGE range = iterator_range(&i); - NMLVCACHEHINT nmlv; - - ZeroMemory(&nmlv, sizeof(NMLVCACHEHINT)); - nmlv.iFrom = range.lower; - nmlv.iTo = range.upper - 1; - notify_hdr(infoPtr, LVN_ODCACHEHINT, &nmlv.hdr); - } - - if ((infoPtr->dwStyle & LVS_OWNERDRAWFIXED) && (uView == LVS_REPORT)) - LISTVIEW_RefreshOwnerDraw(infoPtr, &i, hdc, cdmode); - else - { - if (uView == LVS_REPORT) - LISTVIEW_RefreshReport(infoPtr, &i, hdc, cdmode); - else /* LVS_LIST, LVS_ICON or LVS_SMALLICON */ - LISTVIEW_RefreshList(infoPtr, &i, hdc, cdmode); - - /* if we have a focus rect, draw it */ - if (infoPtr->bFocus) - DrawFocusRect(hdc, &infoPtr->rcFocus); - } - iterator_destroy(&i); - -enddraw: - if (cdmode & CDRF_NOTIFYPOSTPAINT) - notify_postpaint(infoPtr, &nmlvcd); - - infoPtr->clrTextBk = oldClrTextBk; - infoPtr->clrText = oldClrText; - - SelectObject(hdc, hOldFont); - SetBkMode(hdc, oldBkMode); - SetBkColor(hdc, infoPtr->clrTextBkDefault); - SetTextColor(hdc, oldTextColor); - infoPtr->bIsDrawing = FALSE; -} - - -/*** - * DESCRIPTION: - * Calculates the approximate width and height of a given number of items. - * - * PARAMETER(S): - * [I] infoPtr : valid pointer to the listview structure - * [I] nItemCount : number of items - * [I] wWidth : width - * [I] wHeight : height - * - * RETURN: - * Returns a DWORD. The width in the low word and the height in high word. - */ -static DWORD LISTVIEW_ApproximateViewRect(LISTVIEW_INFO *infoPtr, INT nItemCount, - WORD wWidth, WORD wHeight) -{ - UINT uView = infoPtr->dwStyle & LVS_TYPEMASK; - INT nItemCountPerColumn = 1; - INT nColumnCount = 0; - DWORD dwViewRect = 0; - - if (nItemCount == -1) - nItemCount = infoPtr->nItemCount; - - if (uView == LVS_LIST) - { - if (wHeight == 0xFFFF) - { - /* use current height */ - wHeight = infoPtr->rcList.bottom - infoPtr->rcList.top; - } - - if (wHeight < infoPtr->nItemHeight) - wHeight = infoPtr->nItemHeight; - - if (nItemCount > 0) - { - if (infoPtr->nItemHeight > 0) - { - nItemCountPerColumn = wHeight / infoPtr->nItemHeight; - if (nItemCountPerColumn == 0) - nItemCountPerColumn = 1; - - if (nItemCount % nItemCountPerColumn != 0) - nColumnCount = nItemCount / nItemCountPerColumn; - else - nColumnCount = nItemCount / nItemCountPerColumn + 1; - } - } - - /* Microsoft padding magic */ - wHeight = nItemCountPerColumn * infoPtr->nItemHeight + 2; - wWidth = nColumnCount * infoPtr->nItemWidth + 2; - - dwViewRect = MAKELONG(wWidth, wHeight); - } - else if (uView == LVS_REPORT) - { - RECT rcBox; - - if (infoPtr->nItemCount > 0) - { - LISTVIEW_GetItemBox(infoPtr, 0, &rcBox); - wWidth = rcBox.right - rcBox.left; - wHeight = (rcBox.bottom - rcBox.top) * nItemCount; - } - else - { - /* use current height and width */ - if (wHeight == 0xffff) - wHeight = infoPtr->rcList.bottom - infoPtr->rcList.top; - if (wWidth == 0xffff) - wWidth = infoPtr->rcList.right - infoPtr->rcList.left; - } - - dwViewRect = MAKELONG(wWidth, wHeight); - } - else if (uView == LVS_SMALLICON) - FIXME("uView == LVS_SMALLICON: not implemented\n"); - else if (uView == LVS_ICON) - FIXME("uView == LVS_ICON: not implemented\n"); - - return dwViewRect; -} - - -/*** - * DESCRIPTION: - * Create a drag image list for the specified item. - * - * PARAMETER(S): - * [I] infoPtr : valid pointer to the listview structure - * [I] iItem : index of item - * [O] lppt : Upperr-left corner of the image - * - * RETURN: - * Returns a handle to the image list if successful, NULL otherwise. - */ -static HIMAGELIST LISTVIEW_CreateDragImage(LISTVIEW_INFO *infoPtr, INT iItem, LPPOINT lppt) -{ - RECT rcItem; - SIZE size; - POINT pos; - HDC hdc, hdcOrig; - HBITMAP hbmp, hOldbmp; - HIMAGELIST dragList = 0; - TRACE("iItem=%d Count=%d \n", iItem, infoPtr->nItemCount); - - if (iItem < 0 || iItem >= infoPtr->nItemCount) - return 0; - - rcItem.left = LVIR_BOUNDS; - if (!LISTVIEW_GetItemRect(infoPtr, iItem, &rcItem)) - return 0; - - lppt->x = rcItem.left; - lppt->y = rcItem.top; - - size.cx = rcItem.right - rcItem.left; - size.cy = rcItem.bottom - rcItem.top; - - hdcOrig = GetDC(infoPtr->hwndSelf); - hdc = CreateCompatibleDC(hdcOrig); - hbmp = CreateCompatibleBitmap(hdcOrig, size.cx, size.cy); - hOldbmp = SelectObject(hdc, hbmp); - - rcItem.left = rcItem.top = 0; - rcItem.right = size.cx; - rcItem.bottom = size.cy; - FillRect(hdc, &rcItem, infoPtr->hBkBrush); - - pos.x = pos.y = 0; - if (LISTVIEW_DrawItem(infoPtr, hdc, iItem, 0, pos, infoPtr->cditemmode)) - { - dragList = ImageList_Create(size.cx, size.cy, ILC_COLOR, 10, 10); - SelectObject(hdc, hOldbmp); - ImageList_Add(dragList, hbmp, 0); - } - else - SelectObject(hdc, hOldbmp); - - DeleteObject(hbmp); - DeleteDC(hdc); - ReleaseDC(infoPtr->hwndSelf, hdcOrig); - - TRACE("ret=%p\n", dragList); - - return dragList; -} - - -/*** - * DESCRIPTION: - * Removes all listview items and subitems. - * - * PARAMETER(S): - * [I] infoPtr : valid pointer to the listview structure - * - * RETURN: - * SUCCESS : TRUE - * FAILURE : FALSE - */ -static BOOL LISTVIEW_DeleteAllItems(LISTVIEW_INFO *infoPtr) -{ - NMLISTVIEW nmlv; - HDPA hdpaSubItems = NULL; - BOOL bSuppress; - ITEMHDR *hdrItem; - INT i, j; - - TRACE("()\n"); - - /* we do it directly, to avoid notifications */ - ranges_clear(infoPtr->selectionRanges); - infoPtr->nSelectionMark = -1; - infoPtr->nFocusedItem = -1; - SetRectEmpty(&infoPtr->rcFocus); - /* But we are supposed to leave nHotItem as is! */ - - - /* send LVN_DELETEALLITEMS notification */ - ZeroMemory(&nmlv, sizeof(NMLISTVIEW)); - nmlv.iItem = -1; - bSuppress = notify_listview(infoPtr, LVN_DELETEALLITEMS, &nmlv); - - for (i = infoPtr->nItemCount - 1; i >= 0; i--) - { - /* send LVN_DELETEITEM notification, if not supressed */ - if (!bSuppress) notify_deleteitem(infoPtr, i); - if (!(infoPtr->dwStyle & LVS_OWNERDATA)) - { - hdpaSubItems = (HDPA)DPA_GetPtr(infoPtr->hdpaItems, i); - for (j = 0; j < DPA_GetPtrCount(hdpaSubItems); j++) - { - hdrItem = (ITEMHDR *)DPA_GetPtr(hdpaSubItems, j); - if (is_textW(hdrItem->pszText)) Free(hdrItem->pszText); - Free(hdrItem); - } - DPA_Destroy(hdpaSubItems); - DPA_DeletePtr(infoPtr->hdpaItems, i); - } - DPA_DeletePtr(infoPtr->hdpaPosX, i); - DPA_DeletePtr(infoPtr->hdpaPosY, i); - infoPtr->nItemCount --; - } - - LISTVIEW_UpdateScroll(infoPtr); - - LISTVIEW_InvalidateList(infoPtr); - - return TRUE; -} - -/*** - * DESCRIPTION: - * Scrolls, and updates the columns, when a column is changing width. - * - * PARAMETER(S): - * [I] infoPtr : valid pointer to the listview structure - * [I] nColumn : column to scroll - * [I] dx : amount of scroll, in pixels - * - * RETURN: - * None. - */ -static void LISTVIEW_ScrollColumns(LISTVIEW_INFO *infoPtr, INT nColumn, INT dx) -{ - COLUMN_INFO *lpColumnInfo; - RECT rcOld, rcCol; - INT nCol; - - if (nColumn < 0 || DPA_GetPtrCount(infoPtr->hdpaColumns) < 1) return; - lpColumnInfo = LISTVIEW_GetColumnInfo(infoPtr, min(nColumn, DPA_GetPtrCount(infoPtr->hdpaColumns) - 1)); - rcCol = lpColumnInfo->rcHeader; - if (nColumn >= DPA_GetPtrCount(infoPtr->hdpaColumns)) - rcCol.left = rcCol.right; - - /* ajust the other columns */ - for (nCol = nColumn; nCol < DPA_GetPtrCount(infoPtr->hdpaColumns); nCol++) - { - lpColumnInfo = LISTVIEW_GetColumnInfo(infoPtr, nCol); - lpColumnInfo->rcHeader.left += dx; - lpColumnInfo->rcHeader.right += dx; - } - - /* do not update screen if not in report mode */ - if (!is_redrawing(infoPtr) || (infoPtr->dwStyle & LVS_TYPEMASK) != LVS_REPORT) return; - - /* if we have a focus, must first erase the focus rect */ - if (infoPtr->bFocus) LISTVIEW_ShowFocusRect(infoPtr, FALSE); - - /* Need to reset the item width when inserting a new column */ - infoPtr->nItemWidth += dx; - - LISTVIEW_UpdateScroll(infoPtr); - - /* scroll to cover the deleted column, and invalidate for redraw */ - rcOld = infoPtr->rcList; - rcOld.left = rcCol.left; - ScrollWindowEx(infoPtr->hwndSelf, dx, 0, &rcOld, &rcOld, 0, 0, SW_ERASE | SW_INVALIDATE); - - /* we can restore focus now */ - if (infoPtr->bFocus) LISTVIEW_ShowFocusRect(infoPtr, TRUE); -} - -/*** - * DESCRIPTION: - * Removes a column from the listview control. - * - * PARAMETER(S): - * [I] infoPtr : valid pointer to the listview structure - * [I] nColumn : column index - * - * RETURN: - * SUCCESS : TRUE - * FAILURE : FALSE - */ -static BOOL LISTVIEW_DeleteColumn(LISTVIEW_INFO *infoPtr, INT nColumn) -{ - RECT rcCol; - - TRACE("nColumn=%d\n", nColumn); - - if (nColumn < 0 || DPA_GetPtrCount(infoPtr->hdpaColumns) == 0 - || nColumn >= DPA_GetPtrCount(infoPtr->hdpaColumns)) return FALSE; - - /* While the MSDN specifically says that column zero should not be deleted, - what actually happens is that the column itself is deleted but no items or subitems - are removed. - */ - - LISTVIEW_GetHeaderRect(infoPtr, nColumn, &rcCol); - - if (!Header_DeleteItem(infoPtr->hwndHeader, nColumn)) - return FALSE; - - Free(DPA_GetPtr(infoPtr->hdpaColumns, nColumn)); - DPA_DeletePtr(infoPtr->hdpaColumns, nColumn); - - if (!(infoPtr->dwStyle & LVS_OWNERDATA) && nColumn) - { - SUBITEM_INFO *lpSubItem, *lpDelItem; - HDPA hdpaSubItems; - INT nItem, nSubItem, i; - - for (nItem = 0; nItem < infoPtr->nItemCount; nItem++) - { - hdpaSubItems = (HDPA)DPA_GetPtr(infoPtr->hdpaItems, nItem); - nSubItem = 0; - lpDelItem = 0; - for (i = 1; i < DPA_GetPtrCount(hdpaSubItems); i++) - { - lpSubItem = (SUBITEM_INFO *)DPA_GetPtr(hdpaSubItems, i); - if (lpSubItem->iSubItem == nColumn) - { - nSubItem = i; - lpDelItem = lpSubItem; - } - else if (lpSubItem->iSubItem > nColumn) - { - lpSubItem->iSubItem--; - } - } - - /* if we found our subitem, zapp it */ - if (nSubItem > 0) - { - /* free string */ - if (is_textW(lpDelItem->hdr.pszText)) - Free(lpDelItem->hdr.pszText); - - /* free item */ - Free(lpDelItem); - - /* free dpa memory */ - DPA_DeletePtr(hdpaSubItems, nSubItem); - } - } - } - - /* update the other column info */ - if(DPA_GetPtrCount(infoPtr->hdpaColumns) == 0) - LISTVIEW_InvalidateList(infoPtr); - else - LISTVIEW_ScrollColumns(infoPtr, nColumn, -(rcCol.right - rcCol.left)); - - return TRUE; -} - -/*** - * DESCRIPTION: - * Invalidates the listview after an item's insertion or deletion. - * - * PARAMETER(S): - * [I] infoPtr : valid pointer to the listview structure - * [I] nItem : item index - * [I] dir : -1 if deleting, 1 if inserting - * - * RETURN: - * None - */ -static void LISTVIEW_ScrollOnInsert(LISTVIEW_INFO *infoPtr, INT nItem, INT dir) -{ - UINT uView = infoPtr->dwStyle & LVS_TYPEMASK; - INT nPerCol, nItemCol, nItemRow; - RECT rcScroll; - POINT Origin; - - /* if we don't refresh, what's the point of scrolling? */ - if (!is_redrawing(infoPtr)) return; - - assert (abs(dir) == 1); - - /* arrange icons if autoarrange is on */ - if (is_autoarrange(infoPtr)) - { - BOOL arrange = TRUE; - if (dir < 0 && nItem >= infoPtr->nItemCount) arrange = FALSE; - if (dir > 0 && nItem == infoPtr->nItemCount - 1) arrange = FALSE; - if (arrange) LISTVIEW_Arrange(infoPtr, LVA_DEFAULT); - } - - /* scrollbars need updating */ - LISTVIEW_UpdateScroll(infoPtr); - - /* figure out the item's position */ - if (uView == LVS_REPORT) - nPerCol = infoPtr->nItemCount + 1; - else if (uView == LVS_LIST) - nPerCol = LISTVIEW_GetCountPerColumn(infoPtr); - else /* LVS_ICON, or LVS_SMALLICON */ - return; - - nItemCol = nItem / nPerCol; - nItemRow = nItem % nPerCol; - LISTVIEW_GetOrigin(infoPtr, &Origin); - - /* move the items below up a slot */ - rcScroll.left = nItemCol * infoPtr->nItemWidth; - rcScroll.top = nItemRow * infoPtr->nItemHeight; - rcScroll.right = rcScroll.left + infoPtr->nItemWidth; - rcScroll.bottom = nPerCol * infoPtr->nItemHeight; - OffsetRect(&rcScroll, Origin.x, Origin.y); - TRACE("rcScroll=%s, dx=%d\n", debugrect(&rcScroll), dir * infoPtr->nItemHeight); - if (IntersectRect(&rcScroll, &rcScroll, &infoPtr->rcList)) - { - TRACE("Scrolling rcScroll=%s, rcList=%s\n", debugrect(&rcScroll), debugrect(&infoPtr->rcList)); - ScrollWindowEx(infoPtr->hwndSelf, 0, dir * infoPtr->nItemHeight, - &rcScroll, &rcScroll, 0, 0, SW_ERASE | SW_INVALIDATE); - } - - /* report has only that column, so we're done */ - if (uView == LVS_REPORT) return; - - /* now for LISTs, we have to deal with the columns to the right */ - rcScroll.left = (nItemCol + 1) * infoPtr->nItemWidth; - rcScroll.top = 0; - rcScroll.right = (infoPtr->nItemCount / nPerCol + 1) * infoPtr->nItemWidth; - rcScroll.bottom = nPerCol * infoPtr->nItemHeight; - OffsetRect(&rcScroll, Origin.x, Origin.y); - if (IntersectRect(&rcScroll, &rcScroll, &infoPtr->rcList)) - ScrollWindowEx(infoPtr->hwndSelf, 0, dir * infoPtr->nItemHeight, - &rcScroll, &rcScroll, 0, 0, SW_ERASE | SW_INVALIDATE); -} - -/*** - * DESCRIPTION: - * Removes an item from the listview control. - * - * PARAMETER(S): - * [I] infoPtr : valid pointer to the listview structure - * [I] nItem : item index - * - * RETURN: - * SUCCESS : TRUE - * FAILURE : FALSE - */ -static BOOL LISTVIEW_DeleteItem(LISTVIEW_INFO *infoPtr, INT nItem) -{ - UINT uView = infoPtr->dwStyle & LVS_TYPEMASK; - LVITEMW item; - - TRACE("(nItem=%d)\n", nItem); - - if (nItem < 0 || nItem >= infoPtr->nItemCount) return FALSE; - - /* remove selection, and focus */ - item.state = 0; - item.stateMask = LVIS_SELECTED | LVIS_FOCUSED; - LISTVIEW_SetItemState(infoPtr, nItem, &item); - - /* send LVN_DELETEITEM notification. */ - notify_deleteitem(infoPtr, nItem); - - /* we need to do this here, because we'll be deleting stuff */ - if (uView == LVS_SMALLICON || uView == LVS_ICON) - LISTVIEW_InvalidateItem(infoPtr, nItem); - - if (!(infoPtr->dwStyle & LVS_OWNERDATA)) - { - HDPA hdpaSubItems; - ITEMHDR *hdrItem; - INT i; - - hdpaSubItems = (HDPA)DPA_DeletePtr(infoPtr->hdpaItems, nItem); - for (i = 0; i < DPA_GetPtrCount(hdpaSubItems); i++) - { - hdrItem = (ITEMHDR *)DPA_GetPtr(hdpaSubItems, i); - if (is_textW(hdrItem->pszText)) Free(hdrItem->pszText); - Free(hdrItem); - } - DPA_Destroy(hdpaSubItems); - } - - if (uView == LVS_SMALLICON || uView == LVS_ICON) - { - DPA_DeletePtr(infoPtr->hdpaPosX, nItem); - DPA_DeletePtr(infoPtr->hdpaPosY, nItem); - } - - infoPtr->nItemCount--; - LISTVIEW_ShiftIndices(infoPtr, nItem, -1); - - /* now is the invalidation fun */ - LISTVIEW_ScrollOnInsert(infoPtr, nItem, -1); - return TRUE; -} - - -/*** - * DESCRIPTION: - * Callback implementation for editlabel control - * - * PARAMETER(S): - * [I] infoPtr : valid pointer to the listview structure - * [I] pszText : modified text - * [I] isW : TRUE if psxText is Unicode, FALSE if it's ANSI - * - * RETURN: - * SUCCESS : TRUE - * FAILURE : FALSE - */ -static BOOL LISTVIEW_EndEditLabelT(LISTVIEW_INFO *infoPtr, LPWSTR pszText, BOOL isW) -{ - NMLVDISPINFOW dispInfo; - - TRACE("(pszText=%s, isW=%d)\n", debugtext_t(pszText, isW), isW); - - ZeroMemory(&dispInfo, sizeof(dispInfo)); - dispInfo.item.mask = LVIF_PARAM | LVIF_STATE; - dispInfo.item.iItem = infoPtr->nEditLabelItem; - dispInfo.item.iSubItem = 0; - dispInfo.item.stateMask = ~0; - if (!LISTVIEW_GetItemW(infoPtr, &dispInfo.item)) return FALSE; - /* add the text from the edit in */ - dispInfo.item.mask |= LVIF_TEXT; - dispInfo.item.pszText = pszText; - dispInfo.item.cchTextMax = textlenT(pszText, isW); - - /* Do we need to update the Item Text */ - if (!notify_dispinfoT(infoPtr, LVN_ENDLABELEDITW, &dispInfo, isW)) return FALSE; - if (!pszText) return TRUE; - - ZeroMemory(&dispInfo, sizeof(dispInfo)); - dispInfo.item.mask = LVIF_TEXT; - dispInfo.item.iItem = infoPtr->nEditLabelItem; - dispInfo.item.iSubItem = 0; - dispInfo.item.pszText = pszText; - dispInfo.item.cchTextMax = textlenT(pszText, isW); - return LISTVIEW_SetItemT(infoPtr, &dispInfo.item, isW); -} - -/*** - * DESCRIPTION: - * Begin in place editing of specified list view item - * - * PARAMETER(S): - * [I] infoPtr : valid pointer to the listview structure - * [I] nItem : item index - * [I] isW : TRUE if it's a Unicode req, FALSE if ASCII - * - * RETURN: - * SUCCESS : TRUE - * FAILURE : FALSE - */ -static HWND LISTVIEW_EditLabelT(LISTVIEW_INFO *infoPtr, INT nItem, BOOL isW) -{ - WCHAR szDispText[DISP_TEXT_SIZE] = { 0 }; - NMLVDISPINFOW dispInfo; - RECT rect; - - TRACE("(nItem=%d, isW=%d)\n", nItem, isW); - - if (~infoPtr->dwStyle & LVS_EDITLABELS) return 0; - if (nItem < 0 || nItem >= infoPtr->nItemCount) return 0; - - infoPtr->nEditLabelItem = nItem; - - /* Is the EditBox still there, if so remove it */ - if(infoPtr->hwndEdit != 0) - { - SetFocus(infoPtr->hwndSelf); - infoPtr->hwndEdit = 0; - } - - LISTVIEW_SetSelection(infoPtr, nItem); - LISTVIEW_SetItemFocus(infoPtr, nItem); - LISTVIEW_InvalidateItem(infoPtr, nItem); - - rect.left = LVIR_LABEL; - if (!LISTVIEW_GetItemRect(infoPtr, nItem, &rect)) return 0; - - ZeroMemory(&dispInfo, sizeof(dispInfo)); - dispInfo.item.mask = LVIF_PARAM | LVIF_STATE | LVIF_TEXT; - dispInfo.item.iItem = nItem; - dispInfo.item.iSubItem = 0; - dispInfo.item.stateMask = ~0; - dispInfo.item.pszText = szDispText; - dispInfo.item.cchTextMax = DISP_TEXT_SIZE; - if (!LISTVIEW_GetItemT(infoPtr, &dispInfo.item, isW)) return 0; - - infoPtr->hwndEdit = CreateEditLabelT(infoPtr, dispInfo.item.pszText, WS_VISIBLE, - rect.left-2, rect.top-1, 0, rect.bottom - rect.top+2, isW); - if (!infoPtr->hwndEdit) return 0; - - if (notify_dispinfoT(infoPtr, LVN_BEGINLABELEDITW, &dispInfo, isW)) - { - SendMessageW(infoPtr->hwndEdit, WM_CLOSE, 0, 0); - infoPtr->hwndEdit = 0; - return 0; - } - - ShowWindow(infoPtr->hwndEdit, SW_NORMAL); - SetFocus(infoPtr->hwndEdit); - SendMessageW(infoPtr->hwndEdit, EM_SETSEL, 0, -1); - return infoPtr->hwndEdit; -} - - -/*** - * DESCRIPTION: - * Ensures the specified item is visible, scrolling into view if necessary. - * - * PARAMETER(S): - * [I] infoPtr : valid pointer to the listview structure - * [I] nItem : item index - * [I] bPartial : partially or entirely visible - * - * RETURN: - * SUCCESS : TRUE - * FAILURE : FALSE - */ -static BOOL LISTVIEW_EnsureVisible(LISTVIEW_INFO *infoPtr, INT nItem, BOOL bPartial) -{ - UINT uView = infoPtr->dwStyle & LVS_TYPEMASK; - INT nScrollPosHeight = 0; - INT nScrollPosWidth = 0; - INT nHorzAdjust = 0; - INT nVertAdjust = 0; - INT nHorzDiff = 0; - INT nVertDiff = 0; - RECT rcItem, rcTemp; - - rcItem.left = LVIR_BOUNDS; - if (!LISTVIEW_GetItemRect(infoPtr, nItem, &rcItem)) return FALSE; - - if (bPartial && IntersectRect(&rcTemp, &infoPtr->rcList, &rcItem)) return TRUE; - - if (rcItem.left < infoPtr->rcList.left || rcItem.right > infoPtr->rcList.right) - { - /* scroll left/right, but in LVS_REPORT mode */ - if (uView == LVS_LIST) - nScrollPosWidth = infoPtr->nItemWidth; - else if ((uView == LVS_SMALLICON) || (uView == LVS_ICON)) - nScrollPosWidth = 1; - - if (rcItem.left < infoPtr->rcList.left) - { - nHorzAdjust = -1; - if (uView != LVS_REPORT) nHorzDiff = rcItem.left - infoPtr->rcList.left; - } - else - { - nHorzAdjust = 1; - if (uView != LVS_REPORT) nHorzDiff = rcItem.right - infoPtr->rcList.right; - } - } - - if (rcItem.top < infoPtr->rcList.top || rcItem.bottom > infoPtr->rcList.bottom) - { - /* scroll up/down, but not in LVS_LIST mode */ - if (uView == LVS_REPORT) - nScrollPosHeight = infoPtr->nItemHeight; - else if ((uView == LVS_ICON) || (uView == LVS_SMALLICON)) - nScrollPosHeight = 1; - - if (rcItem.top < infoPtr->rcList.top) - { - nVertAdjust = -1; - if (uView != LVS_LIST) nVertDiff = rcItem.top - infoPtr->rcList.top; - } - else - { - nVertAdjust = 1; - if (uView != LVS_LIST) nVertDiff = rcItem.bottom - infoPtr->rcList.bottom; - } - } - - if (!nScrollPosWidth && !nScrollPosHeight) return TRUE; - - if (nScrollPosWidth) - { - INT diff = nHorzDiff / nScrollPosWidth; - if (nHorzDiff % nScrollPosWidth) diff += nHorzAdjust; - LISTVIEW_HScroll(infoPtr, SB_INTERNAL, diff, 0); - } - - if (nScrollPosHeight) - { - INT diff = nVertDiff / nScrollPosHeight; - if (nVertDiff % nScrollPosHeight) diff += nVertAdjust; - LISTVIEW_VScroll(infoPtr, SB_INTERNAL, diff, 0); - } - - return TRUE; -} - -/*** - * DESCRIPTION: - * Searches for an item with specific characteristics. - * - * PARAMETER(S): - * [I] hwnd : window handle - * [I] nStart : base item index - * [I] lpFindInfo : item information to look for - * - * RETURN: - * SUCCESS : index of item - * FAILURE : -1 - */ -static INT LISTVIEW_FindItemW(LISTVIEW_INFO *infoPtr, INT nStart, - const LVFINDINFOW *lpFindInfo) -{ - UINT uView = infoPtr->dwStyle & LVS_TYPEMASK; - WCHAR szDispText[DISP_TEXT_SIZE] = { '\0' }; - BOOL bWrap = FALSE, bNearest = FALSE; - INT nItem = nStart + 1, nLast = infoPtr->nItemCount, nNearestItem = -1; - ULONG xdist, ydist, dist, mindist = 0x7fffffff; - POINT Position, Destination; - LVITEMW lvItem; - - if (!lpFindInfo || nItem < 0) return -1; - - lvItem.mask = 0; - if (lpFindInfo->flags & (LVFI_STRING | LVFI_PARTIAL)) - { - lvItem.mask |= LVIF_TEXT; - lvItem.pszText = szDispText; - lvItem.cchTextMax = DISP_TEXT_SIZE; - } - - if (lpFindInfo->flags & LVFI_WRAP) - bWrap = TRUE; - - if ((lpFindInfo->flags & LVFI_NEARESTXY) && - (uView == LVS_ICON || uView ==LVS_SMALLICON)) - { - POINT Origin; - RECT rcArea; - - LISTVIEW_GetOrigin(infoPtr, &Origin); - Destination.x = lpFindInfo->pt.x - Origin.x; - Destination.y = lpFindInfo->pt.y - Origin.y; - switch(lpFindInfo->vkDirection) - { - case VK_DOWN: Destination.y += infoPtr->nItemHeight; break; - case VK_UP: Destination.y -= infoPtr->nItemHeight; break; - case VK_RIGHT: Destination.x += infoPtr->nItemWidth; break; - case VK_LEFT: Destination.x -= infoPtr->nItemWidth; break; - case VK_HOME: Destination.x = Destination.y = 0; break; - case VK_NEXT: Destination.y += infoPtr->rcList.bottom - infoPtr->rcList.top; break; - case VK_PRIOR: Destination.y -= infoPtr->rcList.bottom - infoPtr->rcList.top; break; - case VK_END: - LISTVIEW_GetAreaRect(infoPtr, &rcArea); - Destination.x = rcArea.right; - Destination.y = rcArea.bottom; - break; - default: ERR("Unknown vkDirection=%d\n", lpFindInfo->vkDirection); - } - bNearest = TRUE; - } - - /* if LVFI_PARAM is specified, all other flags are ignored */ - if (lpFindInfo->flags & LVFI_PARAM) - { - lvItem.mask |= LVIF_PARAM; - bNearest = FALSE; - lvItem.mask &= ~LVIF_TEXT; - } - -again: - for (; nItem < nLast; nItem++) - { - lvItem.iItem = nItem; - lvItem.iSubItem = 0; - if (!LISTVIEW_GetItemW(infoPtr, &lvItem)) continue; - - if (lvItem.mask & LVIF_PARAM) - { - if (lpFindInfo->lParam == lvItem.lParam) - return nItem; - else - continue; - } - - if (lvItem.mask & LVIF_TEXT) - { - if (lpFindInfo->flags & LVFI_PARTIAL) - { - if (strstrW(lvItem.pszText, lpFindInfo->psz) == NULL) continue; - } - else - { - if (lstrcmpW(lvItem.pszText, lpFindInfo->psz) != 0) continue; - } - } - - if (!bNearest) return nItem; - - /* This is very inefficient. To do a good job here, - * we need a sorted array of (x,y) item positions */ - LISTVIEW_GetItemOrigin(infoPtr, nItem, &Position); - - /* compute the distance^2 to the destination */ - xdist = Destination.x - Position.x; - ydist = Destination.y - Position.y; - dist = xdist * xdist + ydist * ydist; - - /* remember the distance, and item if it's closer */ - if (dist < mindist) - { - mindist = dist; - nNearestItem = nItem; - } - } - - if (bWrap) - { - nItem = 0; - nLast = min(nStart + 1, infoPtr->nItemCount); - bWrap = FALSE; - goto again; - } - - return nNearestItem; -} - -/*** - * DESCRIPTION: - * Searches for an item with specific characteristics. - * - * PARAMETER(S): - * [I] hwnd : window handle - * [I] nStart : base item index - * [I] lpFindInfo : item information to look for - * - * RETURN: - * SUCCESS : index of item - * FAILURE : -1 - */ -static INT LISTVIEW_FindItemA(LISTVIEW_INFO *infoPtr, INT nStart, - const LVFINDINFOA *lpFindInfo) -{ - BOOL hasText = lpFindInfo->flags & (LVFI_STRING | LVFI_PARTIAL); - LVFINDINFOW fiw; - INT res; - - memcpy(&fiw, lpFindInfo, sizeof(fiw)); - if (hasText) fiw.psz = textdupTtoW((LPCWSTR)lpFindInfo->psz, FALSE); - res = LISTVIEW_FindItemW(infoPtr, nStart, &fiw); - if (hasText) textfreeT((LPWSTR)fiw.psz, FALSE); - return res; -} - -/*** - * DESCRIPTION: - * Retrieves the background image of the listview control. - * - * PARAMETER(S): - * [I] infoPtr : valid pointer to the listview structure - * [O] lpBkImage : background image attributes - * - * RETURN: - * SUCCESS : TRUE - * FAILURE : FALSE - */ -/* static BOOL LISTVIEW_GetBkImage(LISTVIEW_INFO *infoPtr, LPLVBKIMAGE lpBkImage) */ -/* { */ -/* FIXME (listview, "empty stub!\n"); */ -/* return FALSE; */ -/* } */ - -/*** - * DESCRIPTION: - * Retrieves column attributes. - * - * PARAMETER(S): - * [I] infoPtr : valid pointer to the listview structure - * [I] nColumn : column index - * [IO] lpColumn : column information - * [I] isW : if TRUE, then lpColumn is a LPLVCOLUMNW - * otherwise it is in fact a LPLVCOLUMNA - * - * RETURN: - * SUCCESS : TRUE - * FAILURE : FALSE - */ -static BOOL LISTVIEW_GetColumnT(LISTVIEW_INFO *infoPtr, INT nColumn, LPLVCOLUMNW lpColumn, BOOL isW) -{ - COLUMN_INFO *lpColumnInfo; - HDITEMW hdi; - - if (!lpColumn || nColumn < 0 || nColumn >= DPA_GetPtrCount(infoPtr->hdpaColumns)) return FALSE; - lpColumnInfo = LISTVIEW_GetColumnInfo(infoPtr, nColumn); - - /* initialize memory */ - ZeroMemory(&hdi, sizeof(hdi)); - - if (lpColumn->mask & LVCF_TEXT) - { - hdi.mask |= HDI_TEXT; - hdi.pszText = lpColumn->pszText; - hdi.cchTextMax = lpColumn->cchTextMax; - } - - if (lpColumn->mask & LVCF_IMAGE) - hdi.mask |= HDI_IMAGE; - - if (lpColumn->mask & LVCF_ORDER) - hdi.mask |= HDI_ORDER; - - if (!SendMessageW(infoPtr->hwndHeader, isW ? HDM_GETITEMW : HDM_GETITEMA, nColumn, (LPARAM)&hdi)) return FALSE; - - if (lpColumn->mask & LVCF_FMT) - lpColumn->fmt = lpColumnInfo->fmt; - - if (lpColumn->mask & LVCF_WIDTH) - lpColumn->cx = lpColumnInfo->rcHeader.right - lpColumnInfo->rcHeader.left; - - if (lpColumn->mask & LVCF_IMAGE) - lpColumn->iImage = hdi.iImage; - - if (lpColumn->mask & LVCF_ORDER) - lpColumn->iOrder = hdi.iOrder; - - return TRUE; -} - - -static BOOL LISTVIEW_GetColumnOrderArray(LISTVIEW_INFO *infoPtr, INT iCount, LPINT lpiArray) -{ - INT i; - - if (!lpiArray) - return FALSE; - - /* FIXME: little hack */ - for (i = 0; i < iCount; i++) - lpiArray[i] = i; - - return TRUE; -} - -/*** - * DESCRIPTION: - * Retrieves the column width. - * - * PARAMETER(S): - * [I] infoPtr : valid pointer to the listview structure - * [I] int : column index - * - * RETURN: - * SUCCESS : column width - * FAILURE : zero - */ -static INT LISTVIEW_GetColumnWidth(LISTVIEW_INFO *infoPtr, INT nColumn) -{ - INT nColumnWidth = 0; - RECT rcHeader; - - TRACE("nColumn=%d\n", nColumn); - - /* we have a 'column' in LIST and REPORT mode only */ - switch(infoPtr->dwStyle & LVS_TYPEMASK) - { - case LVS_LIST: - nColumnWidth = infoPtr->nItemWidth; - break; - case LVS_REPORT: - if (nColumn < 0 || nColumn >= DPA_GetPtrCount(infoPtr->hdpaColumns)) return 0; - LISTVIEW_GetHeaderRect(infoPtr, nColumn, &rcHeader); - nColumnWidth = rcHeader.right - rcHeader.left; - break; - } - - TRACE("nColumnWidth=%d\n", nColumnWidth); - return nColumnWidth; -} - -/*** - * DESCRIPTION: - * In list or report display mode, retrieves the number of items that can fit - * vertically in the visible area. In icon or small icon display mode, - * retrieves the total number of visible items. - * - * PARAMETER(S): - * [I] infoPtr : valid pointer to the listview structure - * - * RETURN: - * Number of fully visible items. - */ -static INT LISTVIEW_GetCountPerPage(LISTVIEW_INFO *infoPtr) -{ - switch (infoPtr->dwStyle & LVS_TYPEMASK) - { - case LVS_ICON: - case LVS_SMALLICON: - return infoPtr->nItemCount; - case LVS_REPORT: - return LISTVIEW_GetCountPerColumn(infoPtr); - case LVS_LIST: - return LISTVIEW_GetCountPerRow(infoPtr) * LISTVIEW_GetCountPerColumn(infoPtr); - } - assert(FALSE); - return 0; -} - -/*** - * DESCRIPTION: - * Retrieves an image list handle. - * - * PARAMETER(S): - * [I] infoPtr : valid pointer to the listview structure - * [I] nImageList : image list identifier - * - * RETURN: - * SUCCESS : image list handle - * FAILURE : NULL - */ -static HIMAGELIST LISTVIEW_GetImageList(LISTVIEW_INFO *infoPtr, INT nImageList) -{ - switch (nImageList) - { - case LVSIL_NORMAL: return infoPtr->himlNormal; - case LVSIL_SMALL: return infoPtr->himlSmall; - case LVSIL_STATE: return infoPtr->himlState; - } - return NULL; -} - -/* LISTVIEW_GetISearchString */ - -/*** - * DESCRIPTION: - * Retrieves item attributes. - * - * PARAMETER(S): - * [I] hwnd : window handle - * [IO] lpLVItem : item info - * [I] isW : if TRUE, then lpLVItem is a LPLVITEMW, - * if FALSE, the lpLVItem is a LPLVITEMA. - * - * NOTE: - * This is the internal 'GetItem' interface -- it tries to - * be smart, and avoids text copies, if possible, by modifing - * lpLVItem->pszText to point to the text string. Please note - * that this is not always possible (e.g. OWNERDATA), so on - * entry you *must* supply valid values for pszText, and cchTextMax. - * The only difference to the documented interface is that upon - * return, you should use *only* the lpLVItem->pszText, rather than - * the buffer pointer you provided on input. Most code already does - * that, so it's not a problem. - * For the two cases when the text must be copied (that is, - * for LVM_GETITEM, and LVM_GETITEMTEXT), use LISTVIEW_GetItemExtT. - * - * RETURN: - * SUCCESS : TRUE - * FAILURE : FALSE - */ -static BOOL LISTVIEW_GetItemT(LISTVIEW_INFO *infoPtr, LPLVITEMW lpLVItem, BOOL isW) -{ - ITEMHDR callbackHdr = { LPSTR_TEXTCALLBACKW, I_IMAGECALLBACK }; - NMLVDISPINFOW dispInfo; - ITEM_INFO *lpItem; - ITEMHDR* pItemHdr; - HDPA hdpaSubItems; - INT isubitem; - - TRACE("(lpLVItem=%s, isW=%d)\n", debuglvitem_t(lpLVItem, isW), isW); - - if (!lpLVItem || lpLVItem->iItem < 0 || lpLVItem->iItem >= infoPtr->nItemCount) - return FALSE; - - if (lpLVItem->mask == 0) return TRUE; - - /* make a local copy */ - isubitem = lpLVItem->iSubItem; - - /* a quick optimization if all we're asked is the focus state - * these queries are worth optimising since they are common, - * and can be answered in constant time, without the heavy accesses */ - if ( (lpLVItem->mask == LVIF_STATE) && (lpLVItem->stateMask == LVIS_FOCUSED) && - !(infoPtr->uCallbackMask & LVIS_FOCUSED) ) - { - lpLVItem->state = 0; - if (infoPtr->nFocusedItem == lpLVItem->iItem) - lpLVItem->state |= LVIS_FOCUSED; - return TRUE; - } - - ZeroMemory(&dispInfo, sizeof(dispInfo)); - - /* if the app stores all the data, handle it separately */ - if (infoPtr->dwStyle & LVS_OWNERDATA) - { - dispInfo.item.state = 0; - - /* apprently, we should not callback for lParam in LVS_OWNERDATA */ - if ((lpLVItem->mask & ~(LVIF_STATE | LVIF_PARAM)) || infoPtr->uCallbackMask) - { - /* NOTE: copy only fields which we _know_ are initialized, some apps - * depend on the uninitialized fields being 0 */ - dispInfo.item.mask = lpLVItem->mask & ~LVIF_PARAM; - dispInfo.item.iItem = lpLVItem->iItem; - dispInfo.item.iSubItem = isubitem; - if (lpLVItem->mask & LVIF_TEXT) - { - dispInfo.item.pszText = lpLVItem->pszText; - dispInfo.item.cchTextMax = lpLVItem->cchTextMax; - } - if (lpLVItem->mask & LVIF_STATE) - dispInfo.item.stateMask = lpLVItem->stateMask & infoPtr->uCallbackMask; - notify_dispinfoT(infoPtr, LVN_GETDISPINFOW, &dispInfo, isW); - dispInfo.item.stateMask = lpLVItem->stateMask; - if (lpLVItem->mask & (LVIF_GROUPID|LVIF_COLUMNS)) - { - /* full size structure expected - _WIN32IE >= 0x560 */ - *lpLVItem = dispInfo.item; - } - else if (lpLVItem->mask & LVIF_INDENT) - { - /* indent member expected - _WIN32IE >= 0x300 */ - memcpy(lpLVItem, &dispInfo.item, offsetof( LVITEMW, iGroupId )); - } - else - { - /* minimal structure expected */ - memcpy(lpLVItem, &dispInfo.item, offsetof( LVITEMW, iIndent )); - } - TRACE(" getdispinfo(1):lpLVItem=%s\n", debuglvitem_t(lpLVItem, isW)); - } - - /* make sure lParam is zeroed out */ - if (lpLVItem->mask & LVIF_PARAM) lpLVItem->lParam = 0; - - /* we store only a little state, so if we're not asked, we're done */ - if (!(lpLVItem->mask & LVIF_STATE) || isubitem) return TRUE; - - /* if focus is handled by us, report it */ - if ( lpLVItem->stateMask & ~infoPtr->uCallbackMask & LVIS_FOCUSED ) - { - lpLVItem->state &= ~LVIS_FOCUSED; - if (infoPtr->nFocusedItem == lpLVItem->iItem) - lpLVItem->state |= LVIS_FOCUSED; - } - - /* and do the same for selection, if we handle it */ - if ( lpLVItem->stateMask & ~infoPtr->uCallbackMask & LVIS_SELECTED ) - { - lpLVItem->state &= ~LVIS_SELECTED; - if (ranges_contain(infoPtr->selectionRanges, lpLVItem->iItem)) - lpLVItem->state |= LVIS_SELECTED; - } - - return TRUE; - } - - /* find the item and subitem structures before we proceed */ - hdpaSubItems = (HDPA)DPA_GetPtr(infoPtr->hdpaItems, lpLVItem->iItem); - lpItem = (ITEM_INFO *)DPA_GetPtr(hdpaSubItems, 0); - assert (lpItem); - - if (isubitem) - { - SUBITEM_INFO *lpSubItem = LISTVIEW_GetSubItemPtr(hdpaSubItems, isubitem); - pItemHdr = lpSubItem ? &lpSubItem->hdr : &callbackHdr; - if (!lpSubItem) - { - WARN(" iSubItem invalid (%08x), ignored.\n", isubitem); - isubitem = 0; - } - } - else - pItemHdr = &lpItem->hdr; - - /* Do we need to query the state from the app? */ - if ((lpLVItem->mask & LVIF_STATE) && infoPtr->uCallbackMask && isubitem == 0) - { - dispInfo.item.mask |= LVIF_STATE; - dispInfo.item.stateMask = infoPtr->uCallbackMask; - } - - /* Do we need to enquire about the image? */ - if ((lpLVItem->mask & LVIF_IMAGE) && pItemHdr->iImage == I_IMAGECALLBACK && - (isubitem == 0 || (infoPtr->dwLvExStyle & LVS_EX_SUBITEMIMAGES))) - { - dispInfo.item.mask |= LVIF_IMAGE; - dispInfo.item.iImage = I_IMAGECALLBACK; - } - - /* Apps depend on calling back for text if it is NULL or LPSTR_TEXTCALLBACKW */ - if ((lpLVItem->mask & LVIF_TEXT) && !is_textW(pItemHdr->pszText)) - { - dispInfo.item.mask |= LVIF_TEXT; - dispInfo.item.pszText = lpLVItem->pszText; - dispInfo.item.cchTextMax = lpLVItem->cchTextMax; - if (dispInfo.item.pszText && dispInfo.item.cchTextMax > 0) - *dispInfo.item.pszText = '\0'; - } - - /* If we don't have all the requested info, query the application */ - if (dispInfo.item.mask != 0) - { - dispInfo.item.iItem = lpLVItem->iItem; - dispInfo.item.iSubItem = lpLVItem->iSubItem; /* yes: the original subitem */ - dispInfo.item.lParam = lpItem->lParam; - notify_dispinfoT(infoPtr, LVN_GETDISPINFOW, &dispInfo, isW); - TRACE(" getdispinfo(2):item=%s\n", debuglvitem_t(&dispInfo.item, isW)); - } - - /* we should not store values for subitems */ - if (isubitem) dispInfo.item.mask &= ~LVIF_DI_SETITEM; - - /* Now, handle the iImage field */ - if (dispInfo.item.mask & LVIF_IMAGE) - { - lpLVItem->iImage = dispInfo.item.iImage; - if ((dispInfo.item.mask & LVIF_DI_SETITEM) && pItemHdr->iImage == I_IMAGECALLBACK) - pItemHdr->iImage = dispInfo.item.iImage; - } - else if (lpLVItem->mask & LVIF_IMAGE) - { - if(isubitem == 0 || (infoPtr->dwLvExStyle & LVS_EX_SUBITEMIMAGES)) - lpLVItem->iImage = pItemHdr->iImage; - else - lpLVItem->iImage = 0; - } - - /* The pszText field */ - if (dispInfo.item.mask & LVIF_TEXT) - { - if ((dispInfo.item.mask & LVIF_DI_SETITEM) && pItemHdr->pszText) - textsetptrT(&pItemHdr->pszText, dispInfo.item.pszText, isW); - - lpLVItem->pszText = dispInfo.item.pszText; - } - else if (lpLVItem->mask & LVIF_TEXT) - { - if (isW) lpLVItem->pszText = pItemHdr->pszText; - else textcpynT(lpLVItem->pszText, isW, pItemHdr->pszText, TRUE, lpLVItem->cchTextMax); - } - - /* if this is a subitem, we're done */ - if (isubitem) return TRUE; - - /* Next is the lParam field */ - if (dispInfo.item.mask & LVIF_PARAM) - { - lpLVItem->lParam = dispInfo.item.lParam; - if ((dispInfo.item.mask & LVIF_DI_SETITEM)) - lpItem->lParam = dispInfo.item.lParam; - } - else if (lpLVItem->mask & LVIF_PARAM) - lpLVItem->lParam = lpItem->lParam; - - /* ... the state field (this one is different due to uCallbackmask) */ - if (lpLVItem->mask & LVIF_STATE) - { - lpLVItem->state = lpItem->state; - if (dispInfo.item.mask & LVIF_STATE) - { - lpLVItem->state &= ~dispInfo.item.stateMask; - lpLVItem->state |= (dispInfo.item.state & dispInfo.item.stateMask); - } - if ( lpLVItem->stateMask & ~infoPtr->uCallbackMask & LVIS_FOCUSED ) - { - lpLVItem->state &= ~LVIS_FOCUSED; - if (infoPtr->nFocusedItem == lpLVItem->iItem) - lpLVItem->state |= LVIS_FOCUSED; - } - if ( lpLVItem->stateMask & ~infoPtr->uCallbackMask & LVIS_SELECTED ) - { - lpLVItem->state &= ~LVIS_SELECTED; - if (ranges_contain(infoPtr->selectionRanges, lpLVItem->iItem)) - lpLVItem->state |= LVIS_SELECTED; - } - } - - /* and last, but not least, the indent field */ - if (lpLVItem->mask & LVIF_INDENT) - lpLVItem->iIndent = lpItem->iIndent; - - return TRUE; -} - -/*** - * DESCRIPTION: - * Retrieves item attributes. - * - * PARAMETER(S): - * [I] hwnd : window handle - * [IO] lpLVItem : item info - * [I] isW : if TRUE, then lpLVItem is a LPLVITEMW, - * if FALSE, the lpLVItem is a LPLVITEMA. - * - * NOTE: - * This is the external 'GetItem' interface -- it properly copies - * the text in the provided buffer. - * - * RETURN: - * SUCCESS : TRUE - * FAILURE : FALSE - */ -static BOOL LISTVIEW_GetItemExtT(LISTVIEW_INFO *infoPtr, LPLVITEMW lpLVItem, BOOL isW) -{ - LPWSTR pszText; - BOOL bResult; - - if (!lpLVItem || lpLVItem->iItem < 0 || lpLVItem->iItem >= infoPtr->nItemCount) - return FALSE; - - pszText = lpLVItem->pszText; - bResult = LISTVIEW_GetItemT(infoPtr, lpLVItem, isW); - if (bResult && lpLVItem->pszText != pszText) - textcpynT(pszText, isW, lpLVItem->pszText, isW, lpLVItem->cchTextMax); - lpLVItem->pszText = pszText; - - return bResult; -} - - -/*** - * DESCRIPTION: - * Retrieves the position (upper-left) of the listview control item. - * Note that for LVS_ICON style, the upper-left is that of the icon - * and not the bounding box. - * - * PARAMETER(S): - * [I] infoPtr : valid pointer to the listview structure - * [I] nItem : item index - * [O] lpptPosition : coordinate information - * - * RETURN: - * SUCCESS : TRUE - * FAILURE : FALSE - */ -static BOOL LISTVIEW_GetItemPosition(LISTVIEW_INFO *infoPtr, INT nItem, LPPOINT lpptPosition) -{ - UINT uView = infoPtr->dwStyle & LVS_TYPEMASK; - POINT Origin; - - TRACE("(nItem=%d, lpptPosition=%p)\n", nItem, lpptPosition); - - if (!lpptPosition || nItem < 0 || nItem >= infoPtr->nItemCount) return FALSE; - - LISTVIEW_GetOrigin(infoPtr, &Origin); - LISTVIEW_GetItemOrigin(infoPtr, nItem, lpptPosition); - - if (uView == LVS_ICON) - { - lpptPosition->x += (infoPtr->nItemWidth - infoPtr->iconSize.cx) / 2; - lpptPosition->y += ICON_TOP_PADDING; - } - lpptPosition->x += Origin.x; - lpptPosition->y += Origin.y; - - TRACE (" lpptPosition=%s\n", debugpoint(lpptPosition)); - return TRUE; -} - - -/*** - * DESCRIPTION: - * Retrieves the bounding rectangle for a listview control item. - * - * PARAMETER(S): - * [I] infoPtr : valid pointer to the listview structure - * [I] nItem : item index - * [IO] lprc : bounding rectangle coordinates - * lprc->left specifies the portion of the item for which the bounding - * rectangle will be retrieved. - * - * LVIR_BOUNDS Returns the bounding rectangle of the entire item, - * including the icon and label. - * * - * * For LVS_ICON - * * Experiment shows that native control returns: - * * width = min (48, length of text line) - * * .left = position.x - (width - iconsize.cx)/2 - * * .right = .left + width - * * height = #lines of text * ntmHeight + icon height + 8 - * * .top = position.y - 2 - * * .bottom = .top + height - * * separation between items .y = itemSpacing.cy - height - * * .x = itemSpacing.cx - width - * LVIR_ICON Returns the bounding rectangle of the icon or small icon. - * * - * * For LVS_ICON - * * Experiment shows that native control returns: - * * width = iconSize.cx + 16 - * * .left = position.x - (width - iconsize.cx)/2 - * * .right = .left + width - * * height = iconSize.cy + 4 - * * .top = position.y - 2 - * * .bottom = .top + height - * * separation between items .y = itemSpacing.cy - height - * * .x = itemSpacing.cx - width - * LVIR_LABEL Returns the bounding rectangle of the item text. - * * - * * For LVS_ICON - * * Experiment shows that native control returns: - * * width = text length - * * .left = position.x - width/2 - * * .right = .left + width - * * height = ntmH * linecount + 2 - * * .top = position.y + iconSize.cy + 6 - * * .bottom = .top + height - * * separation between items .y = itemSpacing.cy - height - * * .x = itemSpacing.cx - width - * LVIR_SELECTBOUNDS Returns the union of the LVIR_ICON and LVIR_LABEL - * rectangles, but excludes columns in report view. - * - * RETURN: - * SUCCESS : TRUE - * FAILURE : FALSE - * - * NOTES - * Note that the bounding rectangle of the label in the LVS_ICON view depends - * upon whether the window has the focus currently and on whether the item - * is the one with the focus. Ensure that the control's record of which - * item has the focus agrees with the items' records. - */ -static BOOL LISTVIEW_GetItemRect(LISTVIEW_INFO *infoPtr, INT nItem, LPRECT lprc) -{ - UINT uView = infoPtr->dwStyle & LVS_TYPEMASK; - WCHAR szDispText[DISP_TEXT_SIZE] = { '\0' }; - BOOL doLabel = TRUE, oversizedBox = FALSE; - POINT Position, Origin; - LVITEMW lvItem; - RECT label_rect; - - TRACE("(hwnd=%p, nItem=%d, lprc=%p)\n", infoPtr->hwndSelf, nItem, lprc); - - if (!lprc || nItem < 0 || nItem >= infoPtr->nItemCount) return FALSE; - - LISTVIEW_GetOrigin(infoPtr, &Origin); - LISTVIEW_GetItemOrigin(infoPtr, nItem, &Position); - - /* Be smart and try to figure out the minimum we have to do */ - if (lprc->left == LVIR_ICON) doLabel = FALSE; - if (uView == LVS_REPORT && lprc->left == LVIR_BOUNDS) doLabel = FALSE; - if (uView == LVS_ICON && lprc->left != LVIR_ICON && - infoPtr->bFocus && LISTVIEW_GetItemState(infoPtr, nItem, LVIS_FOCUSED)) - oversizedBox = TRUE; - - /* get what we need from the item before hand, so we make - * only one request. This can speed up things, if data - * is stored on the app side */ - lvItem.mask = 0; - if (uView == LVS_REPORT) lvItem.mask |= LVIF_INDENT; - if (doLabel) lvItem.mask |= LVIF_TEXT; - lvItem.iItem = nItem; - lvItem.iSubItem = 0; - lvItem.pszText = szDispText; - lvItem.cchTextMax = DISP_TEXT_SIZE; - if (lvItem.mask && !LISTVIEW_GetItemW(infoPtr, &lvItem)) return FALSE; - /* we got the state already up, simulate it here, to avoid a reget */ - if (uView == LVS_ICON && (lprc->left != LVIR_ICON)) - { - lvItem.mask |= LVIF_STATE; - lvItem.stateMask = LVIS_FOCUSED; - lvItem.state = (oversizedBox ? LVIS_FOCUSED : 0); - } - - if (uView == LVS_REPORT && (infoPtr->dwLvExStyle & LVS_EX_FULLROWSELECT) && lprc->left == LVIR_SELECTBOUNDS) - lprc->left = LVIR_BOUNDS; - switch(lprc->left) - { - case LVIR_ICON: - LISTVIEW_GetItemMetrics(infoPtr, &lvItem, NULL, NULL, lprc, NULL); - break; - - case LVIR_LABEL: - LISTVIEW_GetItemMetrics(infoPtr, &lvItem, NULL, NULL, NULL, lprc); - break; - - case LVIR_BOUNDS: - LISTVIEW_GetItemMetrics(infoPtr, &lvItem, lprc, NULL, NULL, NULL); - break; - - case LVIR_SELECTBOUNDS: - LISTVIEW_GetItemMetrics(infoPtr, &lvItem, NULL, NULL, lprc, &label_rect); - UnionRect(lprc, lprc, &label_rect); - break; - - default: - WARN("Unknown value: %ld\n", lprc->left); - return FALSE; - } - - OffsetRect(lprc, Position.x + Origin.x, Position.y + Origin.y); - - TRACE(" rect=%s\n", debugrect(lprc)); - - return TRUE; -} - -/*** - * DESCRIPTION: - * Retrieves the spacing between listview control items. - * - * PARAMETER(S): - * [I] infoPtr : valid pointer to the listview structure - * [IO] lprc : rectangle to receive the output - * on input, lprc->top = nSubItem - * lprc->left = LVIR_ICON | LVIR_BOUNDS | LVIR_LABEL - * - * NOTE: for subItem = 0, we should return the bounds of the _entire_ item, - * not only those of the first column. - * Fortunately, LISTVIEW_GetItemMetrics does the right thing. - * - * RETURN: - * TRUE: success - * FALSE: failure - */ -static BOOL LISTVIEW_GetSubItemRect(LISTVIEW_INFO *infoPtr, INT nItem, LPRECT lprc) -{ - POINT Position; - LVITEMW lvItem; - - if (!lprc) return FALSE; - - TRACE("(nItem=%d, nSubItem=%ld)\n", nItem, lprc->top); - /* On WinNT, a subitem of '0' calls LISTVIEW_GetItemRect */ - if (lprc->top == 0) - return LISTVIEW_GetItemRect(infoPtr, nItem, lprc); - - if ((infoPtr->dwStyle & LVS_TYPEMASK) != LVS_REPORT) return FALSE; - - if (!LISTVIEW_GetItemPosition(infoPtr, nItem, &Position)) return FALSE; - - lvItem.mask = 0; - lvItem.iItem = nItem; - lvItem.iSubItem = lprc->top; - - if (lvItem.mask && !LISTVIEW_GetItemW(infoPtr, &lvItem)) return FALSE; - switch(lprc->left) - { - case LVIR_ICON: - LISTVIEW_GetItemMetrics(infoPtr, &lvItem, NULL, NULL, lprc, NULL); - break; - - case LVIR_LABEL: - case LVIR_BOUNDS: - LISTVIEW_GetItemMetrics(infoPtr, &lvItem, lprc, NULL, NULL, NULL); - break; - - default: - ERR("Unknown bounds=%ld\n", lprc->left); - return FALSE; - } - - OffsetRect(lprc, Position.x, Position.y); - return TRUE; -} - - -/*** - * DESCRIPTION: - * Retrieves the width of a label. - * - * PARAMETER(S): - * [I] infoPtr : valid pointer to the listview structure - * - * RETURN: - * SUCCESS : string width (in pixels) - * FAILURE : zero - */ -static INT LISTVIEW_GetLabelWidth(LISTVIEW_INFO *infoPtr, INT nItem) -{ - WCHAR szDispText[DISP_TEXT_SIZE] = { '\0' }; - LVITEMW lvItem; - - TRACE("(nItem=%d)\n", nItem); - - lvItem.mask = LVIF_TEXT; - lvItem.iItem = nItem; - lvItem.iSubItem = 0; - lvItem.pszText = szDispText; - lvItem.cchTextMax = DISP_TEXT_SIZE; - if (!LISTVIEW_GetItemW(infoPtr, &lvItem)) return 0; - - return LISTVIEW_GetStringWidthT(infoPtr, lvItem.pszText, TRUE); -} - -/*** - * DESCRIPTION: - * Retrieves the spacing between listview control items. - * - * PARAMETER(S): - * [I] infoPtr : valid pointer to the listview structure - * [I] bSmall : flag for small or large icon - * - * RETURN: - * Horizontal + vertical spacing - */ -static LONG LISTVIEW_GetItemSpacing(LISTVIEW_INFO *infoPtr, BOOL bSmall) -{ - LONG lResult; - - if (!bSmall) - { - lResult = MAKELONG(infoPtr->iconSpacing.cx, infoPtr->iconSpacing.cy); - } - else - { - if ((infoPtr->dwStyle & LVS_TYPEMASK) == LVS_ICON) - lResult = MAKELONG(DEFAULT_COLUMN_WIDTH, GetSystemMetrics(SM_CXSMICON)+HEIGHT_PADDING); - else - lResult = MAKELONG(infoPtr->nItemWidth, infoPtr->nItemHeight); - } - return lResult; -} - -/*** - * DESCRIPTION: - * Retrieves the state of a listview control item. - * - * PARAMETER(S): - * [I] infoPtr : valid pointer to the listview structure - * [I] nItem : item index - * [I] uMask : state mask - * - * RETURN: - * State specified by the mask. - */ -static UINT LISTVIEW_GetItemState(LISTVIEW_INFO *infoPtr, INT nItem, UINT uMask) -{ - LVITEMW lvItem; - - if (nItem < 0 || nItem >= infoPtr->nItemCount) return 0; - - lvItem.iItem = nItem; - lvItem.iSubItem = 0; - lvItem.mask = LVIF_STATE; - lvItem.stateMask = uMask; - if (!LISTVIEW_GetItemW(infoPtr, &lvItem)) return 0; - - return lvItem.state & uMask; -} - -/*** - * DESCRIPTION: - * Retrieves the text of a listview control item or subitem. - * - * PARAMETER(S): - * [I] hwnd : window handle - * [I] nItem : item index - * [IO] lpLVItem : item information - * [I] isW : TRUE if lpLVItem is Unicode - * - * RETURN: - * SUCCESS : string length - * FAILURE : 0 - */ -static INT LISTVIEW_GetItemTextT(LISTVIEW_INFO *infoPtr, INT nItem, LPLVITEMW lpLVItem, BOOL isW) -{ - if (!lpLVItem || nItem < 0 || nItem >= infoPtr->nItemCount) return 0; - - lpLVItem->mask = LVIF_TEXT; - lpLVItem->iItem = nItem; - if (!LISTVIEW_GetItemExtT(infoPtr, lpLVItem, isW)) return 0; - - return textlenT(lpLVItem->pszText, isW); -} - -/*** - * DESCRIPTION: - * Searches for an item based on properties + relationships. - * - * PARAMETER(S): - * [I] infoPtr : valid pointer to the listview structure - * [I] nItem : item index - * [I] uFlags : relationship flag - * - * RETURN: - * SUCCESS : item index - * FAILURE : -1 - */ -static INT LISTVIEW_GetNextItem(LISTVIEW_INFO *infoPtr, INT nItem, UINT uFlags) -{ - UINT uView = infoPtr->dwStyle & LVS_TYPEMASK; - UINT uMask = 0; - LVFINDINFOW lvFindInfo; - INT nCountPerColumn; - INT nCountPerRow; - INT i; - - TRACE("nItem=%d, uFlags=%x, nItemCount=%d\n", nItem, uFlags, infoPtr->nItemCount); - if (nItem < -1 || nItem >= infoPtr->nItemCount) return -1; - - ZeroMemory(&lvFindInfo, sizeof(lvFindInfo)); - - if (uFlags & LVNI_CUT) - uMask |= LVIS_CUT; - - if (uFlags & LVNI_DROPHILITED) - uMask |= LVIS_DROPHILITED; - - if (uFlags & LVNI_FOCUSED) - uMask |= LVIS_FOCUSED; - - if (uFlags & LVNI_SELECTED) - uMask |= LVIS_SELECTED; - - /* if we're asked for the focused item, that's only one, - * so it's worth optimizing */ - if (uFlags & LVNI_FOCUSED) - { - if (!(LISTVIEW_GetItemState(infoPtr, infoPtr->nFocusedItem, uMask) & uMask) == uMask) return -1; - return (infoPtr->nFocusedItem == nItem) ? -1 : infoPtr->nFocusedItem; - } - - if (uFlags & LVNI_ABOVE) - { - if ((uView == LVS_LIST) || (uView == LVS_REPORT)) - { - while (nItem >= 0) - { - nItem--; - if ((ListView_GetItemState(infoPtr->hwndSelf, nItem, uMask) & uMask) == uMask) - return nItem; - } - } - else - { - /* Special case for autoarrange - move 'til the top of a list */ - if (is_autoarrange(infoPtr)) - { - nCountPerRow = LISTVIEW_GetCountPerRow(infoPtr); - while (nItem - nCountPerRow >= 0) - { - nItem -= nCountPerRow; - if ((LISTVIEW_GetItemState(infoPtr, nItem, uMask) & uMask) == uMask) - return nItem; - } - return -1; - } - lvFindInfo.flags = LVFI_NEARESTXY; - lvFindInfo.vkDirection = VK_UP; - ListView_GetItemPosition(infoPtr->hwndSelf, nItem, &lvFindInfo.pt); - while ((nItem = ListView_FindItemW(infoPtr->hwndSelf, nItem, &lvFindInfo)) != -1) - { - if ((ListView_GetItemState(infoPtr->hwndSelf, nItem, uMask) & uMask) == uMask) - return nItem; - } - } - } - else if (uFlags & LVNI_BELOW) - { - if ((uView == LVS_LIST) || (uView == LVS_REPORT)) - { - while (nItem < infoPtr->nItemCount) - { - nItem++; - if ((LISTVIEW_GetItemState(infoPtr, nItem, uMask) & uMask) == uMask) - return nItem; - } - } - else - { - /* Special case for autoarrange - move 'til the bottom of a list */ - if (is_autoarrange(infoPtr)) - { - nCountPerRow = LISTVIEW_GetCountPerRow(infoPtr); - while (nItem + nCountPerRow < infoPtr->nItemCount ) - { - nItem += nCountPerRow; - if ((LISTVIEW_GetItemState(infoPtr, nItem, uMask) & uMask) == uMask) - return nItem; - } - return -1; - } - lvFindInfo.flags = LVFI_NEARESTXY; - lvFindInfo.vkDirection = VK_DOWN; - ListView_GetItemPosition(infoPtr->hwndSelf, nItem, &lvFindInfo.pt); - while ((nItem = ListView_FindItemW(infoPtr->hwndSelf, nItem, &lvFindInfo)) != -1) - { - if ((LISTVIEW_GetItemState(infoPtr, nItem, uMask) & uMask) == uMask) - return nItem; - } - } - } - else if (uFlags & LVNI_TOLEFT) - { - if (uView == LVS_LIST) - { - nCountPerColumn = LISTVIEW_GetCountPerColumn(infoPtr); - while (nItem - nCountPerColumn >= 0) - { - nItem -= nCountPerColumn; - if ((LISTVIEW_GetItemState(infoPtr, nItem, uMask) & uMask) == uMask) - return nItem; - } - } - else if ((uView == LVS_SMALLICON) || (uView == LVS_ICON)) - { - /* Special case for autoarrange - move 'ti the beginning of a row */ - if (is_autoarrange(infoPtr)) - { - nCountPerRow = LISTVIEW_GetCountPerRow(infoPtr); - while (nItem % nCountPerRow > 0) - { - nItem --; - if ((LISTVIEW_GetItemState(infoPtr, nItem, uMask) & uMask) == uMask) - return nItem; - } - return -1; - } - lvFindInfo.flags = LVFI_NEARESTXY; - lvFindInfo.vkDirection = VK_LEFT; - ListView_GetItemPosition(infoPtr->hwndSelf, nItem, &lvFindInfo.pt); - while ((nItem = ListView_FindItemW(infoPtr->hwndSelf, nItem, &lvFindInfo)) != -1) - { - if ((ListView_GetItemState(infoPtr->hwndSelf, nItem, uMask) & uMask) == uMask) - return nItem; - } - } - } - else if (uFlags & LVNI_TORIGHT) - { - if (uView == LVS_LIST) - { - nCountPerColumn = LISTVIEW_GetCountPerColumn(infoPtr); - while (nItem + nCountPerColumn < infoPtr->nItemCount) - { - nItem += nCountPerColumn; - if ((ListView_GetItemState(infoPtr->hwndSelf, nItem, uMask) & uMask) == uMask) - return nItem; - } - } - else if ((uView == LVS_SMALLICON) || (uView == LVS_ICON)) - { - /* Special case for autoarrange - move 'til the end of a row */ - if (is_autoarrange(infoPtr)) - { - nCountPerRow = LISTVIEW_GetCountPerRow(infoPtr); - while (nItem % nCountPerRow < nCountPerRow - 1 ) - { - nItem ++; - if ((LISTVIEW_GetItemState(infoPtr, nItem, uMask) & uMask) == uMask) - return nItem; - } - return -1; - } - lvFindInfo.flags = LVFI_NEARESTXY; - lvFindInfo.vkDirection = VK_RIGHT; - ListView_GetItemPosition(infoPtr->hwndSelf, nItem, &lvFindInfo.pt); - while ((nItem = ListView_FindItemW(infoPtr->hwndSelf, nItem, &lvFindInfo)) != -1) - { - if ((LISTVIEW_GetItemState(infoPtr, nItem, uMask) & uMask) == uMask) - return nItem; - } - } - } - else - { - nItem++; - - /* search by index */ - for (i = nItem; i < infoPtr->nItemCount; i++) - { - if ((LISTVIEW_GetItemState(infoPtr, i, uMask) & uMask) == uMask) - return i; - } - } - - return -1; -} - -/* LISTVIEW_GetNumberOfWorkAreas */ - -/*** - * DESCRIPTION: - * Retrieves the origin coordinates when in icon or small icon display mode. - * - * PARAMETER(S): - * [I] infoPtr : valid pointer to the listview structure - * [O] lpptOrigin : coordinate information - * - * RETURN: - * None. - */ -static void LISTVIEW_GetOrigin(LISTVIEW_INFO *infoPtr, LPPOINT lpptOrigin) -{ - UINT uView = infoPtr->dwStyle & LVS_TYPEMASK; - INT nHorzPos = 0, nVertPos = 0; - SCROLLINFO scrollInfo; - - scrollInfo.cbSize = sizeof(SCROLLINFO); - scrollInfo.fMask = SIF_POS; - - if (GetScrollInfo(infoPtr->hwndSelf, SB_HORZ, &scrollInfo)) - nHorzPos = scrollInfo.nPos; - if (GetScrollInfo(infoPtr->hwndSelf, SB_VERT, &scrollInfo)) - nVertPos = scrollInfo.nPos; - - TRACE("nHorzPos=%d, nVertPos=%d\n", nHorzPos, nVertPos); - - lpptOrigin->x = infoPtr->rcList.left; - lpptOrigin->y = infoPtr->rcList.top; - if (uView == LVS_LIST) - nHorzPos *= infoPtr->nItemWidth; - else if (uView == LVS_REPORT) - nVertPos *= infoPtr->nItemHeight; - - lpptOrigin->x -= nHorzPos; - lpptOrigin->y -= nVertPos; - - TRACE(" origin=%s\n", debugpoint(lpptOrigin)); -} - -/*** - * DESCRIPTION: - * Retrieves the width of a string. - * - * PARAMETER(S): - * [I] hwnd : window handle - * [I] lpszText : text string to process - * [I] isW : TRUE if lpszText is Unicode, FALSE otherwise - * - * RETURN: - * SUCCESS : string width (in pixels) - * FAILURE : zero - */ -static INT LISTVIEW_GetStringWidthT(LISTVIEW_INFO *infoPtr, LPCWSTR lpszText, BOOL isW) -{ - SIZE stringSize; - - stringSize.cx = 0; - if (is_textT(lpszText, isW)) - { - HFONT hFont = infoPtr->hFont ? infoPtr->hFont : infoPtr->hDefaultFont; - HDC hdc = GetDC(infoPtr->hwndSelf); - HFONT hOldFont = SelectObject(hdc, hFont); - - if (isW) - GetTextExtentPointW(hdc, lpszText, lstrlenW(lpszText), &stringSize); - else - GetTextExtentPointA(hdc, (LPCSTR)lpszText, lstrlenA((LPCSTR)lpszText), &stringSize); - SelectObject(hdc, hOldFont); - ReleaseDC(infoPtr->hwndSelf, hdc); - } - return stringSize.cx; -} - -/*** - * DESCRIPTION: - * Determines which listview item is located at the specified position. - * - * PARAMETER(S): - * [I] infoPtr : valid pointer to the listview structure - * [IO] lpht : hit test information - * [I] subitem : fill out iSubItem. - * [I] select : return the index only if the hit selects the item - * - * NOTE: - * (mm 20001022): We must not allow iSubItem to be touched, for - * an app might pass only a structure with space up to iItem! - * (MS Office 97 does that for instance in the file open dialog) - * - * RETURN: - * SUCCESS : item index - * FAILURE : -1 - */ -static INT LISTVIEW_HitTest(LISTVIEW_INFO *infoPtr, LPLVHITTESTINFO lpht, BOOL subitem, BOOL select) -{ - WCHAR szDispText[DISP_TEXT_SIZE] = { '\0' }; - UINT uView = infoPtr->dwStyle & LVS_TYPEMASK; - RECT rcBox, rcBounds, rcState, rcIcon, rcLabel, rcSearch; - POINT Origin, Position, opt; - LVITEMW lvItem; - ITERATOR i; - INT iItem; - - TRACE("(pt=%s, subitem=%d, select=%d)\n", debugpoint(&lpht->pt), subitem, select); - - lpht->flags = 0; - lpht->iItem = -1; - if (subitem) lpht->iSubItem = 0; - - if (infoPtr->rcList.left > lpht->pt.x) - lpht->flags |= LVHT_TOLEFT; - else if (infoPtr->rcList.right < lpht->pt.x) - lpht->flags |= LVHT_TORIGHT; - - if (infoPtr->rcList.top > lpht->pt.y) - lpht->flags |= LVHT_ABOVE; - else if (infoPtr->rcList.bottom < lpht->pt.y) - lpht->flags |= LVHT_BELOW; - - TRACE("lpht->flags=0x%x\n", lpht->flags); - if (lpht->flags) return -1; - - lpht->flags |= LVHT_NOWHERE; - - LISTVIEW_GetOrigin(infoPtr, &Origin); - - /* first deal with the large items */ - rcSearch.left = lpht->pt.x; - rcSearch.top = lpht->pt.y; - rcSearch.right = rcSearch.left + 1; - rcSearch.bottom = rcSearch.top + 1; - - iterator_frameditems(&i, infoPtr, &rcSearch); - iterator_next(&i); /* go to first item in the sequence */ - iItem = i.nItem; - iterator_destroy(&i); - - TRACE("lpht->iItem=%d\n", iItem); - if (iItem == -1) return -1; - - lvItem.mask = LVIF_STATE | LVIF_TEXT; - if (uView == LVS_REPORT) lvItem.mask |= LVIF_INDENT; - lvItem.stateMask = LVIS_STATEIMAGEMASK; - if (uView == LVS_ICON) lvItem.stateMask |= LVIS_FOCUSED; - lvItem.iItem = iItem; - lvItem.iSubItem = 0; - lvItem.pszText = szDispText; - lvItem.cchTextMax = DISP_TEXT_SIZE; - if (!LISTVIEW_GetItemW(infoPtr, &lvItem)) return -1; - if (!infoPtr->bFocus) lvItem.state &= ~LVIS_FOCUSED; - - LISTVIEW_GetItemMetrics(infoPtr, &lvItem, &rcBox, &rcState, &rcIcon, &rcLabel); - LISTVIEW_GetItemOrigin(infoPtr, iItem, &Position); - opt.x = lpht->pt.x - Position.x - Origin.x; - opt.y = lpht->pt.y - Position.y - Origin.y; - - if (uView == LVS_REPORT) - rcBounds = rcBox; - else - UnionRect(&rcBounds, &rcIcon, &rcLabel); - TRACE("rcBounds=%s\n", debugrect(&rcBounds)); - if (!PtInRect(&rcBounds, opt)) return -1; - - if (PtInRect(&rcIcon, opt)) - lpht->flags |= LVHT_ONITEMICON; - else if (PtInRect(&rcLabel, opt)) - lpht->flags |= LVHT_ONITEMLABEL; - else if (infoPtr->himlState && ((lvItem.state & LVIS_STATEIMAGEMASK) >> 12) && PtInRect(&rcState, opt)) - lpht->flags |= LVHT_ONITEMSTATEICON; - if (lpht->flags & LVHT_ONITEM) - lpht->flags &= ~LVHT_NOWHERE; - - TRACE("lpht->flags=0x%x\n", lpht->flags); - if (uView == LVS_REPORT && subitem) - { - INT j; - - rcBounds.right = rcBounds.left; - for (j = 0; j < DPA_GetPtrCount(infoPtr->hdpaColumns); j++) - { - rcBounds.left = rcBounds.right; - rcBounds.right += LISTVIEW_GetColumnWidth(infoPtr, j); - if (PtInRect(&rcBounds, opt)) - { - lpht->iSubItem = j; - break; - } - } - } - - if (select && !(uView == LVS_REPORT && - ((infoPtr->dwLvExStyle & LVS_EX_FULLROWSELECT) || - (infoPtr->dwStyle & LVS_OWNERDRAWFIXED)))) - { - if (uView == LVS_REPORT) - { - UnionRect(&rcBounds, &rcIcon, &rcLabel); - UnionRect(&rcBounds, &rcBounds, &rcState); - } - if (!PtInRect(&rcBounds, opt)) iItem = -1; - } - return lpht->iItem = iItem; -} - - -/* LISTVIEW_InsertCompare: callback routine for comparing pszText members of the LV_ITEMS - in a LISTVIEW on insert. Passed to DPA_Sort in LISTVIEW_InsertItem. - This function should only be used for inserting items into a sorted list (LVM_INSERTITEM) - and not during the processing of a LVM_SORTITEMS message. Applications should provide - their own sort proc. when sending LVM_SORTITEMS. -*/ -/* Platform SDK: - (remarks on LVITEM: LVM_INSERTITEM will insert the new item in the proper sort postion... - if: - LVS_SORTXXX must be specified, - LVS_OWNERDRAW is not set, - .pszText is not LPSTR_TEXTCALLBACK. - - (LVS_SORT* flags): "For the LVS_SORTASCENDING... styles, item indices - are sorted based on item text..." -*/ -static INT WINAPI LISTVIEW_InsertCompare( LPVOID first, LPVOID second, LPARAM lParam) -{ - ITEM_INFO* lv_first = (ITEM_INFO*) DPA_GetPtr( (HDPA)first, 0 ); - ITEM_INFO* lv_second = (ITEM_INFO*) DPA_GetPtr( (HDPA)second, 0 ); - INT cmpv = textcmpWT(lv_first->hdr.pszText, lv_second->hdr.pszText, TRUE); - - /* if we're sorting descending, negate the return value */ - return (((LISTVIEW_INFO *)lParam)->dwStyle & LVS_SORTDESCENDING) ? -cmpv : cmpv; -} - -/*** - * DESCRIPTION: - * Inserts a new item in the listview control. - * - * PARAMETER(S): - * [I] infoPtr : valid pointer to the listview structure - * [I] lpLVItem : item information - * [I] isW : TRUE if lpLVItem is Unicode, FALSE if it's ANSI - * - * RETURN: - * SUCCESS : new item index - * FAILURE : -1 - */ -static INT LISTVIEW_InsertItemT(LISTVIEW_INFO *infoPtr, const LVITEMW *lpLVItem, BOOL isW) -{ - UINT uView = infoPtr->dwStyle & LVS_TYPEMASK; - INT nItem; - HDPA hdpaSubItems; - NMLISTVIEW nmlv; - ITEM_INFO *lpItem; - BOOL is_sorted, has_changed; - LVITEMW item; - - TRACE("(lpLVItem=%s, isW=%d)\n", debuglvitem_t(lpLVItem, isW), isW); - - if (infoPtr->dwStyle & LVS_OWNERDATA) return infoPtr->nItemCount++; - - /* make sure it's an item, and not a subitem; cannot insert a subitem */ - if (!lpLVItem || lpLVItem->iItem < 0 || lpLVItem->iSubItem) return -1; - - if (!is_assignable_item(lpLVItem, infoPtr->dwStyle)) return -1; - - if (!(lpItem = (ITEM_INFO *)Alloc(sizeof(ITEM_INFO)))) return -1; - - /* insert item in listview control data structure */ - if ( !(hdpaSubItems = DPA_Create(8)) ) goto fail; - if ( !DPA_SetPtr(hdpaSubItems, 0, lpItem) ) assert (FALSE); - - is_sorted = (infoPtr->dwStyle & (LVS_SORTASCENDING | LVS_SORTDESCENDING)) && - !(infoPtr->dwStyle & LVS_OWNERDRAWFIXED) && (LPSTR_TEXTCALLBACKW != lpLVItem->pszText); - - nItem = is_sorted ? infoPtr->nItemCount : min(lpLVItem->iItem, infoPtr->nItemCount); - TRACE(" inserting at %d, sorted=%d, count=%d, iItem=%d\n", nItem, is_sorted, infoPtr->nItemCount, lpLVItem->iItem); - nItem = DPA_InsertPtr( infoPtr->hdpaItems, nItem, hdpaSubItems ); - if (nItem == -1) goto fail; - infoPtr->nItemCount++; - - /* shift indices first so they don't get tangled */ - LISTVIEW_ShiftIndices(infoPtr, nItem, 1); - - /* set the item attributes */ - if (lpLVItem->mask & (LVIF_GROUPID|LVIF_COLUMNS)) - { - /* full size structure expected - _WIN32IE >= 0x560 */ - item = *lpLVItem; - } - else if (lpLVItem->mask & LVIF_INDENT) - { - /* indent member expected - _WIN32IE >= 0x300 */ - memcpy(&item, lpLVItem, offsetof( LVITEMW, iGroupId )); - } - else - { - /* minimal structure expected */ - memcpy(&item, lpLVItem, offsetof( LVITEMW, iIndent )); - } - item.iItem = nItem; - if (infoPtr->dwLvExStyle & LVS_EX_CHECKBOXES) item.state &= ~LVIS_STATEIMAGEMASK; - if (!set_main_item(infoPtr, &item, TRUE, isW, &has_changed)) goto undo; - - /* if we're sorted, sort the list, and update the index */ - if (is_sorted) - { - DPA_Sort( infoPtr->hdpaItems, LISTVIEW_InsertCompare, (LPARAM)infoPtr ); - nItem = DPA_GetPtrIndex( infoPtr->hdpaItems, hdpaSubItems ); - assert(nItem != -1); - } - - /* make room for the position, if we are in the right mode */ - if ((uView == LVS_SMALLICON) || (uView == LVS_ICON)) - { - if (DPA_InsertPtr(infoPtr->hdpaPosX, nItem, 0) == -1) - goto undo; - if (DPA_InsertPtr(infoPtr->hdpaPosY, nItem, 0) == -1) - { - DPA_DeletePtr(infoPtr->hdpaPosX, nItem); - goto undo; - } - } - - /* send LVN_INSERTITEM notification */ - ZeroMemory(&nmlv, sizeof(NMLISTVIEW)); - nmlv.iItem = nItem; - nmlv.lParam = lpItem->lParam; - notify_listview(infoPtr, LVN_INSERTITEM, &nmlv); - - /* align items (set position of each item) */ - if ((uView == LVS_SMALLICON || uView == LVS_ICON)) - { - POINT pt; - - if (infoPtr->dwStyle & LVS_ALIGNLEFT) - LISTVIEW_NextIconPosLeft(infoPtr, &pt); - else - LISTVIEW_NextIconPosTop(infoPtr, &pt); - - LISTVIEW_MoveIconTo(infoPtr, nItem, &pt, TRUE); - } - - /* now is the invalidation fun */ - LISTVIEW_ScrollOnInsert(infoPtr, nItem, 1); - return nItem; - -undo: - LISTVIEW_ShiftIndices(infoPtr, nItem, -1); - DPA_DeletePtr(infoPtr->hdpaItems, nItem); - infoPtr->nItemCount--; -fail: - DPA_DeletePtr(hdpaSubItems, 0); - DPA_Destroy (hdpaSubItems); - Free (lpItem); - return -1; -} - -/*** - * DESCRIPTION: - * Redraws a range of items. - * - * PARAMETER(S): - * [I] infoPtr : valid pointer to the listview structure - * [I] nFirst : first item - * [I] nLast : last item - * - * RETURN: - * SUCCESS : TRUE - * FAILURE : FALSE - */ -static BOOL LISTVIEW_RedrawItems(LISTVIEW_INFO *infoPtr, INT nFirst, INT nLast) -{ - INT i; - - if (nLast < nFirst || min(nFirst, nLast) < 0 || - max(nFirst, nLast) >= infoPtr->nItemCount) - return FALSE; - - for (i = nFirst; i <= nLast; i++) - LISTVIEW_InvalidateItem(infoPtr, i); - - return TRUE; -} - -/*** - * DESCRIPTION: - * Scroll the content of a listview. - * - * PARAMETER(S): - * [I] infoPtr : valid pointer to the listview structure - * [I] dx : horizontal scroll amount in pixels - * [I] dy : vertical scroll amount in pixels - * - * RETURN: - * SUCCESS : TRUE - * FAILURE : FALSE - * - * COMMENTS: - * If the control is in report mode (LVS_REPORT) the control can - * be scrolled only in line increments. "dy" will be rounded to the - * nearest number of pixels that are a whole line. Ex: if line height - * is 16 and an 8 is passed, the list will be scrolled by 16. If a 7 - * is passed the the scroll will be 0. (per MSDN 7/2002) - * - * For: (per experimentaion with native control and CSpy ListView) - * LVS_ICON dy=1 = 1 pixel (vertical only) - * dx ignored - * LVS_SMALLICON dy=1 = 1 pixel (vertical only) - * dx ignored - * LVS_LIST dx=1 = 1 column (horizontal only) - * but will only scroll 1 column per message - * no matter what the value. - * dy must be 0 or FALSE returned. - * LVS_REPORT dx=1 = 1 pixel - * dy= see above - * - */ -static BOOL LISTVIEW_Scroll(LISTVIEW_INFO *infoPtr, INT dx, INT dy) -{ - switch(infoPtr->dwStyle & LVS_TYPEMASK) { - case LVS_REPORT: - dy += (dy < 0 ? -1 : 1) * infoPtr->nItemHeight/2; - dy /= infoPtr->nItemHeight; - break; - case LVS_LIST: - if (dy != 0) return FALSE; - break; - default: /* icon */ - dx = 0; - break; - } - - if (dx != 0) LISTVIEW_HScroll(infoPtr, SB_INTERNAL, dx, 0); - if (dy != 0) LISTVIEW_VScroll(infoPtr, SB_INTERNAL, dy, 0); - - return TRUE; -} - -/*** - * DESCRIPTION: - * Sets the background color. - * - * PARAMETER(S): - * [I] infoPtr : valid pointer to the listview structure - * [I] clrBk : background color - * - * RETURN: - * SUCCESS : TRUE - * FAILURE : FALSE - */ -static BOOL LISTVIEW_SetBkColor(LISTVIEW_INFO *infoPtr, COLORREF clrBk) -{ - TRACE("(clrBk=%lx)\n", clrBk); - - if(infoPtr->clrBk != clrBk) { - if (infoPtr->clrBk != CLR_NONE) DeleteObject(infoPtr->hBkBrush); - infoPtr->clrBk = clrBk; - if (clrBk == CLR_NONE) - infoPtr->hBkBrush = (HBRUSH)GetClassLongW(infoPtr->hwndSelf, GCL_HBRBACKGROUND); - else - infoPtr->hBkBrush = CreateSolidBrush(clrBk); - LISTVIEW_InvalidateList(infoPtr); - } - - return TRUE; -} - -/* LISTVIEW_SetBkImage */ - -/*** Helper for {Insert,Set}ColumnT *only* */ -static void column_fill_hditem(LISTVIEW_INFO *infoPtr, HDITEMW *lphdi, INT nColumn, const LVCOLUMNW *lpColumn, BOOL isW) -{ - if (lpColumn->mask & LVCF_FMT) - { - /* format member is valid */ - lphdi->mask |= HDI_FORMAT; - - /* set text alignment (leftmost column must be left-aligned) */ - if (nColumn == 0 || lpColumn->fmt & LVCFMT_LEFT) - lphdi->fmt |= HDF_LEFT; - else if (lpColumn->fmt & LVCFMT_RIGHT) - lphdi->fmt |= HDF_RIGHT; - else if (lpColumn->fmt & LVCFMT_CENTER) - lphdi->fmt |= HDF_CENTER; - - if (lpColumn->fmt & LVCFMT_BITMAP_ON_RIGHT) - lphdi->fmt |= HDF_BITMAP_ON_RIGHT; - - if (lpColumn->fmt & LVCFMT_COL_HAS_IMAGES) - { - lphdi->fmt |= HDF_IMAGE; - lphdi->iImage = I_IMAGECALLBACK; - } - } - - if (lpColumn->mask & LVCF_WIDTH) - { - lphdi->mask |= HDI_WIDTH; - if(lpColumn->cx == LVSCW_AUTOSIZE_USEHEADER) - { - /* make it fill the remainder of the controls width */ - RECT rcHeader; - INT item_index; - - for(item_index = 0; item_index < (nColumn - 1); item_index++) - { - LISTVIEW_GetHeaderRect(infoPtr, item_index, &rcHeader); - lphdi->cxy += rcHeader.right - rcHeader.left; - } - - /* retrieve the layout of the header */ - GetClientRect(infoPtr->hwndSelf, &rcHeader); - TRACE("start cxy=%d rcHeader=%s\n", lphdi->cxy, debugrect(&rcHeader)); - - lphdi->cxy = (rcHeader.right - rcHeader.left) - lphdi->cxy; - } - else - lphdi->cxy = lpColumn->cx; - } - - if (lpColumn->mask & LVCF_TEXT) - { - lphdi->mask |= HDI_TEXT | HDI_FORMAT; - lphdi->fmt |= HDF_STRING; - lphdi->pszText = lpColumn->pszText; - lphdi->cchTextMax = textlenT(lpColumn->pszText, isW); - } - - if (lpColumn->mask & LVCF_IMAGE) - { - lphdi->mask |= HDI_IMAGE; - lphdi->iImage = lpColumn->iImage; - } - - if (lpColumn->mask & LVCF_ORDER) - { - lphdi->mask |= HDI_ORDER; - lphdi->iOrder = lpColumn->iOrder; - } -} - - -/*** - * DESCRIPTION: - * Inserts a new column. - * - * PARAMETER(S): - * [I] infoPtr : valid pointer to the listview structure - * [I] nColumn : column index - * [I] lpColumn : column information - * [I] isW : TRUE if lpColumn is Unicode, FALSE otherwise - * - * RETURN: - * SUCCESS : new column index - * FAILURE : -1 - */ -static INT LISTVIEW_InsertColumnT(LISTVIEW_INFO *infoPtr, INT nColumn, - const LVCOLUMNW *lpColumn, BOOL isW) -{ - COLUMN_INFO *lpColumnInfo; - INT nNewColumn; - HDITEMW hdi; - - TRACE("(nColumn=%d, lpColumn=%s, isW=%d)\n", nColumn, debuglvcolumn_t(lpColumn, isW), isW); - - if (!lpColumn || nColumn < 0) return -1; - nColumn = min(nColumn, DPA_GetPtrCount(infoPtr->hdpaColumns)); - - ZeroMemory(&hdi, sizeof(HDITEMW)); - column_fill_hditem(infoPtr, &hdi, nColumn, lpColumn, isW); - - /* insert item in header control */ - nNewColumn = SendMessageW(infoPtr->hwndHeader, - isW ? HDM_INSERTITEMW : HDM_INSERTITEMA, - (WPARAM)nColumn, (LPARAM)&hdi); - if (nNewColumn == -1) return -1; - if (nNewColumn != nColumn) ERR("nColumn=%d, nNewColumn=%d\n", nColumn, nNewColumn); - - /* create our own column info */ - if (!(lpColumnInfo = Alloc(sizeof(COLUMN_INFO)))) goto fail; - if (DPA_InsertPtr(infoPtr->hdpaColumns, nNewColumn, lpColumnInfo) == -1) goto fail; - - if (lpColumn->mask & LVCF_FMT) lpColumnInfo->fmt = lpColumn->fmt; - if (!Header_GetItemRect(infoPtr->hwndHeader, nNewColumn, &lpColumnInfo->rcHeader)) goto fail; - - /* now we have to actually adjust the data */ - if (!(infoPtr->dwStyle & LVS_OWNERDATA) && infoPtr->nItemCount > 0) - { - SUBITEM_INFO *lpSubItem; - HDPA hdpaSubItems; - INT nItem, i; - - for (nItem = 0; nItem < infoPtr->nItemCount; nItem++) - { - hdpaSubItems = (HDPA)DPA_GetPtr(infoPtr->hdpaItems, nItem); - for (i = 1; i < DPA_GetPtrCount(hdpaSubItems); i++) - { - lpSubItem = (SUBITEM_INFO *)DPA_GetPtr(hdpaSubItems, i); - if (lpSubItem->iSubItem >= nNewColumn) - lpSubItem->iSubItem++; - } - } - } - - /* make space for the new column */ - LISTVIEW_ScrollColumns(infoPtr, nNewColumn + 1, lpColumnInfo->rcHeader.right - lpColumnInfo->rcHeader.left); - - return nNewColumn; - -fail: - if (nNewColumn != -1) SendMessageW(infoPtr->hwndHeader, HDM_DELETEITEM, nNewColumn, 0); - if (lpColumnInfo) - { - DPA_DeletePtr(infoPtr->hdpaColumns, nNewColumn); - Free(lpColumnInfo); - } - return -1; -} - -/*** - * DESCRIPTION: - * Sets the attributes of a header item. - * - * PARAMETER(S): - * [I] infoPtr : valid pointer to the listview structure - * [I] nColumn : column index - * [I] lpColumn : column attributes - * [I] isW: if TRUE, the lpColumn is a LPLVCOLUMNW, else it is a LPLVCOLUMNA - * - * RETURN: - * SUCCESS : TRUE - * FAILURE : FALSE - */ -static BOOL LISTVIEW_SetColumnT(LISTVIEW_INFO *infoPtr, INT nColumn, - const LVCOLUMNW *lpColumn, BOOL isW) -{ - HDITEMW hdi, hdiget; - BOOL bResult; - - TRACE("(nColumn=%d, lpColumn=%s, isW=%d)\n", nColumn, debuglvcolumn_t(lpColumn, isW), isW); - - if (!lpColumn || nColumn < 0 || nColumn >= DPA_GetPtrCount(infoPtr->hdpaColumns)) return FALSE; - - ZeroMemory(&hdi, sizeof(HDITEMW)); - if (lpColumn->mask & LVCF_FMT) - { - hdi.mask |= HDI_FORMAT; - hdiget.mask = HDI_FORMAT; - if (Header_GetItemW(infoPtr->hwndHeader, nColumn, &hdiget)) - hdi.fmt = hdiget.fmt & HDF_STRING; - } - column_fill_hditem(infoPtr, &hdi, nColumn, lpColumn, isW); - - /* set header item attributes */ - bResult = SendMessageW(infoPtr->hwndHeader, isW ? HDM_SETITEMW : HDM_SETITEMA, (WPARAM)nColumn, (LPARAM)&hdi); - if (!bResult) return FALSE; - - if (lpColumn->mask & LVCF_FMT) - { - COLUMN_INFO *lpColumnInfo = LISTVIEW_GetColumnInfo(infoPtr, nColumn); - int oldFmt = lpColumnInfo->fmt; - - lpColumnInfo->fmt = lpColumn->fmt; - if ((oldFmt ^ lpColumn->fmt) & (LVCFMT_JUSTIFYMASK | LVCFMT_IMAGE)) - { - UINT uView = infoPtr->dwStyle & LVS_TYPEMASK; - if (uView == LVS_REPORT) LISTVIEW_InvalidateColumn(infoPtr, nColumn); - } - } - - return TRUE; -} - -/*** - * DESCRIPTION: - * Sets the column order array - * - * PARAMETERS: - * [I] infoPtr : valid pointer to the listview structure - * [I] iCount : number of elements in column order array - * [I] lpiArray : pointer to column order array - * - * RETURN: - * SUCCESS : TRUE - * FAILURE : FALSE - */ -static BOOL LISTVIEW_SetColumnOrderArray(LISTVIEW_INFO *infoPtr, INT iCount, const INT *lpiArray) -{ - FIXME("iCount %d lpiArray %p\n", iCount, lpiArray); - - if (!lpiArray) - return FALSE; - - return TRUE; -} - - -/*** - * DESCRIPTION: - * Sets the width of a column - * - * PARAMETERS: - * [I] infoPtr : valid pointer to the listview structure - * [I] nColumn : column index - * [I] cx : column width - * - * RETURN: - * SUCCESS : TRUE - * FAILURE : FALSE - */ -static BOOL LISTVIEW_SetColumnWidth(LISTVIEW_INFO *infoPtr, INT nColumn, INT cx) -{ - UINT uView = infoPtr->dwStyle & LVS_TYPEMASK; - WCHAR szDispText[DISP_TEXT_SIZE] = { 0 }; - INT max_cx = 0; - HDITEMW hdi; - - TRACE("(nColumn=%d, cx=%d\n", nColumn, cx); - - /* set column width only if in report or list mode */ - if (uView != LVS_REPORT && uView != LVS_LIST) return FALSE; - - /* take care of invalid cx values */ - if(uView == LVS_REPORT && cx < -2) cx = LVSCW_AUTOSIZE; - else if (uView == LVS_LIST && cx < 1) return FALSE; - - /* resize all columns if in LVS_LIST mode */ - if(uView == LVS_LIST) - { - infoPtr->nItemWidth = cx; - LISTVIEW_InvalidateList(infoPtr); - return TRUE; - } - - if (nColumn < 0 || nColumn >= DPA_GetPtrCount(infoPtr->hdpaColumns)) return FALSE; - - if (cx == LVSCW_AUTOSIZE || (cx == LVSCW_AUTOSIZE_USEHEADER && nColumn < DPA_GetPtrCount(infoPtr->hdpaColumns) -1)) - { - INT nLabelWidth; - LVITEMW lvItem; - - lvItem.mask = LVIF_TEXT; - lvItem.iItem = 0; - lvItem.iSubItem = nColumn; - lvItem.pszText = szDispText; - lvItem.cchTextMax = DISP_TEXT_SIZE; - for (; lvItem.iItem < infoPtr->nItemCount; lvItem.iItem++) - { - if (!LISTVIEW_GetItemW(infoPtr, &lvItem)) continue; - nLabelWidth = LISTVIEW_GetStringWidthT(infoPtr, lvItem.pszText, TRUE); - if (max_cx < nLabelWidth) max_cx = nLabelWidth; - } - if (infoPtr->himlSmall && (nColumn == 0 || (LISTVIEW_GetColumnInfo(infoPtr, nColumn)->fmt & LVCFMT_IMAGE))) - max_cx += infoPtr->iconSize.cx; - max_cx += TRAILING_LABEL_PADDING; - } - - /* autosize based on listview items width */ - if(cx == LVSCW_AUTOSIZE) - cx = max_cx; - else if(cx == LVSCW_AUTOSIZE_USEHEADER) - { - /* if iCol is the last column make it fill the remainder of the controls width */ - if(nColumn == DPA_GetPtrCount(infoPtr->hdpaColumns) - 1) - { - RECT rcHeader; - POINT Origin; - - LISTVIEW_GetOrigin(infoPtr, &Origin); - LISTVIEW_GetHeaderRect(infoPtr, nColumn, &rcHeader); - - cx = infoPtr->rcList.right - Origin.x - rcHeader.left; - } - else - { - /* Despite what the MS docs say, if this is not the last - column, then MS resizes the column to the width of the - largest text string in the column, including headers - and items. This is different from LVSCW_AUTOSIZE in that - LVSCW_AUTOSIZE ignores the header string length. */ - cx = 0; - - /* retrieve header text */ - hdi.mask = HDI_TEXT; - hdi.cchTextMax = DISP_TEXT_SIZE; - hdi.pszText = szDispText; - if (Header_GetItemW(infoPtr->hwndHeader, nColumn, (LPARAM)&hdi)) - { - HDC hdc = GetDC(infoPtr->hwndSelf); - HFONT old_font = SelectObject(hdc, (HFONT)SendMessageW(infoPtr->hwndHeader, WM_GETFONT, 0, 0)); - SIZE size; - - if (GetTextExtentPoint32W(hdc, hdi.pszText, lstrlenW(hdi.pszText), &size)) - cx = size.cx + TRAILING_HEADER_PADDING; - /* FIXME: Take into account the header image, if one is present */ - SelectObject(hdc, old_font); - ReleaseDC(infoPtr->hwndSelf, hdc); - } - cx = max (cx, max_cx); - } - } - - if (cx < 0) return FALSE; - - /* call header to update the column change */ - hdi.mask = HDI_WIDTH; - hdi.cxy = cx; - TRACE("hdi.cxy=%d\n", hdi.cxy); - return Header_SetItemW(infoPtr->hwndHeader, nColumn, (LPARAM)&hdi); -} - -/*** - * Creates the checkbox imagelist. Helper for LISTVIEW_SetExtendedListViewStyle - * - */ -static HIMAGELIST LISTVIEW_CreateCheckBoxIL(LISTVIEW_INFO *infoPtr) -{ - HDC hdc_wnd, hdc; - HBITMAP hbm_im, hbm_mask, hbm_orig; - RECT rc; - HBRUSH hbr_white = GetStockObject(WHITE_BRUSH); - HBRUSH hbr_black = GetStockObject(BLACK_BRUSH); - HIMAGELIST himl; - - himl = ImageList_Create(GetSystemMetrics(SM_CXSMICON), GetSystemMetrics(SM_CYSMICON), - ILC_COLOR | ILC_MASK, 2, 2); - hdc_wnd = GetDC(infoPtr->hwndSelf); - hdc = CreateCompatibleDC(hdc_wnd); - hbm_im = CreateCompatibleBitmap(hdc_wnd, GetSystemMetrics(SM_CXSMICON), GetSystemMetrics(SM_CYSMICON)); - hbm_mask = CreateBitmap(GetSystemMetrics(SM_CXSMICON), GetSystemMetrics(SM_CYSMICON), 1, 1, NULL); - ReleaseDC(infoPtr->hwndSelf, hdc_wnd); - - rc.left = rc.top = 0; - rc.right = GetSystemMetrics(SM_CXSMICON); - rc.bottom = GetSystemMetrics(SM_CYSMICON); - - hbm_orig = SelectObject(hdc, hbm_mask); - FillRect(hdc, &rc, hbr_white); - InflateRect(&rc, -3, -3); - FillRect(hdc, &rc, hbr_black); - - SelectObject(hdc, hbm_im); - DrawFrameControl(hdc, &rc, DFC_BUTTON, DFCS_BUTTONCHECK | DFCS_MONO); - SelectObject(hdc, hbm_orig); - ImageList_Add(himl, hbm_im, hbm_mask); - - SelectObject(hdc, hbm_im); - DrawFrameControl(hdc, &rc, DFC_BUTTON, DFCS_BUTTONCHECK | DFCS_MONO | DFCS_CHECKED); - SelectObject(hdc, hbm_orig); - ImageList_Add(himl, hbm_im, hbm_mask); - - DeleteObject(hbm_mask); - DeleteObject(hbm_im); - DeleteDC(hdc); - - return himl; -} - -/*** - * DESCRIPTION: - * Sets the extended listview style. - * - * PARAMETERS: - * [I] infoPtr : valid pointer to the listview structure - * [I] dwMask : mask - * [I] dwStyle : style - * - * RETURN: - * SUCCESS : previous style - * FAILURE : 0 - */ -static DWORD LISTVIEW_SetExtendedListViewStyle(LISTVIEW_INFO *infoPtr, DWORD dwMask, DWORD dwStyle) -{ - DWORD dwOldStyle = infoPtr->dwLvExStyle; - - /* set new style */ - if (dwMask) - infoPtr->dwLvExStyle = (dwOldStyle & ~dwMask) | (dwStyle & dwMask); - else - infoPtr->dwLvExStyle = dwStyle; - - if((infoPtr->dwLvExStyle ^ dwOldStyle) & LVS_EX_CHECKBOXES) - { - HIMAGELIST himl = 0; - if(infoPtr->dwLvExStyle & LVS_EX_CHECKBOXES) - himl = LISTVIEW_CreateCheckBoxIL(infoPtr); - LISTVIEW_SetImageList(infoPtr, LVSIL_STATE, himl); - } - - return dwOldStyle; -} - -/*** - * DESCRIPTION: - * Sets the new hot cursor used during hot tracking and hover selection. - * - * PARAMETER(S): - * [I] infoPtr : valid pointer to the listview structure - * [I} hCurosr : the new hot cursor handle - * - * RETURN: - * Returns the previous hot cursor - */ -static HCURSOR LISTVIEW_SetHotCursor(LISTVIEW_INFO *infoPtr, HCURSOR hCursor) -{ - HCURSOR oldCursor = infoPtr->hHotCursor; - - infoPtr->hHotCursor = hCursor; - - return oldCursor; -} - - -/*** - * DESCRIPTION: - * Sets the hot item index. - * - * PARAMETERS: - * [I] infoPtr : valid pointer to the listview structure - * [I] iIndex : index - * - * RETURN: - * SUCCESS : previous hot item index - * FAILURE : -1 (no hot item) - */ -static INT LISTVIEW_SetHotItem(LISTVIEW_INFO *infoPtr, INT iIndex) -{ - INT iOldIndex = infoPtr->nHotItem; - - infoPtr->nHotItem = iIndex; - - return iOldIndex; -} - - -/*** - * DESCRIPTION: - * Sets the amount of time the cursor must hover over an item before it is selected. - * - * PARAMETER(S): - * [I] infoPtr : valid pointer to the listview structure - * [I] dwHoverTime : hover time, if -1 the hover time is set to the default - * - * RETURN: - * Returns the previous hover time - */ -static DWORD LISTVIEW_SetHoverTime(LISTVIEW_INFO *infoPtr, DWORD dwHoverTime) -{ - DWORD oldHoverTime = infoPtr->dwHoverTime; - - infoPtr->dwHoverTime = dwHoverTime; - - return oldHoverTime; -} - -/*** - * DESCRIPTION: - * Sets spacing for icons of LVS_ICON style. - * - * PARAMETER(S): - * [I] infoPtr : valid pointer to the listview structure - * [I] cx : horizontal spacing (-1 = system spacing, 0 = autosize) - * [I] cy : vertical spacing (-1 = system spacing, 0 = autosize) - * - * RETURN: - * MAKELONG(oldcx, oldcy) - */ -static DWORD LISTVIEW_SetIconSpacing(LISTVIEW_INFO *infoPtr, INT cx, INT cy) -{ - DWORD oldspacing = MAKELONG(infoPtr->iconSpacing.cx, infoPtr->iconSpacing.cy); - UINT uView = infoPtr->dwStyle & LVS_TYPEMASK; - - TRACE("requested=(%d,%d)\n", cx, cy); - - /* this is supported only for LVS_ICON style */ - if (uView != LVS_ICON) return oldspacing; - - /* set to defaults, if instructed to */ - if (cx == -1) cx = GetSystemMetrics(SM_CXICONSPACING); - if (cy == -1) cy = GetSystemMetrics(SM_CYICONSPACING); - - /* if 0 then compute width - * FIXME: Should scan each item and determine max width of - * icon or label, then make that the width */ - if (cx == 0) - cx = infoPtr->iconSpacing.cx; - - /* if 0 then compute height */ - if (cy == 0) - cy = infoPtr->iconSize.cy + 2 * infoPtr->ntmHeight + - ICON_BOTTOM_PADDING + ICON_TOP_PADDING + LABEL_VERT_PADDING; - - - infoPtr->iconSpacing.cx = cx; - infoPtr->iconSpacing.cy = cy; - - TRACE("old=(%d,%d), new=(%d,%d), iconSize=(%ld,%ld), ntmH=%d\n", - LOWORD(oldspacing), HIWORD(oldspacing), cx, cy, - infoPtr->iconSize.cx, infoPtr->iconSize.cy, - infoPtr->ntmHeight); - - /* these depend on the iconSpacing */ - LISTVIEW_UpdateItemSize(infoPtr); - - return oldspacing; -} - -inline void set_icon_size(SIZE *size, HIMAGELIST himl, BOOL small) -{ - INT cx, cy; - - if (himl && ImageList_GetIconSize(himl, &cx, &cy)) - { - size->cx = cx; - size->cy = cy; - } - else - { - size->cx = GetSystemMetrics(small ? SM_CXSMICON : SM_CXICON); - size->cy = GetSystemMetrics(small ? SM_CYSMICON : SM_CYICON); - } -} - -/*** - * DESCRIPTION: - * Sets image lists. - * - * PARAMETER(S): - * [I] infoPtr : valid pointer to the listview structure - * [I] nType : image list type - * [I] himl : image list handle - * - * RETURN: - * SUCCESS : old image list - * FAILURE : NULL - */ -static HIMAGELIST LISTVIEW_SetImageList(LISTVIEW_INFO *infoPtr, INT nType, HIMAGELIST himl) -{ - UINT uView = infoPtr->dwStyle & LVS_TYPEMASK; - INT oldHeight = infoPtr->nItemHeight; - HIMAGELIST himlOld = 0; - - TRACE("(nType=%d, himl=%p\n", nType, himl); - - switch (nType) - { - case LVSIL_NORMAL: - himlOld = infoPtr->himlNormal; - infoPtr->himlNormal = himl; - if (uView == LVS_ICON) set_icon_size(&infoPtr->iconSize, himl, FALSE); - LISTVIEW_SetIconSpacing(infoPtr, 0, 0); - break; - - case LVSIL_SMALL: - himlOld = infoPtr->himlSmall; - infoPtr->himlSmall = himl; - if (uView != LVS_ICON) set_icon_size(&infoPtr->iconSize, himl, TRUE); - break; - - case LVSIL_STATE: - himlOld = infoPtr->himlState; - infoPtr->himlState = himl; - set_icon_size(&infoPtr->iconStateSize, himl, TRUE); - ImageList_SetBkColor(infoPtr->himlState, CLR_NONE); - break; - - default: - ERR("Unknown icon type=%d\n", nType); - return NULL; - } - - infoPtr->nItemHeight = LISTVIEW_CalculateItemHeight(infoPtr); - if (infoPtr->nItemHeight != oldHeight) - LISTVIEW_UpdateScroll(infoPtr); - - return himlOld; -} - -/*** - * DESCRIPTION: - * Preallocates memory (does *not* set the actual count of items !) - * - * PARAMETER(S): - * [I] infoPtr : valid pointer to the listview structure - * [I] nItems : item count (projected number of items to allocate) - * [I] dwFlags : update flags - * - * RETURN: - * SUCCESS : TRUE - * FAILURE : FALSE - */ -static BOOL LISTVIEW_SetItemCount(LISTVIEW_INFO *infoPtr, INT nItems, DWORD dwFlags) -{ - TRACE("(nItems=%d, dwFlags=%lx)\n", nItems, dwFlags); - - if (infoPtr->dwStyle & LVS_OWNERDATA) - { - UINT uView = infoPtr->dwStyle & LVS_TYPEMASK; - INT nOldCount = infoPtr->nItemCount; - - if (nItems < nOldCount) - { - RANGE range = { nItems, nOldCount }; - ranges_del(infoPtr->selectionRanges, range); - if (infoPtr->nFocusedItem >= nItems) - { - infoPtr->nFocusedItem = -1; - SetRectEmpty(&infoPtr->rcFocus); - } - } - - infoPtr->nItemCount = nItems; - LISTVIEW_UpdateScroll(infoPtr); - - /* the flags are valid only in ownerdata report and list modes */ - if (uView == LVS_ICON || uView == LVS_SMALLICON) dwFlags = 0; - - if (!(dwFlags & LVSICF_NOSCROLL) && infoPtr->nFocusedItem != -1) - LISTVIEW_EnsureVisible(infoPtr, infoPtr->nFocusedItem, FALSE); - - if (!(dwFlags & LVSICF_NOINVALIDATEALL)) - LISTVIEW_InvalidateList(infoPtr); - else - { - INT nFrom, nTo; - POINT Origin; - RECT rcErase; - - LISTVIEW_GetOrigin(infoPtr, &Origin); - nFrom = min(nOldCount, nItems); - nTo = max(nOldCount, nItems); - - if (uView == LVS_REPORT) - { - rcErase.left = 0; - rcErase.top = nFrom * infoPtr->nItemHeight; - rcErase.right = infoPtr->nItemWidth; - rcErase.bottom = nTo * infoPtr->nItemHeight; - OffsetRect(&rcErase, Origin.x, Origin.y); - if (IntersectRect(&rcErase, &rcErase, &infoPtr->rcList)) - LISTVIEW_InvalidateRect(infoPtr, &rcErase); - } - else /* LVS_LIST */ - { - INT nPerCol = LISTVIEW_GetCountPerColumn(infoPtr); - - rcErase.left = (nFrom / nPerCol) * infoPtr->nItemWidth; - rcErase.top = (nFrom % nPerCol) * infoPtr->nItemHeight; - rcErase.right = rcErase.left + infoPtr->nItemWidth; - rcErase.bottom = nPerCol * infoPtr->nItemHeight; - OffsetRect(&rcErase, Origin.x, Origin.y); - if (IntersectRect(&rcErase, &rcErase, &infoPtr->rcList)) - LISTVIEW_InvalidateRect(infoPtr, &rcErase); - - rcErase.left = (nFrom / nPerCol + 1) * infoPtr->nItemWidth; - rcErase.top = 0; - rcErase.right = (nTo / nPerCol + 1) * infoPtr->nItemWidth; - rcErase.bottom = nPerCol * infoPtr->nItemHeight; - OffsetRect(&rcErase, Origin.x, Origin.y); - if (IntersectRect(&rcErase, &rcErase, &infoPtr->rcList)) - LISTVIEW_InvalidateRect(infoPtr, &rcErase); - } - } - } - else - { - /* According to MSDN for non-LVS_OWNERDATA this is just - * a performance issue. The control allocates its internal - * data structures for the number of items specified. It - * cuts down on the number of memory allocations. Therefore - * we will just issue a WARN here - */ - WARN("for non-ownerdata performance option not implemented.\n"); - } - - return TRUE; -} - -/*** - * DESCRIPTION: - * Sets the position of an item. - * - * PARAMETER(S): - * [I] infoPtr : valid pointer to the listview structure - * [I] nItem : item index - * [I] pt : coordinate - * - * RETURN: - * SUCCESS : TRUE - * FAILURE : FALSE - */ -static BOOL LISTVIEW_SetItemPosition(LISTVIEW_INFO *infoPtr, INT nItem, POINT pt) -{ - UINT uView = infoPtr->dwStyle & LVS_TYPEMASK; - POINT Origin; - - TRACE("(nItem=%d, &pt=%s\n", nItem, debugpoint(&pt)); - - if (nItem < 0 || nItem >= infoPtr->nItemCount || - !(uView == LVS_ICON || uView == LVS_SMALLICON)) return FALSE; - - LISTVIEW_GetOrigin(infoPtr, &Origin); - - /* This point value seems to be an undocumented feature. - * The best guess is that it means either at the origin, - * or at true beginning of the list. I will assume the origin. */ - if ((pt.x == -1) && (pt.y == -1)) - pt = Origin; - - if (uView == LVS_ICON) - { - pt.x -= (infoPtr->nItemWidth - infoPtr->iconSize.cx) / 2; - pt.y -= ICON_TOP_PADDING; - } - pt.x -= Origin.x; - pt.y -= Origin.y; - - infoPtr->bAutoarrange = FALSE; - - return LISTVIEW_MoveIconTo(infoPtr, nItem, &pt, FALSE); -} - -/*** - * DESCRIPTION: - * Sets the state of one or many items. - * - * PARAMETER(S): - * [I] infoPtr : valid pointer to the listview structure - * [I] nItem : item index - * [I] lpLVItem : item or subitem info - * - * RETURN: - * SUCCESS : TRUE - * FAILURE : FALSE - */ -static BOOL LISTVIEW_SetItemState(LISTVIEW_INFO *infoPtr, INT nItem, const LVITEMW *lpLVItem) -{ - BOOL bResult = TRUE; - LVITEMW lvItem; - - lvItem.iItem = nItem; - lvItem.iSubItem = 0; - lvItem.mask = LVIF_STATE; - lvItem.state = lpLVItem->state; - lvItem.stateMask = lpLVItem->stateMask; - TRACE("lvItem=%s\n", debuglvitem_t(&lvItem, TRUE)); - - if (nItem == -1) - { - /* apply to all items */ - for (lvItem.iItem = 0; lvItem.iItem < infoPtr->nItemCount; lvItem.iItem++) - if (!LISTVIEW_SetItemT(infoPtr, &lvItem, TRUE)) bResult = FALSE; - } - else - bResult = LISTVIEW_SetItemT(infoPtr, &lvItem, TRUE); - - /* - *update selection mark - * - * Investigation on windows 2k showed that selection mark was updated - * whenever a new selection was made, but if the selected item was - * unselected it was not updated. - * - * we are probably still not 100% accurate, but this at least sets the - * proper selection mark when it is needed - */ - - if (bResult && (lvItem.state & lvItem.stateMask & LVIS_SELECTED) && - ((infoPtr->nSelectionMark == -1) || (lvItem.iItem <= infoPtr->nSelectionMark))) - { - int i; - infoPtr->nSelectionMark = -1; - for (i = 0; i < infoPtr->nItemCount; i++) - { - if (infoPtr->uCallbackMask & LVIS_SELECTED) - { - if (LISTVIEW_GetItemState(infoPtr, i, LVIS_SELECTED)) - { - infoPtr->nSelectionMark = i; - break; - } - } - else if (ranges_contain(infoPtr->selectionRanges, i)) - { - infoPtr->nSelectionMark = i; - break; - } - } - } - - return bResult; -} - -/*** - * DESCRIPTION: - * Sets the text of an item or subitem. - * - * PARAMETER(S): - * [I] hwnd : window handle - * [I] nItem : item index - * [I] lpLVItem : item or subitem info - * [I] isW : TRUE if input is Unicode - * - * RETURN: - * SUCCESS : TRUE - * FAILURE : FALSE - */ -static BOOL LISTVIEW_SetItemTextT(LISTVIEW_INFO *infoPtr, INT nItem, const LVITEMW *lpLVItem, BOOL isW) -{ - LVITEMW lvItem; - - if (nItem < 0 && nItem >= infoPtr->nItemCount) return FALSE; - - lvItem.iItem = nItem; - lvItem.iSubItem = lpLVItem->iSubItem; - lvItem.mask = LVIF_TEXT; - lvItem.pszText = lpLVItem->pszText; - lvItem.cchTextMax = lpLVItem->cchTextMax; - - TRACE("(nItem=%d, lpLVItem=%s, isW=%d)\n", nItem, debuglvitem_t(&lvItem, isW), isW); - - return LISTVIEW_SetItemT(infoPtr, &lvItem, isW); -} - -/*** - * DESCRIPTION: - * Set item index that marks the start of a multiple selection. - * - * PARAMETER(S): - * [I] infoPtr : valid pointer to the listview structure - * [I] nIndex : index - * - * RETURN: - * Index number or -1 if there is no selection mark. - */ -static INT LISTVIEW_SetSelectionMark(LISTVIEW_INFO *infoPtr, INT nIndex) -{ - INT nOldIndex = infoPtr->nSelectionMark; - - TRACE("(nIndex=%d)\n", nIndex); - - infoPtr->nSelectionMark = nIndex; - - return nOldIndex; -} - -/*** - * DESCRIPTION: - * Sets the text background color. - * - * PARAMETER(S): - * [I] infoPtr : valid pointer to the listview structure - * [I] clrTextBk : text background color - * - * RETURN: - * SUCCESS : TRUE - * FAILURE : FALSE - */ -static BOOL LISTVIEW_SetTextBkColor(LISTVIEW_INFO *infoPtr, COLORREF clrTextBk) -{ - TRACE("(clrTextBk=%lx)\n", clrTextBk); - - if (infoPtr->clrTextBk != clrTextBk) - { - infoPtr->clrTextBk = clrTextBk; - LISTVIEW_InvalidateList(infoPtr); - } - - return TRUE; -} - -/*** - * DESCRIPTION: - * Sets the text foreground color. - * - * PARAMETER(S): - * [I] infoPtr : valid pointer to the listview structure - * [I] clrText : text color - * - * RETURN: - * SUCCESS : TRUE - * FAILURE : FALSE - */ -static BOOL LISTVIEW_SetTextColor (LISTVIEW_INFO *infoPtr, COLORREF clrText) -{ - TRACE("(clrText=%lx)\n", clrText); - - if (infoPtr->clrText != clrText) - { - infoPtr->clrText = clrText; - LISTVIEW_InvalidateList(infoPtr); - } - - return TRUE; -} - -/*** - * DESCRIPTION: - * Determines which listview item is located at the specified position. - * - * PARAMETER(S): - * [I] infoPtr : valid pointer to the listview structure - * [I] hwndNewToolTip : handle to new ToolTip - * - * RETURN: - * old tool tip - */ -static HWND LISTVIEW_SetToolTips( LISTVIEW_INFO *infoPtr, HWND hwndNewToolTip) -{ - HWND hwndOldToolTip = infoPtr->hwndToolTip; - infoPtr->hwndToolTip = hwndNewToolTip; - return hwndOldToolTip; -} - -/* LISTVIEW_SetUnicodeFormat */ -/* LISTVIEW_SetWorkAreas */ - -/*** - * DESCRIPTION: - * Callback internally used by LISTVIEW_SortItems() - * - * PARAMETER(S): - * [I] first : pointer to first ITEM_INFO to compare - * [I] second : pointer to second ITEM_INFO to compare - * [I] lParam : HWND of control - * - * RETURN: - * if first comes before second : negative - * if first comes after second : positive - * if first and second are equivalent : zero - */ -static INT WINAPI LISTVIEW_CallBackCompare(LPVOID first, LPVOID second, LPARAM lParam) -{ - LISTVIEW_INFO *infoPtr = (LISTVIEW_INFO *)lParam; - ITEM_INFO* lv_first = (ITEM_INFO*) DPA_GetPtr( (HDPA)first, 0 ); - ITEM_INFO* lv_second = (ITEM_INFO*) DPA_GetPtr( (HDPA)second, 0 ); - - /* Forward the call to the client defined callback */ - return (infoPtr->pfnCompare)( lv_first->lParam , lv_second->lParam, infoPtr->lParamSort ); -} - -/*** - * DESCRIPTION: - * Sorts the listview items. - * - * PARAMETER(S): - * [I] infoPtr : valid pointer to the listview structure - * [I] pfnCompare : application-defined value - * [I] lParamSort : pointer to comparision callback - * - * RETURN: - * SUCCESS : TRUE - * FAILURE : FALSE - */ -static BOOL LISTVIEW_SortItems(LISTVIEW_INFO *infoPtr, PFNLVCOMPARE pfnCompare, LPARAM lParamSort) -{ - UINT uView = infoPtr->dwStyle & LVS_TYPEMASK; - HDPA hdpaSubItems; - ITEM_INFO *lpItem; - LPVOID selectionMarkItem; - LVITEMW item; - int i; - - TRACE("(pfnCompare=%p, lParamSort=%lx)\n", pfnCompare, lParamSort); - - if (infoPtr->dwStyle & LVS_OWNERDATA) return FALSE; - - if (!pfnCompare) return FALSE; - if (!infoPtr->hdpaItems) return FALSE; - - /* if there are 0 or 1 items, there is no need to sort */ - if (infoPtr->nItemCount < 2) return TRUE; - - if (infoPtr->nFocusedItem >= 0) - { - hdpaSubItems = (HDPA)DPA_GetPtr(infoPtr->hdpaItems, infoPtr->nFocusedItem); - lpItem = (ITEM_INFO *)DPA_GetPtr(hdpaSubItems, 0); - if (lpItem) lpItem->state |= LVIS_FOCUSED; - } - /* FIXME: go thorugh selected items and mark them so in lpItem->state */ - /* clear the lpItem->state for non-selected ones */ - /* remove the selection ranges */ - - infoPtr->pfnCompare = pfnCompare; - infoPtr->lParamSort = lParamSort; - DPA_Sort(infoPtr->hdpaItems, LISTVIEW_CallBackCompare, (LPARAM)infoPtr); - - /* Adjust selections and indices so that they are the way they should - * be after the sort (otherwise, the list items move around, but - * whatever is at the item's previous original position will be - * selected instead) - */ - selectionMarkItem=(infoPtr->nSelectionMark>=0)?DPA_GetPtr(infoPtr->hdpaItems, infoPtr->nSelectionMark):NULL; - for (i=0; i < infoPtr->nItemCount; i++) - { - hdpaSubItems = (HDPA)DPA_GetPtr(infoPtr->hdpaItems, i); - lpItem = (ITEM_INFO *)DPA_GetPtr(hdpaSubItems, 0); - - if (lpItem->state & LVIS_SELECTED) - { - item.state = LVIS_SELECTED; - item.stateMask = LVIS_SELECTED; - LISTVIEW_SetItemState(infoPtr, i, &item); - } - if (lpItem->state & LVIS_FOCUSED) - { - infoPtr->nFocusedItem = i; - lpItem->state &= ~LVIS_FOCUSED; - } - } - if (selectionMarkItem != NULL) - infoPtr->nSelectionMark = DPA_GetPtrIndex(infoPtr->hdpaItems, selectionMarkItem); - /* I believe nHotItem should be left alone, see LISTVIEW_ShiftIndices */ - - /* refresh the display */ - if (uView != LVS_ICON && uView != LVS_SMALLICON) - LISTVIEW_InvalidateList(infoPtr); - - return TRUE; -} - -/*** - * DESCRIPTION: - * Updates an items or rearranges the listview control. - * - * PARAMETER(S): - * [I] infoPtr : valid pointer to the listview structure - * [I] nItem : item index - * - * RETURN: - * SUCCESS : TRUE - * FAILURE : FALSE - */ -static BOOL LISTVIEW_Update(LISTVIEW_INFO *infoPtr, INT nItem) -{ - TRACE("(nItem=%d)\n", nItem); - - if (nItem < 0 || nItem >= infoPtr->nItemCount) return FALSE; - - /* rearrange with default alignment style */ - if (is_autoarrange(infoPtr)) - LISTVIEW_Arrange(infoPtr, LVA_DEFAULT); - else - LISTVIEW_InvalidateItem(infoPtr, nItem); - - return TRUE; -} - - -/*** - * DESCRIPTION: - * Creates the listview control. - * - * PARAMETER(S): - * [I] hwnd : window handle - * [I] lpcs : the create parameters - * - * RETURN: - * Success: 0 - * Failure: -1 - */ -static LRESULT LISTVIEW_Create(HWND hwnd, const CREATESTRUCTW *lpcs) -{ - LISTVIEW_INFO *infoPtr; - UINT uView = lpcs->style & LVS_TYPEMASK; - LOGFONTW logFont; - - TRACE("(lpcs=%p)\n", lpcs); - - /* initialize info pointer */ - infoPtr = (LISTVIEW_INFO *)Alloc(sizeof(LISTVIEW_INFO)); - if (!infoPtr) return -1; - - SetWindowLongPtrW(hwnd, 0, (DWORD_PTR)infoPtr); - - infoPtr->hwndSelf = hwnd; - infoPtr->dwStyle = lpcs->style; - /* determine the type of structures to use */ - infoPtr->hwndNotify = lpcs->hwndParent; - infoPtr->notifyFormat = SendMessageW(infoPtr->hwndNotify, WM_NOTIFYFORMAT, - (WPARAM)infoPtr->hwndSelf, (LPARAM)NF_QUERY); - - /* initialize color information */ - infoPtr->clrBk = CLR_NONE; - infoPtr->clrText = comctl32_color.clrWindowText; - infoPtr->clrTextBk = CLR_DEFAULT; - LISTVIEW_SetBkColor(infoPtr, comctl32_color.clrWindow); - - /* set default values */ - infoPtr->nFocusedItem = -1; - infoPtr->nSelectionMark = -1; - infoPtr->nHotItem = -1; - infoPtr->bRedraw = TRUE; - infoPtr->bNoItemMetrics = TRUE; - infoPtr->bDoChangeNotify = TRUE; - infoPtr->iconSpacing.cx = GetSystemMetrics(SM_CXICONSPACING); - infoPtr->iconSpacing.cy = GetSystemMetrics(SM_CYICONSPACING); - infoPtr->nEditLabelItem = -1; - infoPtr->dwHoverTime = -1; /* default system hover time */ - - /* get default font (icon title) */ - SystemParametersInfoW(SPI_GETICONTITLELOGFONT, 0, &logFont, 0); - infoPtr->hDefaultFont = CreateFontIndirectW(&logFont); - infoPtr->hFont = infoPtr->hDefaultFont; - LISTVIEW_SaveTextMetrics(infoPtr); - - /* create header */ - infoPtr->hwndHeader = CreateWindowW(WC_HEADERW, NULL, - WS_CHILD | HDS_HORZ | (DWORD)((LVS_NOSORTHEADER & lpcs->style)?0:HDS_BUTTONS), - 0, 0, 0, 0, hwnd, NULL, - lpcs->hInstance, NULL); - if (!infoPtr->hwndHeader) goto fail; - - /* set header unicode format */ - SendMessageW(infoPtr->hwndHeader, HDM_SETUNICODEFORMAT, (WPARAM)TRUE, (LPARAM)NULL); - - /* set header font */ - SendMessageW(infoPtr->hwndHeader, WM_SETFONT, (WPARAM)infoPtr->hFont, (LPARAM)TRUE); - - /* allocate memory for the data structure */ - if (!(infoPtr->selectionRanges = ranges_create(10))) goto fail; - if (!(infoPtr->hdpaItems = DPA_Create(10))) goto fail; - if (!(infoPtr->hdpaPosX = DPA_Create(10))) goto fail; - if (!(infoPtr->hdpaPosY = DPA_Create(10))) goto fail; - if (!(infoPtr->hdpaColumns = DPA_Create(10))) goto fail; - - /* initialize the icon sizes */ - set_icon_size(&infoPtr->iconSize, infoPtr->himlNormal, uView != LVS_ICON); - set_icon_size(&infoPtr->iconStateSize, infoPtr->himlState, TRUE); - - /* init item size to avoid division by 0 */ - LISTVIEW_UpdateItemSize (infoPtr); - - if (uView == LVS_REPORT) - { - if (!(LVS_NOCOLUMNHEADER & lpcs->style)) - { - ShowWindow(infoPtr->hwndHeader, SW_SHOWNORMAL); - } - else - { - /* set HDS_HIDDEN flag to hide the header bar */ - SetWindowLongW(infoPtr->hwndHeader, GWL_STYLE, - GetWindowLongW(infoPtr->hwndHeader, GWL_STYLE) | HDS_HIDDEN); - } - } - - return 0; - -fail: - DestroyWindow(infoPtr->hwndHeader); - ranges_destroy(infoPtr->selectionRanges); - DPA_Destroy(infoPtr->hdpaItems); - DPA_Destroy(infoPtr->hdpaPosX); - DPA_Destroy(infoPtr->hdpaPosY); - DPA_Destroy(infoPtr->hdpaColumns); - Free(infoPtr); - return -1; -} - -/*** - * DESCRIPTION: - * Erases the background of the listview control. - * - * PARAMETER(S): - * [I] infoPtr : valid pointer to the listview structure - * [I] hdc : device context handle - * - * RETURN: - * SUCCESS : TRUE - * FAILURE : FALSE - */ -static inline BOOL LISTVIEW_EraseBkgnd(LISTVIEW_INFO *infoPtr, HDC hdc) -{ - RECT rc; - - TRACE("(hdc=%p)\n", hdc); - - if (!GetClipBox(hdc, &rc)) return FALSE; - - return LISTVIEW_FillBkgnd(infoPtr, hdc, &rc); -} - - -/*** - * DESCRIPTION: - * Helper function for LISTVIEW_[HV]Scroll *only*. - * Performs vertical/horizontal scrolling by a give amount. - * - * PARAMETER(S): - * [I] infoPtr : valid pointer to the listview structure - * [I] dx : amount of horizontal scroll - * [I] dy : amount of vertical scroll - */ -static void scroll_list(LISTVIEW_INFO *infoPtr, INT dx, INT dy) -{ - /* now we can scroll the list */ - ScrollWindowEx(infoPtr->hwndSelf, dx, dy, &infoPtr->rcList, - &infoPtr->rcList, 0, 0, SW_ERASE | SW_INVALIDATE); - /* if we have focus, adjust rect */ - OffsetRect(&infoPtr->rcFocus, dx, dy); - UpdateWindow(infoPtr->hwndSelf); -} - -/*** - * DESCRIPTION: - * Performs vertical scrolling. - * - * PARAMETER(S): - * [I] infoPtr : valid pointer to the listview structure - * [I] nScrollCode : scroll code - * [I] nScrollDiff : units to scroll in SB_INTERNAL mode, 0 otherwise - * [I] hScrollWnd : scrollbar control window handle - * - * RETURN: - * Zero - * - * NOTES: - * SB_LINEUP/SB_LINEDOWN: - * for LVS_ICON, LVS_SMALLICON is 37 by experiment - * for LVS_REPORT is 1 line - * for LVS_LIST cannot occur - * - */ -static LRESULT LISTVIEW_VScroll(LISTVIEW_INFO *infoPtr, INT nScrollCode, - INT nScrollDiff, HWND hScrollWnd) -{ - UINT uView = infoPtr->dwStyle & LVS_TYPEMASK; - INT nOldScrollPos, nNewScrollPos; - SCROLLINFO scrollInfo; - BOOL is_an_icon; - - TRACE("(nScrollCode=%d(%s), nScrollDiff=%d)\n", nScrollCode, - debugscrollcode(nScrollCode), nScrollDiff); - - if (infoPtr->hwndEdit) SendMessageW(infoPtr->hwndEdit, WM_KILLFOCUS, 0, 0); - - scrollInfo.cbSize = sizeof(SCROLLINFO); - scrollInfo.fMask = SIF_PAGE | SIF_POS | SIF_RANGE | SIF_TRACKPOS; - - is_an_icon = ((uView == LVS_ICON) || (uView == LVS_SMALLICON)); - - if (!GetScrollInfo(infoPtr->hwndSelf, SB_VERT, &scrollInfo)) return 1; - - nOldScrollPos = scrollInfo.nPos; - switch (nScrollCode) - { - case SB_INTERNAL: - break; - - case SB_LINEUP: - nScrollDiff = (is_an_icon) ? -LISTVIEW_SCROLL_ICON_LINE_SIZE : -1; - break; - - case SB_LINEDOWN: - nScrollDiff = (is_an_icon) ? LISTVIEW_SCROLL_ICON_LINE_SIZE : 1; - break; - - case SB_PAGEUP: - nScrollDiff = -scrollInfo.nPage; - break; - - case SB_PAGEDOWN: - nScrollDiff = scrollInfo.nPage; - break; - - case SB_THUMBPOSITION: - case SB_THUMBTRACK: - nScrollDiff = scrollInfo.nTrackPos - scrollInfo.nPos; - break; - - default: - nScrollDiff = 0; - } - - /* quit right away if pos isn't changing */ - if (nScrollDiff == 0) return 0; - - /* calculate new position, and handle overflows */ - nNewScrollPos = scrollInfo.nPos + nScrollDiff; - if (nScrollDiff > 0) { - if (nNewScrollPos < nOldScrollPos || - nNewScrollPos > scrollInfo.nMax) - nNewScrollPos = scrollInfo.nMax; - } else { - if (nNewScrollPos > nOldScrollPos || - nNewScrollPos < scrollInfo.nMin) - nNewScrollPos = scrollInfo.nMin; - } - - /* set the new position, and reread in case it changed */ - scrollInfo.fMask = SIF_POS; - scrollInfo.nPos = nNewScrollPos; - nNewScrollPos = SetScrollInfo(infoPtr->hwndSelf, SB_VERT, &scrollInfo, TRUE); - - /* carry on only if it really changed */ - if (nNewScrollPos == nOldScrollPos) return 0; - - /* now adjust to client coordinates */ - nScrollDiff = nOldScrollPos - nNewScrollPos; - if (uView == LVS_REPORT) nScrollDiff *= infoPtr->nItemHeight; - - /* and scroll the window */ - scroll_list(infoPtr, 0, nScrollDiff); - - return 0; -} - -/*** - * DESCRIPTION: - * Performs horizontal scrolling. - * - * PARAMETER(S): - * [I] infoPtr : valid pointer to the listview structure - * [I] nScrollCode : scroll code - * [I] nScrollDiff : units to scroll in SB_INTERNAL mode, 0 otherwise - * [I] hScrollWnd : scrollbar control window handle - * - * RETURN: - * Zero - * - * NOTES: - * SB_LINELEFT/SB_LINERIGHT: - * for LVS_ICON, LVS_SMALLICON 1 pixel - * for LVS_REPORT is 1 pixel - * for LVS_LIST is 1 column --> which is a 1 because the - * scroll is based on columns not pixels - * - */ -static LRESULT LISTVIEW_HScroll(LISTVIEW_INFO *infoPtr, INT nScrollCode, - INT nScrollDiff, HWND hScrollWnd) -{ - UINT uView = infoPtr->dwStyle & LVS_TYPEMASK; - INT nOldScrollPos, nNewScrollPos; - SCROLLINFO scrollInfo; - - TRACE("(nScrollCode=%d(%s), nScrollDiff=%d)\n", nScrollCode, - debugscrollcode(nScrollCode), nScrollDiff); - - if (infoPtr->hwndEdit) SendMessageW(infoPtr->hwndEdit, WM_KILLFOCUS, 0, 0); - - scrollInfo.cbSize = sizeof(SCROLLINFO); - scrollInfo.fMask = SIF_PAGE | SIF_POS | SIF_RANGE | SIF_TRACKPOS; - - if (!GetScrollInfo(infoPtr->hwndSelf, SB_HORZ, &scrollInfo)) return 1; - - nOldScrollPos = scrollInfo.nPos; - - switch (nScrollCode) - { - case SB_INTERNAL: - break; - - case SB_LINELEFT: - nScrollDiff = -1; - break; - - case SB_LINERIGHT: - nScrollDiff = 1; - break; - - case SB_PAGELEFT: - nScrollDiff = -scrollInfo.nPage; - break; - - case SB_PAGERIGHT: - nScrollDiff = scrollInfo.nPage; - break; - - case SB_THUMBPOSITION: - case SB_THUMBTRACK: - nScrollDiff = scrollInfo.nTrackPos - scrollInfo.nPos; - break; - - default: - nScrollDiff = 0; - } - - /* quit right away if pos isn't changing */ - if (nScrollDiff == 0) return 0; - - /* calculate new position, and handle overflows */ - nNewScrollPos = scrollInfo.nPos + nScrollDiff; - if (nScrollDiff > 0) { - if (nNewScrollPos < nOldScrollPos || - nNewScrollPos > scrollInfo.nMax) - nNewScrollPos = scrollInfo.nMax; - } else { - if (nNewScrollPos > nOldScrollPos || - nNewScrollPos < scrollInfo.nMin) - nNewScrollPos = scrollInfo.nMin; - } - - /* set the new position, and reread in case it changed */ - scrollInfo.fMask = SIF_POS; - scrollInfo.nPos = nNewScrollPos; - nNewScrollPos = SetScrollInfo(infoPtr->hwndSelf, SB_HORZ, &scrollInfo, TRUE); - - /* carry on only if it really changed */ - if (nNewScrollPos == nOldScrollPos) return 0; - - if(uView == LVS_REPORT) - LISTVIEW_UpdateHeaderSize(infoPtr, nNewScrollPos); - - /* now adjust to client coordinates */ - nScrollDiff = nOldScrollPos - nNewScrollPos; - if (uView == LVS_LIST) nScrollDiff *= infoPtr->nItemWidth; - - /* and scroll the window */ - scroll_list(infoPtr, nScrollDiff, 0); - - return 0; -} - -static LRESULT LISTVIEW_MouseWheel(LISTVIEW_INFO *infoPtr, INT wheelDelta) -{ - UINT uView = infoPtr->dwStyle & LVS_TYPEMASK; - INT gcWheelDelta = 0; - INT pulScrollLines = 3; - SCROLLINFO scrollInfo; - - TRACE("(wheelDelta=%d)\n", wheelDelta); - - SystemParametersInfoW(SPI_GETWHEELSCROLLLINES,0, &pulScrollLines, 0); - gcWheelDelta -= wheelDelta; - - scrollInfo.cbSize = sizeof(SCROLLINFO); - scrollInfo.fMask = SIF_POS; - - switch(uView) - { - case LVS_ICON: - case LVS_SMALLICON: - /* - * listview should be scrolled by a multiple of 37 dependently on its dimension or its visible item number - * should be fixed in the future. - */ - LISTVIEW_VScroll(infoPtr, SB_INTERNAL, (gcWheelDelta < 0) ? - -LISTVIEW_SCROLL_ICON_LINE_SIZE : LISTVIEW_SCROLL_ICON_LINE_SIZE, 0); - break; - - case LVS_REPORT: - if (abs(gcWheelDelta) >= WHEEL_DELTA && pulScrollLines) - { - int cLineScroll = min(LISTVIEW_GetCountPerColumn(infoPtr), pulScrollLines); - cLineScroll *= (gcWheelDelta / WHEEL_DELTA); - LISTVIEW_VScroll(infoPtr, SB_INTERNAL, cLineScroll, 0); - } - break; - - case LVS_LIST: - LISTVIEW_HScroll(infoPtr, (gcWheelDelta < 0) ? SB_LINELEFT : SB_LINERIGHT, 0, 0); - break; - } - return 0; -} - -/*** - * DESCRIPTION: - * ??? - * - * PARAMETER(S): - * [I] infoPtr : valid pointer to the listview structure - * [I] nVirtualKey : virtual key - * [I] lKeyData : key data - * - * RETURN: - * Zero - */ -static LRESULT LISTVIEW_KeyDown(LISTVIEW_INFO *infoPtr, INT nVirtualKey, LONG lKeyData) -{ - UINT uView = infoPtr->dwStyle & LVS_TYPEMASK; - INT nItem = -1; - NMLVKEYDOWN nmKeyDown; - - TRACE("(nVirtualKey=%d, lKeyData=%ld)\n", nVirtualKey, lKeyData); - - /* send LVN_KEYDOWN notification */ - nmKeyDown.wVKey = nVirtualKey; - nmKeyDown.flags = 0; - notify_hdr(infoPtr, LVN_KEYDOWN, &nmKeyDown.hdr); - - switch (nVirtualKey) - { - case VK_RETURN: - if ((infoPtr->nItemCount > 0) && (infoPtr->nFocusedItem != -1)) - { - notify(infoPtr, NM_RETURN); - notify(infoPtr, LVN_ITEMACTIVATE); - } - break; - - case VK_HOME: - if (infoPtr->nItemCount > 0) - nItem = 0; - break; - - case VK_END: - if (infoPtr->nItemCount > 0) - nItem = infoPtr->nItemCount - 1; - break; - - case VK_LEFT: - nItem = ListView_GetNextItem(infoPtr->hwndSelf, infoPtr->nFocusedItem, LVNI_TOLEFT); - break; - - case VK_UP: - nItem = ListView_GetNextItem(infoPtr->hwndSelf, infoPtr->nFocusedItem, LVNI_ABOVE); - break; - - case VK_RIGHT: - nItem = ListView_GetNextItem(infoPtr->hwndSelf, infoPtr->nFocusedItem, LVNI_TORIGHT); - break; - - case VK_DOWN: - nItem = ListView_GetNextItem(infoPtr->hwndSelf, infoPtr->nFocusedItem, LVNI_BELOW); - break; - - case VK_PRIOR: - if (uView == LVS_REPORT) - nItem = infoPtr->nFocusedItem - LISTVIEW_GetCountPerColumn(infoPtr); - else - nItem = infoPtr->nFocusedItem - LISTVIEW_GetCountPerColumn(infoPtr) - * LISTVIEW_GetCountPerRow(infoPtr); - if(nItem < 0) nItem = 0; - break; - - case VK_NEXT: - if (uView == LVS_REPORT) - nItem = infoPtr->nFocusedItem + LISTVIEW_GetCountPerColumn(infoPtr); - else - nItem = infoPtr->nFocusedItem + LISTVIEW_GetCountPerColumn(infoPtr) - * LISTVIEW_GetCountPerRow(infoPtr); - if(nItem >= infoPtr->nItemCount) nItem = infoPtr->nItemCount - 1; - break; - } - - if ((nItem != -1) && (nItem != infoPtr->nFocusedItem)) - LISTVIEW_KeySelection(infoPtr, nItem); - - return 0; -} - -/*** - * DESCRIPTION: - * Kills the focus. - * - * PARAMETER(S): - * [I] infoPtr : valid pointer to the listview structure - * - * RETURN: - * Zero - */ -static LRESULT LISTVIEW_KillFocus(LISTVIEW_INFO *infoPtr) -{ - TRACE("()\n"); - - /* if we did not have the focus, there's nothing to do */ - if (!infoPtr->bFocus) return 0; - - /* send NM_KILLFOCUS notification */ - notify(infoPtr, NM_KILLFOCUS); - - /* if we have a focus rectagle, get rid of it */ - LISTVIEW_ShowFocusRect(infoPtr, FALSE); - - /* set window focus flag */ - infoPtr->bFocus = FALSE; - - /* invalidate the selected items before reseting focus flag */ - LISTVIEW_InvalidateSelectedItems(infoPtr); - - return 0; -} - - -/*** - * DESCRIPTION: - * Track mouse/dragging - * - * PARAMETER(S): - * [I] infoPtr : valid pointer to the listview structure - * [I] pt : mouse coordinate - * - * RETURN: - * Zero - */ -static LRESULT LISTVIEW_TrackMouse(LISTVIEW_INFO *infoPtr, POINT pt) -{ - INT cxDrag = GetSystemMetrics(SM_CXDRAG); - INT cyDrag = GetSystemMetrics(SM_CYDRAG); - RECT r; - MSG msg; - - TRACE("\n"); - - r.top = pt.y - cyDrag; - r.left = pt.x - cxDrag; - r.bottom = pt.y + cyDrag; - r.right = pt.x + cxDrag; - - SetCapture(infoPtr->hwndSelf); - - while (1) - { - if (PeekMessageW(&msg, 0, 0, 0, PM_REMOVE | PM_NOYIELD)) - { - if (msg.message == WM_MOUSEMOVE) - { - pt.x = (short)LOWORD(msg.lParam); - pt.y = (short)HIWORD(msg.lParam); - if (PtInRect(&r, pt)) - continue; - else - { - ReleaseCapture(); - return 1; - } - } - else if (msg.message >= WM_LBUTTONDOWN && - msg.message <= WM_RBUTTONDBLCLK) - { - break; - } - - DispatchMessageW(&msg); - } - - if (GetCapture() != infoPtr->hwndSelf) - return 0; - } - - ReleaseCapture(); - return 0; -} - - -/*** - * DESCRIPTION: - * Processes double click messages (left mouse button). - * - * PARAMETER(S): - * [I] infoPtr : valid pointer to the listview structure - * [I] wKey : key flag - * [I] x,y : mouse coordinate - * - * RETURN: - * Zero - */ -static LRESULT LISTVIEW_LButtonDblClk(LISTVIEW_INFO *infoPtr, WORD wKey, INT x, INT y) -{ - LVHITTESTINFO htInfo; - - TRACE("(key=%hu, X=%hu, Y=%hu)\n", wKey, x, y); - - /* send NM_RELEASEDCAPTURE notification */ - notify(infoPtr, NM_RELEASEDCAPTURE); - - htInfo.pt.x = x; - htInfo.pt.y = y; - - /* send NM_DBLCLK notification */ - LISTVIEW_HitTest(infoPtr, &htInfo, TRUE, FALSE); - notify_click(infoPtr, NM_DBLCLK, &htInfo); - - /* To send the LVN_ITEMACTIVATE, it must be on an Item */ - if(htInfo.iItem != -1) notify_itemactivate(infoPtr,&htInfo); - - return 0; -} - -/*** - * DESCRIPTION: - * Processes mouse down messages (left mouse button). - * - * PARAMETER(S): - * [I] infoPtr : valid pointer to the listview structure - * [I] wKey : key flag - * [I] x,y : mouse coordinate - * - * RETURN: - * Zero - */ -static LRESULT LISTVIEW_LButtonDown(LISTVIEW_INFO *infoPtr, WORD wKey, INT x, INT y) -{ - LVHITTESTINFO lvHitTestInfo; - static BOOL bGroupSelect = TRUE; - POINT pt = { x, y }; - INT nItem; - - TRACE("(key=%hu, X=%hu, Y=%hu)\n", wKey, x, y); - - /* send NM_RELEASEDCAPTURE notification */ - notify(infoPtr, NM_RELEASEDCAPTURE); - - if (!infoPtr->bFocus) SetFocus(infoPtr->hwndSelf); - - /* set left button down flag */ - infoPtr->bLButtonDown = TRUE; - - lvHitTestInfo.pt.x = x; - lvHitTestInfo.pt.y = y; - - nItem = LISTVIEW_HitTest(infoPtr, &lvHitTestInfo, TRUE, TRUE); - TRACE("at %s, nItem=%d\n", debugpoint(&pt), nItem); - infoPtr->nEditLabelItem = -1; - if ((nItem >= 0) && (nItem < infoPtr->nItemCount)) - { - if ((infoPtr->dwLvExStyle & LVS_EX_CHECKBOXES) && (lvHitTestInfo.flags & LVHT_ONITEMSTATEICON)) - { - DWORD state = LISTVIEW_GetItemState(infoPtr, nItem, LVIS_STATEIMAGEMASK) >> 12; - if(state == 1 || state == 2) - { - LVITEMW lvitem; - state ^= 3; - lvitem.state = state << 12; - lvitem.stateMask = LVIS_STATEIMAGEMASK; - LISTVIEW_SetItemState(infoPtr, nItem, &lvitem); - } - return 0; - } - if (LISTVIEW_TrackMouse(infoPtr, lvHitTestInfo.pt)) - { - NMLISTVIEW nmlv; - - ZeroMemory(&nmlv, sizeof(nmlv)); - nmlv.iItem = nItem; - nmlv.ptAction.x = lvHitTestInfo.pt.x; - nmlv.ptAction.y = lvHitTestInfo.pt.y; - - notify_listview(infoPtr, LVN_BEGINDRAG, &nmlv); - - return 0; - } - - if (infoPtr->dwStyle & LVS_SINGLESEL) - { - if (LISTVIEW_GetItemState(infoPtr, nItem, LVIS_SELECTED)) - infoPtr->nEditLabelItem = nItem; - else - LISTVIEW_SetSelection(infoPtr, nItem); - } - else - { - if ((wKey & MK_CONTROL) && (wKey & MK_SHIFT)) - { - if (bGroupSelect) - { - LISTVIEW_AddGroupSelection(infoPtr, nItem); - LISTVIEW_SetItemFocus(infoPtr, nItem); - infoPtr->nSelectionMark = nItem; - } - else - { - LVITEMW item; - - item.state = LVIS_SELECTED | LVIS_FOCUSED; - item.stateMask = LVIS_SELECTED | LVIS_FOCUSED; - - LISTVIEW_SetItemState(infoPtr,nItem,&item); - infoPtr->nSelectionMark = nItem; - } - } - else if (wKey & MK_CONTROL) - { - LVITEMW item; - - bGroupSelect = (LISTVIEW_GetItemState(infoPtr, nItem, LVIS_SELECTED) == 0); - - item.state = (bGroupSelect ? LVIS_SELECTED : 0) | LVIS_FOCUSED; - item.stateMask = LVIS_SELECTED | LVIS_FOCUSED; - LISTVIEW_SetItemState(infoPtr, nItem, &item); - infoPtr->nSelectionMark = nItem; - } - else if (wKey & MK_SHIFT) - { - LISTVIEW_SetGroupSelection(infoPtr, nItem); - } - else - { - if (LISTVIEW_GetItemState(infoPtr, nItem, LVIS_SELECTED)) - infoPtr->nEditLabelItem = nItem; - - /* set selection (clears other pre-existing selections) */ - LISTVIEW_SetSelection(infoPtr, nItem); - } - } - } - else - { - /* remove all selections */ - LISTVIEW_DeselectAll(infoPtr); - ReleaseCapture(); - } - - return 0; -} - -/*** - * DESCRIPTION: - * Processes mouse up messages (left mouse button). - * - * PARAMETER(S): - * [I] infoPtr : valid pointer to the listview structure - * [I] wKey : key flag - * [I] x,y : mouse coordinate - * - * RETURN: - * Zero - */ -static LRESULT LISTVIEW_LButtonUp(LISTVIEW_INFO *infoPtr, WORD wKey, INT x, INT y) -{ - LVHITTESTINFO lvHitTestInfo; - - TRACE("(key=%hu, X=%hu, Y=%hu)\n", wKey, x, y); - - if (!infoPtr->bLButtonDown) return 0; - - lvHitTestInfo.pt.x = x; - lvHitTestInfo.pt.y = y; - - /* send NM_CLICK notification */ - LISTVIEW_HitTest(infoPtr, &lvHitTestInfo, TRUE, FALSE); - notify_click(infoPtr, NM_CLICK, &lvHitTestInfo); - - /* set left button flag */ - infoPtr->bLButtonDown = FALSE; - - /* if we clicked on a selected item, edit the label */ - if(lvHitTestInfo.iItem == infoPtr->nEditLabelItem && (lvHitTestInfo.flags & LVHT_ONITEMLABEL)) - LISTVIEW_EditLabelT(infoPtr, lvHitTestInfo.iItem, TRUE); - - return 0; -} - -/*** - * DESCRIPTION: - * Destroys the listview control (called after WM_DESTROY). - * - * PARAMETER(S): - * [I] infoPtr : valid pointer to the listview structure - * - * RETURN: - * Zero - */ -static LRESULT LISTVIEW_NCDestroy(LISTVIEW_INFO *infoPtr) -{ - TRACE("()\n"); - - /* delete all items */ - LISTVIEW_DeleteAllItems(infoPtr); - - /* destroy data structure */ - DPA_Destroy(infoPtr->hdpaItems); - DPA_Destroy(infoPtr->hdpaPosX); - DPA_Destroy(infoPtr->hdpaPosY); - DPA_Destroy(infoPtr->hdpaColumns); - ranges_destroy(infoPtr->selectionRanges); - - /* destroy image lists */ - if (!(infoPtr->dwStyle & LVS_SHAREIMAGELISTS)) - { - if (infoPtr->himlNormal) - ImageList_Destroy(infoPtr->himlNormal); - if (infoPtr->himlSmall) - ImageList_Destroy(infoPtr->himlSmall); - if (infoPtr->himlState) - ImageList_Destroy(infoPtr->himlState); - } - - /* destroy font, bkgnd brush */ - infoPtr->hFont = 0; - if (infoPtr->hDefaultFont) DeleteObject(infoPtr->hDefaultFont); - if (infoPtr->clrBk != CLR_NONE) DeleteObject(infoPtr->hBkBrush); - - SetWindowLongPtrW(infoPtr->hwndSelf, 0, 0); - - /* free listview info pointer*/ - Free(infoPtr); - - return 0; -} - -/*** - * DESCRIPTION: - * Handles notifications from header. - * - * PARAMETER(S): - * [I] infoPtr : valid pointer to the listview structure - * [I] nCtrlId : control identifier - * [I] lpnmh : notification information - * - * RETURN: - * Zero - */ -static LRESULT LISTVIEW_HeaderNotification(LISTVIEW_INFO *infoPtr, const NMHEADERW *lpnmh) -{ - UINT uView = infoPtr->dwStyle & LVS_TYPEMASK; - - TRACE("(lpnmh=%p)\n", lpnmh); - - if (!lpnmh || lpnmh->iItem < 0 || lpnmh->iItem >= DPA_GetPtrCount(infoPtr->hdpaColumns)) return 0; - - switch (lpnmh->hdr.code) - { - case HDN_TRACKW: - case HDN_TRACKA: - case HDN_ITEMCHANGEDW: - case HDN_ITEMCHANGEDA: - { - COLUMN_INFO *lpColumnInfo; - INT dx, cxy; - - if (!lpnmh->pitem || !(lpnmh->pitem->mask & HDI_WIDTH)) - { - HDITEMW hdi; - - hdi.mask = HDI_WIDTH; - if (!Header_GetItemW(infoPtr->hwndHeader, lpnmh->iItem, (LPARAM)&hdi)) return 0; - cxy = hdi.cxy; - } - else - cxy = lpnmh->pitem->cxy; - - /* determine how much we change since the last know position */ - lpColumnInfo = LISTVIEW_GetColumnInfo(infoPtr, lpnmh->iItem); - dx = cxy - (lpColumnInfo->rcHeader.right - lpColumnInfo->rcHeader.left); - if (dx != 0) - { - RECT rcCol = lpColumnInfo->rcHeader; - - lpColumnInfo->rcHeader.right += dx; - LISTVIEW_ScrollColumns(infoPtr, lpnmh->iItem + 1, dx); - if (uView == LVS_REPORT && is_redrawing(infoPtr)) - { - /* this trick works for left aligned columns only */ - if ((lpColumnInfo->fmt & LVCFMT_JUSTIFYMASK) == LVCFMT_LEFT) - { - rcCol.right = min (rcCol.right, lpColumnInfo->rcHeader.right); - rcCol.left = max (rcCol.left, rcCol.right - 3 * infoPtr->ntmAveCharWidth); - } - rcCol.top = infoPtr->rcList.top; - rcCol.bottom = infoPtr->rcList.bottom; - LISTVIEW_InvalidateRect(infoPtr, &rcCol); - } - } - } - break; - - case HDN_ITEMCLICKW: - case HDN_ITEMCLICKA: - { - /* Handle sorting by Header Column */ - NMLISTVIEW nmlv; - - ZeroMemory(&nmlv, sizeof(NMLISTVIEW)); - nmlv.iItem = -1; - nmlv.iSubItem = lpnmh->iItem; - notify_listview(infoPtr, LVN_COLUMNCLICK, &nmlv); - } - break; - } - - return 0; -} - -/*** - * DESCRIPTION: - * Determines the type of structure to use. - * - * PARAMETER(S): - * [I] infoPtr : valid pointer to the listview structureof the sender - * [I] hwndFrom : listview window handle - * [I] nCommand : command specifying the nature of the WM_NOTIFYFORMAT - * - * RETURN: - * Zero - */ -static LRESULT LISTVIEW_NotifyFormat(LISTVIEW_INFO *infoPtr, HWND hwndFrom, INT nCommand) -{ - TRACE("(hwndFrom=%p, nCommand=%d)\n", hwndFrom, nCommand); - - if (nCommand != NF_REQUERY) return 0; - - infoPtr->notifyFormat = SendMessageW(hwndFrom, WM_NOTIFYFORMAT, (WPARAM)infoPtr->hwndSelf, NF_QUERY); - - return 0; -} - -/*** - * DESCRIPTION: - * Paints/Repaints the listview control. - * - * PARAMETER(S): - * [I] infoPtr : valid pointer to the listview structure - * [I] hdc : device context handle - * - * RETURN: - * Zero - */ -static LRESULT LISTVIEW_Paint(LISTVIEW_INFO *infoPtr, HDC hdc) -{ - TRACE("(hdc=%p)\n", hdc); - - if (infoPtr->bNoItemMetrics && infoPtr->nItemCount) - { - UINT uView = infoPtr->dwStyle & LVS_TYPEMASK; - - infoPtr->bNoItemMetrics = FALSE; - LISTVIEW_UpdateItemSize(infoPtr); - if (uView == LVS_ICON || uView == LVS_SMALLICON) - LISTVIEW_Arrange(infoPtr, LVA_DEFAULT); - LISTVIEW_UpdateScroll(infoPtr); - } - if (hdc) - LISTVIEW_Refresh(infoPtr, hdc); - else - { - PAINTSTRUCT ps; - - hdc = BeginPaint(infoPtr->hwndSelf, &ps); - if (!hdc) return 1; - if (ps.fErase) LISTVIEW_FillBkgnd(infoPtr, hdc, &ps.rcPaint); - LISTVIEW_Refresh(infoPtr, hdc); - EndPaint(infoPtr->hwndSelf, &ps); - } - - return 0; -} - -/*** - * DESCRIPTION: - * Processes double click messages (right mouse button). - * - * PARAMETER(S): - * [I] infoPtr : valid pointer to the listview structure - * [I] wKey : key flag - * [I] x,y : mouse coordinate - * - * RETURN: - * Zero - */ -static LRESULT LISTVIEW_RButtonDblClk(LISTVIEW_INFO *infoPtr, WORD wKey, INT x, INT y) -{ - LVHITTESTINFO lvHitTestInfo; - - TRACE("(key=%hu,X=%hu,Y=%hu)\n", wKey, x, y); - - /* send NM_RELEASEDCAPTURE notification */ - notify(infoPtr, NM_RELEASEDCAPTURE); - - /* send NM_RDBLCLK notification */ - lvHitTestInfo.pt.x = x; - lvHitTestInfo.pt.y = y; - LISTVIEW_HitTest(infoPtr, &lvHitTestInfo, TRUE, FALSE); - notify_click(infoPtr, NM_RDBLCLK, &lvHitTestInfo); - - return 0; -} - -/*** - * DESCRIPTION: - * Processes mouse down messages (right mouse button). - * - * PARAMETER(S): - * [I] infoPtr : valid pointer to the listview structure - * [I] wKey : key flag - * [I] x,y : mouse coordinate - * - * RETURN: - * Zero - */ -static LRESULT LISTVIEW_RButtonDown(LISTVIEW_INFO *infoPtr, WORD wKey, INT x, INT y) -{ - LVHITTESTINFO lvHitTestInfo; - INT nItem; - - TRACE("(key=%hu,X=%hu,Y=%hu)\n", wKey, x, y); - - /* send NM_RELEASEDCAPTURE notification */ - notify(infoPtr, NM_RELEASEDCAPTURE); - - /* make sure the listview control window has the focus */ - if (!infoPtr->bFocus) SetFocus(infoPtr->hwndSelf); - - /* set right button down flag */ - infoPtr->bRButtonDown = TRUE; - - /* determine the index of the selected item */ - lvHitTestInfo.pt.x = x; - lvHitTestInfo.pt.y = y; - nItem = LISTVIEW_HitTest(infoPtr, &lvHitTestInfo, TRUE, TRUE); - - if ((nItem >= 0) && (nItem < infoPtr->nItemCount)) - { - LISTVIEW_SetItemFocus(infoPtr, nItem); - if (!((wKey & MK_SHIFT) || (wKey & MK_CONTROL)) && - !LISTVIEW_GetItemState(infoPtr, nItem, LVIS_SELECTED)) - LISTVIEW_SetSelection(infoPtr, nItem); - } - else - { - LISTVIEW_DeselectAll(infoPtr); - } - - return 0; -} - -/*** - * DESCRIPTION: - * Processes mouse up messages (right mouse button). - * - * PARAMETER(S): - * [I] infoPtr : valid pointer to the listview structure - * [I] wKey : key flag - * [I] x,y : mouse coordinate - * - * RETURN: - * Zero - */ -static LRESULT LISTVIEW_RButtonUp(LISTVIEW_INFO *infoPtr, WORD wKey, INT x, INT y) -{ - LVHITTESTINFO lvHitTestInfo; - POINT pt; - - TRACE("(key=%hu,X=%hu,Y=%hu)\n", wKey, x, y); - - if (!infoPtr->bRButtonDown) return 0; - - /* set button flag */ - infoPtr->bRButtonDown = FALSE; - - /* Send NM_RClICK notification */ - lvHitTestInfo.pt.x = x; - lvHitTestInfo.pt.y = y; - LISTVIEW_HitTest(infoPtr, &lvHitTestInfo, TRUE, FALSE); - notify_click(infoPtr, NM_RCLICK, &lvHitTestInfo); - - /* Change to screen coordinate for WM_CONTEXTMENU */ - pt = lvHitTestInfo.pt; - ClientToScreen(infoPtr->hwndSelf, &pt); - - /* Send a WM_CONTEXTMENU message in response to the RBUTTONUP */ - SendMessageW(infoPtr->hwndSelf, WM_CONTEXTMENU, - (WPARAM)infoPtr->hwndSelf, MAKELPARAM(pt.x, pt.y)); - - return 0; -} - - -/*** - * DESCRIPTION: - * Sets the cursor. - * - * PARAMETER(S): - * [I] infoPtr : valid pointer to the listview structure - * [I] hwnd : window handle of window containing the cursor - * [I] nHittest : hit-test code - * [I] wMouseMsg : ideintifier of the mouse message - * - * RETURN: - * TRUE if cursor is set - * FALSE otherwise - */ -static BOOL LISTVIEW_SetCursor(LISTVIEW_INFO *infoPtr, HWND hwnd, UINT nHittest, UINT wMouseMsg) -{ - LVHITTESTINFO lvHitTestInfo; - - if(!(infoPtr->dwLvExStyle & LVS_EX_TRACKSELECT)) return FALSE; - - if(!infoPtr->hHotCursor) return FALSE; - - GetCursorPos(&lvHitTestInfo.pt); - if (LISTVIEW_HitTest(infoPtr, &lvHitTestInfo, FALSE, FALSE) < 0) return FALSE; - - SetCursor(infoPtr->hHotCursor); - - return TRUE; -} - -/*** - * DESCRIPTION: - * Sets the focus. - * - * PARAMETER(S): - * [I] infoPtr : valid pointer to the listview structure - * [I] hwndLoseFocus : handle of previously focused window - * - * RETURN: - * Zero - */ -static LRESULT LISTVIEW_SetFocus(LISTVIEW_INFO *infoPtr, HWND hwndLoseFocus) -{ - TRACE("(hwndLoseFocus=%p)\n", hwndLoseFocus); - - /* if we have the focus already, there's nothing to do */ - if (infoPtr->bFocus) return 0; - - /* send NM_SETFOCUS notification */ - notify(infoPtr, NM_SETFOCUS); - - /* set window focus flag */ - infoPtr->bFocus = TRUE; - - /* put the focus rect back on */ - LISTVIEW_ShowFocusRect(infoPtr, TRUE); - - /* redraw all visible selected items */ - LISTVIEW_InvalidateSelectedItems(infoPtr); - - return 0; -} - -/*** - * DESCRIPTION: - * Sets the font. - * - * PARAMETER(S): - * [I] infoPtr : valid pointer to the listview structure - * [I] fRedraw : font handle - * [I] fRedraw : redraw flag - * - * RETURN: - * Zero - */ -static LRESULT LISTVIEW_SetFont(LISTVIEW_INFO *infoPtr, HFONT hFont, WORD fRedraw) -{ - HFONT oldFont = infoPtr->hFont; - - TRACE("(hfont=%p,redraw=%hu)\n", hFont, fRedraw); - - infoPtr->hFont = hFont ? hFont : infoPtr->hDefaultFont; - if (infoPtr->hFont == oldFont) return 0; - - LISTVIEW_SaveTextMetrics(infoPtr); - - if ((infoPtr->dwStyle & LVS_TYPEMASK) == LVS_REPORT) - SendMessageW(infoPtr->hwndHeader, WM_SETFONT, (WPARAM)hFont, MAKELPARAM(fRedraw, 0)); - - if (fRedraw) LISTVIEW_InvalidateList(infoPtr); - - return 0; -} - -/*** - * DESCRIPTION: - * Message handling for WM_SETREDRAW. - * For the Listview, it invalidates the entire window (the doc specifies otherwise) - * - * PARAMETER(S): - * [I] infoPtr : valid pointer to the listview structure - * [I] bRedraw: state of redraw flag - * - * RETURN: - * DefWinProc return value - */ -static LRESULT LISTVIEW_SetRedraw(LISTVIEW_INFO *infoPtr, BOOL bRedraw) -{ - TRACE("infoPtr->bRedraw=%d, bRedraw=%d\n", infoPtr->bRedraw, bRedraw); - - /* we can not use straight equality here because _any_ non-zero value is TRUE */ - if ((infoPtr->bRedraw && bRedraw) || (!infoPtr->bRedraw && !bRedraw)) return 0; - - infoPtr->bRedraw = bRedraw; - - if(!bRedraw) return 0; - - if (is_autoarrange(infoPtr)) - LISTVIEW_Arrange(infoPtr, LVA_DEFAULT); - LISTVIEW_UpdateScroll(infoPtr); - - /* despite what the WM_SETREDRAW docs says, apps expect us - * to invalidate the listview here... stupid! */ - LISTVIEW_InvalidateList(infoPtr); - - return 0; -} - -/*** - * DESCRIPTION: - * Resizes the listview control. This function processes WM_SIZE - * messages. At this time, the width and height are not used. - * - * PARAMETER(S): - * [I] infoPtr : valid pointer to the listview structure - * [I] Width : new width - * [I] Height : new height - * - * RETURN: - * Zero - */ -static LRESULT LISTVIEW_Size(LISTVIEW_INFO *infoPtr, int Width, int Height) -{ - RECT rcOld = infoPtr->rcList; - - TRACE("(width=%d, height=%d)\n", Width, Height); - - LISTVIEW_UpdateSize(infoPtr); - if (EqualRect(&rcOld, &infoPtr->rcList)) return 0; - - /* do not bother with display related stuff if we're not redrawing */ - if (!is_redrawing(infoPtr)) return 0; - - if (is_autoarrange(infoPtr)) - LISTVIEW_Arrange(infoPtr, LVA_DEFAULT); - - LISTVIEW_UpdateScroll(infoPtr); - - /* refresh all only for lists whose height changed significantly */ - if ((infoPtr->dwStyle & LVS_TYPEMASK) == LVS_LIST && - (rcOld.bottom - rcOld.top) / infoPtr->nItemHeight != - (infoPtr->rcList.bottom - infoPtr->rcList.top) / infoPtr->nItemHeight) - LISTVIEW_InvalidateList(infoPtr); - - return 0; -} - -/*** - * DESCRIPTION: - * Sets the size information. - * - * PARAMETER(S): - * [I] infoPtr : valid pointer to the listview structure - * - * RETURN: - * None - */ -static void LISTVIEW_UpdateSize(LISTVIEW_INFO *infoPtr) -{ - UINT uView = infoPtr->dwStyle & LVS_TYPEMASK; - - TRACE("uView=%d, rcList(old)=%s\n", uView, debugrect(&infoPtr->rcList)); - - GetClientRect(infoPtr->hwndSelf, &infoPtr->rcList); - - if (uView == LVS_LIST) - { - /* Apparently the "LIST" style is supposed to have the same - * number of items in a column even if there is no scroll bar. - * Since if a scroll bar already exists then the bottom is already - * reduced, only reduce if the scroll bar does not currently exist. - * The "2" is there to mimic the native control. I think it may be - * related to either padding or edges. (GLA 7/2002) - */ - if (!(GetWindowLongW(infoPtr->hwndSelf, GWL_STYLE) & WS_HSCROLL)) - infoPtr->rcList.bottom -= GetSystemMetrics(SM_CYHSCROLL); - infoPtr->rcList.bottom = max (infoPtr->rcList.bottom - 2, 0); - } - else if (uView == LVS_REPORT && !(infoPtr->dwStyle & LVS_NOCOLUMNHEADER)) - { - HDLAYOUT hl; - WINDOWPOS wp; - - hl.prc = &infoPtr->rcList; - hl.pwpos = ℘ - Header_Layout(infoPtr->hwndHeader, &hl); - - SetWindowPos(wp.hwnd, wp.hwndInsertAfter, wp.x, wp.y, wp.cx, wp.cy, wp.flags); - - infoPtr->rcList.top = max(wp.cy, 0); - } - - TRACE(" rcList=%s\n", debugrect(&infoPtr->rcList)); -} - -/*** - * DESCRIPTION: - * Processes WM_STYLECHANGED messages. - * - * PARAMETER(S): - * [I] infoPtr : valid pointer to the listview structure - * [I] wStyleType : window style type (normal or extended) - * [I] lpss : window style information - * - * RETURN: - * Zero - */ -static INT LISTVIEW_StyleChanged(LISTVIEW_INFO *infoPtr, WPARAM wStyleType, - const STYLESTRUCT *lpss) -{ - UINT uNewView = lpss->styleNew & LVS_TYPEMASK; - UINT uOldView = lpss->styleOld & LVS_TYPEMASK; - - TRACE("(styletype=%x, styleOld=0x%08lx, styleNew=0x%08lx)\n", - wStyleType, lpss->styleOld, lpss->styleNew); - - if (wStyleType != GWL_STYLE) return 0; - - /* FIXME: if LVS_NOSORTHEADER changed, update header */ - /* what if LVS_OWNERDATA changed? */ - /* or LVS_SINGLESEL */ - /* or LVS_SORT{AS,DES}CENDING */ - - infoPtr->dwStyle = lpss->styleNew; - - if (((lpss->styleOld & WS_HSCROLL) != 0)&& - ((lpss->styleNew & WS_HSCROLL) == 0)) - ShowScrollBar(infoPtr->hwndSelf, SB_HORZ, FALSE); - - if (((lpss->styleOld & WS_VSCROLL) != 0)&& - ((lpss->styleNew & WS_VSCROLL) == 0)) - ShowScrollBar(infoPtr->hwndSelf, SB_VERT, FALSE); - - if (uNewView != uOldView) - { - SIZE oldIconSize = infoPtr->iconSize; - HIMAGELIST himl; - - SendMessageW(infoPtr->hwndEdit, WM_KILLFOCUS, 0, 0); - ShowWindow(infoPtr->hwndHeader, SW_HIDE); - - ShowScrollBar(infoPtr->hwndSelf, SB_BOTH, FALSE); - SetRectEmpty(&infoPtr->rcFocus); - - himl = (uNewView == LVS_ICON ? infoPtr->himlNormal : infoPtr->himlSmall); - set_icon_size(&infoPtr->iconSize, himl, uNewView != LVS_ICON); - - if (uNewView == LVS_ICON) - { - if ((infoPtr->iconSize.cx != oldIconSize.cx) || (infoPtr->iconSize.cy != oldIconSize.cy)) - { - TRACE("icon old size=(%ld,%ld), new size=(%ld,%ld)\n", - oldIconSize.cx, oldIconSize.cy, infoPtr->iconSize.cx, infoPtr->iconSize.cy); - LISTVIEW_SetIconSpacing(infoPtr, 0, 0); - } - } - else if (uNewView == LVS_REPORT) - { - HDLAYOUT hl; - WINDOWPOS wp; - - hl.prc = &infoPtr->rcList; - hl.pwpos = ℘ - Header_Layout(infoPtr->hwndHeader, &hl); - SetWindowPos(infoPtr->hwndHeader, infoPtr->hwndSelf, wp.x, wp.y, wp.cx, wp.cy, wp.flags); - } - - LISTVIEW_UpdateItemSize(infoPtr); - } - - if (uNewView == LVS_REPORT) - ShowWindow(infoPtr->hwndHeader, (lpss->styleNew & LVS_NOCOLUMNHEADER) ? SW_HIDE : SW_SHOWNORMAL); - - if ( (uNewView == LVS_ICON || uNewView == LVS_SMALLICON) && - (uNewView != uOldView || ((lpss->styleNew ^ lpss->styleOld) & LVS_ALIGNMASK)) ) - LISTVIEW_Arrange(infoPtr, LVA_DEFAULT); - - /* update the size of the client area */ - LISTVIEW_UpdateSize(infoPtr); - - /* add scrollbars if needed */ - LISTVIEW_UpdateScroll(infoPtr); - - /* invalidate client area + erase background */ - LISTVIEW_InvalidateList(infoPtr); - - return 0; -} - -/*** - * DESCRIPTION: - * Window procedure of the listview control. - * - */ -static LRESULT WINAPI -LISTVIEW_WindowProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam) -{ - LISTVIEW_INFO *infoPtr = (LISTVIEW_INFO *)GetWindowLongPtrW(hwnd, 0); - - TRACE("(uMsg=%x wParam=%x lParam=%lx)\n", uMsg, wParam, lParam); - - if (!infoPtr && (uMsg != WM_CREATE)) - return DefWindowProcW(hwnd, uMsg, wParam, lParam); - - switch (uMsg) - { - case LVM_APPROXIMATEVIEWRECT: - return LISTVIEW_ApproximateViewRect(infoPtr, (INT)wParam, - LOWORD(lParam), HIWORD(lParam)); - case LVM_ARRANGE: - return LISTVIEW_Arrange(infoPtr, (INT)wParam); - -/* case LVM_CANCELEDITLABEL: */ - - case LVM_CREATEDRAGIMAGE: - return (LRESULT)LISTVIEW_CreateDragImage(infoPtr, (INT)wParam, (LPPOINT)lParam); - - case LVM_DELETEALLITEMS: - return LISTVIEW_DeleteAllItems(infoPtr); - - case LVM_DELETECOLUMN: - return LISTVIEW_DeleteColumn(infoPtr, (INT)wParam); - - case LVM_DELETEITEM: - return LISTVIEW_DeleteItem(infoPtr, (INT)wParam); - - case LVM_EDITLABELW: - return (LRESULT)LISTVIEW_EditLabelT(infoPtr, (INT)wParam, TRUE); - - case LVM_EDITLABELA: - return (LRESULT)LISTVIEW_EditLabelT(infoPtr, (INT)wParam, FALSE); - - /* case LVM_ENABLEGROUPVIEW: */ - - case LVM_ENSUREVISIBLE: - return LISTVIEW_EnsureVisible(infoPtr, (INT)wParam, (BOOL)lParam); - - case LVM_FINDITEMW: - return LISTVIEW_FindItemW(infoPtr, (INT)wParam, (LPLVFINDINFOW)lParam); - - case LVM_FINDITEMA: - return LISTVIEW_FindItemA(infoPtr, (INT)wParam, (LPLVFINDINFOA)lParam); - - case LVM_GETBKCOLOR: - return infoPtr->clrBk; - - /* case LVM_GETBKIMAGE: */ - - case LVM_GETCALLBACKMASK: - return infoPtr->uCallbackMask; - - case LVM_GETCOLUMNA: - return LISTVIEW_GetColumnT(infoPtr, (INT)wParam, (LPLVCOLUMNW)lParam, FALSE); - - case LVM_GETCOLUMNW: - return LISTVIEW_GetColumnT(infoPtr, (INT)wParam, (LPLVCOLUMNW)lParam, TRUE); - - case LVM_GETCOLUMNORDERARRAY: - return LISTVIEW_GetColumnOrderArray(infoPtr, (INT)wParam, (LPINT)lParam); - - case LVM_GETCOLUMNWIDTH: - return LISTVIEW_GetColumnWidth(infoPtr, (INT)wParam); - - case LVM_GETCOUNTPERPAGE: - return LISTVIEW_GetCountPerPage(infoPtr); - - case LVM_GETEDITCONTROL: - return (LRESULT)infoPtr->hwndEdit; - - case LVM_GETEXTENDEDLISTVIEWSTYLE: - return infoPtr->dwLvExStyle; - - /* case LVM_GETGROUPINFO: */ - - /* case LVM_GETGROUPMETRICS: */ - - case LVM_GETHEADER: - return (LRESULT)infoPtr->hwndHeader; - - case LVM_GETHOTCURSOR: - return (LRESULT)infoPtr->hHotCursor; - - case LVM_GETHOTITEM: - return infoPtr->nHotItem; - - case LVM_GETHOVERTIME: - return infoPtr->dwHoverTime; - - case LVM_GETIMAGELIST: - return (LRESULT)LISTVIEW_GetImageList(infoPtr, (INT)wParam); - - /* case LVM_GETINSERTMARK: */ - - /* case LVM_GETINSERTMARKCOLOR: */ - - /* case LVM_GETINSERTMARKRECT: */ - - case LVM_GETISEARCHSTRINGA: - case LVM_GETISEARCHSTRINGW: - FIXME("LVM_GETISEARCHSTRING: unimplemented\n"); - return FALSE; - - case LVM_GETITEMA: - return LISTVIEW_GetItemExtT(infoPtr, (LPLVITEMW)lParam, FALSE); - - case LVM_GETITEMW: - return LISTVIEW_GetItemExtT(infoPtr, (LPLVITEMW)lParam, TRUE); - - case LVM_GETITEMCOUNT: - return infoPtr->nItemCount; - - case LVM_GETITEMPOSITION: - return LISTVIEW_GetItemPosition(infoPtr, (INT)wParam, (LPPOINT)lParam); - - case LVM_GETITEMRECT: - return LISTVIEW_GetItemRect(infoPtr, (INT)wParam, (LPRECT)lParam); - - case LVM_GETITEMSPACING: - return LISTVIEW_GetItemSpacing(infoPtr, (BOOL)wParam); - - case LVM_GETITEMSTATE: - return LISTVIEW_GetItemState(infoPtr, (INT)wParam, (UINT)lParam); - - case LVM_GETITEMTEXTA: - return LISTVIEW_GetItemTextT(infoPtr, (INT)wParam, (LPLVITEMW)lParam, FALSE); - - case LVM_GETITEMTEXTW: - return LISTVIEW_GetItemTextT(infoPtr, (INT)wParam, (LPLVITEMW)lParam, TRUE); - - case LVM_GETNEXTITEM: - return LISTVIEW_GetNextItem(infoPtr, (INT)wParam, LOWORD(lParam)); - - case LVM_GETNUMBEROFWORKAREAS: - FIXME("LVM_GETNUMBEROFWORKAREAS: unimplemented\n"); - return 1; - - case LVM_GETORIGIN: - if (!lParam) return FALSE; - LISTVIEW_GetOrigin(infoPtr, (LPPOINT)lParam); - return TRUE; - - /* case LVM_GETOUTLINECOLOR: */ - - /* case LVM_GETSELECTEDCOLUMN: */ - - case LVM_GETSELECTEDCOUNT: - return LISTVIEW_GetSelectedCount(infoPtr); - - case LVM_GETSELECTIONMARK: - return infoPtr->nSelectionMark; - - case LVM_GETSTRINGWIDTHA: - return LISTVIEW_GetStringWidthT(infoPtr, (LPCWSTR)lParam, FALSE); - - case LVM_GETSTRINGWIDTHW: - return LISTVIEW_GetStringWidthT(infoPtr, (LPCWSTR)lParam, TRUE); - - case LVM_GETSUBITEMRECT: - return LISTVIEW_GetSubItemRect(infoPtr, (UINT)wParam, (LPRECT)lParam); - - case LVM_GETTEXTBKCOLOR: - return infoPtr->clrTextBk; - - case LVM_GETTEXTCOLOR: - return infoPtr->clrText; - - /* case LVM_GETTILEINFO: */ - - /* case LVM_GETTILEVIEWINFO: */ - - case LVM_GETTOOLTIPS: - if( !infoPtr->hwndToolTip ) - infoPtr->hwndToolTip = COMCTL32_CreateToolTip( hwnd ); - return (LRESULT)infoPtr->hwndToolTip; - - case LVM_GETTOPINDEX: - return LISTVIEW_GetTopIndex(infoPtr); - - /*case LVM_GETUNICODEFORMAT: - FIXME("LVM_GETUNICODEFORMAT: unimplemented\n"); - return FALSE;*/ - - /* case LVM_GETVIEW: */ - - case LVM_GETVIEWRECT: - return LISTVIEW_GetViewRect(infoPtr, (LPRECT)lParam); - - case LVM_GETWORKAREAS: - FIXME("LVM_GETWORKAREAS: unimplemented\n"); - return FALSE; - - /* case LVM_HASGROUP: */ - - case LVM_HITTEST: - return LISTVIEW_HitTest(infoPtr, (LPLVHITTESTINFO)lParam, FALSE, FALSE); - - case LVM_INSERTCOLUMNA: - return LISTVIEW_InsertColumnT(infoPtr, (INT)wParam, (LPLVCOLUMNW)lParam, FALSE); - - case LVM_INSERTCOLUMNW: - return LISTVIEW_InsertColumnT(infoPtr, (INT)wParam, (LPLVCOLUMNW)lParam, TRUE); - - /* case LVM_INSERTGROUP: */ - - /* case LVM_INSERTGROUPSORTED: */ - - case LVM_INSERTITEMA: - return LISTVIEW_InsertItemT(infoPtr, (LPLVITEMW)lParam, FALSE); - - case LVM_INSERTITEMW: - return LISTVIEW_InsertItemT(infoPtr, (LPLVITEMW)lParam, TRUE); - - /* case LVM_INSERTMARKHITTEST: */ - - /* case LVM_ISGROUPVIEWENABLED: */ - - /* case LVM_MAPIDTOINDEX: */ - - /* case LVM_MAPINDEXTOID: */ - - /* case LVM_MOVEGROUP: */ - - /* case LVM_MOVEITEMTOGROUP: */ - - case LVM_REDRAWITEMS: - return LISTVIEW_RedrawItems(infoPtr, (INT)wParam, (INT)lParam); - - /* case LVM_REMOVEALLGROUPS: */ - - /* case LVM_REMOVEGROUP: */ - - case LVM_SCROLL: - return LISTVIEW_Scroll(infoPtr, (INT)wParam, (INT)lParam); - - case LVM_SETBKCOLOR: - return LISTVIEW_SetBkColor(infoPtr, (COLORREF)lParam); - - /* case LVM_SETBKIMAGE: */ - - case LVM_SETCALLBACKMASK: - infoPtr->uCallbackMask = (UINT)wParam; - return TRUE; - - case LVM_SETCOLUMNA: - return LISTVIEW_SetColumnT(infoPtr, (INT)wParam, (LPLVCOLUMNW)lParam, FALSE); - - case LVM_SETCOLUMNW: - return LISTVIEW_SetColumnT(infoPtr, (INT)wParam, (LPLVCOLUMNW)lParam, TRUE); - - case LVM_SETCOLUMNORDERARRAY: - return LISTVIEW_SetColumnOrderArray(infoPtr, (INT)wParam, (LPINT)lParam); - - case LVM_SETCOLUMNWIDTH: - return LISTVIEW_SetColumnWidth(infoPtr, (INT)wParam, (short)LOWORD(lParam)); - - case LVM_SETEXTENDEDLISTVIEWSTYLE: - return LISTVIEW_SetExtendedListViewStyle(infoPtr, (DWORD)wParam, (DWORD)lParam); - - /* case LVM_SETGROUPINFO: */ - - /* case LVM_SETGROUPMETRICS: */ - - case LVM_SETHOTCURSOR: - return (LRESULT)LISTVIEW_SetHotCursor(infoPtr, (HCURSOR)lParam); - - case LVM_SETHOTITEM: - return LISTVIEW_SetHotItem(infoPtr, (INT)wParam); - - case LVM_SETHOVERTIME: - return LISTVIEW_SetHoverTime(infoPtr, (DWORD)wParam); - - case LVM_SETICONSPACING: - return LISTVIEW_SetIconSpacing(infoPtr, (short)LOWORD(lParam), (short)HIWORD(lParam)); - - case LVM_SETIMAGELIST: - return (LRESULT)LISTVIEW_SetImageList(infoPtr, (INT)wParam, (HIMAGELIST)lParam); - - /* case LVM_SETINFOTIP: */ - - /* case LVM_SETINSERTMARK: */ - - /* case LVM_SETINSERTMARKCOLOR: */ - - case LVM_SETITEMA: - return LISTVIEW_SetItemT(infoPtr, (LPLVITEMW)lParam, FALSE); - - case LVM_SETITEMW: - return LISTVIEW_SetItemT(infoPtr, (LPLVITEMW)lParam, TRUE); - - case LVM_SETITEMCOUNT: - return LISTVIEW_SetItemCount(infoPtr, (INT)wParam, (DWORD)lParam); - - case LVM_SETITEMPOSITION: - { - POINT pt; - pt.x = (short)LOWORD(lParam); - pt.y = (short)HIWORD(lParam); - return LISTVIEW_SetItemPosition(infoPtr, (INT)wParam, pt); - } - - case LVM_SETITEMPOSITION32: - if (lParam == 0) return FALSE; - return LISTVIEW_SetItemPosition(infoPtr, (INT)wParam, *((POINT*)lParam)); - - case LVM_SETITEMSTATE: - return LISTVIEW_SetItemState(infoPtr, (INT)wParam, (LPLVITEMW)lParam); - - case LVM_SETITEMTEXTA: - return LISTVIEW_SetItemTextT(infoPtr, (INT)wParam, (LPLVITEMW)lParam, FALSE); - - case LVM_SETITEMTEXTW: - return LISTVIEW_SetItemTextT(infoPtr, (INT)wParam, (LPLVITEMW)lParam, TRUE); - - /* case LVM_SETOUTLINECOLOR: */ - - /* case LVM_SETSELECTEDCOLUMN: */ - - case LVM_SETSELECTIONMARK: - return LISTVIEW_SetSelectionMark(infoPtr, (INT)lParam); - - case LVM_SETTEXTBKCOLOR: - return LISTVIEW_SetTextBkColor(infoPtr, (COLORREF)lParam); - - case LVM_SETTEXTCOLOR: - return LISTVIEW_SetTextColor(infoPtr, (COLORREF)lParam); - - /* case LVM_SETTILEINFO: */ - - /* case LVM_SETTILEVIEWINFO: */ - - /* case LVM_SETTILEWIDTH: */ - - case LVM_SETTOOLTIPS: - return (LRESULT)LISTVIEW_SetToolTips(infoPtr, (HWND)lParam); - - /* case LVM_SETUNICODEFORMAT: */ - - /* case LVM_SETVIEW: */ - - /* case LVM_SETWORKAREAS: */ - - /* case LVM_SORTGROUPS: */ - - case LVM_SORTITEMS: - return LISTVIEW_SortItems(infoPtr, (PFNLVCOMPARE)lParam, (LPARAM)wParam); - - /* LVM_SORTITEMSEX: */ - - case LVM_SUBITEMHITTEST: - return LISTVIEW_HitTest(infoPtr, (LPLVHITTESTINFO)lParam, TRUE, FALSE); - - case LVM_UPDATE: - return LISTVIEW_Update(infoPtr, (INT)wParam); - - case WM_CHAR: - return LISTVIEW_ProcessLetterKeys( infoPtr, wParam, lParam ); - - case WM_COMMAND: - return LISTVIEW_Command(infoPtr, wParam, lParam); - - case WM_CREATE: - return LISTVIEW_Create(hwnd, (LPCREATESTRUCTW)lParam); - - case WM_ERASEBKGND: - return LISTVIEW_EraseBkgnd(infoPtr, (HDC)wParam); - - case WM_GETDLGCODE: - return DLGC_WANTCHARS | DLGC_WANTARROWS; - - case WM_GETFONT: - return (LRESULT)infoPtr->hFont; - - case WM_HSCROLL: - return LISTVIEW_HScroll(infoPtr, (INT)LOWORD(wParam), 0, (HWND)lParam); - - case WM_KEYDOWN: - return LISTVIEW_KeyDown(infoPtr, (INT)wParam, (LONG)lParam); - - case WM_KILLFOCUS: - return LISTVIEW_KillFocus(infoPtr); - - case WM_LBUTTONDBLCLK: - return LISTVIEW_LButtonDblClk(infoPtr, (WORD)wParam, (SHORT)LOWORD(lParam), (SHORT)HIWORD(lParam)); - - case WM_LBUTTONDOWN: - return LISTVIEW_LButtonDown(infoPtr, (WORD)wParam, (SHORT)LOWORD(lParam), (SHORT)HIWORD(lParam)); - - case WM_LBUTTONUP: - return LISTVIEW_LButtonUp(infoPtr, (WORD)wParam, (SHORT)LOWORD(lParam), (SHORT)HIWORD(lParam)); - - case WM_MOUSEMOVE: - return LISTVIEW_MouseMove (infoPtr, (WORD)wParam, (SHORT)LOWORD(lParam), (SHORT)HIWORD(lParam)); - - case WM_MOUSEHOVER: - return LISTVIEW_MouseHover(infoPtr, (WORD)wParam, (SHORT)LOWORD(lParam), (SHORT)HIWORD(lParam)); - - case WM_NCDESTROY: - return LISTVIEW_NCDestroy(infoPtr); - - case WM_NOTIFY: - if (lParam && ((LPNMHDR)lParam)->hwndFrom == infoPtr->hwndHeader) - return LISTVIEW_HeaderNotification(infoPtr, (LPNMHEADERW)lParam); - else return 0; - - case WM_NOTIFYFORMAT: - return LISTVIEW_NotifyFormat(infoPtr, (HWND)wParam, (INT)lParam); - - case WM_PAINT: - return LISTVIEW_Paint(infoPtr, (HDC)wParam); - - case WM_RBUTTONDBLCLK: - return LISTVIEW_RButtonDblClk(infoPtr, (WORD)wParam, (SHORT)LOWORD(lParam), (SHORT)HIWORD(lParam)); - - case WM_RBUTTONDOWN: - return LISTVIEW_RButtonDown(infoPtr, (WORD)wParam, (SHORT)LOWORD(lParam), (SHORT)HIWORD(lParam)); - - case WM_RBUTTONUP: - return LISTVIEW_RButtonUp(infoPtr, (WORD)wParam, (SHORT)LOWORD(lParam), (SHORT)HIWORD(lParam)); - - case WM_SETCURSOR: - if(LISTVIEW_SetCursor(infoPtr, (HWND)wParam, LOWORD(lParam), HIWORD(lParam))) - return TRUE; - goto fwd_msg; - - case WM_SETFOCUS: - return LISTVIEW_SetFocus(infoPtr, (HWND)wParam); - - case WM_SETFONT: - return LISTVIEW_SetFont(infoPtr, (HFONT)wParam, (WORD)lParam); - - case WM_SETREDRAW: - return LISTVIEW_SetRedraw(infoPtr, (BOOL)wParam); - - case WM_SIZE: - return LISTVIEW_Size(infoPtr, (short)LOWORD(lParam), (short)HIWORD(lParam)); - - case WM_STYLECHANGED: - return LISTVIEW_StyleChanged(infoPtr, wParam, (LPSTYLESTRUCT)lParam); - - case WM_SYSCOLORCHANGE: - COMCTL32_RefreshSysColors(); - return 0; - -/* case WM_TIMER: */ - - case WM_VSCROLL: - return LISTVIEW_VScroll(infoPtr, (INT)LOWORD(wParam), 0, (HWND)lParam); - - case WM_MOUSEWHEEL: - if (wParam & (MK_SHIFT | MK_CONTROL)) - return DefWindowProcW(hwnd, uMsg, wParam, lParam); - return LISTVIEW_MouseWheel(infoPtr, (short int)HIWORD(wParam)); - - case WM_WINDOWPOSCHANGED: - if (!(((WINDOWPOS *)lParam)->flags & SWP_NOSIZE)) - { - SetWindowPos(infoPtr->hwndSelf, 0, 0, 0, 0, 0, SWP_FRAMECHANGED | SWP_NOACTIVATE | - SWP_NOZORDER | SWP_NOMOVE | SWP_NOSIZE); - LISTVIEW_UpdateSize(infoPtr); - LISTVIEW_UpdateScroll(infoPtr); - } - return DefWindowProcW(hwnd, uMsg, wParam, lParam); - -/* case WM_WININICHANGE: */ - - default: - if ((uMsg >= WM_USER) && (uMsg < WM_APP)) - ERR("unknown msg %04x wp=%08x lp=%08lx\n", uMsg, wParam, lParam); - - fwd_msg: - /* call default window procedure */ - return DefWindowProcW(hwnd, uMsg, wParam, lParam); - } - - return 0; -} - -/*** - * DESCRIPTION: - * Registers the window class. - * - * PARAMETER(S): - * None - * - * RETURN: - * None - */ -void LISTVIEW_Register(void) -{ - WNDCLASSW wndClass; - - ZeroMemory(&wndClass, sizeof(WNDCLASSW)); - wndClass.style = CS_GLOBALCLASS | CS_DBLCLKS; - wndClass.lpfnWndProc = LISTVIEW_WindowProc; - wndClass.cbClsExtra = 0; - wndClass.cbWndExtra = sizeof(LISTVIEW_INFO *); - wndClass.hCursor = LoadCursorW(0, (LPWSTR)IDC_ARROW); - wndClass.hbrBackground = (HBRUSH)(COLOR_WINDOW + 1); - wndClass.lpszClassName = WC_LISTVIEWW; - RegisterClassW(&wndClass); -} - -/*** - * DESCRIPTION: - * Unregisters the window class. - * - * PARAMETER(S): - * None - * - * RETURN: - * None - */ -void LISTVIEW_Unregister(void) -{ - UnregisterClassW(WC_LISTVIEWW, NULL); -} - -/*** - * DESCRIPTION: - * Handle any WM_COMMAND messages - * - * PARAMETER(S): - * [I] infoPtr : valid pointer to the listview structure - * [I] wParam : the first message parameter - * [I] lParam : the second message parameter - * - * RETURN: - * Zero. - */ -static LRESULT LISTVIEW_Command(LISTVIEW_INFO *infoPtr, WPARAM wParam, LPARAM lParam) -{ - switch (HIWORD(wParam)) - { - case EN_UPDATE: - { - /* - * Adjust the edit window size - */ - WCHAR buffer[1024]; - HDC hdc = GetDC(infoPtr->hwndEdit); - HFONT hFont, hOldFont = 0; - RECT rect; - SIZE sz; - int len; - - if (!infoPtr->hwndEdit || !hdc) return 0; - len = GetWindowTextW(infoPtr->hwndEdit, buffer, sizeof(buffer)/sizeof(buffer[0])); - GetWindowRect(infoPtr->hwndEdit, &rect); - - /* Select font to get the right dimension of the string */ - hFont = (HFONT)SendMessageW(infoPtr->hwndEdit, WM_GETFONT, 0, 0); - if(hFont != 0) - { - hOldFont = SelectObject(hdc, hFont); - } - - if (GetTextExtentPoint32W(hdc, buffer, lstrlenW(buffer), &sz)) - { - TEXTMETRICW textMetric; - - /* Add Extra spacing for the next character */ - GetTextMetricsW(hdc, &textMetric); - sz.cx += (textMetric.tmMaxCharWidth * 2); - - SetWindowPos ( - infoPtr->hwndEdit, - HWND_TOP, - 0, - 0, - sz.cx, - rect.bottom - rect.top, - SWP_DRAWFRAME|SWP_NOMOVE); - } - if(hFont != 0) - SelectObject(hdc, hOldFont); - - ReleaseDC(infoPtr->hwndSelf, hdc); - - break; - } - - default: - return SendMessageW (infoPtr->hwndNotify, WM_COMMAND, wParam, lParam); - } - - 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 - * [I] isW : TRUE if input is Unicode - * - * RETURN: - * Zero. - */ -static LRESULT EditLblWndProcT(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL isW) -{ - LISTVIEW_INFO *infoPtr = (LISTVIEW_INFO *)GetWindowLongPtrW(GetParent(hwnd), 0); - BOOL cancel = FALSE; - - TRACE("(hwnd=%p, uMsg=%x, wParam=%x, lParam=%lx, isW=%d)\n", - hwnd, uMsg, wParam, lParam, isW); - - switch (uMsg) - { - case WM_GETDLGCODE: - return DLGC_WANTARROWS | DLGC_WANTALLKEYS; - - case WM_KILLFOCUS: - break; - - case WM_DESTROY: - { - WNDPROC editProc = infoPtr->EditWndProc; - infoPtr->EditWndProc = 0; - SetWindowLongPtrW(hwnd, GWLP_WNDPROC, (DWORD_PTR)editProc); - return CallWindowProcT(editProc, hwnd, uMsg, wParam, lParam, isW); - } - - case WM_KEYDOWN: - if (VK_ESCAPE == (INT)wParam) - { - cancel = TRUE; - break; - } - else if (VK_RETURN == (INT)wParam) - break; - - default: - return CallWindowProcT(infoPtr->EditWndProc, hwnd, uMsg, wParam, lParam, isW); - } - - /* kill the edit */ - if (infoPtr->hwndEdit) - { - LPWSTR buffer = NULL; - - infoPtr->hwndEdit = 0; - if (!cancel) - { - DWORD len = isW ? GetWindowTextLengthW(hwnd) : GetWindowTextLengthA(hwnd); - - if (len) - { - if ( (buffer = Alloc((len+1) * (isW ? sizeof(WCHAR) : sizeof(CHAR)))) ) - { - if (isW) GetWindowTextW(hwnd, buffer, len+1); - else GetWindowTextA(hwnd, (CHAR*)buffer, len+1); - } - } - } - LISTVIEW_EndEditLabelT(infoPtr, buffer, isW); - - if (buffer) Free(buffer); - - } - - SendMessageW(hwnd, WM_CLOSE, 0, 0); - return 0; -} - -/*** - * DESCRIPTION: - * Subclassed edit control Unicode 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 - * - * RETURN: - */ -LRESULT CALLBACK EditLblWndProcW(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam) -{ - return EditLblWndProcT(hwnd, uMsg, wParam, lParam, TRUE); -} - -/*** - * DESCRIPTION: - * Subclassed edit control ANSI 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 - * - * RETURN: - */ -LRESULT CALLBACK EditLblWndProcA(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam) -{ - return EditLblWndProcT(hwnd, uMsg, wParam, lParam, FALSE); -} - -/*** - * DESCRIPTION: - * Creates a subclassed edit cotrol - * - * PARAMETER(S): - * [I] infoPtr : valid pointer to the listview structure - * [I] text : initial text for the edit - * [I] style : the window style - * [I] isW : TRUE if input is Unicode - * - * RETURN: - */ -static HWND CreateEditLabelT(LISTVIEW_INFO *infoPtr, LPCWSTR text, DWORD style, - INT x, INT y, INT width, INT height, BOOL isW) -{ - WCHAR editName[5] = { 'E', 'd', 'i', 't', '\0' }; - HWND hedit; - SIZE sz; - HDC hdc; - HDC hOldFont=0; - TEXTMETRICW textMetric; - HINSTANCE hinst = (HINSTANCE)GetWindowLongPtrW(infoPtr->hwndSelf, GWLP_HINSTANCE); - - TRACE("(text=%s, ..., isW=%d)\n", debugtext_t(text, isW), isW); - - style |= WS_CHILDWINDOW|WS_CLIPSIBLINGS|ES_LEFT|WS_BORDER; - hdc = GetDC(infoPtr->hwndSelf); - - /* Select the font to get appropriate metric dimensions */ - if(infoPtr->hFont != 0) - hOldFont = SelectObject(hdc, infoPtr->hFont); - - /*Get String Length in pixels */ - if(!GetTextExtentPoint32W(hdc, text, lstrlenW(text), &sz)) - sz.cx = 0; - - /*Add Extra spacing for the next character */ - GetTextMetricsW(hdc, &textMetric); - sz.cx += (textMetric.tmMaxCharWidth * 2); - - if(infoPtr->hFont != 0) - SelectObject(hdc, hOldFont); - - ReleaseDC(infoPtr->hwndSelf, hdc); - if (isW) - hedit = CreateWindowW(editName, text, style, x, y, sz.cx, height, infoPtr->hwndSelf, 0, hinst, 0); - else - hedit = CreateWindowA("Edit", (LPCSTR)text, style, x, y, sz.cx, height, infoPtr->hwndSelf, 0, hinst, 0); - - if (!hedit) return 0; - - infoPtr->EditWndProc = (WNDPROC) - (isW ? SetWindowLongPtrW(hedit, GWLP_WNDPROC, (DWORD_PTR)EditLblWndProcW) : - SetWindowLongPtrA(hedit, GWLP_WNDPROC, (DWORD_PTR)EditLblWndProcA) ); - - SendMessageW(hedit, WM_SETFONT, (WPARAM)infoPtr->hFont, FALSE); - - return hedit; -} diff --git a/reactos/lib/comctl32/makefile b/reactos/lib/comctl32/makefile deleted file mode 100644 index 39336bfb74e..00000000000 --- a/reactos/lib/comctl32/makefile +++ /dev/null @@ -1,9 +0,0 @@ -# $Id: makefile,v 1.6 2004/01/02 19:49:45 gvg Exp $ - -PATH_TO_TOP = ../.. - -TARGET_TYPE = winedll - -include $(PATH_TO_TOP)/rules.mak - -include $(TOOLS_PATH)/helper.mk diff --git a/reactos/lib/comctl32/monthcal.c b/reactos/lib/comctl32/monthcal.c deleted file mode 100644 index f1130aedb3b..00000000000 --- a/reactos/lib/comctl32/monthcal.c +++ /dev/null @@ -1,2045 +0,0 @@ -/* 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 and - * James Abbatiello - * Copyright 2000 Uwe Bonnes - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2.1 of the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - * - * 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 - * -- Unicodification - * -- handle resources better (doesn't work now); - * -- take care of internationalization. - * -- keyboard handling. - * -- GetRange: At the moment, we copy ranges anyway, regardless of - * infoPtr->rangeValid; a invalid range is simply filled - * with zeros in SetRange. Is this the right behavior? - * -- search for FIXME - */ - -#include -#include -#include -#include -#include - -#include "windef.h" -#include "winbase.h" -#include "wingdi.h" -#include "winuser.h" -#include "winnls.h" -#include "commctrl.h" -#include "comctl32.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_NEXTMONTHDELAY 350 /* when continuously pressing `next */ - /* month', wait 500 ms before going */ - /* to the next month */ -#define MC_NEXTMONTHTIMER 1 /* Timer ID's */ -#define MC_PREVMONTHTIMER 2 - -typedef struct -{ - HWND hwndSelf; - COLORREF bk; - COLORREF txt; - COLORREF titlebk; - COLORREF titletxt; - COLORREF monthbk; - COLORREF trailingtxt; - HFONT hFont; - HFONT hBoldFont; - int textHeight; - int textWidth; - int height_increment; - int width_increment; - int firstDayplace; /* place of the first day of the current month */ - 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 */ - int monthRange; - MONTHDAYSTATE *monthdayState; - SYSTEMTIME todaysDate; - DWORD currentMonth; - DWORD currentYear; - int status; /* See MC_SEL flags */ - int curSelDay; /* current selected day */ - int firstSelDay; /* first selected day */ - int maxSelCount; - SYSTEMTIME minSel; - SYSTEMTIME maxSel; - DWORD rangeValid; - SYSTEMTIME minDate; - SYSTEMTIME maxDate; - - RECT title; /* rect for the header above the calendar */ - RECT titlebtnnext; /* the `next month' button in the header */ - RECT titlebtnprev; /* the `prev month' button in the header */ - RECT titlemonth; /* the `month name' txt in the header */ - RECT titleyear; /* the `year number' txt in the header */ - RECT wdays; /* week days at top */ - RECT days; /* calendar area */ - RECT weeknums; /* week numbers at left side */ - 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 */ -} MONTHCAL_INFO, *LPMONTHCAL_INFO; - - -/* Offsets of days in the week to the weekday of january 1. */ -static const int DayOfWeekTable[] = {0, 3, 2, 5, 0, 3, 5, 1, 4, 6, 2, 4}; - - -#define MONTHCAL_GetInfoPtr(hwnd) ((MONTHCAL_INFO *)GetWindowLongPtrW(hwnd, 0)) - -/* helper functions */ - -/* 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, 0}; - /*Wrap around, this eases handling*/ - if(month == 0) - month = 12; - if(month == 13) - month = 1; - - /* 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]; - } -} - - -/* make sure that time is valid */ -static int MONTHCAL_ValidateTime(SYSTEMTIME time) -{ - if(time.wMonth > 12) return FALSE; - if(time.wDayOfWeek > 6) return FALSE; - if(time.wDay > MONTHCAL_MonthLength(time.wMonth, time.wYear)) - return FALSE; - if(time.wHour > 23) return FALSE; - if(time.wMinute > 59) return FALSE; - if(time.wSecond > 59) return FALSE; - if(time.wMilliseconds > 999) return FALSE; - - return TRUE; -} - - -void MONTHCAL_CopyTime(const SYSTEMTIME *from, SYSTEMTIME *to) -{ - to->wYear = from->wYear; - to->wMonth = from->wMonth; - to->wDayOfWeek = from->wDayOfWeek; - to->wDay = from->wDay; - to->wHour = from->wHour; - to->wMinute = from->wMinute; - to->wSecond = from->wSecond; - to->wMilliseconds = from->wMilliseconds; -} - - -/* 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 = Monday. -*/ - -/* returns the day in the week(0 == monday, 6 == sunday) */ -/* day(1 == 1st, 2 == 2nd... etc), year is the year value */ -static int MONTHCAL_CalculateDayOfWeek(DWORD day, DWORD month, DWORD year) -{ - year-=(month < 3); - - return((year + year/4 - year/100 + year/400 + - DayOfWeekTable[month-1] + day - 1 ) % 7); -} - -/* 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(MONTHCAL_INFO *infoPtr, int x, int y, - int *daypos,int *weekpos) -{ - int retval, firstDay; - RECT rcClient; - - GetClientRect(infoPtr->hwndSelf, &rcClient); - - /* if the point is outside the x bounds of the window put - it at the boundry */ - if (x > rcClient.right) - x = rcClient.right; - - - *daypos = (x - infoPtr->days.left ) / infoPtr->width_increment; - *weekpos = (y - infoPtr->days.top ) / infoPtr->height_increment; - - firstDay = (MONTHCAL_CalculateDayOfWeek(1, infoPtr->currentMonth, infoPtr->currentYear)+6 - infoPtr->firstDay)%7; - retval = *daypos + (7 * *weekpos) - firstDay; - return retval; -} - -/* day is the day of the month, 1 == 1st day of the month */ -/* sets x and y to be the position of the day */ -/* x == day, y == week where(0,0) == firstDay, 1st week */ -static void MONTHCAL_CalcDayXY(MONTHCAL_INFO *infoPtr, int day, int month, - int *x, int *y) -{ - int firstDay, prevMonth; - - firstDay = (MONTHCAL_CalculateDayOfWeek(1, infoPtr->currentMonth, infoPtr->currentYear) +6 - infoPtr->firstDay)%7; - - if(month==infoPtr->currentMonth) { - *x = (day + firstDay) % 7; - *y = (day + firstDay - *x) / 7; - return; - } - if(month < infoPtr->currentMonth) { - prevMonth = month - 1; - if(prevMonth==0) - prevMonth = 12; - - *x = (MONTHCAL_MonthLength(prevMonth, infoPtr->currentYear) - firstDay) % 7; - *y = 0; - return; - } - - *y = MONTHCAL_MonthLength(month, infoPtr->currentYear - 1) / 7; - *x = (day + firstDay + MONTHCAL_MonthLength(month, - infoPtr->currentYear)) % 7; -} - - -/* x: column(day), y: row(week) */ -static void MONTHCAL_CalcDayRect(MONTHCAL_INFO *infoPtr, RECT *r, int x, int y) -{ - r->left = infoPtr->days.left + x * infoPtr->width_increment; - r->right = r->left + infoPtr->width_increment; - r->top = infoPtr->days.top + y * infoPtr->height_increment; - r->bottom = r->top + infoPtr->textHeight; -} - - -/* sets the RECT struct r to the rectangle around the day and month */ -/* day is the day value of the month(1 == 1st), month is the month */ -/* value(january == 1, december == 12) */ -static inline void MONTHCAL_CalcPosFromDay(MONTHCAL_INFO *infoPtr, - int day, int month, RECT *r) -{ - int x, y; - - MONTHCAL_CalcDayXY(infoPtr, day, month, &x, &y); - MONTHCAL_CalcDayRect(infoPtr, r, x, y); -} - - -/* day is the day in the month(1 == 1st of the month) */ -/* month is the month value(1 == january, 12 == december) */ -static void MONTHCAL_CircleDay(MONTHCAL_INFO *infoPtr, HDC hdc, int day, int month) -{ - HPEN hRedPen = CreatePen(PS_SOLID, 2, RGB(255, 0, 0)); - HPEN hOldPen2 = SelectObject(hdc, hRedPen); - POINT points[13]; - int x, y; - RECT day_rect; - - - MONTHCAL_CalcPosFromDay(infoPtr, day, month, &day_rect); - - x = day_rect.left; - y = day_rect.top; - - points[0].x = x; - points[0].y = y - 1; - points[1].x = x + 0.8 * infoPtr->width_increment; - points[1].y = y - 1; - points[2].x = x + 0.9 * infoPtr->width_increment; - points[2].y = y; - points[3].x = x + infoPtr->width_increment; - points[3].y = y + 0.5 * infoPtr->height_increment; - - points[4].x = x + infoPtr->width_increment; - points[4].y = y + 0.9 * infoPtr->height_increment; - points[5].x = x + 0.6 * infoPtr->width_increment; - points[5].y = y + 0.9 * infoPtr->height_increment; - points[6].x = x + 0.5 * infoPtr->width_increment; - points[6].y = y + 0.9 * infoPtr->height_increment; /* bring the bottom up just - a hair to fit inside the day rectangle */ - - points[7].x = x + 0.2 * infoPtr->width_increment; - points[7].y = y + 0.8 * infoPtr->height_increment; - points[8].x = x + 0.1 * infoPtr->width_increment; - points[8].y = y + 0.8 * infoPtr->height_increment; - points[9].x = x; - points[9].y = y + 0.5 * infoPtr->height_increment; - - points[10].x = x + 0.1 * infoPtr->width_increment; - points[10].y = y + 0.2 * infoPtr->height_increment; - points[11].x = x + 0.2 * infoPtr->width_increment; - points[11].y = y + 0.3 * infoPtr->height_increment; - points[12].x = x + 0.4 * infoPtr->width_increment; - points[12].y = y + 0.2 * infoPtr->height_increment; - - PolyBezier(hdc, points, 13); - DeleteObject(hRedPen); - SelectObject(hdc, hOldPen2); -} - - -static void MONTHCAL_DrawDay(MONTHCAL_INFO *infoPtr, HDC hdc, int day, int month, - int x, int y, int bold) -{ - char buf[10]; - RECT r; - static int haveBoldFont, haveSelectedDay = FALSE; - HBRUSH hbr; - HPEN hNewPen, hOldPen = 0; - COLORREF oldCol = 0; - COLORREF oldBk = 0; - - sprintf(buf, "%d", day); - -/* No need to check styles: when selection is not valid, it is set to zero. - * 1=infoPtr->minSel.wDay) && (day<=infoPtr->maxSel.wDay) - && (month==infoPtr->currentMonth)) { - HRGN hrgn; - RECT r2; - - TRACE("%d %d %d\n",day, infoPtr->minSel.wDay, infoPtr->maxSel.wDay); - TRACE("%ld %ld %ld %ld\n", r.left, r.top, r.right, r.bottom); - oldCol = SetTextColor(hdc, infoPtr->monthbk); - oldBk = SetBkColor(hdc, infoPtr->trailingtxt); - hbr = GetSysColorBrush(COLOR_GRAYTEXT); - hrgn = CreateEllipticRgn(r.left, r.top, r.right, r.bottom); - FillRgn(hdc, hrgn, hbr); - - /* FIXME: this may need to be changed now b/c of the other - drawing changes 11/3/99 CMM */ - r2.left = r.left - 0.25 * infoPtr->textWidth; - r2.top = r.top; - r2.right = r.left + 0.5 * infoPtr->textWidth; - r2.bottom = r.bottom; - if(haveSelectedDay) FillRect(hdc, &r2, hbr); - haveSelectedDay = TRUE; - } else { - haveSelectedDay = FALSE; - } - - /* need to add some code for multiple selections */ - - if((bold) &&(!haveBoldFont)) { - SelectObject(hdc, infoPtr->hBoldFont); - haveBoldFont = TRUE; - } - if((!bold) &&(haveBoldFont)) { - SelectObject(hdc, infoPtr->hFont); - haveBoldFont = FALSE; - } - - if(haveSelectedDay) { - SetTextColor(hdc, oldCol); - SetBkColor(hdc, oldBk); - } - - SetBkMode(hdc,TRANSPARENT); - DrawTextA(hdc, buf, -1, &r, DT_CENTER | DT_VCENTER | DT_SINGLELINE ); - - /* draw a rectangle around the currently selected days text */ - if((day==infoPtr->curSelDay) && (month==infoPtr->currentMonth)) { - hNewPen = CreatePen(PS_ALTERNATE, 0, GetSysColor(COLOR_WINDOWTEXT) ); - hbr = GetSysColorBrush(COLOR_WINDOWTEXT); - FrameRect(hdc, &r, hbr); - SelectObject(hdc, hOldPen); - } -} - - -static void MONTHCAL_Refresh(MONTHCAL_INFO *infoPtr, HDC hdc, PAINTSTRUCT* ps) -{ - RECT *title=&infoPtr->title; - RECT *prev=&infoPtr->titlebtnprev; - RECT *next=&infoPtr->titlebtnnext; - RECT *titlemonth=&infoPtr->titlemonth; - RECT *titleyear=&infoPtr->titleyear; - RECT dayrect; - RECT *days=&dayrect; - RECT rtoday; - int i, j, m, mask, day, firstDay, weeknum, weeknum1,prevMonth; - int textHeight = infoPtr->textHeight, textWidth = infoPtr->textWidth; - SIZE size; - HBRUSH hbr; - HFONT currentFont; - char buf[20]; - char buf1[20]; - char buf2[32]; - COLORREF oldTextColor, oldBkColor; - DWORD dwStyle = GetWindowLongW(infoPtr->hwndSelf, GWL_STYLE); - RECT rcTemp; - RECT rcDay; /* used in MONTHCAL_CalcDayRect() */ - SYSTEMTIME localtime; - int startofprescal; - - oldTextColor = SetTextColor(hdc, GetSysColor(COLOR_WINDOWTEXT)); - - /* fill background */ - hbr = CreateSolidBrush (infoPtr->bk); - FillRect(hdc, &ps->rcPaint, hbr); - DeleteObject(hbr); - - /* draw header */ - if(IntersectRect(&rcTemp, &(ps->rcPaint), title)) - { - hbr = CreateSolidBrush(infoPtr->titlebk); - FillRect(hdc, title, hbr); - DeleteObject(hbr); - } - - /* if the previous button is pressed draw it depressed */ - if(IntersectRect(&rcTemp, &(ps->rcPaint), prev)) - { - if((infoPtr->status & MC_PREVPRESSED)) - DrawFrameControl(hdc, prev, DFC_SCROLL, - DFCS_SCROLLLEFT | DFCS_PUSHED | - (dwStyle & WS_DISABLED ? DFCS_INACTIVE : 0)); - else /* if the previous button is pressed draw it depressed */ - DrawFrameControl(hdc, prev, DFC_SCROLL, - DFCS_SCROLLLEFT |(dwStyle & WS_DISABLED ? DFCS_INACTIVE : 0)); - } - - /* if next button is depressed draw it depressed */ - if(IntersectRect(&rcTemp, &(ps->rcPaint), next)) - { - if((infoPtr->status & MC_NEXTPRESSED)) - DrawFrameControl(hdc, next, DFC_SCROLL, - DFCS_SCROLLRIGHT | DFCS_PUSHED | - (dwStyle & WS_DISABLED ? DFCS_INACTIVE : 0)); - else /* if the next button is pressed draw it depressed */ - DrawFrameControl(hdc, next, DFC_SCROLL, - DFCS_SCROLLRIGHT |(dwStyle & WS_DISABLED ? DFCS_INACTIVE : 0)); - } - - oldBkColor = SetBkColor(hdc, infoPtr->titlebk); - SetTextColor(hdc, infoPtr->titletxt); - currentFont = SelectObject(hdc, infoPtr->hBoldFont); - - /* titlemonth->left and right are set in MONTHCAL_UpdateSize */ - titlemonth->left = title->left; - titlemonth->right = title->right; - - GetLocaleInfoA( LOCALE_USER_DEFAULT,LOCALE_SMONTHNAME1+infoPtr->currentMonth -1, - buf1,sizeof(buf1)); - sprintf(buf, "%s %ld", buf1, infoPtr->currentYear); - - if(IntersectRect(&rcTemp, &(ps->rcPaint), titlemonth)) - { - DrawTextA(hdc, buf, strlen(buf), titlemonth, - DT_CENTER | DT_VCENTER | DT_SINGLELINE); - } - - SelectObject(hdc, infoPtr->hFont); - -/* titlemonth left/right contained rect for whole titletxt('June 1999') - * MCM_HitTestInfo wants month & year rects, so prepare these now. - *(no, we can't draw them separately; the whole text is centered) - */ - GetTextExtentPoint32A(hdc, buf, strlen(buf), &size); - titlemonth->left = title->right / 2 - size.cx / 2; - titleyear->right = title->right / 2 + size.cx / 2; - GetTextExtentPoint32A(hdc, buf1, strlen(buf1), &size); - titlemonth->right = titlemonth->left + size.cx; - titleyear->left = titlemonth->right; - - /* draw month area */ - rcTemp.top=infoPtr->wdays.top; - rcTemp.left=infoPtr->wdays.left; - rcTemp.bottom=infoPtr->todayrect.bottom; - rcTemp.right =infoPtr->todayrect.right; - if(IntersectRect(&rcTemp, &(ps->rcPaint), &rcTemp)) - { - hbr = CreateSolidBrush(infoPtr->monthbk); - FillRect(hdc, &rcTemp, hbr); - DeleteObject(hbr); - } - -/* draw line under day abbreviatons */ - - MoveToEx(hdc, infoPtr->days.left + 3, title->bottom + textHeight + 1, NULL); - LineTo(hdc, infoPtr->days.right - 3, title->bottom + textHeight + 1); - - prevMonth = infoPtr->currentMonth - 1; - if(prevMonth == 0) /* if currentMonth is january(1) prevMonth is */ - prevMonth = 12; /* december(12) of the previous year */ - - infoPtr->wdays.left = infoPtr->days.left = infoPtr->weeknums.right; -/* draw day abbreviations */ - - SetBkColor(hdc, infoPtr->monthbk); - SetTextColor(hdc, infoPtr->trailingtxt); - - /* copy this rect so we can change the values without changing */ - /* the original version */ - days->left = infoPtr->wdays.left; - days->right = days->left + infoPtr->width_increment; - days->top = infoPtr->wdays.top; - days->bottom = infoPtr->wdays.bottom; - - i = infoPtr->firstDay; - - for(j=0; j<7; j++) { - GetLocaleInfoA( LOCALE_USER_DEFAULT,LOCALE_SABBREVDAYNAME1 + (i +j)%7, - buf,sizeof(buf)); - DrawTextA(hdc, buf, strlen(buf), days, - DT_CENTER | DT_VCENTER | DT_SINGLELINE ); - days->left+=infoPtr->width_increment; - days->right+=infoPtr->width_increment; - } - -/* draw day numbers; first, the previous month */ - - firstDay = MONTHCAL_CalculateDayOfWeek(1, infoPtr->currentMonth, infoPtr->currentYear); - - day = MONTHCAL_MonthLength(prevMonth, infoPtr->currentYear) + - (infoPtr->firstDay + 7 - firstDay)%7 + 1; - if (day > MONTHCAL_MonthLength(prevMonth, infoPtr->currentYear)) - day -=7; - startofprescal = day; - mask = 1<<(day-1); - - i = 0; - m = 0; - while(day <= MONTHCAL_MonthLength(prevMonth, infoPtr->currentYear)) { - MONTHCAL_CalcDayRect(infoPtr, &rcDay, i, 0); - if(IntersectRect(&rcTemp, &(ps->rcPaint), &rcDay)) - { - MONTHCAL_DrawDay(infoPtr, hdc, day, prevMonth, i, 0, - infoPtr->monthdayState[m] & mask); - } - - mask<<=1; - day++; - i++; - } - -/* draw `current' month */ - - day = 1; /* start at the beginning of the current month */ - - infoPtr->firstDayplace = i; - SetTextColor(hdc, infoPtr->txt); - m++; - mask = 1; - - /* draw the first week of the current month */ - while(i<7) { - MONTHCAL_CalcDayRect(infoPtr, &rcDay, i, 0); - if(IntersectRect(&rcTemp, &(ps->rcPaint), &rcDay)) - { - - MONTHCAL_DrawDay(infoPtr, hdc, day, infoPtr->currentMonth, i, 0, - infoPtr->monthdayState[m] & mask); - - if((infoPtr->currentMonth==infoPtr->todaysDate.wMonth) && - (day==infoPtr->todaysDate.wDay) && - (infoPtr->currentYear == infoPtr->todaysDate.wYear)) { - if(!(dwStyle & MCS_NOTODAYCIRCLE)) - MONTHCAL_CircleDay(infoPtr, hdc, day, infoPtr->currentMonth); - } - } - - mask<<=1; - day++; - i++; - } - - j = 1; /* move to the 2nd week of the current month */ - i = 0; /* move back to sunday */ - while(day <= MONTHCAL_MonthLength(infoPtr->currentMonth, infoPtr->currentYear)) { - MONTHCAL_CalcDayRect(infoPtr, &rcDay, i, j); - if(IntersectRect(&rcTemp, &(ps->rcPaint), &rcDay)) - { - MONTHCAL_DrawDay(infoPtr, hdc, day, infoPtr->currentMonth, i, j, - infoPtr->monthdayState[m] & mask); - - if((infoPtr->currentMonth==infoPtr->todaysDate.wMonth) && - (day==infoPtr->todaysDate.wDay) && - (infoPtr->currentYear == infoPtr->todaysDate.wYear)) - if(!(dwStyle & MCS_NOTODAYCIRCLE)) - MONTHCAL_CircleDay(infoPtr, hdc, day, infoPtr->currentMonth); - } - mask<<=1; - day++; - i++; - if(i>6) { /* past saturday, goto the next weeks sunday */ - i = 0; - j++; - } - } - -/* draw `next' month */ - - day = 1; /* start at the first day of the next month */ - m++; - mask = 1; - - SetTextColor(hdc, infoPtr->trailingtxt); - while((i<7) &&(j<6)) { - MONTHCAL_CalcDayRect(infoPtr, &rcDay, i, j); - if(IntersectRect(&rcTemp, &(ps->rcPaint), &rcDay)) - { - MONTHCAL_DrawDay(infoPtr, hdc, day, infoPtr->currentMonth + 1, i, j, - infoPtr->monthdayState[m] & mask); - } - - mask<<=1; - day++; - i++; - if(i==7) { /* past saturday, go to next week's sunday */ - i = 0; - j++; - } - } - SetTextColor(hdc, infoPtr->txt); - - -/* draw `today' date if style allows it, and draw a circle before today's - * date if necessary */ - - if(!(dwStyle & MCS_NOTODAY)) { - int offset = 0; - if(!(dwStyle & MCS_NOTODAYCIRCLE)) { - /*day is the number of days from nextmonth we put on the calendar */ - MONTHCAL_CircleDay(infoPtr, hdc, - day+MONTHCAL_MonthLength(infoPtr->currentMonth,infoPtr->currentYear), - infoPtr->currentMonth); - offset+=textWidth; - } - if (!LoadStringA(COMCTL32_hModule,IDM_TODAY,buf1,sizeof(buf1))) - { - WARN("Can't load resource\n"); - strcpy(buf1,"Today:"); - } - MONTHCAL_CalcDayRect(infoPtr, &rtoday, 1, 6); - MONTHCAL_CopyTime(&infoPtr->todaysDate,&localtime); - GetDateFormatA(LOCALE_USER_DEFAULT,DATE_SHORTDATE,&localtime,NULL,buf2,sizeof(buf2)); - sprintf(buf, "%s %s", buf1,buf2); - SelectObject(hdc, infoPtr->hBoldFont); - - if(IntersectRect(&rcTemp, &(ps->rcPaint), &rtoday)) - { - DrawTextA(hdc, buf, -1, &rtoday, DT_CALCRECT | DT_LEFT | DT_VCENTER | DT_SINGLELINE); - DrawTextA(hdc, buf, -1, &rtoday, DT_LEFT | DT_VCENTER | DT_SINGLELINE); - } - SelectObject(hdc, infoPtr->hFont); - } - -/*eventually draw week numbers*/ - if(dwStyle & MCS_WEEKNUMBERS) { - /* display weeknumbers*/ - int mindays; - - /* 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 - */ - GetLocaleInfoA(LOCALE_USER_DEFAULT, LOCALE_IFIRSTWEEKOFYEAR, - buf, sizeof(buf)); - sscanf(buf, "%d", &weeknum); - switch (weeknum) - { - case 1: mindays = 6; - break; - case 2: mindays = 3; - break; - case 0: - default: - mindays = 0; - } - if (infoPtr->currentMonth < 2) - { - /* calculate all those exceptions for january */ - weeknum1=MONTHCAL_CalculateDayOfWeek(1,1,infoPtr->currentYear); - if ((infoPtr->firstDay +7 - weeknum1)%7 > mindays) - weeknum =1; - else - { - weeknum = 0; - for(i=0; i<11; i++) - weeknum+=MONTHCAL_MonthLength(i+1, infoPtr->currentYear-1); - weeknum +=startofprescal+ 7; - weeknum /=7; - weeknum1=MONTHCAL_CalculateDayOfWeek(1,1,infoPtr->currentYear-1); - if ((infoPtr->firstDay + 7 - weeknum1)%7 > mindays) - weeknum++; - } - } - else - { - weeknum = 0; - for(i=0; icurrentYear); - weeknum +=startofprescal+ 7; - weeknum /=7; - weeknum1=MONTHCAL_CalculateDayOfWeek(1,1,infoPtr->currentYear); - if ((infoPtr->firstDay + 7 - weeknum1)%7 > mindays) - weeknum++; - } - days->left = infoPtr->weeknums.left; - days->right = infoPtr->weeknums.right; - days->top = infoPtr->weeknums.top; - days->bottom = days->top +infoPtr->height_increment; - for(i=0; i<6; i++) { - if((i==0)&&(weeknum>50)) - { - sprintf(buf, "%d", weeknum); - weeknum=0; - } - else if((i==5)&&(weeknum>47)) - { - sprintf(buf, "%d", 1); - } - else - sprintf(buf, "%d", weeknum + i); - DrawTextA(hdc, buf, -1, days, DT_CENTER | DT_VCENTER | DT_SINGLELINE ); - days->top+=infoPtr->height_increment; - days->bottom+=infoPtr->height_increment; - } - - MoveToEx(hdc, infoPtr->weeknums.right, infoPtr->weeknums.top + 3 , NULL); - LineTo(hdc, infoPtr->weeknums.right, infoPtr->weeknums.bottom ); - - } - /* currentFont was font at entering Refresh */ - - SetBkColor(hdc, oldBkColor); - SelectObject(hdc, currentFont); - SetTextColor(hdc, oldTextColor); -} - - -static LRESULT -MONTHCAL_GetMinReqRect(MONTHCAL_INFO *infoPtr, LPARAM lParam) -{ - LPRECT lpRect = (LPRECT) lParam; - - TRACE("rect %p\n", lpRect); - - /* validate parameters */ - - if((infoPtr==NULL) ||(lpRect == NULL) ) return FALSE; - - lpRect->left = infoPtr->title.left; - lpRect->top = infoPtr->title.top; - lpRect->right = infoPtr->title.right; - lpRect->bottom = infoPtr->todayrect.bottom; - AdjustWindowRect(lpRect, GetWindowLongW(infoPtr->hwndSelf, GWL_STYLE), FALSE); - - TRACE("%s\n", wine_dbgstr_rect(lpRect)); - - return TRUE; -} - - -static LRESULT -MONTHCAL_GetColor(MONTHCAL_INFO *infoPtr, WPARAM wParam) -{ - TRACE("\n"); - - switch((int)wParam) { - 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; -} - - -static LRESULT -MONTHCAL_SetColor(MONTHCAL_INFO *infoPtr, WPARAM wParam, LPARAM lParam) -{ - int prev = -1; - - TRACE("%d: color %08lx\n", wParam, lParam); - - switch((int)wParam) { - case MCSC_BACKGROUND: - prev = infoPtr->bk; - infoPtr->bk = (COLORREF)lParam; - break; - case MCSC_TEXT: - prev = infoPtr->txt; - infoPtr->txt = (COLORREF)lParam; - break; - case MCSC_TITLEBK: - prev = infoPtr->titlebk; - infoPtr->titlebk = (COLORREF)lParam; - break; - case MCSC_TITLETEXT: - prev=infoPtr->titletxt; - infoPtr->titletxt = (COLORREF)lParam; - break; - case MCSC_MONTHBK: - prev = infoPtr->monthbk; - infoPtr->monthbk = (COLORREF)lParam; - break; - case MCSC_TRAILINGTEXT: - prev = infoPtr->trailingtxt; - infoPtr->trailingtxt = (COLORREF)lParam; - break; - } - - InvalidateRect(infoPtr->hwndSelf, NULL, FALSE); - return prev; -} - - -static LRESULT -MONTHCAL_GetMonthDelta(MONTHCAL_INFO *infoPtr) -{ - TRACE("\n"); - - if(infoPtr->delta) - return infoPtr->delta; - else - return infoPtr->visible; -} - - -static LRESULT -MONTHCAL_SetMonthDelta(MONTHCAL_INFO *infoPtr, WPARAM wParam) -{ - int prev = infoPtr->delta; - - TRACE("delta %d\n", wParam); - - infoPtr->delta = (int)wParam; - return prev; -} - - -static LRESULT -MONTHCAL_GetFirstDayOfWeek(MONTHCAL_INFO *infoPtr) -{ - return infoPtr->firstDay; -} - - -/* sets the first day of the week that will appear in the control */ -/* 0 == Monday, 6 == Sunday */ -/* FIXME: this needs to be implemented properly in MONTHCAL_Refresh() */ -/* FIXME: we need more error checking here */ -static LRESULT -MONTHCAL_SetFirstDayOfWeek(MONTHCAL_INFO *infoPtr, LPARAM lParam) -{ - int prev = infoPtr->firstDay; - char buf[40]; - int day; - - TRACE("day %ld\n", lParam); - - if((lParam >= 0) && (lParam < 7)) { - infoPtr->firstDay = (int)lParam; - } - else - { - GetLocaleInfoA(LOCALE_USER_DEFAULT, LOCALE_IFIRSTDAYOFWEEK, - buf, sizeof(buf)); - TRACE("%s %d\n", buf, strlen(buf)); - if(sscanf(buf, "%d", &day) == 1) - infoPtr->firstDay = day; - else - infoPtr->firstDay = 0; - } - return prev; -} - - -static LRESULT -MONTHCAL_GetMonthRange(MONTHCAL_INFO *infoPtr) -{ - TRACE("\n"); - - return infoPtr->monthRange; -} - - -static LRESULT -MONTHCAL_GetMaxTodayWidth(MONTHCAL_INFO *infoPtr) -{ - return(infoPtr->todayrect.right - infoPtr->todayrect.left); -} - - -/* FIXME: are validated times taken from current date/time or simply - * copied? - * FIXME: check whether MCM_GETMONTHRANGE shows correct result after - * adjusting range with MCM_SETRANGE - */ - -static LRESULT -MONTHCAL_SetRange(MONTHCAL_INFO *infoPtr, WPARAM wParam, LPARAM lParam) -{ - SYSTEMTIME *lprgSysTimeArray=(SYSTEMTIME *)lParam; - int prev; - - TRACE("%x %lx\n", wParam, lParam); - - if(wParam & GDTR_MAX) { - if(MONTHCAL_ValidateTime(lprgSysTimeArray[1])){ - MONTHCAL_CopyTime(&lprgSysTimeArray[1], &infoPtr->maxDate); - infoPtr->rangeValid|=GDTR_MAX; - } else { - GetSystemTime(&infoPtr->todaysDate); - MONTHCAL_CopyTime(&infoPtr->todaysDate, &infoPtr->maxDate); - } - } - if(wParam & GDTR_MIN) { - if(MONTHCAL_ValidateTime(lprgSysTimeArray[0])) { - MONTHCAL_CopyTime(&lprgSysTimeArray[0], &infoPtr->minDate); - infoPtr->rangeValid|=GDTR_MIN; - } else { - GetSystemTime(&infoPtr->todaysDate); - MONTHCAL_CopyTime(&infoPtr->todaysDate, &infoPtr->minDate); - } - } - - prev = infoPtr->monthRange; - infoPtr->monthRange = infoPtr->maxDate.wMonth - infoPtr->minDate.wMonth; - - if(infoPtr->monthRange!=prev) { - infoPtr->monthdayState = ReAlloc(infoPtr->monthdayState, - infoPtr->monthRange * sizeof(MONTHDAYSTATE)); - } - - return 1; -} - - -static LRESULT -MONTHCAL_GetRange(HWND hwnd, WPARAM wParam, LPARAM lParam) -{ - MONTHCAL_INFO *infoPtr = MONTHCAL_GetInfoPtr(hwnd); - SYSTEMTIME *lprgSysTimeArray = (SYSTEMTIME *)lParam; - - /* validate parameters */ - - if((infoPtr==NULL) || (lprgSysTimeArray==NULL)) return FALSE; - - MONTHCAL_CopyTime(&infoPtr->maxDate, &lprgSysTimeArray[1]); - MONTHCAL_CopyTime(&infoPtr->minDate, &lprgSysTimeArray[0]); - - return infoPtr->rangeValid; -} - - -static LRESULT -MONTHCAL_SetDayState(MONTHCAL_INFO *infoPtr, WPARAM wParam, LPARAM lParam) - -{ - int i, iMonths = (int)wParam; - MONTHDAYSTATE *dayStates = (LPMONTHDAYSTATE)lParam; - - TRACE("%x %lx\n", wParam, lParam); - if(iMonths!=infoPtr->monthRange) return 0; - - for(i=0; imonthdayState[i] = dayStates[i]; - return 1; -} - -static LRESULT -MONTHCAL_GetCurSel(MONTHCAL_INFO *infoPtr, LPARAM lParam) -{ - SYSTEMTIME *lpSel = (SYSTEMTIME *) lParam; - - TRACE("%lx\n", lParam); - if((infoPtr==NULL) ||(lpSel==NULL)) return FALSE; - if(GetWindowLongW(infoPtr->hwndSelf, GWL_STYLE) & MCS_MULTISELECT) return FALSE; - - MONTHCAL_CopyTime(&infoPtr->minSel, lpSel); - TRACE("%d/%d/%d\n", lpSel->wYear, lpSel->wMonth, lpSel->wDay); - return TRUE; -} - -/* FIXME: if the specified date is not visible, make it visible */ -/* FIXME: redraw? */ -static LRESULT -MONTHCAL_SetCurSel(MONTHCAL_INFO *infoPtr, LPARAM lParam) -{ - SYSTEMTIME *lpSel = (SYSTEMTIME *)lParam; - - TRACE("%lx\n", lParam); - if((infoPtr==NULL) ||(lpSel==NULL)) return FALSE; - if(GetWindowLongW(infoPtr->hwndSelf, GWL_STYLE) & MCS_MULTISELECT) return FALSE; - - infoPtr->currentMonth=lpSel->wMonth; - infoPtr->currentYear=lpSel->wYear; - - MONTHCAL_CopyTime(lpSel, &infoPtr->minSel); - MONTHCAL_CopyTime(lpSel, &infoPtr->maxSel); - - InvalidateRect(infoPtr->hwndSelf, NULL, FALSE); - - return TRUE; -} - - -static LRESULT -MONTHCAL_GetMaxSelCount(MONTHCAL_INFO *infoPtr) -{ - return infoPtr->maxSelCount; -} - - -static LRESULT -MONTHCAL_SetMaxSelCount(MONTHCAL_INFO *infoPtr, WPARAM wParam) -{ - TRACE("%x\n", wParam); - - if(GetWindowLongW(infoPtr->hwndSelf, GWL_STYLE) & MCS_MULTISELECT) { - infoPtr->maxSelCount = wParam; - } - - return TRUE; -} - - -static LRESULT -MONTHCAL_GetSelRange(MONTHCAL_INFO *infoPtr, LPARAM lParam) -{ - SYSTEMTIME *lprgSysTimeArray = (SYSTEMTIME *) lParam; - - TRACE("%lx\n", lParam); - - /* validate parameters */ - - if((infoPtr==NULL) ||(lprgSysTimeArray==NULL)) return FALSE; - - if(GetWindowLongW(infoPtr->hwndSelf, GWL_STYLE) & MCS_MULTISELECT) - { - MONTHCAL_CopyTime(&infoPtr->maxSel, &lprgSysTimeArray[1]); - MONTHCAL_CopyTime(&infoPtr->minSel, &lprgSysTimeArray[0]); - TRACE("[min,max]=[%d %d]\n", infoPtr->minSel.wDay, infoPtr->maxSel.wDay); - return TRUE; - } - - return FALSE; -} - - -static LRESULT -MONTHCAL_SetSelRange(MONTHCAL_INFO *infoPtr, LPARAM lParam) -{ - SYSTEMTIME *lprgSysTimeArray = (SYSTEMTIME *) lParam; - - TRACE("%lx\n", lParam); - - /* validate parameters */ - - if((infoPtr==NULL) ||(lprgSysTimeArray==NULL)) return FALSE; - - if(GetWindowLongW(infoPtr->hwndSelf, GWL_STYLE) & MCS_MULTISELECT) - { - MONTHCAL_CopyTime(&lprgSysTimeArray[1], &infoPtr->maxSel); - MONTHCAL_CopyTime(&lprgSysTimeArray[0], &infoPtr->minSel); - TRACE("[min,max]=[%d %d]\n", infoPtr->minSel.wDay, infoPtr->maxSel.wDay); - return TRUE; - } - - return FALSE; -} - - -static LRESULT -MONTHCAL_GetToday(MONTHCAL_INFO *infoPtr, LPARAM lParam) -{ - SYSTEMTIME *lpToday = (SYSTEMTIME *) lParam; - - TRACE("%lx\n", lParam); - - /* validate parameters */ - - if((infoPtr==NULL) || (lpToday==NULL)) return FALSE; - MONTHCAL_CopyTime(&infoPtr->todaysDate, lpToday); - return TRUE; -} - - -static LRESULT -MONTHCAL_SetToday(MONTHCAL_INFO *infoPtr, LPARAM lParam) -{ - SYSTEMTIME *lpToday = (SYSTEMTIME *) lParam; - - TRACE("%lx\n", lParam); - - /* validate parameters */ - - if((infoPtr==NULL) ||(lpToday==NULL)) return FALSE; - MONTHCAL_CopyTime(lpToday, &infoPtr->todaysDate); - InvalidateRect(infoPtr->hwndSelf, NULL, FALSE); - return TRUE; -} - - -static LRESULT -MONTHCAL_HitTest(MONTHCAL_INFO *infoPtr, LPARAM lParam) -{ - PMCHITTESTINFO lpht = (PMCHITTESTINFO)lParam; - UINT x,y; - DWORD retval; - int day,wday,wnum; - - - x = lpht->pt.x; - y = lpht->pt.y; - retval = MCHT_NOWHERE; - - - /* 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); - */ - - /* are we in the header? */ - - if(PtInRect(&infoPtr->title, lpht->pt)) { - if(PtInRect(&infoPtr->titlebtnprev, lpht->pt)) { - retval = MCHT_TITLEBTNPREV; - goto done; - } - if(PtInRect(&infoPtr->titlebtnnext, lpht->pt)) { - retval = MCHT_TITLEBTNNEXT; - goto done; - } - if(PtInRect(&infoPtr->titlemonth, lpht->pt)) { - retval = MCHT_TITLEMONTH; - goto done; - } - if(PtInRect(&infoPtr->titleyear, lpht->pt)) { - retval = MCHT_TITLEYEAR; - goto done; - } - - retval = MCHT_TITLE; - goto done; - } - - day = MONTHCAL_CalcDayFromPos(infoPtr,x,y,&wday,&wnum); - if(PtInRect(&infoPtr->wdays, lpht->pt)) { - retval = MCHT_CALENDARDAY; - lpht->st.wYear = infoPtr->currentYear; - lpht->st.wMonth = (day < 1)? infoPtr->currentMonth -1 : infoPtr->currentMonth; - lpht->st.wDay = (day < 1)? - MONTHCAL_MonthLength(infoPtr->currentMonth-1,infoPtr->currentYear) -day : day; - goto done; - } - if(PtInRect(&infoPtr->weeknums, lpht->pt)) { - retval = MCHT_CALENDARWEEKNUM; - lpht->st.wYear = infoPtr->currentYear; - lpht->st.wMonth = (day < 1) ? infoPtr->currentMonth -1 : - (day > MONTHCAL_MonthLength(infoPtr->currentMonth,infoPtr->currentYear)) ? - infoPtr->currentMonth +1 :infoPtr->currentMonth; - lpht->st.wDay = (day < 1 ) ? - MONTHCAL_MonthLength(infoPtr->currentMonth-1,infoPtr->currentYear) -day : - (day > MONTHCAL_MonthLength(infoPtr->currentMonth,infoPtr->currentYear)) ? - day - MONTHCAL_MonthLength(infoPtr->currentMonth,infoPtr->currentYear) : day; - goto done; - } - if(PtInRect(&infoPtr->days, lpht->pt)) - { - lpht->st.wYear = infoPtr->currentYear; - if ( day < 1) - { - retval = MCHT_CALENDARDATEPREV; - lpht->st.wMonth = infoPtr->currentMonth - 1; - if (lpht->st.wMonth <1) - { - lpht->st.wMonth = 12; - lpht->st.wYear--; - } - lpht->st.wDay = MONTHCAL_MonthLength(lpht->st.wMonth,lpht->st.wYear) -day; - } - else if (day > MONTHCAL_MonthLength(infoPtr->currentMonth,infoPtr->currentYear)) - { - retval = MCHT_CALENDARDATENEXT; - lpht->st.wMonth = infoPtr->currentMonth + 1; - if (lpht->st.wMonth <12) - { - lpht->st.wMonth = 1; - lpht->st.wYear++; - } - lpht->st.wDay = day - MONTHCAL_MonthLength(infoPtr->currentMonth,infoPtr->currentYear) ; - } - else { - retval = MCHT_CALENDARDATE; - lpht->st.wMonth = infoPtr->currentMonth; - lpht->st.wDay = day; - } - goto done; - } - if(PtInRect(&infoPtr->todayrect, lpht->pt)) { - retval = MCHT_TODAYLINK; - goto done; - } - - - /* Hit nothing special? What's left must be background :-) */ - - retval = MCHT_CALENDARBK; - done: - lpht->uHit = retval; - return retval; -} - - -static void MONTHCAL_GoToNextMonth(MONTHCAL_INFO *infoPtr) -{ - DWORD dwStyle = GetWindowLongW(infoPtr->hwndSelf, GWL_STYLE); - - TRACE("MONTHCAL_GoToNextMonth\n"); - - infoPtr->currentMonth++; - if(infoPtr->currentMonth > 12) { - infoPtr->currentYear++; - infoPtr->currentMonth = 1; - } - - if(dwStyle & MCS_DAYSTATE) { - NMDAYSTATE nmds; - int i; - - 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)); - - SendMessageA(infoPtr->hwndNotify, WM_NOTIFY, - (WPARAM)nmds.nmhdr.idFrom, (LPARAM)&nmds); - for(i=0; imonthRange; i++) - infoPtr->monthdayState[i] = nmds.prgDayState[i]; - } -} - - -static void MONTHCAL_GoToPrevMonth(MONTHCAL_INFO *infoPtr) -{ - DWORD dwStyle = GetWindowLongW(infoPtr->hwndSelf, GWL_STYLE); - - TRACE("\n"); - - infoPtr->currentMonth--; - if(infoPtr->currentMonth < 1) { - infoPtr->currentYear--; - infoPtr->currentMonth = 12; - } - - if(dwStyle & MCS_DAYSTATE) { - NMDAYSTATE nmds; - int i; - - 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)); - - SendMessageA(infoPtr->hwndNotify, WM_NOTIFY, - (WPARAM)nmds.nmhdr.idFrom, (LPARAM)&nmds); - for(i=0; imonthRange; i++) - infoPtr->monthdayState[i] = nmds.prgDayState[i]; - } -} - -static LRESULT -MONTHCAL_RButtonDown(MONTHCAL_INFO *infoPtr, LPARAM lParam) -{ - HMENU hMenu; - POINT menupoint; - char buf[32]; - - hMenu = CreatePopupMenu(); - if (!LoadStringA(COMCTL32_hModule,IDM_GOTODAY,buf,sizeof(buf))) - { - WARN("Can't load resource\n"); - strcpy(buf,"Go to Today:"); - } - AppendMenuA(hMenu, MF_STRING|MF_ENABLED,1, buf); - menupoint.x=(INT)LOWORD(lParam); - menupoint.y=(INT)HIWORD(lParam); - ClientToScreen(infoPtr->hwndSelf, &menupoint); - if( TrackPopupMenu(hMenu,TPM_RIGHTBUTTON| TPM_NONOTIFY|TPM_RETURNCMD, - menupoint.x, menupoint.y, 0, infoPtr->hwndSelf, NULL)) - { - infoPtr->currentMonth=infoPtr->todaysDate.wMonth; - infoPtr->currentYear=infoPtr->todaysDate.wYear; - InvalidateRect(infoPtr->hwndSelf, NULL, FALSE); - } - return 0; -} - -static LRESULT -MONTHCAL_LButtonDown(MONTHCAL_INFO *infoPtr, LPARAM lParam) -{ - MCHITTESTINFO ht; - DWORD hit; - HMENU hMenu; - RECT rcDay; /* used in determining area to invalidate */ - char buf[32]; - int i; - POINT menupoint; - - TRACE("%lx\n", lParam); - - if (infoPtr->hWndYearUpDown) - { - infoPtr->currentYear=SendMessageA( infoPtr->hWndYearUpDown, UDM_SETPOS, (WPARAM) 0,(LPARAM)0); - if(!DestroyWindow(infoPtr->hWndYearUpDown)) - { - FIXME("Can't destroy Updown Control\n"); - } - else - infoPtr->hWndYearUpDown=0; - if(!DestroyWindow(infoPtr->hWndYearEdit)) - { - FIXME("Can't destroy Updown Control\n"); - } - else - infoPtr->hWndYearEdit=0; - InvalidateRect(infoPtr->hwndSelf, NULL, FALSE); - } - - ht.pt.x = (INT)LOWORD(lParam); - ht.pt.y = (INT)HIWORD(lParam); - hit = MONTHCAL_HitTest(infoPtr, (LPARAM)&ht); - - /* FIXME: these flags should be checked by */ - /*((hit & MCHT_XXX) == MCHT_XXX) b/c some of the flags are */ - /* multi-bit */ - if(hit ==MCHT_TITLEBTNNEXT) { - MONTHCAL_GoToNextMonth(infoPtr); - infoPtr->status = MC_NEXTPRESSED; - SetTimer(infoPtr->hwndSelf, MC_NEXTMONTHTIMER, MC_NEXTMONTHDELAY, 0); - InvalidateRect(infoPtr->hwndSelf, NULL, FALSE); - return TRUE; - } - if(hit == MCHT_TITLEBTNPREV){ - MONTHCAL_GoToPrevMonth(infoPtr); - infoPtr->status = MC_PREVPRESSED; - SetTimer(infoPtr->hwndSelf, MC_PREVMONTHTIMER, MC_NEXTMONTHDELAY, 0); - InvalidateRect(infoPtr->hwndSelf, NULL, FALSE); - return TRUE; - } - - if(hit == MCHT_TITLEMONTH) { - hMenu = CreatePopupMenu(); - - for (i=0; i<12;i++) - { - GetLocaleInfoA( LOCALE_USER_DEFAULT,LOCALE_SMONTHNAME1+i, - buf,sizeof(buf)); - AppendMenuA(hMenu, MF_STRING|MF_ENABLED,i+1, buf); - } - menupoint.x=infoPtr->titlemonth.right; - menupoint.y=infoPtr->titlemonth.bottom; - ClientToScreen(infoPtr->hwndSelf, &menupoint); - i= TrackPopupMenu(hMenu,TPM_LEFTALIGN | TPM_NONOTIFY | TPM_RIGHTBUTTON | TPM_RETURNCMD, - menupoint.x, menupoint.y, 0, infoPtr->hwndSelf, NULL); - if ((i>0) && (i<13)) - { - infoPtr->currentMonth=i; - InvalidateRect(infoPtr->hwndSelf, NULL, FALSE); - } - } - if(hit == MCHT_TITLEYEAR) { - infoPtr->hWndYearEdit=CreateWindowExA(0, - "EDIT", - 0, - WS_VISIBLE | WS_CHILD |UDS_SETBUDDYINT, - infoPtr->titleyear.left+3,infoPtr->titlebtnnext.top, - infoPtr->titleyear.right-infoPtr->titleyear.left, - infoPtr->textHeight, - infoPtr->hwndSelf, - NULL, - NULL, - NULL); - infoPtr->hWndYearUpDown=CreateWindowExA(0, - UPDOWN_CLASSA, - 0, - WS_VISIBLE | WS_CHILD |UDS_SETBUDDYINT|UDS_NOTHOUSANDS|UDS_ARROWKEYS, - infoPtr->titleyear.right+6,infoPtr->titlebtnnext.top, - 20, - infoPtr->textHeight, - infoPtr->hwndSelf, - NULL, - NULL, - NULL); - SendMessageA( infoPtr->hWndYearUpDown, UDM_SETRANGE, (WPARAM) 0, MAKELONG (9999, 1753)); - SendMessageA( infoPtr->hWndYearUpDown, UDM_SETBUDDY, (WPARAM) infoPtr->hWndYearEdit, (LPARAM)0 ); - SendMessageA( infoPtr->hWndYearUpDown, UDM_SETPOS, (WPARAM) 0,(LPARAM)infoPtr->currentYear ); - return TRUE; - - } - if(hit == MCHT_TODAYLINK) { - infoPtr->currentMonth=infoPtr->todaysDate.wMonth; - infoPtr->currentYear=infoPtr->todaysDate.wYear; - InvalidateRect(infoPtr->hwndSelf, NULL, FALSE); - return TRUE; - } - if(hit == MCHT_CALENDARDATE) { - SYSTEMTIME selArray[2]; - NMSELCHANGE nmsc; - - MONTHCAL_CopyTime(&ht.st, &selArray[0]); - MONTHCAL_CopyTime(&ht.st, &selArray[1]); - MONTHCAL_SetSelRange(infoPtr, (LPARAM)&selArray); - MONTHCAL_SetCurSel(infoPtr, (LPARAM)&selArray); - TRACE("MCHT_CALENDARDATE\n"); - nmsc.nmhdr.hwndFrom = infoPtr->hwndSelf; - nmsc.nmhdr.idFrom = GetWindowLongPtrW(infoPtr->hwndSelf, GWLP_ID); - nmsc.nmhdr.code = MCN_SELCHANGE; - MONTHCAL_CopyTime(&infoPtr->minSel,&nmsc.stSelStart); - MONTHCAL_CopyTime(&infoPtr->maxSel,&nmsc.stSelEnd); - - SendMessageA(infoPtr->hwndNotify, WM_NOTIFY, - (WPARAM)nmsc.nmhdr.idFrom,(LPARAM)&nmsc); - - - /* redraw both old and new days if the selected day changed */ - if(infoPtr->curSelDay != ht.st.wDay) { - MONTHCAL_CalcPosFromDay(infoPtr, ht.st.wDay, ht.st.wMonth, &rcDay); - InvalidateRect(infoPtr->hwndSelf, &rcDay, TRUE); - - MONTHCAL_CalcPosFromDay(infoPtr, infoPtr->curSelDay, infoPtr->currentMonth, &rcDay); - InvalidateRect(infoPtr->hwndSelf, &rcDay, TRUE); - } - - infoPtr->firstSelDay = ht.st.wDay; - infoPtr->curSelDay = ht.st.wDay; - infoPtr->status = MC_SEL_LBUTDOWN; - return TRUE; - } - - return 0; -} - - -static LRESULT -MONTHCAL_LButtonUp(MONTHCAL_INFO *infoPtr, LPARAM lParam) -{ - NMSELCHANGE nmsc; - NMHDR nmhdr; - BOOL redraw = FALSE; - MCHITTESTINFO ht; - DWORD hit; - - TRACE("\n"); - - if(infoPtr->status & MC_NEXTPRESSED) { - KillTimer(infoPtr->hwndSelf, MC_NEXTMONTHTIMER); - infoPtr->status &= ~MC_NEXTPRESSED; - redraw = TRUE; - } - if(infoPtr->status & MC_PREVPRESSED) { - KillTimer(infoPtr->hwndSelf, MC_PREVMONTHTIMER); - infoPtr->status &= ~MC_PREVPRESSED; - redraw = TRUE; - } - - ht.pt.x = (INT)LOWORD(lParam); - ht.pt.y = (INT)HIWORD(lParam); - hit = MONTHCAL_HitTest(infoPtr, (LPARAM)&ht); - - infoPtr->status = MC_SEL_LBUTUP; - - if(hit ==MCHT_CALENDARDATENEXT) { - MONTHCAL_GoToNextMonth(infoPtr); - InvalidateRect(infoPtr->hwndSelf, NULL, FALSE); - return TRUE; - } - if(hit == MCHT_CALENDARDATEPREV){ - MONTHCAL_GoToPrevMonth(infoPtr); - InvalidateRect(infoPtr->hwndSelf, NULL, FALSE); - return TRUE; - } - 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); - - SendMessageA(infoPtr->hwndNotify, WM_NOTIFY, - (WPARAM)nmhdr.idFrom, (LPARAM)&nmhdr); - /* redraw if necessary */ - if(redraw) - InvalidateRect(infoPtr->hwndSelf, NULL, FALSE); - /* only send MCN_SELECT if currently displayed month's day was selected */ - if(hit == MCHT_CALENDARDATE) { - nmsc.nmhdr.hwndFrom = infoPtr->hwndSelf; - nmsc.nmhdr.idFrom = GetWindowLongPtrW(infoPtr->hwndSelf, GWLP_ID); - nmsc.nmhdr.code = MCN_SELECT; - MONTHCAL_CopyTime(&infoPtr->minSel, &nmsc.stSelStart); - MONTHCAL_CopyTime(&infoPtr->maxSel, &nmsc.stSelEnd); - - SendMessageA(infoPtr->hwndNotify, WM_NOTIFY, - (WPARAM)nmsc.nmhdr.idFrom, (LPARAM)&nmsc); - - } - return 0; -} - - -static LRESULT -MONTHCAL_Timer(MONTHCAL_INFO *infoPtr, WPARAM wParam) -{ - BOOL redraw = FALSE; - - TRACE("%d\n", wParam); - - switch(wParam) { - case MC_NEXTMONTHTIMER: - redraw = TRUE; - MONTHCAL_GoToNextMonth(infoPtr); - break; - case MC_PREVMONTHTIMER: - redraw = TRUE; - MONTHCAL_GoToPrevMonth(infoPtr); - break; - default: - ERR("got unknown timer\n"); - break; - } - - /* redraw only if necessary */ - if(redraw) - InvalidateRect(infoPtr->hwndSelf, NULL, FALSE); - - return 0; -} - - -static LRESULT -MONTHCAL_MouseMove(MONTHCAL_INFO *infoPtr, WPARAM wParam, LPARAM lParam) -{ - MCHITTESTINFO ht; - int oldselday, selday, hit; - RECT r; - - if(!(infoPtr->status & MC_SEL_LBUTDOWN)) return 0; - - ht.pt.x = LOWORD(lParam); - ht.pt.y = HIWORD(lParam); - - hit = MONTHCAL_HitTest(infoPtr, (LPARAM)&ht); - - /* not on the calendar date numbers? bail out */ - TRACE("hit:%x\n",hit); - if((hit & MCHT_CALENDARDATE) != MCHT_CALENDARDATE) return 0; - - selday = ht.st.wDay; - oldselday = infoPtr->curSelDay; - infoPtr->curSelDay = selday; - MONTHCAL_CalcPosFromDay(infoPtr, selday, ht.st. wMonth, &r); - - if(GetWindowLongW(infoPtr->hwndSelf, GWL_STYLE) & MCS_MULTISELECT) { - SYSTEMTIME selArray[2]; - int i; - - MONTHCAL_GetSelRange(infoPtr, (LPARAM)&selArray); - i = 0; - if(infoPtr->firstSelDay==selArray[0].wDay) i=1; - TRACE("oldRange:%d %d %d %d\n", infoPtr->firstSelDay, selArray[0].wDay, selArray[1].wDay, i); - if(infoPtr->firstSelDay==selArray[1].wDay) { - /* 1st time we get here: selArray[0]=selArray[1]) */ - /* if we're still at the first selected date, return */ - if(infoPtr->firstSelDay==selday) goto done; - if(seldayfirstSelDay) i = 0; - } - - if(abs(infoPtr->firstSelDay - selday) >= infoPtr->maxSelCount) { - if(selday>infoPtr->firstSelDay) - selday = infoPtr->firstSelDay + infoPtr->maxSelCount; - else - selday = infoPtr->firstSelDay - infoPtr->maxSelCount; - } - - if(selArray[i].wDay!=selday) { - TRACE("newRange:%d %d %d %d\n", infoPtr->firstSelDay, selArray[0].wDay, selArray[1].wDay, i); - - selArray[i].wDay = selday; - - if(selArray[0].wDay>selArray[1].wDay) { - DWORD tempday; - tempday = selArray[1].wDay; - selArray[1].wDay = selArray[0].wDay; - selArray[0].wDay = tempday; - } - - MONTHCAL_SetSelRange(infoPtr, (LPARAM)&selArray); - } - } - -done: - - /* only redraw if the currently selected day changed */ - /* FIXME: this should specify a rectangle containing only the days that changed */ - /* using InvalidateRect */ - if(oldselday != infoPtr->curSelDay) - InvalidateRect(infoPtr->hwndSelf, NULL, FALSE); - - return 0; -} - - -static LRESULT -MONTHCAL_Paint(MONTHCAL_INFO *infoPtr, WPARAM wParam) -{ - HDC hdc; - PAINTSTRUCT ps; - - if (wParam) - { - GetClientRect(infoPtr->hwndSelf, &ps.rcPaint); - hdc = (HDC)wParam; - } - else - hdc = BeginPaint(infoPtr->hwndSelf, &ps); - - MONTHCAL_Refresh(infoPtr, hdc, &ps); - if (!wParam) EndPaint(infoPtr->hwndSelf, &ps); - return 0; -} - - -static LRESULT -MONTHCAL_KillFocus(MONTHCAL_INFO *infoPtr) -{ - TRACE("\n"); - - InvalidateRect(infoPtr->hwndSelf, NULL, TRUE); - - return 0; -} - - -static LRESULT -MONTHCAL_SetFocus(MONTHCAL_INFO *infoPtr) -{ - TRACE("\n"); - - InvalidateRect(infoPtr->hwndSelf, NULL, FALSE); - - return 0; -} - -/* sets the size information */ -static void MONTHCAL_UpdateSize(MONTHCAL_INFO *infoPtr) -{ - HDC hdc = GetDC(infoPtr->hwndSelf); - RECT *title=&infoPtr->title; - RECT *prev=&infoPtr->titlebtnprev; - RECT *next=&infoPtr->titlebtnnext; - RECT *titlemonth=&infoPtr->titlemonth; - RECT *titleyear=&infoPtr->titleyear; - RECT *wdays=&infoPtr->wdays; - RECT *weeknumrect=&infoPtr->weeknums; - RECT *days=&infoPtr->days; - RECT *todayrect=&infoPtr->todayrect; - SIZE size; - TEXTMETRICA tm; - DWORD dwStyle = GetWindowLongW(infoPtr->hwndSelf, GWL_STYLE); - HFONT currentFont; - int xdiv, left_offset; - RECT rcClient; - - GetClientRect(infoPtr->hwndSelf, &rcClient); - - currentFont = SelectObject(hdc, infoPtr->hFont); - - /* get the height and width of each day's text */ - GetTextMetricsA(hdc, &tm); - infoPtr->textHeight = tm.tmHeight + tm.tmExternalLeading + tm.tmInternalLeading; - GetTextExtentPoint32A(hdc, "Sun", 3, &size); - infoPtr->textWidth = size.cx + 2; - - /* recalculate the height and width increments and offsets */ - GetTextExtentPoint32A(hdc, "00", 2, &size); - - xdiv = (dwStyle & MCS_WEEKNUMBERS) ? 8 : 7; - - infoPtr->width_increment = size.cx * 2; - infoPtr->height_increment = infoPtr->textHeight; - left_offset = (rcClient.right - rcClient.left) - (infoPtr->width_increment * xdiv); - - /* calculate title area */ - title->top = rcClient.top; - title->bottom = title->top + 3 * infoPtr->height_increment / 2; - title->left = left_offset; - title->right = rcClient.right; - - /* 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 = left_offset; - if(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 = rcClient.left; - todayrect->right = rcClient.right; - todayrect->top = days->bottom; - todayrect->bottom = days->bottom + infoPtr->height_increment; - - 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); - - /* invalidate client area and erase background */ - InvalidateRect(infoPtr->hwndSelf, NULL, TRUE); - - return 0; -} - -static LRESULT MONTHCAL_GetFont(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); - - if (redraw) - InvalidateRect(infoPtr->hwndSelf, NULL, FALSE); - - return (LRESULT)hOldFont; -} - -/* FIXME: check whether dateMin/dateMax need to be adjusted. */ -static LRESULT -MONTHCAL_Create(HWND hwnd, WPARAM wParam, LPARAM lParam) -{ - MONTHCAL_INFO *infoPtr; - - /* allocate memory for info structure */ - infoPtr =(MONTHCAL_INFO*)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 = ((LPCREATESTRUCTW)lParam)->hwndParent; - - MONTHCAL_SetFont(infoPtr, GetStockObject(DEFAULT_GUI_FONT), FALSE); - - /* initialize info structure */ - /* FIXME: calculate systemtime ->> localtime(substract timezoneinfo) */ - - GetSystemTime(&infoPtr->todaysDate); - MONTHCAL_SetFirstDayOfWeek(infoPtr, (LPARAM)-1); - infoPtr->currentMonth = infoPtr->todaysDate.wMonth; - infoPtr->currentYear = infoPtr->todaysDate.wYear; - MONTHCAL_CopyTime(&infoPtr->todaysDate, &infoPtr->minDate); - MONTHCAL_CopyTime(&infoPtr->todaysDate, &infoPtr->maxDate); - infoPtr->maxDate.wYear=2050; - infoPtr->minDate.wYear=1950; - infoPtr->maxSelCount = 7; - infoPtr->monthRange = 3; - infoPtr->monthdayState = Alloc - (infoPtr->monthRange * sizeof(MONTHDAYSTATE)); - infoPtr->titlebk = GetSysColor(COLOR_ACTIVECAPTION); - infoPtr->titletxt = GetSysColor(COLOR_WINDOW); - infoPtr->monthbk = GetSysColor(COLOR_WINDOW); - infoPtr->trailingtxt = GetSysColor(COLOR_GRAYTEXT); - infoPtr->bk = GetSysColor(COLOR_WINDOW); - infoPtr->txt = GetSysColor(COLOR_WINDOWTEXT); - - /* call MONTHCAL_UpdateSize to set all of the dimensions */ - /* of the control */ - MONTHCAL_UpdateSize(infoPtr); - - return 0; -} - - -static LRESULT -MONTHCAL_Destroy(MONTHCAL_INFO *infoPtr) -{ - /* free month calendar info data */ - if(infoPtr->monthdayState) - Free(infoPtr->monthdayState); - SetWindowLongPtrW(infoPtr->hwndSelf, 0, 0); - Free(infoPtr); - return 0; -} - - -static LRESULT WINAPI -MONTHCAL_WindowProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam) -{ - MONTHCAL_INFO *infoPtr; - - TRACE("hwnd=%p msg=%x wparam=%x lparam=%lx\n", hwnd, uMsg, wParam, lParam); - - infoPtr = MONTHCAL_GetInfoPtr(hwnd); - if (!infoPtr && (uMsg != WM_CREATE)) - return DefWindowProcA(hwnd, uMsg, wParam, lParam); - switch(uMsg) - { - case MCM_GETCURSEL: - return MONTHCAL_GetCurSel(infoPtr, lParam); - - case MCM_SETCURSEL: - return MONTHCAL_SetCurSel(infoPtr, lParam); - - case MCM_GETMAXSELCOUNT: - return MONTHCAL_GetMaxSelCount(infoPtr); - - case MCM_SETMAXSELCOUNT: - return MONTHCAL_SetMaxSelCount(infoPtr, wParam); - - case MCM_GETSELRANGE: - return MONTHCAL_GetSelRange(infoPtr, lParam); - - case MCM_SETSELRANGE: - return MONTHCAL_SetSelRange(infoPtr, lParam); - - case MCM_GETMONTHRANGE: - return MONTHCAL_GetMonthRange(infoPtr); - - case MCM_SETDAYSTATE: - return MONTHCAL_SetDayState(infoPtr, wParam, lParam); - - case MCM_GETMINREQRECT: - return MONTHCAL_GetMinReqRect(infoPtr, lParam); - - case MCM_GETCOLOR: - return MONTHCAL_GetColor(infoPtr, wParam); - - case MCM_SETCOLOR: - return MONTHCAL_SetColor(infoPtr, wParam, lParam); - - case MCM_GETTODAY: - return MONTHCAL_GetToday(infoPtr, lParam); - - case MCM_SETTODAY: - return MONTHCAL_SetToday(infoPtr, lParam); - - case MCM_HITTEST: - return MONTHCAL_HitTest(infoPtr, lParam); - - case MCM_GETFIRSTDAYOFWEEK: - return MONTHCAL_GetFirstDayOfWeek(infoPtr); - - case MCM_SETFIRSTDAYOFWEEK: - return MONTHCAL_SetFirstDayOfWeek(infoPtr, lParam); - - case MCM_GETRANGE: - return MONTHCAL_GetRange(hwnd, wParam, lParam); - - case MCM_SETRANGE: - return MONTHCAL_SetRange(infoPtr, wParam, lParam); - - case MCM_GETMONTHDELTA: - return MONTHCAL_GetMonthDelta(infoPtr); - - case MCM_SETMONTHDELTA: - return MONTHCAL_SetMonthDelta(infoPtr, wParam); - - case MCM_GETMAXTODAYWIDTH: - return MONTHCAL_GetMaxTodayWidth(infoPtr); - - case WM_GETDLGCODE: - return DLGC_WANTARROWS | DLGC_WANTCHARS; - - case WM_KILLFOCUS: - return MONTHCAL_KillFocus(infoPtr); - - case WM_RBUTTONDOWN: - return MONTHCAL_RButtonDown(infoPtr, lParam); - - case WM_LBUTTONDOWN: - return MONTHCAL_LButtonDown(infoPtr, lParam); - - case WM_MOUSEMOVE: - return MONTHCAL_MouseMove(infoPtr, wParam, lParam); - - case WM_LBUTTONUP: - return MONTHCAL_LButtonUp(infoPtr, lParam); - - case WM_PAINT: - return MONTHCAL_Paint(infoPtr, wParam); - - case WM_SETFOCUS: - return MONTHCAL_SetFocus(infoPtr); - - case WM_SIZE: - return MONTHCAL_Size(infoPtr, (SHORT)LOWORD(lParam), (SHORT)HIWORD(lParam)); - - case WM_CREATE: - return MONTHCAL_Create(hwnd, wParam, 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_DESTROY: - return MONTHCAL_Destroy(infoPtr); - - default: - if ((uMsg >= WM_USER) && (uMsg < WM_APP)) - ERR( "unknown msg %04x wp=%08x lp=%08lx\n", uMsg, wParam, lParam); - return DefWindowProcA(hwnd, uMsg, wParam, lParam); - } - return 0; -} - - -void -MONTHCAL_Register(void) -{ - WNDCLASSA wndClass; - - ZeroMemory(&wndClass, sizeof(WNDCLASSA)); - wndClass.style = CS_GLOBALCLASS; - wndClass.lpfnWndProc = MONTHCAL_WindowProc; - wndClass.cbClsExtra = 0; - wndClass.cbWndExtra = sizeof(MONTHCAL_INFO *); - wndClass.hCursor = LoadCursorA(0, (LPSTR)IDC_ARROW); - wndClass.hbrBackground = (HBRUSH)(COLOR_WINDOW + 1); - wndClass.lpszClassName = MONTHCAL_CLASSA; - - RegisterClassA(&wndClass); -} - - -void -MONTHCAL_Unregister(void) -{ - UnregisterClassA(MONTHCAL_CLASSA, NULL); -} diff --git a/reactos/lib/comctl32/nativefont.c b/reactos/lib/comctl32/nativefont.c deleted file mode 100644 index 86d1e79fa96..00000000000 --- a/reactos/lib/comctl32/nativefont.c +++ /dev/null @@ -1,135 +0,0 @@ -/* - * Native Font control - * - * Copyright 1998, 1999 Eric Kohl - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2.1 of the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - * - * NOTES - * This is just a dummy control. An author is needed! Any volunteers? - * I will only improve this control once in a while. - * Eric - * - * TODO: - * - All messages. - * - All notifications. - */ - -#include - -#include "windef.h" -#include "winbase.h" -#include "wingdi.h" -#include "winuser.h" -#include "commctrl.h" -#include "comctl32.h" -#include "wine/debug.h" - -WINE_DEFAULT_DEBUG_CHANNEL(nativefont); - -typedef struct -{ - HWND hwndSelf; /* my own handle */ -} NATIVEFONT_INFO; - -#define NATIVEFONT_GetInfoPtr(hwnd) ((NATIVEFONT_INFO *)GetWindowLongPtrW (hwnd, 0)) - -static LRESULT -NATIVEFONT_Create (HWND hwnd, WPARAM wParam, LPARAM lParam) -{ - NATIVEFONT_INFO *infoPtr; - - /* allocate memory for info structure */ - infoPtr = (NATIVEFONT_INFO *)Alloc (sizeof(NATIVEFONT_INFO)); - SetWindowLongPtrW (hwnd, 0, (DWORD_PTR)infoPtr); - - /* initialize info structure */ - infoPtr->hwndSelf = hwnd; - - return 0; -} - -static LRESULT -NATIVEFONT_Destroy (NATIVEFONT_INFO *infoPtr) -{ - /* free control info data */ - SetWindowLongPtrW( infoPtr->hwndSelf, 0, 0 ); - Free (infoPtr); - - return 0; -} - -static LRESULT WINAPI -NATIVEFONT_WindowProc (HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam) -{ - NATIVEFONT_INFO *infoPtr = NATIVEFONT_GetInfoPtr(hwnd); - - TRACE("hwnd=%p msg=%04x wparam=%08x lparam=%08lx\n", - hwnd, uMsg, wParam, lParam); - - if (!infoPtr && (uMsg != WM_CREATE)) - return DefWindowProcW( hwnd, uMsg, wParam, lParam ); - - switch (uMsg) - { - case WM_CREATE: - return NATIVEFONT_Create (hwnd, wParam, lParam); - - case WM_DESTROY: - return NATIVEFONT_Destroy (infoPtr); - - case WM_MOVE: - case WM_SIZE: - case WM_SHOWWINDOW: - case WM_WINDOWPOSCHANGING: - case WM_WINDOWPOSCHANGED: - case WM_SETFONT: - case WM_GETDLGCODE: - /* FIXME("message %04x seen but stubbed\n", uMsg); */ - return DefWindowProcW (hwnd, uMsg, wParam, lParam); - - default: - if ((uMsg >= WM_USER) && (uMsg < WM_APP)) - ERR("unknown msg %04x wp=%08x lp=%08lx\n", - uMsg, wParam, lParam); - return DefWindowProcW (hwnd, uMsg, wParam, lParam); - } - return 0; -} - - -VOID -NATIVEFONT_Register (void) -{ - WNDCLASSW wndClass; - - ZeroMemory (&wndClass, sizeof(WNDCLASSW)); - wndClass.style = CS_GLOBALCLASS; - wndClass.lpfnWndProc = NATIVEFONT_WindowProc; - wndClass.cbClsExtra = 0; - wndClass.cbWndExtra = sizeof(NATIVEFONT_INFO *); - wndClass.hCursor = LoadCursorW (0, (LPWSTR)IDC_ARROW); - wndClass.hbrBackground = (HBRUSH)(COLOR_BTNFACE + 1); - wndClass.lpszClassName = WC_NATIVEFONTCTLW; - - RegisterClassW (&wndClass); -} - - -VOID -NATIVEFONT_Unregister (void) -{ - UnregisterClassW (WC_NATIVEFONTCTLW, NULL); -} diff --git a/reactos/lib/comctl32/pager.c b/reactos/lib/comctl32/pager.c deleted file mode 100644 index 8c267b7dbb3..00000000000 --- a/reactos/lib/comctl32/pager.c +++ /dev/null @@ -1,1398 +0,0 @@ -/* - * Pager control - * - * Copyright 1998, 1999 Eric Kohl - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2.1 of the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - * - * NOTES - * Tested primarily with the controlspy Pager application. - * Susan Farley (susan@codeweavers.com) - * - * This code was audited for completeness against the documented features - * of Comctl32.dll version 6.0 on Sep. 18, 2004, by Robert Shearman. - * - * Unless otherwise noted, we believe this code to be complete, as per - * the specification mentioned above. - * If you discover missing features or bugs please note them below. - * - * TODO: - * Implement repetitive button press. - * Adjust arrow size relative to size of button. - * Allow border size changes. - * Styles: - * PGS_DRAGNDROP - * Notifications: - * PGN_HOTITEMCHANGE - */ - -#include -#include -#include "windef.h" -#include "winbase.h" -#include "wingdi.h" -#include "winuser.h" -#include "winnls.h" -#include "commctrl.h" -#include "comctl32.h" -#include "wine/debug.h" - -WINE_DEFAULT_DEBUG_CHANNEL(pager); - -typedef struct -{ - HWND hwndChild; /* handle of the contained wnd */ - HWND hwndNotify; /* handle of the parent wnd */ - BOOL bNoResize; /* set when created with CCS_NORESIZE */ - COLORREF clrBk; /* background color */ - INT nBorder; /* border size for the control */ - INT nButtonSize;/* size of the pager btns */ - INT nPos; /* scroll position */ - INT nWidth; /* from child wnd's response to PGN_CALCSIZE */ - INT nHeight; /* from child wnd's response to PGN_CALCSIZE */ - BOOL bForward; /* forward WM_MOUSEMOVE msgs to the contained wnd */ - BOOL bCapture; /* we have captured the mouse */ - INT TLbtnState; /* state of top or left btn */ - INT BRbtnState; /* state of bottom or right btn */ - INT direction; /* direction of the scroll, (e.g. PGF_SCROLLUP) */ -} PAGER_INFO; - -#define PAGER_GetInfoPtr(hwnd) ((PAGER_INFO *)GetWindowLongPtrW(hwnd, 0)) -#define PAGER_IsHorizontal(hwnd) ((GetWindowLongA (hwnd, GWL_STYLE) & PGS_HORZ)) - -#define MIN_ARROW_WIDTH 8 -#define MIN_ARROW_HEIGHT 5 - -#define TIMERID1 1 -#define TIMERID2 2 -#define INITIAL_DELAY 500 -#define REPEAT_DELAY 50 - -static void -PAGER_GetButtonRects(HWND hwnd, PAGER_INFO* infoPtr, RECT* prcTopLeft, RECT* prcBottomRight, BOOL bClientCoords) -{ - RECT rcWindow; - GetWindowRect (hwnd, &rcWindow); - - if (bClientCoords) - { - POINT pt = {rcWindow.left, rcWindow.top}; - ScreenToClient(hwnd, &pt); - OffsetRect(&rcWindow, -(rcWindow.left-pt.x), -(rcWindow.top-pt.y)); - } - else - OffsetRect(&rcWindow, -rcWindow.left, -rcWindow.top); - - *prcTopLeft = *prcBottomRight = rcWindow; - if (PAGER_IsHorizontal(hwnd)) - { - prcTopLeft->right = prcTopLeft->left + infoPtr->nButtonSize; - prcBottomRight->left = prcBottomRight->right - infoPtr->nButtonSize; - } - else - { - prcTopLeft->bottom = prcTopLeft->top + infoPtr->nButtonSize; - prcBottomRight->top = prcBottomRight->bottom - infoPtr->nButtonSize; - } -} - -/* the horizontal arrows are: - * - * 01234 01234 - * 1 * * - * 2 ** ** - * 3*** *** - * 4*** *** - * 5 ** ** - * 6 * * - * 7 - * - */ -static void -PAGER_DrawHorzArrow (HDC hdc, RECT r, INT colorRef, BOOL left) -{ - INT x, y, w, h; - HPEN hPen, hOldPen; - - w = r.right - r.left + 1; - h = r.bottom - r.top + 1; - if ((h < MIN_ARROW_WIDTH) || (w < MIN_ARROW_HEIGHT)) - return; /* refuse to draw partial arrow */ - - if (!(hPen = CreatePen( PS_SOLID, 1, GetSysColor( colorRef )))) return; - hOldPen = SelectObject ( hdc, hPen ); - if (left) - { - x = r.left + ((w - MIN_ARROW_HEIGHT) / 2) + 3; - y = r.top + ((h - MIN_ARROW_WIDTH) / 2) + 1; - MoveToEx (hdc, x, y, NULL); - LineTo (hdc, x--, y+5); y++; - MoveToEx (hdc, x, y, NULL); - LineTo (hdc, x--, y+3); y++; - MoveToEx (hdc, x, y, NULL); - LineTo (hdc, x, y+1); - } - else - { - x = r.left + ((w - MIN_ARROW_HEIGHT) / 2) + 1; - y = r.top + ((h - MIN_ARROW_WIDTH) / 2) + 1; - MoveToEx (hdc, x, y, NULL); - LineTo (hdc, x++, y+5); y++; - MoveToEx (hdc, x, y, NULL); - LineTo (hdc, x++, y+3); y++; - MoveToEx (hdc, x, y, NULL); - LineTo (hdc, x, y+1); - } - - SelectObject( hdc, hOldPen ); - DeleteObject( hPen ); -} - -/* the vertical arrows are: - * - * 01234567 01234567 - * 1****** ** - * 2 **** **** - * 3 ** ****** - * 4 - * - */ -static void -PAGER_DrawVertArrow (HDC hdc, RECT r, INT colorRef, BOOL up) -{ - INT x, y, w, h; - HPEN hPen, hOldPen; - - w = r.right - r.left + 1; - h = r.bottom - r.top + 1; - if ((h < MIN_ARROW_WIDTH) || (w < MIN_ARROW_HEIGHT)) - return; /* refuse to draw partial arrow */ - - if (!(hPen = CreatePen( PS_SOLID, 1, GetSysColor( colorRef )))) return; - hOldPen = SelectObject ( hdc, hPen ); - if (up) - { - x = r.left + ((w - MIN_ARROW_HEIGHT) / 2) + 1; - y = r.top + ((h - MIN_ARROW_WIDTH) / 2) + 3; - MoveToEx (hdc, x, y, NULL); - LineTo (hdc, x+5, y--); x++; - MoveToEx (hdc, x, y, NULL); - LineTo (hdc, x+3, y--); x++; - MoveToEx (hdc, x, y, NULL); - LineTo (hdc, x+1, y); - } - else - { - x = r.left + ((w - MIN_ARROW_HEIGHT) / 2) + 1; - y = r.top + ((h - MIN_ARROW_WIDTH) / 2) + 1; - MoveToEx (hdc, x, y, NULL); - LineTo (hdc, x+5, y++); x++; - MoveToEx (hdc, x, y, NULL); - LineTo (hdc, x+3, y++); x++; - MoveToEx (hdc, x, y, NULL); - LineTo (hdc, x+1, y); - } - - SelectObject( hdc, hOldPen ); - DeleteObject( hPen ); -} - -static void -PAGER_DrawButton(HDC hdc, COLORREF clrBk, RECT arrowRect, - BOOL horz, BOOL topLeft, INT btnState) -{ - HBRUSH hBrush, hOldBrush; - RECT rc = arrowRect; - - TRACE("arrowRect = %s, btnState = %d\n", wine_dbgstr_rect(&arrowRect), btnState); - - if (btnState == PGF_INVISIBLE) - return; - - if ((rc.right - rc.left <= 0) || (rc.bottom - rc.top <= 0)) - return; - - hBrush = CreateSolidBrush(clrBk); - hOldBrush = (HBRUSH)SelectObject(hdc, hBrush); - - FillRect(hdc, &rc, hBrush); - - if (btnState == PGF_HOT) - { - DrawEdge( hdc, &rc, BDR_RAISEDINNER, BF_RECT); - if (horz) - PAGER_DrawHorzArrow(hdc, rc, COLOR_WINDOWFRAME, topLeft); - else - PAGER_DrawVertArrow(hdc, rc, COLOR_WINDOWFRAME, topLeft); - } - else if (btnState == PGF_NORMAL) - { - DrawEdge (hdc, &rc, BDR_OUTER, BF_FLAT); - if (horz) - PAGER_DrawHorzArrow(hdc, rc, COLOR_WINDOWFRAME, topLeft); - else - PAGER_DrawVertArrow(hdc, rc, COLOR_WINDOWFRAME, topLeft); - } - else if (btnState == PGF_DEPRESSED) - { - DrawEdge( hdc, &rc, BDR_SUNKENOUTER, BF_RECT); - if (horz) - PAGER_DrawHorzArrow(hdc, rc, COLOR_WINDOWFRAME, topLeft); - else - PAGER_DrawVertArrow(hdc, rc, COLOR_WINDOWFRAME, topLeft); - } - else if (btnState == PGF_GRAYED) - { - DrawEdge (hdc, &rc, BDR_OUTER, BF_FLAT); - if (horz) - { - PAGER_DrawHorzArrow(hdc, rc, COLOR_3DHIGHLIGHT, topLeft); - rc.left++, rc.top++; rc.right++, rc.bottom++; - PAGER_DrawHorzArrow(hdc, rc, COLOR_3DSHADOW, topLeft); - } - else - { - PAGER_DrawVertArrow(hdc, rc, COLOR_3DHIGHLIGHT, topLeft); - rc.left++, rc.top++; rc.right++, rc.bottom++; - PAGER_DrawVertArrow(hdc, rc, COLOR_3DSHADOW, topLeft); - } - } - - SelectObject( hdc, hOldBrush ); - DeleteObject(hBrush); -} - -/* << PAGER_GetDropTarget >> */ - -static inline LRESULT -PAGER_ForwardMouse (HWND hwnd, WPARAM wParam) -{ - PAGER_INFO *infoPtr = PAGER_GetInfoPtr (hwnd); - TRACE("[%p]\n", hwnd); - - infoPtr->bForward = (BOOL)wParam; - - return 0; -} - -static inline LRESULT -PAGER_GetButtonState (HWND hwnd, WPARAM wParam, LPARAM lParam) -{ - PAGER_INFO *infoPtr = PAGER_GetInfoPtr (hwnd); - LRESULT btnState = PGF_INVISIBLE; - INT btn = (INT)lParam; - TRACE("[%p]\n", hwnd); - - if (btn == PGB_TOPORLEFT) - btnState = infoPtr->TLbtnState; - else if (btn == PGB_BOTTOMORRIGHT) - btnState = infoPtr->BRbtnState; - - return btnState; -} - - -static inline LRESULT -PAGER_GetPos(HWND hwnd) -{ - PAGER_INFO *infoPtr = PAGER_GetInfoPtr (hwnd); - TRACE("[%p] returns %d\n", hwnd, infoPtr->nPos); - return (LRESULT)infoPtr->nPos; -} - -static inline LRESULT -PAGER_GetButtonSize(HWND hwnd) -{ - PAGER_INFO *infoPtr = PAGER_GetInfoPtr (hwnd); - TRACE("[%p] returns %d\n", hwnd, infoPtr->nButtonSize); - return (LRESULT)infoPtr->nButtonSize; -} - -static inline LRESULT -PAGER_GetBorder(HWND hwnd) -{ - PAGER_INFO *infoPtr = PAGER_GetInfoPtr (hwnd); - TRACE("[%p] returns %d\n", hwnd, infoPtr->nBorder); - return (LRESULT)infoPtr->nBorder; -} - -static inline LRESULT -PAGER_GetBkColor(HWND hwnd) -{ - PAGER_INFO *infoPtr = PAGER_GetInfoPtr (hwnd); - TRACE("[%p] returns %06lx\n", hwnd, infoPtr->clrBk); - return (LRESULT)infoPtr->clrBk; -} - -static void -PAGER_CalcSize (HWND hwnd, INT* size, BOOL getWidth) -{ - PAGER_INFO *infoPtr = PAGER_GetInfoPtr (hwnd); - NMPGCALCSIZE nmpgcs; - ZeroMemory (&nmpgcs, sizeof (NMPGCALCSIZE)); - nmpgcs.hdr.hwndFrom = hwnd; - nmpgcs.hdr.idFrom = GetWindowLongPtrW (hwnd, GWLP_ID); - nmpgcs.hdr.code = PGN_CALCSIZE; - nmpgcs.dwFlag = getWidth ? PGF_CALCWIDTH : PGF_CALCHEIGHT; - nmpgcs.iWidth = getWidth ? *size : 0; - nmpgcs.iHeight = getWidth ? 0 : *size; - SendMessageW (infoPtr->hwndNotify, WM_NOTIFY, - (WPARAM)nmpgcs.hdr.idFrom, (LPARAM)&nmpgcs); - - *size = getWidth ? nmpgcs.iWidth : nmpgcs.iHeight; - - TRACE("[%p] PGN_CALCSIZE returns %s=%d\n", hwnd, - getWidth ? "width" : "height", *size); -} - -static void -PAGER_PositionChildWnd(HWND hwnd, PAGER_INFO* infoPtr) -{ - if (infoPtr->hwndChild) - { - RECT rcClient; - int nPos = infoPtr->nPos; - - /* compensate for a grayed btn, which will soon become invisible */ - if (infoPtr->TLbtnState == PGF_GRAYED) - nPos += infoPtr->nButtonSize; - - GetClientRect(hwnd, &rcClient); - - if (PAGER_IsHorizontal(hwnd)) - { - int wndSize = max(0, rcClient.right - rcClient.left); - if (infoPtr->nWidth < wndSize) - infoPtr->nWidth = wndSize; - - TRACE("[%p] SWP %dx%d at (%d,%d)\n", hwnd, - infoPtr->nWidth, infoPtr->nHeight, - -nPos, 0); - SetWindowPos(infoPtr->hwndChild, 0, - -nPos, 0, - infoPtr->nWidth, infoPtr->nHeight, - SWP_NOZORDER); - } - else - { - int wndSize = max(0, rcClient.bottom - rcClient.top); - if (infoPtr->nHeight < wndSize) - infoPtr->nHeight = wndSize; - - TRACE("[%p] SWP %dx%d at (%d,%d)\n", hwnd, - infoPtr->nWidth, infoPtr->nHeight, - 0, -nPos); - SetWindowPos(infoPtr->hwndChild, 0, - 0, -nPos, - infoPtr->nWidth, infoPtr->nHeight, - SWP_NOZORDER); - } - - InvalidateRect(infoPtr->hwndChild, NULL, TRUE); - } -} - -static INT -PAGER_GetScrollRange(HWND hwnd, PAGER_INFO* infoPtr) -{ - INT scrollRange = 0; - - if (infoPtr->hwndChild) - { - INT wndSize, childSize; - RECT wndRect; - GetWindowRect(hwnd, &wndRect); - - if (PAGER_IsHorizontal(hwnd)) - { - wndSize = wndRect.right - wndRect.left; - PAGER_CalcSize(hwnd, &infoPtr->nWidth, TRUE); - childSize = infoPtr->nWidth; - } - else - { - wndSize = wndRect.bottom - wndRect.top; - PAGER_CalcSize(hwnd, &infoPtr->nHeight, FALSE); - childSize = infoPtr->nHeight; - } - - TRACE("childSize = %d, wndSize = %d\n", childSize, wndSize); - if (childSize > wndSize) - scrollRange = childSize - wndSize + infoPtr->nButtonSize; - } - - TRACE("[%p] returns %d\n", hwnd, scrollRange); - return scrollRange; -} - -static void -PAGER_UpdateBtns(HWND hwnd, PAGER_INFO *infoPtr, - INT scrollRange, BOOL hideGrayBtns) -{ - BOOL resizeClient; - BOOL repaintBtns; - INT oldTLbtnState = infoPtr->TLbtnState; - INT oldBRbtnState = infoPtr->BRbtnState; - POINT pt; - RECT rcTopLeft, rcBottomRight; - - /* get button rects */ - PAGER_GetButtonRects(hwnd, infoPtr, &rcTopLeft, &rcBottomRight, FALSE); - - GetCursorPos(&pt); - - /* update states based on scroll position */ - if (infoPtr->nPos > 0) - { - if (infoPtr->TLbtnState == PGF_INVISIBLE || infoPtr->TLbtnState == PGF_GRAYED) - infoPtr->TLbtnState = PGF_NORMAL; - } - else if (PtInRect(&rcTopLeft, pt)) - infoPtr->TLbtnState = PGF_GRAYED; - else - infoPtr->TLbtnState = PGF_INVISIBLE; - - if (scrollRange <= 0) - { - infoPtr->TLbtnState = PGF_INVISIBLE; - infoPtr->BRbtnState = PGF_INVISIBLE; - } - else if (infoPtr->nPos < scrollRange) - { - if (infoPtr->BRbtnState == PGF_INVISIBLE || infoPtr->BRbtnState == PGF_GRAYED) - infoPtr->BRbtnState = PGF_NORMAL; - } - else if (PtInRect(&rcBottomRight, pt)) - infoPtr->BRbtnState = PGF_GRAYED; - else - infoPtr->BRbtnState = PGF_INVISIBLE; - - /* only need to resize when entering or leaving PGF_INVISIBLE state */ - resizeClient = - ((oldTLbtnState == PGF_INVISIBLE) != (infoPtr->TLbtnState == PGF_INVISIBLE)) || - ((oldBRbtnState == PGF_INVISIBLE) != (infoPtr->BRbtnState == PGF_INVISIBLE)); - /* initiate NCCalcSize to resize client wnd if necessary */ - if (resizeClient) - SetWindowPos(hwnd, 0,0,0,0,0, - SWP_FRAMECHANGED | SWP_NOSIZE | SWP_NOMOVE | - SWP_NOZORDER | SWP_NOACTIVATE); - - /* repaint when changing any state */ - repaintBtns = (oldTLbtnState != infoPtr->TLbtnState) || - (oldBRbtnState != infoPtr->BRbtnState); - if (repaintBtns) - SendMessageW(hwnd, WM_NCPAINT, 0, 0); -} - -static LRESULT -PAGER_SetPos(HWND hwnd, INT newPos, BOOL fromBtnPress) -{ - PAGER_INFO *infoPtr = PAGER_GetInfoPtr (hwnd); - INT scrollRange = PAGER_GetScrollRange(hwnd, infoPtr); - INT oldPos = infoPtr->nPos; - - if ((scrollRange <= 0) || (newPos < 0)) - infoPtr->nPos = 0; - else if (newPos > scrollRange) - infoPtr->nPos = scrollRange; - else - infoPtr->nPos = newPos; - - TRACE("[%p] pos=%d, oldpos=%d\n", hwnd, infoPtr->nPos, oldPos); - - if (infoPtr->nPos != oldPos) - { - /* gray and restore btns, and if from WM_SETPOS, hide the gray btns */ - PAGER_UpdateBtns(hwnd, infoPtr, scrollRange, !fromBtnPress); - PAGER_PositionChildWnd(hwnd, infoPtr); - } - - return 0; -} - -static LRESULT -PAGER_HandleWindowPosChanging(HWND hwnd, WPARAM wParam, WINDOWPOS *winpos) -{ - PAGER_INFO *infoPtr = PAGER_GetInfoPtr (hwnd); - - if (infoPtr->bNoResize && !(winpos->flags & SWP_NOSIZE)) - { - /* don't let the app resize the nonscrollable dimension of a control - * that was created with CCS_NORESIZE style - * (i.e. height for a horizontal pager, or width for a vertical one) */ - - /* except if the current dimension is 0 and app is setting for - * first time, then save amount as dimension. - GA 8/01 */ - - if (PAGER_IsHorizontal(hwnd)) - if (!infoPtr->nHeight && winpos->cy) - infoPtr->nHeight = winpos->cy; - else - winpos->cy = infoPtr->nHeight; - else - if (!infoPtr->nWidth && winpos->cx) - infoPtr->nWidth = winpos->cx; - else - winpos->cx = infoPtr->nWidth; - return 0; - } - - DefWindowProcW (hwnd, WM_WINDOWPOSCHANGING, wParam, (LPARAM)winpos); - - return 1; -} - -static INT -PAGER_SetFixedWidth(HWND hwnd, PAGER_INFO* infoPtr) -{ - /* Must set the non-scrollable dimension to be less than the full height/width - * so that NCCalcSize is called. The Msoft docs mention 3/4 factor for button - * size, and experimentation shows that affect is almost right. */ - - RECT wndRect; - INT delta, h; - GetWindowRect(hwnd, &wndRect); - - /* see what the app says for btn width */ - PAGER_CalcSize(hwnd, &infoPtr->nWidth, TRUE); - - if (infoPtr->bNoResize) - { - delta = wndRect.right - wndRect.left - infoPtr->nWidth; - if (delta > infoPtr->nButtonSize) - infoPtr->nWidth += 4 * infoPtr->nButtonSize / 3; - else if (delta > 0) - infoPtr->nWidth += infoPtr->nButtonSize / 3; - } - - h = wndRect.bottom - wndRect.top + infoPtr->nButtonSize; - - TRACE("[%p] infoPtr->nWidth set to %d\n", - hwnd, infoPtr->nWidth); - - return h; -} - -static INT -PAGER_SetFixedHeight(HWND hwnd, PAGER_INFO* infoPtr) -{ - /* Must set the non-scrollable dimension to be less than the full height/width - * so that NCCalcSize is called. The Msoft docs mention 3/4 factor for button - * size, and experimentation shows that affect is almost right. */ - - RECT wndRect; - INT delta, w; - GetWindowRect(hwnd, &wndRect); - - /* see what the app says for btn height */ - PAGER_CalcSize(hwnd, &infoPtr->nHeight, FALSE); - - if (infoPtr->bNoResize) - { - delta = wndRect.bottom - wndRect.top - infoPtr->nHeight; - if (delta > infoPtr->nButtonSize) - infoPtr->nHeight += infoPtr->nButtonSize; - else if (delta > 0) - infoPtr->nHeight += infoPtr->nButtonSize / 3; - } - - w = wndRect.right - wndRect.left + infoPtr->nButtonSize; - - TRACE("[%p] infoPtr->nHeight set to %d\n", - hwnd, infoPtr->nHeight); - - return w; -} - -/****************************************************************** - * For the PGM_RECALCSIZE message (but not the other uses in * - * this module), the native control does only the following: * - * * - * if (some condition) * - * PostMessageW(hwnd, EM_FMTLINES, 0, 0); * - * return DefWindowProcW(hwnd, PGM_RECALCSIZE, 0, 0); * - * * - * When we figure out what the "some condition" is we will * - * implement that for the message processing. * - ******************************************************************/ - -static LRESULT -PAGER_RecalcSize(HWND hwnd) -{ - PAGER_INFO *infoPtr = PAGER_GetInfoPtr (hwnd); - - TRACE("[%p]\n", hwnd); - - if (infoPtr->hwndChild) - { - INT scrollRange = PAGER_GetScrollRange(hwnd, infoPtr); - - if (scrollRange <= 0) - { - infoPtr->nPos = -1; - PAGER_SetPos(hwnd, 0, FALSE); - } - else - PAGER_PositionChildWnd(hwnd, infoPtr); - } - - return 1; -} - - -static LRESULT -PAGER_SetBkColor (HWND hwnd, WPARAM wParam, LPARAM lParam) -{ - PAGER_INFO *infoPtr = PAGER_GetInfoPtr (hwnd); - COLORREF clrTemp = infoPtr->clrBk; - - infoPtr->clrBk = (COLORREF)lParam; - TRACE("[%p] %06lx\n", hwnd, infoPtr->clrBk); - - /* the native control seems to do things this way */ - SetWindowPos(hwnd, 0,0,0,0,0, - SWP_FRAMECHANGED | SWP_NOSIZE | SWP_NOMOVE | - SWP_NOZORDER | SWP_NOACTIVATE); - - RedrawWindow(hwnd, 0, 0, RDW_ERASE | RDW_INVALIDATE); - - return (LRESULT)clrTemp; -} - - -static LRESULT -PAGER_SetBorder (HWND hwnd, WPARAM wParam, LPARAM lParam) -{ - PAGER_INFO *infoPtr = PAGER_GetInfoPtr (hwnd); - INT nTemp = infoPtr->nBorder; - - infoPtr->nBorder = (INT)lParam; - TRACE("[%p] %d\n", hwnd, infoPtr->nBorder); - - PAGER_RecalcSize(hwnd); - - return (LRESULT)nTemp; -} - - -static LRESULT -PAGER_SetButtonSize (HWND hwnd, WPARAM wParam, LPARAM lParam) -{ - PAGER_INFO *infoPtr = PAGER_GetInfoPtr (hwnd); - INT nTemp = infoPtr->nButtonSize; - - infoPtr->nButtonSize = (INT)lParam; - TRACE("[%p] %d\n", hwnd, infoPtr->nButtonSize); - - PAGER_RecalcSize(hwnd); - - return (LRESULT)nTemp; -} - - -static LRESULT -PAGER_SetChild (HWND hwnd, WPARAM wParam, LPARAM lParam) -{ - PAGER_INFO *infoPtr = PAGER_GetInfoPtr (hwnd); - INT hw; - - infoPtr->hwndChild = IsWindow ((HWND)lParam) ? (HWND)lParam : 0; - - if (infoPtr->hwndChild) - { - TRACE("[%p] hwndChild=%p\n", hwnd, infoPtr->hwndChild); - - if (PAGER_IsHorizontal(hwnd)) { - hw = PAGER_SetFixedHeight(hwnd, infoPtr); - /* adjust non-scrollable dimension to fit the child */ - SetWindowPos(hwnd, 0, 0,0, hw, infoPtr->nHeight, - SWP_FRAMECHANGED | SWP_NOMOVE | SWP_NOZORDER | - SWP_NOSIZE | SWP_NOACTIVATE); - } - else { - hw = PAGER_SetFixedWidth(hwnd, infoPtr); - /* adjust non-scrollable dimension to fit the child */ - SetWindowPos(hwnd, 0, 0,0, infoPtr->nWidth, hw, - SWP_FRAMECHANGED | SWP_NOMOVE | SWP_NOZORDER | - SWP_NOSIZE | SWP_NOACTIVATE); - } - - /* position child within the page scroller */ - SetWindowPos(infoPtr->hwndChild, HWND_TOP, - 0,0,0,0, - SWP_SHOWWINDOW | SWP_NOSIZE); /* native is 0 */ - - infoPtr->nPos = -1; - PAGER_SetPos(hwnd, 0, FALSE); - } - - return 0; -} - -static void -PAGER_Scroll(HWND hwnd, INT dir) -{ - PAGER_INFO *infoPtr = PAGER_GetInfoPtr (hwnd); - NMPGSCROLL nmpgScroll; - RECT rcWnd; - - if (infoPtr->hwndChild) - { - ZeroMemory (&nmpgScroll, sizeof (NMPGSCROLL)); - nmpgScroll.hdr.hwndFrom = hwnd; - nmpgScroll.hdr.idFrom = GetWindowLongPtrW (hwnd, GWLP_ID); - nmpgScroll.hdr.code = PGN_SCROLL; - - GetWindowRect(hwnd, &rcWnd); - GetClientRect(hwnd, &nmpgScroll.rcParent); - nmpgScroll.iXpos = nmpgScroll.iYpos = 0; - nmpgScroll.iDir = dir; - - if (PAGER_IsHorizontal(hwnd)) - { - nmpgScroll.iScroll = rcWnd.right - rcWnd.left; - nmpgScroll.iXpos = infoPtr->nPos; - } - else - { - nmpgScroll.iScroll = rcWnd.bottom - rcWnd.top; - nmpgScroll.iYpos = infoPtr->nPos; - } - nmpgScroll.iScroll -= 2*infoPtr->nButtonSize; - - SendMessageW (infoPtr->hwndNotify, WM_NOTIFY, - (WPARAM)nmpgScroll.hdr.idFrom, (LPARAM)&nmpgScroll); - - TRACE("[%p] PGN_SCROLL returns iScroll=%d\n", hwnd, nmpgScroll.iScroll); - - if (nmpgScroll.iScroll > 0) - { - infoPtr->direction = dir; - - if (dir == PGF_SCROLLLEFT || dir == PGF_SCROLLUP) - PAGER_SetPos(hwnd, infoPtr->nPos - nmpgScroll.iScroll, TRUE); - else - PAGER_SetPos(hwnd, infoPtr->nPos + nmpgScroll.iScroll, TRUE); - } - else - infoPtr->direction = -1; - } -} - -static LRESULT -PAGER_FmtLines(HWND hwnd) -{ - PAGER_INFO *infoPtr = PAGER_GetInfoPtr (hwnd); - - /* initiate NCCalcSize to resize client wnd and get size */ - SetWindowPos(hwnd, 0, 0,0,0,0, - SWP_FRAMECHANGED | SWP_NOSIZE | SWP_NOMOVE | - SWP_NOZORDER | SWP_NOACTIVATE); - - SetWindowPos(infoPtr->hwndChild, 0, - 0,0,infoPtr->nWidth,infoPtr->nHeight, - 0); - - return DefWindowProcW (hwnd, EM_FMTLINES, 0, 0); -} - -static LRESULT -PAGER_Create (HWND hwnd, WPARAM wParam, LPARAM lParam) -{ - PAGER_INFO *infoPtr; - DWORD dwStyle = GetWindowLongA (hwnd, GWL_STYLE); - - /* allocate memory for info structure */ - infoPtr = (PAGER_INFO *)Alloc (sizeof(PAGER_INFO)); - SetWindowLongPtrW (hwnd, 0, (DWORD_PTR)infoPtr); - - /* set default settings */ - infoPtr->hwndChild = NULL; - infoPtr->hwndNotify = ((LPCREATESTRUCTW)lParam)->hwndParent; - infoPtr->bNoResize = dwStyle & CCS_NORESIZE; - infoPtr->clrBk = GetSysColor(COLOR_BTNFACE); - infoPtr->nBorder = 0; - infoPtr->nButtonSize = 12; - infoPtr->nPos = 0; - infoPtr->nWidth = 0; - infoPtr->nHeight = 0; - infoPtr->bForward = FALSE; - infoPtr->bCapture = FALSE; - infoPtr->TLbtnState = PGF_INVISIBLE; - infoPtr->BRbtnState = PGF_INVISIBLE; - infoPtr->direction = -1; - - if (dwStyle & PGS_DRAGNDROP) - FIXME("[%p] Drag and Drop style is not implemented yet.\n", hwnd); - /* - * If neither horizontal nor vertical style specified, default to vertical. - * This is probably not necessary, since the style may be set later on as - * the control is initialized, but just in case it isn't, set it here. - */ - if (!(dwStyle & PGS_HORZ) && !(dwStyle & PGS_VERT)) - { - dwStyle |= PGS_VERT; - SetWindowLongA(hwnd, GWL_STYLE, dwStyle); - } - - return 0; -} - - -static LRESULT -PAGER_Destroy (HWND hwnd, WPARAM wParam, LPARAM lParam) -{ - PAGER_INFO *infoPtr = PAGER_GetInfoPtr (hwnd); - /* free pager info data */ - Free (infoPtr); - SetWindowLongPtrW (hwnd, 0, 0); - return 0; -} - -static LRESULT -PAGER_NCCalcSize(HWND hwnd, WPARAM wParam, LPARAM lParam) -{ - PAGER_INFO *infoPtr = PAGER_GetInfoPtr (hwnd); - LPRECT lpRect = (LPRECT)lParam; - RECT rcChild, rcWindow; - INT scrollRange; - - /* - * lParam points to a RECT struct. On entry, the struct - * contains the proposed wnd rectangle for the window. - * On exit, the struct should contain the screen - * coordinates of the corresponding window's client area. - */ - - DefWindowProcW (hwnd, WM_NCCALCSIZE, wParam, lParam); - - TRACE("orig rect=%s\n", wine_dbgstr_rect(lpRect)); - - GetWindowRect (infoPtr->hwndChild, &rcChild); - MapWindowPoints (0, hwnd, (LPPOINT)&rcChild, 2); /* FIXME: RECT != 2 POINTS */ - GetWindowRect (hwnd, &rcWindow); - - if (PAGER_IsHorizontal(hwnd)) - { - infoPtr->nWidth = lpRect->right - lpRect->left; - PAGER_CalcSize (hwnd, &infoPtr->nWidth, TRUE); - - scrollRange = infoPtr->nWidth - (rcWindow.right - rcWindow.left); - - if (infoPtr->TLbtnState && (lpRect->left + infoPtr->nButtonSize < lpRect->right)) - lpRect->left += infoPtr->nButtonSize; - if (infoPtr->BRbtnState && (lpRect->right - infoPtr->nButtonSize > lpRect->left)) - lpRect->right -= infoPtr->nButtonSize; - } - else - { - infoPtr->nHeight = lpRect->bottom - lpRect->top; - PAGER_CalcSize (hwnd, &infoPtr->nHeight, FALSE); - - scrollRange = infoPtr->nHeight - (rcWindow.bottom - rcWindow.top); - - if (infoPtr->TLbtnState && (lpRect->top + infoPtr->nButtonSize < lpRect->bottom)) - lpRect->top += infoPtr->nButtonSize; - if (infoPtr->BRbtnState && (lpRect->bottom - infoPtr->nButtonSize > lpRect->top)) - lpRect->bottom -= infoPtr->nButtonSize; - } - - TRACE("nPos=%d, nHeigth=%d, window=%s\n", - infoPtr->nPos, infoPtr->nHeight, - wine_dbgstr_rect(&rcWindow)); - - TRACE("[%p] client rect set to %ldx%ld at (%ld,%ld) BtnState[%d,%d]\n", - hwnd, lpRect->right-lpRect->left, lpRect->bottom-lpRect->top, - lpRect->left, lpRect->top, - infoPtr->TLbtnState, infoPtr->BRbtnState); - - return 0; -} - -static LRESULT -PAGER_NCPaint (HWND hwnd, WPARAM wParam, LPARAM lParam) -{ - PAGER_INFO* infoPtr = PAGER_GetInfoPtr(hwnd); - DWORD dwStyle = GetWindowLongA (hwnd, GWL_STYLE); - RECT rcBottomRight, rcTopLeft; - HDC hdc; - BOOL bHorizontal = PAGER_IsHorizontal(hwnd); - - if (dwStyle & WS_MINIMIZE) - return 0; - - DefWindowProcW (hwnd, WM_NCPAINT, wParam, lParam); - - if (!(hdc = GetDCEx (hwnd, 0, DCX_USESTYLE | DCX_WINDOW))) - return 0; - - PAGER_GetButtonRects(hwnd, infoPtr, &rcTopLeft, &rcBottomRight, FALSE); - - PAGER_DrawButton(hdc, infoPtr->clrBk, rcTopLeft, - bHorizontal, TRUE, infoPtr->TLbtnState); - PAGER_DrawButton(hdc, infoPtr->clrBk, rcBottomRight, - bHorizontal, FALSE, infoPtr->BRbtnState); - - ReleaseDC( hwnd, hdc ); - return 0; -} - -static INT -PAGER_HitTest (HWND hwnd, const POINT * pt) -{ - PAGER_INFO *infoPtr = PAGER_GetInfoPtr (hwnd); - RECT clientRect, rcTopLeft, rcBottomRight; - POINT ptWindow; - - GetClientRect (hwnd, &clientRect); - - if (PtInRect(&clientRect, *pt)) - { - TRACE("child\n"); - return -1; - } - - ptWindow = *pt; - PAGER_GetButtonRects(hwnd, infoPtr, &rcTopLeft, &rcBottomRight, TRUE); - - if ((infoPtr->TLbtnState != PGF_INVISIBLE) && PtInRect(&rcTopLeft, ptWindow)) - { - TRACE("PGB_TOPORLEFT\n"); - return PGB_TOPORLEFT; - } - else if ((infoPtr->BRbtnState != PGF_INVISIBLE) && PtInRect(&rcBottomRight, ptWindow)) - { - TRACE("PGB_BOTTOMORRIGHT\n"); - return PGB_BOTTOMORRIGHT; - } - - TRACE("nowhere\n"); - return -1; -} - -static LRESULT -PAGER_NCHitTest (HWND hwnd, WPARAM wParam, LPARAM lParam) -{ - POINT pt; - INT nHit; - - pt.x = (short)LOWORD(lParam); - pt.y = (short)HIWORD(lParam); - - ScreenToClient (hwnd, &pt); - nHit = PAGER_HitTest(hwnd, &pt); - if (nHit < 0) - return HTTRANSPARENT; - return HTCLIENT; -} - -static LRESULT -PAGER_MouseMove (HWND hwnd, WPARAM wParam, LPARAM lParam) -{ - PAGER_INFO *infoPtr = PAGER_GetInfoPtr (hwnd); - POINT clpt, pt; - RECT wnrect, *btnrect = NULL; - DWORD dwStyle = GetWindowLongA (hwnd, GWL_STYLE); - BOOL topLeft = FALSE; - INT btnstate = 0; - INT hit; - HDC hdc; - - pt.x = (short)LOWORD(lParam); - pt.y = (short)HIWORD(lParam); - - TRACE("[%p] to (%ld,%ld)\n", hwnd, pt.x, pt.y); - ClientToScreen(hwnd, &pt); - GetWindowRect(hwnd, &wnrect); - if (PtInRect(&wnrect, pt)) { - RECT TLbtnrect, BRbtnrect; - PAGER_GetButtonRects(hwnd, infoPtr, &TLbtnrect, &BRbtnrect, FALSE); - - clpt = pt; - MapWindowPoints(0, hwnd, &clpt, 1); - hit = PAGER_HitTest(hwnd, &clpt); - if ((hit == PGB_TOPORLEFT) && (infoPtr->TLbtnState == PGF_NORMAL)) - { - topLeft = TRUE; - btnrect = &TLbtnrect; - infoPtr->TLbtnState = PGF_HOT; - btnstate = infoPtr->TLbtnState; - } - else if ((hit == PGB_BOTTOMORRIGHT) && (infoPtr->BRbtnState == PGF_NORMAL)) - { - topLeft = FALSE; - btnrect = &BRbtnrect; - infoPtr->BRbtnState = PGF_HOT; - btnstate = infoPtr->BRbtnState; - } - - /* If in one of the buttons the capture and draw buttons */ - if (btnrect) - { - TRACE("[%p] draw btn (%ld,%ld)-(%ld,%ld), Capture %s, style %08lx\n", - hwnd, btnrect->left, btnrect->top, - btnrect->right, btnrect->bottom, - (infoPtr->bCapture) ? "TRUE" : "FALSE", - dwStyle); - if (!infoPtr->bCapture) - { - TRACE("[%p] SetCapture\n", hwnd); - SetCapture(hwnd); - infoPtr->bCapture = TRUE; - } - if (dwStyle & PGS_AUTOSCROLL) - SetTimer(hwnd, TIMERID1, 0x3e, 0); - hdc = GetWindowDC(hwnd); - /* OffsetRect(wnrect, 0 | 1, 0 | 1) */ - PAGER_DrawButton(hdc, infoPtr->clrBk, *btnrect, - PAGER_IsHorizontal(hwnd), topLeft, btnstate); - ReleaseDC(hwnd, hdc); - return 0; - } - } - - /* If we think we are captured, then do release */ - if (infoPtr->bCapture && (WindowFromPoint(pt) != hwnd)) - { - NMHDR nmhdr; - - infoPtr->bCapture = FALSE; - - if (GetCapture() == hwnd) - { - ReleaseCapture(); - - if (infoPtr->TLbtnState == PGF_GRAYED) - { - infoPtr->TLbtnState = PGF_INVISIBLE; - SetWindowPos(hwnd, 0,0,0,0,0, - SWP_FRAMECHANGED | SWP_NOSIZE | SWP_NOMOVE | - SWP_NOZORDER | SWP_NOACTIVATE); - } - else if (infoPtr->TLbtnState == PGF_HOT) - { - infoPtr->TLbtnState = PGF_NORMAL; - /* FIXME: just invalidate button rect */ - RedrawWindow(hwnd, NULL, NULL, RDW_FRAME | RDW_INVALIDATE); - } - - if (infoPtr->BRbtnState == PGF_GRAYED) - { - infoPtr->BRbtnState = PGF_INVISIBLE; - SetWindowPos(hwnd, 0,0,0,0,0, - SWP_FRAMECHANGED | SWP_NOSIZE | SWP_NOMOVE | - SWP_NOZORDER | SWP_NOACTIVATE); - } - else if (infoPtr->BRbtnState == PGF_HOT) - { - infoPtr->BRbtnState = PGF_NORMAL; - /* FIXME: just invalidate button rect */ - RedrawWindow(hwnd, NULL, NULL, RDW_FRAME | RDW_INVALIDATE); - } - - /* Notify parent of released mouse capture */ - memset(&nmhdr, 0, sizeof(NMHDR)); - nmhdr.hwndFrom = hwnd; - nmhdr.idFrom = GetWindowLongPtrW(hwnd, GWLP_ID); - nmhdr.code = NM_RELEASEDCAPTURE; - SendMessageW(infoPtr->hwndNotify, WM_NOTIFY, - (WPARAM)nmhdr.idFrom, (LPARAM)&nmhdr); - } - if (IsWindow(hwnd)) - KillTimer(hwnd, TIMERID1); - } - return 0; -} - -static LRESULT -PAGER_LButtonDown (HWND hwnd, WPARAM wParam, LPARAM lParam) -{ - PAGER_INFO *infoPtr = PAGER_GetInfoPtr (hwnd); - BOOL repaintBtns = FALSE; - POINT pt; - INT hit; - - pt.x = (short)LOWORD(lParam); - pt.y = (short)HIWORD(lParam); - - TRACE("[%p] at (%d,%d)\n", hwnd, (short)LOWORD(lParam), (short)HIWORD(lParam)); - - hit = PAGER_HitTest(hwnd, &pt); - - /* put btn in DEPRESSED state */ - if (hit == PGB_TOPORLEFT) - { - repaintBtns = infoPtr->TLbtnState != PGF_DEPRESSED; - infoPtr->TLbtnState = PGF_DEPRESSED; - SetTimer(hwnd, TIMERID1, INITIAL_DELAY, 0); - } - else if (hit == PGB_BOTTOMORRIGHT) - { - repaintBtns = infoPtr->BRbtnState != PGF_DEPRESSED; - infoPtr->BRbtnState = PGF_DEPRESSED; - SetTimer(hwnd, TIMERID1, INITIAL_DELAY, 0); - } - - if (repaintBtns) - SendMessageW(hwnd, WM_NCPAINT, 0, 0); - - switch(hit) - { - case PGB_TOPORLEFT: - if (PAGER_IsHorizontal(hwnd)) - { - TRACE("[%p] PGF_SCROLLLEFT\n", hwnd); - PAGER_Scroll(hwnd, PGF_SCROLLLEFT); - } - else - { - TRACE("[%p] PGF_SCROLLUP\n", hwnd); - PAGER_Scroll(hwnd, PGF_SCROLLUP); - } - break; - case PGB_BOTTOMORRIGHT: - if (PAGER_IsHorizontal(hwnd)) - { - TRACE("[%p] PGF_SCROLLRIGHT\n", hwnd); - PAGER_Scroll(hwnd, PGF_SCROLLRIGHT); - } - else - { - TRACE("[%p] PGF_SCROLLDOWN\n", hwnd); - PAGER_Scroll(hwnd, PGF_SCROLLDOWN); - } - break; - default: - break; - } - - return TRUE; -} - -static LRESULT -PAGER_LButtonUp (HWND hwnd, WPARAM wParam, LPARAM lParam) -{ - PAGER_INFO *infoPtr = PAGER_GetInfoPtr (hwnd); - TRACE("[%p]\n", hwnd); - - KillTimer (hwnd, TIMERID1); - KillTimer (hwnd, TIMERID2); - - /* make PRESSED btns NORMAL but don't hide gray btns */ - if (infoPtr->TLbtnState & (PGF_HOT | PGF_DEPRESSED)) - infoPtr->TLbtnState = PGF_NORMAL; - if (infoPtr->BRbtnState & (PGF_HOT | PGF_DEPRESSED)) - infoPtr->BRbtnState = PGF_NORMAL; - - return 0; -} - -static LRESULT -PAGER_Timer (HWND hwnd, WPARAM wParam) -{ - PAGER_INFO *infoPtr = PAGER_GetInfoPtr (hwnd); - DWORD dwStyle = GetWindowLongA (hwnd, GWL_STYLE); - INT dir; - - /* if initial timer, kill it and start the repeat timer */ - if (wParam == TIMERID1) { - if (infoPtr->TLbtnState == PGF_HOT) - dir = PAGER_IsHorizontal(hwnd) ? - PGF_SCROLLLEFT : PGF_SCROLLUP; - else - dir = PAGER_IsHorizontal(hwnd) ? - PGF_SCROLLRIGHT : PGF_SCROLLDOWN; - TRACE("[%p] TIMERID1: style=%08lx, dir=%d\n", hwnd, dwStyle, dir); - KillTimer(hwnd, TIMERID1); - SetTimer(hwnd, TIMERID1, REPEAT_DELAY, 0); - if (dwStyle & PGS_AUTOSCROLL) { - PAGER_Scroll(hwnd, dir); - SetWindowPos(hwnd, 0,0,0,0,0, - SWP_FRAMECHANGED | SWP_NOSIZE | SWP_NOMOVE | - SWP_NOZORDER | SWP_NOACTIVATE); - } - return 0; - - } - - TRACE("[%p] TIMERID2: dir=%d\n", hwnd, infoPtr->direction); - KillTimer(hwnd, TIMERID2); - if (infoPtr->direction > 0) { - PAGER_Scroll(hwnd, infoPtr->direction); - SetTimer(hwnd, TIMERID2, REPEAT_DELAY, 0); - } - return 0; -} - -static LRESULT -PAGER_EraseBackground (HWND hwnd, WPARAM wParam, LPARAM lParam) -{ - POINT pt, ptorig; - HDC hdc = (HDC)wParam; - HWND parent; - - pt.x = 0; - pt.y = 0; - parent = GetParent(hwnd); - MapWindowPoints(hwnd, parent, &pt, 1); - OffsetWindowOrgEx (hdc, pt.x, pt.y, &ptorig); - SendMessageW (parent, WM_ERASEBKGND, wParam, lParam); - SetWindowOrgEx (hdc, ptorig.x, ptorig.y, 0); - - return TRUE; -} - - -static LRESULT -PAGER_Size (HWND hwnd, WPARAM wParam, LPARAM lParam) -{ - /* note that WM_SIZE is sent whenever NCCalcSize resizes the client wnd */ - - PAGER_INFO *infoPtr = PAGER_GetInfoPtr (hwnd); - TRACE("[%p] %dx%d\n", hwnd, (short)LOWORD(lParam), (short)HIWORD(lParam)); - - if (PAGER_IsHorizontal(hwnd)) - infoPtr->nHeight = (short)HIWORD(lParam); - else - infoPtr->nWidth = (short)LOWORD(lParam); - - return PAGER_RecalcSize(hwnd); -} - - -static LRESULT WINAPI -PAGER_WindowProc (HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam) -{ - PAGER_INFO *infoPtr = PAGER_GetInfoPtr (hwnd); - - if (!infoPtr && (uMsg != WM_CREATE)) - return DefWindowProcW (hwnd, uMsg, wParam, lParam); - - switch (uMsg) - { - case EM_FMTLINES: - return PAGER_FmtLines(hwnd); - - case PGM_FORWARDMOUSE: - return PAGER_ForwardMouse (hwnd, wParam); - - case PGM_GETBKCOLOR: - return PAGER_GetBkColor(hwnd); - - case PGM_GETBORDER: - return PAGER_GetBorder(hwnd); - - case PGM_GETBUTTONSIZE: - return PAGER_GetButtonSize(hwnd); - - case PGM_GETPOS: - return PAGER_GetPos(hwnd); - - case PGM_GETBUTTONSTATE: - return PAGER_GetButtonState (hwnd, wParam, lParam); - -/* case PGM_GETDROPTARGET: */ - - case PGM_RECALCSIZE: - return PAGER_RecalcSize(hwnd); - - case PGM_SETBKCOLOR: - return PAGER_SetBkColor (hwnd, wParam, lParam); - - case PGM_SETBORDER: - return PAGER_SetBorder (hwnd, wParam, lParam); - - case PGM_SETBUTTONSIZE: - return PAGER_SetButtonSize (hwnd, wParam, lParam); - - case PGM_SETCHILD: - return PAGER_SetChild (hwnd, wParam, lParam); - - case PGM_SETPOS: - return PAGER_SetPos(hwnd, (INT)lParam, FALSE); - - case WM_CREATE: - return PAGER_Create (hwnd, wParam, lParam); - - case WM_DESTROY: - return PAGER_Destroy (hwnd, wParam, lParam); - - case WM_SIZE: - return PAGER_Size (hwnd, wParam, lParam); - - case WM_NCPAINT: - return PAGER_NCPaint (hwnd, wParam, lParam); - - case WM_WINDOWPOSCHANGING: - return PAGER_HandleWindowPosChanging (hwnd, wParam, (WINDOWPOS*)lParam); - - case WM_NCCALCSIZE: - return PAGER_NCCalcSize (hwnd, wParam, lParam); - - case WM_NCHITTEST: - return PAGER_NCHitTest (hwnd, wParam, lParam); - - case WM_MOUSEMOVE: - if (infoPtr->bForward && infoPtr->hwndChild) - PostMessageW(infoPtr->hwndChild, WM_MOUSEMOVE, wParam, lParam); - return PAGER_MouseMove (hwnd, wParam, lParam); - - case WM_LBUTTONDOWN: - return PAGER_LButtonDown (hwnd, wParam, lParam); - - case WM_LBUTTONUP: - return PAGER_LButtonUp (hwnd, wParam, lParam); - - case WM_ERASEBKGND: - return PAGER_EraseBackground (hwnd, wParam, lParam); - - case WM_TIMER: - return PAGER_Timer (hwnd, wParam); - - case WM_NOTIFY: - case WM_COMMAND: - return SendMessageW (infoPtr->hwndNotify, uMsg, wParam, lParam); - - default: - return DefWindowProcW (hwnd, uMsg, wParam, lParam); - } - - return 0; -} - - -VOID -PAGER_Register (void) -{ - WNDCLASSW wndClass; - - ZeroMemory (&wndClass, sizeof(WNDCLASSW)); - wndClass.style = CS_GLOBALCLASS; - wndClass.lpfnWndProc = PAGER_WindowProc; - wndClass.cbClsExtra = 0; - wndClass.cbWndExtra = sizeof(PAGER_INFO *); - wndClass.hCursor = LoadCursorW (0, (LPWSTR)IDC_ARROW); - wndClass.hbrBackground = (HBRUSH)(COLOR_BTNFACE+1); - wndClass.lpszClassName = WC_PAGESCROLLERW; - - RegisterClassW (&wndClass); -} - - -VOID -PAGER_Unregister (void) -{ - UnregisterClassW (WC_PAGESCROLLERW, NULL); -} diff --git a/reactos/lib/comctl32/progress.c b/reactos/lib/comctl32/progress.c deleted file mode 100644 index 72cc2516a4f..00000000000 --- a/reactos/lib/comctl32/progress.c +++ /dev/null @@ -1,681 +0,0 @@ -/* - * Progress control - * - * Copyright 1997, 2002 Dimitrie O. Paun - * Copyright 1998, 1999 Eric Kohl - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2.1 of the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - * - * NOTE - * - * This code was audited for completeness against the documented features - * of Comctl32.dll version 6.0 on Sep. 9, 2002, 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. - * - */ - -#include -#include -#include "windef.h" -#include "winbase.h" -#include "wingdi.h" -#include "winuser.h" -#include "winnls.h" -#include "commctrl.h" -#include "comctl32.h" -#include "wine/debug.h" - -WINE_DEFAULT_DEBUG_CHANNEL(progress); - -typedef struct -{ - HWND Self; /* The window handle for this control */ - INT CurVal; /* Current progress value */ - INT MinVal; /* Minimum progress value */ - INT MaxVal; /* Maximum progress value */ - INT Step; /* Step to use on PMB_STEPIT */ - INT MarqueePos; /* Marquee animation position */ - BOOL Marquee; /* Whether the marquee animation is enabled */ - COLORREF ColorBar; /* Bar color */ - COLORREF ColorBk; /* Background color */ - HFONT Font; /* Handle to font (not unused) */ -} PROGRESS_INFO; - -/* Control configuration constants */ - -#define LED_GAP 2 -#define MARQUEE_LEDS 5 -#define ID_MARQUEE_TIMER 1 - -/*********************************************************************** - * PROGRESS_Invalidate - * - * Invalide the range between old and new pos. - */ -static void PROGRESS_Invalidate( PROGRESS_INFO *infoPtr, INT old, INT new ) -{ - LONG style = GetWindowLongW (infoPtr->Self, GWL_STYLE); - RECT rect; - int oldPos, newPos, ledWidth; - - GetClientRect (infoPtr->Self, &rect); - InflateRect(&rect, -1, -1); - - if (style & PBS_VERTICAL) - { - oldPos = rect.bottom - MulDiv (old - infoPtr->MinVal, rect.bottom - rect.top, - infoPtr->MaxVal - infoPtr->MinVal); - newPos = rect.bottom - MulDiv (new - infoPtr->MinVal, rect.bottom - rect.top, - infoPtr->MaxVal - infoPtr->MinVal); - ledWidth = MulDiv (rect.right - rect.left, 2, 3); - rect.top = min( oldPos, newPos ); - rect.bottom = max( oldPos, newPos ); - if (!(style & PBS_SMOOTH)) rect.top -= ledWidth; - InvalidateRect( infoPtr->Self, &rect, oldPos < newPos ); - } - else - { - oldPos = rect.left + MulDiv (old - infoPtr->MinVal, rect.right - rect.left, - infoPtr->MaxVal - infoPtr->MinVal); - newPos = rect.left + MulDiv (new - infoPtr->MinVal, rect.right - rect.left, - infoPtr->MaxVal - infoPtr->MinVal); - ledWidth = MulDiv (rect.bottom - rect.top, 2, 3); - rect.left = min( oldPos, newPos ); - rect.right = max( oldPos, newPos ); - if (!(style & PBS_SMOOTH)) rect.right += ledWidth; - InvalidateRect( infoPtr->Self, &rect, oldPos > newPos ); - } -} - - -/*********************************************************************** - * PROGRESS_Draw - * Draws the progress bar. - */ -static LRESULT PROGRESS_Draw (PROGRESS_INFO *infoPtr, HDC hdc) -{ - HBRUSH hbrBar, hbrBk; - int rightBar, rightMost, ledWidth; - RECT rect; - DWORD dwStyle; - - TRACE("(infoPtr=%p, hdc=%p)\n", infoPtr, hdc); - - /* get the required bar brush */ - if (infoPtr->ColorBar == CLR_DEFAULT) - hbrBar = GetSysColorBrush(COLOR_HIGHLIGHT); - else - hbrBar = CreateSolidBrush (infoPtr->ColorBar); - - if (infoPtr->ColorBk == CLR_DEFAULT) - hbrBk = GetSysColorBrush(COLOR_3DFACE); - else - hbrBk = CreateSolidBrush(infoPtr->ColorBk); - - /* get client rectangle */ - GetClientRect (infoPtr->Self, &rect); - FrameRect( hdc, &rect, hbrBk ); - InflateRect(&rect, -1, -1); - - /* get the window style */ - dwStyle = GetWindowLongW (infoPtr->Self, GWL_STYLE); - - /* compute extent of progress bar */ - if (dwStyle & PBS_VERTICAL) { - rightBar = rect.bottom - - MulDiv (infoPtr->CurVal - infoPtr->MinVal, - rect.bottom - rect.top, - infoPtr->MaxVal - infoPtr->MinVal); - ledWidth = MulDiv (rect.right - rect.left, 2, 3); - rightMost = rect.top; - } else { - rightBar = rect.left + - MulDiv (infoPtr->CurVal - infoPtr->MinVal, - rect.right - rect.left, - infoPtr->MaxVal - infoPtr->MinVal); - ledWidth = MulDiv (rect.bottom - rect.top, 2, 3); - rightMost = rect.right; - } - - /* now draw the bar */ - if (dwStyle & PBS_SMOOTH) - { - if (dwStyle & PBS_VERTICAL) - { - if (dwStyle & PBS_MARQUEE) - { - INT old_top, old_bottom, ledMStart, leds; - old_top = rect.top; - old_bottom = rect.bottom; - - leds = rect.bottom - rect.top; - ledMStart = (infoPtr->MarqueePos + MARQUEE_LEDS) - leds; - - if(ledMStart > 0) - { - rect.top = max(rect.bottom - ledMStart, old_top); - FillRect(hdc, &rect, hbrBar); - rect.bottom = rect.top; - } - if(infoPtr->MarqueePos > 0) - { - rect.top = max(old_bottom - infoPtr->MarqueePos, old_top); - FillRect(hdc, &rect, hbrBk); - rect.bottom = rect.top; - } - if(rect.top >= old_top) - { - rect.top = max(rect.bottom - MARQUEE_LEDS, old_top); - FillRect(hdc, &rect, hbrBar); - rect.bottom = rect.top; - } - if(rect.top >= old_top) - { - rect.top = old_top; - FillRect(hdc, &rect, hbrBk); - } - } - else - { - INT old_top = rect.top; - rect.top = rightBar; - FillRect(hdc, &rect, hbrBar); - rect.bottom = rect.top; - rect.top = old_top; - FillRect(hdc, &rect, hbrBk); - } - } - else - { - if (dwStyle & PBS_MARQUEE) - { - INT old_left, old_right, ledMStart, leds; - old_left = rect.left; - old_right = rect.right; - - leds = rect.right - rect.left; - ledMStart = (infoPtr->MarqueePos + MARQUEE_LEDS) - leds; - rect.right = rect.left; - - if(ledMStart > 0) - { - rect.right = min(rect.left + ledMStart, old_right); - FillRect(hdc, &rect, hbrBar); - rect.left = rect.right; - } - if(infoPtr->MarqueePos > 0) - { - rect.right = min(old_left + infoPtr->MarqueePos, old_right); - FillRect(hdc, &rect, hbrBk); - rect.left = rect.right; - } - if(rect.right < old_right) - { - rect.right = min(rect.left + MARQUEE_LEDS, old_right); - FillRect(hdc, &rect, hbrBar); - rect.left = rect.right; - } - if(rect.right < old_right) - { - rect.right = old_right; - FillRect(hdc, &rect, hbrBk); - } - } - else - { - INT old_right = rect.right; - rect.right = rightBar; - FillRect(hdc, &rect, hbrBar); - rect.left = rect.right; - rect.right = old_right; - FillRect(hdc, &rect, hbrBk); - } - } - } else { - if (dwStyle & PBS_VERTICAL) { - if (dwStyle & PBS_MARQUEE) - { - INT i, old_top, old_bottom, ledMStart, leds; - old_top = rect.top; - old_bottom = rect.bottom; - - leds = ((rect.bottom - rect.top) + (ledWidth + LED_GAP) - 1) / (ledWidth + LED_GAP); - ledMStart = (infoPtr->MarqueePos + MARQUEE_LEDS) - leds; - - while(ledMStart > 0) - { - rect.top = max(rect.bottom - ledWidth, old_top); - FillRect(hdc, &rect, hbrBar); - rect.bottom = rect.top; - rect.top -= LED_GAP; - if (rect.top <= old_top) break; - FillRect(hdc, &rect, hbrBk); - rect.bottom = rect.top; - ledMStart--; - } - if(infoPtr->MarqueePos > 0) - { - rect.top = max(old_bottom - (infoPtr->MarqueePos * (ledWidth + LED_GAP)), old_top); - FillRect(hdc, &rect, hbrBk); - rect.bottom = rect.top; - } - for(i = 0; i < MARQUEE_LEDS && rect.top >= old_top; i++) - { - rect.top = max(rect.bottom - ledWidth, old_top); - FillRect(hdc, &rect, hbrBar); - rect.bottom = rect.top; - rect.top -= LED_GAP; - if (rect.top <= old_top) break; - FillRect(hdc, &rect, hbrBk); - rect.bottom = rect.top; - } - if(rect.top >= old_top) - { - rect.top = old_top; - FillRect(hdc, &rect, hbrBk); - } - } - else - { - while(rect.bottom > rightBar) { - rect.top = rect.bottom - ledWidth; - if (rect.top < rightMost) - rect.top = rightMost; - FillRect(hdc, &rect, hbrBar); - rect.bottom = rect.top; - rect.top -= LED_GAP; - if (rect.top <= rightBar) break; - FillRect(hdc, &rect, hbrBk); - rect.bottom = rect.top; - } - } - rect.top = rightMost; - FillRect(hdc, &rect, hbrBk); - } else { - if (dwStyle & PBS_MARQUEE) - { - INT i, old_right, old_left, ledMStart, leds; - old_left = rect.left; - old_right = rect.right; - - leds = ((rect.right - rect.left) + ledWidth - 1) / (ledWidth + LED_GAP); - ledMStart = (infoPtr->MarqueePos + MARQUEE_LEDS) - leds; - rect.right = rect.left; - - while(ledMStart > 0) - { - rect.right = min(rect.left + ledWidth, old_right); - FillRect(hdc, &rect, hbrBar); - rect.left = rect.right; - rect.right += LED_GAP; - if (rect.right > old_right) break; - FillRect(hdc, &rect, hbrBk); - rect.left = rect.right; - ledMStart--; - } - if(infoPtr->MarqueePos > 0) - { - rect.right = min(old_left + (infoPtr->MarqueePos * (ledWidth + LED_GAP)), old_right); - FillRect(hdc, &rect, hbrBk); - rect.left = rect.right; - } - for(i = 0; i < MARQUEE_LEDS && rect.right < old_right; i++) - { - rect.right = min(rect.left + ledWidth, old_right); - FillRect(hdc, &rect, hbrBar); - rect.left = rect.right; - rect.right += LED_GAP; - if (rect.right > old_right) break; - FillRect(hdc, &rect, hbrBk); - rect.left = rect.right; - } - if(rect.right < old_right) - { - rect.right = old_right; - FillRect(hdc, &rect, hbrBk); - } - } - else - { - while(rect.left < rightBar) { - rect.right = rect.left + ledWidth; - if (rect.right > rightMost) - rect.right = rightMost; - FillRect(hdc, &rect, hbrBar); - rect.left = rect.right; - rect.right += LED_GAP; - if (rect.right >= rightBar) break; - FillRect(hdc, &rect, hbrBk); - rect.left = rect.right; - } - rect.right = rightMost; - FillRect(hdc, &rect, hbrBk); - } - } - } - - /* delete bar brush */ - if (infoPtr->ColorBar != CLR_DEFAULT) DeleteObject (hbrBar); - if (infoPtr->ColorBk != CLR_DEFAULT) DeleteObject (hbrBk); - - return 0; -} - - -/*********************************************************************** - * PROGRESS_Paint - * Draw the progress bar. The background need not be erased. - * If dc!=0, it draws on it - */ -static LRESULT PROGRESS_Paint (PROGRESS_INFO *infoPtr, HDC hdc) -{ - PAINTSTRUCT ps; - if (hdc) return PROGRESS_Draw (infoPtr, hdc); - hdc = BeginPaint (infoPtr->Self, &ps); - PROGRESS_Draw (infoPtr, hdc); - EndPaint (infoPtr->Self, &ps); - return 0; -} - - -/*********************************************************************** - * PROGRESS_Timer - * Handle the marquee timer messages - */ -static LRESULT PROGRESS_Timer (PROGRESS_INFO *infoPtr, INT idTimer) -{ - if(idTimer == ID_MARQUEE_TIMER) - { - LONG style = GetWindowLongW (infoPtr->Self, GWL_STYLE); - RECT rect; - int ledWidth, leds; - - GetClientRect (infoPtr->Self, &rect); - InflateRect(&rect, -1, -1); - - if(!(style & PBS_SMOOTH)) - { - int width, height; - - if(style & PBS_VERTICAL) - { - width = rect.bottom - rect.top; - height = rect.right - rect.left; - } - else - { - height = rect.bottom - rect.top; - width = rect.right - rect.left; - } - ledWidth = MulDiv (height, 2, 3); - leds = (width + ledWidth - 1) / (ledWidth + LED_GAP); - } - else - { - ledWidth = 1; - if(style & PBS_VERTICAL) - { - leds = rect.bottom - rect.top; - } - else - { - leds = rect.right - rect.left; - } - } - - /* increment the marquee progress */ - if(++infoPtr->MarqueePos >= leds) - { - infoPtr->MarqueePos = 0; - } - - InvalidateRect(infoPtr->Self, &rect, TRUE); - } - return 0; -} - - -/*********************************************************************** - * PROGRESS_CoercePos - * Makes sure the current position (CurVal) is within bounds. - */ -static void PROGRESS_CoercePos(PROGRESS_INFO *infoPtr) -{ - if(infoPtr->CurVal < infoPtr->MinVal) - infoPtr->CurVal = infoPtr->MinVal; - if(infoPtr->CurVal > infoPtr->MaxVal) - infoPtr->CurVal = infoPtr->MaxVal; -} - - -/*********************************************************************** - * PROGRESS_SetFont - * Set new Font for progress bar - */ -static HFONT PROGRESS_SetFont (PROGRESS_INFO *infoPtr, HFONT hFont, BOOL bRedraw) -{ - HFONT hOldFont = infoPtr->Font; - infoPtr->Font = hFont; - /* Since infoPtr->Font is not used, there is no need for repaint */ - return hOldFont; -} - -static DWORD PROGRESS_SetRange (PROGRESS_INFO *infoPtr, int low, int high) -{ - DWORD res = MAKELONG(LOWORD(infoPtr->MinVal), LOWORD(infoPtr->MaxVal)); - - /* if nothing changes, simply return */ - if(infoPtr->MinVal == low && infoPtr->MaxVal == high) return res; - - infoPtr->MinVal = low; - infoPtr->MaxVal = high; - PROGRESS_CoercePos(infoPtr); - InvalidateRect(infoPtr->Self, NULL, TRUE); - return res; -} - -/*********************************************************************** - * ProgressWindowProc - */ -static LRESULT WINAPI ProgressWindowProc(HWND hwnd, UINT message, - WPARAM wParam, LPARAM lParam) -{ - PROGRESS_INFO *infoPtr; - - TRACE("hwnd=%p msg=%04x wparam=%x lParam=%lx\n", hwnd, message, wParam, lParam); - - infoPtr = (PROGRESS_INFO *)GetWindowLongPtrW(hwnd, 0); - - if (!infoPtr && message != WM_CREATE) - return DefWindowProcW( hwnd, message, wParam, lParam ); - - switch(message) { - case WM_CREATE: - { - DWORD dwExStyle = GetWindowLongW (hwnd, GWL_EXSTYLE); - dwExStyle &= ~(WS_EX_CLIENTEDGE | WS_EX_WINDOWEDGE); - dwExStyle |= WS_EX_STATICEDGE; - SetWindowLongW (hwnd, GWL_EXSTYLE, dwExStyle); - /* Force recalculation of a non-client area */ - SetWindowPos(hwnd, 0, 0, 0, 0, 0, - SWP_FRAMECHANGED | SWP_NOSIZE | SWP_NOMOVE | SWP_NOZORDER | SWP_NOACTIVATE); - - /* allocate memory for info struct */ - infoPtr = (PROGRESS_INFO *)Alloc (sizeof(PROGRESS_INFO)); - if (!infoPtr) return -1; - SetWindowLongPtrW (hwnd, 0, (DWORD_PTR)infoPtr); - - /* initialize the info struct */ - infoPtr->Self = hwnd; - infoPtr->MinVal = 0; - infoPtr->MaxVal = 100; - infoPtr->CurVal = 0; - infoPtr->Step = 10; - infoPtr->MarqueePos = 0; - infoPtr->Marquee = FALSE; - infoPtr->ColorBar = CLR_DEFAULT; - infoPtr->ColorBk = CLR_DEFAULT; - infoPtr->Font = 0; - TRACE("Progress Ctrl creation, hwnd=%p\n", hwnd); - return 0; - } - - case WM_DESTROY: - TRACE("Progress Ctrl destruction, hwnd=%p\n", hwnd); - Free (infoPtr); - SetWindowLongPtrW(hwnd, 0, 0); - return 0; - - case WM_GETFONT: - return (LRESULT)infoPtr->Font; - - case WM_SETFONT: - return (LRESULT)PROGRESS_SetFont(infoPtr, (HFONT)wParam, (BOOL)lParam); - - case WM_PAINT: - return PROGRESS_Paint (infoPtr, (HDC)wParam); - - case WM_TIMER: - return PROGRESS_Timer (infoPtr, (INT)wParam); - - case PBM_DELTAPOS: - { - INT oldVal; - oldVal = infoPtr->CurVal; - if(wParam != 0) { - infoPtr->CurVal += (INT)wParam; - PROGRESS_CoercePos (infoPtr); - TRACE("PBM_DELTAPOS: current pos changed from %d to %d\n", oldVal, infoPtr->CurVal); - PROGRESS_Invalidate( infoPtr, oldVal, infoPtr->CurVal ); - } - return oldVal; - } - - case PBM_SETPOS: - { - UINT oldVal; - oldVal = infoPtr->CurVal; - if(oldVal != wParam) { - infoPtr->CurVal = (INT)wParam; - PROGRESS_CoercePos(infoPtr); - TRACE("PBM_SETPOS: current pos changed from %d to %d\n", oldVal, infoPtr->CurVal); - PROGRESS_Invalidate( infoPtr, oldVal, infoPtr->CurVal ); - } - return oldVal; - } - - case PBM_SETRANGE: - return PROGRESS_SetRange (infoPtr, (int)LOWORD(lParam), (int)HIWORD(lParam)); - - case PBM_SETSTEP: - { - INT oldStep; - oldStep = infoPtr->Step; - infoPtr->Step = (INT)wParam; - return oldStep; - } - - case PBM_STEPIT: - { - INT oldVal; - oldVal = infoPtr->CurVal; - infoPtr->CurVal += infoPtr->Step; - if(infoPtr->CurVal > infoPtr->MaxVal) - infoPtr->CurVal = infoPtr->MinVal; - if(oldVal != infoPtr->CurVal) - { - TRACE("PBM_STEPIT: current pos changed from %d to %d\n", oldVal, infoPtr->CurVal); - PROGRESS_Invalidate( infoPtr, oldVal, infoPtr->CurVal ); - } - return oldVal; - } - - case PBM_SETRANGE32: - return PROGRESS_SetRange (infoPtr, (int)wParam, (int)lParam); - - case PBM_GETRANGE: - if (lParam) { - ((PPBRANGE)lParam)->iLow = infoPtr->MinVal; - ((PPBRANGE)lParam)->iHigh = infoPtr->MaxVal; - } - return wParam ? infoPtr->MinVal : infoPtr->MaxVal; - - case PBM_GETPOS: - return infoPtr->CurVal; - - case PBM_SETBARCOLOR: - infoPtr->ColorBar = (COLORREF)lParam; - InvalidateRect(hwnd, NULL, TRUE); - return 0; - - case PBM_SETBKCOLOR: - infoPtr->ColorBk = (COLORREF)lParam; - InvalidateRect(hwnd, NULL, TRUE); - return 0; - - case PBM_SETMARQUEE: - if(wParam != 0) - { - infoPtr->Marquee = TRUE; - SetTimer(infoPtr->Self, ID_MARQUEE_TIMER, (UINT)lParam, NULL); - } - else - { - infoPtr->Marquee = FALSE; - KillTimer(infoPtr->Self, ID_MARQUEE_TIMER); - } - return infoPtr->Marquee; - - default: - if ((message >= WM_USER) && (message < WM_APP)) - ERR("unknown msg %04x wp=%04x lp=%08lx\n", message, wParam, lParam ); - return DefWindowProcW( hwnd, message, wParam, lParam ); - } -} - - -/*********************************************************************** - * PROGRESS_Register [Internal] - * - * Registers the progress bar window class. - */ -void PROGRESS_Register (void) -{ - WNDCLASSW wndClass; - - ZeroMemory (&wndClass, sizeof(wndClass)); - wndClass.style = CS_GLOBALCLASS | CS_VREDRAW | CS_HREDRAW; - wndClass.lpfnWndProc = (WNDPROC)ProgressWindowProc; - wndClass.cbClsExtra = 0; - wndClass.cbWndExtra = sizeof (PROGRESS_INFO *); - wndClass.hCursor = LoadCursorW (0, (LPWSTR)IDC_ARROW); - wndClass.lpszClassName = PROGRESS_CLASSW; - - RegisterClassW (&wndClass); -} - - -/*********************************************************************** - * PROGRESS_Unregister [Internal] - * - * Unregisters the progress bar window class. - */ -void PROGRESS_Unregister (void) -{ - UnregisterClassW (PROGRESS_CLASSW, NULL); -} diff --git a/reactos/lib/comctl32/propsheet.c b/reactos/lib/comctl32/propsheet.c deleted file mode 100644 index c49672fc977..00000000000 --- a/reactos/lib/comctl32/propsheet.c +++ /dev/null @@ -1,3695 +0,0 @@ -/* - * Property Sheets - * - * Copyright 1998 Francis Beaudet - * Copyright 1999 Thuy Nguyen - * Copyright 2004 Maxime Bellenge - * Copyright 2004 Filip Navara - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2.1 of the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - * - * This code was audited for completeness against the documented features - * of Comctl32.dll version 6.0 on Sep. 12, 2004, by Filip Navara. - * - * 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: - * - Tab order - * - Wizard 97 header resizing - * - Enforcing of minimal wizard size - * - Messages: - * o PSM_GETRESULT - * o PSM_IDTOINDEX - * o PSM_INSERTPAGE - * o PSM_RECALCPAGESIZES - * o PSM_SETHEADERSUBTITLE - * o PSM_SETHEADERTITLE - * o WM_HELP - * o WM_CONTEXTMENU - * - Notifications: - * o PSN_GETOBJECT - * o PSN_QUERYINITIALFOCUS - * o PSN_TRANSLATEACCELERATOR - * - Styles: - * o PSH_WIZARDHASFINISH - * o PSH_RTLREADING - * o PSH_STRETCHWATERMARK - * o PSH_USEPAGELANG - * o PSH_USEPSTARTPAGE - * - Page styles: - * o PSP_USEFUSIONCONTEXT - * o PSP_USEREFPARENT - */ - -#include -#include - -#define NONAMELESSUNION -#define NONAMELESSSTRUCT -#include "windef.h" -#include "winbase.h" -#include "wingdi.h" -#include "winuser.h" -#include "winnls.h" -#include "commctrl.h" -#include "prsht.h" -#include "comctl32.h" - -#include "wine/debug.h" -#include "wine/unicode.h" - -/****************************************************************************** - * Data structures - */ -#include "pshpack2.h" - -typedef struct -{ - WORD dlgVer; - WORD signature; - DWORD helpID; - DWORD exStyle; - DWORD style; -} MyDLGTEMPLATEEX; - -typedef struct -{ - DWORD helpid; - DWORD exStyle; - DWORD style; - short x; - short y; - short cx; - short cy; - DWORD id; -} MyDLGITEMTEMPLATEEX; -#include "poppack.h" - -typedef struct tagPropPageInfo -{ - HPROPSHEETPAGE hpage; /* to keep track of pages not passed to PropertySheet */ - HWND hwndPage; - BOOL isDirty; - LPCWSTR pszText; - BOOL hasHelp; - BOOL useCallback; - BOOL hasIcon; -} PropPageInfo; - -typedef struct tagPropSheetInfo -{ - HWND hwnd; - PROPSHEETHEADERW ppshheader; - BOOL unicode; - LPWSTR strPropertiesFor; - int nPages; - int active_page; - BOOL isModeless; - BOOL hasHelp; - BOOL hasApply; - BOOL useCallback; - BOOL restartWindows; - BOOL rebootSystem; - BOOL activeValid; - PropPageInfo* proppage; - HFONT hFont; - HFONT hFontBold; - int width; - int height; - HIMAGELIST hImageList; -} PropSheetInfo; - -typedef struct -{ - int x; - int y; -} PADDING_INFO; - -/****************************************************************************** - * Defines and global variables - */ - -const WCHAR PropSheetInfoStr[] = - {'P','r','o','p','e','r','t','y','S','h','e','e','t','I','n','f','o',0 }; - -#define PSP_INTERNAL_UNICODE 0x80000000 - -#define MAX_CAPTION_LENGTH 255 -#define MAX_TABTEXT_LENGTH 255 -#define MAX_BUTTONTEXT_LENGTH 64 - -#define INTRNL_ANY_WIZARD (PSH_WIZARD | PSH_WIZARD97_OLD | PSH_WIZARD97_NEW | PSH_WIZARD_LITE) - -/* Wizard metrics specified in DLUs */ -#define WIZARD_PADDING 7 -#define WIZARD_HEADER_HEIGHT 36 - -/****************************************************************************** - * Prototypes - */ -static int PROPSHEET_CreateDialog(PropSheetInfo* psInfo); -static BOOL PROPSHEET_SizeMismatch(HWND hwndDlg, PropSheetInfo* psInfo); -static BOOL PROPSHEET_AdjustSize(HWND hwndDlg, PropSheetInfo* psInfo); -static BOOL PROPSHEET_AdjustButtons(HWND hwndParent, PropSheetInfo* psInfo); -static BOOL PROPSHEET_CollectSheetInfoA(LPCPROPSHEETHEADERA lppsh, - PropSheetInfo * psInfo); -static BOOL PROPSHEET_CollectSheetInfoW(LPCPROPSHEETHEADERW lppsh, - PropSheetInfo * psInfo); -static BOOL PROPSHEET_CollectPageInfo(LPCPROPSHEETPAGEW lppsp, - PropSheetInfo * psInfo, - int index); -static BOOL PROPSHEET_CreateTabControl(HWND hwndParent, - PropSheetInfo * psInfo); -static BOOL PROPSHEET_CreatePage(HWND hwndParent, int index, - const PropSheetInfo * psInfo, - LPCPROPSHEETPAGEW ppshpage); -static BOOL PROPSHEET_ShowPage(HWND hwndDlg, int index, PropSheetInfo * psInfo); -static PADDING_INFO PROPSHEET_GetPaddingInfo(HWND hwndDlg); -static BOOL PROPSHEET_Back(HWND hwndDlg); -static BOOL PROPSHEET_Next(HWND hwndDlg); -static BOOL PROPSHEET_Finish(HWND hwndDlg); -static BOOL PROPSHEET_Apply(HWND hwndDlg, LPARAM lParam); -static void PROPSHEET_Cancel(HWND hwndDlg, LPARAM lParam); -static void PROPSHEET_Help(HWND hwndDlg); -static void PROPSHEET_Changed(HWND hwndDlg, HWND hwndDirtyPage); -static void PROPSHEET_UnChanged(HWND hwndDlg, HWND hwndCleanPage); -static void PROPSHEET_PressButton(HWND hwndDlg, int buttonID); -static void PROPSHEET_SetFinishTextA(HWND hwndDlg, LPCSTR lpszText); -static void PROPSHEET_SetFinishTextW(HWND hwndDlg, LPCWSTR lpszText); -static void PROPSHEET_SetTitleA(HWND hwndDlg, DWORD dwStyle, LPCSTR lpszText); -static void PROPSHEET_SetTitleW(HWND hwndDlg, DWORD dwStyle, LPCWSTR lpszText); -static BOOL PROPSHEET_CanSetCurSel(HWND hwndDlg); -static BOOL PROPSHEET_SetCurSel(HWND hwndDlg, - int index, - int skipdir, - HPROPSHEETPAGE hpage); -static void PROPSHEET_SetCurSelId(HWND hwndDlg, int id); -static LRESULT PROPSHEET_QuerySiblings(HWND hwndDlg, - WPARAM wParam, LPARAM lParam); -static BOOL PROPSHEET_AddPage(HWND hwndDlg, - HPROPSHEETPAGE hpage); - -static BOOL PROPSHEET_RemovePage(HWND hwndDlg, - int index, - HPROPSHEETPAGE hpage); -static void PROPSHEET_CleanUp(HWND hwndDlg); -static int PROPSHEET_GetPageIndex(HPROPSHEETPAGE hpage, PropSheetInfo* psInfo); -static void PROPSHEET_SetWizButtons(HWND hwndDlg, DWORD dwFlags); -static PADDING_INFO PROPSHEET_GetPaddingInfoWizard(HWND hwndDlg, const PropSheetInfo* psInfo); -static BOOL PROPSHEET_IsDialogMessage(HWND hwnd, LPMSG lpMsg); -static BOOL PROPSHEET_DoCommand(HWND hwnd, WORD wID); - -INT_PTR CALLBACK -PROPSHEET_DialogProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam); - -WINE_DEFAULT_DEBUG_CHANNEL(propsheet); - -#define add_flag(a) if (dwFlags & a) {strcat(string, #a );strcat(string," ");} -/****************************************************************************** - * PROPSHEET_UnImplementedFlags - * - * Document use of flags we don't implement yet. - */ -static VOID PROPSHEET_UnImplementedFlags(DWORD dwFlags) -{ - CHAR string[256]; - - string[0] = '\0'; - - /* - * unhandled header flags: - * PSH_WIZARDHASFINISH 0x00000010 - * PSH_RTLREADING 0x00000800 - * PSH_STRETCHWATERMARK 0x00040000 - * PSH_USEPAGELANG 0x00200000 - */ - - add_flag(PSH_WIZARDHASFINISH); - add_flag(PSH_RTLREADING); - add_flag(PSH_STRETCHWATERMARK); - add_flag(PSH_USEPAGELANG); - if (string[0] != '\0') - FIXME("%s\n", string); -} -#undef add_flag - -/****************************************************************************** - * PROPSHEET_GetPageRect - * - * Retrieve rect from tab control and map into the dialog for SetWindowPos - */ -static void PROPSHEET_GetPageRect(const PropSheetInfo * psInfo, HWND hwndDlg, - RECT *rc, LPCPROPSHEETPAGEW ppshpage) -{ - if (psInfo->ppshheader.dwFlags & INTRNL_ANY_WIZARD) { - HWND hwndChild; - RECT r; - - if (((psInfo->ppshheader.dwFlags & (PSH_WIZARD97_NEW | PSH_WIZARD97_OLD)) && - (psInfo->ppshheader.dwFlags & PSH_HEADER) && - !(ppshpage->dwFlags & PSP_HIDEHEADER)) || - (psInfo->ppshheader.dwFlags & PSH_WIZARD)) - { - rc->left = rc->top = WIZARD_PADDING; - } - else - { - rc->left = rc->top = 0; - } - rc->right = psInfo->width - rc->left; - rc->bottom = psInfo->height - rc->top; - MapDialogRect(hwndDlg, rc); - - if ((psInfo->ppshheader.dwFlags & (PSH_WIZARD97_NEW | PSH_WIZARD97_OLD)) && - (psInfo->ppshheader.dwFlags & PSH_HEADER) && - !(ppshpage->dwFlags & PSP_HIDEHEADER)) - { - hwndChild = GetDlgItem(hwndDlg, IDC_SUNKEN_LINEHEADER); - GetClientRect(hwndChild, &r); - MapWindowPoints(hwndChild, hwndDlg, (LPPOINT) &r, 2); - rc->top += r.bottom + 1; - } - } else { - HWND hwndTabCtrl = GetDlgItem(hwndDlg, IDC_TABCONTROL); - GetClientRect(hwndTabCtrl, rc); - SendMessageW(hwndTabCtrl, TCM_ADJUSTRECT, FALSE, (LPARAM)rc); - MapWindowPoints(hwndTabCtrl, hwndDlg, (LPPOINT)rc, 2); - } -} - -/****************************************************************************** - * PROPSHEET_FindPageByResId - * - * Find page index corresponding to page resource id. - */ -INT PROPSHEET_FindPageByResId(PropSheetInfo * psInfo, LRESULT resId) -{ - INT i; - - for (i = 0; i < psInfo->nPages; i++) - { - LPCPROPSHEETPAGEA lppsp = (LPCPROPSHEETPAGEA)psInfo->proppage[i].hpage; - - /* Fixme: if resource ID is a string shall we use strcmp ??? */ - if (lppsp->u.pszTemplate == (LPVOID)resId) - break; - } - - return i; -} - -/****************************************************************************** - * PROPSHEET_AtoW - * - * Convert ASCII to Unicode since all data is saved as Unicode. - */ -static void PROPSHEET_AtoW(LPCWSTR *tostr, LPCSTR frstr) -{ - INT len; - - TRACE("<%s>\n", frstr); - len = MultiByteToWideChar(CP_ACP, 0, frstr, -1, 0, 0); - *tostr = (LPWSTR)HeapAlloc(GetProcessHeap(), 0, len * sizeof(WCHAR)); - MultiByteToWideChar(CP_ACP, 0, frstr, -1, (LPWSTR)*tostr, len); -} - -/****************************************************************************** - * PROPSHEET_CollectSheetInfoA - * - * Collect relevant data. - */ -static BOOL PROPSHEET_CollectSheetInfoA(LPCPROPSHEETHEADERA lppsh, - PropSheetInfo * psInfo) -{ - DWORD dwSize = min(lppsh->dwSize,sizeof(PROPSHEETHEADERA)); - DWORD dwFlags = lppsh->dwFlags; - - psInfo->hasHelp = dwFlags & PSH_HASHELP; - psInfo->hasApply = !(dwFlags & PSH_NOAPPLYNOW); - psInfo->useCallback = (dwFlags & PSH_USECALLBACK )&& (lppsh->pfnCallback); - psInfo->isModeless = dwFlags & PSH_MODELESS; - - memcpy(&psInfo->ppshheader,lppsh,dwSize); - TRACE("\n** PROPSHEETHEADER **\ndwSize\t\t%ld\ndwFlags\t\t%08lx\nhwndParent\t%p\nhInstance\t%p\npszCaption\t'%s'\nnPages\t\t%d\npfnCallback\t%p\n", - lppsh->dwSize, lppsh->dwFlags, lppsh->hwndParent, lppsh->hInstance, - debugstr_a(lppsh->pszCaption), lppsh->nPages, lppsh->pfnCallback); - - PROPSHEET_UnImplementedFlags(lppsh->dwFlags); - - if (lppsh->dwFlags & INTRNL_ANY_WIZARD) - psInfo->ppshheader.pszCaption = NULL; - else - { - if (HIWORD(lppsh->pszCaption)) - { - int len = MultiByteToWideChar(CP_ACP, 0, lppsh->pszCaption, -1, NULL, 0); - psInfo->ppshheader.pszCaption = HeapAlloc( GetProcessHeap(), 0, len*sizeof (WCHAR) ); - MultiByteToWideChar(CP_ACP, 0, lppsh->pszCaption, -1, (LPWSTR) psInfo->ppshheader.pszCaption, len); - } - } - psInfo->nPages = lppsh->nPages; - - if (dwFlags & PSH_USEPSTARTPAGE) - { - TRACE("PSH_USEPSTARTPAGE is on\n"); - psInfo->active_page = 0; - } - else - psInfo->active_page = lppsh->u2.nStartPage; - - if (psInfo->active_page < 0 || psInfo->active_page >= psInfo->nPages) - psInfo->active_page = 0; - - psInfo->restartWindows = FALSE; - psInfo->rebootSystem = FALSE; - psInfo->hImageList = 0; - psInfo->activeValid = FALSE; - - return TRUE; -} - -/****************************************************************************** - * PROPSHEET_CollectSheetInfoW - * - * Collect relevant data. - */ -static BOOL PROPSHEET_CollectSheetInfoW(LPCPROPSHEETHEADERW lppsh, - PropSheetInfo * psInfo) -{ - DWORD dwSize = min(lppsh->dwSize,sizeof(PROPSHEETHEADERW)); - DWORD dwFlags = lppsh->dwFlags; - - psInfo->hasHelp = dwFlags & PSH_HASHELP; - psInfo->hasApply = !(dwFlags & PSH_NOAPPLYNOW); - psInfo->useCallback = (dwFlags & PSH_USECALLBACK) && (lppsh->pfnCallback); - psInfo->isModeless = dwFlags & PSH_MODELESS; - - memcpy(&psInfo->ppshheader,lppsh,dwSize); - TRACE("\n** PROPSHEETHEADER **\ndwSize\t\t%ld\ndwFlags\t\t%08lx\nhwndParent\t%p\nhInstance\t%p\npszCaption\t'%s'\nnPages\t\t%d\npfnCallback\t%p\n", - lppsh->dwSize, lppsh->dwFlags, lppsh->hwndParent, lppsh->hInstance, debugstr_w(lppsh->pszCaption), lppsh->nPages, lppsh->pfnCallback); - - PROPSHEET_UnImplementedFlags(lppsh->dwFlags); - - if (lppsh->dwFlags & INTRNL_ANY_WIZARD) - psInfo->ppshheader.pszCaption = NULL; - else - { - if (HIWORD(lppsh->pszCaption)) - { - int len = strlenW(lppsh->pszCaption); - psInfo->ppshheader.pszCaption = HeapAlloc( GetProcessHeap(), 0, (len+1)*sizeof(WCHAR) ); - strcpyW( (WCHAR *)psInfo->ppshheader.pszCaption, lppsh->pszCaption ); - } - } - psInfo->nPages = lppsh->nPages; - - if (dwFlags & PSH_USEPSTARTPAGE) - { - TRACE("PSH_USEPSTARTPAGE is on\n"); - psInfo->active_page = 0; - } - else - psInfo->active_page = lppsh->u2.nStartPage; - - if (psInfo->active_page < 0 || psInfo->active_page >= psInfo->nPages) - psInfo->active_page = 0; - - psInfo->restartWindows = FALSE; - psInfo->rebootSystem = FALSE; - psInfo->hImageList = 0; - psInfo->activeValid = FALSE; - - return TRUE; -} - -/****************************************************************************** - * PROPSHEET_CollectPageInfo - * - * Collect property sheet data. - * With code taken from DIALOG_ParseTemplate32. - */ -BOOL PROPSHEET_CollectPageInfo(LPCPROPSHEETPAGEW lppsp, - PropSheetInfo * psInfo, - int index) -{ - DLGTEMPLATE* pTemplate; - const WORD* p; - DWORD dwFlags; - int width, height; - - TRACE("\n"); - psInfo->proppage[index].hpage = (HPROPSHEETPAGE)lppsp; - psInfo->proppage[index].hwndPage = 0; - psInfo->proppage[index].isDirty = FALSE; - - /* - * Process property page flags. - */ - dwFlags = lppsp->dwFlags; - psInfo->proppage[index].useCallback = (dwFlags & PSP_USECALLBACK) && (lppsp->pfnCallback); - psInfo->proppage[index].hasHelp = dwFlags & PSP_HASHELP; - psInfo->proppage[index].hasIcon = dwFlags & (PSP_USEHICON | PSP_USEICONID); - - /* as soon as we have a page with the help flag, set the sheet flag on */ - if (psInfo->proppage[index].hasHelp) - psInfo->hasHelp = TRUE; - - /* - * Process page template. - */ - if (dwFlags & PSP_DLGINDIRECT) - pTemplate = (DLGTEMPLATE*)lppsp->u.pResource; - else if(dwFlags & PSP_INTERNAL_UNICODE ) - { - HRSRC hResource = FindResourceW(lppsp->hInstance, - lppsp->u.pszTemplate, - (LPWSTR)RT_DIALOG); - HGLOBAL hTemplate = LoadResource(lppsp->hInstance, - hResource); - pTemplate = (LPDLGTEMPLATEW)LockResource(hTemplate); - } - else - { - HRSRC hResource = FindResourceA(lppsp->hInstance, - (LPSTR)lppsp->u.pszTemplate, - (LPSTR)RT_DIALOG); - HGLOBAL hTemplate = LoadResource(lppsp->hInstance, - hResource); - pTemplate = (LPDLGTEMPLATEA)LockResource(hTemplate); - } - - /* - * Extract the size of the page and the caption. - */ - if (!pTemplate) - return FALSE; - - p = (const WORD *)pTemplate; - - if (((MyDLGTEMPLATEEX*)pTemplate)->signature == 0xFFFF) - { - /* DLGTEMPLATEEX (not defined in any std. header file) */ - - p++; /* dlgVer */ - p++; /* signature */ - p += 2; /* help ID */ - p += 2; /* ext style */ - p += 2; /* style */ - } - else - { - /* DLGTEMPLATE */ - - p += 2; /* style */ - p += 2; /* ext style */ - } - - p++; /* nb items */ - p++; /* x */ - p++; /* y */ - width = (WORD)*p; p++; - height = (WORD)*p; p++; - - /* Special calculation for interior wizard pages so the largest page is - * calculated correctly. We need to add all the padding and space occupied - * by the header so the width and height sums up to the whole wizard client - * area. */ - if ((psInfo->ppshheader.dwFlags & (PSH_WIZARD97_OLD | PSH_WIZARD97_NEW)) && - (psInfo->ppshheader.dwFlags & PSH_HEADER) && - !(dwFlags & PSP_HIDEHEADER)) - { - height += 2 * WIZARD_PADDING + WIZARD_HEADER_HEIGHT; - width += 2 * WIZARD_PADDING; - } - if (psInfo->ppshheader.dwFlags & PSH_WIZARD) - { - height += 2 * WIZARD_PADDING; - width += 2 * WIZARD_PADDING; - } - - /* remember the largest width and height */ - if (width > psInfo->width) - psInfo->width = width; - - if (height > psInfo->height) - psInfo->height = height; - - /* menu */ - switch ((WORD)*p) - { - case 0x0000: - p++; - break; - case 0xffff: - p += 2; - break; - default: - p += lstrlenW( (LPCWSTR)p ) + 1; - break; - } - - /* class */ - switch ((WORD)*p) - { - case 0x0000: - p++; - break; - case 0xffff: - p += 2; - break; - default: - p += lstrlenW( (LPCWSTR)p ) + 1; - break; - } - - /* Extract the caption */ - psInfo->proppage[index].pszText = (LPCWSTR)p; - TRACE("Tab %d %s\n",index,debugstr_w((LPCWSTR)p)); - p += lstrlenW((LPCWSTR)p) + 1; - - if (dwFlags & PSP_USETITLE) - { - WCHAR szTitle[256]; - const WCHAR *pTitle; - static const WCHAR pszNull[] = { '(','n','u','l','l',')',0 }; - int len; - - if ( !HIWORD( lppsp->pszTitle ) ) - { - if (!LoadStringW( lppsp->hInstance, (UINT)lppsp->pszTitle,szTitle,sizeof(szTitle) )) - { - pTitle = pszNull; - FIXME("Could not load resource #%04x?\n",LOWORD(lppsp->pszTitle)); - } - else - pTitle = szTitle; - } - else - pTitle = lppsp->pszTitle; - - len = strlenW(pTitle); - psInfo->proppage[index].pszText = Alloc( (len+1)*sizeof (WCHAR) ); - strcpyW( (LPWSTR)psInfo->proppage[index].pszText,pTitle); - } - - /* - * Build the image list for icons - */ - if ((dwFlags & PSP_USEHICON) || (dwFlags & PSP_USEICONID)) - { - HICON hIcon; - int icon_cx = GetSystemMetrics(SM_CXSMICON); - int icon_cy = GetSystemMetrics(SM_CYSMICON); - - if (dwFlags & PSP_USEICONID) - hIcon = LoadImageW(lppsp->hInstance, lppsp->u2.pszIcon, IMAGE_ICON, - icon_cx, icon_cy, LR_DEFAULTCOLOR); - else - hIcon = lppsp->u2.hIcon; - - if ( hIcon ) - { - if (psInfo->hImageList == 0 ) - psInfo->hImageList = ImageList_Create(icon_cx, icon_cy, ILC_COLOR, 1, 1); - - ImageList_AddIcon(psInfo->hImageList, hIcon); - } - - } - - return TRUE; -} - -/****************************************************************************** - * PROPSHEET_CreateDialog - * - * Creates the actual property sheet. - */ -int PROPSHEET_CreateDialog(PropSheetInfo* psInfo) -{ - LRESULT ret; - LPCVOID template; - LPVOID temp = 0; - HRSRC hRes; - DWORD resSize; - WORD resID = IDD_PROPSHEET; - - TRACE("\n"); - if (psInfo->ppshheader.dwFlags & INTRNL_ANY_WIZARD) - resID = IDD_WIZARD; - - if( psInfo->unicode ) - { - if(!(hRes = FindResourceW(COMCTL32_hModule, - MAKEINTRESOURCEW(resID), - (LPWSTR)RT_DIALOG))) - return -1; - } - else - { - if(!(hRes = FindResourceA(COMCTL32_hModule, - MAKEINTRESOURCEA(resID), - (LPSTR)RT_DIALOG))) - return -1; - } - - if(!(template = (LPVOID)LoadResource(COMCTL32_hModule, hRes))) - return -1; - - /* - * Make a copy of the dialog template. - */ - resSize = SizeofResource(COMCTL32_hModule, hRes); - - temp = Alloc(resSize); - - if (!temp) - return -1; - - memcpy(temp, template, resSize); - - if (psInfo->ppshheader.dwFlags & PSH_NOCONTEXTHELP) - { - if (((MyDLGTEMPLATEEX*)temp)->signature == 0xFFFF) - ((MyDLGTEMPLATEEX*)temp)->style &= ~DS_CONTEXTHELP; - else - ((DLGTEMPLATE*)temp)->style &= ~DS_CONTEXTHELP; - } - if ((psInfo->ppshheader.dwFlags & INTRNL_ANY_WIZARD) && - (psInfo->ppshheader.dwFlags & PSH_WIZARDCONTEXTHELP)) - { - if (((MyDLGTEMPLATEEX*)temp)->signature == 0xFFFF) - ((MyDLGTEMPLATEEX*)temp)->style |= DS_CONTEXTHELP; - else - ((DLGTEMPLATE*)temp)->style |= DS_CONTEXTHELP; - } - - if (psInfo->useCallback) - (*(psInfo->ppshheader.pfnCallback))(0, PSCB_PRECREATE, (LPARAM)temp); - - /* NOTE: MSDN states "Returns a positive value if successful, or -1 - * otherwise for modal property sheets.", but this is wrong. The - * actual return value is either TRUE (success), FALSE (cancel) or - * -1 (error). */ - if( psInfo->unicode ) - { - if (!(psInfo->ppshheader.dwFlags & PSH_MODELESS)) - ret = DialogBoxIndirectParamW(psInfo->ppshheader.hInstance, - (LPDLGTEMPLATEW) temp, - psInfo->ppshheader.hwndParent, - PROPSHEET_DialogProc, - (LPARAM)psInfo); - else - { - ret = (int)CreateDialogIndirectParamW(psInfo->ppshheader.hInstance, - (LPDLGTEMPLATEW) temp, - psInfo->ppshheader.hwndParent, - PROPSHEET_DialogProc, - (LPARAM)psInfo); - if ( !ret ) ret = -1; - } - } - else - { - if (!(psInfo->ppshheader.dwFlags & PSH_MODELESS)) - ret = DialogBoxIndirectParamA(psInfo->ppshheader.hInstance, - (LPDLGTEMPLATEA) temp, - psInfo->ppshheader.hwndParent, - PROPSHEET_DialogProc, - (LPARAM)psInfo); - else - { - ret = (int)CreateDialogIndirectParamA(psInfo->ppshheader.hInstance, - (LPDLGTEMPLATEA) temp, - psInfo->ppshheader.hwndParent, - PROPSHEET_DialogProc, - (LPARAM)psInfo); - if ( !ret ) ret = -1; - } - } - - Free(temp); - - return ret; -} - -/****************************************************************************** - * PROPSHEET_SizeMismatch - * - * Verify that the tab control and the "largest" property sheet page dlg. template - * match in size. - */ -static BOOL PROPSHEET_SizeMismatch(HWND hwndDlg, PropSheetInfo* psInfo) -{ - HWND hwndTabCtrl = GetDlgItem(hwndDlg, IDC_TABCONTROL); - RECT rcOrigTab, rcPage; - - /* - * Original tab size. - */ - GetClientRect(hwndTabCtrl, &rcOrigTab); - TRACE("orig tab %ld %ld %ld %ld\n", rcOrigTab.left, rcOrigTab.top, - rcOrigTab.right, rcOrigTab.bottom); - - /* - * Biggest page size. - */ - rcPage.left = 0; - rcPage.top = 0; - rcPage.right = psInfo->width; - rcPage.bottom = psInfo->height; - - MapDialogRect(hwndDlg, &rcPage); - TRACE("biggest page %ld %ld %ld %ld\n", rcPage.left, rcPage.top, - rcPage.right, rcPage.bottom); - - if ( (rcPage.right - rcPage.left) != (rcOrigTab.right - rcOrigTab.left) ) - return TRUE; - if ( (rcPage.bottom - rcPage.top) != (rcOrigTab.bottom - rcOrigTab.top) ) - return TRUE; - - return FALSE; -} - -/****************************************************************************** - * PROPSHEET_AdjustSize - * - * Resizes the property sheet and the tab control to fit the largest page. - */ -static BOOL PROPSHEET_AdjustSize(HWND hwndDlg, PropSheetInfo* psInfo) -{ - HWND hwndTabCtrl = GetDlgItem(hwndDlg, IDC_TABCONTROL); - HWND hwndButton = GetDlgItem(hwndDlg, IDOK); - RECT rc,tabRect; - int tabOffsetX, tabOffsetY, buttonHeight; - PADDING_INFO padding = PROPSHEET_GetPaddingInfo(hwndDlg); - RECT units; - - /* Get the height of buttons */ - GetClientRect(hwndButton, &rc); - buttonHeight = rc.bottom; - - /* - * Biggest page size. - */ - rc.left = 0; - rc.top = 0; - rc.right = psInfo->width; - rc.bottom = psInfo->height; - - MapDialogRect(hwndDlg, &rc); - - /* retrieve the dialog units */ - units.left = units.right = 4; - units.top = units.bottom = 8; - MapDialogRect(hwndDlg, &units); - - /* - * Resize the tab control. - */ - GetClientRect(hwndTabCtrl,&tabRect); - - SendMessageW(hwndTabCtrl, TCM_ADJUSTRECT, FALSE, (LPARAM)&tabRect); - - if ((rc.bottom - rc.top) < (tabRect.bottom - tabRect.top)) - { - rc.bottom = rc.top + tabRect.bottom - tabRect.top; - psInfo->height = MulDiv((rc.bottom - rc.top),8,units.top); - } - - if ((rc.right - rc.left) < (tabRect.right - tabRect.left)) - { - rc.right = rc.left + tabRect.right - tabRect.left; - psInfo->width = MulDiv((rc.right - rc.left),4,units.left); - } - - SendMessageW(hwndTabCtrl, TCM_ADJUSTRECT, TRUE, (LPARAM)&rc); - - tabOffsetX = -(rc.left); - tabOffsetY = -(rc.top); - - rc.right -= rc.left; - rc.bottom -= rc.top; - TRACE("setting tab %08lx, rc (0,0)-(%ld,%ld)\n", - (DWORD)hwndTabCtrl, rc.right, rc.bottom); - SetWindowPos(hwndTabCtrl, 0, 0, 0, rc.right, rc.bottom, - SWP_NOMOVE | SWP_NOZORDER | SWP_NOACTIVATE); - - GetClientRect(hwndTabCtrl, &rc); - - TRACE("tab client rc %ld %ld %ld %ld\n", - rc.left, rc.top, rc.right, rc.bottom); - - rc.right += ((padding.x * 2) + tabOffsetX); - rc.bottom += (buttonHeight + (3 * padding.y) + tabOffsetY); - - /* - * Resize the property sheet. - */ - TRACE("setting dialog %08lx, rc (0,0)-(%ld,%ld)\n", - (DWORD)hwndDlg, rc.right, rc.bottom); - SetWindowPos(hwndDlg, 0, 0, 0, rc.right, rc.bottom, - SWP_NOMOVE | SWP_NOZORDER | SWP_NOACTIVATE); - return TRUE; -} - -/****************************************************************************** - * PROPSHEET_AdjustSizeWizard - * - * Resizes the property sheet to fit the largest page. - */ -static BOOL PROPSHEET_AdjustSizeWizard(HWND hwndDlg, PropSheetInfo* psInfo) -{ - HWND hwndLine = GetDlgItem(hwndDlg, IDC_SUNKEN_LINE); - RECT rc, lineRect, dialogRect; - - /* Biggest page size */ - rc.left = 0; - rc.top = 0; - rc.right = psInfo->width; - rc.bottom = psInfo->height; - MapDialogRect(hwndDlg, &rc); - - TRACE("Biggest page %ld %ld %ld %ld\n", rc.left, rc.top, rc.right, rc.bottom); - - /* Add space for the buttons row */ - GetWindowRect(hwndLine, &lineRect); - MapWindowPoints(NULL, hwndDlg, (LPPOINT)&lineRect, 2); - GetClientRect(hwndDlg, &dialogRect); - rc.bottom += dialogRect.bottom - lineRect.top - 1; - - /* Convert the client coordinates to window coordinates */ - AdjustWindowRect(&rc, GetWindowLongW(hwndDlg, GWL_STYLE), FALSE); - - /* Resize the property sheet */ - TRACE("setting dialog %08lx, rc (0,0)-(%ld,%ld)\n", - (DWORD)hwndDlg, rc.right, rc.bottom); - SetWindowPos(hwndDlg, 0, 0, 0, rc.right - rc.left, rc.bottom - rc.top, - SWP_NOMOVE | SWP_NOZORDER | SWP_NOACTIVATE); - - return TRUE; -} - -/****************************************************************************** - * PROPSHEET_AdjustButtons - * - * Adjusts the buttons' positions. - */ -static BOOL PROPSHEET_AdjustButtons(HWND hwndParent, PropSheetInfo* psInfo) -{ - HWND hwndButton = GetDlgItem(hwndParent, IDOK); - RECT rcSheet; - int x, y; - int num_buttons = 2; - int buttonWidth, buttonHeight; - PADDING_INFO padding = PROPSHEET_GetPaddingInfo(hwndParent); - - if (psInfo->hasApply) - num_buttons++; - - if (psInfo->hasHelp) - num_buttons++; - - /* - * Obtain the size of the buttons. - */ - GetClientRect(hwndButton, &rcSheet); - buttonWidth = rcSheet.right; - buttonHeight = rcSheet.bottom; - - /* - * Get the size of the property sheet. - */ - GetClientRect(hwndParent, &rcSheet); - - /* - * All buttons will be at this y coordinate. - */ - y = rcSheet.bottom - (padding.y + buttonHeight); - - /* - * Position OK button and make it default. - */ - hwndButton = GetDlgItem(hwndParent, IDOK); - - x = rcSheet.right - ((padding.x + buttonWidth) * num_buttons); - - SetWindowPos(hwndButton, 0, x, y, 0, 0, - SWP_NOSIZE | SWP_NOZORDER | SWP_NOACTIVATE); - - SendMessageA(hwndParent, DM_SETDEFID, IDOK, 0); - - - /* - * Position Cancel button. - */ - hwndButton = GetDlgItem(hwndParent, IDCANCEL); - - x = rcSheet.right - ((padding.x + buttonWidth) * (num_buttons - 1)); - - SetWindowPos(hwndButton, 0, x, y, 0, 0, - SWP_NOSIZE | SWP_NOZORDER | SWP_NOACTIVATE); - - /* - * Position Apply button. - */ - hwndButton = GetDlgItem(hwndParent, IDC_APPLY_BUTTON); - - if (psInfo->hasApply) - { - if (psInfo->hasHelp) - x = rcSheet.right - ((padding.x + buttonWidth) * 2); - else - x = rcSheet.right - (padding.x + buttonWidth); - - SetWindowPos(hwndButton, 0, x, y, 0, 0, - SWP_NOSIZE | SWP_NOZORDER | SWP_NOACTIVATE); - - EnableWindow(hwndButton, FALSE); - } - else - ShowWindow(hwndButton, SW_HIDE); - - /* - * Position Help button. - */ - hwndButton = GetDlgItem(hwndParent, IDHELP); - - if (psInfo->hasHelp) - { - x = rcSheet.right - (padding.x + buttonWidth); - - SetWindowPos(hwndButton, 0, x, y, 0, 0, - SWP_NOSIZE | SWP_NOZORDER | SWP_NOACTIVATE); - } - else - ShowWindow(hwndButton, SW_HIDE); - - return TRUE; -} - -/****************************************************************************** - * PROPSHEET_AdjustButtonsWizard - * - * Adjusts the buttons' positions. - */ -static BOOL PROPSHEET_AdjustButtonsWizard(HWND hwndParent, - PropSheetInfo* psInfo) -{ - HWND hwndButton = GetDlgItem(hwndParent, IDCANCEL); - HWND hwndLine = GetDlgItem(hwndParent, IDC_SUNKEN_LINE); - HWND hwndLineHeader = GetDlgItem(hwndParent, IDC_SUNKEN_LINEHEADER); - RECT rcSheet; - int x, y; - int num_buttons = 3; - int buttonWidth, buttonHeight, lineHeight, lineWidth; - PADDING_INFO padding = PROPSHEET_GetPaddingInfoWizard(hwndParent, psInfo); - - if (psInfo->hasHelp) - num_buttons++; - - /* - * Obtain the size of the buttons. - */ - GetClientRect(hwndButton, &rcSheet); - buttonWidth = rcSheet.right; - buttonHeight = rcSheet.bottom; - - GetClientRect(hwndLine, &rcSheet); - lineHeight = rcSheet.bottom; - - /* - * Get the size of the property sheet. - */ - GetClientRect(hwndParent, &rcSheet); - - /* - * All buttons will be at this y coordinate. - */ - y = rcSheet.bottom - (padding.y + buttonHeight); - - /* - * Position the Next and the Finish buttons. - */ - hwndButton = GetDlgItem(hwndParent, IDC_NEXT_BUTTON); - - x = rcSheet.right - ((padding.x + buttonWidth) * (num_buttons - 1)); - - SetWindowPos(hwndButton, 0, x, y, 0, 0, - SWP_NOSIZE | SWP_NOZORDER | SWP_NOACTIVATE); - - hwndButton = GetDlgItem(hwndParent, IDC_FINISH_BUTTON); - - SetWindowPos(hwndButton, 0, x, y, 0, 0, - SWP_NOSIZE | SWP_NOZORDER | SWP_NOACTIVATE); - - ShowWindow(hwndButton, SW_HIDE); - - /* - * Position the Back button. - */ - hwndButton = GetDlgItem(hwndParent, IDC_BACK_BUTTON); - - x -= buttonWidth; - - SetWindowPos(hwndButton, 0, x, y, 0, 0, - SWP_NOSIZE | SWP_NOZORDER | SWP_NOACTIVATE); - - /* - * Position the Cancel button. - */ - hwndButton = GetDlgItem(hwndParent, IDCANCEL); - - x = rcSheet.right - ((padding.x + buttonWidth) * (num_buttons - 2)); - - SetWindowPos(hwndButton, 0, x, y, 0, 0, - SWP_NOSIZE | SWP_NOZORDER | SWP_NOACTIVATE); - - /* - * Position Help button. - */ - hwndButton = GetDlgItem(hwndParent, IDHELP); - - if (psInfo->hasHelp) - { - x = rcSheet.right - (padding.x + buttonWidth); - - SetWindowPos(hwndButton, 0, x, y, 0, 0, - SWP_NOSIZE | SWP_NOZORDER | SWP_NOACTIVATE); - } - else - ShowWindow(hwndButton, SW_HIDE); - - if (psInfo->ppshheader.dwFlags & - (PSH_WIZARD97_OLD | PSH_WIZARD97_NEW | PSH_WIZARD_LITE)) - padding.x = 0; - - /* - * Position and resize the sunken line. - */ - x = padding.x; - y = rcSheet.bottom - ((padding.y * 2) + buttonHeight + lineHeight); - - lineWidth = rcSheet.right - (padding.x * 2); - SetWindowPos(hwndLine, 0, x, y, lineWidth, 2, - SWP_NOZORDER | SWP_NOACTIVATE); - - /* - * Position and resize the header sunken line. - */ - - SetWindowPos(hwndLineHeader, 0, 0, 0, rcSheet.right, 2, - SWP_NOZORDER | SWP_NOMOVE | SWP_NOACTIVATE); - if (!(psInfo->ppshheader.dwFlags & (PSH_WIZARD97_OLD | PSH_WIZARD97_NEW))) - ShowWindow(hwndLineHeader, SW_HIDE); - - return TRUE; -} - -/****************************************************************************** - * PROPSHEET_GetPaddingInfo - * - * Returns the layout information. - */ -static PADDING_INFO PROPSHEET_GetPaddingInfo(HWND hwndDlg) -{ - HWND hwndTab = GetDlgItem(hwndDlg, IDC_TABCONTROL); - RECT rcTab; - POINT tl; - PADDING_INFO padding; - - GetWindowRect(hwndTab, &rcTab); - - tl.x = rcTab.left; - tl.y = rcTab.top; - - ScreenToClient(hwndDlg, &tl); - - padding.x = tl.x; - padding.y = tl.y; - - return padding; -} - -/****************************************************************************** - * PROPSHEET_GetPaddingInfoWizard - * - * Returns the layout information. - * Vertical spacing is the distance between the line and the buttons. - * Do NOT use the Help button to gather padding information when it isn't mapped - * (PSH_HASHELP), as app writers aren't forced to supply correct coordinates - * for it in this case ! - * FIXME: I'm not sure about any other coordinate problems with these evil - * buttons. Fix it in case additional problems appear or maybe calculate - * a padding in a completely different way, as this is somewhat messy. - */ -static PADDING_INFO PROPSHEET_GetPaddingInfoWizard(HWND hwndDlg, const PropSheetInfo* - psInfo) -{ - PADDING_INFO padding; - RECT rc; - HWND hwndControl; - INT idButton; - POINT ptButton, ptLine; - - TRACE("\n"); - if (psInfo->hasHelp) - { - idButton = IDHELP; - } - else - { - if (psInfo->ppshheader.dwFlags & INTRNL_ANY_WIZARD) - { - idButton = IDC_NEXT_BUTTON; - } - else - { - /* hopefully this is ok */ - idButton = IDCANCEL; - } - } - - hwndControl = GetDlgItem(hwndDlg, idButton); - GetWindowRect(hwndControl, &rc); - - ptButton.x = rc.left; - ptButton.y = rc.top; - - ScreenToClient(hwndDlg, &ptButton); - - /* Line */ - hwndControl = GetDlgItem(hwndDlg, IDC_SUNKEN_LINE); - GetWindowRect(hwndControl, &rc); - - ptLine.x = rc.left; - ptLine.y = rc.bottom; - - ScreenToClient(hwndDlg, &ptLine); - - padding.y = ptButton.y - ptLine.y; - - if (padding.y < 0) - ERR("padding negative ! Please report this !\n"); - - /* this is most probably not correct, but the best we have now */ - padding.x = padding.y; - return padding; -} - -/****************************************************************************** - * PROPSHEET_CreateTabControl - * - * Insert the tabs in the tab control. - */ -static BOOL PROPSHEET_CreateTabControl(HWND hwndParent, - PropSheetInfo * psInfo) -{ - HWND hwndTabCtrl = GetDlgItem(hwndParent, IDC_TABCONTROL); - TCITEMW item; - int i, nTabs; - int iImage = 0; - - TRACE("\n"); - item.mask = TCIF_TEXT; - item.cchTextMax = MAX_TABTEXT_LENGTH; - - nTabs = psInfo->nPages; - - /* - * Set the image list for icons. - */ - if (psInfo->hImageList) - { - SendMessageW(hwndTabCtrl, TCM_SETIMAGELIST, 0, (LPARAM)psInfo->hImageList); - } - - SendMessageW(GetDlgItem(hwndTabCtrl, IDC_TABCONTROL), WM_SETREDRAW, 0, 0); - for (i = 0; i < nTabs; i++) - { - if ( psInfo->proppage[i].hasIcon ) - { - item.mask |= TCIF_IMAGE; - item.iImage = iImage++; - } - else - { - item.mask &= ~TCIF_IMAGE; - } - - item.pszText = (LPWSTR) psInfo->proppage[i].pszText; - SendMessageW(hwndTabCtrl, TCM_INSERTITEMW, (WPARAM)i, (LPARAM)&item); - } - SendMessageW(GetDlgItem(hwndTabCtrl, IDC_TABCONTROL), WM_SETREDRAW, 1, 0); - - return TRUE; -} - -/****************************************************************************** - * PROPSHEET_WizardSubclassProc - * - * Subclassing window procedure for wizard extrior pages to prevent drawing - * background and so drawing above the watermark. - */ -LRESULT CALLBACK -PROPSHEET_WizardSubclassProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam, UINT_PTR uID, DWORD_PTR dwRef) -{ - switch (uMsg) - { - case WM_ERASEBKGND: - return TRUE; - - case WM_CTLCOLORSTATIC: - SetBkColor((HDC)wParam, GetSysColor(COLOR_WINDOW)); - return (INT_PTR)GetSysColorBrush(COLOR_WINDOW); - } - - return DefSubclassProc(hwnd, uMsg, wParam, lParam); -} - -/* - * Get the size of an in-memory Template - * - *( Based on the code of PROPSHEET_CollectPageInfo) - * See also dialog.c/DIALOG_ParseTemplate32(). - */ - -static UINT GetTemplateSize(DLGTEMPLATE* pTemplate) - -{ - const WORD* p = (const WORD *)pTemplate; - BOOL istemplateex = (((MyDLGTEMPLATEEX*)pTemplate)->signature == 0xFFFF); - WORD nrofitems; - - if (istemplateex) - { - /* DLGTEMPLATEEX (not defined in any std. header file) */ - - TRACE("is DLGTEMPLATEEX\n"); - p++; /* dlgVer */ - p++; /* signature */ - p += 2; /* help ID */ - p += 2; /* ext style */ - p += 2; /* style */ - } - else - { - /* DLGTEMPLATE */ - - TRACE("is DLGTEMPLATE\n"); - p += 2; /* style */ - p += 2; /* ext style */ - } - - nrofitems = (WORD)*p; p++; /* nb items */ - p++; /* x */ - p++; /* y */ - p++; /* width */ - p++; /* height */ - - /* menu */ - switch ((WORD)*p) - { - case 0x0000: - p++; - break; - case 0xffff: - p += 2; - break; - default: - TRACE("menu %s\n",debugstr_w((LPCWSTR)p)); - p += lstrlenW( (LPCWSTR)p ) + 1; - break; - } - - /* class */ - switch ((WORD)*p) - { - case 0x0000: - p++; - break; - case 0xffff: - p += 2; /* 0xffff plus predefined window class ordinal value */ - break; - default: - TRACE("class %s\n",debugstr_w((LPCWSTR)p)); - p += lstrlenW( (LPCWSTR)p ) + 1; - break; - } - - /* title */ - TRACE("title %s\n",debugstr_w((LPCWSTR)p)); - p += lstrlenW((LPCWSTR)p) + 1; - - /* font, if DS_SETFONT set */ - if ((DS_SETFONT & ((istemplateex)? ((MyDLGTEMPLATEEX*)pTemplate)->style : - pTemplate->style))) - { - p+=(istemplateex)?3:1; - TRACE("font %s\n",debugstr_w((LPCWSTR)p)); - p += lstrlenW( (LPCWSTR)p ) + 1; /* the font name */ - } - - /* now process the DLGITEMTEMPLATE(EX) structs (plus custom data) - * that are following the DLGTEMPLATE(EX) data */ - TRACE("%d items\n",nrofitems); - while (nrofitems > 0) - { - p = (WORD*)(((DWORD)p + 3) & ~3); /* DWORD align */ - - /* skip header */ - p += (istemplateex ? sizeof(MyDLGITEMTEMPLATEEX) : sizeof(DLGITEMTEMPLATE))/sizeof(WORD); - - /* check class */ - switch ((WORD)*p) - { - case 0x0000: - p++; - break; - case 0xffff: - TRACE("class ordinal 0x%08lx\n",*(DWORD*)p); - p += 2; - break; - default: - TRACE("class %s\n",debugstr_w((LPCWSTR)p)); - p += lstrlenW( (LPCWSTR)p ) + 1; - break; - } - - /* check title text */ - switch ((WORD)*p) - { - case 0x0000: - p++; - break; - case 0xffff: - TRACE("text ordinal 0x%08lx\n",*(DWORD*)p); - p += 2; - break; - default: - TRACE("text %s\n",debugstr_w((LPCWSTR)p)); - p += lstrlenW( (LPCWSTR)p ) + 1; - break; - } - p += *p / sizeof(WORD) + 1; /* Skip extra data */ - --nrofitems; - } - - TRACE("%p %p size 0x%08x\n",p, (WORD*)pTemplate,sizeof(WORD)*(p - (WORD*)pTemplate)); - return (p - (WORD*)pTemplate)*sizeof(WORD); - -} - -/****************************************************************************** - * PROPSHEET_CreatePage - * - * Creates a page. - */ -static BOOL PROPSHEET_CreatePage(HWND hwndParent, - int index, - const PropSheetInfo * psInfo, - LPCPROPSHEETPAGEW ppshpage) -{ - DLGTEMPLATE* pTemplate; - HWND hwndPage; - DWORD resSize; - LPVOID temp = NULL; - - TRACE("index %d\n", index); - - if (ppshpage == NULL) - { - return FALSE; - } - - if (ppshpage->dwFlags & PSP_DLGINDIRECT) - { - pTemplate = (DLGTEMPLATE*)ppshpage->u.pResource; - resSize = GetTemplateSize(pTemplate); - } - else if(ppshpage->dwFlags & PSP_INTERNAL_UNICODE) - { - HRSRC hResource; - HANDLE hTemplate; - - hResource = FindResourceW(ppshpage->hInstance, - ppshpage->u.pszTemplate, - (LPWSTR)RT_DIALOG); - if(!hResource) - return FALSE; - - resSize = SizeofResource(ppshpage->hInstance, hResource); - - hTemplate = LoadResource(ppshpage->hInstance, hResource); - if(!hTemplate) - return FALSE; - - pTemplate = (LPDLGTEMPLATEW)LockResource(hTemplate); - /* - * Make a copy of the dialog template to make it writable - */ - } - else - { - HRSRC hResource; - HANDLE hTemplate; - - hResource = FindResourceA(ppshpage->hInstance, - (LPSTR)ppshpage->u.pszTemplate, - (LPSTR)RT_DIALOG); - if(!hResource) - return FALSE; - - resSize = SizeofResource(ppshpage->hInstance, hResource); - - hTemplate = LoadResource(ppshpage->hInstance, hResource); - if(!hTemplate) - return FALSE; - - pTemplate = (LPDLGTEMPLATEA)LockResource(hTemplate); - /* - * Make a copy of the dialog template to make it writable - */ - } - temp = Alloc(resSize); - if (!temp) - return FALSE; - - TRACE("copying pTemplate %p into temp %p (%ld)\n", pTemplate, temp, resSize); - memcpy(temp, pTemplate, resSize); - pTemplate = temp; - - if (((MyDLGTEMPLATEEX*)pTemplate)->signature == 0xFFFF) - { - ((MyDLGTEMPLATEEX*)pTemplate)->style |= WS_CHILD | WS_TABSTOP | DS_CONTROL; - ((MyDLGTEMPLATEEX*)pTemplate)->style &= ~DS_MODALFRAME; - ((MyDLGTEMPLATEEX*)pTemplate)->style &= ~WS_CAPTION; - ((MyDLGTEMPLATEEX*)pTemplate)->style &= ~WS_SYSMENU; - ((MyDLGTEMPLATEEX*)pTemplate)->style &= ~WS_POPUP; - ((MyDLGTEMPLATEEX*)pTemplate)->style &= ~WS_DISABLED; - ((MyDLGTEMPLATEEX*)pTemplate)->style &= ~WS_VISIBLE; - ((MyDLGTEMPLATEEX*)pTemplate)->style &= ~WS_THICKFRAME; - - ((MyDLGTEMPLATEEX*)pTemplate)->exStyle |= WS_EX_CONTROLPARENT; - } - else - { - pTemplate->style |= WS_CHILD | WS_TABSTOP | DS_CONTROL; - pTemplate->style &= ~DS_MODALFRAME; - pTemplate->style &= ~WS_CAPTION; - pTemplate->style &= ~WS_SYSMENU; - pTemplate->style &= ~WS_POPUP; - pTemplate->style &= ~WS_DISABLED; - pTemplate->style &= ~WS_VISIBLE; - pTemplate->style &= ~WS_THICKFRAME; - - pTemplate->dwExtendedStyle |= WS_EX_CONTROLPARENT; - } - - if (psInfo->proppage[index].useCallback) - (*(ppshpage->pfnCallback))(0, PSPCB_CREATE, - (LPPROPSHEETPAGEW)ppshpage); - - if(ppshpage->dwFlags & PSP_INTERNAL_UNICODE) - hwndPage = CreateDialogIndirectParamW(ppshpage->hInstance, - pTemplate, - hwndParent, - ppshpage->pfnDlgProc, - (LPARAM)ppshpage); - else - hwndPage = CreateDialogIndirectParamA(ppshpage->hInstance, - pTemplate, - hwndParent, - ppshpage->pfnDlgProc, - (LPARAM)ppshpage); - /* Free a no more needed copy */ - if(temp) - Free(temp); - - psInfo->proppage[index].hwndPage = hwndPage; - - /* Subclass exterior wizard pages */ - if((psInfo->ppshheader.dwFlags & (PSH_WIZARD97_NEW | PSH_WIZARD97_OLD)) && - (psInfo->ppshheader.dwFlags & PSH_WATERMARK) && - (ppshpage->dwFlags & PSP_HIDEHEADER)) - { - SetWindowSubclass(hwndPage, PROPSHEET_WizardSubclassProc, 1, - (DWORD_PTR)ppshpage); - } - - return TRUE; -} - -/****************************************************************************** - * PROPSHEET_LoadWizardBitmaps - * - * Loads the watermark and header bitmaps for a wizard. - */ -static VOID PROPSHEET_LoadWizardBitmaps(PropSheetInfo *psInfo) -{ - if (psInfo->ppshheader.dwFlags & (PSH_WIZARD97_NEW | PSH_WIZARD97_OLD)) - { - /* if PSH_USEHBMWATERMARK is not set, load the resource from pszbmWatermark - and put the HBITMAP in hbmWatermark. Thus all the rest of the code always - considers hbmWatermark as valid. */ - if ((psInfo->ppshheader.dwFlags & PSH_WATERMARK) && - !(psInfo->ppshheader.dwFlags & PSH_USEHBMWATERMARK)) - { - ((PropSheetInfo *)psInfo)->ppshheader.u4.hbmWatermark = - CreateMappedBitmap(psInfo->ppshheader.hInstance, (INT)psInfo->ppshheader.u4.pszbmWatermark, 0, NULL, 0); - } - - /* Same behavior as for watermarks */ - if ((psInfo->ppshheader.dwFlags & PSH_HEADER) && - !(psInfo->ppshheader.dwFlags & PSH_USEHBMHEADER)) - { - ((PropSheetInfo *)psInfo)->ppshheader.u5.hbmHeader = - CreateMappedBitmap(psInfo->ppshheader.hInstance, (INT)psInfo->ppshheader.u5.pszbmHeader, 0, NULL, 0); - } - } -} - - -/****************************************************************************** - * PROPSHEET_ShowPage - * - * Displays or creates the specified page. - */ -static BOOL PROPSHEET_ShowPage(HWND hwndDlg, int index, PropSheetInfo * psInfo) -{ - HWND hwndTabCtrl; - HWND hwndLineHeader; - LPCPROPSHEETPAGEW ppshpage; - - TRACE("active_page %d, index %d\n", psInfo->active_page, index); - if (index == psInfo->active_page) - { - if (GetTopWindow(hwndDlg) != psInfo->proppage[index].hwndPage) - SetWindowPos(psInfo->proppage[index].hwndPage, HWND_TOP, 0, 0, 0, 0, SWP_NOSIZE | SWP_NOMOVE); - return TRUE; - } - - ppshpage = (LPCPROPSHEETPAGEW)psInfo->proppage[index].hpage; - if (psInfo->proppage[index].hwndPage == 0) - { - PROPSHEET_CreatePage(hwndDlg, index, psInfo, ppshpage); - } - - if ((psInfo->ppshheader.dwFlags & INTRNL_ANY_WIZARD) && - (ppshpage->dwFlags & PSP_USETITLE)) - { - PROPSHEET_SetTitleW(hwndDlg, psInfo->ppshheader.dwFlags, - psInfo->proppage[index].pszText); - } - - if (psInfo->active_page != -1) - ShowWindow(psInfo->proppage[psInfo->active_page].hwndPage, SW_HIDE); - - ShowWindow(psInfo->proppage[index].hwndPage, SW_SHOW); - - /* Synchronize current selection with tab control - * It seems to be needed even in case of PSH_WIZARD (no tab controls there) */ - hwndTabCtrl = GetDlgItem(hwndDlg, IDC_TABCONTROL); - SendMessageW(hwndTabCtrl, TCM_SETCURSEL, index, 0); - - psInfo->active_page = index; - psInfo->activeValid = TRUE; - - if (psInfo->ppshheader.dwFlags & (PSH_WIZARD97_OLD | PSH_WIZARD97_NEW) ) - { - hwndLineHeader = GetDlgItem(hwndDlg, IDC_SUNKEN_LINEHEADER); - ppshpage = (LPCPROPSHEETPAGEW)psInfo->proppage[index].hpage; - - if ((ppshpage->dwFlags & PSP_HIDEHEADER) || (!(psInfo->ppshheader.dwFlags & PSH_HEADER)) ) - ShowWindow(hwndLineHeader, SW_HIDE); - else - ShowWindow(hwndLineHeader, SW_SHOW); - } - - InvalidateRgn(hwndDlg, NULL, TRUE); - UpdateWindow(hwndDlg); - - return TRUE; -} - -/****************************************************************************** - * PROPSHEET_Back - */ -static BOOL PROPSHEET_Back(HWND hwndDlg) -{ - PSHNOTIFY psn; - HWND hwndPage; - PropSheetInfo* psInfo = (PropSheetInfo*) GetPropW(hwndDlg, - PropSheetInfoStr); - LRESULT result; - int idx; - - TRACE("active_page %d\n", psInfo->active_page); - if (psInfo->active_page < 0) - return FALSE; - - psn.hdr.code = PSN_WIZBACK; - psn.hdr.hwndFrom = hwndDlg; - psn.hdr.idFrom = 0; - psn.lParam = 0; - - hwndPage = psInfo->proppage[psInfo->active_page].hwndPage; - - result = SendMessageW(hwndPage, WM_NOTIFY, 0, (LPARAM) &psn); - if (result == -1) - return FALSE; - else if (result == 0) - idx = psInfo->active_page - 1; - else - idx = PROPSHEET_FindPageByResId(psInfo, result); - - if (idx >= 0 && idx < psInfo->nPages) - { - if (PROPSHEET_CanSetCurSel(hwndDlg)) - PROPSHEET_SetCurSel(hwndDlg, idx, -1, 0); - } - return TRUE; -} - -/****************************************************************************** - * PROPSHEET_Next - */ -static BOOL PROPSHEET_Next(HWND hwndDlg) -{ - PSHNOTIFY psn; - HWND hwndPage; - LRESULT msgResult = 0; - PropSheetInfo* psInfo = (PropSheetInfo*) GetPropW(hwndDlg, - PropSheetInfoStr); - int idx; - - TRACE("active_page %d\n", psInfo->active_page); - if (psInfo->active_page < 0) - return FALSE; - - psn.hdr.code = PSN_WIZNEXT; - psn.hdr.hwndFrom = hwndDlg; - psn.hdr.idFrom = 0; - psn.lParam = 0; - - hwndPage = psInfo->proppage[psInfo->active_page].hwndPage; - - msgResult = SendMessageA(hwndPage, WM_NOTIFY, 0, (LPARAM) &psn); - if (msgResult == -1) - return FALSE; - else if (msgResult == 0) - idx = psInfo->active_page + 1; - else - idx = PROPSHEET_FindPageByResId(psInfo, msgResult); - - if (idx < psInfo->nPages ) - { - if (PROPSHEET_CanSetCurSel(hwndDlg) != FALSE) - PROPSHEET_SetCurSel(hwndDlg, idx, 1, 0); - } - - return TRUE; -} - -/****************************************************************************** - * PROPSHEET_Finish - */ -static BOOL PROPSHEET_Finish(HWND hwndDlg) -{ - PSHNOTIFY psn; - HWND hwndPage; - LRESULT msgResult = 0; - PropSheetInfo* psInfo = (PropSheetInfo*) GetPropW(hwndDlg, - PropSheetInfoStr); - - TRACE("active_page %d\n", psInfo->active_page); - if (psInfo->active_page < 0) - return FALSE; - - psn.hdr.code = PSN_WIZFINISH; - psn.hdr.hwndFrom = hwndDlg; - psn.hdr.idFrom = 0; - psn.lParam = 0; - - hwndPage = psInfo->proppage[psInfo->active_page].hwndPage; - - msgResult = SendMessageW(hwndPage, WM_NOTIFY, 0, (LPARAM) &psn); - - TRACE("msg result %ld\n", msgResult); - - if (msgResult != 0) - return FALSE; - - if (psInfo->isModeless) - psInfo->activeValid = FALSE; - else - EndDialog(hwndDlg, TRUE); - - return TRUE; -} - -/****************************************************************************** - * PROPSHEET_Apply - */ -static BOOL PROPSHEET_Apply(HWND hwndDlg, LPARAM lParam) -{ - int i; - HWND hwndPage; - PSHNOTIFY psn; - PropSheetInfo* psInfo = (PropSheetInfo*) GetPropW(hwndDlg, - PropSheetInfoStr); - - TRACE("active_page %d\n", psInfo->active_page); - if (psInfo->active_page < 0) - return FALSE; - - psn.hdr.hwndFrom = hwndDlg; - psn.hdr.idFrom = 0; - psn.lParam = 0; - - - /* - * Send PSN_KILLACTIVE to the current page. - */ - psn.hdr.code = PSN_KILLACTIVE; - - hwndPage = psInfo->proppage[psInfo->active_page].hwndPage; - - if (SendMessageA(hwndPage, WM_NOTIFY, 0, (LPARAM) &psn) != FALSE) - return FALSE; - - /* - * Send PSN_APPLY to all pages. - */ - psn.hdr.code = PSN_APPLY; - psn.lParam = lParam; - - for (i = 0; i < psInfo->nPages; i++) - { - hwndPage = psInfo->proppage[i].hwndPage; - if (hwndPage) - { - switch (SendMessageA(hwndPage, WM_NOTIFY, 0, (LPARAM) &psn)) - { - case PSNRET_INVALID: - PROPSHEET_ShowPage(hwndDlg, i, psInfo); - /* fall through */ - case PSNRET_INVALID_NOCHANGEPAGE: - return FALSE; - } - } - } - - if(lParam) - { - psInfo->activeValid = FALSE; - } - else if(psInfo->active_page >= 0) - { - psn.hdr.code = PSN_SETACTIVE; - psn.lParam = 0; - hwndPage = psInfo->proppage[psInfo->active_page].hwndPage; - SendMessageA(hwndPage, WM_NOTIFY, 0, (LPARAM) &psn); - } - - return TRUE; -} - -/****************************************************************************** - * PROPSHEET_Cancel - */ -static void PROPSHEET_Cancel(HWND hwndDlg, LPARAM lParam) -{ - PropSheetInfo* psInfo = (PropSheetInfo*) GetPropW(hwndDlg, - PropSheetInfoStr); - HWND hwndPage; - PSHNOTIFY psn; - int i; - - TRACE("active_page %d\n", psInfo->active_page); - if (psInfo->active_page < 0) - return; - - hwndPage = psInfo->proppage[psInfo->active_page].hwndPage; - psn.hdr.code = PSN_QUERYCANCEL; - psn.hdr.hwndFrom = hwndDlg; - psn.hdr.idFrom = 0; - psn.lParam = 0; - - if (SendMessageA(hwndPage, WM_NOTIFY, 0, (LPARAM) &psn)) - return; - - psn.hdr.code = PSN_RESET; - psn.lParam = lParam; - - for (i = 0; i < psInfo->nPages; i++) - { - hwndPage = psInfo->proppage[i].hwndPage; - - if (hwndPage) - SendMessageA(hwndPage, WM_NOTIFY, 0, (LPARAM) &psn); - } - - if (psInfo->isModeless) - { - /* makes PSM_GETCURRENTPAGEHWND return NULL */ - psInfo->activeValid = FALSE; - } - else - EndDialog(hwndDlg, FALSE); -} - -/****************************************************************************** - * PROPSHEET_Help - */ -static void PROPSHEET_Help(HWND hwndDlg) -{ - PropSheetInfo* psInfo = (PropSheetInfo*) GetPropW(hwndDlg, - PropSheetInfoStr); - HWND hwndPage; - PSHNOTIFY psn; - - TRACE("active_page %d\n", psInfo->active_page); - if (psInfo->active_page < 0) - return; - - hwndPage = psInfo->proppage[psInfo->active_page].hwndPage; - psn.hdr.code = PSN_HELP; - psn.hdr.hwndFrom = hwndDlg; - psn.hdr.idFrom = 0; - psn.lParam = 0; - - SendMessageA(hwndPage, WM_NOTIFY, 0, (LPARAM) &psn); -} - -/****************************************************************************** - * PROPSHEET_Changed - */ -static void PROPSHEET_Changed(HWND hwndDlg, HWND hwndDirtyPage) -{ - int i; - PropSheetInfo* psInfo = (PropSheetInfo*) GetPropW(hwndDlg, - PropSheetInfoStr); - - TRACE("\n"); - if (!psInfo) return; - /* - * Set the dirty flag of this page. - */ - for (i = 0; i < psInfo->nPages; i++) - { - if (psInfo->proppage[i].hwndPage == hwndDirtyPage) - psInfo->proppage[i].isDirty = TRUE; - } - - /* - * Enable the Apply button. - */ - if (psInfo->hasApply) - { - HWND hwndApplyBtn = GetDlgItem(hwndDlg, IDC_APPLY_BUTTON); - - EnableWindow(hwndApplyBtn, TRUE); - } -} - -/****************************************************************************** - * PROPSHEET_UnChanged - */ -static void PROPSHEET_UnChanged(HWND hwndDlg, HWND hwndCleanPage) -{ - int i; - BOOL noPageDirty = TRUE; - HWND hwndApplyBtn = GetDlgItem(hwndDlg, IDC_APPLY_BUTTON); - PropSheetInfo* psInfo = (PropSheetInfo*) GetPropW(hwndDlg, - PropSheetInfoStr); - - TRACE("\n"); - if ( !psInfo ) return; - for (i = 0; i < psInfo->nPages; i++) - { - /* set the specified page as clean */ - if (psInfo->proppage[i].hwndPage == hwndCleanPage) - psInfo->proppage[i].isDirty = FALSE; - - /* look to see if there's any dirty pages */ - if (psInfo->proppage[i].isDirty) - noPageDirty = FALSE; - } - - /* - * Disable Apply button. - */ - if (noPageDirty) - EnableWindow(hwndApplyBtn, FALSE); -} - -/****************************************************************************** - * PROPSHEET_PressButton - */ -static void PROPSHEET_PressButton(HWND hwndDlg, int buttonID) -{ - TRACE("buttonID %d\n", buttonID); - switch (buttonID) - { - case PSBTN_APPLYNOW: - PROPSHEET_DoCommand(hwndDlg, IDC_APPLY_BUTTON); - break; - case PSBTN_BACK: - PROPSHEET_Back(hwndDlg); - break; - case PSBTN_CANCEL: - PROPSHEET_DoCommand(hwndDlg, IDCANCEL); - break; - case PSBTN_FINISH: - PROPSHEET_Finish(hwndDlg); - break; - case PSBTN_HELP: - PROPSHEET_DoCommand(hwndDlg, IDHELP); - break; - case PSBTN_NEXT: - PROPSHEET_Next(hwndDlg); - break; - case PSBTN_OK: - PROPSHEET_DoCommand(hwndDlg, IDOK); - break; - default: - FIXME("Invalid button index %d\n", buttonID); - } -} - - -/************************************************************************* - * BOOL PROPSHEET_CanSetCurSel [Internal] - * - * Test whether the current page can be changed by sending a PSN_KILLACTIVE - * - * PARAMS - * hwndDlg [I] handle to a Dialog hWnd - * - * RETURNS - * TRUE if Current Selection can change - * - * NOTES - */ -static BOOL PROPSHEET_CanSetCurSel(HWND hwndDlg) -{ - PropSheetInfo* psInfo = (PropSheetInfo*) GetPropW(hwndDlg, - PropSheetInfoStr); - HWND hwndPage; - PSHNOTIFY psn; - BOOL res = FALSE; - - TRACE("active_page %d\n", psInfo->active_page); - if (!psInfo) - { - res = FALSE; - goto end; - } - - if (psInfo->active_page < 0) - { - res = TRUE; - goto end; - } - - /* - * Notify the current page. - */ - hwndPage = psInfo->proppage[psInfo->active_page].hwndPage; - psn.hdr.code = PSN_KILLACTIVE; - psn.hdr.hwndFrom = hwndDlg; - psn.hdr.idFrom = 0; - psn.lParam = 0; - - res = !SendMessageA(hwndPage, WM_NOTIFY, 0, (LPARAM) &psn); - -end: - TRACE("<-- %d\n", res); - return res; -} - -/****************************************************************************** - * PROPSHEET_SetCurSel - */ -static BOOL PROPSHEET_SetCurSel(HWND hwndDlg, - int index, - int skipdir, - HPROPSHEETPAGE hpage - ) -{ - PropSheetInfo* psInfo = (PropSheetInfo*) GetPropW(hwndDlg, PropSheetInfoStr); - HWND hwndHelp = GetDlgItem(hwndDlg, IDHELP); - HWND hwndTabControl = GetDlgItem(hwndDlg, IDC_TABCONTROL); - - TRACE("index %d, skipdir %d, hpage %p\n", index, skipdir, hpage); - /* hpage takes precedence over index */ - if (hpage != NULL) - index = PROPSHEET_GetPageIndex(hpage, psInfo); - - if (index < 0 || index >= psInfo->nPages) - { - TRACE("Could not find page to select!\n"); - return FALSE; - } - - while (1) { - int result; - PSHNOTIFY psn; - RECT rc; - LPCPROPSHEETPAGEW ppshpage = (LPCPROPSHEETPAGEW)psInfo->proppage[index].hpage; - - if (hwndTabControl) - SendMessageW(hwndTabControl, TCM_SETCURSEL, index, 0); - - psn.hdr.code = PSN_SETACTIVE; - psn.hdr.hwndFrom = hwndDlg; - psn.hdr.idFrom = 0; - psn.lParam = 0; - - if (!psInfo->proppage[index].hwndPage) { - PROPSHEET_CreatePage(hwndDlg, index, psInfo, ppshpage); - } - - /* Resize the property sheet page to the fit in the Tab control - * (for regular property sheets) or to fit in the client area (for - * wizards). - * NOTE: The resizing happens every time the page is selected and - * not only when it's created (some applications depend on it). */ - PROPSHEET_GetPageRect(psInfo, hwndDlg, &rc, ppshpage); - TRACE("setting page %p, rc (%ld,%ld)-(%ld,%ld) w=%ld, h=%ld\n", - psInfo->proppage[index].hwndPage, rc.left, rc.top, rc.right, rc.bottom, - rc.right - rc.left, rc.bottom - rc.top); - SetWindowPos(psInfo->proppage[index].hwndPage, HWND_TOP, - rc.left, rc.top, - rc.right - rc.left, rc.bottom - rc.top, 0); - - result = SendMessageW(psInfo->proppage[index].hwndPage, WM_NOTIFY, 0, (LPARAM) &psn); - if (!result) - break; - if (result == -1) { - index+=skipdir; - if (index < 0) { - index = 0; - WARN("Tried to skip before first property sheet page!\n"); - break; - } - if (index >= psInfo->nPages) { - WARN("Tried to skip after last property sheet page!\n"); - index = psInfo->nPages-1; - break; - } - } - else if (result != 0) - { - int old_index = index; - index = PROPSHEET_FindPageByResId(psInfo, result); - if(index >= psInfo->nPages) { - index = old_index; - WARN("Tried to skip to nonexistant page by res id\n"); - break; - } - continue; - } - } - /* - * Display the new page. - */ - PROPSHEET_ShowPage(hwndDlg, index, psInfo); - - if (psInfo->proppage[index].hasHelp) - EnableWindow(hwndHelp, TRUE); - else - EnableWindow(hwndHelp, FALSE); - - return TRUE; -} - -/****************************************************************************** - * PROPSHEET_SetCurSelId - * - * Selects the page, specified by resource id. - */ -static void PROPSHEET_SetCurSelId(HWND hwndDlg, int id) -{ - int idx; - PropSheetInfo* psInfo = - (PropSheetInfo*) GetPropW(hwndDlg, PropSheetInfoStr); - - idx = PROPSHEET_FindPageByResId(psInfo, id); - if (idx < psInfo->nPages ) - { - if (PROPSHEET_CanSetCurSel(hwndDlg) != FALSE) - PROPSHEET_SetCurSel(hwndDlg, idx, 1, 0); - } -} - -/****************************************************************************** - * PROPSHEET_SetTitleA - */ -static void PROPSHEET_SetTitleA(HWND hwndDlg, DWORD dwStyle, LPCSTR lpszText) -{ - if(HIWORD(lpszText)) - { - WCHAR szTitle[256]; - MultiByteToWideChar(CP_ACP, 0, lpszText, -1, - szTitle, sizeof(szTitle)); - PROPSHEET_SetTitleW(hwndDlg, dwStyle, szTitle); - } - else - { - PROPSHEET_SetTitleW(hwndDlg, dwStyle, (LPCWSTR)lpszText); - } -} - -/****************************************************************************** - * PROPSHEET_SetTitleW - */ -static void PROPSHEET_SetTitleW(HWND hwndDlg, DWORD dwStyle, LPCWSTR lpszText) -{ - PropSheetInfo* psInfo = (PropSheetInfo*) GetPropW(hwndDlg, PropSheetInfoStr); - WCHAR szTitle[256]; - - TRACE("'%s' (style %08lx)\n", debugstr_w(lpszText), dwStyle); - if (HIWORD(lpszText) == 0) { - if (!LoadStringW(psInfo->ppshheader.hInstance, - LOWORD(lpszText), szTitle, sizeof(szTitle)-sizeof(WCHAR))) - return; - lpszText = szTitle; - } - if (dwStyle & PSH_PROPTITLE) - { - WCHAR* dest; - int lentitle = strlenW(lpszText); - int lenprop = strlenW(psInfo->strPropertiesFor); - - dest = Alloc( (lentitle + lenprop + 1)*sizeof (WCHAR)); - strcpyW(dest, psInfo->strPropertiesFor); - strcatW(dest, lpszText); - - SetWindowTextW(hwndDlg, dest); - Free(dest); - } - else - SetWindowTextW(hwndDlg, lpszText); -} - -/****************************************************************************** - * PROPSHEET_SetFinishTextA - */ -static void PROPSHEET_SetFinishTextA(HWND hwndDlg, LPCSTR lpszText) -{ - HWND hwndButton = GetDlgItem(hwndDlg, IDC_FINISH_BUTTON); - - TRACE("'%s'\n", lpszText); - /* Set text, show and enable the Finish button */ - SetWindowTextA(hwndButton, lpszText); - ShowWindow(hwndButton, SW_SHOW); - EnableWindow(hwndButton, TRUE); - - /* Make it default pushbutton */ - SendMessageA(hwndDlg, DM_SETDEFID, IDC_FINISH_BUTTON, 0); - - /* Hide Back button */ - hwndButton = GetDlgItem(hwndDlg, IDC_BACK_BUTTON); - ShowWindow(hwndButton, SW_HIDE); - - /* Hide Next button */ - hwndButton = GetDlgItem(hwndDlg, IDC_NEXT_BUTTON); - ShowWindow(hwndButton, SW_HIDE); -} - -/****************************************************************************** - * PROPSHEET_SetFinishTextW - */ -static void PROPSHEET_SetFinishTextW(HWND hwndDlg, LPCWSTR lpszText) -{ - HWND hwndButton = GetDlgItem(hwndDlg, IDC_FINISH_BUTTON); - - TRACE("'%s'\n", debugstr_w(lpszText)); - /* Set text, show and enable the Finish button */ - SetWindowTextW(hwndButton, lpszText); - ShowWindow(hwndButton, SW_SHOW); - EnableWindow(hwndButton, TRUE); - - /* Make it default pushbutton */ - SendMessageW(hwndDlg, DM_SETDEFID, IDC_FINISH_BUTTON, 0); - - /* Hide Back button */ - hwndButton = GetDlgItem(hwndDlg, IDC_BACK_BUTTON); - ShowWindow(hwndButton, SW_HIDE); - - /* Hide Next button */ - hwndButton = GetDlgItem(hwndDlg, IDC_NEXT_BUTTON); - ShowWindow(hwndButton, SW_HIDE); -} - -/****************************************************************************** - * PROPSHEET_QuerySiblings - */ -static LRESULT PROPSHEET_QuerySiblings(HWND hwndDlg, - WPARAM wParam, LPARAM lParam) -{ - int i = 0; - HWND hwndPage; - LRESULT msgResult = 0; - PropSheetInfo* psInfo = (PropSheetInfo*) GetPropW(hwndDlg, - PropSheetInfoStr); - - while ((i < psInfo->nPages) && (msgResult == 0)) - { - hwndPage = psInfo->proppage[i].hwndPage; - msgResult = SendMessageA(hwndPage, PSM_QUERYSIBLINGS, wParam, lParam); - i++; - } - - return msgResult; -} - - -/****************************************************************************** - * PROPSHEET_AddPage - */ -static BOOL PROPSHEET_AddPage(HWND hwndDlg, - HPROPSHEETPAGE hpage) -{ - PropSheetInfo * psInfo = (PropSheetInfo*) GetPropW(hwndDlg, - PropSheetInfoStr); - HWND hwndTabControl = GetDlgItem(hwndDlg, IDC_TABCONTROL); - TCITEMW item; - LPCPROPSHEETPAGEW ppsp = (LPCPROPSHEETPAGEW)hpage; - - TRACE("hpage %p\n", hpage); - /* - * Allocate and fill in a new PropPageInfo entry. - */ - psInfo->proppage = (PropPageInfo*) ReAlloc(psInfo->proppage, - sizeof(PropPageInfo) * - (psInfo->nPages + 1)); - if (!PROPSHEET_CollectPageInfo(ppsp, psInfo, psInfo->nPages)) - return FALSE; - - psInfo->proppage[psInfo->nPages].hpage = hpage; - - if (ppsp->dwFlags & PSP_PREMATURE) - { - /* Create the page but don't show it */ - PROPSHEET_CreatePage(hwndDlg, psInfo->nPages, psInfo, ppsp); - } - - /* - * Add a new tab to the tab control. - */ - item.mask = TCIF_TEXT; - item.pszText = (LPWSTR) psInfo->proppage[psInfo->nPages].pszText; - item.cchTextMax = MAX_TABTEXT_LENGTH; - - if (psInfo->hImageList) - { - SendMessageW(hwndTabControl, TCM_SETIMAGELIST, 0, (LPARAM)psInfo->hImageList); - } - - if ( psInfo->proppage[psInfo->nPages].hasIcon ) - { - item.mask |= TCIF_IMAGE; - item.iImage = psInfo->nPages; - } - - SendMessageW(hwndTabControl, TCM_INSERTITEMW, psInfo->nPages + 1, - (LPARAM)&item); - - psInfo->nPages++; - - /* If it is the only page - show it */ - if(psInfo->nPages == 1) - PROPSHEET_SetCurSel(hwndDlg, 0, 1, 0); - return TRUE; -} - -/****************************************************************************** - * PROPSHEET_RemovePage - */ -static BOOL PROPSHEET_RemovePage(HWND hwndDlg, - int index, - HPROPSHEETPAGE hpage) -{ - PropSheetInfo * psInfo = (PropSheetInfo*) GetPropW(hwndDlg, - PropSheetInfoStr); - HWND hwndTabControl = GetDlgItem(hwndDlg, IDC_TABCONTROL); - PropPageInfo* oldPages; - - TRACE("index %d, hpage %p\n", index, hpage); - if (!psInfo) { - return FALSE; - } - /* - * hpage takes precedence over index. - */ - if (hpage != 0) - { - index = PROPSHEET_GetPageIndex(hpage, psInfo); - } - - /* Make sure that index is within range */ - if (index < 0 || index >= psInfo->nPages) - { - TRACE("Could not find page to remove!\n"); - return FALSE; - } - - TRACE("total pages %d removing page %d active page %d\n", - psInfo->nPages, index, psInfo->active_page); - /* - * Check if we're removing the active page. - */ - if (index == psInfo->active_page) - { - if (psInfo->nPages > 1) - { - if (index > 0) - { - /* activate previous page */ - PROPSHEET_SetCurSel(hwndDlg, index - 1, -1, 0); - } - else - { - /* activate the next page */ - PROPSHEET_SetCurSel(hwndDlg, index + 1, 1, 0); - psInfo->active_page = index; - } - } - else - { - psInfo->active_page = -1; - if (!psInfo->isModeless) - { - EndDialog(hwndDlg, FALSE); - return TRUE; - } - } - } - else if (index < psInfo->active_page) - psInfo->active_page--; - - /* Unsubclass the page dialog window */ - if((psInfo->ppshheader.dwFlags & (PSH_WIZARD97_NEW | PSH_WIZARD97_OLD) && - (psInfo->ppshheader.dwFlags & PSH_WATERMARK) && - ((PROPSHEETPAGEW*)psInfo->proppage[index].hpage)->dwFlags & PSP_HIDEHEADER)) - { - RemoveWindowSubclass(psInfo->proppage[index].hwndPage, - PROPSHEET_WizardSubclassProc, 1); - } - - /* Destroy page dialog window */ - DestroyWindow(psInfo->proppage[index].hwndPage); - - /* Free page resources */ - if(psInfo->proppage[index].hpage) - { - PROPSHEETPAGEW* psp = (PROPSHEETPAGEW*)psInfo->proppage[index].hpage; - - if ((psp->dwFlags & PSP_USETITLE) && psInfo->proppage[index].pszText) - HeapFree(GetProcessHeap(), 0, (LPVOID)psInfo->proppage[index].pszText); - - DestroyPropertySheetPage(psInfo->proppage[index].hpage); - } - - /* Remove the tab */ - SendMessageW(hwndTabControl, TCM_DELETEITEM, index, 0); - - oldPages = psInfo->proppage; - psInfo->nPages--; - psInfo->proppage = Alloc(sizeof(PropPageInfo) * psInfo->nPages); - - if (index > 0) - memcpy(&psInfo->proppage[0], &oldPages[0], index * sizeof(PropPageInfo)); - - if (index < psInfo->nPages) - memcpy(&psInfo->proppage[index], &oldPages[index + 1], - (psInfo->nPages - index) * sizeof(PropPageInfo)); - - Free(oldPages); - - return FALSE; -} - -/****************************************************************************** - * PROPSHEET_SetWizButtons - * - * This code will work if (and assumes that) the Next button is on top of the - * Finish button. ie. Finish comes after Next in the Z order. - * This means make sure the dialog template reflects this. - * - */ -static void PROPSHEET_SetWizButtons(HWND hwndDlg, DWORD dwFlags) -{ - HWND hwndBack = GetDlgItem(hwndDlg, IDC_BACK_BUTTON); - HWND hwndNext = GetDlgItem(hwndDlg, IDC_NEXT_BUTTON); - HWND hwndFinish = GetDlgItem(hwndDlg, IDC_FINISH_BUTTON); - - TRACE("%ld\n", dwFlags); - - EnableWindow(hwndBack, FALSE); - EnableWindow(hwndNext, FALSE); - EnableWindow(hwndFinish, FALSE); - - if (dwFlags & PSWIZB_BACK) - EnableWindow(hwndBack, TRUE); - - if (dwFlags & PSWIZB_NEXT) - { - /* Hide the Finish button */ - ShowWindow(hwndFinish, SW_HIDE); - - /* Show and enable the Next button */ - ShowWindow(hwndNext, SW_SHOW); - EnableWindow(hwndNext, TRUE); - - /* Set the Next button as the default pushbutton */ - SendMessageA(hwndDlg, DM_SETDEFID, IDC_NEXT_BUTTON, 0); - } - - if ((dwFlags & PSWIZB_FINISH) || (dwFlags & PSWIZB_DISABLEDFINISH)) - { - /* Hide the Next button */ - ShowWindow(hwndNext, SW_HIDE); - - /* Show the Finish button */ - ShowWindow(hwndFinish, SW_SHOW); - - if (dwFlags & PSWIZB_FINISH) - EnableWindow(hwndFinish, TRUE); - - /* Set the Finish button as the default pushbutton */ - SendMessageA(hwndDlg, DM_SETDEFID, IDC_FINISH_BUTTON, 0); - } -} - -/****************************************************************************** - * PROPSHEET_InsertPage - */ -static BOOL PROPSHEET_InsertPage(HWND hwndDlg, HPROPSHEETPAGE hpageInsertAfter, HPROPSHEETPAGE hpage) -{ - if (!HIWORD(hpageInsertAfter)) - FIXME("(%p, %d, %p): stub\n", hwndDlg, LOWORD(hpageInsertAfter), hpage); - else - FIXME("(%p, %p, %p): stub\n", hwndDlg, hpageInsertAfter, hpage); - return FALSE; -} - -/****************************************************************************** - * PROPSHEET_SetHeaderTitleW - */ -static void PROPSHEET_SetHeaderTitleW(HWND hwndDlg, int iPageIndex, LPCWSTR pszHeaderTitle) -{ - FIXME("(%p, %d, %s): stub\n", hwndDlg, iPageIndex, debugstr_w(pszHeaderTitle)); -} - -/****************************************************************************** - * PROPSHEET_SetHeaderTitleA - */ -static void PROPSHEET_SetHeaderTitleA(HWND hwndDlg, int iPageIndex, LPCSTR pszHeaderTitle) -{ - FIXME("(%p, %d, %s): stub\n", hwndDlg, iPageIndex, debugstr_a(pszHeaderTitle)); -} - -/****************************************************************************** - * PROPSHEET_SetHeaderSubTitleW - */ -static void PROPSHEET_SetHeaderSubTitleW(HWND hwndDlg, int iPageIndex, LPCWSTR pszHeaderSubTitle) -{ - FIXME("(%p, %d, %s): stub\n", hwndDlg, iPageIndex, debugstr_w(pszHeaderSubTitle)); -} - -/****************************************************************************** - * PROPSHEET_SetHeaderSubTitleA - */ -static void PROPSHEET_SetHeaderSubTitleA(HWND hwndDlg, int iPageIndex, LPCSTR pszHeaderSubTitle) -{ - FIXME("(%p, %d, %s): stub\n", hwndDlg, iPageIndex, debugstr_a(pszHeaderSubTitle)); -} - -/****************************************************************************** - * PROPSHEET_HwndToIndex - */ -static LRESULT PROPSHEET_HwndToIndex(HWND hwndDlg, HWND hPageDlg) -{ - int index; - PropSheetInfo * psInfo = (PropSheetInfo*) GetPropW(hwndDlg, - PropSheetInfoStr); - - TRACE("(%p, %p)\n", hwndDlg, hPageDlg); - - for (index = 0; index < psInfo->nPages; index++) - if (psInfo->proppage[index].hwndPage == hPageDlg) - return index; - WARN("%p not found\n", hPageDlg); - return -1; -} - -/****************************************************************************** - * PROPSHEET_IndexToHwnd - */ -static LRESULT PROPSHEET_IndexToHwnd(HWND hwndDlg, int iPageIndex) -{ - PropSheetInfo * psInfo = (PropSheetInfo*) GetPropW(hwndDlg, - PropSheetInfoStr); - TRACE("(%p, %d)\n", hwndDlg, iPageIndex); - if (iPageIndex<0 || iPageIndex>=psInfo->nPages) { - WARN("%d out of range.\n", iPageIndex); - return 0; - } - return (LRESULT)psInfo->proppage[iPageIndex].hwndPage; -} - -/****************************************************************************** - * PROPSHEET_PageToIndex - */ -static LRESULT PROPSHEET_PageToIndex(HWND hwndDlg, HPROPSHEETPAGE hPage) -{ - int index; - PropSheetInfo * psInfo = (PropSheetInfo*) GetPropW(hwndDlg, - PropSheetInfoStr); - - TRACE("(%p, %p)\n", hwndDlg, hPage); - - for (index = 0; index < psInfo->nPages; index++) - if (psInfo->proppage[index].hpage == hPage) - return index; - WARN("%p not found\n", hPage); - return -1; -} - -/****************************************************************************** - * PROPSHEET_IndexToPage - */ -static LRESULT PROPSHEET_IndexToPage(HWND hwndDlg, int iPageIndex) -{ - PropSheetInfo * psInfo = (PropSheetInfo*) GetPropW(hwndDlg, - PropSheetInfoStr); - TRACE("(%p, %d)\n", hwndDlg, iPageIndex); - if (iPageIndex<0 || iPageIndex>=psInfo->nPages) { - WARN("%d out of range.\n", iPageIndex); - return 0; - } - return (LRESULT)psInfo->proppage[iPageIndex].hpage; -} - -/****************************************************************************** - * PROPSHEET_IdToIndex - */ -static LRESULT PROPSHEET_IdToIndex(HWND hwndDlg, int iPageId) -{ - FIXME("(%p, %d): stub\n", hwndDlg, iPageId); - return -1; -} - -/****************************************************************************** - * PROPSHEET_IndexToId - */ -static LRESULT PROPSHEET_IndexToId(HWND hwndDlg, int iPageIndex) -{ - PropSheetInfo * psInfo = (PropSheetInfo*) GetPropW(hwndDlg, - PropSheetInfoStr); - LPCPROPSHEETPAGEW psp; - TRACE("(%p, %d)\n", hwndDlg, iPageIndex); - if (iPageIndex<0 || iPageIndex>=psInfo->nPages) { - WARN("%d out of range.\n", iPageIndex); - return 0; - } - psp = (LPCPROPSHEETPAGEW)psInfo->proppage[iPageIndex].hpage; - if (psp->dwFlags & PSP_DLGINDIRECT || HIWORD(psp->u.pszTemplate)) { - return 0; - } - return (LRESULT)psp->u.pszTemplate; -} - -/****************************************************************************** - * PROPSHEET_GetResult - */ -static LRESULT PROPSHEET_GetResult(HWND hwndDlg) -{ - FIXME("(%p): stub\n", hwndDlg); - return -1; -} - -/****************************************************************************** - * PROPSHEET_RecalcPageSizes - */ -static BOOL PROPSHEET_RecalcPageSizes(HWND hwndDlg) -{ - FIXME("(%p): stub\n", hwndDlg); - return FALSE; -} - -/****************************************************************************** - * PROPSHEET_GetPageIndex - * - * Given a HPROPSHEETPAGE, returns the index of the corresponding page from - * the array of PropPageInfo. - */ -static int PROPSHEET_GetPageIndex(HPROPSHEETPAGE hpage, PropSheetInfo* psInfo) -{ - BOOL found = FALSE; - int index = 0; - - TRACE("hpage %p\n", hpage); - while ((index < psInfo->nPages) && (found == FALSE)) - { - if (psInfo->proppage[index].hpage == hpage) - found = TRUE; - else - index++; - } - - if (found == FALSE) - index = -1; - - return index; -} - -/****************************************************************************** - * PROPSHEET_CleanUp - */ -static void PROPSHEET_CleanUp(HWND hwndDlg) -{ - int i; - PropSheetInfo* psInfo = (PropSheetInfo*) RemovePropW(hwndDlg, - PropSheetInfoStr); - - TRACE("\n"); - if (!psInfo) return; - if (HIWORD(psInfo->ppshheader.pszCaption)) - HeapFree(GetProcessHeap(), 0, (LPVOID)psInfo->ppshheader.pszCaption); - - for (i = 0; i < psInfo->nPages; i++) - { - PROPSHEETPAGEA* psp = (PROPSHEETPAGEA*)psInfo->proppage[i].hpage; - - /* Unsubclass the page dialog window */ - if((psInfo->ppshheader.dwFlags & (PSH_WIZARD97_NEW | PSH_WIZARD97_OLD)) && - (psInfo->ppshheader.dwFlags & PSH_WATERMARK) && - (psp->dwFlags & PSP_HIDEHEADER)) - { - RemoveWindowSubclass(psInfo->proppage[i].hwndPage, - PROPSHEET_WizardSubclassProc, 1); - } - - if(psInfo->proppage[i].hwndPage) - DestroyWindow(psInfo->proppage[i].hwndPage); - - if(psp) - { - if ((psp->dwFlags & PSP_USETITLE) && psInfo->proppage[i].pszText) - HeapFree(GetProcessHeap(), 0, (LPVOID)psInfo->proppage[i].pszText); - - DestroyPropertySheetPage(psInfo->proppage[i].hpage); - } - } - - DeleteObject(psInfo->hFont); - DeleteObject(psInfo->hFontBold); - /* If we created the bitmaps, destroy them */ - if ((psInfo->ppshheader.dwFlags & PSH_WATERMARK) && - (!(psInfo->ppshheader.dwFlags & PSH_USEHBMWATERMARK)) ) - DeleteObject(psInfo->ppshheader.u4.hbmWatermark); - if ((psInfo->ppshheader.dwFlags & PSH_HEADER) && - (!(psInfo->ppshheader.dwFlags & PSH_USEHBMHEADER)) ) - DeleteObject(psInfo->ppshheader.u5.hbmHeader); - - Free(psInfo->proppage); - Free(psInfo->strPropertiesFor); - ImageList_Destroy(psInfo->hImageList); - - GlobalFree((HGLOBAL)psInfo); -} - -/****************************************************************************** - * PropertySheet (COMCTL32.@) - * PropertySheetA (COMCTL32.@) - * - * Creates a property sheet in the specified property sheet header. - * - * RETURNS - * Modal property sheets: Positive if successful or -1 otherwise. - * Modeless property sheets: Property sheet handle. - * Or: - *| ID_PSREBOOTSYSTEM - The user must reboot the computer for the changes to take effect. - *| ID_PSRESTARTWINDOWS - The user must restart Windows for the changes to take effect. - */ -INT WINAPI PropertySheetA(LPCPROPSHEETHEADERA lppsh) -{ - int bRet = 0; - PropSheetInfo* psInfo = (PropSheetInfo*) GlobalAlloc(GPTR, - sizeof(PropSheetInfo)); - UINT i, n; - BYTE* pByte; - - TRACE("(%p)\n", lppsh); - - PROPSHEET_CollectSheetInfoA(lppsh, psInfo); - - psInfo->proppage = (PropPageInfo*) Alloc(sizeof(PropPageInfo) * - lppsh->nPages); - pByte = (BYTE*) psInfo->ppshheader.u3.ppsp; - - for (n = i = 0; i < lppsh->nPages; i++, n++) - { - if (!(lppsh->dwFlags & PSH_PROPSHEETPAGE)) - psInfo->proppage[n].hpage = psInfo->ppshheader.u3.phpage[i]; - else - { - psInfo->proppage[n].hpage = CreatePropertySheetPageA((LPCPROPSHEETPAGEA)pByte); - pByte += ((LPPROPSHEETPAGEA)pByte)->dwSize; - } - - if (!PROPSHEET_CollectPageInfo((LPCPROPSHEETPAGEW)psInfo->proppage[n].hpage, - psInfo, n)) - { - if (lppsh->dwFlags & PSH_PROPSHEETPAGE) - DestroyPropertySheetPage(psInfo->proppage[n].hpage); - n--; - psInfo->nPages--; - } - } - - psInfo->unicode = FALSE; - bRet = PROPSHEET_CreateDialog(psInfo); - - return bRet; -} - -/****************************************************************************** - * PropertySheetW (COMCTL32.@) - * - * See PropertySheetA. - */ -INT WINAPI PropertySheetW(LPCPROPSHEETHEADERW lppsh) -{ - int bRet = 0; - PropSheetInfo* psInfo = (PropSheetInfo*) GlobalAlloc(GPTR, - sizeof(PropSheetInfo)); - UINT i, n; - BYTE* pByte; - - TRACE("(%p)\n", lppsh); - - PROPSHEET_CollectSheetInfoW(lppsh, psInfo); - - psInfo->proppage = (PropPageInfo*) Alloc(sizeof(PropPageInfo) * - lppsh->nPages); - pByte = (BYTE*) psInfo->ppshheader.u3.ppsp; - - for (n = i = 0; i < lppsh->nPages; i++, n++) - { - if (!(lppsh->dwFlags & PSH_PROPSHEETPAGE)) - psInfo->proppage[n].hpage = psInfo->ppshheader.u3.phpage[i]; - else - { - psInfo->proppage[n].hpage = CreatePropertySheetPageW((LPCPROPSHEETPAGEW)pByte); - pByte += ((LPPROPSHEETPAGEW)pByte)->dwSize; - } - - if (!PROPSHEET_CollectPageInfo((LPCPROPSHEETPAGEW)psInfo->proppage[n].hpage, - psInfo, n)) - { - if (lppsh->dwFlags & PSH_PROPSHEETPAGE) - DestroyPropertySheetPage(psInfo->proppage[n].hpage); - n--; - psInfo->nPages--; - } - } - - psInfo->unicode = TRUE; - bRet = PROPSHEET_CreateDialog(psInfo); - - return bRet; -} - -/****************************************************************************** - * CreatePropertySheetPage (COMCTL32.@) - * CreatePropertySheetPageA (COMCTL32.@) - * - * Creates a new property sheet page. - * - * RETURNS - * Success: Handle to new property sheet page. - * Failure: NULL. - * - * NOTES - * An application must use the PSM_ADDPAGE message to add the new page to - * an existing property sheet. - */ -HPROPSHEETPAGE WINAPI CreatePropertySheetPageA( - LPCPROPSHEETPAGEA lpPropSheetPage) -{ - PROPSHEETPAGEW* ppsp = Alloc(sizeof(PROPSHEETPAGEW)); - - memcpy(ppsp,lpPropSheetPage,min(lpPropSheetPage->dwSize,sizeof(PROPSHEETPAGEA))); - - ppsp->dwFlags &= ~ PSP_INTERNAL_UNICODE; - if ( !(ppsp->dwFlags & PSP_DLGINDIRECT) && HIWORD( ppsp->u.pszTemplate ) ) - { - int len = strlen(lpPropSheetPage->u.pszTemplate); - - ppsp->u.pszTemplate = HeapAlloc( GetProcessHeap(),0,len+1 ); - strcpy( (LPSTR)ppsp->u.pszTemplate, lpPropSheetPage->u.pszTemplate ); - } - if ( (ppsp->dwFlags & PSP_USEICONID) && HIWORD( ppsp->u2.pszIcon ) ) - { - PROPSHEET_AtoW(&ppsp->u2.pszIcon, lpPropSheetPage->u2.pszIcon); - } - - if ((ppsp->dwFlags & PSP_USETITLE) && HIWORD( ppsp->pszTitle )) - { - PROPSHEET_AtoW(&ppsp->pszTitle, lpPropSheetPage->pszTitle); - } - else if ( !(ppsp->dwFlags & PSP_USETITLE) ) - ppsp->pszTitle = NULL; - - return (HPROPSHEETPAGE)ppsp; -} - -/****************************************************************************** - * CreatePropertySheetPageW (COMCTL32.@) - * - * See CreatePropertySheetA. - */ -HPROPSHEETPAGE WINAPI CreatePropertySheetPageW(LPCPROPSHEETPAGEW lpPropSheetPage) -{ - PROPSHEETPAGEW* ppsp = Alloc(sizeof(PROPSHEETPAGEW)); - - memcpy(ppsp,lpPropSheetPage,min(lpPropSheetPage->dwSize,sizeof(PROPSHEETPAGEW))); - - ppsp->dwFlags |= PSP_INTERNAL_UNICODE; - - if ( !(ppsp->dwFlags & PSP_DLGINDIRECT) && HIWORD( ppsp->u.pszTemplate ) ) - { - int len = strlenW(lpPropSheetPage->u.pszTemplate); - - ppsp->u.pszTemplate = HeapAlloc( GetProcessHeap(),0,(len+1)*sizeof (WCHAR) ); - strcpyW( (WCHAR *)ppsp->u.pszTemplate, lpPropSheetPage->u.pszTemplate ); - } - if ( (ppsp->dwFlags & PSP_USEICONID) && HIWORD( ppsp->u2.pszIcon ) ) - { - int len = strlenW(lpPropSheetPage->u2.pszIcon); - ppsp->u2.pszIcon = HeapAlloc( GetProcessHeap(), 0, (len+1)*sizeof (WCHAR) ); - strcpyW( (WCHAR *)ppsp->u2.pszIcon, lpPropSheetPage->u2.pszIcon ); - } - - if ((ppsp->dwFlags & PSP_USETITLE) && HIWORD( ppsp->pszTitle )) - { - int len = strlenW(lpPropSheetPage->pszTitle); - ppsp->pszTitle = HeapAlloc( GetProcessHeap(), 0, (len+1)*sizeof (WCHAR) ); - strcpyW( (WCHAR *)ppsp->pszTitle, lpPropSheetPage->pszTitle ); - } - else if ( !(ppsp->dwFlags & PSP_USETITLE) ) - ppsp->pszTitle = NULL; - - return (HPROPSHEETPAGE)ppsp; -} - -/****************************************************************************** - * DestroyPropertySheetPage (COMCTL32.@) - * - * Destroys a property sheet page previously created with - * CreatePropertySheetA() or CreatePropertySheetW() and frees the associated - * memory. - * - * RETURNS - * Success: TRUE - * Failure: FALSE - */ -BOOL WINAPI DestroyPropertySheetPage(HPROPSHEETPAGE hPropPage) -{ - PROPSHEETPAGEW *psp = (PROPSHEETPAGEW *)hPropPage; - - if (!psp) - return FALSE; - - if ( !(psp->dwFlags & PSP_DLGINDIRECT) && HIWORD( psp->u.pszTemplate ) ) - HeapFree(GetProcessHeap(), 0, (LPVOID)psp->u.pszTemplate); - - if ( (psp->dwFlags & PSP_USEICONID) && HIWORD( psp->u2.pszIcon ) ) - HeapFree(GetProcessHeap(), 0, (LPVOID)psp->u2.pszIcon); - - if ((psp->dwFlags & PSP_USETITLE) && HIWORD( psp->pszTitle )) - HeapFree(GetProcessHeap(), 0, (LPVOID)psp->pszTitle); - - Free(hPropPage); - - return TRUE; -} - -/****************************************************************************** - * PROPSHEET_IsDialogMessage - */ -static BOOL PROPSHEET_IsDialogMessage(HWND hwnd, LPMSG lpMsg) -{ - PropSheetInfo* psInfo = (PropSheetInfo*) GetPropW(hwnd, PropSheetInfoStr); - - TRACE("\n"); - if (!psInfo || (hwnd != lpMsg->hwnd && !IsChild(hwnd, lpMsg->hwnd))) - return FALSE; - - if (lpMsg->message == WM_KEYDOWN && (GetKeyState(VK_CONTROL) & 0x8000)) - { - int new_page = 0; - INT dlgCode = SendMessageA(lpMsg->hwnd, WM_GETDLGCODE, 0, (LPARAM)lpMsg); - - if (!(dlgCode & DLGC_WANTMESSAGE)) - { - switch (lpMsg->wParam) - { - case VK_TAB: - if (GetKeyState(VK_SHIFT) & 0x8000) - new_page = -1; - else - new_page = 1; - break; - - case VK_NEXT: new_page = 1; break; - case VK_PRIOR: new_page = -1; break; - } - } - - if (new_page) - { - if (PROPSHEET_CanSetCurSel(hwnd) != FALSE) - { - new_page += psInfo->active_page; - - if (new_page < 0) - new_page = psInfo->nPages - 1; - else if (new_page >= psInfo->nPages) - new_page = 0; - - PROPSHEET_SetCurSel(hwnd, new_page, 1, 0); - } - - return TRUE; - } - } - - return IsDialogMessageA(hwnd, lpMsg); -} - -/****************************************************************************** - * PROPSHEET_DoCommand - */ -static BOOL PROPSHEET_DoCommand(HWND hwnd, WORD wID) -{ - - switch (wID) { - - case IDOK: - case IDC_APPLY_BUTTON: - { - HWND hwndApplyBtn = GetDlgItem(hwnd, IDC_APPLY_BUTTON); - - if (PROPSHEET_Apply(hwnd, wID == IDOK ? 1: 0) == FALSE) - break; - - if (wID == IDOK) - { - PropSheetInfo* psInfo = (PropSheetInfo*) GetPropW(hwnd, - PropSheetInfoStr); - int result = TRUE; - - if (psInfo->restartWindows) - result = ID_PSRESTARTWINDOWS; - - /* reboot system takes precedence over restart windows */ - if (psInfo->rebootSystem) - result = ID_PSREBOOTSYSTEM; - - if (psInfo->isModeless) - psInfo->activeValid = FALSE; - else - EndDialog(hwnd, result); - } - else - EnableWindow(hwndApplyBtn, FALSE); - - break; - } - - case IDC_BACK_BUTTON: - PROPSHEET_Back(hwnd); - break; - - case IDC_NEXT_BUTTON: - PROPSHEET_Next(hwnd); - break; - - case IDC_FINISH_BUTTON: - PROPSHEET_Finish(hwnd); - break; - - case IDCANCEL: - PROPSHEET_Cancel(hwnd, 0); - break; - - case IDHELP: - PROPSHEET_Help(hwnd); - break; - - default: - return FALSE; - } - - return TRUE; -} - -/****************************************************************************** - * PROPSHEET_Paint - */ -static LRESULT PROPSHEET_Paint(HWND hwnd) -{ - PropSheetInfo* psInfo = (PropSheetInfo*) GetPropW(hwnd, PropSheetInfoStr); - PAINTSTRUCT ps; - HDC hdc, hdcSrc; - BITMAP bm; - HBITMAP hbmp; - HPALETTE hOldPal = 0; - int offsety = 0; - HBRUSH hbr; - RECT r, rzone; - LPCPROPSHEETPAGEW ppshpage; - WCHAR szBuffer[256]; - int nLength; - - hdc = BeginPaint(hwnd, &ps); - if (!hdc) return 1; - - hdcSrc = CreateCompatibleDC(0); - ppshpage = (LPCPROPSHEETPAGEW)psInfo->proppage[psInfo->active_page].hpage; - - if (psInfo->ppshheader.dwFlags & PSH_USEHPLWATERMARK) - hOldPal = SelectPalette(hdc, psInfo->ppshheader.hplWatermark, FALSE); - - if ( (!(ppshpage->dwFlags & PSP_HIDEHEADER)) && - (psInfo->ppshheader.dwFlags & (PSH_WIZARD97_OLD | PSH_WIZARD97_NEW)) && - (psInfo->ppshheader.dwFlags & PSH_HEADER) ) - { - HWND hwndLineHeader = GetDlgItem(hwnd, IDC_SUNKEN_LINEHEADER); - HFONT hOldFont; - COLORREF clrOld = 0; - int oldBkMode = 0; - - hbmp = SelectObject(hdcSrc, psInfo->ppshheader.u5.hbmHeader); - hOldFont = SelectObject(hdc, psInfo->hFontBold); - - GetClientRect(hwndLineHeader, &r); - MapWindowPoints(hwndLineHeader, hwnd, (LPPOINT) &r, 2); - SetRect(&rzone, 0, 0, r.right + 1, r.top - 1); - - GetObjectA(psInfo->ppshheader.u5.hbmHeader, sizeof(BITMAP), (LPVOID)&bm); - - if (psInfo->ppshheader.dwFlags & PSH_WIZARD97_OLD) - { - /* Fill the unoccupied part of the header with color of the - * left-top pixel, but do it only when needed. - */ - if (bm.bmWidth < r.right || bm.bmHeight < r.bottom) - { - hbr = CreateSolidBrush(GetPixel(hdcSrc, 0, 0)); - CopyRect(&r, &rzone); - if (bm.bmWidth < r.right) - { - r.left = bm.bmWidth; - FillRect(hdc, &r, hbr); - } - if (bm.bmHeight < r.bottom) - { - r.left = 0; - r.top = bm.bmHeight; - FillRect(hdc, &r, hbr); - } - DeleteObject(hbr); - } - - /* Draw the header itself. */ - BitBlt(hdc, 0, 0, - bm.bmWidth, min(bm.bmHeight, rzone.bottom), - hdcSrc, 0, 0, SRCCOPY); - } - else - { - hbr = GetSysColorBrush(COLOR_WINDOW); - FillRect(hdc, &rzone, hbr); - - /* Draw the header bitmap. It's always centered like a - * common 49 x 49 bitmap. */ - BitBlt(hdc, rzone.right - 49 - ((rzone.bottom - 49) / 2), - (rzone.bottom - 49) / 2, - bm.bmWidth, bm.bmHeight, - hdcSrc, 0, 0, SRCCOPY); - - /* NOTE: Native COMCTL32 draws a white stripe over the bitmap - * if its height is smaller than 49 pixels. Because the reason - * for this bug is unknown the current code doesn't try to - * replicate it. */ - } - - clrOld = SetTextColor (hdc, 0x00000000); - oldBkMode = SetBkMode (hdc, TRANSPARENT); - - if (ppshpage->dwFlags & PSP_USEHEADERTITLE) { - SetRect(&r, 20, 10, 0, 0); - if (HIWORD(ppshpage->pszHeaderTitle)) - { - if (psInfo->unicode) - DrawTextW(hdc, (LPWSTR)ppshpage->pszHeaderTitle, - -1, &r, DT_LEFT | DT_SINGLELINE | DT_NOCLIP); - else - DrawTextA(hdc, (LPCSTR)ppshpage->pszHeaderTitle, - -1, &r, DT_LEFT | DT_SINGLELINE | DT_NOCLIP); - } - else - { - nLength = LoadStringW(ppshpage->hInstance, (UINT)ppshpage->pszHeaderTitle, - szBuffer, 256); - if (nLength != 0) - { - DrawTextW(hdc, szBuffer, nLength, - &r, DT_LEFT | DT_SINGLELINE | DT_NOCLIP); - } - } - } - - if (ppshpage->dwFlags & PSP_USEHEADERSUBTITLE) { - SelectObject(hdc, psInfo->hFont); - SetRect(&r, 40, 25, rzone.right - 69, rzone.bottom); - if (HIWORD(ppshpage->pszHeaderTitle)) - { - if (psInfo->unicode) - DrawTextW(hdc, (LPWSTR)ppshpage->pszHeaderSubTitle, - -1, &r, DT_LEFT | DT_SINGLELINE); - else - DrawTextA(hdc, (LPCSTR)ppshpage->pszHeaderSubTitle, - -1, &r, DT_LEFT | DT_SINGLELINE); - } - else - { - nLength = LoadStringW(ppshpage->hInstance, (UINT)ppshpage->pszHeaderSubTitle, - szBuffer, 256); - if (nLength != 0) - { - DrawTextW(hdc, szBuffer, nLength, - &r, DT_LEFT | DT_SINGLELINE); - } - } - } - - offsety = rzone.bottom + 2; - - SetTextColor(hdc, clrOld); - SetBkMode(hdc, oldBkMode); - SelectObject(hdc, hOldFont); - SelectObject(hdcSrc, hbmp); - } - - if ( (ppshpage->dwFlags & PSP_HIDEHEADER) && - (psInfo->ppshheader.dwFlags & (PSH_WIZARD97_OLD | PSH_WIZARD97_NEW)) && - (psInfo->ppshheader.dwFlags & PSH_WATERMARK) ) - { - HWND hwndLine = GetDlgItem(hwnd, IDC_SUNKEN_LINE); - - GetClientRect(hwndLine, &r); - MapWindowPoints(hwndLine, hwnd, (LPPOINT) &r, 2); - - rzone.left = 0; - rzone.top = 0; - rzone.right = r.right; - rzone.bottom = r.top - 1; - - hbr = GetSysColorBrush(COLOR_WINDOW); - FillRect(hdc, &rzone, hbr); - - GetObjectA(psInfo->ppshheader.u4.hbmWatermark, sizeof(BITMAP), (LPVOID)&bm); - hbmp = SelectObject(hdcSrc, psInfo->ppshheader.u4.hbmWatermark); - - BitBlt(hdc, 0, offsety, min(bm.bmWidth, r.right), - min(bm.bmHeight, r.bottom), hdcSrc, 0, 0, SRCCOPY); - - /* If the bitmap is not big enough, fill the remaining area - with the color of pixel (0,0) of bitmap - see MSDN */ - if (r.top > bm.bmHeight) { - r.bottom = r.top - 1; - r.top = bm.bmHeight; - r.left = 0; - r.right = bm.bmWidth; - hbr = CreateSolidBrush(GetPixel(hdcSrc, 0, 0)); - FillRect(hdc, &r, hbr); - DeleteObject(hbr); - } - - SelectObject(hdcSrc, hbmp); - } - - if (psInfo->ppshheader.dwFlags & PSH_USEHPLWATERMARK) - SelectPalette(hdc, hOldPal, FALSE); - - DeleteDC(hdcSrc); - - EndPaint(hwnd, &ps); - - return 0; -} - -/****************************************************************************** - * PROPSHEET_DialogProc - */ -INT_PTR CALLBACK -PROPSHEET_DialogProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam) -{ - TRACE("hwnd=%p msg=0x%04x wparam=%x lparam=%lx\n", - hwnd, uMsg, wParam, lParam); - - switch (uMsg) - { - case WM_INITDIALOG: - { - PropSheetInfo* psInfo = (PropSheetInfo*) lParam; - WCHAR* strCaption = (WCHAR*)Alloc(MAX_CAPTION_LENGTH*sizeof(WCHAR)); - HWND hwndTabCtrl = GetDlgItem(hwnd, IDC_TABCONTROL); - LPCPROPSHEETPAGEW ppshpage; - int idx; - LOGFONTA logFont; - - /* Using PropSheetInfoStr to store extra data doesn't match the native - * common control: native uses TCM_[GS]ETITEM - */ - SetPropW(hwnd, PropSheetInfoStr, (HANDLE)psInfo); - - /* - * psInfo->hwnd is not being used by WINE code - it exists - * for compatibility with "real" Windoze. The same about - * SetWindowLongPtr - WINE is only using the PropSheetInfoStr - * property. - */ - psInfo->hwnd = hwnd; - SetWindowLongPtrW(hwnd, DWLP_USER, (DWORD_PTR)psInfo); - - /* set up the Next and Back buttons by default */ - PROPSHEET_SetWizButtons(hwnd, PSWIZB_BACK|PSWIZB_NEXT); - - /* Set up fonts */ - SystemParametersInfoA (SPI_GETICONTITLELOGFONT, 0, &logFont, 0); - psInfo->hFont = CreateFontIndirectA (&logFont); - logFont.lfWeight = FW_BOLD; - psInfo->hFontBold = CreateFontIndirectA (&logFont); - - /* - * Small icon in the title bar. - */ - if ((psInfo->ppshheader.dwFlags & PSH_USEICONID) || - (psInfo->ppshheader.dwFlags & PSH_USEHICON)) - { - HICON hIcon; - int icon_cx = GetSystemMetrics(SM_CXSMICON); - int icon_cy = GetSystemMetrics(SM_CYSMICON); - - if (psInfo->ppshheader.dwFlags & PSH_USEICONID) - hIcon = LoadImageW(psInfo->ppshheader.hInstance, - psInfo->ppshheader.u.pszIcon, - IMAGE_ICON, - icon_cx, icon_cy, - LR_DEFAULTCOLOR); - else - hIcon = psInfo->ppshheader.u.hIcon; - - SendMessageW(hwnd, WM_SETICON, 0, (LPARAM)hIcon); - } - - if (psInfo->ppshheader.dwFlags & PSH_USEHICON) - SendMessageW(hwnd, WM_SETICON, 0, (LPARAM)psInfo->ppshheader.u.hIcon); - - psInfo->strPropertiesFor = strCaption; - - GetWindowTextW(hwnd, psInfo->strPropertiesFor, MAX_CAPTION_LENGTH); - - PROPSHEET_CreateTabControl(hwnd, psInfo); - - PROPSHEET_LoadWizardBitmaps(psInfo); - - if (psInfo->ppshheader.dwFlags & INTRNL_ANY_WIZARD) - { - ShowWindow(hwndTabCtrl, SW_HIDE); - PROPSHEET_AdjustSizeWizard(hwnd, psInfo); - PROPSHEET_AdjustButtonsWizard(hwnd, psInfo); - } - else - { - if (PROPSHEET_SizeMismatch(hwnd, psInfo)) - { - PROPSHEET_AdjustSize(hwnd, psInfo); - PROPSHEET_AdjustButtons(hwnd, psInfo); - } - } - - if (psInfo->useCallback) - (*(psInfo->ppshheader.pfnCallback))(hwnd, - PSCB_INITIALIZED, (LPARAM)0); - - idx = psInfo->active_page; - ppshpage = (LPCPROPSHEETPAGEW)psInfo->proppage[idx].hpage; - psInfo->active_page = -1; - - PROPSHEET_SetCurSel(hwnd, idx, 1, psInfo->proppage[idx].hpage); - - /* doing TCM_SETCURSEL seems to be needed even in case of PSH_WIZARD, - * as some programs call TCM_GETCURSEL to get the current selection - * from which to switch to the next page */ - SendMessageW(hwndTabCtrl, TCM_SETCURSEL, psInfo->active_page, 0); - - if (!HIWORD(psInfo->ppshheader.pszCaption) && - psInfo->ppshheader.hInstance) - { - WCHAR szText[256]; - - if (LoadStringW(psInfo->ppshheader.hInstance, - (UINT)psInfo->ppshheader.pszCaption, szText, 255)) - PROPSHEET_SetTitleW(hwnd, psInfo->ppshheader.dwFlags, szText); - } - else - { - PROPSHEET_SetTitleW(hwnd, psInfo->ppshheader.dwFlags, - psInfo->ppshheader.pszCaption); - } - - return TRUE; - } - - case WM_PAINT: - PROPSHEET_Paint(hwnd); - return TRUE; - - case WM_DESTROY: - PROPSHEET_CleanUp(hwnd); - return TRUE; - - case WM_CLOSE: - PROPSHEET_Cancel(hwnd, 1); - return TRUE; - - case WM_COMMAND: - if (!PROPSHEET_DoCommand(hwnd, LOWORD(wParam))) - { - PropSheetInfo* psInfo = (PropSheetInfo*) GetPropW(hwnd, PropSheetInfoStr); - - if (!psInfo) - return FALSE; - - /* No default handler, forward notification to active page */ - if (psInfo->activeValid && psInfo->active_page != -1) - { - HWND hwndPage = psInfo->proppage[psInfo->active_page].hwndPage; - SendMessageW(hwndPage, WM_COMMAND, wParam, lParam); - } - } - return TRUE; - - case WM_NOTIFY: - { - NMHDR* pnmh = (LPNMHDR) lParam; - - if (pnmh->code == TCN_SELCHANGE) - { - int index = SendMessageW(pnmh->hwndFrom, TCM_GETCURSEL, 0, 0); - PROPSHEET_SetCurSel(hwnd, index, 1, 0); - } - - if(pnmh->code == TCN_SELCHANGING) - { - BOOL bRet = PROPSHEET_CanSetCurSel(hwnd); - SetWindowLongPtrW(hwnd, DWLP_MSGRESULT, !bRet); - return TRUE; - } - - return FALSE; - } - - case PSM_GETCURRENTPAGEHWND: - { - PropSheetInfo* psInfo = (PropSheetInfo*) GetPropW(hwnd, - PropSheetInfoStr); - HWND hwndPage = 0; - - if (!psInfo) - return FALSE; - - if (psInfo->activeValid && psInfo->active_page != -1) - hwndPage = psInfo->proppage[psInfo->active_page].hwndPage; - - SetWindowLongPtrW(hwnd, DWLP_MSGRESULT, (DWORD_PTR)hwndPage); - - return TRUE; - } - - case PSM_CHANGED: - PROPSHEET_Changed(hwnd, (HWND)wParam); - return TRUE; - - case PSM_UNCHANGED: - PROPSHEET_UnChanged(hwnd, (HWND)wParam); - return TRUE; - - case PSM_GETTABCONTROL: - { - HWND hwndTabCtrl = GetDlgItem(hwnd, IDC_TABCONTROL); - - SetWindowLongPtrW(hwnd, DWLP_MSGRESULT, (DWORD_PTR)hwndTabCtrl); - - return TRUE; - } - - case PSM_SETCURSEL: - { - BOOL msgResult; - - msgResult = PROPSHEET_CanSetCurSel(hwnd); - if(msgResult != FALSE) - { - msgResult = PROPSHEET_SetCurSel(hwnd, - (int)wParam, - 1, - (HPROPSHEETPAGE)lParam); - } - - SetWindowLongPtrW(hwnd, DWLP_MSGRESULT, msgResult); - - return TRUE; - } - - case PSM_CANCELTOCLOSE: - { - WCHAR buf[MAX_BUTTONTEXT_LENGTH]; - HWND hwndOK = GetDlgItem(hwnd, IDOK); - HWND hwndCancel = GetDlgItem(hwnd, IDCANCEL); - - EnableWindow(hwndCancel, FALSE); - if (LoadStringW(COMCTL32_hModule, IDS_CLOSE, buf, sizeof(buf))) - SetWindowTextW(hwndOK, buf); - - return FALSE; - } - - case PSM_RESTARTWINDOWS: - { - PropSheetInfo* psInfo = (PropSheetInfo*) GetPropW(hwnd, - PropSheetInfoStr); - - if (!psInfo) - return FALSE; - - psInfo->restartWindows = TRUE; - return TRUE; - } - - case PSM_REBOOTSYSTEM: - { - PropSheetInfo* psInfo = (PropSheetInfo*) GetPropW(hwnd, - PropSheetInfoStr); - - if (!psInfo) - return FALSE; - - psInfo->rebootSystem = TRUE; - return TRUE; - } - - case PSM_SETTITLEA: - PROPSHEET_SetTitleA(hwnd, (DWORD) wParam, (LPCSTR) lParam); - return TRUE; - - case PSM_SETTITLEW: - PROPSHEET_SetTitleW(hwnd, (DWORD) wParam, (LPCWSTR) lParam); - return TRUE; - - case PSM_APPLY: - { - BOOL msgResult = PROPSHEET_Apply(hwnd, 0); - - SetWindowLongPtrW(hwnd, DWLP_MSGRESULT, msgResult); - - return TRUE; - } - - case PSM_QUERYSIBLINGS: - { - LRESULT msgResult = PROPSHEET_QuerySiblings(hwnd, wParam, lParam); - - SetWindowLongPtrW(hwnd, DWLP_MSGRESULT, msgResult); - - return TRUE; - } - - case PSM_ADDPAGE: - { - /* - * Note: MSVC++ 6.0 documentation says that PSM_ADDPAGE does not have - * a return value. This is not true. PSM_ADDPAGE returns TRUE - * on success or FALSE otherwise, as specified on MSDN Online. - * Also see the MFC code for - * CPropertySheet::AddPage(CPropertyPage* pPage). - */ - - BOOL msgResult = PROPSHEET_AddPage(hwnd, (HPROPSHEETPAGE)lParam); - - SetWindowLongPtrW(hwnd, DWLP_MSGRESULT, msgResult); - - return TRUE; - } - - case PSM_REMOVEPAGE: - PROPSHEET_RemovePage(hwnd, (int)wParam, (HPROPSHEETPAGE)lParam); - return TRUE; - - case PSM_ISDIALOGMESSAGE: - { - BOOL msgResult = PROPSHEET_IsDialogMessage(hwnd, (LPMSG)lParam); - SetWindowLongPtrW(hwnd, DWLP_MSGRESULT, msgResult); - return TRUE; - } - - case PSM_PRESSBUTTON: - PROPSHEET_PressButton(hwnd, (int)wParam); - return TRUE; - - case PSM_SETFINISHTEXTA: - PROPSHEET_SetFinishTextA(hwnd, (LPCSTR) lParam); - return TRUE; - - case PSM_SETWIZBUTTONS: - PROPSHEET_SetWizButtons(hwnd, (DWORD)lParam); - return TRUE; - - case PSM_SETCURSELID: - PROPSHEET_SetCurSelId(hwnd, (int)lParam); - return TRUE; - - case PSM_SETFINISHTEXTW: - PROPSHEET_SetFinishTextW(hwnd, (LPCWSTR) lParam); - return FALSE; - - case PSM_INSERTPAGE: - { - BOOL msgResult = PROPSHEET_InsertPage(hwnd, (HPROPSHEETPAGE)wParam, (HPROPSHEETPAGE)lParam); - SetWindowLongPtrW(hwnd, DWLP_MSGRESULT, msgResult); - return TRUE; - } - - case PSM_SETHEADERTITLEW: - PROPSHEET_SetHeaderTitleW(hwnd, (int)wParam, (LPCWSTR)lParam); - return TRUE; - - case PSM_SETHEADERTITLEA: - PROPSHEET_SetHeaderTitleA(hwnd, (int)wParam, (LPCSTR)lParam); - return TRUE; - - case PSM_SETHEADERSUBTITLEW: - PROPSHEET_SetHeaderSubTitleW(hwnd, (int)wParam, (LPCWSTR)lParam); - return TRUE; - - case PSM_SETHEADERSUBTITLEA: - PROPSHEET_SetHeaderSubTitleA(hwnd, (int)wParam, (LPCSTR)lParam); - return TRUE; - - case PSM_HWNDTOINDEX: - { - LRESULT msgResult = PROPSHEET_HwndToIndex(hwnd, (HWND)wParam); - SetWindowLongPtrW(hwnd, DWLP_MSGRESULT, msgResult); - return TRUE; - } - - case PSM_INDEXTOHWND: - { - LRESULT msgResult = PROPSHEET_IndexToHwnd(hwnd, (int)wParam); - SetWindowLongPtrW(hwnd, DWLP_MSGRESULT, msgResult); - return TRUE; - } - - case PSM_PAGETOINDEX: - { - LRESULT msgResult = PROPSHEET_PageToIndex(hwnd, (HPROPSHEETPAGE)wParam); - SetWindowLongPtrW(hwnd, DWLP_MSGRESULT, msgResult); - return TRUE; - } - - case PSM_INDEXTOPAGE: - { - LRESULT msgResult = PROPSHEET_IndexToPage(hwnd, (int)wParam); - SetWindowLongPtrW(hwnd, DWLP_MSGRESULT, msgResult); - return TRUE; - } - - case PSM_IDTOINDEX: - { - LRESULT msgResult = PROPSHEET_IdToIndex(hwnd, (int)lParam); - SetWindowLongPtrW(hwnd, DWLP_MSGRESULT, msgResult); - return TRUE; - } - - case PSM_INDEXTOID: - { - LRESULT msgResult = PROPSHEET_IndexToId(hwnd, (int)wParam); - SetWindowLongPtrW(hwnd, DWLP_MSGRESULT, msgResult); - return TRUE; - } - - case PSM_GETRESULT: - { - LRESULT msgResult = PROPSHEET_GetResult(hwnd); - SetWindowLongPtrW(hwnd, DWLP_MSGRESULT, msgResult); - return TRUE; - } - - case PSM_RECALCPAGESIZES: - { - LRESULT msgResult = PROPSHEET_RecalcPageSizes(hwnd); - SetWindowLongPtrW(hwnd, DWLP_MSGRESULT, msgResult); - return TRUE; - } - - default: - return FALSE; - } - - return FALSE; -} diff --git a/reactos/lib/comctl32/rebar.c b/reactos/lib/comctl32/rebar.c deleted file mode 100644 index 069734ea6f7..00000000000 --- a/reactos/lib/comctl32/rebar.c +++ /dev/null @@ -1,4732 +0,0 @@ -/* - * Rebar control - * - * Copyright 1998, 1999 Eric Kohl - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2.1 of the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - * - * - * This code was audited for completeness against the documented features - * of Comctl32.dll version 6.0 on Oct. 19, 2004, by Robert Shearman. - * - * Unless otherwise noted, we believe this code to be complete, as per - * the specification mentioned above. - * If you discover missing features or bugs please note them below. - * - * TODO - * Styles: - * - RBS_DBLCLKTOGGLE - * - RBS_FIXEDORDER - * - RBS_REGISTERDROP - * - RBS_TOOLTIPS - * - CCS_NORESIZE - * - CCS_NOMOVEX - * - CCS_NOMOVEY - * Messages: - * - RB_BEGINDRAG - * - RB_DRAGMOVE - * - RB_ENDDRAG - * - RB_GETBANDMARGINS - * - RB_GETCOLORSCHEME - * - RB_GETDROPTARGET - * - RB_GETPALETTE - * - RB_SETCOLORSCHEME - * - RB_SETPALETTE - * - RB_SETTOOLTIPS - * - WM_CHARTOITEM - * - WM_LBUTTONDBLCLK - * - WM_MEASUREITEM - * - WM_PALETTECHANGED - * - WM_PRINTCLIENT - * - WM_QUERYNEWPALETTE - * - WM_RBUTTONDOWN - * - WM_RBUTTONUP - * - WM_SYSCOLORCHANGE - * - WM_VKEYTOITEM - * - WM_WININICHANGE - * Notifications: - * - NM_HCHITTEST - * - NM_RELEASEDCAPTURE - * - RBN_AUTOBREAK - * - RBN_GETOBJECT - * - RBN_MINMAX - * Band styles: - * - RBBS_FIXEDBMP - * Native uses (on each draw!!) SM_CYBORDER (or SM_CXBORDER for CCS_VERT) - * to set the size of the separator width (the value SEP_WIDTH_SIZE - * in here). Should be fixed!! - */ - -/* - * Testing: set to 1 to make background brush *always* green - */ -#define GLATESTING 0 - -/* - * - * 2. At "FIXME: problem # 2" WinRAR: - * if "#if 1" then last band draws in separate row - * if "#if 0" then last band draws in previous row *** just like native *** - * - */ -#define PROBLEM2 0 - -/* - * 3. REBAR_MoveChildWindows should have a loop because more than - * one pass is made (together with the RBN_CHILDSIZEs) is made on - * at least RB_INSERTBAND - */ - -#include -#include -#include - -#include "windef.h" -#include "winbase.h" -#include "wingdi.h" -#include "wine/unicode.h" -#include "winuser.h" -#include "winnls.h" -#include "commctrl.h" -#include "comctl32.h" -#include "wine/debug.h" - -WINE_DEFAULT_DEBUG_CHANNEL(rebar); - -typedef struct -{ - UINT fStyle; - UINT fMask; - COLORREF clrFore; - COLORREF clrBack; - INT iImage; - HWND hwndChild; - UINT cxMinChild; /* valid if _CHILDSIZE */ - UINT cyMinChild; /* valid if _CHILDSIZE */ - UINT cx; /* valid if _SIZE */ - HBITMAP hbmBack; - UINT wID; - UINT cyChild; /* valid if _CHILDSIZE */ - UINT cyMaxChild; /* valid if _CHILDSIZE */ - UINT cyIntegral; /* valid if _CHILDSIZE */ - UINT cxIdeal; - LPARAM lParam; - UINT cxHeader; - - UINT lcx; /* minimum cx for band */ - UINT ccx; /* current cx for band */ - UINT hcx; /* maximum cx for band */ - UINT lcy; /* minimum cy for band */ - UINT ccy; /* current cy for band */ - UINT hcy; /* maximum cy for band */ - - SIZE offChild; /* x,y offset if child is not FIXEDSIZE */ - UINT uMinHeight; - INT iRow; /* row this band assigned to */ - UINT fStatus; /* status flags, reset only by _Validate */ - UINT fDraw; /* drawing flags, reset only by _Layout */ - UINT uCDret; /* last return from NM_CUSTOMDRAW */ - RECT rcoldBand; /* previous calculated band rectangle */ - RECT rcBand; /* calculated band rectangle */ - RECT rcGripper; /* calculated gripper rectangle */ - RECT rcCapImage; /* calculated caption image rectangle */ - RECT rcCapText; /* calculated caption text rectangle */ - RECT rcChild; /* calculated child rectangle */ - RECT rcChevron; /* calculated chevron rectangle */ - - LPWSTR lpText; - HWND hwndPrevParent; -} REBAR_BAND; - -/* fStatus flags */ -#define HAS_GRIPPER 0x00000001 -#define HAS_IMAGE 0x00000002 -#define HAS_TEXT 0x00000004 - -/* fDraw flags */ -#define DRAW_GRIPPER 0x00000001 -#define DRAW_IMAGE 0x00000002 -#define DRAW_TEXT 0x00000004 -#define DRAW_RIGHTSEP 0x00000010 -#define DRAW_BOTTOMSEP 0x00000020 -#define DRAW_CHEVRONHOT 0x00000040 -#define DRAW_CHEVRONPUSHED 0x00000080 -#define DRAW_LAST_IN_ROW 0x00000100 -#define DRAW_FIRST_IN_ROW 0x00000200 -#define NTF_INVALIDATE 0x01000000 - -typedef struct -{ - COLORREF clrBk; /* background color */ - COLORREF clrText; /* text color */ - COLORREF clrBtnText; /* system color for BTNTEXT */ - COLORREF clrBtnFace; /* system color for BTNFACE */ - HIMAGELIST himl; /* handle to imagelist */ - UINT uNumBands; /* # of bands in rebar (first=0, last=uNumBands-1 */ - UINT uNumRows; /* # of rows of bands (first=1, last=uNumRows */ - HWND hwndSelf; /* handle of REBAR window itself */ - HWND hwndToolTip; /* handle to the tool tip control */ - HWND hwndNotify; /* notification window (parent) */ - HFONT hDefaultFont; - HFONT hFont; /* handle to the rebar's font */ - SIZE imageSize; /* image size (image list) */ - DWORD dwStyle; /* window style */ - SIZE calcSize; /* calculated rebar size */ - SIZE oldSize; /* previous calculated rebar size */ - BOOL bUnicode; /* TRUE if this window is W type */ - BOOL NtfUnicode; /* TRUE if parent wants notify in W format */ - BOOL DoRedraw; /* TRUE to acutally draw bands */ - UINT fStatus; /* Status flags (see below) */ - HCURSOR hcurArrow; /* handle to the arrow cursor */ - HCURSOR hcurHorz; /* handle to the EW cursor */ - HCURSOR hcurVert; /* handle to the NS cursor */ - HCURSOR hcurDrag; /* handle to the drag cursor */ - INT iVersion; /* version number */ - POINT dragStart; /* x,y of button down */ - POINT dragNow; /* x,y of this MouseMove */ - INT iOldBand; /* last band that had the mouse cursor over it */ - INT ihitoffset; /* offset of hotspot from gripper.left */ - POINT origin; /* left/upper corner of client */ - INT ichevronhotBand; /* last band that had a hot chevron */ - INT iGrabbedBand;/* band number of band whose gripper was grabbed */ - - REBAR_BAND *bands; /* pointer to the array of rebar bands */ -} REBAR_INFO; - -/* fStatus flags */ -#define BEGIN_DRAG_ISSUED 0x00000001 -#define AUTO_RESIZE 0x00000002 -#define RESIZE_ANYHOW 0x00000004 -#define NTF_HGHTCHG 0x00000008 -#define BAND_NEEDS_LAYOUT 0x00000010 -#define BAND_NEEDS_REDRAW 0x00000020 -#define CREATE_RUNNING 0x00000040 - -/* ---- REBAR layout constants. Mostly determined by ---- */ -/* ---- experiment on WIN 98. ---- */ - -/* Width (or height) of separators between bands (either horz. or */ -/* vert.). True only if RBS_BANDBORDERS is set */ -#define SEP_WIDTH_SIZE 2 -#define SEP_WIDTH ((infoPtr->dwStyle & RBS_BANDBORDERS) ? SEP_WIDTH_SIZE : 0) - -/* Blank (background color) space between Gripper (if present) */ -/* and next item (image, text, or window). Always present */ -#define REBAR_ALWAYS_SPACE 4 - -/* Blank (background color) space after Image (if present). */ -#define REBAR_POST_IMAGE 2 - -/* Blank (background color) space after Text (if present). */ -#define REBAR_POST_TEXT 4 - -/* Height of vertical gripper in a CCS_VERT rebar. */ -#define GRIPPER_HEIGHT 16 - -/* Blank (background color) space before Gripper (if present). */ -#define REBAR_PRE_GRIPPER 2 - -/* Width (of normal vertical gripper) or height (of horz. gripper) */ -/* if present. */ -#define GRIPPER_WIDTH 3 - -/* Width of the chevron button if present */ -#define CHEVRON_WIDTH 10 - -/* Height of divider for Rebar if not disabled (CCS_NODIVIDER) */ -/* either top or bottom */ -#define REBAR_DIVIDER 2 - -/* minimium vertical height of a normal bar */ -/* or minimum width of a CCS_VERT bar - from experiment on Win2k */ -#define REBAR_MINSIZE 23 - -/* This is the increment that is used over the band height */ -#define REBARSPACE(a) ((a->fStyle & RBBS_CHILDEDGE) ? 2*REBAR_DIVIDER : 0) - -/* ---- End of REBAR layout constants. ---- */ - -#define RB_GETBANDINFO_OLD (WM_USER+5) /* obsoleted after IE3, but we have to support it anyway */ - -/* The following 6 defines return the proper rcBand element */ -/* depending on whether CCS_VERT was set. */ -#define rcBlt(b) ((infoPtr->dwStyle & CCS_VERT) ? b->rcBand.top : b->rcBand.left) -#define rcBrb(b) ((infoPtr->dwStyle & CCS_VERT) ? b->rcBand.bottom : b->rcBand.right) -#define rcBw(b) ((infoPtr->dwStyle & CCS_VERT) ? (b->rcBand.bottom - b->rcBand.top) : \ - (b->rcBand.right - b->rcBand.left)) -#define ircBlt(b) ((infoPtr->dwStyle & CCS_VERT) ? b->rcBand.left : b->rcBand.top) -#define ircBrb(b) ((infoPtr->dwStyle & CCS_VERT) ? b->rcBand.right : b->rcBand.bottom) -#define ircBw(b) ((infoPtr->dwStyle & CCS_VERT) ? (b->rcBand.right - b->rcBand.left) : \ - (b->rcBand.bottom - b->rcBand.top)) - -/* The following define determines if a given band is hidden */ -#define HIDDENBAND(a) (((a)->fStyle & RBBS_HIDDEN) || \ - ((infoPtr->dwStyle & CCS_VERT) && \ - ((a)->fStyle & RBBS_NOVERT))) - -/* The following defines adjust the right or left end of a rectangle */ -#define READJ(b,i) do { if(infoPtr->dwStyle & CCS_VERT) b->rcBand.bottom+=(i); \ - else b->rcBand.right += (i); } while(0) -#define LEADJ(b,i) do { if(infoPtr->dwStyle & CCS_VERT) b->rcBand.top+=(i); \ - else b->rcBand.left += (i); } while(0) - - -#define REBAR_GetInfoPtr(wndPtr) ((REBAR_INFO *)GetWindowLongPtrW (hwnd, 0)) - - -/* "constant values" retrieved when DLL was initialized */ -/* FIXME we do this when the classes are registered. */ -static UINT mindragx = 0; -static UINT mindragy = 0; - -static const char *band_stylename[] = { - "RBBS_BREAK", /* 0001 */ - "RBBS_FIXEDSIZE", /* 0002 */ - "RBBS_CHILDEDGE", /* 0004 */ - "RBBS_HIDDEN", /* 0008 */ - "RBBS_NOVERT", /* 0010 */ - "RBBS_FIXEDBMP", /* 0020 */ - "RBBS_VARIABLEHEIGHT", /* 0040 */ - "RBBS_GRIPPERALWAYS", /* 0080 */ - "RBBS_NOGRIPPER", /* 0100 */ - NULL }; - -static const char *band_maskname[] = { - "RBBIM_STYLE", /* 0x00000001 */ - "RBBIM_COLORS", /* 0x00000002 */ - "RBBIM_TEXT", /* 0x00000004 */ - "RBBIM_IMAGE", /* 0x00000008 */ - "RBBIM_CHILD", /* 0x00000010 */ - "RBBIM_CHILDSIZE", /* 0x00000020 */ - "RBBIM_SIZE", /* 0x00000040 */ - "RBBIM_BACKGROUND", /* 0x00000080 */ - "RBBIM_ID", /* 0x00000100 */ - "RBBIM_IDEALSIZE", /* 0x00000200 */ - "RBBIM_LPARAM", /* 0x00000400 */ - "RBBIM_HEADERSIZE", /* 0x00000800 */ - NULL }; - - -static CHAR line[200]; - - -static CHAR * -REBAR_FmtStyle( UINT style) -{ - INT i = 0; - - *line = 0; - while (band_stylename[i]) { - if (style & (1<wID, pB->cbSize, pB->hwndChild, pB->clrFore, pB->clrBack); - TRACE("band info: mask=0x%08x (%s)\n", pB->fMask, REBAR_FmtMask(pB->fMask)); - if (pB->fMask & RBBIM_STYLE) - TRACE("band info: style=0x%08x (%s)\n", pB->fStyle, REBAR_FmtStyle(pB->fStyle)); - if (pB->fMask & (RBBIM_SIZE | RBBIM_IDEALSIZE | RBBIM_HEADERSIZE | RBBIM_LPARAM )) { - TRACE("band info:"); - if (pB->fMask & RBBIM_SIZE) - TRACE(" cx=%u", pB->cx); - if (pB->fMask & RBBIM_IDEALSIZE) - TRACE(" xIdeal=%u", pB->cxIdeal); - if (pB->fMask & RBBIM_HEADERSIZE) - TRACE(" xHeader=%u", pB->cxHeader); - if (pB->fMask & RBBIM_LPARAM) - TRACE(" lParam=0x%08lx", pB->lParam); - TRACE("\n"); - } - if (pB->fMask & RBBIM_CHILDSIZE) - TRACE("band info: xMin=%u, yMin=%u, yChild=%u, yMax=%u, yIntgl=%u\n", - pB->cxMinChild, - pB->cyMinChild, pB->cyChild, pB->cyMaxChild, pB->cyIntegral); -} - -static VOID -REBAR_DumpBand (REBAR_INFO *iP) -{ - REBAR_BAND *pB; - UINT i; - - if(! TRACE_ON(rebar) ) return; - - TRACE("hwnd=%p: color=%08lx/%08lx, bands=%u, rows=%u, cSize=%ld,%ld\n", - iP->hwndSelf, iP->clrText, iP->clrBk, iP->uNumBands, iP->uNumRows, - iP->calcSize.cx, iP->calcSize.cy); - TRACE("hwnd=%p: flags=%08x, dragStart=%ld,%ld, dragNow=%ld,%ld, iGrabbedBand=%d\n", - iP->hwndSelf, iP->fStatus, iP->dragStart.x, iP->dragStart.y, - iP->dragNow.x, iP->dragNow.y, - iP->iGrabbedBand); - TRACE("hwnd=%p: style=%08lx, I'm Unicode=%s, notify in Unicode=%s, redraw=%s\n", - iP->hwndSelf, iP->dwStyle, (iP->bUnicode)?"TRUE":"FALSE", - (iP->NtfUnicode)?"TRUE":"FALSE", (iP->DoRedraw)?"TRUE":"FALSE"); - for (i = 0; i < iP->uNumBands; i++) { - pB = &iP->bands[i]; - TRACE("band # %u: ID=%u, child=%p, row=%u, clrF=0x%06lx, clrB=0x%06lx\n", - i, pB->wID, pB->hwndChild, pB->iRow, pB->clrFore, pB->clrBack); - TRACE("band # %u: mask=0x%08x (%s)\n", i, pB->fMask, REBAR_FmtMask(pB->fMask)); - if (pB->fMask & RBBIM_STYLE) - TRACE("band # %u: style=0x%08x (%s)\n", - i, pB->fStyle, REBAR_FmtStyle(pB->fStyle)); - TRACE("band # %u: uMinH=%u xHeader=%u", - i, pB->uMinHeight, pB->cxHeader); - if (pB->fMask & (RBBIM_SIZE | RBBIM_IDEALSIZE | RBBIM_LPARAM )) { - if (pB->fMask & RBBIM_SIZE) - TRACE(" cx=%u", pB->cx); - if (pB->fMask & RBBIM_IDEALSIZE) - TRACE(" xIdeal=%u", pB->cxIdeal); - if (pB->fMask & RBBIM_LPARAM) - TRACE(" lParam=0x%08lx", pB->lParam); - } - TRACE("\n"); - if (RBBIM_CHILDSIZE) - TRACE("band # %u: xMin=%u, yMin=%u, yChild=%u, yMax=%u, yIntgl=%u\n", - i, pB->cxMinChild, pB->cyMinChild, pB->cyChild, pB->cyMaxChild, pB->cyIntegral); - if (pB->fMask & RBBIM_TEXT) - TRACE("band # %u: text=%s\n", - i, (pB->lpText) ? debugstr_w(pB->lpText) : "(null)"); - TRACE("band # %u: lcx=%u, ccx=%u, hcx=%u, lcy=%u, ccy=%u, hcy=%u, offChild=%ld,%ld\n", - i, pB->lcx, pB->ccx, pB->hcx, pB->lcy, pB->ccy, pB->hcy, pB->offChild.cx, pB->offChild.cy); - TRACE("band # %u: fStatus=%08x, fDraw=%08x, Band=(%ld,%ld)-(%ld,%ld), Grip=(%ld,%ld)-(%ld,%ld)\n", - i, pB->fStatus, pB->fDraw, - pB->rcBand.left, pB->rcBand.top, pB->rcBand.right, pB->rcBand.bottom, - pB->rcGripper.left, pB->rcGripper.top, pB->rcGripper.right, pB->rcGripper.bottom); - TRACE("band # %u: Img=(%ld,%ld)-(%ld,%ld), Txt=(%ld,%ld)-(%ld,%ld), Child=(%ld,%ld)-(%ld,%ld)\n", - i, - pB->rcCapImage.left, pB->rcCapImage.top, pB->rcCapImage.right, pB->rcCapImage.bottom, - pB->rcCapText.left, pB->rcCapText.top, pB->rcCapText.right, pB->rcCapText.bottom, - pB->rcChild.left, pB->rcChild.top, pB->rcChild.right, pB->rcChild.bottom); - } - -} - -static void -REBAR_DrawChevron (HDC hdc, INT left, INT top, INT colorRef) -{ - INT x, y; - HPEN hPen, hOldPen; - - if (!(hPen = CreatePen( PS_SOLID, 1, GetSysColor( colorRef )))) return; - hOldPen = SelectObject ( hdc, hPen ); - x = left + 2; - y = top; - MoveToEx (hdc, x, y, NULL); - LineTo (hdc, x+5, y++); x++; - MoveToEx (hdc, x, y, NULL); - LineTo (hdc, x+3, y++); x++; - MoveToEx (hdc, x, y, NULL); - LineTo (hdc, x+1, y++); - SelectObject( hdc, hOldPen ); - DeleteObject( hPen ); -} - -static HWND -REBAR_GetNotifyParent (REBAR_INFO *infoPtr) -{ - HWND parent, owner; - - parent = infoPtr->hwndNotify; - if (!parent) { - parent = GetParent (infoPtr->hwndSelf); - owner = GetWindow (infoPtr->hwndSelf, GW_OWNER); - if (owner) parent = owner; - } - return parent; -} - - -static INT -REBAR_Notify (NMHDR *nmhdr, REBAR_INFO *infoPtr, UINT code) -{ - HWND parent; - - parent = REBAR_GetNotifyParent (infoPtr); - nmhdr->idFrom = GetDlgCtrlID (infoPtr->hwndSelf); - nmhdr->hwndFrom = infoPtr->hwndSelf; - nmhdr->code = code; - - TRACE("window %p, code=%08x, %s\n", parent, code, - (infoPtr->NtfUnicode) ? "via Unicode" : "via ANSI"); - - if (infoPtr->NtfUnicode) - return SendMessageW (parent, WM_NOTIFY, (WPARAM) nmhdr->idFrom, - (LPARAM)nmhdr); - else - return SendMessageA (parent, WM_NOTIFY, (WPARAM) nmhdr->idFrom, - (LPARAM)nmhdr); -} - -static INT -REBAR_Notify_NMREBAR (REBAR_INFO *infoPtr, UINT uBand, UINT code) -{ - NMREBAR notify_rebar; - REBAR_BAND *lpBand; - - notify_rebar.dwMask = 0; - if (uBand!=-1) { - lpBand = &infoPtr->bands[uBand]; - if (lpBand->fMask & RBBIM_ID) { - notify_rebar.dwMask |= RBNM_ID; - notify_rebar.wID = lpBand->wID; - } - if (lpBand->fMask & RBBIM_LPARAM) { - notify_rebar.dwMask |= RBNM_LPARAM; - notify_rebar.lParam = lpBand->lParam; - } - if (lpBand->fMask & RBBIM_STYLE) { - notify_rebar.dwMask |= RBNM_STYLE; - notify_rebar.fStyle = lpBand->fStyle; - } - } - notify_rebar.uBand = uBand; - return REBAR_Notify ((NMHDR *)¬ify_rebar, infoPtr, code); -} - -static VOID -REBAR_DrawBand (HDC hdc, REBAR_INFO *infoPtr, REBAR_BAND *lpBand) -{ - HFONT hOldFont = 0; - INT oldBkMode = 0; - NMCUSTOMDRAW nmcd; - - if (lpBand->fDraw & DRAW_TEXT) { - hOldFont = SelectObject (hdc, infoPtr->hFont); - oldBkMode = SetBkMode (hdc, TRANSPARENT); - } - - /* should test for CDRF_NOTIFYITEMDRAW here */ - nmcd.dwDrawStage = CDDS_ITEMPREPAINT; - nmcd.hdc = hdc; - nmcd.rc = lpBand->rcBand; - nmcd.rc.right = lpBand->rcCapText.right; - nmcd.rc.bottom = lpBand->rcCapText.bottom; - nmcd.dwItemSpec = lpBand->wID; - nmcd.uItemState = 0; - nmcd.lItemlParam = lpBand->lParam; - lpBand->uCDret = REBAR_Notify ((NMHDR *)&nmcd, infoPtr, NM_CUSTOMDRAW); - if (lpBand->uCDret == CDRF_SKIPDEFAULT) { - if (oldBkMode != TRANSPARENT) - SetBkMode (hdc, oldBkMode); - SelectObject (hdc, hOldFont); - return; - } - - /* draw gripper */ - if (lpBand->fDraw & DRAW_GRIPPER) - DrawEdge (hdc, &lpBand->rcGripper, BDR_RAISEDINNER, BF_RECT | BF_MIDDLE); - - /* draw caption image */ - if (lpBand->fDraw & DRAW_IMAGE) { - POINT pt; - - /* center image */ - pt.y = (lpBand->rcCapImage.bottom + lpBand->rcCapImage.top - infoPtr->imageSize.cy)/2; - pt.x = (lpBand->rcCapImage.right + lpBand->rcCapImage.left - infoPtr->imageSize.cx)/2; - - ImageList_Draw (infoPtr->himl, lpBand->iImage, hdc, - pt.x, pt.y, - ILD_TRANSPARENT); - } - - /* draw caption text */ - if (lpBand->fDraw & DRAW_TEXT) { - /* need to handle CDRF_NEWFONT here */ - INT oldBkMode = SetBkMode (hdc, TRANSPARENT); - COLORREF oldcolor = CLR_NONE; - COLORREF new; - if (lpBand->clrFore != CLR_NONE) { - new = (lpBand->clrFore == CLR_DEFAULT) ? infoPtr->clrBtnText : - lpBand->clrFore; - oldcolor = SetTextColor (hdc, new); - } - DrawTextW (hdc, lpBand->lpText, -1, &lpBand->rcCapText, - DT_CENTER | DT_VCENTER | DT_SINGLELINE); - if (oldBkMode != TRANSPARENT) - SetBkMode (hdc, oldBkMode); - if (lpBand->clrFore != CLR_NONE) - SetTextColor (hdc, oldcolor); - SelectObject (hdc, hOldFont); - } - - if (!IsRectEmpty(&lpBand->rcChevron)) - { - if (lpBand->fDraw & DRAW_CHEVRONPUSHED) - { - DrawEdge(hdc, &lpBand->rcChevron, BDR_SUNKENOUTER, BF_RECT | BF_MIDDLE); - REBAR_DrawChevron(hdc, lpBand->rcChevron.left+1, lpBand->rcChevron.top + 11, COLOR_WINDOWFRAME); - } - else if (lpBand->fDraw & DRAW_CHEVRONHOT) - { - DrawEdge(hdc, &lpBand->rcChevron, BDR_RAISEDINNER, BF_RECT | BF_MIDDLE); - REBAR_DrawChevron(hdc, lpBand->rcChevron.left, lpBand->rcChevron.top + 10, COLOR_WINDOWFRAME); - } - else - REBAR_DrawChevron(hdc, lpBand->rcChevron.left, lpBand->rcChevron.top + 10, COLOR_WINDOWFRAME); - } - - if (lpBand->uCDret == (CDRF_NOTIFYPOSTPAINT | CDRF_NOTIFYITEMDRAW)) { - nmcd.dwDrawStage = CDDS_ITEMPOSTPAINT; - nmcd.hdc = hdc; - nmcd.rc = lpBand->rcBand; - nmcd.rc.right = lpBand->rcCapText.right; - nmcd.rc.bottom = lpBand->rcCapText.bottom; - nmcd.dwItemSpec = lpBand->wID; - nmcd.uItemState = 0; - nmcd.lItemlParam = lpBand->lParam; - lpBand->uCDret = REBAR_Notify ((NMHDR *)&nmcd, infoPtr, NM_CUSTOMDRAW); - } -} - - -static VOID -REBAR_Refresh (REBAR_INFO *infoPtr, HDC hdc) -{ - REBAR_BAND *lpBand; - UINT i; - - if (!infoPtr->DoRedraw) return; - - for (i = 0; i < infoPtr->uNumBands; i++) { - lpBand = &infoPtr->bands[i]; - - if (HIDDENBAND(lpBand)) continue; - - /* now draw the band */ - TRACE("[%p] drawing band %i, flags=%08x\n", - infoPtr->hwndSelf, i, lpBand->fDraw); - REBAR_DrawBand (hdc, infoPtr, lpBand); - - } -} - - -static void -REBAR_FixVert (REBAR_INFO *infoPtr, UINT rowstart, UINT rowend, - INT mcy) - /* Function: */ - /* Cycle through bands in row and fix height of each band. */ - /* Also determine whether each band has changed. */ - /* On entry: */ - /* all bands at desired size. */ - /* start and end bands are *not* hidden */ -{ - REBAR_BAND *lpBand; - INT i; - - for (i = (INT)rowstart; i<=(INT)rowend; i++) { - lpBand = &infoPtr->bands[i]; - if (HIDDENBAND(lpBand)) continue; - - /* adjust height of bands in row to "mcy" value */ - if (infoPtr->dwStyle & CCS_VERT) { - if (lpBand->rcBand.right != lpBand->rcBand.left + mcy) - lpBand->rcBand.right = lpBand->rcBand.left + mcy; - } - else { - if (lpBand->rcBand.bottom != lpBand->rcBand.top + mcy) - lpBand->rcBand.bottom = lpBand->rcBand.top + mcy; - - } - - /* mark whether we need to invalidate this band and trace */ - if ((lpBand->rcoldBand.left !=lpBand->rcBand.left) || - (lpBand->rcoldBand.top !=lpBand->rcBand.top) || - (lpBand->rcoldBand.right !=lpBand->rcBand.right) || - (lpBand->rcoldBand.bottom !=lpBand->rcBand.bottom)) { - lpBand->fDraw |= NTF_INVALIDATE; - TRACE("band %d row=%d: changed to (%ld,%ld)-(%ld,%ld) from (%ld,%ld)-(%ld,%ld)\n", - i, lpBand->iRow, - lpBand->rcBand.left, lpBand->rcBand.top, - lpBand->rcBand.right, lpBand->rcBand.bottom, - lpBand->rcoldBand.left, lpBand->rcoldBand.top, - lpBand->rcoldBand.right, lpBand->rcoldBand.bottom); - } - else - TRACE("band %d row=%d: unchanged (%ld,%ld)-(%ld,%ld)\n", - i, lpBand->iRow, - lpBand->rcBand.left, lpBand->rcBand.top, - lpBand->rcBand.right, lpBand->rcBand.bottom); - } -} - - -static void -REBAR_AdjustBands (REBAR_INFO *infoPtr, UINT rowstart, UINT rowend, - INT maxx, INT mcy) - /* Function: This routine distributes the extra space in a row. */ - /* See algorithm below. */ - /* On entry: */ - /* all bands @ ->cxHeader size */ - /* start and end bands are *not* hidden */ -{ - REBAR_BAND *lpBand; - UINT xsep, extra, curwidth, fudge; - INT x, i, last_adjusted; - - TRACE("start=%u, end=%u, max x=%d, max y=%d\n", - rowstart, rowend, maxx, mcy); - - /* ******************* Phase 1 ************************ */ - /* Alg: */ - /* For each visible band with valid child */ - /* a. inflate band till either all extra space used */ - /* or band's ->ccx reached. */ - /* If any band modified, add any space left to last band */ - /* adjusted. */ - /* */ - /* ****************************************************** */ - lpBand = &infoPtr->bands[rowend]; - extra = maxx - rcBrb(lpBand); - x = 0; - last_adjusted = -1; - for (i=(INT)rowstart; i<=(INT)rowend; i++) { - lpBand = &infoPtr->bands[i]; - if (HIDDENBAND(lpBand)) continue; - xsep = (x == 0) ? 0 : SEP_WIDTH; - curwidth = rcBw(lpBand); - - /* set new left/top point */ - if (infoPtr->dwStyle & CCS_VERT) - lpBand->rcBand.top = x + xsep; - else - lpBand->rcBand.left = x + xsep; - - /* compute new width */ - if ((lpBand->hwndChild && extra) && !(lpBand->fStyle & RBBS_FIXEDSIZE)) { - /* set to the "current" band size less the header */ - fudge = lpBand->ccx; - last_adjusted = i; - if ((lpBand->fMask & RBBIM_SIZE) && (lpBand->cx > 0) && - (fudge > curwidth)) { - TRACE("adjusting band %d by %d, fudge=%d, curwidth=%d, extra=%d\n", - i, fudge-curwidth, fudge, curwidth, extra); - if ((fudge - curwidth) > extra) - fudge = curwidth + extra; - extra -= (fudge - curwidth); - curwidth = fudge; - } - else { - TRACE("adjusting band %d by %d, fudge=%d, curwidth=%d\n", - i, extra, fudge, curwidth); - curwidth += extra; - extra = 0; - } - } - - /* set new right/bottom point */ - if (infoPtr->dwStyle & CCS_VERT) - lpBand->rcBand.bottom = lpBand->rcBand.top + curwidth; - else - lpBand->rcBand.right = lpBand->rcBand.left + curwidth; - TRACE("Phase 1 band %d, (%ld,%ld)-(%ld,%ld), orig x=%d, xsep=%d\n", - i, lpBand->rcBand.left, lpBand->rcBand.top, - lpBand->rcBand.right, lpBand->rcBand.bottom, x, xsep); - x = rcBrb(lpBand); - } - if ((x >= maxx) || (last_adjusted != -1)) { - if (x > maxx) { - ERR("Phase 1 failed, x=%d, maxx=%d, start=%u, end=%u\n", - x, maxx, rowstart, rowend); - } - /* done, so spread extra space */ - if (x < maxx) { - fudge = maxx - x; - TRACE("Need to spread %d on last adjusted band %d\n", - fudge, last_adjusted); - for (i=(INT)last_adjusted; i<=(INT)rowend; i++) { - lpBand = &infoPtr->bands[i]; - if (HIDDENBAND(lpBand)) continue; - - /* set right/bottom point */ - if (i != last_adjusted) { - if (infoPtr->dwStyle & CCS_VERT) - lpBand->rcBand.top += fudge; - else - lpBand->rcBand.left += fudge; - } - - /* set left/bottom point */ - if (infoPtr->dwStyle & CCS_VERT) - lpBand->rcBand.bottom += fudge; - else - lpBand->rcBand.right += fudge; - } - } - TRACE("Phase 1 succeeded, used x=%d\n", x); - REBAR_FixVert (infoPtr, rowstart, rowend, mcy); - return; - } - - /* ******************* Phase 2 ************************ */ - /* Alg: */ - /* Find first visible band, put all */ - /* extra space there. */ - /* */ - /* ****************************************************** */ - - x = 0; - for (i=(INT)rowstart; i<=(INT)rowend; i++) { - lpBand = &infoPtr->bands[i]; - if (HIDDENBAND(lpBand)) continue; - xsep = (x == 0) ? 0 : SEP_WIDTH; - curwidth = rcBw(lpBand); - - /* set new left/top point */ - if (infoPtr->dwStyle & CCS_VERT) - lpBand->rcBand.top = x + xsep; - else - lpBand->rcBand.left = x + xsep; - - /* compute new width */ - if (extra) { - curwidth += extra; - extra = 0; - } - - /* set new right/bottom point */ - if (infoPtr->dwStyle & CCS_VERT) - lpBand->rcBand.bottom = lpBand->rcBand.top + curwidth; - else - lpBand->rcBand.right = lpBand->rcBand.left + curwidth; - TRACE("Phase 2 band %d, (%ld,%ld)-(%ld,%ld), orig x=%d, xsep=%d\n", - i, lpBand->rcBand.left, lpBand->rcBand.top, - lpBand->rcBand.right, lpBand->rcBand.bottom, x, xsep); - x = rcBrb(lpBand); - } - if (x >= maxx) { - if (x > maxx) { - ERR("Phase 2 failed, x=%d, maxx=%d, start=%u, end=%u\n", - x, maxx, rowstart, rowend); - } - /* done, so spread extra space */ - TRACE("Phase 2 succeeded, used x=%d\n", x); - REBAR_FixVert (infoPtr, rowstart, rowend, mcy); - return; - } - - /* ******************* Phase 3 ************************ */ - /* at this point everything is back to ->cxHeader values */ - /* and should not have gotten here. */ - /* ****************************************************** */ - - lpBand = &infoPtr->bands[rowstart]; - ERR("Serious problem adjusting row %d, start band %d, end band %d\n", - lpBand->iRow, rowstart, rowend); - REBAR_DumpBand (infoPtr); - return; -} - - -static void -REBAR_CalcHorzBand (REBAR_INFO *infoPtr, UINT rstart, UINT rend, BOOL notify) - /* Function: this routine initializes all the rectangles in */ - /* each band in a row to fit in the adjusted rcBand rect. */ - /* *** Supports only Horizontal bars. *** */ -{ - REBAR_BAND *lpBand; - UINT i, xoff, yoff; - HWND parenthwnd; - RECT oldChild, work; - - /* MS seems to use GetDlgCtrlID() for above GetWindowLong call */ - parenthwnd = GetParent (infoPtr->hwndSelf); - - for(i=rstart; ibands[i]; - if (HIDDENBAND(lpBand)) { - SetRect (&lpBand->rcChild, - lpBand->rcBand.right, lpBand->rcBand.top, - lpBand->rcBand.right, lpBand->rcBand.bottom); - continue; - } - - oldChild = lpBand->rcChild; - - /* set initial gripper rectangle */ - SetRect (&lpBand->rcGripper, lpBand->rcBand.left, lpBand->rcBand.top, - lpBand->rcBand.left, lpBand->rcBand.bottom); - - /* calculate gripper rectangle */ - if ( lpBand->fStatus & HAS_GRIPPER) { - lpBand->fDraw |= DRAW_GRIPPER; - lpBand->rcGripper.left += REBAR_PRE_GRIPPER; - lpBand->rcGripper.right = lpBand->rcGripper.left + GRIPPER_WIDTH; - lpBand->rcGripper.top += 2; - lpBand->rcGripper.bottom -= 2; - - SetRect (&lpBand->rcCapImage, - lpBand->rcGripper.right+REBAR_ALWAYS_SPACE, lpBand->rcBand.top, - lpBand->rcGripper.right+REBAR_ALWAYS_SPACE, lpBand->rcBand.bottom); - } - else { /* no gripper will be drawn */ - xoff = 0; - if (lpBand->fStatus & (HAS_IMAGE | HAS_TEXT)) - /* if no gripper but either image or text, then leave space */ - xoff = REBAR_ALWAYS_SPACE; - SetRect (&lpBand->rcCapImage, - lpBand->rcBand.left+xoff, lpBand->rcBand.top, - lpBand->rcBand.left+xoff, lpBand->rcBand.bottom); - } - - /* image is visible */ - if (lpBand->fStatus & HAS_IMAGE) { - lpBand->fDraw |= DRAW_IMAGE; - lpBand->rcCapImage.right += infoPtr->imageSize.cx; - lpBand->rcCapImage.bottom = lpBand->rcCapImage.top + infoPtr->imageSize.cy; - - /* set initial caption text rectangle */ - SetRect (&lpBand->rcCapText, - lpBand->rcCapImage.right+REBAR_POST_IMAGE, lpBand->rcBand.top+1, - lpBand->rcBand.left+lpBand->cxHeader, lpBand->rcBand.bottom-1); - /* update band height - if (lpBand->uMinHeight < infoPtr->imageSize.cy + 2) { - lpBand->uMinHeight = infoPtr->imageSize.cy + 2; - lpBand->rcBand.bottom = lpBand->rcBand.top + lpBand->uMinHeight; - } */ - } - else { - /* set initial caption text rectangle */ - SetRect (&lpBand->rcCapText, lpBand->rcCapImage.right, lpBand->rcBand.top+1, - lpBand->rcBand.left+lpBand->cxHeader, lpBand->rcBand.bottom-1); - } - - /* text is visible */ - if ((lpBand->fStatus & HAS_TEXT) && !(lpBand->fStyle & RBBS_HIDETITLE)) { - lpBand->fDraw |= DRAW_TEXT; - lpBand->rcCapText.right = max(lpBand->rcCapText.left, - lpBand->rcCapText.right-REBAR_POST_TEXT); - } - - /* set initial child window rectangle if there is a child */ - if (lpBand->fMask & RBBIM_CHILD) { - xoff = lpBand->offChild.cx; - yoff = lpBand->offChild.cy; - SetRect (&lpBand->rcChild, - lpBand->rcBand.left+lpBand->cxHeader, lpBand->rcBand.top+yoff, - lpBand->rcBand.right-xoff, lpBand->rcBand.bottom-yoff); - if ((lpBand->fStyle & RBBS_USECHEVRON) && (lpBand->rcChild.right - lpBand->rcChild.left < lpBand->cxIdeal)) - { - lpBand->rcChild.right -= CHEVRON_WIDTH; - SetRect(&lpBand->rcChevron, lpBand->rcChild.right, - lpBand->rcChild.top, lpBand->rcChild.right + CHEVRON_WIDTH, - lpBand->rcChild.bottom); - } - } - else { - SetRect (&lpBand->rcChild, - lpBand->rcBand.left+lpBand->cxHeader, lpBand->rcBand.top, - lpBand->rcBand.right, lpBand->rcBand.bottom); - } - - /* flag if notify required and invalidate rectangle */ - if (notify && - ((oldChild.right-oldChild.left != lpBand->rcChild.right-lpBand->rcChild.left) || - (oldChild.bottom-oldChild.top != lpBand->rcChild.bottom-lpBand->rcChild.top))) { - TRACE("Child rectangle changed for band %u\n", i); - TRACE(" from (%ld,%ld)-(%ld,%ld) to (%ld,%ld)-(%ld,%ld)\n", - oldChild.left, oldChild.top, - oldChild.right, oldChild.bottom, - lpBand->rcChild.left, lpBand->rcChild.top, - lpBand->rcChild.right, lpBand->rcChild.bottom); - } - if (lpBand->fDraw & NTF_INVALIDATE) { - TRACE("invalidating (%ld,%ld)-(%ld,%ld)\n", - lpBand->rcBand.left, - lpBand->rcBand.top, - lpBand->rcBand.right + ((lpBand->fDraw & DRAW_RIGHTSEP) ? SEP_WIDTH_SIZE : 0), - lpBand->rcBand.bottom + ((lpBand->fDraw & DRAW_BOTTOMSEP) ? SEP_WIDTH_SIZE : 0)); - lpBand->fDraw &= ~NTF_INVALIDATE; - work = lpBand->rcBand; - if (lpBand->fDraw & DRAW_RIGHTSEP) work.right += SEP_WIDTH_SIZE; - if (lpBand->fDraw & DRAW_BOTTOMSEP) work.bottom += SEP_WIDTH_SIZE; - InvalidateRect(infoPtr->hwndSelf, &work, TRUE); - } - - } - -} - - -static VOID -REBAR_CalcVertBand (REBAR_INFO *infoPtr, UINT rstart, UINT rend, BOOL notify) - /* Function: this routine initializes all the rectangles in */ - /* each band in a row to fit in the adjusted rcBand rect. */ - /* *** Supports only Vertical bars. *** */ -{ - REBAR_BAND *lpBand; - UINT i, xoff, yoff; - HWND parenthwnd; - RECT oldChild, work; - - /* MS seems to use GetDlgCtrlID() for above GetWindowLong call */ - parenthwnd = GetParent (infoPtr->hwndSelf); - - for(i=rstart; ibands[i]; - if (HIDDENBAND(lpBand)) continue; - oldChild = lpBand->rcChild; - - /* set initial gripper rectangle */ - SetRect (&lpBand->rcGripper, lpBand->rcBand.left, lpBand->rcBand.top, - lpBand->rcBand.right, lpBand->rcBand.top); - - /* calculate gripper rectangle */ - if (lpBand->fStatus & HAS_GRIPPER) { - lpBand->fDraw |= DRAW_GRIPPER; - - if (infoPtr->dwStyle & RBS_VERTICALGRIPPER) { - /* vertical gripper */ - lpBand->rcGripper.left += 3; - lpBand->rcGripper.right = lpBand->rcGripper.left + GRIPPER_WIDTH; - lpBand->rcGripper.top += REBAR_PRE_GRIPPER; - lpBand->rcGripper.bottom = lpBand->rcGripper.top + GRIPPER_HEIGHT; - - /* initialize Caption image rectangle */ - SetRect (&lpBand->rcCapImage, lpBand->rcBand.left, - lpBand->rcGripper.bottom + REBAR_ALWAYS_SPACE, - lpBand->rcBand.right, - lpBand->rcGripper.bottom + REBAR_ALWAYS_SPACE); - } - else { - /* horizontal gripper */ - lpBand->rcGripper.left += 2; - lpBand->rcGripper.right -= 2; - lpBand->rcGripper.top += REBAR_PRE_GRIPPER; - lpBand->rcGripper.bottom = lpBand->rcGripper.top + GRIPPER_WIDTH; - - /* initialize Caption image rectangle */ - SetRect (&lpBand->rcCapImage, lpBand->rcBand.left, - lpBand->rcGripper.bottom + REBAR_ALWAYS_SPACE, - lpBand->rcBand.right, - lpBand->rcGripper.bottom + REBAR_ALWAYS_SPACE); - } - } - else { /* no gripper will be drawn */ - xoff = 0; - if (lpBand->fStatus & (HAS_IMAGE | HAS_TEXT)) - /* if no gripper but either image or text, then leave space */ - xoff = REBAR_ALWAYS_SPACE; - /* initialize Caption image rectangle */ - SetRect (&lpBand->rcCapImage, - lpBand->rcBand.left, lpBand->rcBand.top+xoff, - lpBand->rcBand.right, lpBand->rcBand.top+xoff); - } - - /* image is visible */ - if (lpBand->fStatus & HAS_IMAGE) { - lpBand->fDraw |= DRAW_IMAGE; - - lpBand->rcCapImage.right = lpBand->rcCapImage.left + infoPtr->imageSize.cx; - lpBand->rcCapImage.bottom += infoPtr->imageSize.cy; - - /* set initial caption text rectangle */ - SetRect (&lpBand->rcCapText, - lpBand->rcBand.left, lpBand->rcCapImage.bottom+REBAR_POST_IMAGE, - lpBand->rcBand.right, lpBand->rcBand.top+lpBand->cxHeader); - /* update band height * - if (lpBand->uMinHeight < infoPtr->imageSize.cx + 2) { - lpBand->uMinHeight = infoPtr->imageSize.cx + 2; - lpBand->rcBand.right = lpBand->rcBand.left + lpBand->uMinHeight; - } */ - } - else { - /* set initial caption text rectangle */ - SetRect (&lpBand->rcCapText, - lpBand->rcBand.left, lpBand->rcCapImage.bottom, - lpBand->rcBand.right, lpBand->rcBand.top+lpBand->cxHeader); - } - - /* text is visible */ - if ((lpBand->fStatus & HAS_TEXT) && !(lpBand->fStyle & RBBS_HIDETITLE)) { - lpBand->fDraw |= DRAW_TEXT; - lpBand->rcCapText.bottom = max(lpBand->rcCapText.top, - lpBand->rcCapText.bottom); - } - - /* set initial child window rectangle if there is a child */ - if (lpBand->fMask & RBBIM_CHILD) { - yoff = lpBand->offChild.cx; - xoff = lpBand->offChild.cy; - SetRect (&lpBand->rcChild, - lpBand->rcBand.left+xoff, lpBand->rcBand.top+lpBand->cxHeader, - lpBand->rcBand.right-xoff, lpBand->rcBand.bottom-yoff); - } - else { - SetRect (&lpBand->rcChild, - lpBand->rcBand.left, lpBand->rcBand.top+lpBand->cxHeader, - lpBand->rcBand.right, lpBand->rcBand.bottom); - } - - /* flag if notify required and invalidate rectangle */ - if (notify && - ((oldChild.right-oldChild.left != lpBand->rcChild.right-lpBand->rcChild.left) || - (oldChild.bottom-oldChild.top != lpBand->rcChild.bottom-lpBand->rcChild.top))) { - TRACE("Child rectangle changed for band %u\n", i); - TRACE(" from (%ld,%ld)-(%ld,%ld) to (%ld,%ld)-(%ld,%ld)\n", - oldChild.left, oldChild.top, - oldChild.right, oldChild.bottom, - lpBand->rcChild.left, lpBand->rcChild.top, - lpBand->rcChild.right, lpBand->rcChild.bottom); - } - if (lpBand->fDraw & NTF_INVALIDATE) { - TRACE("invalidating (%ld,%ld)-(%ld,%ld)\n", - lpBand->rcBand.left, - lpBand->rcBand.top, - lpBand->rcBand.right + ((lpBand->fDraw & DRAW_BOTTOMSEP) ? SEP_WIDTH_SIZE : 0), - lpBand->rcBand.bottom + ((lpBand->fDraw & DRAW_RIGHTSEP) ? SEP_WIDTH_SIZE : 0)); - lpBand->fDraw &= ~NTF_INVALIDATE; - work = lpBand->rcBand; - if (lpBand->fDraw & DRAW_RIGHTSEP) work.bottom += SEP_WIDTH_SIZE; - if (lpBand->fDraw & DRAW_BOTTOMSEP) work.right += SEP_WIDTH_SIZE; - InvalidateRect(infoPtr->hwndSelf, &work, TRUE); - } - - } -} - - -static VOID -REBAR_ForceResize (REBAR_INFO *infoPtr) - /* Function: This changes the size of the REBAR window to that */ - /* calculated by REBAR_Layout. */ -{ - RECT rc; - INT x, y, width, height; - INT xedge = GetSystemMetrics(SM_CXEDGE); - INT yedge = GetSystemMetrics(SM_CYEDGE); - - GetClientRect (infoPtr->hwndSelf, &rc); - - TRACE( " old [%ld x %ld], new [%ld x %ld], client [%ld x %ld]\n", - infoPtr->oldSize.cx, infoPtr->oldSize.cy, - infoPtr->calcSize.cx, infoPtr->calcSize.cy, - rc.right, rc.bottom); - - /* If we need to shrink client, then skip size test */ - if ((infoPtr->calcSize.cy >= rc.bottom) && - (infoPtr->calcSize.cx >= rc.right)) { - - /* if size did not change then skip process */ - if ((infoPtr->oldSize.cx == infoPtr->calcSize.cx) && - (infoPtr->oldSize.cy == infoPtr->calcSize.cy) && - !(infoPtr->fStatus & RESIZE_ANYHOW)) - { - TRACE("skipping reset\n"); - return; - } - } - - infoPtr->fStatus &= ~RESIZE_ANYHOW; - /* Set flag to ignore next WM_SIZE message */ - infoPtr->fStatus |= AUTO_RESIZE; - - width = 0; - height = 0; - x = 0; - y = 0; - - if (infoPtr->dwStyle & WS_BORDER) { - width = 2 * xedge; - height = 2 * yedge; - } - - if (!(infoPtr->dwStyle & CCS_NOPARENTALIGN)) { - INT mode = infoPtr->dwStyle & (CCS_VERT | CCS_TOP | CCS_BOTTOM); - RECT rcPcl; - - GetClientRect(GetParent(infoPtr->hwndSelf), &rcPcl); - switch (mode) { - case CCS_TOP: - /* _TOP sets width to parents width */ - width += (rcPcl.right - rcPcl.left); - height += infoPtr->calcSize.cy; - x += ((infoPtr->dwStyle & WS_BORDER) ? -xedge : 0); - y += ((infoPtr->dwStyle & WS_BORDER) ? -yedge : 0); - y += ((infoPtr->dwStyle & CCS_NODIVIDER) ? 0 : REBAR_DIVIDER); - break; - case CCS_BOTTOM: - /* FIXME: wrong wrong wrong */ - /* _BOTTOM sets width to parents width */ - width += (rcPcl.right - rcPcl.left); - height += infoPtr->calcSize.cy; - x += -xedge; - y = rcPcl.bottom - height + 1; - break; - case CCS_LEFT: - /* _LEFT sets height to parents height */ - width += infoPtr->calcSize.cx; - height += (rcPcl.bottom - rcPcl.top); - x += ((infoPtr->dwStyle & WS_BORDER) ? -xedge : 0); - x += ((infoPtr->dwStyle & CCS_NODIVIDER) ? 0 : REBAR_DIVIDER); - y += ((infoPtr->dwStyle & WS_BORDER) ? -yedge : 0); - break; - case CCS_RIGHT: - /* FIXME: wrong wrong wrong */ - /* _RIGHT sets height to parents height */ - width += infoPtr->calcSize.cx; - height += (rcPcl.bottom - rcPcl.top); - x = rcPcl.right - width + 1; - y = -yedge; - break; - default: - width += infoPtr->calcSize.cx; - height += infoPtr->calcSize.cy; - } - } - else { - width += infoPtr->calcSize.cx; - height += infoPtr->calcSize.cy; - x = infoPtr->origin.x; - y = infoPtr->origin.y; - } - - TRACE("hwnd %p, style=%08lx, setting at (%d,%d) for (%d,%d)\n", - infoPtr->hwndSelf, infoPtr->dwStyle, - x, y, width, height); - SetWindowPos (infoPtr->hwndSelf, 0, x, y, width, height, - SWP_NOZORDER); - infoPtr->fStatus &= ~AUTO_RESIZE; -} - - -static VOID -REBAR_MoveChildWindows (REBAR_INFO *infoPtr, UINT start, UINT endplus) -{ - REBAR_BAND *lpBand; - CHAR szClassName[40]; - UINT i; - NMREBARCHILDSIZE rbcz; - NMHDR heightchange; - HDWP deferpos; - - if (!(deferpos = BeginDeferWindowPos(infoPtr->uNumBands))) - ERR("BeginDeferWindowPos returned NULL\n"); - - for (i = start; i < endplus; i++) { - lpBand = &infoPtr->bands[i]; - - if (HIDDENBAND(lpBand)) continue; - if (lpBand->hwndChild) { - TRACE("hwndChild = %p\n", lpBand->hwndChild); - - /* Always geterate the RBN_CHILDSIZE even it child - did not change */ - rbcz.uBand = i; - rbcz.wID = lpBand->wID; - rbcz.rcChild = lpBand->rcChild; - rbcz.rcBand = lpBand->rcBand; - if (infoPtr->dwStyle & CCS_VERT) - rbcz.rcBand.top += lpBand->cxHeader; - else - rbcz.rcBand.left += lpBand->cxHeader; - REBAR_Notify ((NMHDR *)&rbcz, infoPtr, RBN_CHILDSIZE); - if (!EqualRect (&lpBand->rcChild, &rbcz.rcChild)) { - TRACE("Child rect changed by NOTIFY for band %u\n", i); - TRACE(" from (%ld,%ld)-(%ld,%ld) to (%ld,%ld)-(%ld,%ld)\n", - lpBand->rcChild.left, lpBand->rcChild.top, - lpBand->rcChild.right, lpBand->rcChild.bottom, - rbcz.rcChild.left, rbcz.rcChild.top, - rbcz.rcChild.right, rbcz.rcChild.bottom); - lpBand->rcChild = rbcz.rcChild; /* *** ??? */ - } - - /* native (IE4 in "Favorites" frame **1) does: - * SetRect (&rc, -1, -1, -1, -1) - * EqualRect (&rc,band->rc???) - * if ret==0 - * CopyRect (band->rc????, &rc) - * set flag outside of loop - */ - - GetClassNameA (lpBand->hwndChild, szClassName, 40); - if (!lstrcmpA (szClassName, "ComboBox") || - !lstrcmpA (szClassName, WC_COMBOBOXEXA)) { - INT nEditHeight, yPos; - RECT rc; - - /* special placement code for combo or comboex box */ - - - /* get size of edit line */ - GetWindowRect (lpBand->hwndChild, &rc); - nEditHeight = rc.bottom - rc.top; - yPos = (lpBand->rcChild.bottom + lpBand->rcChild.top - nEditHeight)/2; - - /* center combo box inside child area */ - TRACE("moving child (Combo(Ex)) %p to (%ld,%d) for (%ld,%d)\n", - lpBand->hwndChild, - lpBand->rcChild.left, yPos, - lpBand->rcChild.right - lpBand->rcChild.left, - nEditHeight); - deferpos = DeferWindowPos (deferpos, lpBand->hwndChild, HWND_TOP, - lpBand->rcChild.left, - /*lpBand->rcChild.top*/ yPos, - lpBand->rcChild.right - lpBand->rcChild.left, - nEditHeight, - SWP_NOZORDER); - if (!deferpos) - ERR("DeferWindowPos returned NULL\n"); - } - else { - TRACE("moving child (Other) %p to (%ld,%ld) for (%ld,%ld)\n", - lpBand->hwndChild, - lpBand->rcChild.left, lpBand->rcChild.top, - lpBand->rcChild.right - lpBand->rcChild.left, - lpBand->rcChild.bottom - lpBand->rcChild.top); - deferpos = DeferWindowPos (deferpos, lpBand->hwndChild, HWND_TOP, - lpBand->rcChild.left, - lpBand->rcChild.top, - lpBand->rcChild.right - lpBand->rcChild.left, - lpBand->rcChild.bottom - lpBand->rcChild.top, - SWP_NOZORDER); - if (!deferpos) - ERR("DeferWindowPos returned NULL\n"); - } - } - } - if (!EndDeferWindowPos(deferpos)) - ERR("EndDeferWindowPos returned NULL\n"); - - if (infoPtr->DoRedraw) - UpdateWindow (infoPtr->hwndSelf); - - if (infoPtr->fStatus & NTF_HGHTCHG) { - infoPtr->fStatus &= ~NTF_HGHTCHG; - /* - * We need to force a resize here, because some applications - * try to get the rebar size during processing of the - * RBN_HEIGHTCHANGE notification. - */ - REBAR_ForceResize (infoPtr); - REBAR_Notify (&heightchange, infoPtr, RBN_HEIGHTCHANGE); - } - - /* native (from **1 above) does: - * UpdateWindow(rebar) - * REBAR_ForceResize - * RBN_HEIGHTCHANGE if necessary - * if ret from any EqualRect was 0 - * Goto "BeginDeferWindowPos" - */ - -} - - -static VOID -REBAR_Layout (REBAR_INFO *infoPtr, LPRECT lpRect, BOOL notify, BOOL resetclient) - /* Function: This routine is resposible for laying out all */ - /* the bands in a rebar. It assigns each band to a row and*/ - /* determines when to start a new row. */ -{ - REBAR_BAND *lpBand, *prevBand; - RECT rcClient, rcAdj; - INT initx, inity, x, y, cx, cxsep, mmcy, mcy, clientcx, clientcy; - INT adjcx, adjcy, row, rightx, bottomy, origheight; - UINT i, j, rowstart, origrows, cntonrow; - BOOL dobreak; - - if (!(infoPtr->fStatus & BAND_NEEDS_LAYOUT)) { - TRACE("no layout done. No band changed.\n"); - REBAR_DumpBand (infoPtr); - return; - } - infoPtr->fStatus &= ~BAND_NEEDS_LAYOUT; - if (!infoPtr->DoRedraw) infoPtr->fStatus |= BAND_NEEDS_REDRAW; - - GetClientRect (infoPtr->hwndSelf, &rcClient); - TRACE("Client is (%ld,%ld)-(%ld,%ld)\n", - rcClient.left, rcClient.top, rcClient.right, rcClient.bottom); - - if (lpRect) { - rcAdj = *lpRect; - TRACE("adjustment rect is (%ld,%ld)-(%ld,%ld)\n", - rcAdj.left, rcAdj.top, rcAdj.right, rcAdj.bottom); - } - else { - CopyRect (&rcAdj, &rcClient); - } - - clientcx = rcClient.right - rcClient.left; - clientcy = rcClient.bottom - rcClient.top; - adjcx = rcAdj.right - rcAdj.left; - adjcy = rcAdj.bottom - rcAdj.top; - if (resetclient) { - TRACE("window client rect will be set to adj rect\n"); - clientcx = adjcx; - clientcy = adjcy; - } - - if (!infoPtr->DoRedraw && (clientcx == 0) && (clientcy == 0)) { - ERR("no redraw and client is zero, skip layout\n"); - infoPtr->fStatus |= BAND_NEEDS_LAYOUT; - return; - } - - /* save height of original control */ - if (infoPtr->dwStyle & CCS_VERT) - origheight = infoPtr->calcSize.cx; - else - origheight = infoPtr->calcSize.cy; - origrows = infoPtr->uNumRows; - - initx = 0; - inity = 0; - - /* ******* Start Phase 1 - all bands on row at minimum size ******* */ - - TRACE("band loop constants, clientcx=%d, clientcy=%d, adjcx=%d, adjcy=%d\n", - clientcx, clientcy, adjcx, adjcy); - x = initx; - y = inity; - row = 1; - cx = 0; - mcy = 0; - rowstart = 0; - prevBand = NULL; - cntonrow = 0; - - for (i = 0; i < infoPtr->uNumBands; i++) { - lpBand = &infoPtr->bands[i]; - lpBand->fDraw = 0; - lpBand->iRow = row; - - SetRectEmpty(&lpBand->rcChevron); - - if (HIDDENBAND(lpBand)) continue; - - lpBand->rcoldBand = lpBand->rcBand; - - /* Set the offset of the child window */ - if ((lpBand->fMask & RBBIM_CHILD) && - !(lpBand->fStyle & RBBS_FIXEDSIZE)) { - lpBand->offChild.cx = ((lpBand->fStyle & RBBS_CHILDEDGE) ? 4 : 0); - } - lpBand->offChild.cy = ((lpBand->fStyle & RBBS_CHILDEDGE) ? 2 : 0); - - /* separator from previous band */ - cxsep = (cntonrow == 0) ? 0 : SEP_WIDTH; - cx = lpBand->lcx; - - if (infoPtr->dwStyle & CCS_VERT) - dobreak = (y + cx + cxsep > adjcy); - else - dobreak = (x + cx + cxsep > adjcx); - - /* This is the check for whether we need to start a new row */ - if ( ( (lpBand->fStyle & RBBS_BREAK) && (i != 0) ) || - ( ((infoPtr->dwStyle & CCS_VERT) ? (y != 0) : (x != 0)) && dobreak)) { - - for (j = rowstart; j < i; j++) { - REBAR_BAND *lpB; - lpB = &infoPtr->bands[j]; - if (infoPtr->dwStyle & CCS_VERT) { - lpB->rcBand.right = lpB->rcBand.left + mcy; - } - else { - lpB->rcBand.bottom = lpB->rcBand.top + mcy; - } - } - - TRACE("P1 Spliting to new row %d on band %u\n", row+1, i); - if (infoPtr->dwStyle & CCS_VERT) { - y = inity; - x += (mcy + SEP_WIDTH); - } - else { - x = initx; - y += (mcy + SEP_WIDTH); - } - - mcy = 0; - cxsep = 0; - row++; - lpBand->iRow = row; - prevBand = NULL; - rowstart = i; - cntonrow = 0; - } - - if (mcy < lpBand->lcy + REBARSPACE(lpBand)) - mcy = lpBand->lcy + REBARSPACE(lpBand); - - /* if boundary rect specified then limit mcy */ - if (lpRect) { - if (infoPtr->dwStyle & CCS_VERT) { - if (x+mcy > adjcx) { - mcy = adjcx - x; - TRACE("P1 row %u limiting mcy=%d, adjcx=%d, x=%d\n", - i, mcy, adjcx, x); - } - } - else { - if (y+mcy > adjcy) { - mcy = adjcy - y; - TRACE("P1 row %u limiting mcy=%d, adjcy=%d, y=%d\n", - i, mcy, adjcy, y); - } - } - } - - TRACE("P1 band %u, row %d, x=%d, y=%d, cxsep=%d, cx=%d\n", - i, row, - x, y, cxsep, cx); - if (infoPtr->dwStyle & CCS_VERT) { - /* bound the bottom side if we have a bounding rectangle */ - rightx = clientcx; - bottomy = (lpRect) ? min(clientcy, y+cxsep+cx) : y+cxsep+cx; - lpBand->rcBand.left = x; - lpBand->rcBand.right = x + min(mcy, - lpBand->lcy+REBARSPACE(lpBand)); - lpBand->rcBand.top = min(bottomy, y + cxsep); - lpBand->rcBand.bottom = bottomy; - lpBand->uMinHeight = lpBand->lcy; - y = bottomy; - } - else { - /* bound the right side if we have a bounding rectangle */ - rightx = (lpRect) ? min(clientcx, x+cxsep+cx) : x+cxsep+cx; - bottomy = clientcy; - lpBand->rcBand.left = min(rightx, x + cxsep); - lpBand->rcBand.right = rightx; - lpBand->rcBand.top = y; - lpBand->rcBand.bottom = y + min(mcy, - lpBand->lcy+REBARSPACE(lpBand)); - lpBand->uMinHeight = lpBand->lcy; - x = rightx; - } - TRACE("P1 band %u, row %d, (%ld,%ld)-(%ld,%ld)\n", - i, row, - lpBand->rcBand.left, lpBand->rcBand.top, - lpBand->rcBand.right, lpBand->rcBand.bottom); - prevBand = lpBand; - cntonrow++; - - } /* for (i = 0; i < infoPtr->uNumBands... */ - - if (infoPtr->dwStyle & CCS_VERT) - x += mcy; - else - y += mcy; - - for (j = rowstart; j < infoPtr->uNumBands; j++) { - lpBand = &infoPtr->bands[j]; - if (infoPtr->dwStyle & CCS_VERT) { - lpBand->rcBand.right = lpBand->rcBand.left + mcy; - } - else { - lpBand->rcBand.bottom = lpBand->rcBand.top + mcy; - } - } - - if (infoPtr->uNumBands) - infoPtr->uNumRows = row; - - /* ******* End Phase 1 - all bands on row at minimum size ******* */ - - - /* ******* Start Phase 1a - Adjust heights for RBS_VARHEIGHT off ******* */ - - mmcy = 0; - if (!(infoPtr->dwStyle & RBS_VARHEIGHT)) { - INT xy; - - /* get the max height of all bands */ - for (i=0; iuNumBands; i++) { - lpBand = &infoPtr->bands[i]; - if (HIDDENBAND(lpBand)) continue; - if (infoPtr->dwStyle & CCS_VERT) - mmcy = max(mmcy, lpBand->rcBand.right - lpBand->rcBand.left); - else - mmcy = max(mmcy, lpBand->rcBand.bottom - lpBand->rcBand.top); - } - - /* now adjust all rectangles by using the height found above */ - xy = 0; - row = 1; - for (i=0; iuNumBands; i++) { - lpBand = &infoPtr->bands[i]; - if (HIDDENBAND(lpBand)) continue; - if (lpBand->iRow != row) - xy += (mmcy + SEP_WIDTH); - if (infoPtr->dwStyle & CCS_VERT) { - lpBand->rcBand.left = xy; - lpBand->rcBand.right = xy + mmcy; - } - else { - lpBand->rcBand.top = xy; - lpBand->rcBand.bottom = xy + mmcy; - } - } - - /* set the x/y values to the correct maximum */ - if (infoPtr->dwStyle & CCS_VERT) - x = xy + mmcy; - else - y = xy + mmcy; - } - - /* ******* End Phase 1a - Adjust heights for RBS_VARHEIGHT off ******* */ - - - /* ******* Start Phase 2 - split rows till adjustment height full ******* */ - - /* assumes that the following variables contain: */ - /* y/x current height/width of all rows */ - if (lpRect) { - INT i, prev_rh, new_rh, adj_rh, prev_idx, current_idx; - REBAR_BAND *prev, *current, *walk; - UINT j; - -/* FIXME: problem # 2 */ - if (((infoPtr->dwStyle & CCS_VERT) ? -#if PROBLEM2 - (x < adjcx) : (y < adjcy) -#else - (adjcx - x > 5) : (adjcy - y > 4) -#endif - ) && - (infoPtr->uNumBands > 1)) { - for (i=(INT)infoPtr->uNumBands-2; i>=0; i--) { - TRACE("P2 adjcx=%d, adjcy=%d, x=%d, y=%d\n", - adjcx, adjcy, x, y); - - /* find the current band (starts at i+1) */ - current = &infoPtr->bands[i+1]; - current_idx = i+1; - while (HIDDENBAND(current)) { - i--; - if (i < 0) break; /* out of bands */ - current = &infoPtr->bands[i+1]; - current_idx = i+1; - } - if (i < 0) break; /* out of bands */ - - /* now find the prev band (starts at i) */ - prev = &infoPtr->bands[i]; - prev_idx = i; - while (HIDDENBAND(prev)) { - i--; - if (i < 0) break; /* out of bands */ - prev = &infoPtr->bands[i]; - prev_idx = i; - } - if (i < 0) break; /* out of bands */ - - prev_rh = ircBw(prev); - if (prev->iRow == current->iRow) { - new_rh = (infoPtr->dwStyle & RBS_VARHEIGHT) ? - current->lcy + REBARSPACE(current) : - mmcy; - adj_rh = new_rh + SEP_WIDTH; - infoPtr->uNumRows++; - current->fDraw |= NTF_INVALIDATE; - current->iRow++; - if (infoPtr->dwStyle & CCS_VERT) { - current->rcBand.top = inity; - current->rcBand.bottom = clientcy; - current->rcBand.left += (prev_rh + SEP_WIDTH); - current->rcBand.right = current->rcBand.left + new_rh; - x += adj_rh; - } - else { - current->rcBand.left = initx; - current->rcBand.right = clientcx; - current->rcBand.top += (prev_rh + SEP_WIDTH); - current->rcBand.bottom = current->rcBand.top + new_rh; - y += adj_rh; - } - TRACE("P2 moving band %d to own row at (%ld,%ld)-(%ld,%ld)\n", - current_idx, - current->rcBand.left, current->rcBand.top, - current->rcBand.right, current->rcBand.bottom); - TRACE("P2 prev band %d at (%ld,%ld)-(%ld,%ld)\n", - prev_idx, - prev->rcBand.left, prev->rcBand.top, - prev->rcBand.right, prev->rcBand.bottom); - TRACE("P2 values: prev_rh=%d, new_rh=%d, adj_rh=%d\n", - prev_rh, new_rh, adj_rh); - /* for bands below current adjust row # and top/bottom */ - for (j = current_idx+1; juNumBands; j++) { - walk = &infoPtr->bands[j]; - if (HIDDENBAND(walk)) continue; - walk->fDraw |= NTF_INVALIDATE; - walk->iRow++; - if (infoPtr->dwStyle & CCS_VERT) { - walk->rcBand.left += adj_rh; - walk->rcBand.right += adj_rh; - } - else { - walk->rcBand.top += adj_rh; - walk->rcBand.bottom += adj_rh; - } - } - if ((infoPtr->dwStyle & CCS_VERT) ? (x >= adjcx) : (y >= adjcy)) - break; /* all done */ - } - } - } - } - - /* ******* End Phase 2 - split rows till adjustment height full ******* */ - - - /* ******* Start Phase 2a - mark first and last band in each ******* */ - - prevBand = NULL; - for (i = 0; i < infoPtr->uNumBands; i++) { - lpBand = &infoPtr->bands[i]; - if (HIDDENBAND(lpBand)) - continue; - if( !prevBand ) { - lpBand->fDraw |= DRAW_FIRST_IN_ROW; - prevBand = lpBand; - } - else if( prevBand->iRow == lpBand->iRow ) - prevBand = lpBand; - else { - prevBand->fDraw |= DRAW_LAST_IN_ROW; - lpBand->fDraw |= DRAW_FIRST_IN_ROW; - prevBand = lpBand; - } - } - if( prevBand ) - prevBand->fDraw |= DRAW_LAST_IN_ROW; - - /* ******* End Phase 2a - mark first and last band in each ******* */ - - - /* ******* Start Phase 2b - adjust all bands for height full ******* */ - /* assumes that the following variables contain: */ - /* y/x current height/width of all rows */ - /* clientcy/clientcx height/width of client area */ - - if (((infoPtr->dwStyle & CCS_VERT) ? clientcx > x : clientcy > y) && - infoPtr->uNumBands) { - INT diff, i; - UINT j; - - diff = (infoPtr->dwStyle & CCS_VERT) ? clientcx - x : clientcy - y; - - /* iterate backwards thru the rows */ - for (i = infoPtr->uNumBands-1; i>=0; i--) { - lpBand = &infoPtr->bands[i]; - if(HIDDENBAND(lpBand)) continue; - - /* if row has more than 1 band, ignore it */ - if( !(lpBand->fDraw&DRAW_FIRST_IN_ROW) ) - continue; - if( !(lpBand->fDraw&DRAW_LAST_IN_ROW) ) - continue; - - if (lpBand->fMask & RBBS_VARIABLEHEIGHT) continue; - if (((INT)lpBand->cyMaxChild < 1) || - ((INT)lpBand->cyIntegral < 1)) { - if (lpBand->cyMaxChild + lpBand->cyIntegral == 0) continue; - ERR("P2b band %u RBBS_VARIABLEHEIGHT set but cyMax=%d, cyInt=%d\n", - i, lpBand->cyMaxChild, lpBand->cyIntegral); - continue; - } - /* j is now the maximum height/width in the client area */ - j = ((diff / lpBand->cyIntegral) * lpBand->cyIntegral) + - ircBw(lpBand); - if (j > lpBand->cyMaxChild + REBARSPACE(lpBand)) - j = lpBand->cyMaxChild + REBARSPACE(lpBand); - diff -= (j - ircBw(lpBand)); - if (infoPtr->dwStyle & CCS_VERT) - lpBand->rcBand.right = lpBand->rcBand.left + j; - else - lpBand->rcBand.bottom = lpBand->rcBand.top + j; - TRACE("P2b band %d, row %d changed to (%ld,%ld)-(%ld,%ld)\n", - i, lpBand->iRow, - lpBand->rcBand.left, lpBand->rcBand.top, - lpBand->rcBand.right, lpBand->rcBand.bottom); - if (diff <= 0) break; - } - if (diff < 0) { - ERR("P2b allocated more than available, diff=%d\n", diff); - diff = 0; - } - if (infoPtr->dwStyle & CCS_VERT) - x = clientcx - diff; - else - y = clientcy - diff; - } - - /* ******* End Phase 2b - adjust all bands for height full ******* */ - - - /* ******* Start Phase 3 - adjust all bands for width full ******* */ - - if (infoPtr->uNumBands) { - int startband; - - /* If RBS_BANDBORDERS set then indicate to draw bottom separator */ - /* on all bands in all rows but last row. */ - /* Also indicate to draw the right separator for each band in */ - /* each row but the rightmost band. */ - if (infoPtr->dwStyle & RBS_BANDBORDERS) { - - for (i=0; iuNumBands; i++) { - lpBand = &infoPtr->bands[i]; - if (HIDDENBAND(lpBand)) - continue; - - /* not righthand bands */ - if( !(lpBand->fDraw & DRAW_LAST_IN_ROW) ) - lpBand->fDraw |= DRAW_RIGHTSEP; - - /* not the last row */ - if( lpBand->iRow != infoPtr->uNumRows ) - lpBand->fDraw |= DRAW_BOTTOMSEP; - } - } - - /* Distribute the extra space on the horizontal and adjust */ - /* all bands in row to same height. */ - mcy = 0; - startband = -1; - for (i=0; iuNumBands; i++) { - - lpBand = &infoPtr->bands[i]; - - if( lpBand->fDraw & DRAW_FIRST_IN_ROW ) - { - startband = i; - mcy = 0; - } - - if ( (mcy < ircBw(lpBand)) && !HIDDENBAND(lpBand) ) - mcy = ircBw(lpBand); - - if( lpBand->fDraw & DRAW_LAST_IN_ROW ) - { - TRACE("P3 processing row %d, starting band %d, ending band %d\n", - lpBand->iRow, startband, i); - if( startband < 0 ) - ERR("Last band %d with no first, row %d\n", i, lpBand->iRow); - - REBAR_AdjustBands (infoPtr, startband, i, - (infoPtr->dwStyle & CCS_VERT) ? - clientcy : clientcx, mcy); - } - } - - /* Calculate the other rectangles in each band */ - if (infoPtr->dwStyle & CCS_VERT) { - REBAR_CalcVertBand (infoPtr, 0, infoPtr->uNumBands, - notify); - } - else { - REBAR_CalcHorzBand (infoPtr, 0, infoPtr->uNumBands, - notify); - } - } - - /* ******* End Phase 3 - adjust all bands for width full ******* */ - - /* now compute size of Rebar itself */ - infoPtr->oldSize = infoPtr->calcSize; - if (infoPtr->uNumBands == 0) { - /* we have no bands, so make size the size of client */ - x = clientcx; - y = clientcy; - } - if (infoPtr->dwStyle & CCS_VERT) { - if( x < REBAR_MINSIZE ) - x = REBAR_MINSIZE; - infoPtr->calcSize.cx = x; - infoPtr->calcSize.cy = clientcy; - TRACE("vert, notify=%d, x=%d, origheight=%d\n", - notify, x, origheight); - if (notify && (x != origheight)) infoPtr->fStatus |= NTF_HGHTCHG; - } - else { - if( y < REBAR_MINSIZE ) - y = REBAR_MINSIZE; - infoPtr->calcSize.cx = clientcx; - infoPtr->calcSize.cy = y; - TRACE("horz, notify=%d, y=%d, origheight=%d\n", - notify, y, origheight); - if (notify && (y != origheight)) infoPtr->fStatus |= NTF_HGHTCHG; - } - - REBAR_DumpBand (infoPtr); - - REBAR_MoveChildWindows (infoPtr, 0, infoPtr->uNumBands); - - REBAR_ForceResize (infoPtr); -} - - -static VOID -REBAR_ValidateBand (REBAR_INFO *infoPtr, REBAR_BAND *lpBand) - /* Function: This routine evaluates the band specs supplied */ - /* by the user and updates the following 5 fields in */ - /* the internal band structure: cxHeader, lcx, lcy, hcx, hcy*/ -{ - UINT header=0; - UINT textheight=0; - UINT i, nonfixed; - REBAR_BAND *tBand; - - lpBand->fStatus = 0; - lpBand->lcx = 0; - lpBand->lcy = 0; - lpBand->ccx = 0; - lpBand->ccy = 0; - lpBand->hcx = 0; - lpBand->hcy = 0; - - /* Data comming in from users into the cx... and cy... fields */ - /* may be bad, just garbage, because the user never clears */ - /* the fields. RB_{SET|INSERT}BAND{A|W} just passes the data */ - /* along if the fields exist in the input area. Here we must */ - /* determine if the data is valid. I have no idea how MS does */ - /* the validation, but it does because the RB_GETBANDINFO */ - /* returns a 0 when I know the sample program passed in an */ - /* address. Here I will use the algorithim that if the value */ - /* is greater than 65535 then it is bad and replace it with */ - /* a zero. Feel free to improve the algorithim. - GA 12/2000 */ - if (lpBand->cxMinChild > 65535) lpBand->cxMinChild = 0; - if (lpBand->cyMinChild > 65535) lpBand->cyMinChild = 0; - if (lpBand->cx > 65535) lpBand->cx = 0; - if (lpBand->cyChild > 65535) lpBand->cyChild = 0; - if (lpBand->cyMaxChild > 65535) lpBand->cyMaxChild = 0; - if (lpBand->cyIntegral > 65535) lpBand->cyIntegral = 0; - if (lpBand->cxIdeal > 65535) lpBand->cxIdeal = 0; - if (lpBand->cxHeader > 65535) lpBand->cxHeader = 0; - - /* FIXME: probably should only set NEEDS_LAYOUT flag when */ - /* values change. Till then always set it. */ - TRACE("setting NEEDS_LAYOUT\n"); - infoPtr->fStatus |= BAND_NEEDS_LAYOUT; - - /* Header is where the image, text and gripper exist */ - /* in the band and preceed the child window. */ - - /* count number of non-FIXEDSIZE and non-Hidden bands */ - nonfixed = 0; - for (i=0; iuNumBands; i++){ - tBand = &infoPtr->bands[i]; - if (!HIDDENBAND(tBand) && !(tBand->fStyle & RBBS_FIXEDSIZE)) - nonfixed++; - } - - /* calculate gripper rectangle */ - if ( (!(lpBand->fStyle & RBBS_NOGRIPPER)) && - ( (lpBand->fStyle & RBBS_GRIPPERALWAYS) || - ( !(lpBand->fStyle & RBBS_FIXEDSIZE) && (nonfixed > 1))) - ) { - lpBand->fStatus |= HAS_GRIPPER; - if (infoPtr->dwStyle & CCS_VERT) - if (infoPtr->dwStyle & RBS_VERTICALGRIPPER) - header += (GRIPPER_HEIGHT + REBAR_PRE_GRIPPER); - else - header += (GRIPPER_WIDTH + REBAR_PRE_GRIPPER); - else - header += (REBAR_PRE_GRIPPER + GRIPPER_WIDTH); - /* Always have 4 pixels before anything else */ - header += REBAR_ALWAYS_SPACE; - } - - /* image is visible */ - if ((lpBand->fMask & RBBIM_IMAGE) && (infoPtr->himl)) { - lpBand->fStatus |= HAS_IMAGE; - if (infoPtr->dwStyle & CCS_VERT) { - header += (infoPtr->imageSize.cy + REBAR_POST_IMAGE); - lpBand->lcy = infoPtr->imageSize.cx + 2; - } - else { - header += (infoPtr->imageSize.cx + REBAR_POST_IMAGE); - lpBand->lcy = infoPtr->imageSize.cy + 2; - } - } - - /* text is visible */ - if ((lpBand->fMask & RBBIM_TEXT) && (lpBand->lpText) && - !(lpBand->fStyle & RBBS_HIDETITLE)) { - HDC hdc = GetDC (0); - HFONT hOldFont = SelectObject (hdc, infoPtr->hFont); - SIZE size; - - lpBand->fStatus |= HAS_TEXT; - GetTextExtentPoint32W (hdc, lpBand->lpText, - lstrlenW (lpBand->lpText), &size); - header += ((infoPtr->dwStyle & CCS_VERT) ? (size.cy + REBAR_POST_TEXT) : (size.cx + REBAR_POST_TEXT)); - textheight = (infoPtr->dwStyle & CCS_VERT) ? 0 : size.cy; - - SelectObject (hdc, hOldFont); - ReleaseDC (0, hdc); - } - - /* if no gripper but either image or text, then leave space */ - if ((lpBand->fStatus & (HAS_IMAGE | HAS_TEXT)) && - !(lpBand->fStatus & HAS_GRIPPER)) { - header += REBAR_ALWAYS_SPACE; - } - - /* check if user overrode the header value */ - if (!(lpBand->fMask & RBBIM_HEADERSIZE)) - lpBand->cxHeader = header; - - - /* Now compute minimum size of child window */ - lpBand->offChild.cx = 0; - lpBand->offChild.cy = 0; - lpBand->lcy = textheight; - lpBand->ccy = lpBand->lcy; - if (lpBand->fMask & RBBIM_CHILDSIZE) { - lpBand->lcx = lpBand->cxMinChild; - - /* Set the .cy values for CHILDSIZE case */ - lpBand->lcy = max(lpBand->lcy, lpBand->cyMinChild); - lpBand->ccy = lpBand->lcy; - lpBand->hcy = lpBand->lcy; - if (lpBand->cyMaxChild != 0xffffffff) { - lpBand->hcy = lpBand->cyMaxChild; - } - if (lpBand->cyChild != 0xffffffff) - lpBand->ccy = max (lpBand->cyChild, lpBand->lcy); - - TRACE("_CHILDSIZE\n"); - } - if (lpBand->fMask & RBBIM_SIZE) { - lpBand->hcx = max (lpBand->cx-lpBand->cxHeader, lpBand->lcx); - TRACE("_SIZE\n"); - } - else - lpBand->hcx = lpBand->lcx; - lpBand->ccx = lpBand->hcx; - - /* make ->.cx include header size for _Layout */ - lpBand->lcx += lpBand->cxHeader; - lpBand->ccx += lpBand->cxHeader; - lpBand->hcx += lpBand->cxHeader; - -} - -static BOOL -REBAR_CommonSetupBand (HWND hwnd, LPREBARBANDINFOA lprbbi, REBAR_BAND *lpBand) - /* Function: This routine copies the supplied values from */ - /* user input (lprbbi) to the internal band structure. */ - /* It returns true if something changed and false if not. */ -{ - BOOL bChanged = FALSE; - - lpBand->fMask |= lprbbi->fMask; - - if( (lprbbi->fMask & RBBIM_STYLE) && - (lpBand->fStyle != lprbbi->fStyle ) ) - { - lpBand->fStyle = lprbbi->fStyle; - bChanged = TRUE; - } - - if( (lprbbi->fMask & RBBIM_COLORS) && - ( ( lpBand->clrFore != lprbbi->clrFore ) || - ( lpBand->clrBack != lprbbi->clrBack ) ) ) - { - lpBand->clrFore = lprbbi->clrFore; - lpBand->clrBack = lprbbi->clrBack; - bChanged = TRUE; - } - - if( (lprbbi->fMask & RBBIM_IMAGE) && - ( lpBand->iImage != lprbbi->iImage ) ) - { - lpBand->iImage = lprbbi->iImage; - bChanged = TRUE; - } - - if( (lprbbi->fMask & RBBIM_CHILD) && - (lprbbi->hwndChild != lpBand->hwndChild ) ) - { - if (lprbbi->hwndChild) { - lpBand->hwndChild = lprbbi->hwndChild; - lpBand->hwndPrevParent = - SetParent (lpBand->hwndChild, hwnd); - /* below in trace fro WinRAR */ - ShowWindow(lpBand->hwndChild, SW_SHOWNOACTIVATE | SW_SHOWNORMAL); - /* above in trace fro WinRAR */ - } - else { - TRACE("child: %p prev parent: %p\n", - lpBand->hwndChild, lpBand->hwndPrevParent); - lpBand->hwndChild = 0; - lpBand->hwndPrevParent = 0; - } - bChanged = TRUE; - } - - if( (lprbbi->fMask & RBBIM_CHILDSIZE) && - ( (lpBand->cxMinChild != lprbbi->cxMinChild) || - (lpBand->cyMinChild != lprbbi->cyMinChild ) || - ( (lprbbi->cbSize >= sizeof (REBARBANDINFOA)) && - ( (lpBand->cyChild != lprbbi->cyChild ) || - (lpBand->cyMaxChild != lprbbi->cyMaxChild ) || - (lpBand->cyIntegral != lprbbi->cyIntegral ) ) ) || - ( (lprbbi->cbSize < sizeof (REBARBANDINFOA)) && - ( (lpBand->cyChild || - lpBand->cyMaxChild || - lpBand->cyIntegral ) ) ) ) ) - { - lpBand->cxMinChild = lprbbi->cxMinChild; - lpBand->cyMinChild = lprbbi->cyMinChild; - if (lprbbi->cbSize >= sizeof (REBARBANDINFOA)) { - lpBand->cyChild = lprbbi->cyChild; - lpBand->cyMaxChild = lprbbi->cyMaxChild; - lpBand->cyIntegral = lprbbi->cyIntegral; - } - else { /* special case - these should be zeroed out since */ - /* RBBIM_CHILDSIZE added these in WIN32_IE >= 0x0400 */ - lpBand->cyChild = 0; - lpBand->cyMaxChild = 0; - lpBand->cyIntegral = 0; - } - bChanged = TRUE; - } - - if( (lprbbi->fMask & RBBIM_SIZE) && - (lpBand->cx != lprbbi->cx ) ) - { - lpBand->cx = lprbbi->cx; - bChanged = TRUE; - } - - if( (lprbbi->fMask & RBBIM_BACKGROUND) && - ( lpBand->hbmBack != lprbbi->hbmBack ) ) - { - lpBand->hbmBack = lprbbi->hbmBack; - bChanged = TRUE; - } - - if( (lprbbi->fMask & RBBIM_ID) && - (lpBand->wID != lprbbi->wID ) ) - { - lpBand->wID = lprbbi->wID; - bChanged = TRUE; - } - - /* check for additional data */ - if (lprbbi->cbSize >= sizeof (REBARBANDINFOA)) { - if( (lprbbi->fMask & RBBIM_IDEALSIZE) && - ( lpBand->cxIdeal != lprbbi->cxIdeal ) ) - { - lpBand->cxIdeal = lprbbi->cxIdeal; - bChanged = TRUE; - } - - if( (lprbbi->fMask & RBBIM_LPARAM) && - (lpBand->lParam != lprbbi->lParam ) ) - { - lpBand->lParam = lprbbi->lParam; - bChanged = TRUE; - } - - if( (lprbbi->fMask & RBBIM_HEADERSIZE) && - (lpBand->cxHeader != lprbbi->cxHeader ) ) - { - lpBand->cxHeader = lprbbi->cxHeader; - bChanged = TRUE; - } - } - - return bChanged; -} - -static LRESULT -REBAR_InternalEraseBkGnd (REBAR_INFO *infoPtr, WPARAM wParam, LPARAM lParam, RECT *clip) - /* Function: This erases the background rectangle by drawing */ - /* each band with its background color (or the default) and */ - /* draws each bands right separator if necessary. The row */ - /* separators are drawn on the first band of the next row. */ -{ - REBAR_BAND *lpBand; - UINT i; - INT oldrow; - HDC hdc = (HDC)wParam; - RECT rect; - COLORREF old = CLR_NONE, new; - - oldrow = -1; - for(i=0; iuNumBands; i++) { - lpBand = &infoPtr->bands[i]; - if (HIDDENBAND(lpBand)) continue; - - /* draw band separator between rows */ - if (lpBand->iRow != oldrow) { - oldrow = lpBand->iRow; - if (lpBand->fDraw & DRAW_BOTTOMSEP) { - RECT rcRowSep; - rcRowSep = lpBand->rcBand; - if (infoPtr->dwStyle & CCS_VERT) { - rcRowSep.right += SEP_WIDTH_SIZE; - rcRowSep.bottom = infoPtr->calcSize.cy; - DrawEdge (hdc, &rcRowSep, EDGE_ETCHED, BF_RIGHT); - } - else { - rcRowSep.bottom += SEP_WIDTH_SIZE; - rcRowSep.right = infoPtr->calcSize.cx; - DrawEdge (hdc, &rcRowSep, EDGE_ETCHED, BF_BOTTOM); - } - TRACE ("drawing band separator bottom (%ld,%ld)-(%ld,%ld)\n", - rcRowSep.left, rcRowSep.top, - rcRowSep.right, rcRowSep.bottom); - } - } - - /* draw band separator between bands in a row */ - if (lpBand->fDraw & DRAW_RIGHTSEP) { - RECT rcSep; - rcSep = lpBand->rcBand; - if (infoPtr->dwStyle & CCS_VERT) { - rcSep.bottom += SEP_WIDTH_SIZE; - DrawEdge (hdc, &rcSep, EDGE_ETCHED, BF_BOTTOM); - } - else { - rcSep.right += SEP_WIDTH_SIZE; - DrawEdge (hdc, &rcSep, EDGE_ETCHED, BF_RIGHT); - } - TRACE("drawing band separator right (%ld,%ld)-(%ld,%ld)\n", - rcSep.left, rcSep.top, rcSep.right, rcSep.bottom); - } - - /* draw the actual background */ - if (lpBand->clrBack != CLR_NONE) { - new = (lpBand->clrBack == CLR_DEFAULT) ? infoPtr->clrBtnFace : - lpBand->clrBack; -#if GLATESTING - /* testing only - make background green to see it */ - new = RGB(0,128,0); -#endif - } - else { - /* In the absence of documentation for Rebar vs. CLR_NONE, - * we will use the default BtnFace color. Note documentation - * exists for Listview and Imagelist. - */ - new = infoPtr->clrBtnFace; -#if GLATESTING - /* testing only - make background green to see it */ - new = RGB(0,128,0); -#endif - } - old = SetBkColor (hdc, new); - - rect = lpBand->rcBand; - TRACE("%s background color=0x%06lx, band (%ld,%ld)-(%ld,%ld), clip (%ld,%ld)-(%ld,%ld)\n", - (lpBand->clrBack == CLR_NONE) ? "none" : - ((lpBand->clrBack == CLR_DEFAULT) ? "dft" : ""), - GetBkColor(hdc), - lpBand->rcBand.left,lpBand->rcBand.top, - lpBand->rcBand.right,lpBand->rcBand.bottom, - clip->left, clip->top, - clip->right, clip->bottom); - ExtTextOutA (hdc, 0, 0, ETO_OPAQUE, &rect, NULL, 0, 0); - if (lpBand->clrBack != CLR_NONE) - SetBkColor (hdc, old); - } - return TRUE; -} - -static void -REBAR_InternalHitTest (REBAR_INFO *infoPtr, const LPPOINT lpPt, UINT *pFlags, INT *pBand) -{ - REBAR_BAND *lpBand; - RECT rect; - UINT iCount; - - GetClientRect (infoPtr->hwndSelf, &rect); - - *pFlags = RBHT_NOWHERE; - if (PtInRect (&rect, *lpPt)) - { - if (infoPtr->uNumBands == 0) { - *pFlags = RBHT_NOWHERE; - if (pBand) - *pBand = -1; - TRACE("NOWHERE\n"); - return; - } - else { - /* somewhere inside */ - for (iCount = 0; iCount < infoPtr->uNumBands; iCount++) { - lpBand = &infoPtr->bands[iCount]; - if (HIDDENBAND(lpBand)) continue; - if (PtInRect (&lpBand->rcBand, *lpPt)) { - if (pBand) - *pBand = iCount; - if (PtInRect (&lpBand->rcGripper, *lpPt)) { - *pFlags = RBHT_GRABBER; - TRACE("ON GRABBER %d\n", iCount); - return; - } - else if (PtInRect (&lpBand->rcCapImage, *lpPt)) { - *pFlags = RBHT_CAPTION; - TRACE("ON CAPTION %d\n", iCount); - return; - } - else if (PtInRect (&lpBand->rcCapText, *lpPt)) { - *pFlags = RBHT_CAPTION; - TRACE("ON CAPTION %d\n", iCount); - return; - } - else if (PtInRect (&lpBand->rcChild, *lpPt)) { - *pFlags = RBHT_CLIENT; - TRACE("ON CLIENT %d\n", iCount); - return; - } - else if (PtInRect (&lpBand->rcChevron, *lpPt)) { - *pFlags = RBHT_CHEVRON; - TRACE("ON CHEVRON %d\n", iCount); - return; - } - else { - *pFlags = RBHT_NOWHERE; - TRACE("NOWHERE %d\n", iCount); - return; - } - } - } - - *pFlags = RBHT_NOWHERE; - if (pBand) - *pBand = -1; - - TRACE("NOWHERE\n"); - return; - } - } - else { - *pFlags = RBHT_NOWHERE; - if (pBand) - *pBand = -1; - TRACE("NOWHERE\n"); - return; - } -} - - -static INT -REBAR_Shrink (REBAR_INFO *infoPtr, REBAR_BAND *band, INT movement, INT i) - /* Function: This attempts to shrink the given band by the */ - /* the amount in "movement". A shrink to the left is indi- */ - /* cated by "movement" being negative. "i" is merely the */ - /* band index for trace messages. */ -{ - INT Leadjust, Readjust, avail, ret; - - /* Note: a left drag is indicated by "movement" being negative. */ - /* Similarly, a right drag is indicated by "movement" */ - /* being positive. "movement" should never be 0, but if */ - /* it is then the band does not move. */ - - avail = rcBw(band) - band->lcx; - - /* now compute the Left End adjustment factor and Right End */ - /* adjustment factor. They may be different if shrinking. */ - if (avail <= 0) { - /* if this band is not shrinkable, then just move it */ - Leadjust = Readjust = movement; - ret = movement; - } - else { - if (movement < 0) { - /* Drag to left */ - if (avail <= abs(movement)) { - Readjust = movement; - Leadjust = movement + avail; - ret = Leadjust; - } - else { - Readjust = movement; - Leadjust = 0; - ret = 0; - } - } - else { - /* Drag to right */ - if (avail <= abs(movement)) { - Leadjust = movement; - Readjust = movement - avail; - ret = Readjust; - } - else { - Leadjust = movement; - Readjust = 0; - ret = 0; - } - } - } - - /* Reasonability Check */ - if (rcBlt(band) + Leadjust < 0) { - ERR("adjustment will fail, band %d: left=%d, right=%d, move=%d, rtn=%d\n", - i, Leadjust, Readjust, movement, ret); - } - - LEADJ(band, Leadjust); - READJ(band, Readjust); - - TRACE("band %d: left=%d, right=%d, move=%d, rtn=%d, rcBand=(%ld,%ld)-(%ld,%ld)\n", - i, Leadjust, Readjust, movement, ret, - band->rcBand.left, band->rcBand.top, - band->rcBand.right, band->rcBand.bottom); - return ret; -} - - -static void -REBAR_HandleLRDrag (REBAR_INFO *infoPtr, const POINT *ptsmove) - /* Function: This will implement the functionality of a */ - /* Gripper drag within a row. It will not implement "out- */ - /* of-row" drags. (They are detected and handled in */ - /* REBAR_MouseMove.) */ - /* **** FIXME Switching order of bands in a row not **** */ - /* **** yet implemented. **** */ -{ - REBAR_BAND *hitBand, *band, *mindBand, *maxdBand; - RECT newrect; - INT imindBand = -1, imaxdBand, ihitBand, i, movement; - INT RHeaderSum = 0, LHeaderSum = 0; - INT compress; - - /* on first significant mouse movement, issue notify */ - - if (!(infoPtr->fStatus & BEGIN_DRAG_ISSUED)) { - if (REBAR_Notify_NMREBAR (infoPtr, -1, RBN_BEGINDRAG)) { - /* Notify returned TRUE - abort drag */ - infoPtr->dragStart.x = 0; - infoPtr->dragStart.y = 0; - infoPtr->dragNow = infoPtr->dragStart; - infoPtr->iGrabbedBand = -1; - ReleaseCapture (); - return ; - } - infoPtr->fStatus |= BEGIN_DRAG_ISSUED; - } - - ihitBand = infoPtr->iGrabbedBand; - hitBand = &infoPtr->bands[ihitBand]; - imaxdBand = ihitBand; /* to suppress warning message */ - - /* find all the bands in the row of the one whose Gripper was seized */ - for (i=0; iuNumBands; i++) { - band = &infoPtr->bands[i]; - if (HIDDENBAND(band)) continue; - if (band->iRow == hitBand->iRow) { - imaxdBand = i; - if (imindBand == -1) imindBand = i; - /* minimum size of each band is size of header plus */ - /* size of minimum child plus offset of child from header plus */ - /* a one to separate each band. */ - if (i < ihitBand) - LHeaderSum += (band->lcx + SEP_WIDTH); - else - RHeaderSum += (band->lcx + SEP_WIDTH); - - } - } - if (RHeaderSum) RHeaderSum -= SEP_WIDTH; /* no separator after last band */ - - mindBand = &infoPtr->bands[imindBand]; - maxdBand = &infoPtr->bands[imaxdBand]; - - if (imindBand == imaxdBand) return; /* nothing to drag against */ - if (imindBand == ihitBand) return; /* first band in row, can't drag */ - - /* limit movement to inside adjustable bands - Left */ - if ( (ptsmove->x < mindBand->rcBand.left) || - (ptsmove->x > maxdBand->rcBand.right) || - (ptsmove->y < mindBand->rcBand.top) || - (ptsmove->y > maxdBand->rcBand.bottom)) - return; /* should swap bands */ - - if (infoPtr->dwStyle & CCS_VERT) - movement = ptsmove->y - ((hitBand->rcBand.top+REBAR_PRE_GRIPPER) - - infoPtr->ihitoffset); - else - movement = ptsmove->x - ((hitBand->rcBand.left+REBAR_PRE_GRIPPER) - - infoPtr->ihitoffset); - infoPtr->dragNow = *ptsmove; - - TRACE("before: movement=%d (%ld,%ld), imindBand=%d, ihitBand=%d, imaxdBand=%d, LSum=%d, RSum=%d\n", - movement, ptsmove->x, ptsmove->y, imindBand, ihitBand, - imaxdBand, LHeaderSum, RHeaderSum); - REBAR_DumpBand (infoPtr); - - if (movement < 0) { - - /* *** Drag left/up *** */ - compress = rcBlt(hitBand) - rcBlt(mindBand) - - LHeaderSum; - if (compress < abs(movement)) { - TRACE("limiting left drag, was %d changed to %d\n", - movement, -compress); - movement = -compress; - } - - for (i=ihitBand; i>=imindBand; i--) { - band = &infoPtr->bands[i]; - if (HIDDENBAND(band)) continue; - if (i == ihitBand) { - LEADJ(band, movement); - } - else - movement = REBAR_Shrink (infoPtr, band, movement, i); - band->ccx = rcBw(band); - } - } - else { - BOOL first = TRUE; - - /* *** Drag right/down *** */ - compress = rcBrb(maxdBand) - rcBlt(hitBand) - - RHeaderSum; - if (compress < abs(movement)) { - TRACE("limiting right drag, was %d changed to %d\n", - movement, compress); - movement = compress; - } - for (i=ihitBand-1; i<=imaxdBand; i++) { - band = &infoPtr->bands[i]; - if (HIDDENBAND(band)) continue; - if (first) { - first = FALSE; - READJ(band, movement); - } - else - movement = REBAR_Shrink (infoPtr, band, movement, i); - band->ccx = rcBw(band); - } - } - - /* recompute all rectangles */ - if (infoPtr->dwStyle & CCS_VERT) { - REBAR_CalcVertBand (infoPtr, imindBand, imaxdBand+1, - FALSE); - } - else { - REBAR_CalcHorzBand (infoPtr, imindBand, imaxdBand+1, - FALSE); - } - - TRACE("bands after adjustment, see band # %d, %d\n", - imindBand, imaxdBand); - REBAR_DumpBand (infoPtr); - - SetRect (&newrect, - mindBand->rcBand.left, - mindBand->rcBand.top, - maxdBand->rcBand.right, - maxdBand->rcBand.bottom); - - REBAR_MoveChildWindows (infoPtr, imindBand, imaxdBand+1); - - InvalidateRect (infoPtr->hwndSelf, &newrect, TRUE); - UpdateWindow (infoPtr->hwndSelf); - -} - - - -/* << REBAR_BeginDrag >> */ - - -static LRESULT -REBAR_DeleteBand (REBAR_INFO *infoPtr, WPARAM wParam, LPARAM lParam) -{ - UINT uBand = (UINT)wParam; - HWND childhwnd = 0; - REBAR_BAND *lpBand; - - if (uBand >= infoPtr->uNumBands) - return FALSE; - - TRACE("deleting band %u!\n", uBand); - lpBand = &infoPtr->bands[uBand]; - REBAR_Notify_NMREBAR (infoPtr, uBand, RBN_DELETINGBAND); - - if (infoPtr->uNumBands == 1) { - TRACE(" simple delete!\n"); - if ((lpBand->fMask & RBBIM_CHILD) && lpBand->hwndChild) - childhwnd = lpBand->hwndChild; - Free (infoPtr->bands); - infoPtr->bands = NULL; - infoPtr->uNumBands = 0; - } - else { - REBAR_BAND *oldBands = infoPtr->bands; - TRACE("complex delete! [uBand=%u]\n", uBand); - - if ((lpBand->fMask & RBBIM_CHILD) && lpBand->hwndChild) - childhwnd = lpBand->hwndChild; - - infoPtr->uNumBands--; - infoPtr->bands = Alloc (sizeof (REBAR_BAND) * infoPtr->uNumBands); - if (uBand > 0) { - memcpy (&infoPtr->bands[0], &oldBands[0], - uBand * sizeof(REBAR_BAND)); - } - - if (uBand < infoPtr->uNumBands) { - memcpy (&infoPtr->bands[uBand], &oldBands[uBand+1], - (infoPtr->uNumBands - uBand) * sizeof(REBAR_BAND)); - } - - Free (oldBands); - } - - if (childhwnd) - ShowWindow (childhwnd, SW_HIDE); - - REBAR_Notify_NMREBAR (infoPtr, -1, RBN_DELETEDBAND); - - /* if only 1 band left the re-validate to possible eliminate gripper */ - if (infoPtr->uNumBands == 1) - REBAR_ValidateBand (infoPtr, &infoPtr->bands[0]); - - TRACE("setting NEEDS_LAYOUT\n"); - infoPtr->fStatus |= BAND_NEEDS_LAYOUT; - infoPtr->fStatus |= RESIZE_ANYHOW; - REBAR_Layout (infoPtr, NULL, TRUE, FALSE); - - return TRUE; -} - - -/* << REBAR_DragMove >> */ -/* << REBAR_EndDrag >> */ - - -static LRESULT -REBAR_GetBandBorders (REBAR_INFO *infoPtr, WPARAM wParam, LPARAM lParam) -{ - LPRECT lpRect = (LPRECT)lParam; - REBAR_BAND *lpBand; - - if (!lParam) - return 0; - if ((UINT)wParam >= infoPtr->uNumBands) - return 0; - - lpBand = &infoPtr->bands[(UINT)wParam]; - - /* FIXME - the following values were determined by experimentation */ - /* with the REBAR Control Spy. I have guesses as to what the 4 and */ - /* 1 are, but I am not sure. There doesn't seem to be any actual */ - /* difference in size of the control area with and without the */ - /* style. - GA */ - if (infoPtr->dwStyle & RBS_BANDBORDERS) { - if (infoPtr->dwStyle & CCS_VERT) { - lpRect->left = 1; - lpRect->top = lpBand->cxHeader + 4; - lpRect->right = 1; - lpRect->bottom = 0; - } - else { - lpRect->left = lpBand->cxHeader + 4; - lpRect->top = 1; - lpRect->right = 0; - lpRect->bottom = 1; - } - } - else { - lpRect->left = lpBand->cxHeader; - } - return 0; -} - - -inline static LRESULT -REBAR_GetBandCount (REBAR_INFO *infoPtr) -{ - TRACE("band count %u!\n", infoPtr->uNumBands); - - return infoPtr->uNumBands; -} - - -static LRESULT -REBAR_GetBandInfoA (REBAR_INFO *infoPtr, WPARAM wParam, LPARAM lParam) -{ - LPREBARBANDINFOA lprbbi = (LPREBARBANDINFOA)lParam; - REBAR_BAND *lpBand; - - if (lprbbi == NULL) - return FALSE; - if (lprbbi->cbSize < REBARBANDINFOA_V3_SIZE) - return FALSE; - if ((UINT)wParam >= infoPtr->uNumBands) - return FALSE; - - TRACE("index %u\n", (UINT)wParam); - - /* copy band information */ - lpBand = &infoPtr->bands[(UINT)wParam]; - - if (lprbbi->fMask & RBBIM_STYLE) - lprbbi->fStyle = lpBand->fStyle; - - if (lprbbi->fMask & RBBIM_COLORS) { - lprbbi->clrFore = lpBand->clrFore; - lprbbi->clrBack = lpBand->clrBack; - if (lprbbi->clrBack == CLR_DEFAULT) - lprbbi->clrBack = infoPtr->clrBtnFace; - } - - if ((lprbbi->fMask & RBBIM_TEXT) && (lprbbi->lpText)) { - if (lpBand->lpText && (lpBand->fMask & RBBIM_TEXT)) - { - if (!WideCharToMultiByte( CP_ACP, 0, lpBand->lpText, -1, - lprbbi->lpText, lprbbi->cch, NULL, NULL )) - lprbbi->lpText[lprbbi->cch-1] = 0; - } - else - *lprbbi->lpText = 0; - } - - if (lprbbi->fMask & RBBIM_IMAGE) { - if (lpBand->fMask & RBBIM_IMAGE) - lprbbi->iImage = lpBand->iImage; - else - lprbbi->iImage = -1; - } - - if (lprbbi->fMask & RBBIM_CHILD) - lprbbi->hwndChild = lpBand->hwndChild; - - if (lprbbi->fMask & RBBIM_CHILDSIZE) { - lprbbi->cxMinChild = lpBand->cxMinChild; - lprbbi->cyMinChild = lpBand->cyMinChild; - if (lprbbi->cbSize >= sizeof (REBARBANDINFOA)) { - lprbbi->cyChild = lpBand->cyChild; - lprbbi->cyMaxChild = lpBand->cyMaxChild; - lprbbi->cyIntegral = lpBand->cyIntegral; - } - } - - if (lprbbi->fMask & RBBIM_SIZE) - lprbbi->cx = lpBand->cx; - - if (lprbbi->fMask & RBBIM_BACKGROUND) - lprbbi->hbmBack = lpBand->hbmBack; - - if (lprbbi->fMask & RBBIM_ID) - lprbbi->wID = lpBand->wID; - - /* check for additional data */ - if (lprbbi->cbSize >= sizeof (REBARBANDINFOA)) { - if (lprbbi->fMask & RBBIM_IDEALSIZE) - lprbbi->cxIdeal = lpBand->cxIdeal; - - if (lprbbi->fMask & RBBIM_LPARAM) - lprbbi->lParam = lpBand->lParam; - - if (lprbbi->fMask & RBBIM_HEADERSIZE) - lprbbi->cxHeader = lpBand->cxHeader; - } - - REBAR_DumpBandInfo (lprbbi); - - return TRUE; -} - - -static LRESULT -REBAR_GetBandInfoW (REBAR_INFO *infoPtr, WPARAM wParam, LPARAM lParam) -{ - LPREBARBANDINFOW lprbbi = (LPREBARBANDINFOW)lParam; - REBAR_BAND *lpBand; - - if (lprbbi == NULL) - return FALSE; - if (lprbbi->cbSize < REBARBANDINFOW_V3_SIZE) - return FALSE; - if ((UINT)wParam >= infoPtr->uNumBands) - return FALSE; - - TRACE("index %u\n", (UINT)wParam); - - /* copy band information */ - lpBand = &infoPtr->bands[(UINT)wParam]; - - if (lprbbi->fMask & RBBIM_STYLE) - lprbbi->fStyle = lpBand->fStyle; - - if (lprbbi->fMask & RBBIM_COLORS) { - lprbbi->clrFore = lpBand->clrFore; - lprbbi->clrBack = lpBand->clrBack; - if (lprbbi->clrBack == CLR_DEFAULT) - lprbbi->clrBack = infoPtr->clrBtnFace; - } - - if ((lprbbi->fMask & RBBIM_TEXT) && (lprbbi->lpText)) { - if (lpBand->lpText && (lpBand->fMask & RBBIM_TEXT)) - lstrcpynW (lprbbi->lpText, lpBand->lpText, lprbbi->cch); - else - *lprbbi->lpText = 0; - } - - if (lprbbi->fMask & RBBIM_IMAGE) { - if (lpBand->fMask & RBBIM_IMAGE) - lprbbi->iImage = lpBand->iImage; - else - lprbbi->iImage = -1; - } - - if (lprbbi->fMask & RBBIM_CHILD) - lprbbi->hwndChild = lpBand->hwndChild; - - if (lprbbi->fMask & RBBIM_CHILDSIZE) { - lprbbi->cxMinChild = lpBand->cxMinChild; - lprbbi->cyMinChild = lpBand->cyMinChild; - if (lprbbi->cbSize >= sizeof (REBARBANDINFOW)) { - lprbbi->cyChild = lpBand->cyChild; - lprbbi->cyMaxChild = lpBand->cyMaxChild; - lprbbi->cyIntegral = lpBand->cyIntegral; - } - } - - if (lprbbi->fMask & RBBIM_SIZE) - lprbbi->cx = lpBand->cx; - - if (lprbbi->fMask & RBBIM_BACKGROUND) - lprbbi->hbmBack = lpBand->hbmBack; - - if (lprbbi->fMask & RBBIM_ID) - lprbbi->wID = lpBand->wID; - - /* check for additional data */ - if (lprbbi->cbSize >= sizeof (REBARBANDINFOW)) { - if (lprbbi->fMask & RBBIM_IDEALSIZE) - lprbbi->cxIdeal = lpBand->cxIdeal; - - if (lprbbi->fMask & RBBIM_LPARAM) - lprbbi->lParam = lpBand->lParam; - - if (lprbbi->fMask & RBBIM_HEADERSIZE) - lprbbi->cxHeader = lpBand->cxHeader; - } - - REBAR_DumpBandInfo ((LPREBARBANDINFOA)lprbbi); - - return TRUE; -} - - -static LRESULT -REBAR_GetBarHeight (REBAR_INFO *infoPtr, WPARAM wParam, LPARAM lParam) -{ - INT nHeight; - - nHeight = (infoPtr->dwStyle & CCS_VERT) ? infoPtr->calcSize.cx : infoPtr->calcSize.cy; - - TRACE("height = %d\n", nHeight); - - return nHeight; -} - - -static LRESULT -REBAR_GetBarInfo (REBAR_INFO *infoPtr, WPARAM wParam, LPARAM lParam) -{ - LPREBARINFO lpInfo = (LPREBARINFO)lParam; - - if (lpInfo == NULL) - return FALSE; - - if (lpInfo->cbSize < sizeof (REBARINFO)) - return FALSE; - - TRACE("getting bar info!\n"); - - if (infoPtr->himl) { - lpInfo->himl = infoPtr->himl; - lpInfo->fMask |= RBIM_IMAGELIST; - } - - return TRUE; -} - - -inline static LRESULT -REBAR_GetBkColor (REBAR_INFO *infoPtr) -{ - COLORREF clr = infoPtr->clrBk; - - if (clr == CLR_DEFAULT) - clr = infoPtr->clrBtnFace; - - TRACE("background color 0x%06lx!\n", clr); - - return clr; -} - - -/* << REBAR_GetColorScheme >> */ -/* << REBAR_GetDropTarget >> */ - - -static LRESULT -REBAR_GetPalette (REBAR_INFO *infoPtr, WPARAM wParam, LPARAM lParam) -{ - FIXME("empty stub!\n"); - - return 0; -} - - -static LRESULT -REBAR_GetRect (REBAR_INFO *infoPtr, WPARAM wParam, LPARAM lParam) -{ - INT iBand = (INT)wParam; - LPRECT lprc = (LPRECT)lParam; - REBAR_BAND *lpBand; - - if ((iBand < 0) && ((UINT)iBand >= infoPtr->uNumBands)) - return FALSE; - if (!lprc) - return FALSE; - - lpBand = &infoPtr->bands[iBand]; - CopyRect (lprc, &lpBand->rcBand); - - TRACE("band %d, (%ld,%ld)-(%ld,%ld)\n", iBand, - lprc->left, lprc->top, lprc->right, lprc->bottom); - - return TRUE; -} - - -inline static LRESULT -REBAR_GetRowCount (REBAR_INFO *infoPtr) -{ - TRACE("%u\n", infoPtr->uNumRows); - - return infoPtr->uNumRows; -} - - -static LRESULT -REBAR_GetRowHeight (REBAR_INFO *infoPtr, WPARAM wParam, LPARAM lParam) -{ - INT iRow = (INT)wParam; - int j = 0, ret = 0; - UINT i; - REBAR_BAND *lpBand; - - for (i=0; iuNumBands; i++) { - lpBand = &infoPtr->bands[i]; - if (HIDDENBAND(lpBand)) continue; - if (lpBand->iRow != iRow) continue; - if (infoPtr->dwStyle & CCS_VERT) - j = lpBand->rcBand.right - lpBand->rcBand.left; - else - j = lpBand->rcBand.bottom - lpBand->rcBand.top; - if (j > ret) ret = j; - } - - TRACE("row %d, height %d\n", iRow, ret); - - return ret; -} - - -inline static LRESULT -REBAR_GetTextColor (REBAR_INFO *infoPtr) -{ - TRACE("text color 0x%06lx!\n", infoPtr->clrText); - - return infoPtr->clrText; -} - - -inline static LRESULT -REBAR_GetToolTips (REBAR_INFO *infoPtr) -{ - return (LRESULT)infoPtr->hwndToolTip; -} - - -inline static LRESULT -REBAR_GetUnicodeFormat (REBAR_INFO *infoPtr) -{ - TRACE("%s hwnd=%p\n", - infoPtr->bUnicode ? "TRUE" : "FALSE", infoPtr->hwndSelf); - - return infoPtr->bUnicode; -} - - -inline static LRESULT -REBAR_GetVersion (REBAR_INFO *infoPtr) -{ - TRACE("version %d\n", infoPtr->iVersion); - return infoPtr->iVersion; -} - - -static LRESULT -REBAR_HitTest (REBAR_INFO *infoPtr, WPARAM wParam, LPARAM lParam) -{ - LPRBHITTESTINFO lprbht = (LPRBHITTESTINFO)lParam; - - if (!lprbht) - return -1; - - REBAR_InternalHitTest (infoPtr, &lprbht->pt, &lprbht->flags, &lprbht->iBand); - - return lprbht->iBand; -} - - -static LRESULT -REBAR_IdToIndex (REBAR_INFO *infoPtr, WPARAM wParam, LPARAM lParam) -{ - UINT i; - - if (infoPtr == NULL) - return -1; - - if (infoPtr->uNumBands < 1) - return -1; - - for (i = 0; i < infoPtr->uNumBands; i++) { - if (infoPtr->bands[i].wID == (UINT)wParam) { - TRACE("id %u is band %u found!\n", (UINT)wParam, i); - return i; - } - } - - TRACE("id %u is not found\n", (UINT)wParam); - return -1; -} - - -static LRESULT -REBAR_InsertBandA (REBAR_INFO *infoPtr, WPARAM wParam, LPARAM lParam) -{ - LPREBARBANDINFOA lprbbi = (LPREBARBANDINFOA)lParam; - UINT uIndex = (UINT)wParam; - REBAR_BAND *lpBand; - - if (infoPtr == NULL) - return FALSE; - if (lprbbi == NULL) - return FALSE; - if (lprbbi->cbSize < REBARBANDINFOA_V3_SIZE) - return FALSE; - - /* trace the index as signed to see the -1 */ - TRACE("insert band at %d!\n", (INT)uIndex); - REBAR_DumpBandInfo (lprbbi); - - if (infoPtr->uNumBands == 0) { - infoPtr->bands = (REBAR_BAND *)Alloc (sizeof (REBAR_BAND)); - uIndex = 0; - } - else { - REBAR_BAND *oldBands = infoPtr->bands; - infoPtr->bands = - (REBAR_BAND *)Alloc ((infoPtr->uNumBands+1)*sizeof(REBAR_BAND)); - if (((INT)uIndex == -1) || (uIndex > infoPtr->uNumBands)) - uIndex = infoPtr->uNumBands; - - /* pre insert copy */ - if (uIndex > 0) { - memcpy (&infoPtr->bands[0], &oldBands[0], - uIndex * sizeof(REBAR_BAND)); - } - - /* post copy */ - if (uIndex < infoPtr->uNumBands) { - memcpy (&infoPtr->bands[uIndex+1], &oldBands[uIndex], - (infoPtr->uNumBands - uIndex) * sizeof(REBAR_BAND)); - } - - Free (oldBands); - } - - infoPtr->uNumBands++; - - TRACE("index %u!\n", uIndex); - - /* initialize band (infoPtr->bands[uIndex])*/ - lpBand = &infoPtr->bands[uIndex]; - lpBand->fMask = 0; - lpBand->fStatus = 0; - lpBand->clrFore = infoPtr->clrText; - lpBand->clrBack = infoPtr->clrBk; - lpBand->hwndChild = 0; - lpBand->hwndPrevParent = 0; - - REBAR_CommonSetupBand (infoPtr->hwndSelf, lprbbi, lpBand); - lpBand->lpText = NULL; - if ((lprbbi->fMask & RBBIM_TEXT) && (lprbbi->lpText)) { - INT len = MultiByteToWideChar( CP_ACP, 0, lprbbi->lpText, -1, NULL, 0 ); - if (len > 1) { - lpBand->lpText = (LPWSTR)Alloc (len*sizeof(WCHAR)); - MultiByteToWideChar( CP_ACP, 0, lprbbi->lpText, -1, lpBand->lpText, len ); - } - } - - REBAR_ValidateBand (infoPtr, lpBand); - /* On insert of second band, revalidate band 1 to possible add gripper */ - if (infoPtr->uNumBands == 2) - REBAR_ValidateBand (infoPtr, &infoPtr->bands[0]); - - REBAR_DumpBand (infoPtr); - - REBAR_Layout (infoPtr, NULL, TRUE, FALSE); - InvalidateRect(infoPtr->hwndSelf, 0, 1); - - return TRUE; -} - - -static LRESULT -REBAR_InsertBandW (REBAR_INFO *infoPtr, WPARAM wParam, LPARAM lParam) -{ - LPREBARBANDINFOW lprbbi = (LPREBARBANDINFOW)lParam; - UINT uIndex = (UINT)wParam; - REBAR_BAND *lpBand; - - if (infoPtr == NULL) - return FALSE; - if (lprbbi == NULL) - return FALSE; - if (lprbbi->cbSize < REBARBANDINFOW_V3_SIZE) - return FALSE; - - /* trace the index as signed to see the -1 */ - TRACE("insert band at %d!\n", (INT)uIndex); - REBAR_DumpBandInfo ((LPREBARBANDINFOA)lprbbi); - - if (infoPtr->uNumBands == 0) { - infoPtr->bands = (REBAR_BAND *)Alloc (sizeof (REBAR_BAND)); - uIndex = 0; - } - else { - REBAR_BAND *oldBands = infoPtr->bands; - infoPtr->bands = - (REBAR_BAND *)Alloc ((infoPtr->uNumBands+1)*sizeof(REBAR_BAND)); - if (((INT)uIndex == -1) || (uIndex > infoPtr->uNumBands)) - uIndex = infoPtr->uNumBands; - - /* pre insert copy */ - if (uIndex > 0) { - memcpy (&infoPtr->bands[0], &oldBands[0], - uIndex * sizeof(REBAR_BAND)); - } - - /* post copy */ - if (uIndex <= infoPtr->uNumBands - 1) { - memcpy (&infoPtr->bands[uIndex+1], &oldBands[uIndex], - (infoPtr->uNumBands - uIndex) * sizeof(REBAR_BAND)); - } - - Free (oldBands); - } - - infoPtr->uNumBands++; - - TRACE("index %u!\n", uIndex); - - /* initialize band (infoPtr->bands[uIndex])*/ - lpBand = &infoPtr->bands[uIndex]; - lpBand->fMask = 0; - lpBand->fStatus = 0; - lpBand->clrFore = infoPtr->clrText; - lpBand->clrBack = infoPtr->clrBk; - lpBand->hwndChild = 0; - lpBand->hwndPrevParent = 0; - - REBAR_CommonSetupBand (infoPtr->hwndSelf, (LPREBARBANDINFOA)lprbbi, lpBand); - lpBand->lpText = NULL; - if ((lprbbi->fMask & RBBIM_TEXT) && (lprbbi->lpText)) { - INT len = lstrlenW (lprbbi->lpText); - if (len > 0) { - lpBand->lpText = (LPWSTR)Alloc ((len + 1)*sizeof(WCHAR)); - strcpyW (lpBand->lpText, lprbbi->lpText); - } - } - - REBAR_ValidateBand (infoPtr, lpBand); - /* On insert of second band, revalidate band 1 to possible add gripper */ - if (infoPtr->uNumBands == 2) - REBAR_ValidateBand (infoPtr, &infoPtr->bands[uIndex ? 0 : 1]); - - REBAR_DumpBand (infoPtr); - - REBAR_Layout (infoPtr, NULL, TRUE, FALSE); - InvalidateRect(infoPtr->hwndSelf, 0, 1); - - return TRUE; -} - - -static LRESULT -REBAR_MaximizeBand (REBAR_INFO *infoPtr, WPARAM wParam, LPARAM lParam) -{ - REBAR_BAND *lpBand; - UINT uBand = (UINT) wParam; - - /* Validate */ - if ((infoPtr->uNumBands == 0) || - ((INT)uBand < 0) || (uBand >= infoPtr->uNumBands)) { - /* error !!! */ - ERR("Illegal MaximizeBand, requested=%d, current band count=%d\n", - (INT)uBand, infoPtr->uNumBands); - return FALSE; - } - - lpBand = &infoPtr->bands[uBand]; - - if (lParam && (lpBand->fMask & RBBIM_IDEALSIZE)) { - /* handle setting ideal size */ - lpBand->ccx = lpBand->cxIdeal; - } - else { - /* handle setting to max */ - FIXME("(uBand = %u fIdeal = %s) case not coded\n", - (UINT)wParam, lParam ? "TRUE" : "FALSE"); - return FALSE; - } - - infoPtr->fStatus |= BAND_NEEDS_LAYOUT; - REBAR_Layout (infoPtr, 0, TRUE, TRUE); - InvalidateRect (infoPtr->hwndSelf, 0, TRUE); - - return TRUE; - -} - - -static LRESULT -REBAR_MinimizeBand (REBAR_INFO *infoPtr, WPARAM wParam, LPARAM lParam) -{ - REBAR_BAND *band, *lpBand; - UINT uBand = (UINT) wParam; - RECT newrect; - INT imindBand, imaxdBand, iprevBand, startBand, endBand; - INT movement, i; - - /* A "minimize" band is equivalent to "dragging" the gripper - * of than band to the right till the band is only the size - * of the cxHeader. - */ - - /* Validate */ - if ((infoPtr->uNumBands == 0) || - ((INT)uBand < 0) || (uBand >= infoPtr->uNumBands)) { - /* error !!! */ - ERR("Illegal MinimizeBand, requested=%d, current band count=%d\n", - (INT)uBand, infoPtr->uNumBands); - return FALSE; - } - - /* compute amount of movement and validate */ - lpBand = &infoPtr->bands[uBand]; - - if (infoPtr->dwStyle & CCS_VERT) - movement = lpBand->rcBand.bottom - lpBand->rcBand.top - - lpBand->cxHeader; - else - movement = lpBand->rcBand.right - lpBand->rcBand.left - - lpBand->cxHeader; - if (movement < 0) { - ERR("something is wrong, band=(%ld,%ld)-(%ld,%ld), cxheader=%d\n", - lpBand->rcBand.left, lpBand->rcBand.top, - lpBand->rcBand.right, lpBand->rcBand.bottom, - lpBand->cxHeader); - return FALSE; - } - - imindBand = -1; - imaxdBand = -1; - iprevBand = -1; /* to suppress warning message */ - - /* find the first band in row of the one whose is being minimized */ - for (i=0; iuNumBands; i++) { - band = &infoPtr->bands[i]; - if (HIDDENBAND(band)) continue; - if (band->iRow == lpBand->iRow) { - imaxdBand = i; - if (imindBand == -1) imindBand = i; - } - } - - /* if the selected band is first in row then need to expand */ - /* next visible band */ - if (imindBand == uBand) { - band = NULL; - movement = -movement; - /* find the first visible band to the right of the selected band */ - for (i=uBand+1; i<=imaxdBand; i++) { - band = &infoPtr->bands[i]; - if (!HIDDENBAND(band)) { - iprevBand = i; - LEADJ(band, movement); - band->ccx = rcBw(band); - break; - } - } - /* what case is this */ - if (iprevBand == -1) { - ERR("no previous visible band\n"); - return FALSE; - } - startBand = uBand; - endBand = iprevBand; - SetRect (&newrect, - lpBand->rcBand.left, - lpBand->rcBand.top, - band->rcBand.right, - band->rcBand.bottom); - } - /* otherwise expand previous visible band */ - else { - band = NULL; - /* find the first visible band to the left of the selected band */ - for (i=uBand-1; i>=imindBand; i--) { - band = &infoPtr->bands[i]; - if (!HIDDENBAND(band)) { - iprevBand = i; - READJ(band, movement); - band->ccx = rcBw(band); - break; - } - } - /* what case is this */ - if (iprevBand == -1) { - ERR("no previous visible band\n"); - return FALSE; - } - startBand = iprevBand; - endBand = uBand; - SetRect (&newrect, - band->rcBand.left, - band->rcBand.top, - lpBand->rcBand.right, - lpBand->rcBand.bottom); - } - - REBAR_Shrink (infoPtr, lpBand, movement, uBand); - - /* recompute all rectangles */ - if (infoPtr->dwStyle & CCS_VERT) { - REBAR_CalcVertBand (infoPtr, startBand, endBand+1, - FALSE); - } - else { - REBAR_CalcHorzBand (infoPtr, startBand, endBand+1, - FALSE); - } - - TRACE("bands after minimize, see band # %d, %d\n", - startBand, endBand); - REBAR_DumpBand (infoPtr); - - REBAR_MoveChildWindows (infoPtr, startBand, endBand+1); - - InvalidateRect (infoPtr->hwndSelf, &newrect, TRUE); - UpdateWindow (infoPtr->hwndSelf); - return FALSE; -} - - -static LRESULT -REBAR_MoveBand (REBAR_INFO *infoPtr, WPARAM wParam, LPARAM lParam) -{ - REBAR_BAND *oldBands = infoPtr->bands; - REBAR_BAND holder; - UINT uFrom = (UINT)wParam; - UINT uTo = (UINT)lParam; - - /* Validate */ - if ((infoPtr->uNumBands == 0) || - ((INT)uFrom < 0) || (uFrom >= infoPtr->uNumBands) || - ((INT)uTo < 0) || (uTo >= infoPtr->uNumBands)) { - /* error !!! */ - ERR("Illegal MoveBand, from=%d, to=%d, current band count=%d\n", - (INT)uFrom, (INT)uTo, infoPtr->uNumBands); - return FALSE; - } - - /* save one to be moved */ - memcpy (&holder, &oldBands[uFrom], sizeof(REBAR_BAND)); - - /* close up rest of bands (pseudo delete) */ - if (uFrom < infoPtr->uNumBands - 1) { - memcpy (&oldBands[uFrom], &oldBands[uFrom+1], - (infoPtr->uNumBands - uFrom - 1) * sizeof(REBAR_BAND)); - } - - /* allocate new space and copy rest of bands into it */ - infoPtr->bands = - (REBAR_BAND *)Alloc ((infoPtr->uNumBands)*sizeof(REBAR_BAND)); - - /* pre insert copy */ - if (uTo > 0) { - memcpy (&infoPtr->bands[0], &oldBands[0], - uTo * sizeof(REBAR_BAND)); - } - - /* set moved band */ - memcpy (&infoPtr->bands[uTo], &holder, sizeof(REBAR_BAND)); - - /* post copy */ - if (uTo < infoPtr->uNumBands - 1) { - memcpy (&infoPtr->bands[uTo+1], &oldBands[uTo], - (infoPtr->uNumBands - uTo - 1) * sizeof(REBAR_BAND)); - } - - Free (oldBands); - - TRACE("moved band %d to index %d\n", uFrom, uTo); - REBAR_DumpBand (infoPtr); - - infoPtr->fStatus |= BAND_NEEDS_LAYOUT; - /* **************************************************** */ - /* */ - /* We do not do a REBAR_Layout here because the native */ - /* control does not do that. The actual layout and */ - /* repaint is done by the *next* real action, ex.: */ - /* RB_INSERTBAND, RB_DELETEBAND, RB_SIZETORECT, etc. */ - /* */ - /* **************************************************** */ - - return TRUE; -} - - -/* return TRUE if two strings are different */ -static BOOL -REBAR_strdifW( LPCWSTR a, LPCWSTR b ) -{ - return ( (a && !b) || (b && !a) || (a && b && lstrcmpW(a, b) ) ); -} - -static LRESULT -REBAR_SetBandInfoA (REBAR_INFO *infoPtr, WPARAM wParam, LPARAM lParam) -{ - LPREBARBANDINFOA lprbbi = (LPREBARBANDINFOA)lParam; - REBAR_BAND *lpBand; - BOOL bChanged; - - if (lprbbi == NULL) - return FALSE; - if (lprbbi->cbSize < REBARBANDINFOA_V3_SIZE) - return FALSE; - if ((UINT)wParam >= infoPtr->uNumBands) - return FALSE; - - TRACE("index %u\n", (UINT)wParam); - REBAR_DumpBandInfo (lprbbi); - - /* set band information */ - lpBand = &infoPtr->bands[(UINT)wParam]; - - bChanged = REBAR_CommonSetupBand (infoPtr->hwndSelf, lprbbi, lpBand); - if (lprbbi->fMask & RBBIM_TEXT) { - LPWSTR wstr = NULL; - - if (lprbbi->lpText) - { - INT len; - len = MultiByteToWideChar( CP_ACP, 0, lprbbi->lpText, -1, NULL, 0 ); - if (len > 1) - wstr = (LPWSTR)Alloc (len*sizeof(WCHAR)); - if (wstr) - MultiByteToWideChar( CP_ACP, 0, lprbbi->lpText, -1, wstr, len ); - } - if (REBAR_strdifW(lpBand->lpText, wstr)) { - if (lpBand->lpText) { - Free (lpBand->lpText); - lpBand->lpText = NULL; - } - if (wstr) { - lpBand->lpText = wstr; - wstr = NULL; - } - bChanged = TRUE; - } - if (wstr) - Free (wstr); - } - - REBAR_ValidateBand (infoPtr, lpBand); - - REBAR_DumpBand (infoPtr); - - if (bChanged && (lprbbi->fMask & (RBBIM_CHILDSIZE | RBBIM_SIZE))) { - REBAR_Layout (infoPtr, NULL, TRUE, FALSE); - InvalidateRect(infoPtr->hwndSelf, 0, 1); - } - - return TRUE; -} - -static LRESULT -REBAR_SetBandInfoW (REBAR_INFO *infoPtr, WPARAM wParam, LPARAM lParam) -{ - LPREBARBANDINFOW lprbbi = (LPREBARBANDINFOW)lParam; - REBAR_BAND *lpBand; - BOOL bChanged; - - if (lprbbi == NULL) - return FALSE; - if (lprbbi->cbSize < REBARBANDINFOW_V3_SIZE) - return FALSE; - if ((UINT)wParam >= infoPtr->uNumBands) - return FALSE; - - TRACE("index %u\n", (UINT)wParam); - REBAR_DumpBandInfo ((LPREBARBANDINFOA)lprbbi); - - /* set band information */ - lpBand = &infoPtr->bands[(UINT)wParam]; - - bChanged = REBAR_CommonSetupBand (infoPtr->hwndSelf, (LPREBARBANDINFOA)lprbbi, lpBand); - if( (lprbbi->fMask & RBBIM_TEXT) && - REBAR_strdifW( lpBand->lpText, lprbbi->lpText ) ) { - if (lpBand->lpText) { - Free (lpBand->lpText); - lpBand->lpText = NULL; - } - if (lprbbi->lpText) { - INT len = lstrlenW (lprbbi->lpText); - if (len > 0) - { - lpBand->lpText = (LPWSTR)Alloc ((len + 1)*sizeof(WCHAR)); - strcpyW (lpBand->lpText, lprbbi->lpText); - } - } - bChanged = TRUE; - } - - REBAR_ValidateBand (infoPtr, lpBand); - - REBAR_DumpBand (infoPtr); - - if ( bChanged && (lprbbi->fMask & (RBBIM_CHILDSIZE | RBBIM_SIZE)) ) { - REBAR_Layout (infoPtr, NULL, TRUE, FALSE); - InvalidateRect(infoPtr->hwndSelf, 0, 1); - } - - return TRUE; -} - - -static LRESULT -REBAR_SetBarInfo (REBAR_INFO *infoPtr, WPARAM wParam, LPARAM lParam) -{ - LPREBARINFO lpInfo = (LPREBARINFO)lParam; - REBAR_BAND *lpBand; - UINT i; - - if (lpInfo == NULL) - return FALSE; - - if (lpInfo->cbSize < sizeof (REBARINFO)) - return FALSE; - - TRACE("setting bar info!\n"); - - if (lpInfo->fMask & RBIM_IMAGELIST) { - infoPtr->himl = lpInfo->himl; - if (infoPtr->himl) { - INT cx, cy; - ImageList_GetIconSize (infoPtr->himl, &cx, &cy); - infoPtr->imageSize.cx = cx; - infoPtr->imageSize.cy = cy; - } - else { - infoPtr->imageSize.cx = 0; - infoPtr->imageSize.cy = 0; - } - TRACE("new image cx=%ld, cy=%ld\n", infoPtr->imageSize.cx, - infoPtr->imageSize.cy); - } - - /* revalidate all bands to reset flags for images in headers of bands */ - for (i=0; iuNumBands; i++) { - lpBand = &infoPtr->bands[i]; - REBAR_ValidateBand (infoPtr, lpBand); - } - - return TRUE; -} - - -static LRESULT -REBAR_SetBkColor (REBAR_INFO *infoPtr, WPARAM wParam, LPARAM lParam) -{ - COLORREF clrTemp; - - clrTemp = infoPtr->clrBk; - infoPtr->clrBk = (COLORREF)lParam; - - TRACE("background color 0x%06lx!\n", infoPtr->clrBk); - - return clrTemp; -} - - -/* << REBAR_SetColorScheme >> */ -/* << REBAR_SetPalette >> */ - - -static LRESULT -REBAR_SetParent (REBAR_INFO *infoPtr, WPARAM wParam, LPARAM lParam) -{ - HWND hwndTemp = infoPtr->hwndNotify; - - infoPtr->hwndNotify = (HWND)wParam; - - return (LRESULT)hwndTemp; -} - - -static LRESULT -REBAR_SetTextColor (REBAR_INFO *infoPtr, WPARAM wParam, LPARAM lParam) -{ - COLORREF clrTemp; - - clrTemp = infoPtr->clrText; - infoPtr->clrText = (COLORREF)lParam; - - TRACE("text color 0x%06lx!\n", infoPtr->clrText); - - return clrTemp; -} - - -/* << REBAR_SetTooltips >> */ - - -inline static LRESULT -REBAR_SetUnicodeFormat (REBAR_INFO *infoPtr, WPARAM wParam) -{ - BOOL bTemp = infoPtr->bUnicode; - - TRACE("to %s hwnd=%p, was %s\n", - ((BOOL)wParam) ? "TRUE" : "FALSE", infoPtr->hwndSelf, - (bTemp) ? "TRUE" : "FALSE"); - - infoPtr->bUnicode = (BOOL)wParam; - - return bTemp; -} - - -static LRESULT -REBAR_SetVersion (REBAR_INFO *infoPtr, INT iVersion) -{ - INT iOldVersion = infoPtr->iVersion; - - if (iVersion > COMCTL32_VERSION) - return -1; - - infoPtr->iVersion = iVersion; - - TRACE("new version %d\n", iVersion); - - return iOldVersion; -} - - -static LRESULT -REBAR_ShowBand (REBAR_INFO *infoPtr, WPARAM wParam, LPARAM lParam) -{ - REBAR_BAND *lpBand; - - if (((INT)wParam < 0) || ((INT)wParam > infoPtr->uNumBands)) - return FALSE; - - lpBand = &infoPtr->bands[(INT)wParam]; - - if ((BOOL)lParam) { - TRACE("show band %d\n", (INT)wParam); - lpBand->fStyle = lpBand->fStyle & ~RBBS_HIDDEN; - if (IsWindow (lpBand->hwndChild)) - ShowWindow (lpBand->hwndChild, SW_SHOW); - } - else { - TRACE("hide band %d\n", (INT)wParam); - lpBand->fStyle = lpBand->fStyle | RBBS_HIDDEN; - if (IsWindow (lpBand->hwndChild)) - ShowWindow (lpBand->hwndChild, SW_HIDE); - } - - infoPtr->fStatus |= BAND_NEEDS_LAYOUT; - REBAR_Layout (infoPtr, NULL, TRUE, FALSE); - InvalidateRect(infoPtr->hwndSelf, 0, 1); - - return TRUE; -} - - -static LRESULT -REBAR_SizeToRect (REBAR_INFO *infoPtr, WPARAM wParam, LPARAM lParam) -{ - LPRECT lpRect = (LPRECT)lParam; - RECT t1; - - if (lpRect == NULL) - return FALSE; - - TRACE("[%ld %ld %ld %ld]\n", - lpRect->left, lpRect->top, lpRect->right, lpRect->bottom); - - /* what is going on???? */ - GetWindowRect(infoPtr->hwndSelf, &t1); - TRACE("window rect [%ld %ld %ld %ld]\n", - t1.left, t1.top, t1.right, t1.bottom); - GetClientRect(infoPtr->hwndSelf, &t1); - TRACE("client rect [%ld %ld %ld %ld]\n", - t1.left, t1.top, t1.right, t1.bottom); - - /* force full _Layout processing */ - TRACE("setting NEEDS_LAYOUT\n"); - infoPtr->fStatus |= BAND_NEEDS_LAYOUT; - REBAR_Layout (infoPtr, lpRect, TRUE, FALSE); - InvalidateRect (infoPtr->hwndSelf, NULL, TRUE); - return TRUE; -} - - - -static LRESULT -REBAR_Create (REBAR_INFO *infoPtr, WPARAM wParam, LPARAM lParam) -{ - LPCREATESTRUCTA cs = (LPCREATESTRUCTA) lParam; - RECT wnrc1, clrc1; - - if (TRACE_ON(rebar)) { - GetWindowRect(infoPtr->hwndSelf, &wnrc1); - GetClientRect(infoPtr->hwndSelf, &clrc1); - TRACE("window=(%ld,%ld)-(%ld,%ld) client=(%ld,%ld)-(%ld,%ld) cs=(%d,%d %dx%d)\n", - wnrc1.left, wnrc1.top, wnrc1.right, wnrc1.bottom, - clrc1.left, clrc1.top, clrc1.right, clrc1.bottom, - cs->x, cs->y, cs->cx, cs->cy); - } - - TRACE("created!\n"); - return 0; -} - - -static LRESULT -REBAR_Destroy (REBAR_INFO *infoPtr, WPARAM wParam, LPARAM lParam) -{ - REBAR_BAND *lpBand; - UINT i; - - - /* free rebar bands */ - if ((infoPtr->uNumBands > 0) && infoPtr->bands) { - /* clean up each band */ - for (i = 0; i < infoPtr->uNumBands; i++) { - lpBand = &infoPtr->bands[i]; - - /* delete text strings */ - if (lpBand->lpText) { - Free (lpBand->lpText); - lpBand->lpText = NULL; - } - /* destroy child window */ - DestroyWindow (lpBand->hwndChild); - } - - /* free band array */ - Free (infoPtr->bands); - infoPtr->bands = NULL; - } - - DestroyCursor (infoPtr->hcurArrow); - DestroyCursor (infoPtr->hcurHorz); - DestroyCursor (infoPtr->hcurVert); - DestroyCursor (infoPtr->hcurDrag); - if(infoPtr->hDefaultFont) DeleteObject (infoPtr->hDefaultFont); - SetWindowLongPtrW (infoPtr->hwndSelf, 0, 0); - - /* free rebar info data */ - Free (infoPtr); - TRACE("destroyed!\n"); - return 0; -} - - -static LRESULT -REBAR_EraseBkGnd (REBAR_INFO *infoPtr, WPARAM wParam, LPARAM lParam) -{ - RECT cliprect; - - if (GetClipBox ( (HDC)wParam, &cliprect)) - return REBAR_InternalEraseBkGnd (infoPtr, wParam, lParam, &cliprect); - return 0; -} - - -static LRESULT -REBAR_GetFont (REBAR_INFO *infoPtr, WPARAM wParam, LPARAM lParam) -{ - return (LRESULT)infoPtr->hFont; -} - -static LRESULT -REBAR_PushChevron(REBAR_INFO *infoPtr, WPARAM wParam, LPARAM lParam) -{ - if (wParam >= 0 && (UINT)wParam < infoPtr->uNumBands) - { - NMREBARCHEVRON nmrbc; - REBAR_BAND *lpBand = &infoPtr->bands[wParam]; - - TRACE("Pressed chevron on band %d\n", wParam); - - /* redraw chevron in pushed state */ - lpBand->fDraw |= DRAW_CHEVRONPUSHED; - RedrawWindow(infoPtr->hwndSelf, &lpBand->rcChevron,0, - RDW_ERASE|RDW_INVALIDATE|RDW_UPDATENOW); - - /* notify app so it can display a popup menu or whatever */ - nmrbc.uBand = wParam; - nmrbc.wID = lpBand->wID; - nmrbc.lParam = lpBand->lParam; - nmrbc.rc = lpBand->rcChevron; - nmrbc.lParamNM = lParam; - REBAR_Notify((NMHDR*)&nmrbc, infoPtr, RBN_CHEVRONPUSHED); - - /* redraw chevron in previous state */ - lpBand->fDraw &= ~DRAW_CHEVRONPUSHED; - InvalidateRect(infoPtr->hwndSelf, &lpBand->rcChevron, TRUE); - - return TRUE; - } - return FALSE; -} - -static LRESULT -REBAR_LButtonDown (REBAR_INFO *infoPtr, WPARAM wParam, LPARAM lParam) -{ - REBAR_BAND *lpBand; - UINT htFlags; - UINT iHitBand; - POINT ptMouseDown; - ptMouseDown.x = (INT)LOWORD(lParam); - ptMouseDown.y = (INT)HIWORD(lParam); - - REBAR_InternalHitTest(infoPtr, &ptMouseDown, &htFlags, &iHitBand); - lpBand = &infoPtr->bands[iHitBand]; - - if (htFlags == RBHT_CHEVRON) - { - REBAR_PushChevron(infoPtr, iHitBand, 0); - } - else if (htFlags == RBHT_GRABBER || htFlags == RBHT_CAPTION) - { - TRACE("Starting drag\n"); - - SetCapture (infoPtr->hwndSelf); - infoPtr->iGrabbedBand = iHitBand; - - /* save off the LOWORD and HIWORD of lParam as initial x,y */ - infoPtr->dragStart.x = (short)LOWORD(lParam); - infoPtr->dragStart.y = (short)HIWORD(lParam); - infoPtr->dragNow = infoPtr->dragStart; - if (infoPtr->dwStyle & CCS_VERT) - infoPtr->ihitoffset = infoPtr->dragStart.y - (lpBand->rcBand.top+REBAR_PRE_GRIPPER); - else - infoPtr->ihitoffset = infoPtr->dragStart.x - (lpBand->rcBand.left+REBAR_PRE_GRIPPER); - } - return 0; -} - -static LRESULT -REBAR_LButtonUp (REBAR_INFO *infoPtr, WPARAM wParam, LPARAM lParam) -{ - if (infoPtr->iGrabbedBand >= 0) - { - NMHDR layout; - RECT rect; - - infoPtr->dragStart.x = 0; - infoPtr->dragStart.y = 0; - infoPtr->dragNow = infoPtr->dragStart; - - ReleaseCapture (); - - if (infoPtr->fStatus & BEGIN_DRAG_ISSUED) { - REBAR_Notify(&layout, infoPtr, RBN_LAYOUTCHANGED); - REBAR_Notify_NMREBAR (infoPtr, infoPtr->iGrabbedBand, RBN_ENDDRAG); - infoPtr->fStatus &= ~BEGIN_DRAG_ISSUED; - } - - infoPtr->iGrabbedBand = -1; - - GetClientRect(infoPtr->hwndSelf, &rect); - InvalidateRect(infoPtr->hwndSelf, NULL, TRUE); - } - - return 0; -} - -static LRESULT -REBAR_MouseLeave (REBAR_INFO *infoPtr, WPARAM wParam, LPARAM lParam) -{ - if (infoPtr->ichevronhotBand >= 0) - { - REBAR_BAND *lpChevronBand = &infoPtr->bands[infoPtr->ichevronhotBand]; - if (lpChevronBand->fDraw & DRAW_CHEVRONHOT) - { - lpChevronBand->fDraw &= ~DRAW_CHEVRONHOT; - InvalidateRect(infoPtr->hwndSelf, &lpChevronBand->rcChevron, TRUE); - } - } - infoPtr->iOldBand = -1; - infoPtr->ichevronhotBand = -2; - - return TRUE; -} - -static LRESULT -REBAR_MouseMove (REBAR_INFO *infoPtr, WPARAM wParam, LPARAM lParam) -{ - REBAR_BAND *lpChevronBand; - POINT ptMove; - - ptMove.x = (short)LOWORD(lParam); - ptMove.y = (short)HIWORD(lParam); - - /* if we are currently dragging a band */ - if (infoPtr->iGrabbedBand >= 0) - { - REBAR_BAND *band1, *band2; - - if (GetCapture() != infoPtr->hwndSelf) - ERR("We are dragging but haven't got capture?!?\n"); - - band1 = &infoPtr->bands[infoPtr->iGrabbedBand-1]; - band2 = &infoPtr->bands[infoPtr->iGrabbedBand]; - - /* if mouse did not move much, exit */ - if ((abs(ptMove.x - infoPtr->dragNow.x) <= mindragx) && - (abs(ptMove.y - infoPtr->dragNow.y) <= mindragy)) return 0; - - /* Test for valid drag case - must not be first band in row */ - if (infoPtr->dwStyle & CCS_VERT) { - if ((ptMove.x < band2->rcBand.left) || - (ptMove.x > band2->rcBand.right) || - ((infoPtr->iGrabbedBand > 0) && (band1->iRow != band2->iRow))) { - FIXME("Cannot drag to other rows yet!!\n"); - } - else { - REBAR_HandleLRDrag (infoPtr, &ptMove); - } - } - else { - if ((ptMove.y < band2->rcBand.top) || - (ptMove.y > band2->rcBand.bottom) || - ((infoPtr->iGrabbedBand > 0) && (band1->iRow != band2->iRow))) { - FIXME("Cannot drag to other rows yet!!\n"); - } - else { - REBAR_HandleLRDrag (infoPtr, &ptMove); - } - } - } - else - { - INT iHitBand; - UINT htFlags; - TRACKMOUSEEVENT trackinfo; - - REBAR_InternalHitTest(infoPtr, &ptMove, &htFlags, &iHitBand); - - if (infoPtr->iOldBand >= 0 && infoPtr->iOldBand == infoPtr->ichevronhotBand) - { - lpChevronBand = &infoPtr->bands[infoPtr->ichevronhotBand]; - if (lpChevronBand->fDraw & DRAW_CHEVRONHOT) - { - lpChevronBand->fDraw &= ~DRAW_CHEVRONHOT; - InvalidateRect(infoPtr->hwndSelf, &lpChevronBand->rcChevron, TRUE); - } - infoPtr->ichevronhotBand = -2; - } - - if (htFlags == RBHT_CHEVRON) - { - /* fill in the TRACKMOUSEEVENT struct */ - trackinfo.cbSize = sizeof(TRACKMOUSEEVENT); - trackinfo.dwFlags = TME_QUERY; - trackinfo.hwndTrack = infoPtr->hwndSelf; - trackinfo.dwHoverTime = 0; - - /* call _TrackMouseEvent to see if we are currently tracking for this hwnd */ - _TrackMouseEvent(&trackinfo); - - /* Make sure tracking is enabled so we receive a WM_MOUSELEAVE message */ - if(!(trackinfo.dwFlags & TME_LEAVE)) - { - trackinfo.dwFlags = TME_LEAVE; /* notify upon leaving */ - - /* call TRACKMOUSEEVENT so we receive a WM_MOUSELEAVE message */ - /* and can properly deactivate the hot chevron */ - _TrackMouseEvent(&trackinfo); - } - - lpChevronBand = &infoPtr->bands[iHitBand]; - if (!(lpChevronBand->fDraw & DRAW_CHEVRONHOT)) - { - lpChevronBand->fDraw |= DRAW_CHEVRONHOT; - InvalidateRect(infoPtr->hwndSelf, &lpChevronBand->rcChevron, TRUE); - infoPtr->ichevronhotBand = iHitBand; - } - } - infoPtr->iOldBand = iHitBand; - } - - return 0; -} - - -inline static LRESULT -REBAR_NCCalcSize (REBAR_INFO *infoPtr, WPARAM wParam, LPARAM lParam) -{ - if (infoPtr->dwStyle & WS_BORDER) { - InflateRect((LPRECT)lParam, -GetSystemMetrics(SM_CXEDGE), - -GetSystemMetrics(SM_CYEDGE)); - } - TRACE("new client=(%ld,%ld)-(%ld,%ld)\n", - ((LPRECT)lParam)->left, ((LPRECT)lParam)->top, - ((LPRECT)lParam)->right, ((LPRECT)lParam)->bottom); - return 0; -} - - -static LRESULT -REBAR_NCCreate (HWND hwnd, WPARAM wParam, LPARAM lParam) -{ - LPCREATESTRUCTA cs = (LPCREATESTRUCTA) lParam; - REBAR_INFO *infoPtr = REBAR_GetInfoPtr (hwnd); - RECT wnrc1, clrc1; - NONCLIENTMETRICSA ncm; - HFONT tfont; - INT i; - - if (infoPtr != NULL) { - ERR("Strange info structure pointer *not* NULL\n"); - return FALSE; - } - - if (TRACE_ON(rebar)) { - GetWindowRect(hwnd, &wnrc1); - GetClientRect(hwnd, &clrc1); - TRACE("window=(%ld,%ld)-(%ld,%ld) client=(%ld,%ld)-(%ld,%ld) cs=(%d,%d %dx%d)\n", - wnrc1.left, wnrc1.top, wnrc1.right, wnrc1.bottom, - clrc1.left, clrc1.top, clrc1.right, clrc1.bottom, - cs->x, cs->y, cs->cx, cs->cy); - } - - /* allocate memory for info structure */ - infoPtr = (REBAR_INFO *)Alloc (sizeof(REBAR_INFO)); - SetWindowLongPtrW (hwnd, 0, (DWORD_PTR)infoPtr); - - /* initialize info structure - initial values are 0 */ - infoPtr->clrBk = CLR_NONE; - infoPtr->clrText = CLR_NONE; - infoPtr->clrBtnText = GetSysColor (COLOR_BTNTEXT); - infoPtr->clrBtnFace = GetSysColor (COLOR_BTNFACE); - infoPtr->iOldBand = -1; - infoPtr->ichevronhotBand = -2; - infoPtr->iGrabbedBand = -1; - infoPtr->hwndSelf = hwnd; - infoPtr->DoRedraw = TRUE; - infoPtr->hcurArrow = LoadCursorA (0, (LPSTR)IDC_ARROW); - infoPtr->hcurHorz = LoadCursorA (0, (LPSTR)IDC_SIZEWE); - infoPtr->hcurVert = LoadCursorA (0, (LPSTR)IDC_SIZENS); - infoPtr->hcurDrag = LoadCursorA (0, (LPSTR)IDC_SIZE); - infoPtr->bUnicode = IsWindowUnicode (hwnd); - infoPtr->fStatus = CREATE_RUNNING; - infoPtr->hFont = GetStockObject (SYSTEM_FONT); - - /* issue WM_NOTIFYFORMAT to get unicode status of parent */ - i = SendMessageA(REBAR_GetNotifyParent (infoPtr), - WM_NOTIFYFORMAT, (WPARAM)hwnd, NF_QUERY); - if ((i < NFR_ANSI) || (i > NFR_UNICODE)) { - ERR("wrong response to WM_NOTIFYFORMAT (%d), assuming ANSI\n", - i); - i = NFR_ANSI; - } - infoPtr->NtfUnicode = (i == NFR_UNICODE) ? 1 : 0; - - /* add necessary styles to the requested styles */ - infoPtr->dwStyle = cs->style | WS_VISIBLE | CCS_TOP; - SetWindowLongA (hwnd, GWL_STYLE, infoPtr->dwStyle); - - /* get font handle for Caption Font */ - ncm.cbSize = sizeof(NONCLIENTMETRICSA); - SystemParametersInfoA (SPI_GETNONCLIENTMETRICS, - ncm.cbSize, &ncm, 0); - /* if the font is bold, set to normal */ - if (ncm.lfCaptionFont.lfWeight > FW_NORMAL) { - ncm.lfCaptionFont.lfWeight = FW_NORMAL; - } - tfont = CreateFontIndirectA (&ncm.lfCaptionFont); - if (tfont) { - infoPtr->hFont = infoPtr->hDefaultFont = tfont; - } - -/* native does: - GetSysColor (numerous); - GetSysColorBrush (numerous) (see WM_SYSCOLORCHANGE); - *GetStockObject (SYSTEM_FONT); - *SetWindowLong (hwnd, 0, info ptr); - *WM_NOTIFYFORMAT; - *SetWindowLong (hwnd, GWL_STYLE, style+0x10000001); - WS_VISIBLE = 0x10000000; - CCS_TOP = 0x00000001; - *SystemParametersInfo (SPI_GETNONCLIENTMETRICS...); - *CreateFontIndirect (lfCaptionFont from above); - GetDC (); - SelectObject (hdc, fontabove); - GetTextMetrics (hdc, ); guessing is tmHeight - SelectObject (hdc, oldfont); - ReleaseDC (); - GetWindowRect (); - MapWindowPoints (0, parent, rectabove, 2); - GetWindowRect (); - GetClientRect (); - ClientToScreen (clientrect); - SetWindowPos (hwnd, 0, 0, 0, 0, 0, SWP_NOZORDER); - */ - return TRUE; -} - - -static LRESULT -REBAR_NCHitTest (REBAR_INFO *infoPtr, WPARAM wParam, LPARAM lParam) -{ - NMMOUSE nmmouse; - POINT clpt; - INT i; - UINT scrap; - LRESULT ret = HTCLIENT; - - /* - * Differences from doc at MSDN (as observed with version 4.71 of - * comctl32.dll - * 1. doc says nmmouse.pt is in screen coord, trace shows client coord. - * 2. if band is not identified .dwItemSpec is 0xffffffff. - * 3. native always seems to return HTCLIENT if notify return is 0. - */ - - clpt.x = (short)LOWORD(lParam); - clpt.y = (short)HIWORD(lParam); - ScreenToClient (infoPtr->hwndSelf, &clpt); - REBAR_InternalHitTest (infoPtr, &clpt, &scrap, - (INT *)&nmmouse.dwItemSpec); - nmmouse.dwItemData = 0; - nmmouse.pt = clpt; - nmmouse.dwHitInfo = 0; - if ((i = REBAR_Notify((NMHDR *) &nmmouse, infoPtr, NM_NCHITTEST))) { - TRACE("notify changed return value from %ld to %d\n", - ret, i); - ret = (LRESULT) i; - } - TRACE("returning %ld, client point (%ld,%ld)\n", ret, clpt.x, clpt.y); - return ret; -} - - -static LRESULT -REBAR_NCPaint (REBAR_INFO *infoPtr, WPARAM wParam, LPARAM lParam) -{ - RECT rcWindow; - HDC hdc; - - if (infoPtr->dwStyle & WS_MINIMIZE) - return 0; /* Nothing to do */ - - if (infoPtr->dwStyle & WS_BORDER) { - - /* adjust rectangle and draw the necessary edge */ - if (!(hdc = GetDCEx( infoPtr->hwndSelf, 0, DCX_USESTYLE | DCX_WINDOW ))) - return 0; - GetWindowRect (infoPtr->hwndSelf, &rcWindow); - OffsetRect (&rcWindow, -rcWindow.left, -rcWindow.top); - TRACE("rect (%ld,%ld)-(%ld,%ld)\n", - rcWindow.left, rcWindow.top, - rcWindow.right, rcWindow.bottom); - DrawEdge (hdc, &rcWindow, EDGE_ETCHED, BF_RECT); - ReleaseDC( infoPtr->hwndSelf, hdc ); - } - - return 0; -} - - -static LRESULT -REBAR_NotifyFormat (REBAR_INFO *infoPtr, WPARAM wParam, LPARAM lParam) -{ - INT i; - - if (lParam == NF_REQUERY) { - i = SendMessageA(REBAR_GetNotifyParent (infoPtr), - WM_NOTIFYFORMAT, (WPARAM)infoPtr->hwndSelf, NF_QUERY); - if ((i < NFR_ANSI) || (i > NFR_UNICODE)) { - ERR("wrong response to WM_NOTIFYFORMAT (%d), assuming ANSI\n", - i); - i = NFR_ANSI; - } - infoPtr->NtfUnicode = (i == NFR_UNICODE) ? 1 : 0; - return (LRESULT)i; - } - return (LRESULT)((infoPtr->bUnicode) ? NFR_UNICODE : NFR_ANSI); -} - - -static LRESULT -REBAR_Paint (REBAR_INFO *infoPtr, WPARAM wParam, LPARAM lParam) -{ - HDC hdc; - PAINTSTRUCT ps; - RECT rc; - - GetClientRect(infoPtr->hwndSelf, &rc); - hdc = wParam==0 ? BeginPaint (infoPtr->hwndSelf, &ps) : (HDC)wParam; - - TRACE("painting (%ld,%ld)-(%ld,%ld) client (%ld,%ld)-(%ld,%ld)\n", - ps.rcPaint.left, ps.rcPaint.top, - ps.rcPaint.right, ps.rcPaint.bottom, - rc.left, rc.top, rc.right, rc.bottom); - - if (ps.fErase) { - /* Erase area of paint if requested */ - REBAR_InternalEraseBkGnd (infoPtr, wParam, lParam, &ps.rcPaint); - } - - REBAR_Refresh (infoPtr, hdc); - if (!wParam) - EndPaint (infoPtr->hwndSelf, &ps); - return 0; -} - - -static LRESULT -REBAR_SetCursor (REBAR_INFO *infoPtr, WPARAM wParam, LPARAM lParam) -{ - POINT pt; - UINT flags; - - TRACE("code=0x%X id=0x%X\n", LOWORD(lParam), HIWORD(lParam)); - - GetCursorPos (&pt); - ScreenToClient (infoPtr->hwndSelf, &pt); - - REBAR_InternalHitTest (infoPtr, &pt, &flags, NULL); - - if (flags == RBHT_GRABBER) { - if ((infoPtr->dwStyle & CCS_VERT) && - !(infoPtr->dwStyle & RBS_VERTICALGRIPPER)) - SetCursor (infoPtr->hcurVert); - else - SetCursor (infoPtr->hcurHorz); - } - else if (flags != RBHT_CLIENT) - SetCursor (infoPtr->hcurArrow); - - return 0; -} - - -static LRESULT -REBAR_SetFont (REBAR_INFO *infoPtr, WPARAM wParam, LPARAM lParam) -{ - RECT rcClient; - REBAR_BAND *lpBand; - UINT i; - - infoPtr->hFont = (HFONT)wParam; - - /* revalidate all bands to change sizes of text in headers of bands */ - for (i=0; iuNumBands; i++) { - lpBand = &infoPtr->bands[i]; - REBAR_ValidateBand (infoPtr, lpBand); - } - - - if (LOWORD(lParam)) { - GetClientRect (infoPtr->hwndSelf, &rcClient); - REBAR_Layout (infoPtr, &rcClient, FALSE, TRUE); - } - - return 0; -} - - -inline static LRESULT -REBAR_SetRedraw (REBAR_INFO *infoPtr, WPARAM wParam, LPARAM lParam) - /***************************************************** - * - * Function; - * Handles the WM_SETREDRAW message. - * - * Documentation: - * According to testing V4.71 of COMCTL32 returns the - * *previous* status of the redraw flag (either 0 or -1) - * instead of the MSDN documented value of 0 if handled - * - *****************************************************/ -{ - BOOL oldredraw = infoPtr->DoRedraw; - - TRACE("set to %s, fStatus=%08x\n", - (wParam) ? "TRUE" : "FALSE", infoPtr->fStatus); - infoPtr->DoRedraw = (BOOL) wParam; - if (wParam) { - if (infoPtr->fStatus & BAND_NEEDS_REDRAW) { - REBAR_MoveChildWindows (infoPtr, 0, infoPtr->uNumBands); - REBAR_ForceResize (infoPtr); - InvalidateRect (infoPtr->hwndSelf, 0, TRUE); - } - infoPtr->fStatus &= ~BAND_NEEDS_REDRAW; - } - return (oldredraw) ? -1 : 0; -} - - -static LRESULT -REBAR_Size (REBAR_INFO *infoPtr, WPARAM wParam, LPARAM lParam) -{ - RECT rcClient; - - /* auto resize deadlock check */ - if (infoPtr->fStatus & AUTO_RESIZE) { - infoPtr->fStatus &= ~AUTO_RESIZE; - TRACE("AUTO_RESIZE was set, reset, fStatus=%08x lparam=%08lx\n", - infoPtr->fStatus, lParam); - return 0; - } - - if (infoPtr->fStatus & CREATE_RUNNING) { - /* still in CreateWindow */ - RECT rcWin; - - if ((INT)wParam != SIZE_RESTORED) { - ERR("WM_SIZE in create and flags=%08x, lParam=%08lx\n", - wParam, lParam); - } - - TRACE("still in CreateWindow\n"); - infoPtr->fStatus &= ~CREATE_RUNNING; - GetWindowRect ( infoPtr->hwndSelf, &rcWin); - TRACE("win rect (%ld,%ld)-(%ld,%ld)\n", - rcWin.left, rcWin.top, rcWin.right, rcWin.bottom); - - if ((lParam == 0) && (rcWin.right-rcWin.left == 0) && - (rcWin.bottom-rcWin.top == 0)) { - /* native control seems to do this */ - GetClientRect (GetParent(infoPtr->hwndSelf), &rcClient); - TRACE("sizing rebar, message and client zero, parent client (%ld,%ld)\n", - rcClient.right, rcClient.bottom); - } - else { - INT cx, cy; - - cx = rcWin.right - rcWin.left; - cy = rcWin.bottom - rcWin.top; - if ((cx == LOWORD(lParam)) && (cy == HIWORD(lParam))) { - return 0; - } - - /* do the actual WM_SIZE request */ - GetClientRect (infoPtr->hwndSelf, &rcClient); - TRACE("sizing rebar from (%ld,%ld) to (%d,%d), client (%ld,%ld)\n", - infoPtr->calcSize.cx, infoPtr->calcSize.cy, - LOWORD(lParam), HIWORD(lParam), - rcClient.right, rcClient.bottom); - } - } - else { - if ((INT)wParam != SIZE_RESTORED) { - ERR("WM_SIZE out of create and flags=%08x, lParam=%08lx\n", - wParam, lParam); - } - - /* Handle cases when outside of the CreateWindow process */ - - GetClientRect (infoPtr->hwndSelf, &rcClient); - if ((lParam == 0) && (rcClient.right + rcClient.bottom != 0) && - (infoPtr->dwStyle & RBS_AUTOSIZE)) { - /* on a WM_SIZE to zero and current client not zero and AUTOSIZE */ - /* native seems to use the current client rect for the size */ - infoPtr->fStatus |= BAND_NEEDS_LAYOUT; - TRACE("sizing rebar to client (%ld,%ld) size is zero but AUTOSIZE set\n", - rcClient.right, rcClient.bottom); - } - else { - TRACE("sizing rebar from (%ld,%ld) to (%d,%d), client (%ld,%ld)\n", - infoPtr->calcSize.cx, infoPtr->calcSize.cy, - LOWORD(lParam), HIWORD(lParam), - rcClient.right, rcClient.bottom); - } - } - - if (infoPtr->dwStyle & RBS_AUTOSIZE) { - NMRBAUTOSIZE autosize; - - GetClientRect(infoPtr->hwndSelf, &autosize.rcTarget); - autosize.fChanged = 0; /* ??? */ - autosize.rcActual = autosize.rcTarget; /* ??? */ - REBAR_Notify((NMHDR *) &autosize, infoPtr, RBN_AUTOSIZE); - TRACE("RBN_AUTOSIZE client=(%ld,%ld), lp=%08lx\n", - autosize.rcTarget.right, autosize.rcTarget.bottom, lParam); - } - - if ((infoPtr->calcSize.cx != rcClient.right) || - (infoPtr->calcSize.cy != rcClient.bottom)) - infoPtr->fStatus |= BAND_NEEDS_LAYOUT; - - REBAR_Layout (infoPtr, &rcClient, TRUE, TRUE); - - return 0; -} - - -static LRESULT -REBAR_StyleChanged (REBAR_INFO *infoPtr, WPARAM wParam, LPARAM lParam) -{ - STYLESTRUCT *ss = (STYLESTRUCT *)lParam; - - TRACE("current style=%08lx, styleOld=%08lx, style being set to=%08lx\n", - infoPtr->dwStyle, ss->styleOld, ss->styleNew); - infoPtr->dwStyle = ss->styleNew; - - return FALSE; -} - - -static LRESULT -REBAR_WindowPosChanged (REBAR_INFO *infoPtr, WPARAM wParam, LPARAM lParam) -{ - WINDOWPOS *lpwp = (WINDOWPOS *)lParam; - LRESULT ret; - RECT rc; - - /* Save the new origin of this window - used by _ForceResize */ - infoPtr->origin.x = lpwp->x; - infoPtr->origin.y = lpwp->y; - ret = DefWindowProcA(infoPtr->hwndSelf, WM_WINDOWPOSCHANGED, - wParam, lParam); - GetWindowRect(infoPtr->hwndSelf, &rc); - TRACE("hwnd %p new pos (%ld,%ld)-(%ld,%ld)\n", - infoPtr->hwndSelf, rc.left, rc.top, rc.right, rc.bottom); - return ret; -} - - -static LRESULT WINAPI -REBAR_WindowProc (HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam) -{ - REBAR_INFO *infoPtr = REBAR_GetInfoPtr (hwnd); - - TRACE("hwnd=%p msg=%x wparam=%x lparam=%lx\n", - hwnd, uMsg, wParam, lParam); - if (!infoPtr && (uMsg != WM_NCCREATE)) - return DefWindowProcA (hwnd, uMsg, wParam, lParam); - switch (uMsg) - { -/* case RB_BEGINDRAG: */ - - case RB_DELETEBAND: - return REBAR_DeleteBand (infoPtr, wParam, lParam); - -/* case RB_DRAGMOVE: */ -/* case RB_ENDDRAG: */ - - case RB_GETBANDBORDERS: - return REBAR_GetBandBorders (infoPtr, wParam, lParam); - - case RB_GETBANDCOUNT: - return REBAR_GetBandCount (infoPtr); - - case RB_GETBANDINFO_OLD: - case RB_GETBANDINFOA: - return REBAR_GetBandInfoA (infoPtr, wParam, lParam); - - case RB_GETBANDINFOW: - return REBAR_GetBandInfoW (infoPtr, wParam, lParam); - - case RB_GETBARHEIGHT: - return REBAR_GetBarHeight (infoPtr, wParam, lParam); - - case RB_GETBARINFO: - return REBAR_GetBarInfo (infoPtr, wParam, lParam); - - case RB_GETBKCOLOR: - return REBAR_GetBkColor (infoPtr); - -/* case RB_GETCOLORSCHEME: */ -/* case RB_GETDROPTARGET: */ - - case RB_GETPALETTE: - return REBAR_GetPalette (infoPtr, wParam, lParam); - - case RB_GETRECT: - return REBAR_GetRect (infoPtr, wParam, lParam); - - case RB_GETROWCOUNT: - return REBAR_GetRowCount (infoPtr); - - case RB_GETROWHEIGHT: - return REBAR_GetRowHeight (infoPtr, wParam, lParam); - - case RB_GETTEXTCOLOR: - return REBAR_GetTextColor (infoPtr); - - case RB_GETTOOLTIPS: - return REBAR_GetToolTips (infoPtr); - - case RB_GETUNICODEFORMAT: - return REBAR_GetUnicodeFormat (infoPtr); - - case CCM_GETVERSION: - return REBAR_GetVersion (infoPtr); - - case RB_HITTEST: - return REBAR_HitTest (infoPtr, wParam, lParam); - - case RB_IDTOINDEX: - return REBAR_IdToIndex (infoPtr, wParam, lParam); - - case RB_INSERTBANDA: - return REBAR_InsertBandA (infoPtr, wParam, lParam); - - case RB_INSERTBANDW: - return REBAR_InsertBandW (infoPtr, wParam, lParam); - - case RB_MAXIMIZEBAND: - return REBAR_MaximizeBand (infoPtr, wParam, lParam); - - case RB_MINIMIZEBAND: - return REBAR_MinimizeBand (infoPtr, wParam, lParam); - - case RB_MOVEBAND: - return REBAR_MoveBand (infoPtr, wParam, lParam); - - case RB_PUSHCHEVRON: - return REBAR_PushChevron (infoPtr, wParam, lParam); - - case RB_SETBANDINFOA: - return REBAR_SetBandInfoA (infoPtr, wParam, lParam); - - case RB_SETBANDINFOW: - return REBAR_SetBandInfoW (infoPtr, wParam, lParam); - - case RB_SETBARINFO: - return REBAR_SetBarInfo (infoPtr, wParam, lParam); - - case RB_SETBKCOLOR: - return REBAR_SetBkColor (infoPtr, wParam, lParam); - -/* case RB_SETCOLORSCHEME: */ -/* case RB_SETPALETTE: */ -/* return REBAR_GetPalette (infoPtr, wParam, lParam); */ - - case RB_SETPARENT: - return REBAR_SetParent (infoPtr, wParam, lParam); - - case RB_SETTEXTCOLOR: - return REBAR_SetTextColor (infoPtr, wParam, lParam); - -/* case RB_SETTOOLTIPS: */ - - case RB_SETUNICODEFORMAT: - return REBAR_SetUnicodeFormat (infoPtr, wParam); - - case CCM_SETVERSION: - return REBAR_SetVersion (infoPtr, (INT)wParam); - - case RB_SHOWBAND: - return REBAR_ShowBand (infoPtr, wParam, lParam); - - case RB_SIZETORECT: - return REBAR_SizeToRect (infoPtr, wParam, lParam); - - -/* Messages passed to parent */ - case WM_COMMAND: - case WM_DRAWITEM: - case WM_NOTIFY: - if (infoPtr->NtfUnicode) - return SendMessageW (REBAR_GetNotifyParent (infoPtr), - uMsg, wParam, lParam); - else - return SendMessageA (REBAR_GetNotifyParent (infoPtr), - uMsg, wParam, lParam); - - -/* case WM_CHARTOITEM: supported according to ControlSpy */ - - case WM_CREATE: - return REBAR_Create (infoPtr, wParam, lParam); - - case WM_DESTROY: - return REBAR_Destroy (infoPtr, wParam, lParam); - - case WM_ERASEBKGND: - return REBAR_EraseBkGnd (infoPtr, wParam, lParam); - - case WM_GETFONT: - return REBAR_GetFont (infoPtr, wParam, lParam); - -/* case WM_LBUTTONDBLCLK: supported according to ControlSpy */ - - case WM_LBUTTONDOWN: - return REBAR_LButtonDown (infoPtr, wParam, lParam); - - case WM_LBUTTONUP: - return REBAR_LButtonUp (infoPtr, wParam, lParam); - -/* case WM_MEASUREITEM: supported according to ControlSpy */ - - case WM_MOUSEMOVE: - return REBAR_MouseMove (infoPtr, wParam, lParam); - - case WM_MOUSELEAVE: - return REBAR_MouseLeave (infoPtr, wParam, lParam); - - case WM_NCCALCSIZE: - return REBAR_NCCalcSize (infoPtr, wParam, lParam); - - case WM_NCCREATE: - return REBAR_NCCreate (hwnd, wParam, lParam); - - case WM_NCHITTEST: - return REBAR_NCHitTest (infoPtr, wParam, lParam); - - case WM_NCPAINT: - return REBAR_NCPaint (infoPtr, wParam, lParam); - - case WM_NOTIFYFORMAT: - return REBAR_NotifyFormat (infoPtr, wParam, lParam); - - case WM_PAINT: - return REBAR_Paint (infoPtr, wParam, lParam); - -/* case WM_PALETTECHANGED: supported according to ControlSpy */ -/* case WM_PRINTCLIENT: supported according to ControlSpy */ -/* case WM_QUERYNEWPALETTE:supported according to ControlSpy */ -/* case WM_RBUTTONDOWN: supported according to ControlSpy */ -/* case WM_RBUTTONUP: supported according to ControlSpy */ - - case WM_SETCURSOR: - return REBAR_SetCursor (infoPtr, wParam, lParam); - - case WM_SETFONT: - return REBAR_SetFont (infoPtr, wParam, lParam); - - case WM_SETREDRAW: - return REBAR_SetRedraw (infoPtr, wParam, lParam); - - case WM_SIZE: - return REBAR_Size (infoPtr, wParam, lParam); - - case WM_STYLECHANGED: - return REBAR_StyleChanged (infoPtr, wParam, lParam); - -/* case WM_SYSCOLORCHANGE: supported according to ControlSpy */ -/* "Applications that have brushes using the existing system colors - should delete those brushes and recreate them using the new - system colors." per MSDN */ - -/* case WM_VKEYTOITEM: supported according to ControlSpy */ -/* case WM_WININICHANGE: */ - - case WM_WINDOWPOSCHANGED: - return REBAR_WindowPosChanged (infoPtr, wParam, lParam); - - default: - if ((uMsg >= WM_USER) && (uMsg < WM_APP)) - ERR("unknown msg %04x wp=%08x lp=%08lx\n", - uMsg, wParam, lParam); - return DefWindowProcA (hwnd, uMsg, wParam, lParam); - } - return 0; -} - - -VOID -REBAR_Register (void) -{ - WNDCLASSA wndClass; - - ZeroMemory (&wndClass, sizeof(WNDCLASSA)); - wndClass.style = CS_GLOBALCLASS | CS_DBLCLKS; - wndClass.lpfnWndProc = REBAR_WindowProc; - wndClass.cbClsExtra = 0; - wndClass.cbWndExtra = sizeof(REBAR_INFO *); - wndClass.hCursor = 0; - wndClass.hbrBackground = (HBRUSH)(COLOR_BTNFACE + 1); -#if GLATESTING - wndClass.hbrBackground = CreateSolidBrush(RGB(0,128,0)); -#endif - wndClass.lpszClassName = REBARCLASSNAMEA; - - RegisterClassA (&wndClass); - - mindragx = GetSystemMetrics (SM_CXDRAG); - mindragy = GetSystemMetrics (SM_CYDRAG); - -} - - -VOID -REBAR_Unregister (void) -{ - UnregisterClassA (REBARCLASSNAMEA, NULL); -} diff --git a/reactos/lib/comctl32/rsrc.rc b/reactos/lib/comctl32/rsrc.rc deleted file mode 100644 index f86bda1b4fc..00000000000 --- a/reactos/lib/comctl32/rsrc.rc +++ /dev/null @@ -1,1210 +0,0 @@ -/* - * Top level resource file for Common Controls - * - * Copyright 1999 Bertho Stultiens - * Copyright 1999 Eric Kohl - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2.1 of the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -#include "windef.h" -#include "winbase.h" -#include "winuser.h" -#include "winnls.h" -#include "comctl32.h" - -LANGUAGE LANG_NEUTRAL, SUBLANG_NEUTRAL - -#include "wine/wine_common_ver.rc" - -/* BINRES idt_check.bmp */ -IDT_CHECK BITMAP LOADONCALL DISCARDABLE idt_check.bmp -/* { - '42 4D 8E 01 00 00 00 00 00 00 5E 00 00 00 28 00' - '00 00 1F 00 00 00 10 00 00 00 01 00 04 00 02 00' - '00 00 30 01 00 00 01 00 00 00 01 00 00 00 0A 00' - '00 00 0A 00 00 00 00 00 00 00 00 00 80 00 00 80' - '00 00 80 00 00 00 C0 C0 C0 00 80 80 80 00 00 FF' - '00 00 00 FF FF 00 FF 00 00 00 FF FF FF 00 1F 99' - '00 00 01 99 0D 11 02 99 0E 11 01 99 00 00 01 99' - '0D 11 02 99 0E 11 01 99 00 00 01 99 02 11 09 99' - '02 11 02 99 02 11 0A 99 02 11 01 99 00 00 01 99' - '02 11 09 99 02 11 02 99 02 11 0A 99 02 11 01 99' - '00 00 01 99 02 11 09 99 02 11 02 99 02 11 03 99' - '02 00 05 99 02 11 01 99 00 00 01 99 02 11 09 99' - '02 11 02 99 02 11 03 99 03 00 04 99 02 11 01 99' - '00 00 01 99 02 11 09 99 02 11 02 99 02 11 02 99' - '04 00 04 99 02 11 01 99 00 00 01 99 02 11 09 99' - '02 11 02 99 02 11 01 99 02 00 02 99 02 00 03 99' - '02 11 01 99 00 00 01 99 02 11 09 99 02 11 02 99' - '02 11 02 00 04 99 02 00 02 99 02 11 01 99 00 00' - '01 99 02 11 09 99 02 11 02 99 02 11 01 00 06 99' - '02 00 01 99 02 11 01 99 00 00 01 99 02 11 09 99' - '02 11 02 99 02 11 07 99 02 00 01 99 01 00 01 11' - '01 99 00 00 01 99 02 11 09 99 02 11 02 99 02 11' - '08 99 01 00 01 99 01 00 01 11 01 99 00 00 01 99' - '0D 11 02 99 0A 11 02 00 02 11 01 99 00 00 01 99' - '0D 11 02 99 0E 11 01 99 00 00 1F 99 00 01' -} */ - -/* BINRES idb_std_small.bmp */ -IDB_STD_SMALL BITMAP LOADONCALL DISCARDABLE idb_std_small.bmp -/* { - '42 4D 20 07 00 00 00 00 00 00 76 00 00 00 28 00' - '00 00 F0 00 00 00 10 00 00 00 01 00 04 00 02 00' - '00 00 AA 06 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 FF FF FF 00 00 00 80 00 00 80' - '00 00 00 80 80 00 80 00 00 00 80 00 80 00 00 00' - '00 00 80 80 80 00 C0 C0 C0 00 00 00 FF 00 00 FF' - '00 00 00 FF FF 00 FF 00 00 00 FF 00 FF 00 FF FF' - '00 00 00 66 66 00 CC 88 02 44 22 88 00 00 04 88' - '00 04 84 48 1E 88 0A 44 52 88 0C 66 02 68 0C 66' - '02 88 0E 66 08 88 00 04 86 68 12 88 04 84 02 48' - '08 88 02 44 08 88 0A 66 00 04 68 88 00 00 04 88' - '00 08 48 84 88 44 0A 88 02 84 08 44 02 86 04 66' - '02 40 06 00 02 04 22 88 02 86 0A 88 00 04 68 88' - '0A 66 00 04 68 88 0A 66 02 68 04 88 00 04 86 33' - '06 66 00 08 88 63 68 60 08 00 00 08 06 86 66 60' - '08 00 02 06 08 88 00 04 86 68 12 88 00 06 48 44' - '48 00 06 88 00 04 84 44 06 88 02 86 08 88 04 86' - '02 88 00 00 04 88 02 48 04 84 00 04 88 48 08 88' - '02 84 06 00 00 04 04 67 04 37 02 40 06 66 02 04' - '22 88 00 04 66 68 0C 88 02 60 08 00 00 06 68 88' - '66 00 08 33 02 36 04 88 00 04 86 33 06 66 00 08' - '88 63 68 60 06 00 06 66 00 08 68 60 66 06 04 66' - '02 06 08 88 02 66 04 88 00 04 44 48 0A 88 04 84' - '02 44 04 88 04 66 00 04 44 48 06 88 0C 66 04 68' - '00 00 04 88 02 48 04 84 00 04 88 48 08 88 00 04' - '84 06 04 66 00 04 04 63 04 73 02 40 06 00 02 04' - '22 88 04 66 06 88 02 86 04 88 02 60 08 00 00 08' - '68 88 6B 63 08 33 00 08 68 88 86 33 06 66 00 08' - '88 63 68 60 04 00 00 0C 06 78 87 66 88 60 08 00' - '02 06 04 88 00 06 68 88 66 00 04 88 00 04 44 48' - '06 88 04 66 00 10 48 44 48 88 86 78 07 64 04 88' - '00 06 18 88 68 00 04 88 00 0A 8B BB 88 66 68 00' - '00 00 04 88 00 0E 84 44 84 88 48 88 86 00 04 66' - '02 64 06 00 00 04 04 67 04 37 00 06 40 66 60 00' - '04 44 0C 88 02 48 04 88 02 84 0E 88 00 04 86 66' - '06 88 02 68 04 88 02 60 08 00 00 08 68 88 60 B6' - '08 33 00 08 36 88 86 33 08 66 00 06 63 68 60 00' - '04 00 00 10 67 88 E7 76 88 60 66 06 04 66 02 06' - '04 88 00 06 66 86 68 00 0C 88 00 0A 66 88 80 74' - '44 00 04 88 00 12 67 88 80 76 88 81 18 88 68 00' - '04 88 00 06 87 77 88 00 04 68 00 00 06 88 04 84' - '02 44 04 88 02 86 04 00 00 04 04 06 04 66 00 04' - '04 63 04 73 02 40 04 00 00 06 40 48 88 00 04 44' - '02 48 04 88 02 48 04 88 02 84 04 88 02 84 04 44' - '06 88 00 0A 66 68 88 86 68 00 04 88 02 60 08 00' - '00 0A 68 88 6B 0B 63 00 08 33 00 04 68 86 0C 33' - '00 04 68 60 04 00 00 0C 68 88 87 86 88 60 08 00' - '02 06 04 88 04 66 02 68 04 88 00 0A 44 48 88 86' - '78 00 04 88 00 04 07 68 04 88 02 68 04 88 00 04' - '06 88 04 11 02 18 0C 66 00 04 68 86 00 00 06 88' - '00 04 84 64 06 88 00 08 86 06 66 64 06 00 00 04' - '04 67 04 37 02 40 04 00 02 44 04 88 04 44 06 88' - '02 84 04 88 02 48 06 88 04 44 06 88 00 08 86 66' - '88 66 06 88 02 60 08 00 00 0A 68 88 60 B0 B6 00' - '0A 66 00 04 86 33 08 66 00 06 33 68 60 00 04 00' - '00 0C 68 E8 87 86 88 60 06 00 00 04 60 06 04 88' - '08 66 00 0A 88 44 48 88 86 00 06 88 00 04 80 68' - '04 88 00 12 68 0E 88 86 88 81 18 81 68 00 08 88' - '06 86 00 00 08 88 02 68 06 88 02 86 04 00 00 06' - '04 06 60 00 04 44 02 63 04 73 06 44 02 46 04 88' - '00 04 44 48 06 88 02 84 04 88 02 48 06 88 00 04' - '84 44 08 88 04 66 02 68 06 88 02 60 08 00 00 06' - '68 88 6B 00 08 0B 02 68 04 88 00 04 86 36 08 88' - '00 06 63 68 60 00 04 00 00 16 67 EE 87 76 88 60' - '66 00 06 86 06 00 04 88 06 66 00 0C 68 88 84 44' - '88 68 08 88 02 86 04 88 00 08 67 00 88 76 04 88' - '00 06 18 81 86 00 08 66 04 68 02 66 00 00 06 88' - '00 04 86 66 06 88 00 08 86 06 66 64 04 00 00 06' - '40 48 67 00 0A 37 02 36 04 88 00 04 44 84 06 88' - '02 84 04 88 02 48 06 88 00 04 48 44 08 88 00 04' - '86 66 08 88 02 60 08 00 00 06 68 88 60 00 08 B0' - '02 68 04 88 00 04 86 36 08 88 00 06 63 68 60 00' - '04 00 00 10 06 78 87 68 88 60 68 60 04 68 00 06' - '66 68 44 00 06 66 06 88 00 06 44 48 68 00 08 88' - '02 86 04 88 00 08 86 78 87 68 06 88 00 06 81 88' - '60 00 06 00 02 06 04 86 00 00 06 88 04 86 06 88' - '02 86 04 00 02 04 04 00 00 08 44 88 63 76 06 66' - '00 04 67 76 04 88 00 06 48 88 44 00 04 88 02 48' - '04 88 02 84 04 88 00 06 44 88 84 00 08 88 04 66' - '02 68 06 88 02 60 08 00 00 08 68 88 6B 0B 06 66' - '02 68 04 88 00 04 86 36 08 88 00 06 63 68 60 00' - '06 00 04 66 04 88 00 04 60 06 06 86 00 06 88 86' - '44 00 04 66 00 10 68 84 44 88 84 44 68 0E 06 88' - '02 86 06 88 04 66 00 04 88 81 08 88 00 04 86 06' - '04 66 00 06 06 66 68 00 00 00 06 88 00 06 66 86' - '68 00 04 88 00 08 86 06 60 64 04 44 00 08 48 88' - '67 76 06 88 00 04 67 36 0A 88 04 44 08 88 04 44' - '0C 88 00 08 86 66 88 66 06 88 02 60 04 00 00 0C' - '06 66 68 88 86 66 08 88 00 08 66 68 86 36 08 88' - '00 06 63 68 60 00 08 00 02 06 04 88 04 66 06 68' - '04 88 02 44 04 66 00 10 88 84 44 88 84 44 68 0E' - '06 88 02 86 0C 88 00 06 81 88 18 00 04 88 02 86' - '08 00 00 04 68 88 00 00 06 88 00 06 68 88 68 00' - '04 88 02 86 04 00 00 04 60 68 06 88 00 0E 63 73' - '6B 66 B6 73 76 00 24 88 00 0C 86 66 68 88 86 68' - '04 88 02 60 04 00 04 06 10 88 00 08 86 68 86 36' - '08 88 00 06 66 68 60 00 06 00 04 66 08 88 04 86' - '06 88 00 18 44 66 68 88 84 44 88 84 44 86 00 EE' - '04 88 02 68 0C 88 00 06 81 88 11 00 06 88 02 60' - '04 66 00 06 60 68 88 00 00 00 06 88 00 06 68 88' - '68 00 04 88 02 86 04 00 02 66 08 88 02 86 04 66' - '02 BB 04 66 02 68 24 88 04 66 06 88 02 66 04 88' - '02 60 04 00 00 04 06 68 0C 88 00 04 68 88 04 68' - '00 04 86 36 08 88 04 68 02 60 06 00 04 68 0A 88' - '02 68 04 88 00 06 86 44 66 00 06 88 06 44 00 0E' - '48 86 70 00 88 87 68 00 0E 88 04 11 02 18 04 88' - '02 60 06 00 00 04 06 88 00 00 06 88 00 06 68 88' - '68 00 04 88 02 86 04 66 02 68 0C 88 00 06 86 66' - '68 00 28 88 00 04 66 68 08 88 00 04 68 88 08 66' - '0E 88 00 04 86 66 04 88 02 86 0C 66 00 04 68 60' - '06 00 02 66 0C 88 02 86 04 66 00 06 68 44 68 00' - '06 88 02 84 04 44 04 88 02 66 04 88 02 66 12 88' - '02 11 06 88 02 86 08 66 02 88 00 00 90 88 08 66' - '02 68 2A 88 04 66 14 88 02 18 12 88 00 00 00 01' -} */ - -/* BINRES idb_std_large.bmp */ -IDB_STD_LARGE BITMAP LOADONCALL DISCARDABLE idb_std_large.bmp -/* { - '42 4D D6 0A 00 00 00 00 00 00 76 00 00 00 28 00' - '00 00 68 01 00 00 18 00 00 00 01 00 04 00 02 00' - '00 00 60 0A 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 80 00 00 80' - '00 00 00 80 80 00 80 00 00 00 80 00 80 00 00 80' - '00 00 C0 C0 C0 00 80 80 80 00 00 00 FF 00 00 FF' - '00 00 00 FF FF 00 FF 00 00 00 FF 00 FF 00 FF FF' - '00 00 FF FF FF 00 FF 77 69 77 00 00 07 77 03 44' - 'FF 77 5F 77 00 00 06 77 01 47 03 77 01 47 14 77' - '0E 44 5F 77 01 07 06 77 11 00 1F 77 12 00 19 77' - '02 00 03 77 10 00 30 77 02 44 10 77 02 44 0C 77' - '10 00 05 77 00 00 06 77 01 47 03 77 01 47 04 77' - '03 44 0D 77 01 4F 0C FF 01 47 0D 77 0B 44 34 77' - '04 00 16 77 01 0F 0F FF 01 07 04 77 11 00 09 77' - '01 03 03 33 09 00 03 77 00 04 03 30 04 77 10 00' - '03 77 03 00 03 77 01 0F 0E FF 01 07 0E 77 03 00' - '1E 77 03 47 01 47 0E 77 03 47 01 47 0A 77 01 07' - '0E 77 04 07 03 77 00 00 06 77 01 47 03 77 01 47' - '03 77 01 47 03 77 01 47 0C 77 01 4F 0C FF 01 47' - '0D 77 01 4F 09 FF 01 47 34 77 05 00 0D 77 01 07' - '07 77 01 0F 0F FF 01 07 04 77 02 00 0F 33 01 07' - '08 77 01 03 03 33 09 00 03 77 00 04 03 30 04 77' - '01 0F 0E FF 01 07 02 77 04 00 03 77 01 0F 0E FF' - '01 07 0E 77 03 00 04 77 03 44 16 77 03 47 02 44' - '0D 77 03 47 02 44 0A 77 01 07 0E 77 02 07 03 70' - '02 77 00 00 06 77 01 47 03 77 01 47 03 77 01 47' - '03 77 01 47 0C 77 01 4F 02 FF 08 00 01 FF 02 F4' - '0D 77 02 4F 07 00 02 F4 34 77 05 00 0C 77 01 07' - '08 77 01 0F 0F FF 01 07 04 77 03 0F 0F 33 01 07' - '07 77 01 03 03 33 09 00 03 77 00 04 03 30 04 77' - '01 0F 0A FF 0A 00 04 77 00 04 0F F0 03 0F 06 00' - '01 FF 02 F0 0D 77 03 00 04 77 05 44 14 77 03 47' - '02 44 0D 77 03 47 02 44 0A 77 12 00 01 77 03 70' - '01 70 00 00 06 77 01 47 03 77 01 47 03 77 01 47' - '03 77 01 47 06 77 06 00 01 4F 0C FF 01 47 06 77' - '07 00 01 4F 09 FF 01 47 35 77 05 00 0A 77 02 00' - '08 77 01 0F 0F FF 01 07 04 77 00 04 0B F0 0F 33' - '01 07 06 77 01 03 03 33 09 00 03 77 00 04 03 30' - '04 77 01 0F 09 FF 02 08 03 77 01 80 04 00 05 77' - '01 0F 0E FF 01 07 07 77 01 07 05 77 03 00 05 77' - '03 44 14 77 03 47 02 44 09 77 04 00 03 47 02 44' - '0B 77 01 07 10 77 01 00 02 07 03 70 00 00 07 77' - '04 44 03 77 01 47 03 77 01 47 06 77 01 0F 05 FF' - '01 4F 02 FF 08 00 01 FF 02 F4 05 77 01 03 07 38' - '02 4F 07 00 02 F4 12 77 02 44 0D 77 02 44 13 77' - '04 00 09 77 02 00 09 77 01 0F 0F FF 01 07 04 77' - '01 0F 03 FB 01 03 0F 33 01 07 05 77 01 03 03 33' - '09 00 03 77 00 04 03 30 04 77 01 0F 08 FF 00 0A' - '08 77 EE 88 00 77 06 77 00 04 0F F0 03 0F 06 00' - '01 FF 02 F0 07 77 02 00 03 77 03 00 15 77 05 00' - '01 77 04 74 02 44 08 77 02 00 03 77 02 F8 03 44' - '0C 77 01 07 0B 77 03 BB 01 77 07 70 00 00 0A 77' - '01 47 03 77 04 44 07 77 01 0F 05 FF 01 4F 0C FF' - '01 47 05 77 01 08 07 83 01 4F 09 FF 01 47 14 77' - '01 47 0B 77 01 47 16 77 04 00 07 77 03 00 09 77' - '01 0F 0F FF 01 07 04 77 01 0B 04 BF 01 03 0F 33' - '01 07 04 77 01 03 03 33 0D 00 01 33 02 30 04 77' - '01 0F 07 FF 02 08 05 77 00 04 E7 80 06 77 01 0F' - '0E FF 01 07 07 77 03 00 02 77 03 00 06 77 03 44' - '0A 77 02 00 05 77 01 00 02 07 03 44 08 77 02 08' - '05 77 01 F8 02 80 0D 77 01 07 0B 77 03 88 01 77' - '03 70 02 70 02 07 00 00 0A 77 01 44 03 47 01 47' - '0A 77 01 0F 02 FF 03 00 01 4F 02 FF 08 00 01 FF' - '02 F4 05 77 01 03 07 38 02 4F 03 00 02 FF 04 44' - '06 77 06 44 09 77 01 47 09 77 01 47 09 77 06 44' - '09 77 04 00 05 77 03 00 0A 77 01 0F 0F FF 01 07' - '04 77 01 0F 05 FB 01 03 0F 33 01 07 03 77 01 03' - '12 33 01 07 04 77 01 0F 07 FF 01 07 06 77 02 8E' - '03 70 05 77 00 04 0F F0 03 0F 06 00 01 FF 02 F0' - '07 77 07 00 07 77 03 44 09 77 02 08 05 77 01 FF' - '02 F8 03 44 09 77 01 07 07 77 02 F0 06 77 01 17' - '06 77 13 00 01 77 03 70 00 00 0B 77 04 47 0A 77' - '01 0F 05 FF 01 4F 0C FF 01 47 05 77 01 08 07 83' - '01 4F 06 FF 03 4F 07 77 05 44 0B 77 01 47 07 77' - '01 47 0B 77 05 44 0A 77 04 00 03 77 03 00 0B 77' - '01 0F 0F FF 01 07 04 77 01 0B 06 BF 01 03 0F 33' - '00 04 07 70 12 33 01 07 04 77 01 0F 07 FF 01 07' - '06 77 02 8E 03 70 05 77 01 0F 0E FF 01 07 07 77' - '0B 00 03 77 03 44 08 77 02 08 08 77 01 F8 02 80' - '09 77 01 07 0A 77 01 07 04 77 02 11 06 77 01 07' - '10 77 04 07 02 70 00 00 0B 77 03 40 0B 77 01 0F' - '02 FF 03 00 01 4F 02 FF 08 00 01 FF 02 F4 05 77' - '01 03 07 38 01 4F 06 FF 02 44 08 77 04 44 0C 77' - '01 47 07 77 01 47 0C 77 04 44 0B 77 04 00 01 70' - '03 00 0C 77 01 0F 0F FF 01 07 04 77 01 0F 07 FB' - '10 00 01 77 02 70 03 33 0C 00 03 33 01 07 04 77' - '01 0F 07 FF 01 07 03 7E 03 77 02 87 03 70 05 77' - '00 04 0F F0 03 0F 06 00 01 FF 02 F0 07 77 0A 00' - '05 77 03 44 07 77 01 07 0A 77 02 F0 09 77 01 07' - '0A 77 01 07 03 77 06 11 04 77 01 07 0F 77 02 07' - '04 70 00 00 0C 77 01 07 0C 77 01 0F 05 FF 01 4F' - '0C FF 01 47 05 77 01 08 07 83 08 44 09 77 04 44' - '0C 77 01 47 07 77 01 47 0C 77 04 44 0C 77 06 00' - '0D 77 01 0F 0F FF 01 07 04 77 01 0B 10 BF 01 07' - '08 77 00 04 03 30 0C 77 00 04 03 30 04 77 01 0F' - '07 FF 01 08 02 8E 04 77 03 87 01 07 06 77 01 0F' - '0E FF 01 07 07 77 09 00 07 77 03 44 05 77 01 07' - '0B 77 01 F7 03 70 07 77 00 04 07 FE 07 77 01 07' - '04 77 02 11 03 77 01 17 04 77 0F 00 03 70 02 70' - '01 00 00 00 0B 77 03 00 0B 77 01 0F 02 FF 03 00' - '01 4F 02 FF 04 00 02 FF 05 44 05 77 01 03 0E 38' - '01 07 09 77 01 44 02 47 03 74 0A 77 01 47 07 77' - '01 47 0B 77 00 05 47 74 47 88 0D 77 04 00 0E 77' - '01 0F 0F FF 01 07 04 77 01 0F 10 FB 01 07 08 77' - '00 04 03 30 0C 77 00 04 03 30 04 77 01 0F 08 FF' - '00 09 08 EE 77 88 07 68 07 77 01 0F 09 FF 01 0F' - '04 FF 01 07 07 77 08 00 02 77 03 44 04 77 03 44' - '04 77 01 07 03 7F 0A 77 01 07 08 77 00 04 07 FE' - '07 77 01 07 05 77 01 17 03 77 01 17 05 77 01 0F' - '0C FF 01 00 04 07 02 70 00 00 0B 77 04 07 0A 77' - '01 0F 05 FF 01 4F 08 FF 00 04 4F F4 06 77 01 08' - '0E 83 01 07 09 77 01 47 04 77 01 47 09 77 01 47' - '09 77 01 47 09 77 01 47 04 77 01 47 0C 77 06 00' - '0D 77 01 0F 0F FF 01 07 04 77 01 0B 10 BF 01 07' - '08 77 00 04 03 30 0C 77 00 04 03 30 04 77 01 0F' - '09 FF 02 08 03 77 02 80 08 77 01 0F 03 FF 02 00' - '03 FF 03 07 03 FF 01 07 07 77 07 00 03 77 03 44' - '04 77 04 44 03 77 00 04 07 FE 0A 77 01 07 09 77' - '00 05 0F FE E7 88 04 77 01 07 0A 77 01 17 05 77' - '01 0F 02 FF 08 00 02 FF 03 00 04 70 00 00 0A 77' - '01 00 03 07 01 07 0A 77 01 0F 02 FF 03 00 01 4F' - '08 FF 03 4F 07 77 01 03 0E 38 01 07 0F 77 02 44' - '05 77 02 44 0B 77 02 44 05 77 02 44 10 77 04 00' - '02 77 03 00 0C 77 01 0F 0F FF 01 07 04 77 01 0F' - '06 FB 0B 00 08 77 00 04 03 30 0C 77 00 04 03 30' - '04 77 01 0F 0A FF 05 00 09 77 01 0F 03 FF 03 07' - '01 F0 05 07 03 00 02 44 05 77 06 00 04 77 03 44' - '04 77 04 44 03 77 00 05 07 FF E7 00 09 77 01 07' - '09 77 02 08 03 FF 03 77 02 80 03 77 01 17 06 77' - '01 17 06 77 01 0F 0C FF 05 00 01 70 00 00 0A 77' - '01 07 03 77 01 07 0A 77 01 0F 05 FF 01 4F 08 FF' - '02 44 08 77 01 08 02 83 0A 00 01 83 02 30 11 77' - '05 44 0F 77 05 44 11 77 04 00 04 77 03 00 0B 77' - '01 0F 0A FF 06 00 05 77 01 0F 04 FB 01 07 13 77' - '00 04 03 30 0C 77 00 04 03 30 04 77 01 0F 0E FF' - '01 07 09 77 01 0F 04 FF 08 07 00 05 77 04 47 00' - '05 77 05 00 05 77 03 44 04 77 04 44 03 77 00 05' - '07 7F E7 63 09 77 01 07 0A 77 02 00 04 77 02 00' - '04 77 01 17 06 77 01 17 06 77 01 0F 02 FF 08 00' - '01 FF 02 F0 05 77 00 00 09 77 02 00 03 77 02 00' - '09 77 01 0F 02 FF 03 00 0A 44 09 77 00 04 03 80' - '08 77 00 04 03 80 39 77 05 00 07 77 02 00 0A 77' - '01 0F 0A FF 01 0F 03 FF 01 07 07 77 04 00 0C 77' - '05 00 03 77 00 04 03 30 0C 77 00 04 03 30 04 77' - '01 0F 0A FF 05 00 09 77 07 00 05 70 04 77 02 44' - '05 77 04 00 07 77 03 44 02 77 04 44 05 77 00 06' - '07 FF EE 77 06 77 01 07 0D 77 04 00 06 77 01 17' - '0E 77 01 0F 0C FF 01 07 04 77 00 00 09 77 01 07' - '05 77 01 07 09 77 01 0F 08 FF 00 04 0F F0 0C 77' - '01 08 03 83 00 08 0B B0 0B B0 03 38 01 07 38 77' - '05 00 09 77 02 00 09 77 01 0F 0A FF 00 04 0F F0' - '19 77 04 00 03 77 00 04 03 30 0C 77 00 04 03 30' - '04 77 01 0F 0A FF 00 04 0F F0 11 77 04 07 05 77' - '02 44 05 77 03 00 09 77 07 44 06 77 01 08 02 88' - '03 FF 01 E7 04 77 02 80 17 77 01 17 03 77 01 17' - '0A 77 01 0F 02 FF 08 00 01 FF 02 F0 04 77 00 00' - '09 77 01 07 05 77 01 07 09 77 01 0F 08 FF 03 0F' - '0E 77 05 00 04 BB 05 00 38 77 05 00 0B 77 02 00' - '08 77 01 0F 0A FF 03 0F 1B 77 03 00 03 77 00 04' - '03 30 0C 77 04 00 04 77 01 0F 0A FF 03 0F 13 77' - '01 07 06 77 01 04 02 44 05 77 02 00 18 77 00 04' - '08 77 03 FF 00 04 77 80 18 77 01 17 03 77 02 11' - '0A 77 01 0F 0C FF 01 07 03 77 00 00 09 77 01 07' - '05 77 01 07 09 77 01 0F 08 FF 02 00 13 77 06 00' - '3B 77 05 00 0E 77 02 00 06 77 01 0F 0A FF 02 00' - '14 77 01 07 06 77 03 07 01 07 03 77 00 04 03 30' - '0C 77 00 04 07 F0 04 77 01 0F 0A FF 02 00 15 77' - '06 00 01 74 02 44 05 77 01 07 1A 77 02 00 05 77' - '02 00 1A 77 06 11 0A 77 0D 00 03 77 00 00 09 77' - '01 07 05 77 01 07 09 77 0A 00 55 77 04 00 17 77' - '0C 00 16 77 01 07 04 77 01 07 03 77 01 07 03 77' - '14 00 04 77 0C 00 41 77 05 00 1F 77 02 11 1B 77' - '00 00 B6 77 04 00 91 77 01 17 1C 77 00 00 FF 77' - '69 77 00 00 00 01' -} */ - - -/* BINRES idb_view_small.bmp */ -IDB_VIEW_SMALL BITMAP LOADONCALL DISCARDABLE idb_view_small.bmp -/* { - '42 4D 36 10 00 00 00 00 00 00 36 04 00 00 28 00' - '00 00 C0 00 00 00 10 00 00 00 01 00 08 00 00 00' - '00 00 00 0C 00 00 EB 0A 00 00 EB 0A 00 00 00 01' - '00 00 00 01 00 00 00 00 00 00 00 00 80 00 00 80' - '00 00 00 80 80 00 80 00 00 00 80 00 80 00 80 80' - '00 00 C0 C0 C0 00 C0 DC C0 00 F0 CA A6 00 04 04' - '04 00 08 08 08 00 0C 0C 0C 00 11 11 11 00 16 16' - '16 00 1C 1C 1C 00 22 22 22 00 29 29 29 00 55 55' - '55 00 4D 4D 4D 00 42 42 42 00 39 39 39 00 80 7C' - 'FF 00 50 50 FF 00 93 00 D6 00 FF EC CC 00 C6 D6' - 'EF 00 D6 E7 E7 00 90 A9 AD 00 00 00 33 00 00 00' - '66 00 00 00 99 00 00 00 CC 00 00 33 00 00 00 33' - '33 00 00 33 66 00 00 33 99 00 00 33 CC 00 00 33' - 'FF 00 00 66 00 00 00 66 33 00 00 66 66 00 00 66' - '99 00 00 66 CC 00 00 66 FF 00 00 99 00 00 00 99' - '33 00 00 99 66 00 00 99 99 00 00 99 CC 00 00 99' - 'FF 00 00 CC 00 00 00 CC 33 00 00 CC 66 00 00 CC' - '99 00 00 CC CC 00 00 CC FF 00 00 FF 66 00 00 FF' - '99 00 00 FF CC 00 33 00 00 00 33 00 33 00 33 00' - '66 00 33 00 99 00 33 00 CC 00 33 00 FF 00 33 33' - '00 00 33 33 33 00 33 33 66 00 33 33 99 00 33 33' - 'CC 00 33 33 FF 00 33 66 00 00 33 66 33 00 33 66' - '66 00 33 66 99 00 33 66 CC 00 33 66 FF 00 33 99' - '00 00 33 99 33 00 33 99 66 00 33 99 99 00 33 99' - 'CC 00 33 99 FF 00 33 CC 00 00 33 CC 33 00 33 CC' - '66 00 33 CC 99 00 33 CC CC 00 33 CC FF 00 33 FF' - '33 00 33 FF 66 00 33 FF 99 00 33 FF CC 00 33 FF' - 'FF 00 66 00 00 00 66 00 33 00 66 00 66 00 66 00' - '99 00 66 00 CC 00 66 00 FF 00 66 33 00 00 66 33' - '33 00 66 33 66 00 66 33 99 00 66 33 CC 00 66 33' - 'FF 00 66 66 00 00 66 66 33 00 66 66 66 00 66 66' - '99 00 66 66 CC 00 66 99 00 00 66 99 33 00 66 99' - '66 00 66 99 99 00 66 99 CC 00 66 99 FF 00 66 CC' - '00 00 66 CC 33 00 66 CC 99 00 66 CC CC 00 66 CC' - 'FF 00 66 FF 00 00 66 FF 33 00 66 FF 99 00 66 FF' - 'CC 00 CC 00 FF 00 FF 00 CC 00 99 99 00 00 99 33' - '99 00 99 00 99 00 99 00 CC 00 99 00 00 00 99 33' - '33 00 99 00 66 00 99 33 CC 00 99 00 FF 00 99 66' - '00 00 99 66 33 00 99 33 66 00 99 66 99 00 99 66' - 'CC 00 99 33 FF 00 99 99 33 00 99 99 66 00 99 99' - '99 00 99 99 CC 00 99 99 FF 00 99 CC 00 00 99 CC' - '33 00 66 CC 66 00 99 CC 99 00 99 CC CC 00 99 CC' - 'FF 00 99 FF 00 00 99 FF 33 00 99 CC 66 00 99 FF' - '99 00 99 FF CC 00 99 FF FF 00 CC 00 00 00 99 00' - '33 00 CC 00 66 00 CC 00 99 00 CC 00 CC 00 99 33' - '00 00 CC 33 33 00 CC 33 66 00 CC 33 99 00 CC 33' - 'CC 00 CC 33 FF 00 CC 66 00 00 CC 66 33 00 99 66' - '66 00 CC 66 99 00 CC 66 CC 00 99 66 FF 00 CC 99' - '00 00 CC 99 33 00 CC 99 66 00 CC 99 99 00 CC 99' - 'CC 00 CC 99 FF 00 CC CC 00 00 CC CC 33 00 CC CC' - '66 00 CC CC 99 00 CC CC CC 00 CC CC FF 00 CC FF' - '00 00 CC FF 33 00 99 FF 66 00 CC FF 99 00 CC FF' - 'CC 00 CC FF FF 00 CC 00 33 00 FF 00 66 00 FF 00' - '99 00 CC 33 00 00 FF 33 33 00 FF 33 66 00 FF 33' - '99 00 FF 33 CC 00 FF 33 FF 00 FF 66 00 00 FF 66' - '33 00 CC 66 66 00 FF 66 99 00 FF 66 CC 00 CC 66' - 'FF 00 FF 99 00 00 FF 99 33 00 FF 99 66 00 FF 99' - '99 00 FF 99 CC 00 FF 99 FF 00 FF CC 00 00 FF CC' - '33 00 FF CC 66 00 FF CC 99 00 FF CC CC 00 FF CC' - 'FF 00 FF FF 33 00 CC FF 66 00 FF FF 99 00 FF FF' - 'CC 00 66 66 FF 00 66 FF 66 00 66 FF FF 00 FF 66' - '66 00 FF 66 FF 00 FF FF 66 00 21 00 A5 00 5F 5F' - '5F 00 77 77 77 00 86 86 86 00 96 96 96 00 CB CB' - 'CB 00 B2 B2 B2 00 D7 D7 D7 00 DD DD DD 00 E3 E3' - 'E3 00 EA EA EA 00 F1 F1 F1 00 F8 F8 F8 00 F0 FB' - 'FF 00 A4 A0 A0 00 80 80 80 00 00 00 FF 00 00 FF' - '00 00 00 FF FF 00 FF 00 00 00 FF 00 FF 00 FF FF' - '00 00 FF FF FF 00 07 07 07 07 07 07 07 07 07 07' - '07 07 07 07 07 07 07 07 07 07 07 07 07 07 07 07' - '07 07 07 07 07 07 07 07 07 07 07 07 07 07 07 07' - '07 07 07 07 07 07 07 07 07 07 07 07 07 07 07 07' - '07 07 07 07 07 07 07 07 07 07 07 07 07 07 07 07' - '07 07 07 07 07 07 07 07 07 07 07 07 07 07 07 07' - '07 07 07 07 07 07 07 07 07 07 07 07 07 07 07 07' - '07 07 07 07 07 07 07 07 07 07 07 07 07 07 07 07' - '07 07 07 07 07 07 07 07 07 07 07 07 07 07 07 07' - '07 07 07 07 07 07 07 07 07 07 07 07 07 07 07 07' - '07 07 07 07 07 07 07 07 07 07 07 07 07 07 07 07' - '07 07 07 07 07 07 07 07 07 07 07 07 07 07 07 07' - '07 07 07 07 07 07 07 07 07 07 07 07 07 07 07 00' - '00 00 00 00 00 07 07 07 07 04 04 04 07 07 07 07' - '07 07 07 07 07 07 07 07 00 00 00 07 07 07 07 07' - '07 07 07 07 07 07 07 00 00 07 07 07 07 07 07 07' - '07 07 07 07 07 07 07 07 07 04 04 04 04 07 07 07' - '07 07 07 00 07 07 04 04 04 04 04 04 04 04 04 07' - '07 07 07 00 07 07 07 07 07 07 07 07 07 07 07 07' - '07 07 07 00 07 07 07 07 07 07 07 07 07 07 07 07' - '07 07 07 00 07 07 07 07 00 00 00 00 00 00 00 00' - '00 00 00 00 00 07 07 07 07 00 00 00 00 00 00 00' - '00 00 00 00 00 00 07 07 07 00 07 00 07 00 07 00' - '07 00 07 00 07 00 07 07 00 00 00 00 00 00 00 00' - '00 00 00 00 00 07 07 07 07 07 07 07 07 07 07 07' - '07 07 07 07 07 07 07 07 07 04 FF 04 07 00 00 00' - '07 07 07 07 07 07 07 07 FF FF 00 07 00 00 00 00' - '00 00 07 07 07 07 07 FF 00 07 00 00 00 00 07 00' - '00 07 00 00 00 07 07 07 04 04 07 07 04 04 07 07' - '07 07 00 00 00 07 04 FF FF FF FF FF FF FF 04 07' - '07 07 00 00 00 07 07 07 07 07 07 07 07 07 07 07' - '07 07 00 00 00 07 00 00 00 00 00 00 00 00 07 07' - '07 07 00 00 00 07 07 30 79 79 79 79 79 79 79 79' - '79 79 79 79 00 07 07 07 07 00 07 EC EC EC EC EC' - 'EC EC EC EC EC 00 07 07 07 07 07 07 07 07 07 07' - '07 07 07 07 07 07 07 30 79 79 79 79 79 79 79 79' - '79 79 79 79 00 07 07 07 07 07 07 07 07 07 07 07' - '04 04 04 04 07 07 07 07 07 04 04 07 07 07 07 07' - '07 07 07 07 07 07 07 07 FF FF 00 07 00 00 00 00' - '00 00 07 07 07 07 07 FF 00 07 07 07 07 07 07 07' - '07 07 07 07 07 07 07 07 04 04 07 07 07 07 07 07' - '07 00 00 00 00 00 04 FF FF FF FF FF FF FF 04 07' - '07 00 00 00 00 00 07 07 07 07 07 07 07 07 07 07' - '07 00 00 00 00 00 00 FF FF FF FF FF FF 00 07 07' - '07 00 00 00 00 00 07 30 C3 A0 9A A0 9A A0 9A A0' - '9A 9A 9A 79 00 07 07 07 07 00 07 07 07 07 07 07' - '07 07 07 07 EC 00 07 07 07 00 07 07 00 07 00 07' - '00 07 00 07 07 00 07 30 C3 A0 9A A0 9A A0 9A A0' - '9A 9A 9A 79 00 07 07 07 07 07 07 07 07 07 07 07' - '04 FF FF 04 07 07 07 07 07 07 07 07 07 07 07 07' - '07 07 07 07 07 07 07 07 FF FF 00 07 07 07 07 07' - '07 07 07 07 07 07 07 07 07 07 07 07 07 07 07 07' - '07 07 07 07 07 07 07 07 04 04 04 04 04 04 07 07' - '07 07 07 00 07 07 04 FF FF FF FF FF FF FF 04 07' - '07 07 07 00 07 07 07 00 00 00 00 00 00 00 00 00' - '07 07 07 00 07 07 00 FF FF FF FF FF FF 00 07 07' - '07 07 07 00 07 07 07 30 C3 A0 A0 A0 A0 9A A0 9A' - 'A0 BD 9A 79 00 07 07 07 07 00 07 EC EC EC EC EC' - 'EC EC EC EC EC 00 07 07 07 07 07 07 07 07 07 07' - '07 07 07 07 07 07 07 30 C3 A0 A0 A0 A0 9A A0 9A' - 'A0 BD 9A 79 00 07 07 07 07 07 07 07 07 07 07 07' - '04 FF FF 04 07 07 07 07 07 07 07 07 07 07 07 07' - '07 07 07 07 07 07 07 07 07 07 07 07 07 07 07 07' - '07 07 07 07 07 07 07 00 00 07 07 07 07 07 07 07' - '07 07 07 07 07 07 07 07 04 04 07 07 04 04 07 07' - '07 07 07 00 07 07 04 FF FF FF FF FF FF FF 04 07' - '07 07 07 00 07 07 04 04 04 04 04 04 04 04 04 00' - '07 07 07 00 07 07 00 FF FF FF FF FF FF 00 04 04' - '04 07 07 00 07 07 07 30 C3 A0 A0 A0 A0 A0 9A A0' - '9A A0 9A 79 00 07 07 07 07 00 07 07 07 07 07 07' - '07 07 07 07 EC 00 07 07 07 00 07 07 00 07 00 07' - '00 07 00 07 07 00 07 30 C3 A0 A0 A0 A0 A0 9A A0' - '9A A0 9A 79 00 07 07 07 07 07 07 07 07 07 07 07' - '04 FF 04 04 07 07 07 07 07 07 07 07 07 07 04 04' - '04 07 07 07 07 07 07 07 00 00 00 07 07 07 07 07' - '07 07 07 07 07 07 07 FF 00 07 00 00 00 00 07 00' - '00 07 00 00 00 07 07 07 07 04 04 04 04 07 07 07' - '07 07 07 00 07 07 04 FF FF FF FF FF FF FF 04 07' - '07 07 07 00 07 07 04 FF 07 FF 07 FF 07 07 04 00' - '07 07 07 00 07 07 00 FF FF FF FF FF FF 00 A0 A0' - '04 07 07 00 07 07 07 30 C3 A0 A0 A0 A0 9A A0 9A' - 'A0 9A A0 79 00 07 00 07 07 00 07 EC EC EC EC EC' - 'EC EC 02 02 EC 00 07 07 07 07 07 07 07 07 07 07' - '07 07 07 07 07 07 07 30 C3 A0 A0 A0 A0 9A A0 9A' - 'A0 FF 00 79 00 07 07 00 00 00 00 00 00 07 07 07' - '04 04 04 07 07 07 07 07 07 07 07 07 07 07 04 FF' - '04 07 00 00 00 07 07 07 FF FF 00 07 00 00 00 00' - '00 00 07 07 07 07 07 FF 00 07 07 07 07 07 07 07' - '07 07 07 07 07 07 07 07 07 07 07 07 07 07 07 07' - '07 07 07 00 07 07 04 FF FF FF FF FF FF FF 04 07' - '07 07 07 00 07 07 04 07 FF 01 FF 01 01 07 04 00' - '07 07 07 00 07 07 00 FF FF FF FF FF FF 00 A0 A0' - '04 07 07 00 07 07 07 30 C3 A0 A0 A0 A0 A0 A0 A0' - '9A A0 9A 79 00 07 07 00 07 00 07 00 EC EC EC EC' - 'EC EC FA FA EC 00 07 07 07 00 07 07 07 07 07 07' - '00 07 00 07 07 00 07 30 C3 A0 A0 A0 A0 A0 A0 A0' - 'A0 FF 9A 79 00 07 07 07 07 07 07 07 07 07 07 07' - '07 07 07 07 07 07 07 07 07 07 07 07 07 07 04 04' - '07 07 07 07 07 07 07 07 FF FF 00 07 00 00 00 00' - '00 00 07 07 07 07 07 07 07 07 07 07 07 07 07 07' - '07 07 07 07 07 07 07 07 07 07 07 07 07 07 07 07' - '07 07 07 00 07 07 04 FF FF FF FF FF FF FF 04 07' - '07 07 07 00 07 07 04 FF 07 01 07 01 07 FF 04 00' - '07 07 07 00 07 07 00 FF FF FF 00 00 00 00 A0 A0' - '04 07 07 00 07 07 07 30 C3 A0 A0 A0 A0 A0 A0 A0' - 'A0 00 A0 79 00 07 07 07 00 00 00 07 07 07 07 07' - '07 07 07 07 07 00 01 01 07 07 01 01 07 07 07 07' - '07 07 07 07 07 07 07 30 C3 A0 A0 A0 A0 A0 FF 00' - 'A0 FF 00 00 FF 07 07 07 04 04 04 04 07 07 07 07' - '07 07 07 07 07 07 07 07 07 07 07 07 07 07 07 07' - '07 07 07 07 07 07 07 07 FF FF 00 07 07 07 07 07' - '07 07 07 07 07 07 07 00 00 07 07 07 07 07 07 07' - '07 07 07 07 07 07 07 07 07 04 04 04 04 04 07 07' - '07 07 07 00 07 07 04 04 04 04 04 04 04 04 04 07' - '07 07 07 00 07 07 04 07 01 01 FF 07 01 07 04 00' - '07 07 07 00 07 07 00 FF FF FF 00 FF 00 A0 A0 A0' - '04 07 07 00 07 07 07 30 C3 C3 C3 C3 C3 C3 C3 C3' - 'C3 00 A0 79 07 07 00 00 FF FF 00 00 00 00 00 00' - '00 00 00 00 00 00 07 01 01 01 01 07 07 00 07 00' - '07 00 07 00 07 00 07 30 C3 C3 C3 C3 C3 C3 C3 FF' - '00 FF 00 FF 07 07 07 07 04 FF FF 04 07 07 07 07' - '07 07 07 07 07 07 07 07 07 07 07 07 07 07 07 07' - '07 07 07 07 07 07 07 07 07 07 07 07 07 07 07 07' - '07 07 07 07 07 07 07 FF 00 07 00 00 00 00 07 00' - '00 07 00 00 00 07 07 07 04 04 07 07 04 04 07 07' - '07 07 07 00 07 07 07 07 07 07 07 07 07 07 07 07' - '07 07 07 00 07 07 04 FF 07 01 07 01 01 FF 04 00' - '07 07 07 00 07 07 00 FF FF FF 00 00 A0 A0 A0 A0' - '04 07 07 00 07 07 07 30 79 79 79 79 79 79 79 30' - '30 00 30 30 07 07 07 07 00 FF 00 07 07 07 07 07' - '07 07 07 07 07 07 07 07 01 01 07 07 07 07 07 07' - '07 07 07 07 07 07 07 30 79 79 79 79 79 79 00 00' - 'FF FF FF 00 00 07 07 07 04 FF FF 04 07 07 07 07' - '07 07 07 07 07 07 07 04 04 04 07 07 07 07 07 07' - '07 07 07 07 07 07 07 07 00 00 00 07 07 07 07 07' - '07 07 07 07 07 07 07 FF 00 07 07 07 07 07 07 07' - '07 07 07 07 07 07 07 07 04 04 07 07 04 04 07 07' - '07 07 07 00 07 07 07 07 07 07 07 04 04 04 04 07' - '07 07 07 00 07 07 04 07 FF 07 FF 07 FF 07 04 00' - '07 07 07 00 07 07 00 00 00 00 00 A0 A0 04 04 04' - '04 07 07 00 07 07 07 07 30 FF C3 C3 A0 A0 30 00' - '07 00 07 07 07 07 07 00 07 00 07 00 07 07 07 07' - '07 07 07 07 07 07 07 01 01 01 01 07 07 07 07 07' - '07 07 07 07 07 07 07 07 30 FF C3 C3 A0 FF FF FF' - 'FF FF FF FF FF FF 07 07 04 FF 04 04 07 07 07 07' - '07 07 07 07 07 07 07 04 FF 04 07 00 00 00 07 07' - '07 07 07 07 07 07 07 07 FF FF 00 07 00 00 00 00' - '00 00 07 07 07 07 07 07 07 07 07 07 07 07 07 07' - '07 07 07 07 07 07 07 07 07 04 04 04 04 04 07 07' - '07 07 07 00 07 07 07 07 07 07 07 04 FF FF 04 07' - '07 07 07 00 07 07 04 04 04 04 04 04 04 04 04 00' - '07 07 07 00 07 07 07 07 07 04 C3 A0 A0 04 C3 04' - '07 07 07 00 07 07 07 07 07 30 30 30 30 30 00 07' - '07 00 07 07 07 07 00 07 07 FF 07 07 00 07 07 07' - '07 07 07 07 07 07 01 01 07 07 01 01 07 07 07 07' - '07 07 07 07 07 07 07 07 07 30 30 30 30 30 00 00' - 'FF FF FF 00 07 07 07 07 04 04 04 07 07 07 07 07' - '07 07 07 07 07 07 07 04 04 07 07 07 07 07 07 07' - '07 07 07 07 07 07 07 07 FF FF 00 07 00 00 00 00' - '00 00 07 07 07 07 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 07 07 07 07 07 07 04 04 07 07' - '07 07 07 00 07 07 07 07 07 07 07 04 FF FF 04 07' - '07 07 07 00 07 07 04 FC 04 FC FC FC 04 FC 04 00' - '07 07 07 00 07 07 07 07 07 04 FF C3 C3 04 04 07' - '07 07 07 00 07 07 07 07 07 07 07 07 07 07 07 00' - '00 00 00 00 07 07 07 07 07 00 07 07 07 07 07 07' - '07 07 07 07 07 07 07 07 07 07 07 07 07 07 07 07' - '07 07 07 07 07 07 07 07 07 07 07 07 07 07 00 FF' - '00 FF 00 FF 00 07 07 07 07 07 07 07 07 07 07 07' - '07 07 07 07 07 07 07 07 07 07 07 07 07 07 07 07' - '07 07 07 07 07 07 07 07 FF FF 00 07 07 07 07 07' - '07 07 07 07 07 07 00 FF FF 92 FF FF FF FF 92 FF' - 'FF 92 FF FF FF 00 07 07 07 04 04 04 04 07 07 07' - '07 07 07 00 07 07 07 07 07 07 07 04 04 04 04 07' - '07 07 07 00 07 07 04 04 04 04 04 04 04 04 04 07' - '07 07 07 00 07 07 07 07 07 04 04 04 04 04 07 07' - '07 07 07 00 07 07 07 07 07 07 07 07 07 07 07 07' - '00 00 00 07 07 07 07 07 07 FF 07 07 07 07 07 07' - '07 07 07 07 07 07 07 07 07 07 07 07 07 07 07 07' - '07 07 07 07 07 07 07 07 07 07 07 07 07 07 FF 07' - '07 FF 00 07 FF 07 07 07 07 07 07 07 07 07 07 07' - '07 07 07 07 07 07 07 07 07 07 07 07 07 07 07 07' - '07 07 07 07 07 07 07 07 07 07 07 07 07 07 07 07' - '07 07 07 07 07 07 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 07 07 07 07 07 07 07 07 07 07' - '07 07 07 07 07 07 07 07 07 07 07 07 07 07 07 07' - '07 07 07 07 07 07 07 07 07 07 07 07 07 07 07 07' - '07 07 07 07 07 07 07 07 07 07 07 07 07 07 07 07' - '07 07 07 07 07 07 07 07 07 07 07 07 07 07 07 07' - '07 00 07 07 07 07 07 07 07 07 07 07 07 07 07 07' - '07 07 07 07 07 07 07 07 07 07 07 07 07 07 07 07' - '07 07 07 07 07 07 07 07 07 07 07 07 07 07 07 07' - '07 FF 00 07 07 07' -} */ - - -/* BINRES idb_view_large.bmp */ -IDB_VIEW_LARGE BITMAP LOADONCALL MOVEABLE DISCARDABLE idb_view_large.bmp -/* { - '42 4D DE 08 00 00 00 00 00 00 76 00 00 00 28 00' - '00 00 20 01 00 00 18 00 00 00 01 00 04 00 02 00' - '00 00 68 08 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 80 00 00 80' - '00 00 00 80 80 00 80 00 00 00 80 00 80 00 80 80' - '00 00 C0 C0 C0 00 80 80 80 00 00 00 FF 00 00 FF' - '00 00 00 FF FF 00 FF 00 00 00 FF 00 FF 00 FF FF' - '00 00 FF FF FF 00 FE 77 22 77 00 00 78 77 0E 44' - '04 77 02 71 16 77 02 71 16 77 02 71 64 77 00 00' - '0C 77 02 70 08 00 08 77 04 44 0E 77 00 06 74 44' - '47 00 06 77 04 44 08 77 00 04 74 77 04 00 00 0E' - '07 00 07 00 07 00 07 00 08 77 06 44 06 77 02 71' - '04 77 02 4F 0A FF 02 F4 04 77 00 04 11 17 14 77' - '00 04 11 17 14 77 00 04 11 17 62 77 00 00 1E 77' - '00 04 4F F4 0E 77 00 06 74 FF 47 00 06 77 00 04' - '4F F4 24 77 00 0A 74 44 77 74 47 00 04 77 00 08' - '11 17 77 4F 0A FF 00 06 F4 77 71 00 04 11 12 77' - '02 71 04 11 12 77 02 71 04 11 00 04 77 70 16 00' - '30 77 12 00 02 07 04 77 00 00 0E 77 06 44 02 47' - '08 77 00 06 4F F4 70 00 06 00 06 77 00 06 74 FF' - '47 00 04 00 00 08 07 4F F4 70 04 00 00 06 77 74' - '77 00 04 00 00 0E 07 00 07 00 07 00 07 00 06 77' - '00 04 74 44 08 77 02 71 04 11 00 04 77 4F 0A FF' - '00 04 F4 77 06 11 02 17 10 77 06 11 02 17 10 77' - '06 11 00 04 17 70 14 BF 02 B0 04 77 12 00 02 07' - '04 77 14 07 02 0F 10 BF 02 07 04 77 00 00 0E 77' - '02 4F 04 FF 02 47 08 77 00 04 4F 44 0E 77 00 06' - '74 F4 47 00 06 77 00 04 4F 44 24 77 00 04 74 44' - '08 77 06 11 00 04 17 4F 0A FF 02 F4 04 77 02 71' - '16 77 02 71 16 77 02 71 04 77 02 70 14 FB 02 F0' - '04 77 02 07 10 88 02 07 18 77 02 0B 10 FB 02 07' - '04 77 00 00 0E 77 02 4F 04 FF 02 47 08 77 00 04' - '44 47 0E 77 00 04 74 44 08 77 00 04 44 47 08 77' - '00 04 74 77 04 00 00 0E 07 00 07 00 07 00 07 00' - '06 77 02 74 06 44 02 47 04 77 02 71 04 77 02 4F' - '0A FF 02 F4 04 77 02 71 16 77 02 71 04 77 02 74' - '08 44 02 47 06 77 02 71 04 77 02 70 14 BF 02 B0' - '04 77 02 07 0E 77 00 04 78 07 04 77 02 07 0E 70' - '00 06 77 07 0F 00 10 BF 02 07 04 77 00 00 0E 77' - '02 4F 04 FF 02 47 4E 77 00 0A 74 44 77 44 47 00' - '04 77 02 71 04 77 02 4F 0A FF 02 F4 04 77 02 71' - '16 77 02 71 04 77 02 74 08 FF 02 47 06 77 02 71' - '04 77 02 70 06 FB 0C 00 00 04 FB F0 04 77 02 07' - '10 88 02 07 18 77 02 0B 10 FB 02 07 04 77 00 00' - '0E 77 02 4F 04 FF 02 47 32 77 00 04 74 77 04 00' - '00 0E 07 00 07 00 07 00 07 00 06 77 00 0A 74 44' - '77 44 47 00 04 77 02 71 04 77 02 4F 0A FF 02 F4' - '04 77 02 71 08 77 0A 00 04 77 02 71 04 77 02 74' - '08 FF 02 47 06 77 02 71 04 77 02 70 06 BF 02 0F' - '0C BF 02 B0 04 77 02 07 0E 77 00 04 78 07 04 77' - '02 07 0E 70 00 06 77 07 0F 00 10 BF 02 07 04 77' - '00 00 0E 77 00 08 4F FF 44 47 1A 77 00 06 74 44' - '47 00 06 77 04 44 26 77 06 44 06 77 02 71 04 77' - '02 4F 0A FF 02 F4 04 77 02 71 06 77 02 74 08 44' - '02 40 04 77 02 71 04 77 02 74 08 FF 02 47 06 77' - '02 71 04 77 02 70 06 FB 02 0B 0C FB 02 F0 04 77' - '02 07 10 88 02 07 18 77 02 0B 10 FB 02 07 04 77' - '00 00 0E 77 00 06 4F FF 44 00 0E 77 00 06 74 44' - '47 00 08 77 00 06 74 FF 47 00 06 77 00 04 4F F4' - '08 77 00 04 74 77 04 00 00 0E 07 00 07 00 07 00' - '07 00 14 77 02 71 04 77 02 4F 0A FF 02 F4 04 77' - '02 71 06 77 02 74 08 F7 02 40 04 77 02 71 04 77' - '02 74 08 FF 04 44 00 06 47 77 71 00 04 77 02 70' - '06 BF 02 0F 0C BF 00 08 B0 07 77 07 10 88 02 07' - '04 77 02 07 10 77 00 04 07 0F 10 BF 02 07 04 77' - '00 00 02 77 08 00 00 04 07 77 04 44 02 47 0E 77' - '00 06 74 FF 47 00 08 77 00 06 74 FF 47 00 04 00' - '00 08 07 4F F4 70 04 00 2C 77 02 71 04 77 02 4F' - '0A FF 02 F4 04 77 02 71 06 77 02 74 08 7F 02 40' - '04 77 02 71 04 77 02 74 08 FF 00 0A 4F BF 47 77' - '71 00 04 77 00 06 70 FB F0 00 06 00 0A FB 00 0A' - 'F0 70 77 07 80 00 0A 88 00 10 82 28 07 71 17 77' - '71 17 06 77 04 70 04 77 02 0B 10 FB 00 06 07 77' - '07 00 00 00 22 77 00 06 74 FF 47 00 06 00 00 08' - '07 74 F4 47 06 77 00 04 4F 44 08 77 00 04 74 77' - '04 00 00 0E 07 00 07 00 07 00 07 00 14 77 02 71' - '04 77 02 4F 0A FF 02 F4 04 77 02 71 06 77 00 0C' - '74 F7 17 11 17 40 04 77 02 71 04 77 02 74 08 FF' - '00 0A 4B FB 47 77 71 00 04 77 02 70 04 BF 04 00' - '02 0F 0A BF 00 04 B0 77 04 07 02 08 0A 88 00 0E' - '8A A8 07 77 11 77 11 00 0E 77 00 04 07 0F 0C BF' - '00 0A B0 BF 07 70 77 00 00 00 00 04 77 74 06 44' - '18 77 00 06 74 F4 47 00 08 77 00 04 74 44 08 77' - '00 04 44 47 26 77 06 44 02 47 04 77 02 71 04 77' - '0E 44 04 77 02 71 06 77 00 0C 74 7F 1F 18 7F 40' - '04 77 02 71 04 77 02 74 08 FF 00 0A 4F BF 47 77' - '71 00 04 77 02 70 04 FB 00 04 F0 00 0C FB 00 08' - 'F0 77 70 00 0E 77 00 0C 78 07 77 71 11 17 10 77' - '02 0B 0E FB 02 0B 04 07 02 77 00 00 00 04 77 74' - '04 FF 02 F4 18 77 00 04 74 44 22 77 00 04 74 77' - '04 00 00 0E 07 00 07 00 07 00 07 00 06 77 00 0A' - '74 44 77 44 47 00 04 77 02 71 16 77 02 71 06 77' - '00 0C 74 F7 17 F1 87 40 04 77 02 71 04 77 02 74' - '04 FF 00 0E F4 44 4B FB 47 77 71 00 04 77 02 70' - '06 BF 02 0F 0C BF 00 08 B0 00 07 70 10 00 02 07' - '04 77 00 04 11 77 10 07 02 0F 0E BF 00 04 B0 00' - '04 77 00 00 00 04 77 74 04 FF 02 F4 5A 77 00 0A' - '74 44 77 44 47 00 04 77 02 71 16 77 02 71 06 77' - '00 0C 74 71 1F 7F 1F 40 04 77 02 71 04 77 02 74' - '04 FF 04 F4 04 BF 00 06 47 77 71 00 04 77 02 70' - '14 FB 00 04 F0 77 04 70 14 77 00 06 71 11 17 00' - '10 77 12 00 00 06 77 00 07 00 00 00 00 04 77 74' - '04 FF 02 F4 0E 77 00 06 74 44 47 00 12 77 00 06' - '74 44 47 00 06 77 04 44 08 77 00 04 74 77 04 00' - '00 0E 07 00 07 00 07 00 07 00 06 77 00 0A 74 44' - '77 44 47 00 04 77 02 71 0A 77 02 74 04 44 02 47' - '04 77 02 71 06 77 00 0C 74 F7 17 11 87 40 04 77' - '02 71 04 77 02 74 04 FF 00 04 F4 4B 04 FB 00 06' - '47 77 71 00 04 77 02 70 14 BF 00 04 B0 77 06 07' - '12 77 00 06 11 77 11 00 10 77 02 70 08 FB 02 07' - '04 77 04 70 04 77 00 00 00 04 77 74 04 FF 02 F4' - '0E 77 00 06 74 FF 47 00 12 77 00 06 74 FF 47 00' - '06 77 00 04 4F F4 24 77 00 0A 74 44 77 44 47 00' - '04 77 02 71 0A 77 02 74 04 FF 02 47 04 77 02 71' - '06 77 02 74 08 7F 02 40 04 77 02 71 04 77 02 74' - '06 44 06 BF 00 06 47 77 71 00 04 77 02 70 14 00' - '00 04 07 70 04 77 02 70 10 77 00 0A 71 17 77 71' - '17 00 10 77 02 0F 04 BF 02 B0 06 77 06 07 02 77' - '00 00 00 0A 77 74 FF F4 44 00 0E 77 00 06 74 FF' - '47 00 06 00 02 07 0A 77 00 06 74 FF 47 00 04 00' - '00 08 07 4F F4 70 04 00 00 04 77 74 14 44 08 77' - '06 44 02 47 04 77 02 71 0A 77 02 74 04 FF 02 47' - '04 77 02 71 06 77 02 74 08 F7 02 40 04 77 02 71' - '08 77 02 74 04 FB 00 0A F4 44 47 77 71 00 06 77' - '02 0F 08 BF 02 07 0A 77 00 0A 07 77 07 77 07 00' - '28 77 02 70 04 00 02 07 04 77 02 70 04 77 00 04' - '70 77 00 00 00 0A 77 74 FF F4 47 00 0E 77 00 06' - '74 F4 47 00 12 77 00 06 74 F4 47 00 06 77 00 04' - '4F 44 2A 77 00 04 44 47 04 77 02 71 0A 77 02 74' - '04 FF 02 47 04 77 02 71 06 77 02 74 08 44 02 40' - '04 77 02 71 08 77 02 74 04 BF 00 04 B4 F4 04 77' - '02 71 06 77 02 70 06 FB 02 F0 4A 77 00 0A 07 77' - '07 77 07 00 00 00 00 04 77 74 04 44 10 77 00 04' - '74 44 14 77 00 04 74 44 08 77 00 04 44 47 0C 77' - '04 00 00 08 70 00 70 00 0E 77 06 44 06 77 02 71' - '0A 77 02 74 04 FF 02 47 04 77 02 71 06 77 00 0C' - '74 CC 4C C4 CC 40 04 77 02 71 08 77 02 74 04 FB' - '00 04 F4 47 04 77 02 71 08 77 06 00 02 07 10 77' - '02 07 42 77 00 00 7E 77 02 74 04 44 02 47 04 77' - '02 71 06 77 02 74 08 44 02 47 04 77 02 71 08 77' - '02 74 06 44 06 77 02 71 5E 77 02 07 04 77 00 00' - 'FE 77 22 77 00 00 FE 77 22 77 00 00 00 01' -} */ - - -/* BINRES idb_hist_small.bmp */ -IDB_HIST_SMALL BITMAP LOADONCALL DISCARDABLE idb_hist_small.bmp -/* { - '42 4D 8A 05 00 00 00 00 00 00 8A 00 00 00 28 00' - '00 00 50 00 00 00 10 00 00 00 01 00 08 00 00 00' - '00 00 00 05 00 00 12 0B 00 00 12 0B 00 00 15 00' - '00 00 15 00 00 00 FF FF FF 00 00 00 80 00 00 80' - '00 00 00 80 80 00 80 00 00 00 80 00 80 00 00 00' - '00 00 80 80 80 00 C0 C0 C0 00 00 00 FF 00 00 FF' - '00 00 00 FF FF 00 FF 00 00 00 FF 00 FF 00 FF FF' - '00 00 00 66 66 00 CC FF FF 00 99 CC FF 00 99 FF' - 'FF 00 66 CC CC 00 CC CC FF 00 08 08 08 08 08 08' - '08 08 08 08 08 08 08 08 08 08 08 08 08 08 08 08' - '08 08 08 08 08 08 08 08 08 08 08 08 08 08 08 08' - '08 08 08 08 08 08 08 08 08 08 08 08 08 08 08 08' - '08 08 08 08 08 08 08 08 08 08 08 08 08 08 08 08' - '08 08 08 08 08 08 08 08 08 08 08 08 08 08 08 08' - '08 08 08 08 08 08 08 08 08 08 08 08 08 08 08 08' - '08 08 08 08 08 08 08 08 08 08 08 06 06 06 06 06' - '06 06 06 06 06 06 06 06 06 08 08 08 08 08 08 06' - '06 06 06 06 06 06 06 06 06 06 08 08 08 08 08 08' - '08 08 08 08 08 08 08 08 08 08 08 08 08 08 08 08' - '08 08 08 08 08 08 08 08 08 08 08 08 08 08 08 08' - '08 08 08 08 08 08 08 08 08 08 03 13 13 13 13 13' - '13 13 13 13 13 13 13 13 06 08 08 08 08 08 03 13' - '13 13 13 13 13 13 13 13 13 06 08 08 04 04 04 04' - '04 04 04 04 04 04 04 04 04 08 08 08 08 08 08 08' - '08 08 08 08 08 08 08 08 08 08 08 08 08 08 08 08' - '08 08 08 08 08 08 08 08 08 08 03 10 11 12 11 12' - '11 04 11 12 11 11 11 13 06 08 08 08 08 08 03 10' - '12 12 04 11 04 11 04 11 13 06 08 08 04 00 00 00' - '04 00 00 00 00 00 00 00 04 08 08 08 08 08 08 08' - '08 08 08 06 08 08 08 08 08 08 08 08 08 08 08 08' - '06 08 08 08 08 08 08 08 08 08 03 10 12 12 12 04' - '12 04 12 04 12 14 11 13 06 08 08 08 08 08 03 10' - '12 12 12 04 04 04 11 12 13 06 08 08 04 00 00 00' - '04 00 00 00 00 00 00 00 04 08 08 08 08 08 08 08' - '08 08 06 06 08 08 08 08 08 08 08 08 08 08 08 08' - '06 06 08 08 08 08 08 08 08 08 03 10 12 12 12 12' - '04 04 04 12 11 12 11 13 06 08 06 06 06 06 03 10' - '12 12 04 04 12 04 04 11 13 06 08 08 04 00 06 00' - '04 00 00 06 06 06 00 00 04 08 08 08 08 08 08 08' - '08 06 06 06 08 08 08 08 08 08 08 08 08 08 08 08' - '06 06 06 08 08 08 08 08 08 08 03 10 12 12 04 04' - '04 00 04 04 04 11 12 13 06 08 06 00 00 00 03 10' - '12 12 12 04 04 04 12 12 13 06 08 08 04 00 00 00' - '04 00 00 00 00 00 00 00 04 08 08 08 08 08 08 08' - '06 06 06 06 08 08 08 08 08 08 08 08 08 08 08 08' - '06 06 06 06 08 08 08 08 08 08 03 10 12 12 12 12' - '04 04 04 12 11 12 11 13 06 08 06 00 04 04 03 10' - '12 12 04 12 04 12 04 11 13 06 08 08 04 00 06 00' - '04 00 00 06 06 06 00 00 04 08 08 08 08 08 08 06' - '06 06 06 06 08 08 08 08 08 08 08 08 08 08 08 08' - '06 06 06 06 06 08 08 08 08 08 03 10 12 12 12 04' - '12 04 12 04 12 11 12 13 06 08 06 00 00 00 03 10' - '10 10 10 10 10 10 10 12 13 06 08 08 04 00 00 00' - '04 00 00 00 00 00 00 00 04 08 08 08 08 08 08 08' - '06 06 06 06 08 08 08 08 08 08 08 08 08 08 08 08' - '06 06 06 06 08 08 08 08 08 08 03 10 12 12 12 12' - '12 04 12 12 12 12 11 13 06 08 06 00 04 04 03 13' - '13 13 13 13 13 03 03 03 03 08 08 08 04 00 06 00' - '04 00 00 06 06 06 00 00 04 08 08 08 08 08 08 08' - '08 06 06 06 08 08 08 08 08 08 08 08 08 08 08 08' - '06 06 06 08 08 08 08 08 08 08 03 10 10 10 10 10' - '10 10 10 10 10 10 12 13 06 08 06 00 00 00 00 03' - '10 10 12 12 03 06 08 08 08 08 08 08 04 00 00 00' - '04 00 00 00 00 00 00 00 04 08 08 08 08 08 08 08' - '08 08 06 06 08 08 08 08 08 08 08 08 08 08 08 08' - '06 06 08 08 08 08 08 08 08 08 03 13 13 13 13 13' - '13 13 03 03 03 03 03 03 08 08 06 00 02 02 00 04' - '03 03 03 03 06 08 08 06 08 08 08 08 04 00 00 00' - '04 00 00 00 00 00 00 00 04 08 08 08 08 08 08 08' - '08 08 08 06 08 08 08 08 08 08 08 08 08 08 08 08' - '06 08 08 08 08 08 08 08 08 08 08 03 00 10 10 12' - '12 03 06 08 08 08 08 08 08 08 06 00 02 02 00 00' - '00 00 06 08 08 08 08 06 08 08 08 08 04 04 04 04' - '04 04 04 04 04 04 04 04 04 08 08 08 08 08 08 08' - '08 08 08 08 08 08 08 08 08 08 08 08 08 08 08 08' - '08 08 08 08 08 08 08 08 08 08 08 08 03 03 03 03' - '03 06 08 08 08 08 08 08 08 08 06 00 02 02 00 04' - '04 00 06 08 08 06 06 06 06 06 08 08 04 04 04 04' - '04 04 04 04 04 04 04 04 04 08 08 08 08 08 08 08' - '08 08 08 08 08 08 08 08 08 08 08 08 08 08 08 08' - '08 08 08 08 08 08 08 08 08 08 08 08 08 08 08 08' - '08 08 08 08 08 08 08 08 08 08 06 00 00 00 00 00' - '00 00 06 08 08 08 08 06 08 08 08 08 08 08 08 08' - '08 08 08 08 08 08 08 08 08 08 08 08 08 08 08 08' - '08 08 08 08 08 08 08 08 08 08 08 08 08 08 08 08' - '08 08 08 08 08 08 08 08 08 08 08 08 08 08 08 08' - '08 08 08 08 08 08 08 08 08 08 06 06 06 06 06 06' - '06 06 06 08 08 08 08 06 08 08 08 08 08 08 08 08' - '08 08 08 08 08 08 08 08 08 08' -} */ - - -/* BINRES idb_hist_large.bmp */ -IDB_HIST_LARGE BITMAP LOADONCALL DISCARDABLE idb_hist_large.bmp -/* { - '42 4D 16 06 00 00 00 00 00 00 76 00 00 00 28 00' - '00 00 78 00 00 00 18 00 00 00 01 00 04 00 00 00' - '00 00 A0 05 00 00 12 0B 00 00 12 0B 00 00 10 00' - '00 00 10 00 00 00 FF FF FF 00 00 00 80 00 00 80' - '00 00 00 80 80 00 80 00 00 00 80 00 80 00 00 00' - '00 00 80 80 80 00 C0 C0 C0 00 00 00 FF 00 00 FF' - '00 00 00 FF FF 00 FF 00 00 00 FF 00 FF 00 FF FF' - '00 00 00 66 66 00 88 88 88 88 88 88 88 88 88 88' - '88 88 88 88 88 88 88 88 88 88 88 88 88 88 88 88' - '88 88 88 88 88 88 88 88 88 88 88 88 88 88 88 88' - '88 88 88 88 88 88 88 88 88 88 88 88 88 88 88 88' - '88 88 88 88 88 88 88 88 88 88 88 88 88 88 88 88' - '88 88 88 88 88 88 88 88 88 88 88 88 88 88 88 88' - '88 88 88 88 88 88 88 88 88 88 88 88 88 88 88 88' - '88 88 88 88 88 88 88 88 88 88 88 88 88 88 88 88' - '88 88 88 88 88 88 88 88 88 88 88 88 88 88 88 88' - '88 88 88 88 88 88 86 66 66 66 66 66 66 66 66 66' - '66 88 88 88 88 86 66 66 66 66 66 66 66 66 88 88' - '88 88 88 88 88 88 88 88 88 88 88 88 88 88 88 88' - '88 88 88 88 88 88 88 88 88 88 88 88 88 88 88 88' - '88 88 86 0B B0 BB 0B B0 BB 0B B0 BB 06 88 88 88' - '88 86 0B B0 BB 0B B0 BB 0B B6 88 88 88 88 88 88' - '88 88 88 88 88 88 88 88 88 88 88 88 88 88 88 88' - '88 88 88 88 88 88 88 88 88 88 88 88 88 88 86 0B' - 'B0 BB 0B B0 BB 0B B0 BB 06 88 88 88 88 86 0B B0' - 'BB 0B B0 BB 0B B6 88 88 88 88 88 88 88 88 88 88' - '88 88 88 88 88 88 88 88 88 88 88 88 88 88 88 88' - '88 88 88 88 88 88 88 88 88 88 86 B0 0B 00 B0 04' - '00 B0 0B 00 B6 88 88 88 88 86 B0 0B 44 B4 4B 44' - 'B0 06 88 88 88 88 88 88 88 88 88 88 88 88 88 88' - '88 88 88 88 88 68 88 88 88 88 88 88 88 88 86 88' - '88 88 88 88 88 88 86 0B B0 BB 4B B4 BB 4B B0 BB' - '06 88 88 88 88 86 0B B0 BB 44 44 BB 0B B6 88 88' - '84 44 44 44 44 44 44 48 88 88 88 88 88 88 88 88' - '86 68 88 88 88 88 88 88 88 88 86 68 88 88 88 88' - '88 88 86 0B B0 BB 4B B4 BB 4B B0 BB 06 88 88 88' - '88 86 0B B0 BB 44 44 BB 0B B6 88 88 84 00 04 00' - '00 00 00 48 88 88 88 88 88 88 88 88 66 68 88 88' - '88 88 88 88 88 88 86 66 88 88 88 88 88 88 86 B0' - '0B 00 B4 44 44 B0 0B 00 B6 88 86 66 66 66 B0 0B' - '44 4B B4 44 B0 06 88 88 84 00 04 00 00 00 00 48' - '88 88 88 88 88 88 88 86 66 68 88 88 88 88 88 88' - '88 88 86 66 68 88 88 88 88 88 86 0B B0 44 44 40' - '44 44 40 BB 06 88 86 00 00 06 0B B0 BB 44 44 BB' - '0B B6 88 88 84 06 04 00 66 66 00 48 88 88 88 88' - '88 88 88 66 66 68 88 88 88 88 88 88 88 88 86 66' - '66 88 88 88 88 88 86 0B B0 44 44 40 44 44 40 BB' - '06 88 86 00 00 06 0B B0 BB 44 44 BB 0B B6 88 88' - '84 00 04 00 00 00 00 48 88 88 88 88 88 88 86 66' - '66 68 88 88 88 88 88 88 88 88 86 66 66 68 88 88' - '88 88 86 B0 0B 00 B4 44 44 B0 0B 00 B6 88 86 04' - '44 46 B0 0B 44 B4 4B 44 B0 06 88 88 84 06 04 00' - '66 66 00 48 88 88 88 88 88 88 66 66 66 68 88 88' - '88 88 88 88 88 88 86 66 66 66 88 88 88 88 86 0B' - 'B0 BB 4B B4 BB 4B B0 BB 06 88 86 00 00 06 0B B0' - 'BB 0B B0 BB 0B B6 88 88 84 00 04 00 00 00 00 48' - '88 88 88 88 88 88 66 66 66 68 88 88 88 88 88 88' - '88 88 86 66 66 66 88 88 88 88 86 0B B0 BB 4B B4' - 'BB 4B B0 BB 06 88 86 00 00 06 0B B0 BB 0B B0 BB' - '0B B6 88 88 84 06 04 00 66 66 00 48 88 88 88 88' - '88 88 86 66 66 68 88 88 88 88 88 88 88 88 86 66' - '66 68 88 88 88 88 86 B0 0B 00 B0 04 00 B0 0B 00' - 'B6 88 86 04 44 46 66 66 66 66 66 66 66 66 88 88' - '84 00 04 00 00 00 00 48 88 88 88 88 88 88 88 66' - '66 68 88 88 88 88 88 88 88 88 86 66 66 88 88 88' - '88 88 86 0B B0 BB 0B B0 BB 0B B0 BB 06 88 86 00' - '00 00 6B B0 BB 06 88 88 88 88 88 88 84 00 04 00' - '00 00 00 48 88 88 88 88 88 88 88 86 66 68 88 88' - '88 88 88 88 88 88 86 66 68 88 88 88 88 88 86 0B' - 'B0 BB 0B B0 BB 0B B0 BB 06 88 86 00 00 00 6B B0' - 'BB 06 88 88 88 88 88 88 84 44 44 44 44 44 44 48' - '88 88 88 88 88 88 88 88 66 68 88 88 88 88 88 88' - '88 88 86 66 88 88 88 88 88 88 86 66 66 66 66 66' - '66 66 66 66 66 88 86 02 22 00 46 66 66 68 88 88' - '68 88 88 88 84 44 44 44 44 44 44 48 88 88 88 88' - '88 88 88 88 86 68 88 88 88 88 88 88 88 88 86 68' - '88 88 88 88 88 88 88 6B B0 BB 0B B6 88 88 88 88' - '88 88 86 02 22 00 00 00 68 88 88 88 68 88 88 88' - '88 88 88 88 88 88 88 88 88 88 88 88 88 88 88 88' - '88 68 88 88 88 88 88 88 88 88 86 88 88 88 88 88' - '88 88 88 6B B0 BB 0B B6 88 88 88 88 88 88 86 02' - '22 00 00 00 68 88 88 88 68 88 88 88 88 88 88 88' - '88 88 88 88 88 88 88 88 88 88 88 88 88 88 88 88' - '88 88 88 88 88 88 88 88 88 88 88 88 88 88 88 86' - '66 66 66 68 88 88 88 88 88 88 86 02 22 00 44 40' - '68 88 86 66 66 66 88 88 88 88 88 88 88 88 88 88' - '87 88 88 88 88 88 88 88 88 88 88 88 88 88 88 88' - '88 88 88 88 88 88 88 88 88 88 88 88 88 88 88 88' - '88 88 88 88 88 88 86 00 00 00 00 00 68 88 88 88' - '68 88 88 88 88 88 88 88 88 88 88 88 87 88 88 88' - '88 88 88 88 88 88 88 88 88 88 88 88 88 88 88 88' - '88 88 88 88 88 88 88 88 88 88 88 88 88 88 88 88' - '88 88 86 00 00 00 00 00 68 88 88 88 68 88 88 88' - '88 88 88 88 88 88 88 88 88 88 88 88 88 88 88 88' - '88 88 88 88 88 88 88 88 88 88 88 88 88 88 88 88' - '88 88 88 88 88 88 88 88 88 88 88 88 88 88 86 66' - '66 66 66 66 68 88 88 88 68 88 88 88 88 88 88 88' - '88 88 88 88 88 88' -} */ - - -/* BINRES idc_copy.cur */ -IDC_COPY CURSOR LOADONCALL DISCARDABLE idc_copy.cur -/* { - '00 00 02 00 01 00 20 20 00 00 00 00 00 00 30 01' - '00 00 16 00 00 00 28 00 00 00 20 00 00 00 40 00' - '00 00 01 00 01 00 00 00 00 00 00 01 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 FF FF FF 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 C0 00 00 00 C0' - '00 00 01 80 00 00 01 80 00 00 03 00 00 00 43 00' - '00 00 66 00 00 00 76 00 00 00 7E 00 00 00 7F C0' - '00 00 7F 80 00 00 7F 00 00 00 7E 00 00 00 7C 00' - '00 00 78 00 00 00 70 00 00 00 60 00 00 00 40 00' - '00 00 00 00 00 00 FF FF FF FF FF FF FF FF FF FF' - 'FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF' - 'FF FF FF FF FF FF FF FD FF FF FF FD FF FF FF F0' - '7F FF FF FD FF FF FF 3D FF FF FE 1F FF FF FE 1F' - 'FF FF FC 3F FF FF 7C 3F FF FF 38 7F FF FF 18 7F' - 'FF FF 00 FF FF FF 00 FF FF FF 00 0F FF FF 00 1F' - 'FF FF 00 3F FF FF 00 7F FF FF 00 FF FF FF 01 FF' - 'FF FF 03 FF FF FF 07 FF FF FF 0F FF FF FF 1F FF' - 'FF FF 3F FF FF FF' -} */ - - -/* BINRES idc_divider.cur */ -IDC_DIVIDER CURSOR LOADONCALL DISCARDABLE idc_divider.cur -/* { - '00 00 02 00 01 00 20 20 00 00 09 00 09 00 30 01' - '00 00 16 00 00 00 28 00 00 00 20 00 00 00 40 00' - '00 00 01 00 01 00 00 00 00 00 80 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 FF FF FF 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 01 E0' - '00 00 01 20 00 00 01 20 00 00 01 20 00 00 01 20' - '00 00 19 26 00 00 29 25 00 00 4F 3C 80 00 80 00' - '40 00 80 00 40 00 4F 3C 80 00 29 25 00 00 19 26' - '00 00 01 20 00 00 01 20 00 00 01 20 00 00 01 20' - '00 00 01 E0 00 00 FF FF FF FF FF FF FF FF FF FF' - 'FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF' - 'FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF' - 'FF FF FF FF FF FF FF FF FF FF FF FF FF FF FE 1F' - 'FF FF FE 1F FF FF FE 1F FF FF FE 1F FF FF FE 1F' - 'FF FF E6 19 FF FF C6 18 FF FF 80 00 7F FF 00 00' - '3F FF 00 00 3F FF 80 00 7F FF C6 18 FF FF E6 19' - 'FF FF FE 1F FF FF FE 1F FF FF FE 1F FF FF FE 1F' - 'FF FF FE 1F FF FF' -} */ - - -/* BINRES idc_divideropen.cur */ -IDC_DIVIDEROPEN CURSOR LOADONCALL DISCARDABLE idc_divideropen.cur -/* { - '00 00 02 00 01 00 20 20 00 00 09 00 09 00 30 01' - '00 00 16 00 00 00 28 00 00 00 20 00 00 00 40 00' - '00 00 01 00 01 00 00 00 00 00 80 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 FF FF FF 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 03 F0' - '00 00 02 D0 00 00 02 D0 00 00 02 D0 00 00 02 D0' - '00 00 1A D6 00 00 2A D5 00 00 4E DC 80 00 80 C0' - '40 00 80 C0 40 00 4E DC 80 00 2A D5 00 00 1A D6' - '00 00 02 D0 00 00 02 D0 00 00 02 D0 00 00 02 D0' - '00 00 03 F0 00 00 FF FF FF FF FF FF FF FF FF FF' - 'FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF' - 'FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF' - 'FF FF FF FF FF FF FF FF FF FF FF FF FF FF FC 0F' - 'FF FF FC 0F FF FF FC 0F FF FF FC 0F FF FF FC 0F' - 'FF FF E4 09 FF FF C4 08 FF FF 80 00 7F FF 00 00' - '3F FF 00 00 3F FF 80 00 7F FF C4 08 FF FF E4 09' - 'FF FF FC 0F FF FF FC 0F FF FF FC 0F FF FF FC 0F' - 'FF FF FC 0F FF FF' -} */ - - -/* BINRES idc_movebutton.cur */ -IDC_MOVEBUTTON CURSOR LOADONCALL DISCARDABLE idc_movebutton.cur -/* { - '00 00 02 00 01 00 20 20 00 00 10 00 10 00 30 01' - '00 00 16 00 00 00 28 00 00 00 20 00 00 00 40 00' - '00 00 01 00 01 00 00 00 00 00 00 01 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 FF FF FF 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 0F F8 00 00 0F' - 'F8 00 00 1F FC 00 00 1F FC 00 00 3F FC 00 00 3F' - 'FE 00 00 7F FE 00 00 5F FE 00 00 DF FE 00 01 DF' - 'FE 00 01 9F FE 00 00 1D B6 00 00 1D B4 00 00 0D' - 'B0 00 00 01 80 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 FF FF FF FF FF FF FF FF D2 49' - '24 93 DF FF FF FF FF FF FF FB DF FF FF FB DF FF' - 'FF FF FF FF FF FB DF E0 03 FB DF E0 03 FF FF E0' - '03 FB DF C0 01 FB DF C0 01 FF FF 80 01 FB DF 80' - '00 FB DF 00 00 FF FF 00 00 FB DE 00 00 FB DC 00' - '00 FF FC 00 00 FB DC 40 00 FB DF C0 01 FF FF E0' - '03 FB DF F0 0F FB DF FE 7F FF FF FF FF FB DF FF' - 'FF FB DF FF FF FF FF FF FF FB C9 24 92 4B FF FF' - 'FF FF FF FF FF FF' -} */ - - -/* BINRES idi_dragarrow.ico */ -IDI_DRAGARROW ICON LOADONCALL DISCARDABLE idi_dragarrow.ico -/* { - '00 00 01 00 01 00 20 20 02 00 00 00 00 00 30 01' - '00 00 16 00 00 00 28 00 00 00 20 00 00 00 40 00' - '00 00 01 00 01 00 00 00 00 00 00 01 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 FF FF FF 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 60 00 00 00 50 00 00 0F C8' - '00 00 08 04 00 00 08 02 00 00 08 04 00 00 09 C8' - '00 00 09 50 00 00 0F 60 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 FF FF FF FF FF FF FF FF FF FF' - 'FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF' - 'FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF' - 'FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF' - 'FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF' - 'FF FF FF FF FF FF FF 9F FF FF FF 8F FF FF F0 07' - 'FF FF F0 03 FF FF F0 01 FF FF F0 03 FF FF F0 07' - 'FF FF F0 8F FF FF F0 9F FF FF FF FF FF FF FF FF' - 'FF FF FF FF FF FF' -} */ - - -/* BINRES idi_tt_info_sm.ico */ -IDI_TT_INFO_SM ICON LOADONCALL DISCARDABLE idi_tt_info_sm.ico -/* { - '00 00 01 00 01 00 10 10 10 00 00 00 00 00 28 01' - '00 00 16 00 00 00 28 00 00 00 10 00 00 00 20 00' - '00 00 01 00 04 00 00 00 00 00 C0 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 80 00 00 80 00 00 00 80 80 00 80 00' - '00 00 80 00 80 00 80 80 00 00 C0 C0 C0 00 80 80' - '80 00 00 00 FF 00 00 FF 00 00 00 FF FF 00 FF 00' - '00 00 FF 00 FF 00 FF FF 00 00 FF FF FF 00 00 00' - '00 00 08 80 00 00 00 00 00 08 00 80 00 00 00 00' - '08 80 F0 80 00 00 00 00 80 0F F0 88 00 00 00 00' - '0F FF FF 00 80 00 00 0F FF FF FF FF 08 00 08 FF' - 'FC CC CC FF F0 80 8F FF FF 8C CF FF FF 08 8F FF' - 'FF 8C CF FF FF 08 8F FF FF 8C CF FF FF 08 8F FF' - 'F8 CC CF FF FF 00 8F FF FF FF FF FF FF 00 08 FF' - 'FF 8C CF FF F0 00 00 8F FF CC CF FF 00 00 00 08' - '8F FF FF 00 00 00 00 00 08 88 88 00 00 00 FF 9F' - '00 00 FE 1F 00 00 F8 1F 00 00 F0 0F 00 00 E0 07' - '00 00 C0 03 00 00 80 01 00 00 00 00 00 00 00 00' - '00 00 00 00 00 00 00 01 00 00 00 01 00 00 80 03' - '00 00 C0 07 00 00 E0 0F 00 00 F8 3F 00 00' -} */ - - -/* BINRES idi_tt_warn_sm.ico */ -IDI_TT_WARN_SM ICON LOADONCALL DISCARDABLE idi_tt_warn_sm.ico -/* { - '00 00 01 00 01 00 10 10 10 00 00 00 00 00 28 01' - '00 00 16 00 00 00 28 00 00 00 10 00 00 00 20 00' - '00 00 01 00 04 00 00 00 00 00 C0 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 80 00 00 80 00 00 00 80 80 00 80 00' - '00 00 80 00 80 00 80 80 00 00 C0 C0 C0 00 80 80' - '80 00 00 00 FF 00 00 FF 00 00 00 FF FF 00 FF 00' - '00 00 FF 00 FF 00 FF FF 00 00 FF FF FF 00 03 33' - '33 33 33 33 33 33 00 00 00 00 00 00 00 03 0B BB' - 'BB BB BB BB BB 03 00 BB BB 30 3B BB B0 30 00 BB' - 'BB 30 3B BB B0 30 00 0B BB BB BB BB 03 00 00 0B' - 'BB B0 BB BB 03 00 00 00 BB 30 3B B0 30 00 00 00' - 'BB 00 0B B0 30 00 00 00 0B 00 0B 03 00 00 00 00' - '0B B0 BB 03 00 00 00 00 00 BB B0 30 00 00 00 00' - '00 BB B0 30 00 00 00 00 00 0B 03 00 00 00 00 00' - '00 0B 03 00 00 00 00 00 00 00 30 00 00 00 80 00' - '00 00 00 00 00 00 00 00 00 00 80 01 00 00 80 01' - '00 00 C0 03 00 00 C0 03 00 00 E0 07 00 00 E0 07' - '00 00 F0 0F 00 00 F0 0F 00 00 F8 1F 00 00 F8 1F' - '00 00 FC 3F 00 00 FC 3F 00 00 FE 7F 00 00' -} */ - - -/* BINRES idi_tt_error_sm.ico */ -IDI_TT_ERROR_SM ICON LOADONCALL DISCARDABLE idi_tt_error_sm.ico -/* { - '00 00 01 00 01 00 10 10 10 00 00 00 00 00 28 01' - '00 00 16 00 00 00 28 00 00 00 10 00 00 00 20 00' - '00 00 01 00 04 00 00 00 00 00 C0 00 00 00 00 00' - '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 00 80 00 00 80 00 00 00 80 80 00 80 00' - '00 00 80 00 80 00 80 80 00 00 C0 C0 C0 00 80 80' - '80 00 00 00 FF 00 00 FF 00 00 00 FF FF 00 FF 00' - '00 00 FF 00 FF 00 FF FF 00 00 FF FF FF 00 00 00' - '08 88 88 80 00 00 00 08 81 11 11 88 80 00 00 01' - '19 99 99 11 88 00 00 19 99 99 99 99 18 80 01 99' - 'F9 99 99 F9 91 80 01 9F FF 99 9F FF 91 88 19 99' - 'FF F9 FF F9 99 18 19 99 9F FF FF 99 99 18 19 99' - '99 FF F9 99 99 18 19 99 9F FF FF 99 99 10 19 99' - 'FF F9 FF F9 99 10 01 9F FF 99 9F FF 91 00 01 99' - 'F9 99 99 F9 91 00 00 19 99 99 99 99 10 00 00 01' - '19 99 99 11 00 00 00 00 01 11 11 00 00 00 F8 1F' - '00 00 E0 07 00 00 E0 03 00 00 C0 01 00 00 80 01' - '00 00 80 00 00 00 00 00 00 00 00 00 00 00 00 00' - '00 00 00 01 00 00 00 01 00 00 80 03 00 00 80 03' - '00 00 C0 07 00 00 E0 0F 00 00 F8 3F 00 00' -} */ - - -/* - * Everything specific to any language goes - * in one of the specific files. - * Note that you can and may override resources - * which also have a neutral version. This is to - * get localized bitmaps for example. - */ - -#include "comctl_Cn.rc" -#include "comctl_Cs.rc" -#include "comctl_De.rc" -#include "comctl_En.rc" -#include "comctl_Es.rc" -#include "comctl_Fr.rc" -#include "comctl_It.rc" -#include "comctl_Ja.rc" -#include "comctl_Ko.rc" -#include "comctl_Nl.rc" -#include "comctl_Pl.rc" -#include "comctl_Pt.rc" -#include "comctl_Ru.rc" -#include "comctl_Si.rc" -#include "comctl_Th.rc" -#include "comctl_Uk.rc" diff --git a/reactos/lib/comctl32/smoothscroll.c b/reactos/lib/comctl32/smoothscroll.c deleted file mode 100644 index 658be6259f2..00000000000 --- a/reactos/lib/comctl32/smoothscroll.c +++ /dev/null @@ -1,136 +0,0 @@ -/* - * Undocumented SmoothScrollWindow function from COMCTL32.DLL - * - * Copyright 2000 Marcus Meissner - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2.1 of the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - * - * TODO - * - actually add smooth scrolling - */ - -#include - -#include "windef.h" -#include "winbase.h" -#include "winreg.h" -#include "winerror.h" -#include "wingdi.h" -#include "winuser.h" -#include "winnls.h" -#include "commctrl.h" -#include "wine/debug.h" - -WINE_DEFAULT_DEBUG_CHANNEL(commctrl); - -static DWORD smoothscroll = 2; - -typedef BOOL (CALLBACK *SCROLLWINDOWEXPROC)(HWND,INT,INT,LPRECT,LPRECT,HRGN,LPRECT,DWORD); -typedef struct tagSMOOTHSCROLLSTRUCT { - DWORD dwSize; - DWORD x2; - HWND hwnd; - DWORD dx; - - DWORD dy; - LPRECT lpscrollrect; - LPRECT lpcliprect; - HRGN hrgnupdate; - - LPRECT lpupdaterect; - DWORD flags; - DWORD stepinterval; - DWORD dx_step; - - DWORD dy_step; - SCROLLWINDOWEXPROC scrollfun; /* same parameters as ScrollWindowEx */ -} SMOOTHSCROLLSTRUCT; - -/************************************************************************** - * SmoothScrollWindow [COMCTL32.382] - * - * Lots of magic for smooth scrolling windows. - * - * RETURNS - * Success: TRUE - * Failure: FALSE - * - * BUGS - * Currently only scrolls ONCE. The comctl32 implementation uses GetTickCount - * and what else to do smooth scrolling. - */ -BOOL WINAPI SmoothScrollWindow( SMOOTHSCROLLSTRUCT *smooth ) { - LPRECT lpupdaterect = smooth->lpupdaterect; - HRGN hrgnupdate = smooth->hrgnupdate; - RECT tmprect; - BOOL ret = TRUE; - DWORD flags = smooth->flags; - - if (smooth->dwSize!=sizeof(SMOOTHSCROLLSTRUCT)) - return FALSE; - - if (!lpupdaterect) - lpupdaterect = &tmprect; - SetRectEmpty(lpupdaterect); - - if (!(flags & 0x40000)) { /* no override, use system wide defaults */ - if (smoothscroll == 2) { - HKEY hkey; - - smoothscroll = 0; - if (!RegOpenKeyA(HKEY_CURRENT_USER,"Control Panel\\Desktop",&hkey)) { - DWORD len = 4; - - RegQueryValueExA(hkey,"SmoothScroll",0,0,(LPBYTE)&smoothscroll,&len); - RegCloseKey(hkey); - } - } - if (!smoothscroll) - flags |= 0x20000; - } - - if (flags & 0x20000) { /* are we doing jump scrolling? */ - if ((smooth->x2 & 1) && smooth->scrollfun) - return smooth->scrollfun( - smooth->hwnd,smooth->dx,smooth->dy,smooth->lpscrollrect, - smooth->lpcliprect,hrgnupdate,lpupdaterect, - flags & 0xffff - ); - else - return ScrollWindowEx( - smooth->hwnd,smooth->dx,smooth->dy,smooth->lpscrollrect, - smooth->lpcliprect,hrgnupdate,lpupdaterect, - flags & 0xffff - ); - } - - FIXME("(hwnd=%p,flags=%lx,x2=%lx): should smooth scroll here.\n", - smooth->hwnd,flags,smooth->x2 - ); - /* FIXME: do timer based smooth scrolling */ - if ((smooth->x2 & 1) && smooth->scrollfun) - return smooth->scrollfun( - smooth->hwnd,smooth->dx,smooth->dy,smooth->lpscrollrect, - smooth->lpcliprect,hrgnupdate,lpupdaterect, - flags & 0xffff - ); - else - return ScrollWindowEx( - smooth->hwnd,smooth->dx,smooth->dy,smooth->lpscrollrect, - smooth->lpcliprect,hrgnupdate,lpupdaterect, - flags & 0xffff - ); - return ret; -} diff --git a/reactos/lib/comctl32/status.c b/reactos/lib/comctl32/status.c deleted file mode 100644 index 24ae72d1c88..00000000000 --- a/reactos/lib/comctl32/status.c +++ /dev/null @@ -1,1293 +0,0 @@ -/* - * Interface code to StatusWindow widget/control - * - * Copyright 1996 Bruce Milner - * Copyright 1998, 1999 Eric Kohl - * Copyright 2002 Dimitrie O. Paun - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2.1 of the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - * - * NOTE - * - * This code was audited for completeness against the documented features - * of Comctl32.dll version 6.0 on Sep. 24, 2002, 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: - * -- CCS_BOTTOM (default) - * -- CCS_LEFT - * -- CCS_NODEVIDER - * -- CCS_NOMOVEX - * -- CCS_NOMOVEY - * -- CCS_NOPARENTALIGN - * -- CCS_RIGHT - * -- CCS_TOP - * -- CCS_VERT (defaults to RIGHT) - */ - -#include -#include - -#include "windef.h" -#include "winbase.h" -#include "wine/unicode.h" -#include "wingdi.h" -#include "winuser.h" -#include "winnls.h" -#include "commctrl.h" -#include "comctl32.h" -#include "wine/debug.h" - -WINE_DEFAULT_DEBUG_CHANNEL(statusbar); - -typedef struct -{ - INT x; - INT style; - RECT bound; - LPWSTR text; - HICON hIcon; -} STATUSWINDOWPART; - -typedef struct -{ - HWND Self; - HWND Notify; - WORD numParts; - UINT height; - BOOL simple; - HWND hwndToolTip; - HFONT hFont; - HFONT hDefaultFont; - COLORREF clrBk; /* background color */ - BOOL bUnicode; /* unicode flag */ - BOOL NtfUnicode; /* notify format */ - STATUSWINDOWPART part0; /* simple window */ - STATUSWINDOWPART* parts; -} STATUS_INFO; - -/* - * Run tests using Waite Group Windows95 API Bible Vol. 1&2 - * The second cdrom contains executables drawstat.exe, gettext.exe, - * simple.exe, getparts.exe, setparts.exe, statwnd.exe - */ - -#define HORZ_BORDER 0 -#define VERT_BORDER 2 -#define HORZ_GAP 2 - -/* prototype */ -static void -STATUSBAR_SetPartBounds (STATUS_INFO *infoPtr); - -static inline LPCSTR debugstr_t(LPCWSTR text, BOOL isW) -{ - return isW ? debugstr_w(text) : debugstr_a((LPCSTR)text); -} - -static void -STATUSBAR_DrawSizeGrip (HDC hdc, LPRECT lpRect) -{ - HPEN hPenFace, hPenShadow, hPenHighlight, hOldPen; - POINT pt; - INT i; - - TRACE("draw size grip %ld,%ld - %ld,%ld\n", lpRect->left, lpRect->top, lpRect->right, lpRect->bottom); - - pt.x = lpRect->right - 1; - pt.y = lpRect->bottom - 1; - - hPenFace = CreatePen( PS_SOLID, 1, GetSysColor( COLOR_3DFACE )); - hOldPen = SelectObject( hdc, hPenFace ); - MoveToEx (hdc, pt.x - 12, pt.y, NULL); - LineTo (hdc, pt.x, pt.y); - LineTo (hdc, pt.x, pt.y - 13); - - pt.x--; - pt.y--; - - hPenShadow = CreatePen( PS_SOLID, 1, GetSysColor( COLOR_3DSHADOW )); - SelectObject( hdc, hPenShadow ); - for (i = 1; i < 11; i += 4) { - MoveToEx (hdc, pt.x - i, pt.y, NULL); - LineTo (hdc, pt.x + 1, pt.y - i - 1); - - MoveToEx (hdc, pt.x - i - 1, pt.y, NULL); - LineTo (hdc, pt.x + 1, pt.y - i - 2); - } - - hPenHighlight = CreatePen( PS_SOLID, 1, GetSysColor( COLOR_3DHIGHLIGHT )); - SelectObject( hdc, hPenHighlight ); - for (i = 3; i < 13; i += 4) { - MoveToEx (hdc, pt.x - i, pt.y, NULL); - LineTo (hdc, pt.x + 1, pt.y - i - 1); - } - - SelectObject (hdc, hOldPen); - DeleteObject( hPenFace ); - DeleteObject( hPenShadow ); - DeleteObject( hPenHighlight ); -} - - -static void -STATUSBAR_DrawPart (STATUS_INFO *infoPtr, HDC hdc, STATUSWINDOWPART *part, int itemID) -{ - RECT r = part->bound; - UINT border = BDR_SUNKENOUTER; - - TRACE("part bound %ld,%ld - %ld,%ld\n", r.left, r.top, r.right, r.bottom); - if (part->style & SBT_POPOUT) - border = BDR_RAISEDOUTER; - else if (part->style & SBT_NOBORDERS) - border = 0; - - DrawEdge(hdc, &r, border, BF_RECT|BF_ADJUST); - - if (part->style & SBT_OWNERDRAW) - { - DRAWITEMSTRUCT dis; - - dis.CtlID = GetWindowLongPtrW (infoPtr->Self, GWLP_ID); - dis.itemID = itemID; - dis.hwndItem = infoPtr->Self; - dis.hDC = hdc; - dis.rcItem = r; - dis.itemData = (INT)part->text; - SendMessageW (infoPtr->Notify, WM_DRAWITEM, (WPARAM)dis.CtlID, (LPARAM)&dis); - } - else - { - if (part->hIcon) - { - INT cy = r.bottom - r.top; - - r.left += 2; - DrawIconEx (hdc, r.left, r.top, part->hIcon, cy, cy, 0, 0, DI_NORMAL); - r.left += cy; - } - DrawStatusTextW (hdc, &r, part->text, SBT_NOBORDERS); - } -} - - -static void -STATUSBAR_RefreshPart (STATUS_INFO *infoPtr, HDC hdc, STATUSWINDOWPART *part, int itemID) -{ - HBRUSH hbrBk; - HFONT hOldFont; - - TRACE("item %d\n", itemID); - if (!IsWindowVisible (infoPtr->Self)) - return; - - if (part->bound.right < part->bound.left) return; - - if (infoPtr->clrBk != CLR_DEFAULT) - hbrBk = CreateSolidBrush (infoPtr->clrBk); - else - hbrBk = GetSysColorBrush (COLOR_3DFACE); - FillRect(hdc, &part->bound, hbrBk); - - hOldFont = SelectObject (hdc, infoPtr->hFont ? infoPtr->hFont : infoPtr->hDefaultFont); - - STATUSBAR_DrawPart (infoPtr, hdc, part, itemID); - - SelectObject (hdc, hOldFont); - - if (infoPtr->clrBk != CLR_DEFAULT) - DeleteObject (hbrBk); - - if (GetWindowLongW (infoPtr->Self, GWL_STYLE) & SBARS_SIZEGRIP) - { - RECT rect; - - GetClientRect (infoPtr->Self, &rect); - STATUSBAR_DrawSizeGrip (hdc, &rect); - } -} - - -static LRESULT -STATUSBAR_Refresh (STATUS_INFO *infoPtr, HDC hdc) -{ - int i; - RECT rect; - HBRUSH hbrBk; - HFONT hOldFont; - - TRACE("\n"); - if (!IsWindowVisible(infoPtr->Self)) - return 0; - - STATUSBAR_SetPartBounds(infoPtr); - - GetClientRect (infoPtr->Self, &rect); - - if (infoPtr->clrBk != CLR_DEFAULT) - hbrBk = CreateSolidBrush (infoPtr->clrBk); - else - hbrBk = GetSysColorBrush (COLOR_3DFACE); - FillRect(hdc, &rect, hbrBk); - - hOldFont = SelectObject (hdc, infoPtr->hFont ? infoPtr->hFont : infoPtr->hDefaultFont); - - if (infoPtr->simple) { - STATUSBAR_RefreshPart (infoPtr, hdc, &infoPtr->part0, 0); - } else { - for (i = 0; i < infoPtr->numParts; i++) { - STATUSBAR_RefreshPart (infoPtr, hdc, &infoPtr->parts[i], i); - } - } - - SelectObject (hdc, hOldFont); - - if (infoPtr->clrBk != CLR_DEFAULT) - DeleteObject (hbrBk); - - if (GetWindowLongW (infoPtr->Self, GWL_STYLE) & SBARS_SIZEGRIP) - STATUSBAR_DrawSizeGrip (hdc, &rect); - - return 0; -} - - -static void -STATUSBAR_SetPartBounds (STATUS_INFO *infoPtr) -{ - STATUSWINDOWPART *part; - RECT rect, *r; - int i; - - /* get our window size */ - GetClientRect (infoPtr->Self, &rect); - TRACE("client wnd size is %ld,%ld - %ld,%ld\n", rect.left, rect.top, rect.right, rect.bottom); - - rect.top += VERT_BORDER; - - /* set bounds for simple rectangle */ - infoPtr->part0.bound = rect; - - /* set bounds for non-simple rectangles */ - for (i = 0; i < infoPtr->numParts; i++) { - part = &infoPtr->parts[i]; - r = &infoPtr->parts[i].bound; - r->top = rect.top; - r->bottom = rect.bottom; - if (i == 0) - r->left = 0; - else - r->left = infoPtr->parts[i-1].bound.right + HORZ_GAP; - if (part->x == -1) - r->right = rect.right; - else - r->right = part->x; - - if (infoPtr->hwndToolTip) { - TTTOOLINFOW ti; - - ti.cbSize = sizeof(TTTOOLINFOW); - ti.hwnd = infoPtr->Self; - ti.uId = i; - ti.rect = *r; - SendMessageW (infoPtr->hwndToolTip, TTM_NEWTOOLRECTW, - 0, (LPARAM)&ti); - } - } -} - - -static LRESULT -STATUSBAR_Relay2Tip (STATUS_INFO *infoPtr, UINT uMsg, - WPARAM wParam, LPARAM lParam) -{ - MSG msg; - - msg.hwnd = infoPtr->Self; - msg.message = uMsg; - msg.wParam = wParam; - msg.lParam = lParam; - msg.time = GetMessageTime (); - msg.pt.x = LOWORD(GetMessagePos ()); - msg.pt.y = HIWORD(GetMessagePos ()); - - return SendMessageW (infoPtr->hwndToolTip, TTM_RELAYEVENT, 0, (LPARAM)&msg); -} - - -static BOOL -STATUSBAR_GetBorders (INT out[]) -{ - TRACE("\n"); - out[0] = HORZ_BORDER; /* horizontal border width */ - out[1] = VERT_BORDER; /* vertical border width */ - out[2] = HORZ_GAP; /* width of border between rectangles */ - - return TRUE; -} - - -static HICON -STATUSBAR_GetIcon (STATUS_INFO *infoPtr, INT nPart) -{ - TRACE("%d\n", nPart); - /* MSDN says: "simple parts are indexed with -1" */ - if ((nPart < -1) || (nPart >= infoPtr->numParts)) - return 0; - - if (nPart == -1) - return (infoPtr->part0.hIcon); - else - return (infoPtr->parts[nPart].hIcon); -} - - -static INT -STATUSBAR_GetParts (STATUS_INFO *infoPtr, INT num_parts, INT parts[]) -{ - INT i; - - TRACE("(%d)\n", num_parts); - if (parts) { - for (i = 0; i < num_parts; i++) { - parts[i] = infoPtr->parts[i].x; - } - } - return infoPtr->numParts; -} - - -static BOOL -STATUSBAR_GetRect (STATUS_INFO *infoPtr, INT nPart, LPRECT rect) -{ - TRACE("part %d\n", nPart); - if (infoPtr->simple) - *rect = infoPtr->part0.bound; - else - *rect = infoPtr->parts[nPart].bound; - return TRUE; -} - - -static LRESULT -STATUSBAR_GetTextA (STATUS_INFO *infoPtr, INT nPart, LPSTR buf) -{ - STATUSWINDOWPART *part; - LRESULT result; - - TRACE("part %d\n", nPart); - - /* MSDN says: "simple parts use index of 0", so this check is ok. */ - if (nPart < 0 || nPart >= infoPtr->numParts) return 0; - - if (infoPtr->simple) - part = &infoPtr->part0; - else - part = &infoPtr->parts[nPart]; - - if (part->style & SBT_OWNERDRAW) - result = (LRESULT)part->text; - else { - DWORD len = part->text ? WideCharToMultiByte( CP_ACP, 0, part->text, -1, - NULL, 0, NULL, NULL ) - 1 : 0; - result = MAKELONG( len, part->style ); - if (part->text && buf) - WideCharToMultiByte( CP_ACP, 0, part->text, -1, buf, len+1, NULL, NULL ); - } - return result; -} - - -static LRESULT -STATUSBAR_GetTextW (STATUS_INFO *infoPtr, INT nPart, LPWSTR buf) -{ - STATUSWINDOWPART *part; - LRESULT result; - - TRACE("part %d\n", nPart); - if (nPart < 0 || nPart >= infoPtr->numParts) return 0; - - if (infoPtr->simple) - part = &infoPtr->part0; - else - part = &infoPtr->parts[nPart]; - - if (part->style & SBT_OWNERDRAW) - result = (LRESULT)part->text; - else { - result = part->text ? strlenW (part->text) : 0; - result |= (part->style << 16); - if (part->text && buf) - strcpyW (buf, part->text); - } - return result; -} - - -static LRESULT -STATUSBAR_GetTextLength (STATUS_INFO *infoPtr, INT nPart) -{ - STATUSWINDOWPART *part; - DWORD result; - - TRACE("part %d\n", nPart); - - /* MSDN says: "simple parts use index of 0", so this check is ok. */ - if (nPart < 0 || nPart >= infoPtr->numParts) return 0; - - if (infoPtr->simple) - part = &infoPtr->part0; - else - part = &infoPtr->parts[nPart]; - - if (part->text) - result = strlenW(part->text); - else - result = 0; - - result |= (part->style << 16); - return result; -} - -static LRESULT -STATUSBAR_GetTipTextA (STATUS_INFO *infoPtr, INT id, LPSTR tip, INT size) -{ - TRACE("\n"); - if (tip) { - CHAR buf[INFOTIPSIZE]; - buf[0]='\0'; - - if (infoPtr->hwndToolTip) { - TTTOOLINFOA ti; - ti.cbSize = sizeof(TTTOOLINFOA); - ti.hwnd = infoPtr->Self; - ti.uId = id; - ti.lpszText = buf; - SendMessageA (infoPtr->hwndToolTip, TTM_GETTEXTA, 0, (LPARAM)&ti); - } - lstrcpynA (tip, buf, size); - } - return 0; -} - - -static LRESULT -STATUSBAR_GetTipTextW (STATUS_INFO *infoPtr, INT id, LPWSTR tip, INT size) -{ - TRACE("\n"); - if (tip) { - WCHAR buf[INFOTIPSIZE]; - buf[0]=0; - - if (infoPtr->hwndToolTip) { - TTTOOLINFOW ti; - ti.cbSize = sizeof(TTTOOLINFOW); - ti.hwnd = infoPtr->Self; - ti.uId = id; - ti.lpszText = buf; - SendMessageW(infoPtr->hwndToolTip, TTM_GETTEXTW, 0, (LPARAM)&ti); - } - lstrcpynW(tip, buf, size); - } - - return 0; -} - - -static COLORREF -STATUSBAR_SetBkColor (STATUS_INFO *infoPtr, COLORREF color) -{ - COLORREF oldBkColor; - - oldBkColor = infoPtr->clrBk; - infoPtr->clrBk = color; - InvalidateRect(infoPtr->Self, NULL, FALSE); - - TRACE("CREF: %08lx -> %08lx\n", oldBkColor, infoPtr->clrBk); - return oldBkColor; -} - - -static BOOL -STATUSBAR_SetIcon (STATUS_INFO *infoPtr, INT nPart, HICON hIcon) -{ - if ((nPart < -1) || (nPart >= infoPtr->numParts)) - return FALSE; - - TRACE("setting part %d\n", nPart); - - /* FIXME: MSDN says "if nPart is -1, the status bar is assumed simple" */ - if (nPart == -1) { - if (infoPtr->part0.hIcon == hIcon) /* same as - no redraw */ - return TRUE; - infoPtr->part0.hIcon = hIcon; - if (infoPtr->simple) - InvalidateRect(infoPtr->Self, &infoPtr->part0.bound, FALSE); - } else { - if (infoPtr->parts[nPart].hIcon == hIcon) /* same as - no redraw */ - return TRUE; - - infoPtr->parts[nPart].hIcon = hIcon; - if (!(infoPtr->simple)) - InvalidateRect(infoPtr->Self, &infoPtr->parts[nPart].bound, FALSE); - } - return TRUE; -} - - -static BOOL -STATUSBAR_SetMinHeight (STATUS_INFO *infoPtr, INT height) -{ - - TRACE("(height=%d)\n", height); - if (IsWindowVisible (infoPtr->Self)) { - INT width, x, y; - RECT parent_rect; - - GetClientRect (infoPtr->Notify, &parent_rect); - infoPtr->height = height + VERT_BORDER; - width = parent_rect.right - parent_rect.left; - x = parent_rect.left; - y = parent_rect.bottom - infoPtr->height; - MoveWindow (infoPtr->Self, parent_rect.left, - parent_rect.bottom - infoPtr->height, - width, infoPtr->height, TRUE); - STATUSBAR_SetPartBounds (infoPtr); - } - - return TRUE; -} - - -static BOOL -STATUSBAR_SetParts (STATUS_INFO *infoPtr, INT count, LPINT parts) -{ - STATUSWINDOWPART *tmp; - int i, oldNumParts; - - TRACE("(%d,%p)\n", count, parts); - - oldNumParts = infoPtr->numParts; - infoPtr->numParts = count; - if (oldNumParts > infoPtr->numParts) { - for (i = infoPtr->numParts ; i < oldNumParts; i++) { - if (infoPtr->parts[i].text && !(infoPtr->parts[i].style & SBT_OWNERDRAW)) - Free (infoPtr->parts[i].text); - } - } else if (oldNumParts < infoPtr->numParts) { - tmp = Alloc (sizeof(STATUSWINDOWPART) * infoPtr->numParts); - if (!tmp) return FALSE; - for (i = 0; i < oldNumParts; i++) { - tmp[i] = infoPtr->parts[i]; - } - if (infoPtr->parts) - Free (infoPtr->parts); - infoPtr->parts = tmp; - } - if (oldNumParts == infoPtr->numParts) { - for (i=0; i < oldNumParts; i++) - if (infoPtr->parts[i].x != parts[i]) - break; - if (i==oldNumParts) /* Unchanged? no need to redraw! */ - return TRUE; - } - - for (i = 0; i < infoPtr->numParts; i++) - infoPtr->parts[i].x = parts[i]; - - if (infoPtr->hwndToolTip) { - INT nTipCount, i; - TTTOOLINFOW ti; - - ZeroMemory (&ti, sizeof(TTTOOLINFOW)); - ti.cbSize = sizeof(TTTOOLINFOW); - ti.hwnd = infoPtr->Self; - - nTipCount = SendMessageW (infoPtr->hwndToolTip, TTM_GETTOOLCOUNT, 0, 0); - if (nTipCount < infoPtr->numParts) { - /* add tools */ - for (i = nTipCount; i < infoPtr->numParts; i++) { - TRACE("add tool %d\n", i); - ti.uId = i; - SendMessageW (infoPtr->hwndToolTip, TTM_ADDTOOLW, - 0, (LPARAM)&ti); - } - } - else if (nTipCount > infoPtr->numParts) { - /* delete tools */ - for (i = nTipCount - 1; i >= infoPtr->numParts; i--) { - TRACE("delete tool %d\n", i); - ti.uId = i; - SendMessageW (infoPtr->hwndToolTip, TTM_DELTOOLW, - 0, (LPARAM)&ti); - } - } - } - STATUSBAR_SetPartBounds (infoPtr); - InvalidateRect(infoPtr->Self, NULL, FALSE); - return TRUE; -} - - -static BOOL -STATUSBAR_SetTextT (STATUS_INFO *infoPtr, INT nPart, WORD style, - LPCWSTR text, BOOL isW) -{ - STATUSWINDOWPART *part=NULL; - BOOL changed = FALSE; - WORD oldStyle; - - if (style & SBT_OWNERDRAW) { - TRACE("part %d, text %p\n",nPart,text); - } - else TRACE("part %d, text %s\n", nPart, debugstr_t(text, isW)); - - /* MSDN says: "If the parameter is set to SB_SIMPLEID (255), the status - * window is assumed to be a simple window */ - - if (nPart == 0x00ff) { - part = &infoPtr->part0; - } else { - if (infoPtr->parts && nPart >= 0 && nPart < infoPtr->numParts) { - part = &infoPtr->parts[nPart]; - } - } - if (!part) return FALSE; - - if (part->style != style) - changed = TRUE; - - oldStyle = part->style; - part->style = style; - if (style & SBT_OWNERDRAW) { - if (part->text == text) - return TRUE; - part->text = (LPWSTR)text; - } else { - LPWSTR ntext; - - if (text && !isW) { - LPCSTR atxt = (LPCSTR)text; - DWORD len = MultiByteToWideChar( CP_ACP, 0, atxt, -1, NULL, 0 ); - ntext = Alloc( (len + 1)*sizeof(WCHAR) ); - if (!ntext) return FALSE; - MultiByteToWideChar( CP_ACP, 0, atxt, -1, ntext, len ); - } else if (text) { - ntext = Alloc( (strlenW(text) + 1)*sizeof(WCHAR) ); - if (!ntext) return FALSE; - strcpyW (ntext, text); - } else ntext = 0; - - /* check if text is unchanged -> no need to redraw */ - if (text) { - if (!changed && part->text && !lstrcmpW(ntext, part->text)) { - Free(ntext); - return TRUE; - } - } else { - if (!changed && !part->text) - return TRUE; - } - - if (part->text && !(oldStyle & SBT_OWNERDRAW)) - Free (part->text); - part->text = ntext; - } - InvalidateRect(infoPtr->Self, &part->bound, FALSE); - - return TRUE; -} - - -static LRESULT -STATUSBAR_SetTipTextA (STATUS_INFO *infoPtr, INT id, LPSTR text) -{ - TRACE("part %d: \"%s\"\n", id, text); - if (infoPtr->hwndToolTip) { - TTTOOLINFOA ti; - ti.cbSize = sizeof(TTTOOLINFOA); - ti.hwnd = infoPtr->Self; - ti.uId = id; - ti.hinst = 0; - ti.lpszText = text; - SendMessageA (infoPtr->hwndToolTip, TTM_UPDATETIPTEXTA, - 0, (LPARAM)&ti); - } - - return 0; -} - - -static LRESULT -STATUSBAR_SetTipTextW (STATUS_INFO *infoPtr, INT id, LPWSTR text) -{ - TRACE("part %d: \"%s\"\n", id, debugstr_w(text)); - if (infoPtr->hwndToolTip) { - TTTOOLINFOW ti; - ti.cbSize = sizeof(TTTOOLINFOW); - ti.hwnd = infoPtr->Self; - ti.uId = id; - ti.hinst = 0; - ti.lpszText = text; - SendMessageW (infoPtr->hwndToolTip, TTM_UPDATETIPTEXTW, - 0, (LPARAM)&ti); - } - - return 0; -} - - -inline static LRESULT -STATUSBAR_SetUnicodeFormat (STATUS_INFO *infoPtr, BOOL bUnicode) -{ - BOOL bOld = infoPtr->bUnicode; - - TRACE("(0x%x)\n", bUnicode); - infoPtr->bUnicode = bUnicode; - - return bOld; -} - - -static BOOL -STATUSBAR_Simple (STATUS_INFO *infoPtr, BOOL simple) -{ - NMHDR nmhdr; - - TRACE("(simple=%d)\n", simple); - if (infoPtr->simple == simple) /* no need to change */ - return TRUE; - - infoPtr->simple = simple; - - /* send notification */ - nmhdr.hwndFrom = infoPtr->Self; - nmhdr.idFrom = GetWindowLongPtrW (infoPtr->Self, GWLP_ID); - nmhdr.code = SBN_SIMPLEMODECHANGE; - SendMessageW (infoPtr->Notify, WM_NOTIFY, 0, (LPARAM)&nmhdr); - InvalidateRect(infoPtr->Self, NULL, FALSE); - return TRUE; -} - - -static LRESULT -STATUSBAR_WMDestroy (STATUS_INFO *infoPtr) -{ - int i; - - TRACE("\n"); - for (i = 0; i < infoPtr->numParts; i++) { - if (infoPtr->parts[i].text && !(infoPtr->parts[i].style & SBT_OWNERDRAW)) - Free (infoPtr->parts[i].text); - } - if (infoPtr->part0.text && !(infoPtr->part0.style & SBT_OWNERDRAW)) - Free (infoPtr->part0.text); - Free (infoPtr->parts); - - /* delete default font */ - if (infoPtr->hDefaultFont) - DeleteObject (infoPtr->hDefaultFont); - - /* delete tool tip control */ - if (infoPtr->hwndToolTip) - DestroyWindow (infoPtr->hwndToolTip); - - SetWindowLongPtrW(infoPtr->Self, 0, 0); - Free (infoPtr); - return 0; -} - - -static LRESULT -STATUSBAR_WMCreate (HWND hwnd, LPCREATESTRUCTA lpCreate) -{ - STATUS_INFO *infoPtr; - NONCLIENTMETRICSW nclm; - DWORD dwStyle; - RECT rect; - int i, width, len, textHeight = 0; - HDC hdc; - - TRACE("\n"); - infoPtr = (STATUS_INFO*)Alloc (sizeof(STATUS_INFO)); - if (!infoPtr) goto create_fail; - SetWindowLongPtrW (hwnd, 0, (DWORD_PTR)infoPtr); - - infoPtr->Self = hwnd; - infoPtr->Notify = lpCreate->hwndParent; - infoPtr->numParts = 1; - infoPtr->parts = 0; - infoPtr->simple = FALSE; - infoPtr->clrBk = CLR_DEFAULT; - infoPtr->hFont = 0; - - i = SendMessageW(infoPtr->Notify, WM_NOTIFYFORMAT, (WPARAM)hwnd, NF_QUERY); - infoPtr->NtfUnicode = (i == NFR_UNICODE); - - GetClientRect (hwnd, &rect); - InvalidateRect (hwnd, &rect, 0); - UpdateWindow(hwnd); - - ZeroMemory (&nclm, sizeof(nclm)); - nclm.cbSize = sizeof(nclm); - SystemParametersInfoW (SPI_GETNONCLIENTMETRICS, nclm.cbSize, &nclm, 0); - infoPtr->hDefaultFont = CreateFontIndirectW (&nclm.lfStatusFont); - - /* initialize simple case */ - infoPtr->part0.bound = rect; - infoPtr->part0.text = 0; - infoPtr->part0.x = 0; - infoPtr->part0.style = 0; - infoPtr->part0.hIcon = 0; - - /* initialize first part */ - infoPtr->parts = Alloc (sizeof(STATUSWINDOWPART)); - if (!infoPtr->parts) goto create_fail; - infoPtr->parts[0].bound = rect; - infoPtr->parts[0].text = 0; - infoPtr->parts[0].x = -1; - infoPtr->parts[0].style = 0; - infoPtr->parts[0].hIcon = 0; - - if (IsWindowUnicode (hwnd)) { - infoPtr->bUnicode = TRUE; - if (lpCreate->lpszName && - (len = strlenW ((LPCWSTR)lpCreate->lpszName))) { - infoPtr->parts[0].text = Alloc ((len + 1)*sizeof(WCHAR)); - if (!infoPtr->parts[0].text) goto create_fail; - strcpyW (infoPtr->parts[0].text, (LPCWSTR)lpCreate->lpszName); - } - } - else { - if (lpCreate->lpszName && - (len = strlen((LPCSTR)lpCreate->lpszName))) { - DWORD lenW = MultiByteToWideChar( CP_ACP, 0, (LPCSTR)lpCreate->lpszName, -1, NULL, 0 ); - infoPtr->parts[0].text = Alloc (lenW*sizeof(WCHAR)); - if (!infoPtr->parts[0].text) goto create_fail; - MultiByteToWideChar( CP_ACP, 0, (LPCSTR)lpCreate->lpszName, -1, - infoPtr->parts[0].text, lenW ); - } - } - - dwStyle = GetWindowLongW (hwnd, GWL_STYLE); - - /* statusbars on managed windows should not have SIZEGRIP style */ - if ((dwStyle & SBARS_SIZEGRIP) && lpCreate->hwndParent) - if (GetWindowLongW (lpCreate->hwndParent, GWL_EXSTYLE) & WS_EX_MANAGED) - SetWindowLongW (hwnd, GWL_STYLE, dwStyle & ~SBARS_SIZEGRIP); - - if ((hdc = GetDC (hwnd))) { - TEXTMETRICW tm; - HFONT hOldFont; - - hOldFont = SelectObject (hdc, infoPtr->hDefaultFont); - GetTextMetricsW (hdc, &tm); - textHeight = tm.tmHeight; - SelectObject (hdc, hOldFont); - ReleaseDC (hwnd, hdc); - } - TRACE(" textHeight=%d\n", textHeight); - - if (dwStyle & SBT_TOOLTIPS) { - infoPtr->hwndToolTip = - CreateWindowExW (0, TOOLTIPS_CLASSW, NULL, 0, - CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, - CW_USEDEFAULT, hwnd, 0, - (HINSTANCE)GetWindowLongPtrW(hwnd, GWLP_HINSTANCE), NULL); - - if (infoPtr->hwndToolTip) { - NMTOOLTIPSCREATED nmttc; - - nmttc.hdr.hwndFrom = hwnd; - nmttc.hdr.idFrom = GetWindowLongPtrW (hwnd, GWLP_ID); - nmttc.hdr.code = NM_TOOLTIPSCREATED; - nmttc.hwndToolTips = infoPtr->hwndToolTip; - - SendMessageW (lpCreate->hwndParent, WM_NOTIFY, - (WPARAM)nmttc.hdr.idFrom, (LPARAM)&nmttc); - } - } - - if (!(dwStyle & CCS_NORESIZE)) { /* don't resize wnd if it doesn't want it ! */ - GetClientRect (infoPtr->Notify, &rect); - width = rect.right - rect.left; - infoPtr->height = textHeight + 4 + VERT_BORDER; - SetWindowPos(hwnd, 0, lpCreate->x, lpCreate->y - 1, - width, infoPtr->height, SWP_NOZORDER); - STATUSBAR_SetPartBounds (infoPtr); - } - - return 0; - -create_fail: - TRACE(" failed!\n"); - if (infoPtr) STATUSBAR_WMDestroy(infoPtr); - return -1; -} - - -/* in contrast to SB_GETTEXT*, WM_GETTEXT handles the text - * of the first part only (usual behaviour) */ -static INT -STATUSBAR_WMGetText (STATUS_INFO *infoPtr, INT size, LPWSTR buf) -{ - INT len; - - TRACE("\n"); - if (!(infoPtr->parts[0].text)) - return 0; - if (infoPtr->bUnicode) - len = strlenW (infoPtr->parts[0].text); - else - len = WideCharToMultiByte( CP_ACP, 0, infoPtr->parts[0].text, -1, NULL, 0, NULL, NULL )-1; - - if (size > len) { - if (infoPtr->bUnicode) - strcpyW (buf, infoPtr->parts[0].text); - else - WideCharToMultiByte( CP_ACP, 0, infoPtr->parts[0].text, -1, - (LPSTR)buf, len+1, NULL, NULL ); - return len; - } - - return -1; -} - - -static BOOL -STATUSBAR_WMNCHitTest (STATUS_INFO *infoPtr, INT x, INT y) -{ - if (GetWindowLongW (infoPtr->Self, GWL_STYLE) & SBARS_SIZEGRIP) { - RECT rect; - POINT pt; - - GetClientRect (infoPtr->Self, &rect); - - pt.x = x; - pt.y = y; - ScreenToClient (infoPtr->Self, &pt); - - rect.left = rect.right - 13; - rect.top += 2; - - if (PtInRect (&rect, pt)) - return HTBOTTOMRIGHT; - } - - return HTERROR; -} - - -static LRESULT -STATUSBAR_WMPaint (STATUS_INFO *infoPtr, HDC hdc) -{ - PAINTSTRUCT ps; - - TRACE("\n"); - if (hdc) return STATUSBAR_Refresh (infoPtr, hdc); - hdc = BeginPaint (infoPtr->Self, &ps); - STATUSBAR_Refresh (infoPtr, hdc); - EndPaint (infoPtr->Self, &ps); - - return 0; -} - - -static LRESULT -STATUSBAR_WMSetFont (STATUS_INFO *infoPtr, HFONT font, BOOL redraw) -{ - infoPtr->hFont = font; - TRACE("%p\n", infoPtr->hFont); - if (redraw) - InvalidateRect(infoPtr->Self, NULL, FALSE); - - return 0; -} - - -static BOOL -STATUSBAR_WMSetText (STATUS_INFO *infoPtr, LPCSTR text) -{ - STATUSWINDOWPART *part; - int len; - - TRACE("\n"); - if (infoPtr->numParts == 0) - return FALSE; - - part = &infoPtr->parts[0]; - /* duplicate string */ - if (part->text) - Free (part->text); - part->text = 0; - if (infoPtr->bUnicode) { - if (text && (len = strlenW((LPCWSTR)text))) { - part->text = Alloc ((len+1)*sizeof(WCHAR)); - if (!part->text) return FALSE; - strcpyW (part->text, (LPCWSTR)text); - } - } - else { - if (text && (len = lstrlenA(text))) { - DWORD lenW = MultiByteToWideChar( CP_ACP, 0, text, -1, NULL, 0 ); - part->text = Alloc (lenW*sizeof(WCHAR)); - if (!part->text) return FALSE; - MultiByteToWideChar( CP_ACP, 0, text, -1, part->text, lenW ); - } - } - - InvalidateRect(infoPtr->Self, &part->bound, FALSE); - - return TRUE; -} - - -static BOOL -STATUSBAR_WMSize (STATUS_INFO *infoPtr, WORD flags) -{ - INT width, x, y; - RECT parent_rect; - - /* Need to resize width to match parent */ - TRACE("flags %04x\n", flags); - - if (flags != SIZE_RESTORED && flags != SIZE_MAXIMIZED) - { - WARN("flags MUST be SIZE_RESTORED or SIZE_MAXIMIZED\n"); - return FALSE; - } - - if (GetWindowLongW(infoPtr->Self, GWL_STYLE) & CCS_NORESIZE) return FALSE; - - /* width and height don't apply */ - GetClientRect (infoPtr->Notify, &parent_rect); - width = parent_rect.right - parent_rect.left; - x = parent_rect.left; - y = parent_rect.bottom - infoPtr->height; - MoveWindow (infoPtr->Self, parent_rect.left, - parent_rect.bottom - infoPtr->height, - width, infoPtr->height, TRUE); - STATUSBAR_SetPartBounds (infoPtr); - return TRUE; -} - - -static LRESULT -STATUSBAR_NotifyFormat (STATUS_INFO *infoPtr, HWND from, INT cmd) -{ - if (cmd == NF_REQUERY) { - INT i = SendMessageW(from, WM_NOTIFYFORMAT, (WPARAM)infoPtr->Self, NF_QUERY); - infoPtr->NtfUnicode = (i == NFR_UNICODE); - } - return infoPtr->NtfUnicode ? NFR_UNICODE : NFR_ANSI; -} - - -static LRESULT -STATUSBAR_SendNotify (STATUS_INFO *infoPtr, UINT code) -{ - NMHDR nmhdr; - - TRACE("code %04x\n", code); - nmhdr.hwndFrom = infoPtr->Self; - nmhdr.idFrom = GetWindowLongPtrW (infoPtr->Self, GWLP_ID); - nmhdr.code = code; - SendMessageW (infoPtr->Notify, WM_NOTIFY, 0, (LPARAM)&nmhdr); - return 0; -} - - - -static LRESULT WINAPI -StatusWindowProc (HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam) -{ - STATUS_INFO *infoPtr = (STATUS_INFO *)GetWindowLongPtrW (hwnd, 0); - INT nPart = ((INT) wParam) & 0x00ff; - LRESULT res; - - TRACE("hwnd=%p msg=%x wparam=%x lparam=%lx\n", hwnd, msg, wParam, lParam); - if (!infoPtr && msg != WM_CREATE) - return DefWindowProcW (hwnd, msg, wParam, lParam); - - switch (msg) { - case SB_GETBORDERS: - return STATUSBAR_GetBorders ((INT *)lParam); - - case SB_GETICON: - return (LRESULT)STATUSBAR_GetIcon (infoPtr, nPart); - - case SB_GETPARTS: - return STATUSBAR_GetParts (infoPtr, (INT)wParam, (INT *)lParam); - - case SB_GETRECT: - return STATUSBAR_GetRect (infoPtr, nPart, (LPRECT)lParam); - - case SB_GETTEXTA: - return STATUSBAR_GetTextA (infoPtr, nPart, (LPSTR)lParam); - - case SB_GETTEXTW: - return STATUSBAR_GetTextW (infoPtr, nPart, (LPWSTR)lParam); - - case SB_GETTEXTLENGTHA: - case SB_GETTEXTLENGTHW: - return STATUSBAR_GetTextLength (infoPtr, nPart); - - case SB_GETTIPTEXTA: - return STATUSBAR_GetTipTextA (infoPtr, LOWORD(wParam), (LPSTR)lParam, HIWORD(wParam)); - - case SB_GETTIPTEXTW: - return STATUSBAR_GetTipTextW (infoPtr, LOWORD(wParam), (LPWSTR)lParam, HIWORD(wParam)); - - case SB_GETUNICODEFORMAT: - return infoPtr->bUnicode; - - case SB_ISSIMPLE: - return infoPtr->simple; - - case SB_SETBKCOLOR: - return STATUSBAR_SetBkColor (infoPtr, (COLORREF)lParam); - - case SB_SETICON: - return STATUSBAR_SetIcon (infoPtr, nPart, (HICON)lParam); - - case SB_SETMINHEIGHT: - return STATUSBAR_SetMinHeight (infoPtr, (INT)wParam); - - case SB_SETPARTS: - return STATUSBAR_SetParts (infoPtr, (INT)wParam, (LPINT)lParam); - - case SB_SETTEXTA: - return STATUSBAR_SetTextT (infoPtr, nPart, wParam & 0xff00, (LPCWSTR)lParam, FALSE); - - case SB_SETTEXTW: - return STATUSBAR_SetTextT (infoPtr, nPart, wParam & 0xff00, (LPCWSTR)lParam, TRUE); - - case SB_SETTIPTEXTA: - return STATUSBAR_SetTipTextA (infoPtr, (INT)wParam, (LPSTR)lParam); - - case SB_SETTIPTEXTW: - return STATUSBAR_SetTipTextW (infoPtr, (INT)wParam, (LPWSTR)lParam); - - case SB_SETUNICODEFORMAT: - return STATUSBAR_SetUnicodeFormat (infoPtr, (BOOL)wParam); - - case SB_SIMPLE: - return STATUSBAR_Simple (infoPtr, (BOOL)wParam); - - case WM_CREATE: - return STATUSBAR_WMCreate (hwnd, (LPCREATESTRUCTA)lParam); - - case WM_DESTROY: - return STATUSBAR_WMDestroy (infoPtr); - - case WM_GETFONT: - return (LRESULT)(infoPtr->hFont? infoPtr->hFont : infoPtr->hDefaultFont); - - case WM_GETTEXT: - return STATUSBAR_WMGetText (infoPtr, (INT)wParam, (LPWSTR)lParam); - - case WM_GETTEXTLENGTH: - return STATUSBAR_GetTextLength (infoPtr, 0); - - case WM_LBUTTONDBLCLK: - return STATUSBAR_SendNotify (infoPtr, NM_DBLCLK); - - case WM_LBUTTONUP: - return STATUSBAR_SendNotify (infoPtr, NM_CLICK); - - case WM_MOUSEMOVE: - return STATUSBAR_Relay2Tip (infoPtr, msg, wParam, lParam); - - case WM_NCHITTEST: - res = STATUSBAR_WMNCHitTest(infoPtr, (INT)LOWORD(lParam), - (INT)HIWORD(lParam)); - if (res != HTERROR) return res; - return DefWindowProcW (hwnd, msg, wParam, lParam); - - case WM_NCLBUTTONUP: - case WM_NCLBUTTONDOWN: - PostMessageW (infoPtr->Notify, msg, wParam, lParam); - return 0; - - case WM_NOTIFYFORMAT: - return STATUSBAR_NotifyFormat(infoPtr, (HWND)wParam, (INT)lParam); - - case WM_PAINT: - return STATUSBAR_WMPaint (infoPtr, (HDC)wParam); - - case WM_RBUTTONDBLCLK: - return STATUSBAR_SendNotify (infoPtr, NM_RDBLCLK); - - case WM_RBUTTONUP: - return STATUSBAR_SendNotify (infoPtr, NM_RCLICK); - - case WM_SETFONT: - return STATUSBAR_WMSetFont (infoPtr, (HFONT)wParam, LOWORD(lParam)); - - case WM_SETTEXT: - return STATUSBAR_WMSetText (infoPtr, (LPCSTR)lParam); - - case WM_SIZE: - if (STATUSBAR_WMSize (infoPtr, (WORD)wParam)) return 0; - return DefWindowProcW (hwnd, msg, wParam, lParam); - - default: - if ((msg >= WM_USER) && (msg < WM_APP)) - ERR("unknown msg %04x wp=%04x lp=%08lx\n", - msg, wParam, lParam); - return DefWindowProcW (hwnd, msg, wParam, lParam); - } - return 0; -} - - -/*********************************************************************** - * STATUS_Register [Internal] - * - * Registers the status window class. - */ - -void -STATUS_Register (void) -{ - WNDCLASSW wndClass; - - ZeroMemory (&wndClass, sizeof(WNDCLASSW)); - wndClass.style = CS_GLOBALCLASS | CS_DBLCLKS | CS_VREDRAW; - wndClass.lpfnWndProc = StatusWindowProc; - wndClass.cbClsExtra = 0; - wndClass.cbWndExtra = sizeof(STATUS_INFO *); - wndClass.hCursor = LoadCursorW (0, (LPWSTR)IDC_ARROW); - wndClass.hbrBackground = (HBRUSH)(COLOR_BTNFACE + 1); - wndClass.lpszClassName = STATUSCLASSNAMEW; - - RegisterClassW (&wndClass); -} - - -/*********************************************************************** - * STATUS_Unregister [Internal] - * - * Unregisters the status window class. - */ - -void -STATUS_Unregister (void) -{ - UnregisterClassW (STATUSCLASSNAMEW, NULL); -} diff --git a/reactos/lib/comctl32/string.c b/reactos/lib/comctl32/string.c deleted file mode 100644 index 4d1d8d29be1..00000000000 --- a/reactos/lib/comctl32/string.c +++ /dev/null @@ -1,851 +0,0 @@ -/* - * String manipulation functions - * - * Copyright 1998 Eric Kohl - * 1998 Juergen Schmied - * 2000 Eric Kohl for CodeWeavers - * Copyright 2002 Jon Griffiths - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2.1 of the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - * - */ - -#include -#include -#include /* atoi */ - -#include "windef.h" -#include "winbase.h" -#include "winuser.h" -#include "winnls.h" - -#include "wine/unicode.h" - -#include "wine/debug.h" - -WINE_DEFAULT_DEBUG_CHANNEL(commctrl); - -/************************************************************************* - * COMCTL32_ChrCmpHelperA - * - * Internal helper for ChrCmpA/COMCTL32_ChrCmpIA. - * - * NOTES - * Both this function and its Unicode counterpart are very inneficient. To - * fix this, CompareString must be completely implemented and optimised - * first. Then the core character test can be taken out of that function and - * placed here, so that it need never be called at all. Until then, do not - * attempt to optimise this code unless you are willing to test that it - * still performs correctly. - */ -static BOOL COMCTL32_ChrCmpHelperA(WORD ch1, WORD ch2, DWORD dwFlags) -{ - char str1[3], str2[3]; - - str1[0] = LOBYTE(ch1); - if (IsDBCSLeadByte(str1[0])) - { - str1[1] = HIBYTE(ch1); - str1[2] = '\0'; - } - else - str1[1] = '\0'; - - str2[0] = LOBYTE(ch2); - if (IsDBCSLeadByte(str2[0])) - { - str2[1] = HIBYTE(ch2); - str2[2] = '\0'; - } - else - str2[1] = '\0'; - - return CompareStringA(GetThreadLocale(), dwFlags, str1, -1, str2, -1) - 2; -} - -/************************************************************************* - * COMCTL32_ChrCmpHelperW - * - * Internal helper for COMCTL32_ChrCmpW/ChrCmpIW. - */ -static BOOL COMCTL32_ChrCmpHelperW(WCHAR ch1, WCHAR ch2, DWORD dwFlags) -{ - WCHAR str1[2], str2[2]; - - str1[0] = ch1; - str1[1] = '\0'; - str2[0] = ch2; - str2[1] = '\0'; - return CompareStringW(GetThreadLocale(), dwFlags, str1, 2, str2, 2) - 2; -} - -/************************************************************************* - * COMCTL32_ChrCmpA (internal) - * - * Internal helper function. - */ -static BOOL COMCTL32_ChrCmpA(WORD ch1, WORD ch2) -{ - return COMCTL32_ChrCmpHelperA(ch1, ch2, 0); -} - -/************************************************************************* - * COMCTL32_ChrCmpIA (internal) - * - * Compare two characters, ignoring case. - * - * PARAMS - * ch1 [I] First character to compare - * ch2 [I] Second character to compare - * - * RETURNS - * FALSE, if the characters are equal. - * Non-zero otherwise. - */ -static BOOL COMCTL32_ChrCmpIA(WORD ch1, WORD ch2) -{ - TRACE("(%d,%d)\n", ch1, ch2); - - return COMCTL32_ChrCmpHelperA(ch1, ch2, NORM_IGNORECASE); -} - -/************************************************************************* - * COMCTL32_ChrCmpW - * - * Internal helper function. - */ -static BOOL COMCTL32_ChrCmpW(WCHAR ch1, WCHAR ch2) -{ - return COMCTL32_ChrCmpHelperW(ch1, ch2, 0); -} - -/************************************************************************* - * COMCTL32_ChrCmpIW - * - * Internal helper function. - */ -static BOOL COMCTL32_ChrCmpIW(WCHAR ch1, WCHAR ch2) -{ - return COMCTL32_ChrCmpHelperW(ch1, ch2, NORM_IGNORECASE); -} - -/************************************************************************** - * StrChrA [COMCTL32.350] - * - * Find a given character in a string. - * - * PARAMS - * lpszStr [I] String to search in. - * ch [I] Character to search for. - * - * RETURNS - * Success: A pointer to the first occurrence of ch in lpszStr, or NULL if - * not found. - * Failure: NULL, if any arguments are invalid. - */ -LPSTR WINAPI StrChrA(LPCSTR lpszStr, WORD ch) -{ - TRACE("(%s,%i)\n", debugstr_a(lpszStr), ch); - - if (lpszStr) - { - while (*lpszStr) - { - if (!COMCTL32_ChrCmpA(*lpszStr, ch)) - return (LPSTR)lpszStr; - lpszStr = CharNextA(lpszStr); - } - } - return NULL; -} - -/************************************************************************* - * COMCTL32_StrStrHelperA - * - * Internal implementation of StrStrA/StrStrIA - */ -static LPSTR COMCTL32_StrStrHelperA(LPCSTR lpszStr, LPCSTR lpszSearch, - int (*pStrCmpFn)(LPCSTR,LPCSTR,size_t)) -{ - size_t iLen; - - if (!lpszStr || !lpszSearch || !*lpszSearch) - return NULL; - - iLen = strlen(lpszSearch); - - while (*lpszStr) - { - if (!pStrCmpFn(lpszStr, lpszSearch, iLen)) - return (LPSTR)lpszStr; - lpszStr = CharNextA(lpszStr); - } - return NULL; -} - -/************************************************************************* - * COMCTL32_StrStrHelperW - * - * Internal implementation of StrStrW/StrStrIW - */ -static LPWSTR COMCTL32_StrStrHelperW(LPCWSTR lpszStr, LPCWSTR lpszSearch, - int (*pStrCmpFn)(LPCWSTR,LPCWSTR,int)) -{ - int iLen; - - if (!lpszStr || !lpszSearch || !*lpszSearch) - return NULL; - - iLen = strlenW(lpszSearch); - - while (*lpszStr) - { - if (!pStrCmpFn(lpszStr, lpszSearch, iLen)) - return (LPWSTR)lpszStr; - lpszStr = CharNextW(lpszStr); - } - return NULL; -} - -/************************************************************************** - * StrStrIA [COMCTL32.355] - * - * Find a substring within a string, ignoring case. - * - * PARAMS - * lpszStr [I] String to search in - * lpszSearch [I] String to look for - * - * RETURNS - * The start of lpszSearch within lpszStr, or NULL if not found. - */ -LPSTR WINAPI StrStrIA(LPCSTR lpszStr, LPCSTR lpszSearch) -{ - TRACE("(%s,%s)\n", debugstr_a(lpszStr), debugstr_a(lpszSearch)); - - return COMCTL32_StrStrHelperA(lpszStr, lpszSearch, strncasecmp); -} - -/************************************************************************** - * StrToIntA [COMCTL32.357] - * - * Read a signed integer from a string. - * - * PARAMS - * lpszStr [I] String to read integer from - * - * RETURNS - * The signed integer value represented by the string, or 0 if no integer is - * present. - */ -INT WINAPI StrToIntA (LPSTR lpszStr) -{ - return atoi(lpszStr); -} - -/************************************************************************** - * StrStrIW [COMCTL32.363] - * - * See StrStrIA. - */ -LPWSTR WINAPI StrStrIW(LPCWSTR lpszStr, LPCWSTR lpszSearch) -{ - TRACE("(%s,%s)\n", debugstr_w(lpszStr), debugstr_w(lpszSearch)); - - return COMCTL32_StrStrHelperW(lpszStr, lpszSearch, (int (*)(LPCWSTR,LPCWSTR,int)) wcsnicmp); -} - -/************************************************************************** - * StrToIntW [COMCTL32.365] - * - * See StrToIntA. - */ -INT WINAPI StrToIntW (LPWSTR lpString) -{ - return atoiW(lpString); -} - -/************************************************************************* - * COMCTL32_StrSpnHelperA (internal) - * - * Internal implementation of StrSpnA/StrCSpnA/StrCSpnIA - */ -static int COMCTL32_StrSpnHelperA(LPCSTR lpszStr, LPCSTR lpszMatch, - LPSTR (WINAPI *pStrChrFn)(LPCSTR,WORD), - BOOL bInvert) -{ - LPCSTR lpszRead = lpszStr; - if (lpszStr && *lpszStr && lpszMatch) - { - while (*lpszRead) - { - LPCSTR lpszTest = pStrChrFn(lpszMatch, *lpszRead); - - if (!bInvert && !lpszTest) - break; - if (bInvert && lpszTest) - break; - lpszRead = CharNextA(lpszRead); - }; - } - return lpszRead - lpszStr; -} - -/************************************************************************** - * StrCSpnA [COMCTL32.356] - * - * Find the length of the start of a string that does not contain certain - * characters. - * - * PARAMS - * lpszStr [I] String to search - * lpszMatch [I] Characters that cannot be in the substring - * - * RETURNS - * The length of the part of lpszStr containing only chars not in lpszMatch, - * or 0 if any parameter is invalid. - */ -int WINAPI StrCSpnA(LPCSTR lpszStr, LPCSTR lpszMatch) -{ - TRACE("(%s,%s)\n",debugstr_a(lpszStr), debugstr_a(lpszMatch)); - - return COMCTL32_StrSpnHelperA(lpszStr, lpszMatch, StrChrA, TRUE); -} - -/************************************************************************** - * StrChrW [COMCTL32.358] - * - * See StrChrA. - */ -LPWSTR WINAPI StrChrW(LPCWSTR lpszStr, WCHAR ch) -{ - LPWSTR lpszRet = NULL; - - TRACE("(%s,%i)\n", debugstr_w(lpszStr), ch); - - if (lpszStr) - lpszRet = strchrW(lpszStr, ch); - return lpszRet; -} - -/************************************************************************** - * StrCmpNA [COMCTL32.352] - * - * Compare two strings, up to a maximum length. - * - * PARAMS - * lpszStr [I] First string to compare - * lpszComp [I] Second string to compare - * iLen [I] Maximum number of chars to compare. - * - * RETURNS - * An integer less than, equal to or greater than 0, indicating that - * lpszStr is less than, the same, or greater than lpszComp. - */ -INT WINAPI StrCmpNA(LPCSTR lpszStr, LPCSTR lpszComp, INT iLen) -{ - INT iRet; - - TRACE("(%s,%s,%i)\n", debugstr_a(lpszStr), debugstr_a(lpszComp), iLen); - - iRet = CompareStringA(GetThreadLocale(), 0, lpszStr, iLen, lpszComp, iLen); - return iRet == CSTR_LESS_THAN ? -1 : iRet == CSTR_GREATER_THAN ? 1 : 0; -} - -/************************************************************************** - * StrCmpNIA [COMCTL32.353] - * - * Compare two strings, up to a maximum length, ignoring case. - * - * PARAMS - * lpszStr [I] First string to compare - * lpszComp [I] Second string to compare - * iLen [I] Maximum number of chars to compare. - * - * RETURNS - * An integer less than, equal to or greater than 0, indicating that - * lpszStr is less than, the same, or greater than lpszComp. - */ -int WINAPI StrCmpNIA(LPCSTR lpszStr, LPCSTR lpszComp, int iLen) -{ - INT iRet; - - TRACE("(%s,%s,%i)\n", debugstr_a(lpszStr), debugstr_a(lpszComp), iLen); - - iRet = CompareStringA(GetThreadLocale(), NORM_IGNORECASE, lpszStr, iLen, lpszComp, iLen); - return iRet == CSTR_LESS_THAN ? -1 : iRet == CSTR_GREATER_THAN ? 1 : 0; -} - -/************************************************************************* - * StrCmpNIW [COMCTL32.361] - * - * See StrCmpNIA. - */ -INT WINAPI StrCmpNIW(LPCWSTR lpszStr, LPCWSTR lpszComp, int iLen) -{ - INT iRet; - - TRACE("(%s,%s,%i)\n", debugstr_w(lpszStr), debugstr_w(lpszComp), iLen); - - iRet = CompareStringW(GetThreadLocale(), NORM_IGNORECASE, lpszStr, iLen, lpszComp, iLen); - return iRet == CSTR_LESS_THAN ? -1 : iRet == CSTR_GREATER_THAN ? 1 : 0; -} - -/************************************************************************** - * StrCmpNW [COMCTL32.360] - * - * See StrCmpNA. - */ -INT WINAPI StrCmpNW(LPCWSTR lpszStr, LPCWSTR lpszComp, INT iLen) -{ - INT iRet; - - TRACE("(%s,%s,%i)\n", debugstr_w(lpszStr), debugstr_w(lpszComp), iLen); - - iRet = CompareStringW(GetThreadLocale(), 0, lpszStr, iLen, lpszComp, iLen); - return iRet == CSTR_LESS_THAN ? -1 : iRet == CSTR_GREATER_THAN ? 1 : 0; -} - -/************************************************************************** - * StrRChrA [COMCTL32.351] - * - * Find the last occurence of a character in string. - * - * PARAMS - * lpszStr [I] String to search in - * lpszEnd [I] Place to end search, or NULL to search until the end of lpszStr - * ch [I] Character to search for. - * - * RETURNS - * Success: A pointer to the last occurrence of ch in lpszStr before lpszEnd, - * or NULL if not found. - * Failure: NULL, if any arguments are invalid. - */ -LPSTR WINAPI StrRChrA(LPCSTR lpszStr, LPCSTR lpszEnd, WORD ch) -{ - LPCSTR lpszRet = NULL; - - TRACE("(%s,%s,%x)\n", debugstr_a(lpszStr), debugstr_a(lpszEnd), ch); - - if (lpszStr) - { - WORD ch2; - - if (!lpszEnd) - lpszEnd = lpszStr + lstrlenA(lpszStr); - - while (*lpszStr && lpszStr <= lpszEnd) - { - ch2 = IsDBCSLeadByte(*lpszStr)? *lpszStr << 8 | lpszStr[1] : *lpszStr; - - if (!COMCTL32_ChrCmpA(ch, ch2)) - lpszRet = lpszStr; - lpszStr = CharNextA(lpszStr); - } - } - return (LPSTR)lpszRet; -} - - -/************************************************************************** - * StrRChrW [COMCTL32.359] - * - * See StrRChrA. - */ -LPWSTR WINAPI StrRChrW(LPCWSTR lpszStr, LPCWSTR lpszEnd, WORD ch) -{ - LPCWSTR lpszRet = NULL; - - TRACE("(%s,%s,%x)\n", debugstr_w(lpszStr), debugstr_w(lpszEnd), ch); - - if (lpszStr) - { - if (!lpszEnd) - lpszEnd = lpszStr + strlenW(lpszStr); - - while (*lpszStr && lpszStr <= lpszEnd) - { - if (!COMCTL32_ChrCmpW(ch, *lpszStr)) - lpszRet = lpszStr; - lpszStr = CharNextW(lpszStr); - } - } - return (LPWSTR)lpszRet; -} - -/************************************************************************** - * StrStrA [COMCTL32.354] - * - * Find a substring within a string. - * - * PARAMS - * lpszStr [I] String to search in - * lpszSearch [I] String to look for - * - * RETURNS - * The start of lpszSearch within lpszStr, or NULL if not found. - */ -LPSTR WINAPI StrStrA(LPCSTR lpszStr, LPCSTR lpszSearch) -{ - TRACE("(%s,%s)\n", debugstr_a(lpszStr), debugstr_a(lpszSearch)); - - return COMCTL32_StrStrHelperA(lpszStr, lpszSearch, strncmp); -} - -/************************************************************************** - * StrStrW [COMCTL32.362] - * - * See StrStrA. - */ -LPWSTR WINAPI StrStrW(LPCWSTR lpszStr, LPCWSTR lpszSearch) -{ - TRACE("(%s,%s)\n", debugstr_w(lpszStr), debugstr_w(lpszSearch)); - - return COMCTL32_StrStrHelperW(lpszStr, lpszSearch, (int (*)(LPCWSTR,LPCWSTR,int)) wcsncmp); -} - -/************************************************************************* - * StrChrIA [COMCTL32.366] - * - * Find a given character in a string, ignoring case. - * - * PARAMS - * lpszStr [I] String to search in. - * ch [I] Character to search for. - * - * RETURNS - * Success: A pointer to the first occurrence of ch in lpszStr, or NULL if - * not found. - * Failure: NULL, if any arguments are invalid. - */ -LPSTR WINAPI StrChrIA(LPCSTR lpszStr, WORD ch) -{ - TRACE("(%s,%i)\n", debugstr_a(lpszStr), ch); - - if (lpszStr) - { - while (*lpszStr) - { - if (!COMCTL32_ChrCmpIA(*lpszStr, ch)) - return (LPSTR)lpszStr; - lpszStr = CharNextA(lpszStr); - } - } - return NULL; -} - -/************************************************************************* - * StrChrIW [COMCTL32.367] - * - * See StrChrA. - */ -LPWSTR WINAPI StrChrIW(LPCWSTR lpszStr, WCHAR ch) -{ - TRACE("(%s,%i)\n", debugstr_w(lpszStr), ch); - - if (lpszStr) - { - ch = toupperW(ch); - while (*lpszStr) - { - if (toupperW(*lpszStr) == ch) - return (LPWSTR)lpszStr; - lpszStr = CharNextW(lpszStr); - } - lpszStr = NULL; - } - return (LPWSTR)lpszStr; -} - -/************************************************************************* - * StrRStrIA [COMCTL32.372] - * - * Find the last occurence of a substring within a string. - * - * PARAMS - * lpszStr [I] String to search in - * lpszEnd [I] End of lpszStr - * lpszSearch [I] String to look for - * - * RETURNS - * The last occurence lpszSearch within lpszStr, or NULL if not found. - */ -LPSTR WINAPI StrRStrIA(LPCSTR lpszStr, LPCSTR lpszEnd, LPCSTR lpszSearch) -{ - LPSTR lpszRet = NULL; - WORD ch1, ch2; - INT iLen; - - TRACE("(%s,%s)\n", debugstr_a(lpszStr), debugstr_a(lpszSearch)); - - if (!lpszStr || !lpszSearch || !*lpszSearch) - return NULL; - - if (!lpszEnd) - lpszEnd = lpszStr + lstrlenA(lpszStr); - - if (IsDBCSLeadByte(*lpszSearch)) - ch1 = *lpszSearch << 8 | lpszSearch[1]; - else - ch1 = *lpszSearch; - iLen = lstrlenA(lpszSearch); - - while (lpszStr <= lpszEnd && *lpszStr) - { - ch2 = IsDBCSLeadByte(*lpszStr)? *lpszStr << 8 | lpszStr[1] : *lpszStr; - if (!COMCTL32_ChrCmpIA(ch1, ch2)) - { - if (!StrCmpNIA(lpszStr, lpszSearch, iLen)) - lpszRet = (LPSTR)lpszStr; - } - lpszStr = CharNextA(lpszStr); - } - return lpszRet; -} - -/************************************************************************* - * StrRStrIW [COMCTL32.373] - * - * See StrRStrIA. - */ -LPWSTR WINAPI StrRStrIW(LPCWSTR lpszStr, LPCWSTR lpszEnd, LPCWSTR lpszSearch) -{ - LPWSTR lpszRet = NULL; - INT iLen; - - TRACE("(%s,%s)\n", debugstr_w(lpszStr), debugstr_w(lpszSearch)); - - if (!lpszStr || !lpszSearch || !*lpszSearch) - return NULL; - - if (!lpszEnd) - lpszEnd = lpszStr + strlenW(lpszStr); - - iLen = strlenW(lpszSearch); - - while (lpszStr <= lpszEnd && *lpszStr) - { - if (!COMCTL32_ChrCmpIW(*lpszSearch, *lpszStr)) - { - if (!StrCmpNIW(lpszStr, lpszSearch, iLen)) - lpszRet = (LPWSTR)lpszStr; - } - lpszStr = CharNextW(lpszStr); - } - return lpszRet; -} - -/************************************************************************* - * COMCTL32_StrSpnHelperW - * - * Internal implementation of StrSpnW/StrCSpnW/StrCSpnIW - */ -static int COMCTL32_StrSpnHelperW(LPCWSTR lpszStr, LPCWSTR lpszMatch, - LPWSTR (WINAPI *pStrChrFn)(LPCWSTR,WCHAR), - BOOL bInvert) -{ - LPCWSTR lpszRead = lpszStr; - if (lpszStr && *lpszStr && lpszMatch) - { - while (*lpszRead) - { - LPCWSTR lpszTest = pStrChrFn(lpszMatch, *lpszRead); - - if (!bInvert && !lpszTest) - break; - if (bInvert && lpszTest) - break; - lpszRead = CharNextW(lpszRead); - }; - } - return lpszRead - lpszStr; -} - -/************************************************************************* - * StrCSpnIA [COMCTL32.374] - * - * Find the length of the start of a string that does not contain certain - * characters, ignoring case. - * - * PARAMS - * lpszStr [I] String to search - * lpszMatch [I] Characters that cannot be in the substring - * - * RETURNS - * The length of the part of lpszStr containing only chars not in lpszMatch, - * or 0 if any parameter is invalid. - */ -int WINAPI StrCSpnIA(LPCSTR lpszStr, LPCSTR lpszMatch) -{ - TRACE("(%s,%s)\n",debugstr_a(lpszStr), debugstr_a(lpszMatch)); - - return COMCTL32_StrSpnHelperA(lpszStr, lpszMatch, StrChrIA, TRUE); -} - -/************************************************************************* - * StrCSpnIW [COMCTL32.375] - * - * See StrCSpnIA. - */ -int WINAPI StrCSpnIW(LPCWSTR lpszStr, LPCWSTR lpszMatch) -{ - TRACE("(%s,%s)\n",debugstr_w(lpszStr), debugstr_w(lpszMatch)); - - return COMCTL32_StrSpnHelperW(lpszStr, lpszMatch, StrChrIW, TRUE); -} - -/************************************************************************** - * StrRChrIA [COMCTL32.368] - * - * Find the last occurence of a character in string, ignoring case. - * - * PARAMS - * lpszStr [I] String to search in - * lpszEnd [I] Place to end search, or NULL to search until the end of lpszStr - * ch [I] Character to search for. - * - * RETURNS - * Success: A pointer to the last occurrence of ch in lpszStr before lpszEnd, - * or NULL if not found. - * Failure: NULL, if any arguments are invalid. - */ -LPSTR WINAPI StrRChrIA(LPCSTR lpszStr, LPCSTR lpszEnd, WORD ch) -{ - LPCSTR lpszRet = NULL; - - TRACE("(%s,%s,%x)\n", debugstr_a(lpszStr), debugstr_a(lpszEnd), ch); - - if (lpszStr) - { - WORD ch2; - - if (!lpszEnd) - lpszEnd = lpszStr + lstrlenA(lpszStr); - - while (*lpszStr && lpszStr <= lpszEnd) - { - ch2 = IsDBCSLeadByte(*lpszStr)? *lpszStr << 8 | lpszStr[1] : *lpszStr; - - if (ch == ch2) - lpszRet = lpszStr; - lpszStr = CharNextA(lpszStr); - } - } - return (LPSTR)lpszRet; -} - -/************************************************************************** - * StrRChrIW [COMCTL32.369] - * - * See StrRChrIA. - */ -LPWSTR WINAPI StrRChrIW(LPCWSTR lpszStr, LPCWSTR lpszEnd, WORD ch) -{ - LPCWSTR lpszRet = NULL; - - TRACE("(%s,%s,%x)\n", debugstr_w(lpszStr), debugstr_w(lpszEnd), ch); - - if (lpszStr) - { - if (!lpszEnd) - lpszEnd = lpszStr + strlenW(lpszStr); - - while (*lpszStr && lpszStr <= lpszEnd) - { - if (ch == *lpszStr) - lpszRet = lpszStr; - lpszStr = CharNextW(lpszStr); - } - } - return (LPWSTR)lpszRet; -} - -/************************************************************************* - * StrCSpnW [COMCTL32.364] - * - * See StrCSpnA. - */ -int WINAPI StrCSpnW(LPCWSTR lpszStr, LPCWSTR lpszMatch) -{ - TRACE("(%s,%s)\n",debugstr_w(lpszStr), debugstr_w(lpszMatch)); - - return COMCTL32_StrSpnHelperW(lpszStr, lpszMatch, StrChrW, TRUE); -} - -/************************************************************************* - * IntlStrEqWorkerA [COMCTL32.376] - * - * Compare two strings. - * - * PARAMS - * bCase [I] Whether to compare case sensitively - * lpszStr [I] First string to compare - * lpszComp [I] Second string to compare - * iLen [I] Length to compare - * - * RETURNS - * TRUE If the strings are equal. - * FALSE Otherwise. - */ -BOOL WINAPI IntlStrEqWorkerA(BOOL bCase, LPCSTR lpszStr, LPCSTR lpszComp, - int iLen) -{ - DWORD dwFlags = LOCALE_USE_CP_ACP; - int iRet; - - TRACE("(%d,%s,%s,%d)\n", bCase, - debugstr_a(lpszStr), debugstr_a(lpszComp), iLen); - - /* FIXME: These flags are undocumented and unknown by our CompareString. - * We need defines for them. - */ - dwFlags |= bCase ? 0x10000000 : 0x10000001; - - iRet = CompareStringA(GetThreadLocale(), - dwFlags, lpszStr, iLen, lpszComp, iLen); - - if (!iRet) - iRet = CompareStringA(2048, dwFlags, lpszStr, iLen, lpszComp, iLen); - - return iRet == 2 ? TRUE : FALSE; -} - -/************************************************************************* - * IntlStrEqWorkerW [COMCTL32.377] - * - * See IntlStrEqWorkerA. - */ -BOOL WINAPI IntlStrEqWorkerW(BOOL bCase, LPCWSTR lpszStr, LPCWSTR lpszComp, - int iLen) -{ - DWORD dwFlags; - int iRet; - - TRACE("(%d,%s,%s,%d)\n", bCase, - debugstr_w(lpszStr),debugstr_w(lpszComp), iLen); - - /* FIXME: These flags are undocumented and unknown by our CompareString. - * We need defines for them. - */ - dwFlags = bCase ? 0x10000000 : 0x10000001; - - iRet = CompareStringW(GetThreadLocale(), - dwFlags, lpszStr, iLen, lpszComp, iLen); - - if (!iRet) - iRet = CompareStringW(2048, dwFlags, lpszStr, iLen, lpszComp, iLen); - - return iRet == 2 ? TRUE : FALSE; -} diff --git a/reactos/lib/comctl32/syslink.c b/reactos/lib/comctl32/syslink.c deleted file mode 100644 index f81fd81bdeb..00000000000 --- a/reactos/lib/comctl32/syslink.c +++ /dev/null @@ -1,1681 +0,0 @@ -/* - * SysLink control - * - * Copyright 2004 Thomas Weidenmueller - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2.1 of the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - * - * TODO: - * - Fix SHIFT+TAB and TAB issue (wrong link is selected when control gets the focus) - * - Better string parsing - * - Improve word wrapping - * - Control styles?! - * - */ - -#include -#include -#include "windef.h" -#include "winbase.h" -#include "wingdi.h" -#include "winuser.h" -#include "winnls.h" -#include "commctrl.h" -#include "comctl32.h" -#include "wine/unicode.h" -#include "wine/debug.h" - -WINE_DEFAULT_DEBUG_CHANNEL(progress); - -INT WINAPI StrCmpNIW(LPCWSTR,LPCWSTR,INT); - -#define SYSLINK_Alloc(size) HeapAlloc(GetProcessHeap(), 0, (size)) -#define SYSLINK_Free(ptr) HeapFree(GetProcessHeap(), 0, (ptr)) -#define SYSLINK_ReAlloc(ptr, size) HeapReAlloc(GetProcessHeap(), 0, ptr, (size)) - -typedef struct -{ - int nChars; - RECT rc; -} DOC_TEXTBLOCK, *PDOC_TEXTBLOCK; - -#define LIF_FLAGSMASK (LIF_STATE | LIF_ITEMID | LIF_URL) -#define LIS_MASK (LIS_FOCUSED | LIS_ENABLED | LIS_VISITED) - -typedef enum -{ - slText = 0, - slLink -} SL_ITEM_TYPE; - -typedef struct _DOC_ITEM -{ - struct _DOC_ITEM *Next; /* Address to the next item */ - LPWSTR Text; /* Text of the document item */ - UINT nText; /* Number of characters of the text */ - SL_ITEM_TYPE Type; /* type of the item */ - PDOC_TEXTBLOCK Blocks; /* Array of text blocks */ - union - { - struct - { - UINT state; /* Link state */ - WCHAR *szID; /* Link ID string */ - WCHAR *szUrl; /* Link URL string */ - HRGN hRgn; /* Region of the link */ - } Link; - struct - { - UINT Dummy; - } Text; - } u; -} DOC_ITEM, *PDOC_ITEM; - -typedef struct -{ - HWND Self; /* The window handle for this control */ - PDOC_ITEM Items; /* Address to the first document item */ - BOOL HasFocus; /* Whether the control has the input focus */ - int MouseDownID; /* ID of the link that the mouse button first selected */ - HFONT Font; /* Handle to the font for text */ - HFONT LinkFont; /* Handle to the font for links */ - COLORREF TextColor; /* Color of the text */ - COLORREF LinkColor; /* Color of links */ - COLORREF VisitedColor; /* Color of visited links */ -} SYSLINK_INFO; - -static const WCHAR SL_LINKOPEN[] = { '<','a', 0 }; -static const WCHAR SL_HREF[] = { 'h','r','e','f','=','\"',0 }; -static const WCHAR SL_ID[] = { 'i','d','=','\"',0 }; -static const WCHAR SL_LINKCLOSE[] = { '<','/','a','>',0 }; - -/* Control configuration constants */ - -#define SL_LEFTMARGIN (0) -#define SL_TOPMARGIN (0) -#define SL_RIGHTMARGIN (0) -#define SL_BOTTOMMARGIN (0) - -/*********************************************************************** - * SYSLINK_FreeDocItem - * Frees all data and gdi objects associated with a document item - */ -static VOID SYSLINK_FreeDocItem (PDOC_ITEM DocItem) -{ - if(DocItem->Type == slLink) - { - if(DocItem->u.Link.szID != NULL) - { - SYSLINK_Free(DocItem->u.Link.szID); - } - if(DocItem->u.Link.szUrl != NULL) - { - SYSLINK_Free(DocItem->u.Link.szUrl); - } - } - - if(DocItem->Type == slLink && DocItem->u.Link.hRgn != NULL) - { - DeleteObject(DocItem->u.Link.hRgn); - } - - /* we don't free Text because it's just a pointer to a character in the - entire window text string */ - - SYSLINK_Free(DocItem); -} - -/*********************************************************************** - * SYSLINK_AppendDocItem - * Create and append a new document item. - */ -static PDOC_ITEM SYSLINK_AppendDocItem (SYSLINK_INFO *infoPtr, LPWSTR Text, UINT textlen, - SL_ITEM_TYPE type, PDOC_ITEM LastItem) -{ - PDOC_ITEM Item; - Item = SYSLINK_Alloc(sizeof(DOC_ITEM) + ((textlen + 1) * sizeof(WCHAR))); - if(Item == NULL) - { - ERR("Failed to alloc DOC_ITEM structure!\n"); - return NULL; - } - textlen = min(textlen, lstrlenW(Text)); - - Item->Next = NULL; - Item->Text = (LPWSTR)(Item + 1); - Item->nText = textlen; - Item->Type = type; - Item->Blocks = NULL; - - if(LastItem != NULL) - { - LastItem->Next = Item; - } - else - { - infoPtr->Items = Item; - } - - lstrcpynW(Item->Text, Text, textlen + 1); - Item->Text[textlen] = 0; - - return Item; -} - -/*********************************************************************** - * SYSLINK_ClearDoc - * Clears the document tree - */ -static VOID SYSLINK_ClearDoc (SYSLINK_INFO *infoPtr) -{ - PDOC_ITEM Item, Next; - - Item = infoPtr->Items; - while(Item != NULL) - { - Next = Item->Next; - SYSLINK_FreeDocItem(Item); - Item = Next; - } - - infoPtr->Items = NULL; -} - -/*********************************************************************** - * SYSLINK_ParseText - * Parses the window text string and creates a document. Returns the - * number of document items created. - */ -static UINT SYSLINK_ParseText (SYSLINK_INFO *infoPtr, LPWSTR Text) -{ - WCHAR *current, *textstart, *linktext, *firsttag; - int taglen = 0, textlen, linklen, docitems = 0; - PDOC_ITEM Last = NULL; - SL_ITEM_TYPE CurrentType = slText; - DWORD Style; - LPWSTR lpID, lpUrl; - UINT lenId, lenUrl; - - Style = GetWindowLongW(infoPtr->Self, GWL_STYLE); - - firsttag = NULL; - textstart = NULL; - linktext = NULL; - textlen = 0; - linklen = 0; - - for(current = (WCHAR*)Text; *current != 0;) - { - if(*current == '<') - { - if(!StrCmpNIW(current, SL_LINKOPEN, 2) && (CurrentType == slText)) - { - BOOL ValidParam = FALSE, ValidLink = FALSE; - - switch (*(current + 2)) - { - case '>': - /* we just have to deal with a tag */ - taglen = 3; - ValidLink = TRUE; - ValidParam = TRUE; - firsttag = current; - linklen = 0; - lpID = NULL; - lpUrl = NULL; - break; - case ' ': - { - /* we expect parameters, parse them */ - LPWSTR *CurrentParameter = NULL; - UINT *CurrentParameterLen = NULL; - WCHAR *tmp; - - taglen = 3; - tmp = current + taglen; - lpID = NULL; - lpUrl = NULL; - -CheckParameter: - /* compare the current position with all known parameters */ - if(!StrCmpNIW(tmp, SL_HREF, 6)) - { - taglen += 6; - ValidParam = TRUE; - CurrentParameter = &lpUrl; - CurrentParameterLen = &lenUrl; - } - else if(!StrCmpNIW(tmp, SL_ID, 4)) - { - taglen += 4; - ValidParam = TRUE; - CurrentParameter = &lpID; - CurrentParameterLen = &lenId; - } - else - { - ValidParam = FALSE; - } - - if(ValidParam) - { - /* we got a known parameter, now search until the next " character. - If we can't find a " character, there's a syntax error and we just assume it's text */ - ValidParam = FALSE; - *CurrentParameter = current + taglen; - *CurrentParameterLen = 0; - - for(tmp = *CurrentParameter; *tmp != 0; tmp++) - { - taglen++; - if(*tmp == '\"') - { - ValidParam = TRUE; - tmp++; - break; - } - (*CurrentParameterLen)++; - } - } - if(ValidParam) - { - /* we're done with this parameter, now there are only 2 possibilities: - * 1. another parameter is coming, so expect a ' ' (space) character - * 2. the tag is being closed, so expect a '<' character - */ - switch(*tmp) - { - case ' ': - /* we expect another parameter, do the whole thing again */ - taglen++; - tmp++; - goto CheckParameter; - - case '>': - /* the tag is being closed, we're done */ - ValidLink = TRUE; - taglen++; - break; - default: - tmp++; - break; - } - } - - break; - } - } - - if(ValidLink && ValidParam) - { - /* the tag appears to be valid. save all information - so we can add the link if we find a valid tag later */ - CurrentType = slLink; - linktext = current + taglen; - linklen = 0; - firsttag = current; - } - else - { - taglen = 1; - lpID = NULL; - lpUrl = NULL; - if(textstart == NULL) - { - textstart = current; - } - } - } - else if(!StrCmpNIW(current, SL_LINKCLOSE, 4) && (CurrentType == slLink) && firsttag) - { - /* there's a tag opened, first add the previous text, if present */ - if(textstart != NULL && textlen > 0 && firsttag > textstart) - { - Last = SYSLINK_AppendDocItem(infoPtr, textstart, firsttag - textstart, slText, Last); - if(Last == NULL) - { - ERR("Unable to create new document item!\n"); - return docitems; - } - docitems++; - textstart = NULL; - textlen = 0; - } - - /* now it's time to add the link to the document */ - current += 4; - if(linktext != NULL && linklen > 0) - { - Last = SYSLINK_AppendDocItem(infoPtr, linktext, linklen, slLink, Last); - if(Last == NULL) - { - ERR("Unable to create new document item!\n"); - return docitems; - } - docitems++; - if(CurrentType == slLink) - { - int nc; - - if(!(Style & WS_DISABLED)) - { - Last->u.Link.state |= LIS_ENABLED; - } - /* Copy the tag parameters */ - if(lpID != NULL) - { - nc = min(lenId, strlenW(lpID)); - nc = min(nc, MAX_LINKID_TEXT); - Last->u.Link.szID = SYSLINK_Alloc((MAX_LINKID_TEXT + 1) * sizeof(WCHAR)); - if(Last->u.Link.szID != NULL) - { - lstrcpynW(Last->u.Link.szID, lpID, nc + 1); - Last->u.Link.szID[nc] = 0; - } - } - else - Last->u.Link.szID = NULL; - if(lpUrl != NULL) - { - nc = min(lenUrl, strlenW(lpUrl)); - nc = min(nc, L_MAX_URL_LENGTH); - Last->u.Link.szUrl = SYSLINK_Alloc((L_MAX_URL_LENGTH + 1) * sizeof(WCHAR)); - if(Last->u.Link.szUrl != NULL) - { - lstrcpynW(Last->u.Link.szUrl, lpUrl, nc + 1); - Last->u.Link.szUrl[nc] = 0; - } - } - else - Last->u.Link.szUrl = NULL; - } - linktext = NULL; - } - CurrentType = slText; - firsttag = NULL; - textstart = NULL; - continue; - } - else - { - /* we don't know what tag it is, so just continue */ - taglen = 1; - linklen++; - if(CurrentType == slText && textstart == NULL) - { - textstart = current; - } - } - - textlen += taglen; - current += taglen; - } - else - { - textlen++; - linklen++; - - /* save the pointer of the current text item if we couldn't find a tag */ - if(textstart == NULL && CurrentType == slText) - { - textstart = current; - } - - current++; - } - } - - if(textstart != NULL && textlen > 0) - { - Last = SYSLINK_AppendDocItem(infoPtr, textstart, textlen, CurrentType, Last); - if(Last == NULL) - { - ERR("Unable to create new document item!\n"); - return docitems; - } - if(CurrentType == slLink) - { - int nc; - - if(!(Style & WS_DISABLED)) - { - Last->u.Link.state |= LIS_ENABLED; - } - /* Copy the tag parameters */ - if(lpID != NULL) - { - nc = min(lenId, strlenW(lpID)); - nc = min(nc, MAX_LINKID_TEXT); - Last->u.Link.szID = SYSLINK_Alloc((MAX_LINKID_TEXT + 1) * sizeof(WCHAR)); - if(Last->u.Link.szID != NULL) - { - lstrcpynW(Last->u.Link.szID, lpID, nc + 1); - Last->u.Link.szID[nc] = 0; - } - } - else - Last->u.Link.szID = NULL; - if(lpUrl != NULL) - { - nc = min(lenUrl, strlenW(lpUrl)); - nc = min(nc, L_MAX_URL_LENGTH); - Last->u.Link.szUrl = SYSLINK_Alloc((L_MAX_URL_LENGTH + 1) * sizeof(WCHAR)); - if(Last->u.Link.szUrl != NULL) - { - lstrcpynW(Last->u.Link.szUrl, lpUrl, nc + 1); - Last->u.Link.szUrl[nc] = 0; - } - } - else - Last->u.Link.szUrl = NULL; - } - docitems++; - } - - if(linktext != NULL && linklen > 0) - { - /* we got a unclosed link, just display the text */ - Last = SYSLINK_AppendDocItem(infoPtr, linktext, linklen, slText, Last); - if(Last == NULL) - { - ERR("Unable to create new document item!\n"); - return docitems; - } - docitems++; - } - - return docitems; -} - -/*********************************************************************** - * SYSLINK_RepaintLink - * Repaints a link. - */ -static VOID SYSLINK_RepaintLink (SYSLINK_INFO *infoPtr, PDOC_ITEM DocItem) -{ - if(DocItem->Type != slLink) - { - ERR("DocItem not a link!\n"); - return; - } - - if(DocItem->u.Link.hRgn != NULL) - { - /* repaint the region */ - RedrawWindow(infoPtr->Self, NULL, DocItem->u.Link.hRgn, RDW_INVALIDATE | RDW_UPDATENOW); - } -} - -/*********************************************************************** - * SYSLINK_GetLinkItemByIndex - * Retreives a document link by it's index - */ -static PDOC_ITEM SYSLINK_GetLinkItemByIndex (SYSLINK_INFO *infoPtr, int iLink) -{ - PDOC_ITEM Current = infoPtr->Items; - - while(Current != NULL) - { - if((Current->Type == slLink) && (iLink-- <= 0)) - { - return Current; - } - Current = Current->Next; - } - return NULL; -} - -/*********************************************************************** - * SYSLINK_GetFocusLink - * Retreives the link that has the LIS_FOCUSED bit - */ -static PDOC_ITEM SYSLINK_GetFocusLink (SYSLINK_INFO *infoPtr, int *LinkId) -{ - PDOC_ITEM Current = infoPtr->Items; - int id = 0; - - while(Current != NULL) - { - if((Current->Type == slLink)) - { - if(Current->u.Link.state & LIS_FOCUSED) - { - if(LinkId != NULL) - *LinkId = id; - return Current; - } - id++; - } - Current = Current->Next; - } - return NULL; -} - -/*********************************************************************** - * SYSLINK_GetNextLink - * Gets the next link - */ -static PDOC_ITEM SYSLINK_GetNextLink (SYSLINK_INFO *infoPtr, PDOC_ITEM Current) -{ - for(Current = (Current != NULL ? Current->Next : infoPtr->Items); - Current != NULL; - Current = Current->Next) - { - if(Current->Type == slLink) - { - return Current; - } - } - return NULL; -} - -/*********************************************************************** - * SYSLINK_GetPrevLink - * Gets the previous link - */ -static PDOC_ITEM SYSLINK_GetPrevLink (SYSLINK_INFO *infoPtr, PDOC_ITEM Current) -{ - if(Current == NULL) - { - /* returns the last link */ - PDOC_ITEM Last = NULL; - - for(Current = infoPtr->Items; Current != NULL; Current = Current->Next) - { - if(Current->Type == slLink) - { - Last = Current; - } - } - return Last; - } - else - { - /* returns the previous link */ - PDOC_ITEM Cur, Prev = NULL; - - for(Cur = infoPtr->Items; Cur != NULL; Cur = Cur->Next) - { - if(Cur == Current) - { - break; - } - if(Cur->Type == slLink) - { - Prev = Cur; - } - } - return Prev; - } -} - -/*********************************************************************** - * SYSLINK_WrapLine - * Tries to wrap a line. - */ -static BOOL SYSLINK_WrapLine (HDC hdc, LPWSTR Text, WCHAR BreakChar, int *LineLen, int nFit, LPSIZE Extent, int Width) -{ - WCHAR *Current; - - if(nFit == *LineLen) - { - return FALSE; - } - - *LineLen = nFit; - - Current = Text + nFit; - - /* check if we're in the middle of a word */ - if((*Current) != BreakChar) - { - /* search for the beginning of the word */ - while(Current > Text && (*(Current - 1)) != BreakChar) - { - Current--; - (*LineLen)--; - } - - if((*LineLen) == 0) - { - Extent->cx = 0; - Extent->cy = 0; - } - return TRUE; - } - - return TRUE; -} - -/*********************************************************************** - * SYSLINK_Render - * Renders the document in memory - */ -static VOID SYSLINK_Render (SYSLINK_INFO *infoPtr, HDC hdc) -{ - RECT rc; - PDOC_ITEM Current; - HGDIOBJ hOldFont; - int x, y, LineHeight; - TEXTMETRICW tm; - - GetClientRect(infoPtr->Self, &rc); - rc.right -= SL_RIGHTMARGIN; - rc.bottom -= SL_BOTTOMMARGIN; - - if(rc.right - SL_LEFTMARGIN < 0 || rc.bottom - SL_TOPMARGIN < 0) return; - - hOldFont = SelectObject(hdc, infoPtr->Font); - GetTextMetricsW(hdc, &tm); - - x = SL_LEFTMARGIN; - y = SL_TOPMARGIN; - LineHeight = 0; - - for(Current = infoPtr->Items; Current != NULL; Current = Current->Next) - { - int n, nBlocks; - LPWSTR tx; - PDOC_TEXTBLOCK bl, cbl; - INT nFit; - SIZE szDim; - - if(Current->nText == 0) - { - ERR("DOC_ITEM with no text?!\n"); - continue; - } - - tx = Current->Text; - n = Current->nText; - bl = Current->Blocks; - nBlocks = 0; - - if(Current->Type == slText) - { - SelectObject(hdc, infoPtr->Font); - } - else if(Current->Type == slLink) - { - SelectObject(hdc, infoPtr->LinkFont); - } - - while(n > 0) - { - if(GetTextExtentExPointW(hdc, tx, n, rc.right - x, &nFit, NULL, &szDim)) - { - int LineLen = n; - BOOL Wrap = SYSLINK_WrapLine(hdc, tx, tm.tmBreakChar, &LineLen, nFit, &szDim, rc.right - x); - - if(LineLen == 0) - { - if(x > SL_LEFTMARGIN) - { - /* move one line down, the word didn't fit into the line */ - x = SL_LEFTMARGIN; - y += LineHeight; - LineHeight = 0; - continue; - } - else - { - /* the word starts at the beginning of the line and doesn't - fit into the line, so break it at the last character that fits */ - LineLen = max(nFit, 1); - } - } - - if(LineLen != n) - { - GetTextExtentExPointW(hdc, tx, LineLen, rc.right - x, NULL, NULL, &szDim); - } - - if(bl != NULL) - { - bl = SYSLINK_ReAlloc(bl, ++nBlocks * sizeof(DOC_TEXTBLOCK)); - } - else - { - bl = SYSLINK_Alloc(++nBlocks * sizeof(DOC_TEXTBLOCK)); - } - - if(bl != NULL) - { - cbl = bl + nBlocks - 1; - - cbl->nChars = LineLen; - cbl->rc.left = x; - cbl->rc.top = y; - cbl->rc.right = x + szDim.cx; - cbl->rc.bottom = y + szDim.cy; - - x += szDim.cx; - LineHeight = max(LineHeight, szDim.cy); - - /* (re)calculate the link's region */ - if(Current->Type == slLink) - { - if(nBlocks <= 1) - { - if(Current->u.Link.hRgn != NULL) - { - DeleteObject(Current->u.Link.hRgn); - } - /* initialize the link's hRgn */ - Current->u.Link.hRgn = CreateRectRgnIndirect(&cbl->rc); - } - else if(Current->u.Link.hRgn != NULL) - { - HRGN hrgn; - hrgn = CreateRectRgnIndirect(&cbl->rc); - /* add the rectangle */ - CombineRgn(Current->u.Link.hRgn, Current->u.Link.hRgn, hrgn, RGN_OR); - DeleteObject(hrgn); - } - } - - if(Wrap) - { - x = SL_LEFTMARGIN; - y += LineHeight; - LineHeight = 0; - } - } - else - { - ERR("Failed to alloc DOC_TEXTBLOCK structure!\n"); - break; - } - n -= LineLen; - tx += LineLen; - } - else - { - ERR("GetTextExtentExPoint() failed?!\n"); - n--; - } - } - Current->Blocks = bl; - } - - SelectObject(hdc, hOldFont); -} - -/*********************************************************************** - * SYSLINK_Draw - * Draws the SysLink control. - */ -static LRESULT SYSLINK_Draw (SYSLINK_INFO *infoPtr, HDC hdc) -{ - RECT rc; - PDOC_ITEM Current; - HFONT hOldFont; - COLORREF OldTextColor, OldBkColor; - - hOldFont = SelectObject(hdc, infoPtr->Font); - OldTextColor = SetTextColor(hdc, infoPtr->TextColor); - OldBkColor = SetBkColor(hdc, GetSysColor(COLOR_BTNFACE)); - - GetClientRect(infoPtr->Self, &rc); - rc.right -= SL_RIGHTMARGIN + SL_LEFTMARGIN; - rc.bottom -= SL_BOTTOMMARGIN + SL_TOPMARGIN; - - if(rc.right < 0 || rc.bottom < 0) return 0; - - for(Current = infoPtr->Items; Current != NULL; Current = Current->Next) - { - int n; - LPWSTR tx; - PDOC_TEXTBLOCK bl; - - bl = Current->Blocks; - if(bl != NULL) - { - tx = Current->Text; - n = Current->nText; - - if(Current->Type == slText) - { - SelectObject(hdc, infoPtr->Font); - SetTextColor(hdc, infoPtr->TextColor); - } - else - { - SelectObject(hdc, infoPtr->LinkFont); - SetTextColor(hdc, (!(Current->u.Link.state & LIS_VISITED) ? infoPtr->LinkColor : infoPtr->VisitedColor)); - } - - while(n > 0) - { - ExtTextOutW(hdc, bl->rc.left, bl->rc.top, ETO_OPAQUE | ETO_CLIPPED, &bl->rc, tx, bl->nChars, NULL); - if((Current->Type == slLink) && (Current->u.Link.state & LIS_FOCUSED) && infoPtr->HasFocus) - { - COLORREF PrevColor; - PrevColor = SetBkColor(hdc, OldBkColor); - DrawFocusRect(hdc, &bl->rc); - SetBkColor(hdc, PrevColor); - } - tx += bl->nChars; - n -= bl->nChars; - bl++; - } - } - } - - SetBkColor(hdc, OldBkColor); - SetTextColor(hdc, OldTextColor); - SelectObject(hdc, hOldFont); - - return 0; -} - - -/*********************************************************************** - * SYSLINK_Paint - * Handles the WM_PAINT message. - */ -static LRESULT SYSLINK_Paint (SYSLINK_INFO *infoPtr) -{ - HDC hdc; - PAINTSTRUCT ps; - hdc = BeginPaint (infoPtr->Self, &ps); - SYSLINK_Draw (infoPtr, hdc); - EndPaint (infoPtr->Self, &ps); - return 0; -} - - -/*********************************************************************** - * SYSLINK_SetFont - * Set new Font for the SysLink control. - */ -static HFONT SYSLINK_SetFont (SYSLINK_INFO *infoPtr, HFONT hFont, BOOL bRedraw) -{ - HDC hdc; - LOGFONTW lf; - HFONT hOldFont = infoPtr->Font; - infoPtr->Font = hFont; - - /* free the underline font */ - if(infoPtr->LinkFont != NULL) - { - DeleteObject(infoPtr->LinkFont); - infoPtr->LinkFont = NULL; - } - - /* Render text position and word wrapping in memory */ - hdc = GetDC(infoPtr->Self); - if(hdc != NULL) - { - /* create a new underline font */ - if(GetObjectW(infoPtr->Font, sizeof(LOGFONTW), &lf)) - { - lf.lfUnderline = TRUE; - infoPtr->LinkFont = CreateFontIndirectW(&lf); - } - else - { - ERR("Failed to create link font!\n"); - } - - SYSLINK_Render(infoPtr, hdc); - ReleaseDC(infoPtr->Self, hdc); - } - - if(bRedraw) - { - RedrawWindow(infoPtr->Self, NULL, NULL, RDW_INVALIDATE | RDW_UPDATENOW); - } - - return hOldFont; -} - -/*********************************************************************** - * SYSLINK_SetText - * Set new text for the SysLink control. - */ -static LRESULT SYSLINK_SetText (SYSLINK_INFO *infoPtr, LPWSTR Text) -{ - int textlen; - - /* clear the document */ - SYSLINK_ClearDoc(infoPtr); - - textlen = lstrlenW(Text); - if(Text == NULL || textlen == 0) - { - return TRUE; - } - - /* let's parse the string and create a document */ - if(SYSLINK_ParseText(infoPtr, Text) > 0) - { - /* Render text position and word wrapping in memory */ - HDC hdc = GetDC(infoPtr->Self); - SYSLINK_Render(infoPtr, hdc); - SYSLINK_Draw(infoPtr, hdc); - ReleaseDC(infoPtr->Self, hdc); - } - - return TRUE; -} - -/*********************************************************************** - * SYSLINK_SetFocusLink - * Updates the focus status bits and focusses the specified link. - * If no document item is specified, the focus bit will be removed from all links. - * Returns the previous focused item. - */ -static PDOC_ITEM SYSLINK_SetFocusLink (SYSLINK_INFO *infoPtr, PDOC_ITEM DocItem) -{ - PDOC_ITEM Current, PrevFocus = NULL; - - for(Current = infoPtr->Items; Current != NULL; Current = Current->Next) - { - if(Current->Type == slLink) - { - if((PrevFocus == NULL) && (Current->u.Link.state & LIS_FOCUSED)) - { - PrevFocus = Current; - } - - if(Current == DocItem) - { - Current->u.Link.state |= LIS_FOCUSED; - } - else - { - Current->u.Link.state &= ~LIS_FOCUSED; - } - } - } - - return PrevFocus; -} - -/*********************************************************************** - * SYSLINK_SetItem - * Sets the states and attributes of a link item. - */ -static LRESULT SYSLINK_SetItem (SYSLINK_INFO *infoPtr, PLITEM Item) -{ - PDOC_ITEM di; - BOOL Repaint = FALSE; - BOOL Ret = TRUE; - - if(!(Item->mask & LIF_ITEMINDEX) || !(Item->mask & (LIF_FLAGSMASK))) - { - ERR("Invalid Flags!\n"); - return FALSE; - } - - di = SYSLINK_GetLinkItemByIndex(infoPtr, Item->iLink); - if(di == NULL) - { - ERR("Link %d couldn't be found\n", Item->iLink); - return FALSE; - } - - if(Item->mask & LIF_STATE) - { - UINT oldstate = di->u.Link.state; - /* clear the masked bits */ - di->u.Link.state &= ~(Item->stateMask & LIS_MASK); - /* copy the bits */ - di->u.Link.state |= (Item->state & Item->stateMask) & LIS_MASK; - Repaint = (oldstate != di->u.Link.state); - - /* update the focus */ - SYSLINK_SetFocusLink(infoPtr, ((di->u.Link.state & LIS_FOCUSED) ? di : NULL)); - } - - if(Item->mask & LIF_ITEMID) - { - if(!di->u.Link.szID) - { - di->u.Link.szID = SYSLINK_Alloc((MAX_LINKID_TEXT + 1) * sizeof(WCHAR)); - if(!Item->szID) - { - ERR("Unable to allocate memory for link id\n"); - Ret = FALSE; - } - } - if(di->u.Link.szID) - { - lstrcpynW(di->u.Link.szID, Item->szID, MAX_LINKID_TEXT + 1); - } - } - - if(Item->mask & LIF_URL) - { - if(!di->u.Link.szUrl) - { - di->u.Link.szUrl = SYSLINK_Alloc((MAX_LINKID_TEXT + 1) * sizeof(WCHAR)); - if(!Item->szUrl) - { - ERR("Unable to allocate memory for link url\n"); - Ret = FALSE; - } - } - if(di->u.Link.szUrl) - { - lstrcpynW(di->u.Link.szUrl, Item->szUrl, MAX_LINKID_TEXT + 1); - } - } - - if(Repaint) - { - SYSLINK_RepaintLink(infoPtr, di); - } - - return Ret; -} - -/*********************************************************************** - * SYSLINK_GetItem - * Retrieves the states and attributes of a link item. - */ -static LRESULT SYSLINK_GetItem (SYSLINK_INFO *infoPtr, PLITEM Item) -{ - PDOC_ITEM di; - - if(!(Item->mask & LIF_ITEMINDEX) || !(Item->mask & (LIF_FLAGSMASK))) - { - ERR("Invalid Flags!\n"); - return FALSE; - } - - di = SYSLINK_GetLinkItemByIndex(infoPtr, Item->iLink); - if(di == NULL) - { - ERR("Link %d couldn't be found\n", Item->iLink); - return FALSE; - } - - if(Item->mask & LIF_STATE) - { - Item->state = (di->u.Link.state & Item->stateMask); - if(!infoPtr->HasFocus) - { - /* remove the LIS_FOCUSED bit if the control doesn't have focus */ - Item->state &= ~LIS_FOCUSED; - } - } - - if(Item->mask & LIF_ITEMID) - { - if(di->u.Link.szID) - { - lstrcpynW(Item->szID, di->u.Link.szID, MAX_LINKID_TEXT + 1); - } - else - { - Item->szID[0] = 0; - } - } - - if(Item->mask & LIF_URL) - { - if(di->u.Link.szUrl) - { - lstrcpynW(Item->szUrl, di->u.Link.szUrl, L_MAX_URL_LENGTH + 1); - } - else - { - Item->szUrl[0] = 0; - } - } - - return TRUE; -} - -/*********************************************************************** - * SYSLINK_HitTest - * Determines the link the user clicked on. - */ -static LRESULT SYSLINK_HitTest (SYSLINK_INFO *infoPtr, PLHITTESTINFO HitTest) -{ - PDOC_ITEM Current; - int id = 0; - - for(Current = infoPtr->Items; Current != NULL; Current = Current->Next) - { - if(Current->Type == slLink) - { - if((Current->u.Link.hRgn != NULL) && - PtInRegion(Current->u.Link.hRgn, HitTest->pt.x, HitTest->pt.y)) - { - HitTest->item.mask = 0; - HitTest->item.iLink = id; - HitTest->item.state = 0; - HitTest->item.stateMask = 0; - if(Current->u.Link.szID) - { - lstrcpynW(HitTest->item.szID, Current->u.Link.szID, MAX_LINKID_TEXT + 1); - } - else - { - HitTest->item.szID[0] = 0; - } - if(Current->u.Link.szUrl) - { - lstrcpynW(HitTest->item.szUrl, Current->u.Link.szUrl, L_MAX_URL_LENGTH + 1); - } - else - { - HitTest->item.szUrl[0] = 0; - } - return TRUE; - } - id++; - } - } - - return FALSE; -} - -/*********************************************************************** - * SYSLINK_GetIdealHeight - * Returns the preferred height of a link at the current control's width. - */ -static LRESULT SYSLINK_GetIdealHeight (SYSLINK_INFO *infoPtr) -{ - HDC hdc = GetDC(infoPtr->Self); - if(hdc != NULL) - { - LRESULT height; - TEXTMETRICW tm; - HGDIOBJ hOldFont = SelectObject(hdc, infoPtr->Font); - - if(GetTextMetricsW(hdc, &tm)) - { - height = tm.tmHeight; - } - else - { - height = 0; - } - SelectObject(hdc, hOldFont); - ReleaseDC(infoPtr->Self, hdc); - - return height; - } - return 0; -} - -/*********************************************************************** - * SYSLINK_SendParentNotify - * Sends a WM_NOTIFY message to the parent window. - */ -static LRESULT SYSLINK_SendParentNotify (SYSLINK_INFO *infoPtr, UINT code, PDOC_ITEM Link, int iLink) -{ - NMLINK nml; - - nml.hdr.hwndFrom = infoPtr->Self; - nml.hdr.idFrom = GetWindowLongPtrW(infoPtr->Self, GWLP_ID); - nml.hdr.code = code; - - nml.item.mask = 0; - nml.item.iLink = iLink; - nml.item.state = 0; - nml.item.stateMask = 0; - if(Link->u.Link.szID) - { - lstrcpynW(nml.item.szID, Link->u.Link.szID, MAX_LINKID_TEXT + 1); - } - else - { - nml.item.szID[0] = 0; - } - if(Link->u.Link.szUrl) - { - lstrcpynW(nml.item.szUrl, Link->u.Link.szUrl, L_MAX_URL_LENGTH + 1); - } - else - { - nml.item.szUrl[0] = 0; - } - - return SendMessageW(GetParent(infoPtr->Self), WM_NOTIFY, (WPARAM)nml.hdr.idFrom, (LPARAM)&nml); -} - -/*********************************************************************** - * SYSLINK_SetFocus - * Handles receiving the input focus. - */ -static LRESULT SYSLINK_SetFocus (SYSLINK_INFO *infoPtr, HWND PrevFocusWindow) -{ - PDOC_ITEM Focus; - - infoPtr->HasFocus = TRUE; - -#if 1 - /* FIXME - How to detect whether SHIFT+TAB or just TAB has been pressed? - * The problem is we could get this message without keyboard input, too - */ - Focus = SYSLINK_GetFocusLink(infoPtr, NULL); - - if(Focus == NULL && (Focus = SYSLINK_GetNextLink(infoPtr, NULL))) - { - SYSLINK_SetFocusLink(infoPtr, Focus); - } -#else - /* This is a temporary hack since I'm not really sure how to detect which link to select. - See message above! */ - Focus = SYSLINK_GetNextLink(infoPtr, NULL); - if(Focus != NULL) - { - SYSLINK_SetFocusLink(infoPtr, Focus); - } -#endif - - SYSLINK_RepaintLink(infoPtr, Focus); - - return 0; -} - -/*********************************************************************** - * SYSLINK_KillFocus - * Handles losing the input focus. - */ -static LRESULT SYSLINK_KillFocus (SYSLINK_INFO *infoPtr, HWND NewFocusWindow) -{ - PDOC_ITEM Focus; - - infoPtr->HasFocus = FALSE; - Focus = SYSLINK_GetFocusLink(infoPtr, NULL); - - if(Focus != NULL) - { - SYSLINK_RepaintLink(infoPtr, Focus); - } - - return 0; -} - -/*********************************************************************** - * SYSLINK_LinkAtPt - * Returns a link at the specified position - */ -static PDOC_ITEM SYSLINK_LinkAtPt (SYSLINK_INFO *infoPtr, POINT *pt, int *LinkId, BOOL MustBeEnabled) -{ - PDOC_ITEM Current; - int id = 0; - - for(Current = infoPtr->Items; Current != NULL; Current = Current->Next) - { - if((Current->Type == slLink) && (Current->u.Link.hRgn != NULL) && - PtInRegion(Current->u.Link.hRgn, pt->x, pt->y) && - (!MustBeEnabled || (MustBeEnabled && (Current->u.Link.state & LIS_ENABLED)))) - { - if(LinkId != NULL) - { - *LinkId = id; - } - return Current; - } - id++; - } - - return NULL; -} - -/*********************************************************************** - * SYSLINK_LButtonDown - * Handles mouse clicks - */ -static LRESULT SYSLINK_LButtonDown (SYSLINK_INFO *infoPtr, DWORD Buttons, POINT *pt) -{ - PDOC_ITEM Current, Old; - int id; - - Current = SYSLINK_LinkAtPt(infoPtr, pt, &id, TRUE); - if(Current != NULL) - { - Old = SYSLINK_SetFocusLink(infoPtr, Current); - if(Old != NULL && Old != Current) - { - SYSLINK_RepaintLink(infoPtr, Old); - } - infoPtr->MouseDownID = id; - SYSLINK_RepaintLink(infoPtr, Current); - SetFocus(infoPtr->Self); - } - - return 0; -} - -/*********************************************************************** - * SYSLINK_LButtonUp - * Handles mouse clicks - */ -static LRESULT SYSLINK_LButtonUp (SYSLINK_INFO *infoPtr, DWORD Buttons, POINT *pt) -{ - if(infoPtr->MouseDownID > -1) - { - PDOC_ITEM Current; - int id; - - Current = SYSLINK_LinkAtPt(infoPtr, pt, &id, TRUE); - if((Current != NULL) && (Current->u.Link.state & LIS_FOCUSED) && (infoPtr->MouseDownID == id)) - { - SYSLINK_SendParentNotify(infoPtr, NM_CLICK, Current, id); - } - } - - infoPtr->MouseDownID = -1; - - return 0; -} - -/*********************************************************************** - * SYSLINK_OnEnter - * Handles ENTER key events - */ -static BOOL SYSLINK_OnEnter (SYSLINK_INFO *infoPtr) -{ - if(infoPtr->HasFocus) - { - PDOC_ITEM Focus; - int id; - - Focus = SYSLINK_GetFocusLink(infoPtr, &id); - if(Focus != NULL) - { - SYSLINK_SendParentNotify(infoPtr, NM_RETURN, Focus, id); - return TRUE; - } - } - return FALSE; -} - -/*********************************************************************** - * SYSKEY_SelectNextPrevLink - * Changes the currently focused link - */ -static BOOL SYSKEY_SelectNextPrevLink (SYSLINK_INFO *infoPtr, BOOL Prev) -{ - if(infoPtr->HasFocus) - { - PDOC_ITEM Focus; - int id; - - Focus = SYSLINK_GetFocusLink(infoPtr, &id); - if(Focus != NULL) - { - PDOC_ITEM NewFocus, OldFocus; - - if(Prev) - NewFocus = SYSLINK_GetPrevLink(infoPtr, Focus); - else - NewFocus = SYSLINK_GetNextLink(infoPtr, Focus); - - if(NewFocus != NULL) - { - OldFocus = SYSLINK_SetFocusLink(infoPtr, NewFocus); - - if(OldFocus != NewFocus) - { - SYSLINK_RepaintLink(infoPtr, OldFocus); - } - SYSLINK_RepaintLink(infoPtr, NewFocus); - return TRUE; - } - } - } - return FALSE; -} - -/*********************************************************************** - * SYSKEY_SelectNextPrevLink - * Determines if there's a next or previous link to decide whether the control - * should capture the tab key message - */ -static BOOL SYSLINK_NoNextLink (SYSLINK_INFO *infoPtr, BOOL Prev) -{ - PDOC_ITEM Focus, NewFocus; - - Focus = SYSLINK_GetFocusLink(infoPtr, NULL); - if(Prev) - NewFocus = SYSLINK_GetPrevLink(infoPtr, Focus); - else - NewFocus = SYSLINK_GetNextLink(infoPtr, Focus); - - return NewFocus == NULL; -} - -/*********************************************************************** - * SysLinkWindowProc - */ -static LRESULT WINAPI SysLinkWindowProc(HWND hwnd, UINT message, - WPARAM wParam, LPARAM lParam) -{ - SYSLINK_INFO *infoPtr; - - TRACE("hwnd=%p msg=%04x wparam=%x lParam=%lx\n", hwnd, message, wParam, lParam); - - infoPtr = (SYSLINK_INFO *)GetWindowLongPtrW(hwnd, 0); - - if (!infoPtr && message != WM_CREATE) - return DefWindowProcW( hwnd, message, wParam, lParam ); - - switch(message) { - case WM_PAINT: - return SYSLINK_Paint (infoPtr); - - case WM_SETCURSOR: - { - LHITTESTINFO ht; - DWORD mp = GetMessagePos(); - - ht.pt.x = (short)LOWORD(mp); - ht.pt.y = (short)HIWORD(mp); - - ScreenToClient(infoPtr->Self, &ht.pt); - if(SYSLINK_HitTest (infoPtr, &ht)) - { - SetCursor(LoadCursorW(0, (LPCWSTR)IDC_HAND)); - return TRUE; - } - /* let the default window proc handle this message */ - return DefWindowProcW(hwnd, message, wParam, lParam); - - } - - case WM_SIZE: - { - HDC hdc = GetDC(infoPtr->Self); - if(hdc != NULL) - { - SYSLINK_Render(infoPtr, hdc); - ReleaseDC(infoPtr->Self, hdc); - } - return 0; - } - - case WM_GETFONT: - return (LRESULT)infoPtr->Font; - - case WM_SETFONT: - return (LRESULT)SYSLINK_SetFont(infoPtr, (HFONT)wParam, (BOOL)lParam); - - case WM_SETTEXT: - SYSLINK_SetText(infoPtr, (LPWSTR)lParam); - return DefWindowProcW(hwnd, message, wParam, lParam); - - case WM_LBUTTONDOWN: - { - POINT pt; - pt.x = LOWORD(lParam); - pt.y = HIWORD(lParam); - return SYSLINK_LButtonDown(infoPtr, wParam, &pt); - } - case WM_LBUTTONUP: - { - POINT pt; - pt.x = LOWORD(lParam); - pt.y = HIWORD(lParam); - return SYSLINK_LButtonUp(infoPtr, wParam, &pt); - } - - case WM_KEYDOWN: - { - switch(wParam) - { - case VK_RETURN: - SYSLINK_OnEnter(infoPtr); - return 0; - case VK_TAB: - { - BOOL shift = GetKeyState(VK_SHIFT) & 0x8000; - SYSKEY_SelectNextPrevLink(infoPtr, shift); - return 0; - } - } - return DefWindowProcW(hwnd, message, wParam, lParam); - } - - case WM_GETDLGCODE: - { - LRESULT Ret = DLGC_HASSETSEL; - int vk = (lParam != 0 ? (int)((LPMSG)lParam)->wParam : 0); - switch(vk) - { - case VK_RETURN: - Ret |= DLGC_WANTMESSAGE; - break; - case VK_TAB: - { - BOOL shift = GetKeyState(VK_SHIFT) & 0x8000; - if(!SYSLINK_NoNextLink(infoPtr, shift)) - { - Ret |= DLGC_WANTTAB; - } - else - { - Ret |= DLGC_WANTCHARS; - } - break; - } - } - return Ret; - } - - case WM_NCHITTEST: - { - POINT pt; - RECT rc; - pt.x = LOWORD(lParam); - pt.y = HIWORD(lParam); - - GetClientRect(infoPtr->Self, &rc); - ScreenToClient(infoPtr->Self, &pt); - if(pt.x < 0 || pt.y < 0 || pt.x > rc.right || pt.y > rc.bottom) - { - return HTNOWHERE; - } - - if(SYSLINK_LinkAtPt(infoPtr, &pt, NULL, FALSE)) - { - return HTCLIENT; - } - - return HTTRANSPARENT; - } - - case LM_HITTEST: - return SYSLINK_HitTest(infoPtr, (PLHITTESTINFO)lParam); - - case LM_SETITEM: - return SYSLINK_SetItem(infoPtr, (PLITEM)lParam); - - case LM_GETITEM: - return SYSLINK_GetItem(infoPtr, (PLITEM)lParam); - - case LM_GETIDEALHEIGHT: - return SYSLINK_GetIdealHeight(infoPtr); - - case WM_SETFOCUS: - return SYSLINK_SetFocus(infoPtr, (HWND)wParam); - - case WM_KILLFOCUS: - return SYSLINK_KillFocus(infoPtr, (HWND)wParam); - - case WM_CREATE: - /* allocate memory for info struct */ - infoPtr = (SYSLINK_INFO *)SYSLINK_Alloc (sizeof(SYSLINK_INFO)); - if (!infoPtr) return -1; - SetWindowLongPtrW (hwnd, 0, (DWORD_PTR)infoPtr); - - /* initialize the info struct */ - infoPtr->Self = hwnd; - infoPtr->Font = 0; - infoPtr->LinkFont = 0; - infoPtr->Items = NULL; - infoPtr->HasFocus = FALSE; - infoPtr->MouseDownID = -1; - infoPtr->TextColor = GetSysColor(COLOR_WINDOWTEXT); - infoPtr->LinkColor = GetSysColor(COLOR_HIGHLIGHT); - infoPtr->VisitedColor = GetSysColor(COLOR_HIGHLIGHT); - TRACE("SysLink Ctrl creation, hwnd=%p\n", hwnd); - lParam = (LPARAM)(((LPCREATESTRUCTW)lParam)->lpszName); - SYSLINK_SetText(infoPtr, (LPWSTR)lParam); - return 0; - - case WM_DESTROY: - TRACE("SysLink Ctrl destruction, hwnd=%p\n", hwnd); - SYSLINK_ClearDoc(infoPtr); - SYSLINK_Free (infoPtr); - SetWindowLongPtrW(hwnd, 0, 0); - return 0; - - default: - if ((message >= WM_USER) && (message < WM_APP)) - ERR("unknown msg %04x wp=%04x lp=%08lx\n", message, wParam, lParam ); - return DefWindowProcW(hwnd, message, wParam, lParam); - } -} - - -/*********************************************************************** - * SYSLINK_Register [Internal] - * - * Registers the SysLink window class. - */ -VOID SYSLINK_Register (void) -{ - WNDCLASSW wndClass; - - ZeroMemory (&wndClass, sizeof(wndClass)); - wndClass.style = CS_GLOBALCLASS | CS_VREDRAW | CS_HREDRAW; - wndClass.lpfnWndProc = SysLinkWindowProc; - wndClass.cbClsExtra = 0; - wndClass.cbWndExtra = sizeof (SYSLINK_INFO *); - wndClass.hCursor = LoadCursorW (0, (LPWSTR)IDC_ARROW); - wndClass.lpszClassName = WC_LINK; - - RegisterClassW (&wndClass); -} - - -/*********************************************************************** - * SYSLINK_Unregister [Internal] - * - * Unregisters the SysLink window class. - */ -VOID SYSLINK_Unregister (void) -{ - UnregisterClassW (WC_LINK, NULL); -} diff --git a/reactos/lib/comctl32/tab.c b/reactos/lib/comctl32/tab.c deleted file mode 100644 index efdf955db6f..00000000000 --- a/reactos/lib/comctl32/tab.c +++ /dev/null @@ -1,3288 +0,0 @@ -/* - * Tab control - * - * Copyright 1998 Anders Carlsson - * Copyright 1999 Alex Priem - * Copyright 1999 Francis Beaudet - * Copyright 2003 Vitaliy Margolen - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2.1 of the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - * - * TODO: - * Unicode support (under construction) - * - * Styles: - * TCIF_RTLREADING - * - * Messages: - * TCM_REMOVEIMAGE - * TCM_DESELECTALL - * TCM_GETEXTENDEDSTYLE - * TCM_SETEXTENDEDSTYLE - * - */ - -#include -#include - -#include "windef.h" -#include "winbase.h" -#include "wingdi.h" -#include "winuser.h" -#include "winnls.h" -#include "commctrl.h" -#include "comctl32.h" -#include "wine/debug.h" -#include - -WINE_DEFAULT_DEBUG_CHANNEL(tab); - -typedef struct -{ - UINT mask; - DWORD dwState; - LPWSTR pszText; - INT iImage; - RECT rect; /* bounding rectangle of the item relative to the - * leftmost item (the leftmost item, 0, would have a - * "left" member of 0 in this rectangle) - * - * additionally the top member hold the row number - * and bottom is unused and should be 0 */ - BYTE extra[1]; /* Space for caller supplied info, variable size */ -} TAB_ITEM; - -/* The size of a tab item depends on how much extra data is requested */ -#define TAB_ITEM_SIZE(infoPtr) (sizeof(TAB_ITEM) - sizeof(BYTE) + infoPtr->cbInfo) - -typedef struct -{ - HWND hwndNotify; /* notification window (parent) */ - UINT uNumItem; /* number of tab items */ - UINT uNumRows; /* number of tab rows */ - INT tabHeight; /* height of the tab row */ - INT tabWidth; /* width of tabs */ - INT tabMinWidth; /* minimum width of items */ - USHORT uHItemPadding; /* amount of horizontal padding, in pixels */ - USHORT uVItemPadding; /* amount of vertical padding, in pixels */ - USHORT uHItemPadding_s; /* Set amount of horizontal padding, in pixels */ - USHORT uVItemPadding_s; /* Set amount of vertical padding, in pixels */ - HFONT hFont; /* handle to the current font */ - HCURSOR hcurArrow; /* handle to the current cursor */ - HIMAGELIST himl; /* handle to a image list (may be 0) */ - HWND hwndToolTip; /* handle to tab's tooltip */ - INT leftmostVisible; /* Used for scrolling, this member contains - * the index of the first visible item */ - INT iSelected; /* the currently selected item */ - INT iHotTracked; /* the highlighted item under the mouse */ - INT uFocus; /* item which has the focus */ - TAB_ITEM* items; /* pointer to an array of TAB_ITEM's */ - BOOL DoRedraw; /* flag for redrawing when tab contents is changed*/ - BOOL needsScrolling; /* TRUE if the size of the tabs is greater than - * the size of the control */ - BOOL fHeightSet; /* was the height of the tabs explicitly set? */ - BOOL bUnicode; /* Unicode control? */ - HWND hwndUpDown; /* Updown control used for scrolling */ - INT cbInfo; /* Number of bytes of caller supplied info per tab */ -} TAB_INFO; - -/****************************************************************************** - * Positioning constants - */ -#define SELECTED_TAB_OFFSET 2 -#define ROUND_CORNER_SIZE 2 -#define DISPLAY_AREA_PADDINGX 2 -#define DISPLAY_AREA_PADDINGY 2 -#define CONTROL_BORDER_SIZEX 2 -#define CONTROL_BORDER_SIZEY 2 -#define BUTTON_SPACINGX 3 -#define BUTTON_SPACINGY 3 -#define FLAT_BTN_SPACINGX 8 -#define DEFAULT_TAB_WIDTH 96 - -#define TAB_GetInfoPtr(hwnd) ((TAB_INFO *)GetWindowLongPtrW(hwnd,0)) -/* Since items are variable sized, cannot directly access them */ -#define TAB_GetItem(info,i) \ - ((TAB_ITEM*)((LPBYTE)info->items + (i) * TAB_ITEM_SIZE(info))) - -/****************************************************************************** - * Hot-tracking timer constants - */ -#define TAB_HOTTRACK_TIMER 1 -#define TAB_HOTTRACK_TIMER_INTERVAL 100 /* milliseconds */ - -/****************************************************************************** - * Prototypes - */ -static void TAB_Refresh (HWND hwnd, HDC hdc); -static void TAB_InvalidateTabArea(HWND hwnd, TAB_INFO* infoPtr); -static void TAB_EnsureSelectionVisible(HWND hwnd, TAB_INFO* infoPtr); -static void TAB_DrawItem(HWND hwnd, HDC hdc, INT iItem); -static void TAB_DrawItemInterior(HWND hwnd, HDC hdc, INT iItem, RECT* drawRect); - -static BOOL -TAB_SendSimpleNotify (HWND hwnd, UINT code) -{ - TAB_INFO *infoPtr = TAB_GetInfoPtr(hwnd); - NMHDR nmhdr; - - nmhdr.hwndFrom = hwnd; - nmhdr.idFrom = GetWindowLongPtrW(hwnd, GWLP_ID); - nmhdr.code = code; - - return (BOOL) SendMessageW (infoPtr->hwndNotify, WM_NOTIFY, - (WPARAM) nmhdr.idFrom, (LPARAM) &nmhdr); -} - -static VOID -TAB_RelayEvent (HWND hwndTip, HWND hwndMsg, UINT uMsg, - WPARAM wParam, LPARAM lParam) -{ - MSG msg; - - msg.hwnd = hwndMsg; - msg.message = uMsg; - msg.wParam = wParam; - msg.lParam = lParam; - msg.time = GetMessageTime (); - msg.pt.x = LOWORD(GetMessagePos ()); - msg.pt.y = HIWORD(GetMessagePos ()); - - SendMessageW (hwndTip, TTM_RELAYEVENT, 0, (LPARAM)&msg); -} - -static void -TAB_DumpItemExternalA(TCITEMA *pti, UINT iItem) -{ - if (TRACE_ON(tab)) { - TRACE("external tab %d, mask=0x%08x, dwState=0x%08x, dwStateMask=0x%08x, cchTextMax=0x%08x\n", - iItem, pti->mask, pti->dwState, pti->dwStateMask, pti->cchTextMax); - TRACE("external tab %d, iImage=%d, lParam=0x%08lx, pszTextA=%s\n", - iItem, pti->iImage, pti->lParam, debugstr_a(pti->pszText)); - } -} - - -static void -TAB_DumpItemExternalW(TCITEMW *pti, UINT iItem) -{ - if (TRACE_ON(tab)) { - TRACE("external tab %d, mask=0x%08x, dwState=0x%08lx, dwStateMask=0x%08lx, cchTextMax=0x%08x\n", - iItem, pti->mask, pti->dwState, pti->dwStateMask, pti->cchTextMax); - TRACE("external tab %d, iImage=%d, lParam=0x%08lx, pszTextW=%s\n", - iItem, pti->iImage, pti->lParam, debugstr_w(pti->pszText)); - } -} - -static void -TAB_DumpItemInternal(TAB_INFO *infoPtr, UINT iItem) -{ - if (TRACE_ON(tab)) { - TAB_ITEM *ti; - - ti = TAB_GetItem(infoPtr, iItem); - TRACE("tab %d, mask=0x%08x, dwState=0x%08lx, pszText=%s, iImage=%d\n", - iItem, ti->mask, ti->dwState, debugstr_w(ti->pszText), - ti->iImage); - TRACE("tab %d, rect.left=%ld, rect.top(row)=%ld\n", - iItem, ti->rect.left, ti->rect.top); - } -} - -static LRESULT -TAB_GetCurSel (HWND hwnd) -{ - TAB_INFO *infoPtr = TAB_GetInfoPtr(hwnd); - - return infoPtr->iSelected; -} - -static LRESULT -TAB_GetCurFocus (HWND hwnd) -{ - TAB_INFO *infoPtr = TAB_GetInfoPtr(hwnd); - - return infoPtr->uFocus; -} - -static LRESULT -TAB_GetToolTips (HWND hwnd, WPARAM wParam, LPARAM lParam) -{ - TAB_INFO *infoPtr = TAB_GetInfoPtr(hwnd); - - if (infoPtr == NULL) return 0; - return (LRESULT)infoPtr->hwndToolTip; -} - -static LRESULT -TAB_SetCurSel (HWND hwnd,WPARAM wParam) -{ - TAB_INFO *infoPtr = TAB_GetInfoPtr(hwnd); - INT iItem = (INT)wParam; - INT prevItem; - - prevItem = -1; - if ((iItem >= 0) && (iItem < infoPtr->uNumItem)) { - prevItem=infoPtr->iSelected; - infoPtr->iSelected=iItem; - TAB_EnsureSelectionVisible(hwnd, infoPtr); - TAB_InvalidateTabArea(hwnd, infoPtr); - } - return prevItem; -} - -static LRESULT -TAB_SetCurFocus (HWND hwnd,WPARAM wParam) -{ - TAB_INFO *infoPtr = TAB_GetInfoPtr(hwnd); - INT iItem=(INT) wParam; - - if ((iItem < 0) || (iItem >= infoPtr->uNumItem)) return 0; - - if (GetWindowLongA(hwnd, GWL_STYLE) & TCS_BUTTONS) { - FIXME("Should set input focus\n"); - } else { - int oldFocus = infoPtr->uFocus; - if (infoPtr->iSelected != iItem || infoPtr->uFocus == -1 ) { - infoPtr->uFocus = iItem; - if (oldFocus != -1) { - if (TAB_SendSimpleNotify(hwnd, TCN_SELCHANGING)!=TRUE) { - infoPtr->iSelected = iItem; - TAB_SendSimpleNotify(hwnd, TCN_SELCHANGE); - } - else - infoPtr->iSelected = iItem; - TAB_EnsureSelectionVisible(hwnd, infoPtr); - TAB_InvalidateTabArea(hwnd, infoPtr); - } - } - } - return 0; -} - -static LRESULT -TAB_SetToolTips (HWND hwnd, WPARAM wParam, LPARAM lParam) -{ - TAB_INFO *infoPtr = TAB_GetInfoPtr(hwnd); - - if (infoPtr == NULL) return 0; - infoPtr->hwndToolTip = (HWND)wParam; - return 0; -} - -static LRESULT -TAB_SetPadding (HWND hwnd, WPARAM wParam, LPARAM lParam) -{ - TAB_INFO *infoPtr = TAB_GetInfoPtr(hwnd); - - if (infoPtr == NULL) return 0; - infoPtr->uHItemPadding_s=LOWORD(lParam); - infoPtr->uVItemPadding_s=HIWORD(lParam); - return 0; -} - -/****************************************************************************** - * TAB_InternalGetItemRect - * - * This method will calculate the rectangle representing a given tab item in - * client coordinates. This method takes scrolling into account. - * - * This method returns TRUE if the item is visible in the window and FALSE - * if it is completely outside the client area. - */ -static BOOL TAB_InternalGetItemRect( - HWND hwnd, - TAB_INFO* infoPtr, - INT itemIndex, - RECT* itemRect, - RECT* selectedRect) -{ - RECT tmpItemRect,clientRect; - LONG lStyle = GetWindowLongA(hwnd, GWL_STYLE); - - /* Perform a sanity check and a trivial visibility check. */ - if ( (infoPtr->uNumItem <= 0) || - (itemIndex >= infoPtr->uNumItem) || - (!((lStyle & TCS_MULTILINE) || (lStyle & TCS_VERTICAL)) && (itemIndex < infoPtr->leftmostVisible)) ) - return FALSE; - - /* - * Avoid special cases in this procedure by assigning the "out" - * parameters if the caller didn't supply them - */ - if (itemRect == NULL) - itemRect = &tmpItemRect; - - /* Retrieve the unmodified item rect. */ - *itemRect = TAB_GetItem(infoPtr,itemIndex)->rect; - - /* calculate the times bottom and top based on the row */ - GetClientRect(hwnd, &clientRect); - - if ((lStyle & TCS_BOTTOM) && (lStyle & TCS_VERTICAL)) - { - itemRect->right = clientRect.right - SELECTED_TAB_OFFSET - itemRect->left * infoPtr->tabHeight - - ((lStyle & TCS_BUTTONS) ? itemRect->left * BUTTON_SPACINGX : 0); - itemRect->left = itemRect->right - infoPtr->tabHeight; - } - else if (lStyle & TCS_VERTICAL) - { - itemRect->left = clientRect.left + SELECTED_TAB_OFFSET + itemRect->left * infoPtr->tabHeight + - ((lStyle & TCS_BUTTONS) ? itemRect->left * BUTTON_SPACINGX : 0); - itemRect->right = itemRect->left + infoPtr->tabHeight; - } - else if (lStyle & TCS_BOTTOM) - { - itemRect->bottom = clientRect.bottom - itemRect->top * infoPtr->tabHeight - - ((lStyle & TCS_BUTTONS) ? itemRect->top * BUTTON_SPACINGY : SELECTED_TAB_OFFSET); - itemRect->top = itemRect->bottom - infoPtr->tabHeight; - } - else /* not TCS_BOTTOM and not TCS_VERTICAL */ - { - itemRect->top = clientRect.top + itemRect->top * infoPtr->tabHeight + - ((lStyle & TCS_BUTTONS) ? itemRect->top * BUTTON_SPACINGY : SELECTED_TAB_OFFSET); - itemRect->bottom = itemRect->top + infoPtr->tabHeight; - } - - /* - * "scroll" it to make sure the item at the very left of the - * tab control is the leftmost visible tab. - */ - if(lStyle & TCS_VERTICAL) - { - OffsetRect(itemRect, - 0, - -TAB_GetItem(infoPtr, infoPtr->leftmostVisible)->rect.top); - - /* - * Move the rectangle so the first item is slightly offset from - * the bottom of the tab control. - */ - OffsetRect(itemRect, - 0, - SELECTED_TAB_OFFSET); - - } else - { - OffsetRect(itemRect, - -TAB_GetItem(infoPtr, infoPtr->leftmostVisible)->rect.left, - 0); - - /* - * Move the rectangle so the first item is slightly offset from - * the left of the tab control. - */ - OffsetRect(itemRect, - SELECTED_TAB_OFFSET, - 0); - } - TRACE("item %d tab h=%d, rect=(%ld,%ld)-(%ld,%ld)\n", - itemIndex, infoPtr->tabHeight, - itemRect->left, itemRect->top, itemRect->right, itemRect->bottom); - - /* Now, calculate the position of the item as if it were selected. */ - if (selectedRect!=NULL) - { - CopyRect(selectedRect, itemRect); - - /* The rectangle of a selected item is a bit wider. */ - if(lStyle & TCS_VERTICAL) - InflateRect(selectedRect, 0, SELECTED_TAB_OFFSET); - else - InflateRect(selectedRect, SELECTED_TAB_OFFSET, 0); - - /* If it also a bit higher. */ - if ((lStyle & TCS_BOTTOM) && (lStyle & TCS_VERTICAL)) - { - selectedRect->left -= 2; /* the border is thicker on the right */ - selectedRect->right += SELECTED_TAB_OFFSET; - } - else if (lStyle & TCS_VERTICAL) - { - selectedRect->left -= SELECTED_TAB_OFFSET; - selectedRect->right += 1; - } - else if (lStyle & TCS_BOTTOM) - { - selectedRect->bottom += SELECTED_TAB_OFFSET; - } - else /* not TCS_BOTTOM and not TCS_VERTICAL */ - { - selectedRect->top -= SELECTED_TAB_OFFSET; - selectedRect->bottom -= 1; - } - } - - return TRUE; -} - -static BOOL TAB_GetItemRect(HWND hwnd, WPARAM wParam, LPARAM lParam) -{ - return TAB_InternalGetItemRect(hwnd, TAB_GetInfoPtr(hwnd), (INT)wParam, - (LPRECT)lParam, (LPRECT)NULL); -} - -/****************************************************************************** - * TAB_KeyUp - * - * This method is called to handle keyboard input - */ -static LRESULT TAB_KeyUp( - HWND hwnd, - WPARAM keyCode) -{ - TAB_INFO* infoPtr = TAB_GetInfoPtr(hwnd); - int newItem = -1; - - switch (keyCode) - { - case VK_LEFT: - newItem = infoPtr->uFocus - 1; - break; - case VK_RIGHT: - newItem = infoPtr->uFocus + 1; - break; - } - - /* - * If we changed to a valid item, change the selection - */ - if ((newItem >= 0) && - (newItem < infoPtr->uNumItem) && - (infoPtr->uFocus != newItem)) - { - if (!TAB_SendSimpleNotify(hwnd, TCN_SELCHANGING)) - { - infoPtr->iSelected = newItem; - infoPtr->uFocus = newItem; - TAB_SendSimpleNotify(hwnd, TCN_SELCHANGE); - - TAB_EnsureSelectionVisible(hwnd, infoPtr); - TAB_InvalidateTabArea(hwnd, infoPtr); - } - } - - return 0; -} - -/****************************************************************************** - * TAB_FocusChanging - * - * This method is called whenever the focus goes in or out of this control - * it is used to update the visual state of the control. - */ -static LRESULT TAB_FocusChanging( - HWND hwnd, - UINT uMsg, - WPARAM wParam, - LPARAM lParam) -{ - TAB_INFO *infoPtr = TAB_GetInfoPtr(hwnd); - RECT selectedRect; - BOOL isVisible; - - /* - * Get the rectangle for the item. - */ - isVisible = TAB_InternalGetItemRect(hwnd, - infoPtr, - infoPtr->uFocus, - NULL, - &selectedRect); - - /* - * If the rectangle is not completely invisible, invalidate that - * portion of the window. - */ - if (isVisible) - { - TRACE("invalidate (%ld,%ld)-(%ld,%ld)\n", - selectedRect.left,selectedRect.top, - selectedRect.right,selectedRect.bottom); - InvalidateRect(hwnd, &selectedRect, TRUE); - } - - /* - * Don't otherwise disturb normal behavior. - */ - return DefWindowProcW (hwnd, uMsg, wParam, lParam); -} - -static INT TAB_InternalHitTest ( - HWND hwnd, - TAB_INFO* infoPtr, - POINT pt, - UINT* flags) - -{ - RECT rect; - INT iCount; - - for (iCount = 0; iCount < infoPtr->uNumItem; iCount++) - { - TAB_InternalGetItemRect(hwnd, infoPtr, iCount, &rect, NULL); - - if (PtInRect(&rect, pt)) - { - *flags = TCHT_ONITEM; - return iCount; - } - } - - *flags = TCHT_NOWHERE; - return -1; -} - -static LRESULT -TAB_HitTest (HWND hwnd, WPARAM wParam, LPARAM lParam) -{ - TAB_INFO *infoPtr = TAB_GetInfoPtr(hwnd); - LPTCHITTESTINFO lptest = (LPTCHITTESTINFO) lParam; - - return TAB_InternalHitTest (hwnd, infoPtr, lptest->pt, &lptest->flags); -} - -/****************************************************************************** - * TAB_NCHitTest - * - * Napster v2b5 has a tab control for its main navigation which has a client - * area that covers the whole area of the dialog pages. - * That's why it receives all msgs for that area and the underlying dialog ctrls - * are dead. - * So I decided that we should handle WM_NCHITTEST here and return - * HTTRANSPARENT if we don't hit the tab control buttons. - * FIXME: WM_NCHITTEST handling correct ? Fix it if you know that Windows - * doesn't do it that way. Maybe depends on tab control styles ? - */ -static LRESULT -TAB_NCHitTest (HWND hwnd, LPARAM lParam) -{ - TAB_INFO *infoPtr = TAB_GetInfoPtr(hwnd); - POINT pt; - UINT dummyflag; - - pt.x = LOWORD(lParam); - pt.y = HIWORD(lParam); - ScreenToClient(hwnd, &pt); - - if (TAB_InternalHitTest(hwnd, infoPtr, pt, &dummyflag) == -1) - return HTTRANSPARENT; - else - return HTCLIENT; -} - -static LRESULT -TAB_LButtonDown (HWND hwnd, WPARAM wParam, LPARAM lParam) -{ - TAB_INFO *infoPtr = TAB_GetInfoPtr(hwnd); - POINT pt; - INT newItem, dummy; - - if (infoPtr->hwndToolTip) - TAB_RelayEvent (infoPtr->hwndToolTip, hwnd, - WM_LBUTTONDOWN, wParam, lParam); - - if (GetWindowLongA(hwnd, GWL_STYLE) & TCS_FOCUSONBUTTONDOWN ) { - SetFocus (hwnd); - } - - if (infoPtr->hwndToolTip) - TAB_RelayEvent (infoPtr->hwndToolTip, hwnd, - WM_LBUTTONDOWN, wParam, lParam); - - pt.x = (INT)LOWORD(lParam); - pt.y = (INT)HIWORD(lParam); - - newItem = TAB_InternalHitTest (hwnd, infoPtr, pt, &dummy); - - TRACE("On Tab, item %d\n", newItem); - - if ((newItem != -1) && (infoPtr->iSelected != newItem)) - { - if (TAB_SendSimpleNotify(hwnd, TCN_SELCHANGING) != TRUE) - { - infoPtr->iSelected = newItem; - infoPtr->uFocus = newItem; - TAB_SendSimpleNotify(hwnd, TCN_SELCHANGE); - - TAB_EnsureSelectionVisible(hwnd, infoPtr); - - TAB_InvalidateTabArea(hwnd, infoPtr); - } - } - return 0; -} - -static LRESULT -TAB_LButtonUp (HWND hwnd, WPARAM wParam, LPARAM lParam) -{ - TAB_SendSimpleNotify(hwnd, NM_CLICK); - - return 0; -} - -static LRESULT -TAB_RButtonDown (HWND hwnd, WPARAM wParam, LPARAM lParam) -{ - TAB_SendSimpleNotify(hwnd, NM_RCLICK); - return 0; -} - -/****************************************************************************** - * TAB_DrawLoneItemInterior - * - * This calls TAB_DrawItemInterior. However, TAB_DrawItemInterior is normally - * called by TAB_DrawItem which is normally called by TAB_Refresh which sets - * up the device context and font. This routine does the same setup but - * only calls TAB_DrawItemInterior for the single specified item. - */ -static void -TAB_DrawLoneItemInterior(HWND hwnd, TAB_INFO* infoPtr, int iItem) -{ - HDC hdc = GetDC(hwnd); - RECT r, rC; - - /* Clip UpDown control to not draw over it */ - if (infoPtr->needsScrolling) - { - GetWindowRect(hwnd, &rC); - GetWindowRect(infoPtr->hwndUpDown, &r); - ExcludeClipRect(hdc, r.left - rC.left, r.top - rC.top, r.right - rC.left, r.bottom - rC.top); - } - TAB_DrawItemInterior(hwnd, hdc, iItem, NULL); - ReleaseDC(hwnd, hdc); -} - -/****************************************************************************** - * TAB_HotTrackTimerProc - * - * When a mouse-move event causes a tab to be highlighted (hot-tracking), a - * timer is setup so we can check if the mouse is moved out of our window. - * (We don't get an event when the mouse leaves, the mouse-move events just - * stop being delivered to our window and just start being delivered to - * another window.) This function is called when the timer triggers so - * we can check if the mouse has left our window. If so, we un-highlight - * the hot-tracked tab. - */ -static VOID CALLBACK -TAB_HotTrackTimerProc - ( - HWND hwnd, /* handle of window for timer messages */ - UINT uMsg, /* WM_TIMER message */ - UINT idEvent, /* timer identifier */ - DWORD dwTime /* current system time */ - ) -{ - TAB_INFO* infoPtr = TAB_GetInfoPtr(hwnd); - - if (infoPtr != NULL && infoPtr->iHotTracked >= 0) - { - POINT pt; - - /* - ** If we can't get the cursor position, or if the cursor is outside our - ** window, we un-highlight the hot-tracked tab. Note that the cursor is - ** "outside" even if it is within our bounding rect if another window - ** overlaps. Note also that the case where the cursor stayed within our - ** window but has moved off the hot-tracked tab will be handled by the - ** WM_MOUSEMOVE event. - */ - if (!GetCursorPos(&pt) || WindowFromPoint(pt) != hwnd) - { - /* Redraw iHotTracked to look normal */ - INT iRedraw = infoPtr->iHotTracked; - infoPtr->iHotTracked = -1; - TAB_DrawLoneItemInterior(hwnd, infoPtr, iRedraw); - - /* Kill this timer */ - KillTimer(hwnd, TAB_HOTTRACK_TIMER); - } - } -} - -/****************************************************************************** - * TAB_RecalcHotTrack - * - * If a tab control has the TCS_HOTTRACK style, then the tab under the mouse - * should be highlighted. This function determines which tab in a tab control, - * if any, is under the mouse and records that information. The caller may - * supply output parameters to receive the item number of the tab item which - * was highlighted but isn't any longer and of the tab item which is now - * highlighted but wasn't previously. The caller can use this information to - * selectively redraw those tab items. - * - * If the caller has a mouse position, it can supply it through the pos - * parameter. For example, TAB_MouseMove does this. Otherwise, the caller - * supplies NULL and this function determines the current mouse position - * itself. - */ -static void -TAB_RecalcHotTrack - ( - HWND hwnd, - const LPARAM* pos, - int* out_redrawLeave, - int* out_redrawEnter - ) -{ - TAB_INFO* infoPtr = TAB_GetInfoPtr(hwnd); - - int item = -1; - - - if (out_redrawLeave != NULL) - *out_redrawLeave = -1; - if (out_redrawEnter != NULL) - *out_redrawEnter = -1; - - if (GetWindowLongA(hwnd, GWL_STYLE) & TCS_HOTTRACK) - { - POINT pt; - UINT flags; - - if (pos == NULL) - { - GetCursorPos(&pt); - ScreenToClient(hwnd, &pt); - } - else - { - pt.x = LOWORD(*pos); - pt.y = HIWORD(*pos); - } - - item = TAB_InternalHitTest(hwnd, infoPtr, pt, &flags); - } - - if (item != infoPtr->iHotTracked) - { - if (infoPtr->iHotTracked >= 0) - { - /* Mark currently hot-tracked to be redrawn to look normal */ - if (out_redrawLeave != NULL) - *out_redrawLeave = infoPtr->iHotTracked; - - if (item < 0) - { - /* Kill timer which forces recheck of mouse pos */ - KillTimer(hwnd, TAB_HOTTRACK_TIMER); - } - } - else - { - /* Start timer so we recheck mouse pos */ - UINT timerID = SetTimer - ( - hwnd, - TAB_HOTTRACK_TIMER, - TAB_HOTTRACK_TIMER_INTERVAL, - TAB_HotTrackTimerProc - ); - - if (timerID == 0) - return; /* Hot tracking not available */ - } - - infoPtr->iHotTracked = item; - - if (item >= 0) - { - /* Mark new hot-tracked to be redrawn to look highlighted */ - if (out_redrawEnter != NULL) - *out_redrawEnter = item; - } - } -} - -/****************************************************************************** - * TAB_MouseMove - * - * Handles the mouse-move event. Updates tooltips. Updates hot-tracking. - */ -static LRESULT -TAB_MouseMove (HWND hwnd, WPARAM wParam, LPARAM lParam) -{ - int redrawLeave; - int redrawEnter; - - TAB_INFO *infoPtr = TAB_GetInfoPtr(hwnd); - - if (infoPtr->hwndToolTip) - TAB_RelayEvent (infoPtr->hwndToolTip, hwnd, - WM_LBUTTONDOWN, wParam, lParam); - - /* Determine which tab to highlight. Redraw tabs which change highlight - ** status. */ - TAB_RecalcHotTrack(hwnd, &lParam, &redrawLeave, &redrawEnter); - - if (redrawLeave != -1) - TAB_DrawLoneItemInterior(hwnd, infoPtr, redrawLeave); - if (redrawEnter != -1) - TAB_DrawLoneItemInterior(hwnd, infoPtr, redrawEnter); - - return 0; -} - -/****************************************************************************** - * TAB_AdjustRect - * - * Calculates the tab control's display area given the window rectangle or - * the window rectangle given the requested display rectangle. - */ -static LRESULT TAB_AdjustRect( - HWND hwnd, - WPARAM fLarger, - LPRECT prc) -{ - TAB_INFO *infoPtr = TAB_GetInfoPtr(hwnd); - DWORD lStyle = GetWindowLongA(hwnd, GWL_STYLE); - LONG *iRightBottom, *iLeftTop; - - TRACE ("hwnd=%p fLarger=%d (%ld,%ld)-(%ld,%ld)\n", hwnd, fLarger, prc->left, prc->top, prc->right, prc->bottom); - - if(lStyle & TCS_VERTICAL) - { - iRightBottom = &(prc->right); - iLeftTop = &(prc->left); - } - else - { - iRightBottom = &(prc->bottom); - iLeftTop = &(prc->top); - } - - if (fLarger) /* Go from display rectangle */ - { - /* Add the height of the tabs. */ - if (lStyle & TCS_BOTTOM) - *iRightBottom += infoPtr->tabHeight * infoPtr->uNumRows; - else - *iLeftTop -= infoPtr->tabHeight * infoPtr->uNumRows + - ((lStyle & TCS_BUTTONS)? 3 * (infoPtr->uNumRows - 1) : 0); - - /* Inflate the rectangle for the padding */ - InflateRect(prc, DISPLAY_AREA_PADDINGX, DISPLAY_AREA_PADDINGY); - - /* Inflate for the border */ - InflateRect(prc, CONTROL_BORDER_SIZEX, CONTROL_BORDER_SIZEY); - } - else /* Go from window rectangle. */ - { - /* Deflate the rectangle for the border */ - InflateRect(prc, -CONTROL_BORDER_SIZEX, -CONTROL_BORDER_SIZEY); - - /* Deflate the rectangle for the padding */ - InflateRect(prc, -DISPLAY_AREA_PADDINGX, -DISPLAY_AREA_PADDINGY); - - /* Remove the height of the tabs. */ - if (lStyle & TCS_BOTTOM) - *iRightBottom -= infoPtr->tabHeight * infoPtr->uNumRows; - else - *iLeftTop += (infoPtr->tabHeight) * infoPtr->uNumRows + - ((lStyle & TCS_BUTTONS)? 3 * (infoPtr->uNumRows - 1) : 0); - } - - return 0; -} - -/****************************************************************************** - * TAB_OnHScroll - * - * This method will handle the notification from the scroll control and - * perform the scrolling operation on the tab control. - */ -static LRESULT TAB_OnHScroll( - HWND hwnd, - int nScrollCode, - int nPos, - HWND hwndScroll) -{ - TAB_INFO *infoPtr = TAB_GetInfoPtr(hwnd); - - if(nScrollCode == SB_THUMBPOSITION && nPos != infoPtr->leftmostVisible) - { - if(nPos < infoPtr->leftmostVisible) - infoPtr->leftmostVisible--; - else - infoPtr->leftmostVisible++; - - TAB_RecalcHotTrack(hwnd, NULL, NULL, NULL); - TAB_InvalidateTabArea(hwnd, infoPtr); - SendMessageW(infoPtr->hwndUpDown, UDM_SETPOS, 0, - MAKELONG(infoPtr->leftmostVisible, 0)); - } - - return 0; -} - -/****************************************************************************** - * TAB_SetupScrolling - * - * This method will check the current scrolling state and make sure the - * scrolling control is displayed (or not). - */ -static void TAB_SetupScrolling( - HWND hwnd, - TAB_INFO* infoPtr, - const RECT* clientRect) -{ - INT maxRange = 0; - DWORD lStyle = GetWindowLongA(hwnd, GWL_STYLE); - - if (infoPtr->needsScrolling) - { - RECT controlPos; - INT vsize, tabwidth; - - /* - * Calculate the position of the scroll control. - */ - if(lStyle & TCS_VERTICAL) - { - controlPos.right = clientRect->right; - controlPos.left = controlPos.right - 2 * GetSystemMetrics(SM_CXHSCROLL); - - if (lStyle & TCS_BOTTOM) - { - controlPos.top = clientRect->bottom - infoPtr->tabHeight; - controlPos.bottom = controlPos.top + GetSystemMetrics(SM_CYHSCROLL); - } - else - { - controlPos.bottom = clientRect->top + infoPtr->tabHeight; - controlPos.top = controlPos.bottom - GetSystemMetrics(SM_CYHSCROLL); - } - } - else - { - controlPos.right = clientRect->right; - controlPos.left = controlPos.right - 2 * GetSystemMetrics(SM_CXHSCROLL); - - if (lStyle & TCS_BOTTOM) - { - controlPos.top = clientRect->bottom - infoPtr->tabHeight; - controlPos.bottom = controlPos.top + GetSystemMetrics(SM_CYHSCROLL); - } - else - { - controlPos.bottom = clientRect->top + infoPtr->tabHeight; - controlPos.top = controlPos.bottom - GetSystemMetrics(SM_CYHSCROLL); - } - } - - /* - * If we don't have a scroll control yet, we want to create one. - * If we have one, we want to make sure it's positioned properly. - */ - if (infoPtr->hwndUpDown==0) - { - infoPtr->hwndUpDown = CreateWindowA("msctls_updown32", - "", - WS_VISIBLE | WS_CHILD | UDS_HORZ, - controlPos.left, controlPos.top, - controlPos.right - controlPos.left, - controlPos.bottom - controlPos.top, - hwnd, - NULL, - NULL, - NULL); - } - else - { - SetWindowPos(infoPtr->hwndUpDown, - NULL, - controlPos.left, controlPos.top, - controlPos.right - controlPos.left, - controlPos.bottom - controlPos.top, - SWP_SHOWWINDOW | SWP_NOZORDER); - } - - /* Now calculate upper limit of the updown control range. - * We do this by calculating how many tabs will be offscreen when the - * last tab is visible. - */ - if(infoPtr->uNumItem) - { - vsize = clientRect->right - (controlPos.right - controlPos.left + 1); - maxRange = infoPtr->uNumItem; - tabwidth = TAB_GetItem(infoPtr, infoPtr->uNumItem - 1)->rect.right; - - for(; maxRange > 0; maxRange--) - { - if(tabwidth - TAB_GetItem(infoPtr,maxRange - 1)->rect.left > vsize) - break; - } - - if(maxRange == infoPtr->uNumItem) - maxRange--; - } - } - else - { - /* If we once had a scroll control... hide it */ - if (infoPtr->hwndUpDown!=0) - ShowWindow(infoPtr->hwndUpDown, SW_HIDE); - } - if (infoPtr->hwndUpDown) - SendMessageW(infoPtr->hwndUpDown, UDM_SETRANGE32, 0, maxRange); -} - -/****************************************************************************** - * TAB_SetItemBounds - * - * This method will calculate the position rectangles of all the items in the - * control. The rectangle calculated starts at 0 for the first item in the - * list and ignores scrolling and selection. - * It also uses the current font to determine the height of the tab row and - * it checks if all the tabs fit in the client area of the window. If they - * don't, a scrolling control is added. - */ -static void TAB_SetItemBounds (HWND hwnd) -{ - TAB_INFO* infoPtr = TAB_GetInfoPtr(hwnd); - LONG lStyle = GetWindowLongA(hwnd, GWL_STYLE); - TEXTMETRICA fontMetrics; - UINT curItem; - INT curItemLeftPos; - INT curItemRowCount; - HFONT hFont, hOldFont; - HDC hdc; - RECT clientRect; - SIZE size; - INT iTemp; - RECT* rcItem; - INT iIndex; - INT icon_width = 0; - - /* - * We need to get text information so we need a DC and we need to select - * a font. - */ - hdc = GetDC(hwnd); - - hFont = infoPtr->hFont ? infoPtr->hFont : GetStockObject (SYSTEM_FONT); - hOldFont = SelectObject (hdc, hFont); - - /* - * We will base the rectangle calculations on the client rectangle - * of the control. - */ - GetClientRect(hwnd, &clientRect); - - /* if TCS_VERTICAL then swap the height and width so this code places the - tabs along the top of the rectangle and we can just rotate them after - rather than duplicate all of the below code */ - if(lStyle & TCS_VERTICAL) - { - iTemp = clientRect.bottom; - clientRect.bottom = clientRect.right; - clientRect.right = iTemp; - } - - /* Now use hPadding and vPadding */ - infoPtr->uHItemPadding = infoPtr->uHItemPadding_s; - infoPtr->uVItemPadding = infoPtr->uVItemPadding_s; - - /* The leftmost item will be "0" aligned */ - curItemLeftPos = 0; - curItemRowCount = infoPtr->uNumItem ? 1 : 0; - - if (!(infoPtr->fHeightSet)) - { - int item_height; - int icon_height = 0; - - /* Use the current font to determine the height of a tab. */ - GetTextMetricsA(hdc, &fontMetrics); - - /* Get the icon height */ - if (infoPtr->himl) - ImageList_GetIconSize(infoPtr->himl, 0, &icon_height); - - /* Take the highest between font or icon */ - if (fontMetrics.tmHeight > icon_height) - item_height = fontMetrics.tmHeight + 2; - else - item_height = icon_height; - - /* - * Make sure there is enough space for the letters + icon + growing the - * selected item + extra space for the selected item. - */ - infoPtr->tabHeight = item_height + - ((lStyle & TCS_BUTTONS) ? 2 : 1) * - infoPtr->uVItemPadding; - - TRACE("tabH=%d, tmH=%ld, iconh=%d\n", - infoPtr->tabHeight, fontMetrics.tmHeight, icon_height); - } - - TRACE("client right=%ld\n", clientRect.right); - - /* Get the icon width */ - if (infoPtr->himl) - { - ImageList_GetIconSize(infoPtr->himl, &icon_width, 0); - - if (lStyle & TCS_FIXEDWIDTH) - icon_width += 4; - else - /* Add padding if icon is present */ - icon_width += infoPtr->uHItemPadding; - } - - for (curItem = 0; curItem < infoPtr->uNumItem; curItem++) - { - TAB_ITEM *curr = TAB_GetItem(infoPtr, curItem); - - /* Set the leftmost position of the tab. */ - curr->rect.left = curItemLeftPos; - - if ((lStyle & TCS_FIXEDWIDTH) || !curr->pszText) - { - curr->rect.right = curr->rect.left + - max(infoPtr->tabWidth, icon_width); - } - else - { - int num = 2; - - /* Calculate how wide the tab is depending on the text it contains */ - GetTextExtentPoint32W(hdc, curr->pszText, - lstrlenW(curr->pszText), &size); - - curr->rect.right = curr->rect.left + size.cx + icon_width + - num * infoPtr->uHItemPadding; - TRACE("for <%s>, l,r=%ld,%ld, num=%d\n", - debugstr_w(curr->pszText), curr->rect.left, curr->rect.right, num); - } - - /* - * Check if this is a multiline tab control and if so - * check to see if we should wrap the tabs - * - * Wrap all these tabs. We will arrange them evenly later. - * - */ - - if (((lStyle & TCS_MULTILINE) || (lStyle & TCS_VERTICAL)) && - (curr->rect.right > - (clientRect.right - CONTROL_BORDER_SIZEX - DISPLAY_AREA_PADDINGX))) - { - curr->rect.right -= curr->rect.left; - - curr->rect.left = 0; - curItemRowCount++; - TRACE("wrapping <%s>, l,r=%ld,%ld\n", debugstr_w(curr->pszText), - curr->rect.left, curr->rect.right); - } - - curr->rect.bottom = 0; - curr->rect.top = curItemRowCount - 1; - - TRACE("TextSize: %li\n", size.cx); - TRACE("Rect: T %li, L %li, B %li, R %li\n", curr->rect.top, - curr->rect.left, curr->rect.bottom, curr->rect.right); - - /* - * The leftmost position of the next item is the rightmost position - * of this one. - */ - if (lStyle & TCS_BUTTONS) - { - curItemLeftPos = curr->rect.right + BUTTON_SPACINGX; - if (lStyle & TCS_FLATBUTTONS) - curItemLeftPos += FLAT_BTN_SPACINGX; - } - else - curItemLeftPos = curr->rect.right; - } - - if (!((lStyle & TCS_MULTILINE) || (lStyle & TCS_VERTICAL))) - { - /* - * Check if we need a scrolling control. - */ - infoPtr->needsScrolling = (curItemLeftPos + (2 * SELECTED_TAB_OFFSET) > - clientRect.right); - - /* Don't need scrolling, then update infoPtr->leftmostVisible */ - if(!infoPtr->needsScrolling) - infoPtr->leftmostVisible = 0; - } - else - { - /* - * No scrolling in Multiline or Vertical styles. - */ - infoPtr->needsScrolling = FALSE; - infoPtr->leftmostVisible = 0; - } - TAB_SetupScrolling(hwnd, infoPtr, &clientRect); - - /* Set the number of rows */ - infoPtr->uNumRows = curItemRowCount; - - /* Arrange all tabs evenly if style says so */ - if (!(lStyle & TCS_RAGGEDRIGHT) && ((lStyle & TCS_MULTILINE) || (lStyle & TCS_VERTICAL)) && (infoPtr->uNumItem > 0)) - { - INT tabPerRow,remTab,iRow; - UINT iItm; - INT iCount=0; - - /* - * Ok windows tries to even out the rows. place the same - * number of tabs in each row. So lets give that a shot - */ - - tabPerRow = infoPtr->uNumItem / (infoPtr->uNumRows); - remTab = infoPtr->uNumItem % (infoPtr->uNumRows); - - for (iItm=0,iRow=0,iCount=0,curItemLeftPos=0; - iItmuNumItem; - iItm++,iCount++) - { - /* normalize the current rect */ - TAB_ITEM *curr = TAB_GetItem(infoPtr, iItm); - - /* shift the item to the left side of the clientRect */ - curr->rect.right -= curr->rect.left; - curr->rect.left = 0; - - TRACE("r=%ld, cl=%d, cl.r=%ld, iCount=%d, iRow=%d, uNumRows=%d, remTab=%d, tabPerRow=%d\n", - curr->rect.right, curItemLeftPos, clientRect.right, - iCount, iRow, infoPtr->uNumRows, remTab, tabPerRow); - - /* if we have reached the maximum number of tabs on this row */ - /* move to the next row, reset our current item left position and */ - /* the count of items on this row */ - - if (lStyle & TCS_VERTICAL) { - /* Vert: Add the remaining tabs in the *last* remainder rows */ - if (iCount >= ((iRow>=(INT)infoPtr->uNumRows - remTab)?tabPerRow + 1:tabPerRow)) { - iRow++; - curItemLeftPos = 0; - iCount = 0; - } - } else { - /* Horz: Add the remaining tabs in the *first* remainder rows */ - if (iCount >= ((iRowrect.left += curItemLeftPos; - curr->rect.right += curItemLeftPos; - curr->rect.top = iRow; - if (lStyle & TCS_BUTTONS) - { - curItemLeftPos = curr->rect.right + 1; - if (lStyle & TCS_FLATBUTTONS) - curItemLeftPos += FLAT_BTN_SPACINGX; - } - else - curItemLeftPos = curr->rect.right; - - TRACE("arranging <%s>, l,r=%ld,%ld, row=%ld\n", - debugstr_w(curr->pszText), curr->rect.left, - curr->rect.right, curr->rect.top); - } - - /* - * Justify the rows - */ - { - INT widthDiff, iIndexStart=0, iIndexEnd=0; - INT remainder; - INT iCount=0; - - while(iIndexStart < infoPtr->uNumItem) - { - TAB_ITEM *start = TAB_GetItem(infoPtr, iIndexStart); - - /* - * find the index of the row - */ - /* find the first item on the next row */ - for (iIndexEnd=iIndexStart; - (iIndexEnd < infoPtr->uNumItem) && - (TAB_GetItem(infoPtr, iIndexEnd)->rect.top == - start->rect.top) ; - iIndexEnd++) - /* intentionally blank */; - - /* - * we need to justify these tabs so they fill the whole given - * client area - * - */ - /* find the amount of space remaining on this row */ - widthDiff = clientRect.right - (2 * SELECTED_TAB_OFFSET) - - TAB_GetItem(infoPtr, iIndexEnd - 1)->rect.right; - - /* iCount is the number of tab items on this row */ - iCount = iIndexEnd - iIndexStart; - - if (iCount > 1) - { - remainder = widthDiff % iCount; - widthDiff = widthDiff / iCount; - /* add widthDiff/iCount, or extra space/items on row, to each item on this row */ - for (iIndex=iIndexStart, iCount=0; iIndex < iIndexEnd; iIndex++, iCount++) - { - TAB_ITEM *item = TAB_GetItem(infoPtr, iIndex); - - item->rect.left += iCount * widthDiff; - item->rect.right += (iCount + 1) * widthDiff; - - TRACE("adjusting 1 <%s>, l,r=%ld,%ld\n", - debugstr_w(item->pszText), - item->rect.left, item->rect.right); - - } - TAB_GetItem(infoPtr, iIndex - 1)->rect.right += remainder; - } - else /* we have only one item on this row, make it take up the entire row */ - { - start->rect.left = clientRect.left; - start->rect.right = clientRect.right - 4; - - TRACE("adjusting 2 <%s>, l,r=%ld,%ld\n", - debugstr_w(start->pszText), - start->rect.left, start->rect.right); - - } - - - iIndexStart = iIndexEnd; - } - } - } - - /* if TCS_VERTICAL rotate the tabs so they are along the side of the clientRect */ - if(lStyle & TCS_VERTICAL) - { - RECT rcOriginal; - for(iIndex = 0; iIndex < infoPtr->uNumItem; iIndex++) - { - rcItem = &TAB_GetItem(infoPtr, iIndex)->rect; - - rcOriginal = *rcItem; - - /* this is rotating the items by 90 degrees clockwise around the center of the control */ - rcItem->top = (rcOriginal.left - clientRect.left); - rcItem->bottom = rcItem->top + (rcOriginal.right - rcOriginal.left); - rcItem->left = rcOriginal.top; - rcItem->right = rcOriginal.bottom; - } - } - - TAB_EnsureSelectionVisible(hwnd,infoPtr); - TAB_RecalcHotTrack(hwnd, NULL, NULL, NULL); - - /* Cleanup */ - SelectObject (hdc, hOldFont); - ReleaseDC (hwnd, hdc); -} - - -static void -TAB_EraseTabInterior - ( - HWND hwnd, - HDC hdc, - INT iItem, - RECT* drawRect - ) -{ - TAB_INFO *infoPtr = TAB_GetInfoPtr(hwnd); - LONG lStyle = GetWindowLongA(hwnd, GWL_STYLE); - HBRUSH hbr = CreateSolidBrush (comctl32_color.clrBtnFace); - BOOL deleteBrush = TRUE; - RECT rTemp = *drawRect; - - InflateRect(&rTemp, -2, -2); - if (lStyle & TCS_BUTTONS) - { - if (iItem == infoPtr->iSelected) - { - /* Background color */ - if (!(lStyle & TCS_OWNERDRAWFIXED)) - { - DeleteObject(hbr); - hbr = GetSysColorBrush(COLOR_SCROLLBAR); - - SetTextColor(hdc, comctl32_color.clr3dFace); - SetBkColor(hdc, comctl32_color.clr3dHilight); - - /* if COLOR_WINDOW happens to be the same as COLOR_3DHILIGHT - * we better use 0x55aa bitmap brush to make scrollbar's background - * look different from the window background. - */ - if (comctl32_color.clr3dHilight == comctl32_color.clrWindow) - hbr = COMCTL32_hPattern55AABrush; - - deleteBrush = FALSE; - } - FillRect(hdc, &rTemp, hbr); - } - else /* ! selected */ - { - if (lStyle & TCS_FLATBUTTONS) - { - FillRect(hdc, drawRect, hbr); - if (iItem == infoPtr->iHotTracked) - DrawEdge(hdc, drawRect, EDGE_RAISED, BF_SOFT|BF_RECT); - } - else - FillRect(hdc, &rTemp, hbr); - } - - } - else /* !TCS_BUTTONS */ - { - FillRect(hdc, &rTemp, hbr); - } - - /* Cleanup */ - if (deleteBrush) DeleteObject(hbr); -} - -/****************************************************************************** - * TAB_DrawItemInterior - * - * This method is used to draw the interior (text and icon) of a single tab - * into the tab control. - */ -static void -TAB_DrawItemInterior - ( - HWND hwnd, - HDC hdc, - INT iItem, - RECT* drawRect - ) -{ - TAB_INFO* infoPtr = TAB_GetInfoPtr(hwnd); - LONG lStyle = GetWindowLongA(hwnd, GWL_STYLE); - - RECT localRect; - - HPEN htextPen; - HPEN holdPen; - INT oldBkMode; - HFONT hOldFont; - -/* if (drawRect == NULL) */ - { - BOOL isVisible; - RECT itemRect; - RECT selectedRect; - - /* - * Get the rectangle for the item. - */ - isVisible = TAB_InternalGetItemRect(hwnd, infoPtr, iItem, &itemRect, &selectedRect); - if (!isVisible) - return; - - /* - * Make sure drawRect points to something valid; simplifies code. - */ - drawRect = &localRect; - - /* - * This logic copied from the part of TAB_DrawItem which draws - * the tab background. It's important to keep it in sync. I - * would have liked to avoid code duplication, but couldn't figure - * out how without making spaghetti of TAB_DrawItem. - */ - if (iItem == infoPtr->iSelected) - *drawRect = selectedRect; - else - *drawRect = itemRect; - - if (lStyle & TCS_BUTTONS) - { - if (iItem == infoPtr->iSelected) - { - drawRect->left += 4; - drawRect->top += 4; - drawRect->right -= 4; - drawRect->bottom -= 1; - } - else - { - drawRect->left += 2; - drawRect->top += 2; - drawRect->right -= 2; - drawRect->bottom -= 2; - } - } - else - { - if ((lStyle & TCS_VERTICAL) && (lStyle & TCS_BOTTOM)) - { - if (iItem != infoPtr->iSelected) - { - drawRect->left += 2; - drawRect->top += 2; - drawRect->bottom -= 2; - } - } - else if (lStyle & TCS_VERTICAL) - { - if (iItem == infoPtr->iSelected) - { - drawRect->right += 1; - } - else - { - drawRect->top += 2; - drawRect->right -= 2; - drawRect->bottom -= 2; - } - } - else if (lStyle & TCS_BOTTOM) - { - if (iItem == infoPtr->iSelected) - { - drawRect->top -= 2; - } - else - { - InflateRect(drawRect, -2, -2); - drawRect->bottom += 2; - } - } - else - { - if (iItem == infoPtr->iSelected) - { - drawRect->bottom += 3; - } - else - { - drawRect->bottom -= 2; - InflateRect(drawRect, -2, 0); - } - } - } - } - TRACE("drawRect=(%ld,%ld)-(%ld,%ld)\n", - drawRect->left, drawRect->top, drawRect->right, drawRect->bottom); - - /* Clear interior */ - TAB_EraseTabInterior (hwnd, hdc, iItem, drawRect); - - /* Draw the focus rectangle */ - if (!(lStyle & TCS_FOCUSNEVER) && - (GetFocus() == hwnd) && - (iItem == infoPtr->uFocus) ) - { - RECT rFocus = *drawRect; - InflateRect(&rFocus, -3, -3); - if (lStyle & TCS_BOTTOM && !(lStyle & TCS_VERTICAL)) - rFocus.top -= 3; - if (lStyle & TCS_BUTTONS) - { - rFocus.left -= 3; - rFocus.top -= 3; - } - - DrawFocusRect(hdc, &rFocus); - } - - /* - * Text pen - */ - htextPen = CreatePen( PS_SOLID, 1, GetSysColor(COLOR_BTNTEXT) ); - holdPen = SelectObject(hdc, htextPen); - hOldFont = SelectObject(hdc, infoPtr->hFont); - - /* - * Setup for text output - */ - oldBkMode = SetBkMode(hdc, TRANSPARENT); - SetTextColor(hdc, (((iItem == infoPtr->iHotTracked) && !(lStyle & TCS_FLATBUTTONS)) | - (TAB_GetItem(infoPtr, iItem)->dwState & TCIS_HIGHLIGHTED)) ? - comctl32_color.clrHighlight : comctl32_color.clrBtnText); - - /* - * if owner draw, tell the owner to draw - */ - if ((lStyle & TCS_OWNERDRAWFIXED) && GetParent(hwnd)) - { - DRAWITEMSTRUCT dis; - UINT id; - - drawRect->top += 2; - drawRect->right -= 1; - if ( iItem == infoPtr->iSelected ) - { - drawRect->right -= 1; - drawRect->left += 1; - } - - /* - * get the control id - */ - id = (UINT)GetWindowLongPtrW( hwnd, GWLP_ID ); - - /* - * put together the DRAWITEMSTRUCT - */ - dis.CtlType = ODT_TAB; - dis.CtlID = id; - dis.itemID = iItem; - dis.itemAction = ODA_DRAWENTIRE; - dis.itemState = 0; - if ( iItem == infoPtr->iSelected ) - dis.itemState |= ODS_SELECTED; - if (infoPtr->uFocus == iItem) - dis.itemState |= ODS_FOCUS; - dis.hwndItem = hwnd; /* */ - dis.hDC = hdc; - CopyRect(&dis.rcItem,drawRect); - dis.itemData = (ULONG_PTR)TAB_GetItem(infoPtr, iItem)->extra; - - /* - * send the draw message - */ - SendMessageW( infoPtr->hwndNotify, WM_DRAWITEM, (WPARAM)id, (LPARAM)&dis ); - } - else - { - TAB_ITEM *item = TAB_GetItem(infoPtr, iItem); - RECT rcTemp; - RECT rcImage; - - /* used to center the icon and text in the tab */ - RECT rcText; - INT center_offset_h, center_offset_v; - - /* set rcImage to drawRect, we will use top & left in our ImageList_Draw call */ - rcImage = *drawRect; - - rcTemp = *drawRect; - - rcText.left = rcText.top = rcText.right = rcText.bottom = 0; - - /* get the rectangle that the text fits in */ - if (item->pszText) - { - DrawTextW(hdc, item->pszText, -1, &rcText, DT_CALCRECT); - } - /* - * If not owner draw, then do the drawing ourselves. - * - * Draw the icon. - */ - if (infoPtr->himl && (item->mask & TCIF_IMAGE)) - { - INT cx; - INT cy; - - ImageList_GetIconSize(infoPtr->himl, &cx, &cy); - - if(lStyle & TCS_VERTICAL) - { - center_offset_h = ((drawRect->bottom - drawRect->top) - (cy + infoPtr->uHItemPadding + (rcText.right - rcText.left))) / 2; - center_offset_v = ((drawRect->right - drawRect->left) - (cx + infoPtr->uVItemPadding)) / 2; - } - else - { - center_offset_h = ((drawRect->right - drawRect->left) - (cx + infoPtr->uHItemPadding + (rcText.right - rcText.left))) / 2; - center_offset_v = ((drawRect->bottom - drawRect->top) - (cy + infoPtr->uVItemPadding)) / 2; - } - - if (lStyle & TCS_FIXEDWIDTH && lStyle & (TCS_FORCELABELLEFT | TCS_FORCEICONLEFT)) - center_offset_h = infoPtr->uHItemPadding; - - if (center_offset_h < 2) - center_offset_h = 2; - - if (center_offset_v < 0) - center_offset_v = 0; - - TRACE("for <%s>, c_o_h=%d, c_o_v=%d, draw=(%ld,%ld)-(%ld,%ld), textlen=%ld\n", - debugstr_w(item->pszText), center_offset_h, center_offset_v, - drawRect->left, drawRect->top, drawRect->right, drawRect->bottom, - (rcText.right-rcText.left)); - - if((lStyle & TCS_VERTICAL) && (lStyle & TCS_BOTTOM)) - { - rcImage.top = drawRect->top + center_offset_h; - /* if tab is TCS_VERTICAL and TCS_BOTTOM, the text is drawn from the */ - /* right side of the tab, but the image still uses the left as its x position */ - /* this keeps the image always drawn off of the same side of the tab */ - rcImage.left = drawRect->right - cx - center_offset_v; - drawRect->top += cy + infoPtr->uHItemPadding; - } - else if(lStyle & TCS_VERTICAL) - { - rcImage.top = drawRect->bottom - cy - center_offset_h; - rcImage.left = drawRect->left + center_offset_v; - drawRect->bottom -= cy + infoPtr->uHItemPadding; - } - else /* normal style, whether TCS_BOTTOM or not */ - { - rcImage.left = drawRect->left + center_offset_h; - rcImage.top = drawRect->top + center_offset_v; - drawRect->left += cx + infoPtr->uHItemPadding; - } - - TRACE("drawing image=%d, left=%ld, top=%ld\n", - item->iImage, rcImage.left, rcImage.top-1); - ImageList_Draw - ( - infoPtr->himl, - item->iImage, - hdc, - rcImage.left, - rcImage.top, - ILD_NORMAL - ); - } - - /* Now position text */ - if (lStyle & TCS_FIXEDWIDTH && lStyle & TCS_FORCELABELLEFT) - center_offset_h = infoPtr->uHItemPadding; - else - if(lStyle & TCS_VERTICAL) - center_offset_h = ((drawRect->bottom - drawRect->top) - (rcText.right - rcText.left)) / 2; - else - center_offset_h = ((drawRect->right - drawRect->left) - (rcText.right - rcText.left)) / 2; - - if(lStyle & TCS_VERTICAL) - { - if(lStyle & TCS_BOTTOM) - drawRect->top+=center_offset_h; - else - drawRect->bottom-=center_offset_h; - - center_offset_v = ((drawRect->right - drawRect->left) - ((rcText.bottom - rcText.top) + infoPtr->uVItemPadding)) / 2; - } - else - { - drawRect->left += center_offset_h; - center_offset_v = ((drawRect->bottom - drawRect->top) - ((rcText.bottom - rcText.top) + infoPtr->uVItemPadding)) / 2; - } - - if (center_offset_v < 0) - center_offset_v = 0; - - if(lStyle & TCS_VERTICAL) - drawRect->left += center_offset_v; - else - drawRect->top += center_offset_v; - - /* Draw the text */ - if(lStyle & TCS_VERTICAL) /* if we are vertical rotate the text and each character */ - { - LOGFONTA logfont; - HFONT hFont = 0; - INT nEscapement = 900; - INT nOrientation = 900; - - if(lStyle & TCS_BOTTOM) - { - nEscapement = -900; - nOrientation = -900; - } - - /* to get a font with the escapement and orientation we are looking for, we need to */ - /* call CreateFontIndirectA, which requires us to set the values of the logfont we pass in */ - if (!GetObjectA((infoPtr->hFont) ? - infoPtr->hFont : GetStockObject(SYSTEM_FONT), - sizeof(LOGFONTA),&logfont)) - { - INT iPointSize = 9; - - lstrcpyA(logfont.lfFaceName, "Arial"); - logfont.lfHeight = -MulDiv(iPointSize, GetDeviceCaps(hdc, LOGPIXELSY), - 72); - logfont.lfWeight = FW_NORMAL; - logfont.lfItalic = 0; - logfont.lfUnderline = 0; - logfont.lfStrikeOut = 0; - } - - logfont.lfEscapement = nEscapement; - logfont.lfOrientation = nOrientation; - hFont = CreateFontIndirectA(&logfont); - SelectObject(hdc, hFont); - - if (item->pszText) - { - ExtTextOutW(hdc, - (lStyle & TCS_BOTTOM) ? drawRect->right : drawRect->left, - (!(lStyle & TCS_BOTTOM)) ? drawRect->bottom : drawRect->top, - ETO_CLIPPED, - drawRect, - item->pszText, - lstrlenW(item->pszText), - 0); - } - - DeleteObject(hFont); - } - else - { - TRACE("for <%s>, c_o_h=%d, c_o_v=%d, draw=(%ld,%ld)-(%ld,%ld), textlen=%ld\n", - debugstr_w(item->pszText), center_offset_h, center_offset_v, - drawRect->left, drawRect->top, drawRect->right, drawRect->bottom, - (rcText.right-rcText.left)); - if (item->pszText) - { - DrawTextW - ( - hdc, - item->pszText, - lstrlenW(item->pszText), - drawRect, - DT_LEFT | DT_SINGLELINE - ); - } - } - - *drawRect = rcTemp; /* restore drawRect */ - } - - /* - * Cleanup - */ - SelectObject(hdc, hOldFont); - SetBkMode(hdc, oldBkMode); - SelectObject(hdc, holdPen); - DeleteObject( htextPen ); -} - -/****************************************************************************** - * TAB_DrawItem - * - * This method is used to draw a single tab into the tab control. - */ -static void TAB_DrawItem( - HWND hwnd, - HDC hdc, - INT iItem) -{ - TAB_INFO *infoPtr = TAB_GetInfoPtr(hwnd); - LONG lStyle = GetWindowLongA(hwnd, GWL_STYLE); - RECT itemRect; - RECT selectedRect; - BOOL isVisible; - RECT r, fillRect, r1; - INT clRight = 0; - INT clBottom = 0; - COLORREF bkgnd, corner; - - /* - * Get the rectangle for the item. - */ - isVisible = TAB_InternalGetItemRect(hwnd, - infoPtr, - iItem, - &itemRect, - &selectedRect); - - if (isVisible) - { - RECT rUD, rC; - - /* Clip UpDown control to not draw over it */ - if (infoPtr->needsScrolling) - { - GetWindowRect(hwnd, &rC); - GetWindowRect(infoPtr->hwndUpDown, &rUD); - ExcludeClipRect(hdc, rUD.left - rC.left, rUD.top - rC.top, rUD.right - rC.left, rUD.bottom - rC.top); - } - - /* If you need to see what the control is doing, - * then override these variables. They will change what - * fill colors are used for filling the tabs, and the - * corners when drawing the edge. - */ - bkgnd = comctl32_color.clrBtnFace; - corner = comctl32_color.clrBtnFace; - - if (lStyle & TCS_BUTTONS) - { - /* Get item rectangle */ - r = itemRect; - - /* Separators between flat buttons */ - if (lStyle & TCS_FLATBUTTONS) - { - r1 = r; - r1.right += (FLAT_BTN_SPACINGX -2); - DrawEdge(hdc, &r1, EDGE_ETCHED, BF_RIGHT); - } - - if (iItem == infoPtr->iSelected) - { - DrawEdge(hdc, &r, EDGE_SUNKEN, BF_SOFT|BF_RECT); - - OffsetRect(&r, 1, 1); - } - else /* ! selected */ - { - if (!(lStyle & TCS_FLATBUTTONS)) - DrawEdge(hdc, &r, EDGE_RAISED, BF_SOFT|BF_RECT); - } - } - else /* !TCS_BUTTONS */ - { - /* We draw a rectangle of different sizes depending on the selection - * state. */ - if (iItem == infoPtr->iSelected) { - RECT rect; - GetClientRect (hwnd, &rect); - clRight = rect.right; - clBottom = rect.bottom; - r = selectedRect; - } - else - r = itemRect; - - /* - * Erase the background. (Delay it but setup rectangle.) - * This is necessary when drawing the selected item since it is larger - * than the others, it might overlap with stuff already drawn by the - * other tabs - */ - fillRect = r; - - if(lStyle & TCS_VERTICAL) - { - /* These are for adjusting the drawing of a Selected tab */ - /* The initial values are for the normal case of non-Selected */ - int ZZ = 1; /* Do not strech if selected */ - if (iItem == infoPtr->iSelected) { - ZZ = 0; - - /* if leftmost draw the line longer */ - if(selectedRect.top == 0) - fillRect.top += CONTROL_BORDER_SIZEY; - /* if rightmost draw the line longer */ - if(selectedRect.bottom == clBottom) - fillRect.bottom -= CONTROL_BORDER_SIZEY; - } - - if (lStyle & TCS_BOTTOM) - { - /* Adjust both rectangles to match native */ - r.left += (1-ZZ); - - TRACE(" item=%d, fill=(%ld,%ld)-(%ld,%ld), edge=(%ld,%ld)-(%ld,%ld)\n", - iItem, - fillRect.left,fillRect.top,fillRect.right,fillRect.bottom, - r.left,r.top,r.right,r.bottom); - - /* Clear interior */ - SetBkColor(hdc, bkgnd); - ExtTextOutA(hdc, 0, 0, 2, &fillRect, NULL, 0, 0); - - /* Draw rectangular edge around tab */ - DrawEdge(hdc, &r, EDGE_RAISED, BF_SOFT|BF_RIGHT|BF_TOP|BF_BOTTOM); - - /* Now erase the top corner and draw diagonal edge */ - SetBkColor(hdc, corner); - r1.left = r.right - ROUND_CORNER_SIZE - 1; - r1.top = r.top; - r1.right = r.right; - r1.bottom = r1.top + ROUND_CORNER_SIZE; - ExtTextOutA(hdc, 0, 0, 2, &r1, NULL, 0, 0); - r1.right--; - DrawEdge(hdc, &r1, EDGE_RAISED, BF_SOFT|BF_DIAGONAL_ENDTOPLEFT); - - /* Now erase the bottom corner and draw diagonal edge */ - r1.left = r.right - ROUND_CORNER_SIZE - 1; - r1.bottom = r.bottom; - r1.right = r.right; - r1.top = r1.bottom - ROUND_CORNER_SIZE; - ExtTextOutA(hdc, 0, 0, 2, &r1, NULL, 0, 0); - r1.right--; - DrawEdge(hdc, &r1, EDGE_RAISED, BF_SOFT|BF_DIAGONAL_ENDBOTTOMLEFT); - - if ((iItem == infoPtr->iSelected) && (selectedRect.top == 0)) { - r1 = r; - r1.right = r1.left; - r1.left--; - DrawEdge(hdc, &r1, EDGE_RAISED, BF_SOFT|BF_TOP); - } - - } - else - { - TRACE(" item=%d, fill=(%ld,%ld)-(%ld,%ld), edge=(%ld,%ld)-(%ld,%ld)\n", - iItem, - fillRect.left,fillRect.top,fillRect.right,fillRect.bottom, - r.left,r.top,r.right,r.bottom); - - /* Clear interior */ - SetBkColor(hdc, bkgnd); - ExtTextOutA(hdc, 0, 0, 2, &fillRect, NULL, 0, 0); - - /* Draw rectangular edge around tab */ - DrawEdge(hdc, &r, EDGE_RAISED, BF_SOFT|BF_LEFT|BF_TOP|BF_BOTTOM); - - /* Now erase the top corner and draw diagonal edge */ - SetBkColor(hdc, corner); - r1.left = r.left; - r1.top = r.top; - r1.right = r1.left + ROUND_CORNER_SIZE + 1; - r1.bottom = r1.top + ROUND_CORNER_SIZE; - ExtTextOutA(hdc, 0, 0, 2, &r1, NULL, 0, 0); - r1.left++; - DrawEdge(hdc, &r1, EDGE_RAISED, BF_SOFT|BF_DIAGONAL_ENDTOPRIGHT); - - /* Now erase the bottom corner and draw diagonal edge */ - r1.left = r.left; - r1.bottom = r.bottom; - r1.right = r1.left + ROUND_CORNER_SIZE + 1; - r1.top = r1.bottom - ROUND_CORNER_SIZE; - ExtTextOutA(hdc, 0, 0, 2, &r1, NULL, 0, 0); - r1.left++; - DrawEdge(hdc, &r1, EDGE_SUNKEN, BF_DIAGONAL_ENDTOPLEFT); - } - } - else /* ! TCS_VERTICAL */ - { - /* These are for adjusting the drawing of a Selected tab */ - /* The initial values are for the normal case of non-Selected */ - if (iItem == infoPtr->iSelected) { - /* if leftmost draw the line longer */ - if(selectedRect.left == 0) - fillRect.left += CONTROL_BORDER_SIZEX; - /* if rightmost draw the line longer */ - if(selectedRect.right == clRight) - fillRect.right -= CONTROL_BORDER_SIZEX; - } - - if (lStyle & TCS_BOTTOM) - { - /* Adjust both rectangles for topmost row */ - if (TAB_GetItem(infoPtr, iItem)->rect.top == infoPtr->uNumRows-1) - { - fillRect.top -= 2; - r.top -= 1; - } - - TRACE(" item=%d, fill=(%ld,%ld)-(%ld,%ld), edge=(%ld,%ld)-(%ld,%ld)\n", - iItem, - fillRect.left,fillRect.top,fillRect.right,fillRect.bottom, - r.left,r.top,r.right,r.bottom); - - /* Clear interior */ - SetBkColor(hdc, bkgnd); - ExtTextOutA(hdc, 0, 0, 2, &fillRect, NULL, 0, 0); - - /* Draw rectangular edge around tab */ - DrawEdge(hdc, &r, EDGE_RAISED, BF_SOFT|BF_LEFT|BF_BOTTOM|BF_RIGHT); - - /* Now erase the righthand corner and draw diagonal edge */ - SetBkColor(hdc, corner); - r1.left = r.right - ROUND_CORNER_SIZE; - r1.bottom = r.bottom; - r1.right = r.right; - r1.top = r1.bottom - ROUND_CORNER_SIZE - 1; - ExtTextOutA(hdc, 0, 0, 2, &r1, NULL, 0, 0); - r1.bottom--; - DrawEdge(hdc, &r1, EDGE_RAISED, BF_SOFT|BF_DIAGONAL_ENDBOTTOMLEFT); - - /* Now erase the lefthand corner and draw diagonal edge */ - r1.left = r.left; - r1.bottom = r.bottom; - r1.right = r1.left + ROUND_CORNER_SIZE; - r1.top = r1.bottom - ROUND_CORNER_SIZE - 1; - ExtTextOutA(hdc, 0, 0, 2, &r1, NULL, 0, 0); - r1.bottom--; - DrawEdge(hdc, &r1, EDGE_RAISED, BF_SOFT|BF_DIAGONAL_ENDTOPLEFT); - - if (iItem == infoPtr->iSelected) - { - r.top += 2; - r.left += 1; - if (selectedRect.left == 0) - { - r1 = r; - r1.bottom = r1.top; - r1.top--; - DrawEdge(hdc, &r1, EDGE_RAISED, BF_SOFT|BF_LEFT); - } - } - - } - else - { - /* Adjust both rectangles for bottommost row */ - if (TAB_GetItem(infoPtr, iItem)->rect.top == infoPtr->uNumRows-1) - { - fillRect.bottom += 3; - r.bottom += 2; - } - - TRACE(" item=%d, fill=(%ld,%ld)-(%ld,%ld), edge=(%ld,%ld)-(%ld,%ld)\n", - iItem, - fillRect.left,fillRect.top,fillRect.right,fillRect.bottom, - r.left,r.top,r.right,r.bottom); - - /* Clear interior */ - SetBkColor(hdc, bkgnd); - ExtTextOutA(hdc, 0, 0, 2, &fillRect, NULL, 0, 0); - - /* Draw rectangular edge around tab */ - DrawEdge(hdc, &r, EDGE_RAISED, BF_SOFT|BF_LEFT|BF_TOP|BF_RIGHT); - - /* Now erase the righthand corner and draw diagonal edge */ - SetBkColor(hdc, corner); - r1.left = r.right - ROUND_CORNER_SIZE; - r1.top = r.top; - r1.right = r.right; - r1.bottom = r1.top + ROUND_CORNER_SIZE + 1; - ExtTextOutA(hdc, 0, 0, 2, &r1, NULL, 0, 0); - r1.top++; - DrawEdge(hdc, &r1, EDGE_RAISED, BF_SOFT|BF_DIAGONAL_ENDBOTTOMRIGHT); - - /* Now erase the lefthand corner and draw diagonal edge */ - r1.left = r.left; - r1.top = r.top; - r1.right = r1.left + ROUND_CORNER_SIZE; - r1.bottom = r1.top + ROUND_CORNER_SIZE + 1; - ExtTextOutA(hdc, 0, 0, 2, &r1, NULL, 0, 0); - r1.top++; - DrawEdge(hdc, &r1, EDGE_RAISED, BF_SOFT|BF_DIAGONAL_ENDTOPRIGHT); - } - } - } - - TAB_DumpItemInternal(infoPtr, iItem); - - /* This modifies r to be the text rectangle. */ - TAB_DrawItemInterior(hwnd, hdc, iItem, &r); - } -} - -/****************************************************************************** - * TAB_DrawBorder - * - * This method is used to draw the raised border around the tab control - * "content" area. - */ -static void TAB_DrawBorder (HWND hwnd, HDC hdc) -{ - TAB_INFO *infoPtr = TAB_GetInfoPtr(hwnd); - RECT rect; - DWORD lStyle = GetWindowLongA(hwnd, GWL_STYLE); - - GetClientRect (hwnd, &rect); - - /* - * Adjust for the style - */ - - if (infoPtr->uNumItem) - { - if ((lStyle & TCS_BOTTOM) && !(lStyle & TCS_VERTICAL)) - rect.bottom -= infoPtr->tabHeight * infoPtr->uNumRows + CONTROL_BORDER_SIZEX; - else if((lStyle & TCS_BOTTOM) && (lStyle & TCS_VERTICAL)) - rect.right -= infoPtr->tabHeight * infoPtr->uNumRows + CONTROL_BORDER_SIZEX; - else if(lStyle & TCS_VERTICAL) - rect.left += infoPtr->tabHeight * infoPtr->uNumRows + CONTROL_BORDER_SIZEX; - else /* not TCS_VERTICAL and not TCS_BOTTOM */ - rect.top += infoPtr->tabHeight * infoPtr->uNumRows + CONTROL_BORDER_SIZEX; - } - - TRACE("border=(%ld,%ld)-(%ld,%ld)\n", - rect.left, rect.top, rect.right, rect.bottom); - - DrawEdge(hdc, &rect, EDGE_RAISED, BF_SOFT|BF_RECT); -} - -/****************************************************************************** - * TAB_Refresh - * - * This method repaints the tab control.. - */ -static void TAB_Refresh (HWND hwnd, HDC hdc) -{ - TAB_INFO *infoPtr = TAB_GetInfoPtr(hwnd); - HFONT hOldFont; - INT i; - - if (!infoPtr->DoRedraw) - return; - - hOldFont = SelectObject (hdc, infoPtr->hFont); - - if (GetWindowLongA(hwnd, GWL_STYLE) & TCS_BUTTONS) - { - for (i = 0; i < infoPtr->uNumItem; i++) - TAB_DrawItem (hwnd, hdc, i); - } - else - { - /* Draw all the non selected item first */ - for (i = 0; i < infoPtr->uNumItem; i++) - { - if (i != infoPtr->iSelected) - TAB_DrawItem (hwnd, hdc, i); - } - - /* Now, draw the border, draw it before the selected item - * since the selected item overwrites part of the border. */ - TAB_DrawBorder (hwnd, hdc); - - /* Then, draw the selected item */ - TAB_DrawItem (hwnd, hdc, infoPtr->iSelected); - - /* If we haven't set the current focus yet, set it now. - * Only happens when we first paint the tab controls */ - if (infoPtr->uFocus == -1) - TAB_SetCurFocus(hwnd, infoPtr->iSelected); - } - - SelectObject (hdc, hOldFont); -} - -static DWORD -TAB_GetRowCount (HWND hwnd ) -{ - TAB_INFO *infoPtr = TAB_GetInfoPtr(hwnd); - - return infoPtr->uNumRows; -} - -static LRESULT -TAB_SetRedraw (HWND hwnd, WPARAM wParam) -{ - TAB_INFO *infoPtr = TAB_GetInfoPtr(hwnd); - - infoPtr->DoRedraw=(BOOL) wParam; - return 0; -} - -/****************************************************************************** - * TAB_EnsureSelectionVisible - * - * This method will make sure that the current selection is completely - * visible by scrolling until it is. - */ -static void TAB_EnsureSelectionVisible( - HWND hwnd, - TAB_INFO* infoPtr) -{ - INT iSelected = infoPtr->iSelected; - LONG lStyle = GetWindowLongA(hwnd, GWL_STYLE); - INT iOrigLeftmostVisible = infoPtr->leftmostVisible; - - /* set the items row to the bottommost row or topmost row depending on - * style */ - if ((infoPtr->uNumRows > 1) && !(lStyle & TCS_BUTTONS)) - { - TAB_ITEM *selected = TAB_GetItem(infoPtr, iSelected); - INT newselected; - INT iTargetRow; - - if(lStyle & TCS_VERTICAL) - newselected = selected->rect.left; - else - newselected = selected->rect.top; - - /* the target row is always (number of rows - 1) - as row 0 is furthest from the clientRect */ - iTargetRow = infoPtr->uNumRows - 1; - - if (newselected != iTargetRow) - { - UINT i; - if(lStyle & TCS_VERTICAL) - { - for (i=0; i < infoPtr->uNumItem; i++) - { - /* move everything in the row of the selected item to the iTargetRow */ - TAB_ITEM *item = TAB_GetItem(infoPtr, i); - - if (item->rect.left == newselected ) - item->rect.left = iTargetRow; - else - { - if (item->rect.left > newselected) - item->rect.left-=1; - } - } - } - else - { - for (i=0; i < infoPtr->uNumItem; i++) - { - TAB_ITEM *item = TAB_GetItem(infoPtr, i); - - if (item->rect.top == newselected ) - item->rect.top = iTargetRow; - else - { - if (item->rect.top > newselected) - item->rect.top-=1; - } - } - } - TAB_RecalcHotTrack(hwnd, NULL, NULL, NULL); - } - } - - /* - * Do the trivial cases first. - */ - if ( (!infoPtr->needsScrolling) || - (infoPtr->hwndUpDown==0) || (lStyle & TCS_VERTICAL)) - return; - - if (infoPtr->leftmostVisible >= iSelected) - { - infoPtr->leftmostVisible = iSelected; - } - else - { - TAB_ITEM *selected = TAB_GetItem(infoPtr, iSelected); - RECT r; - INT width; - UINT i; - - /* Calculate the part of the client area that is visible */ - GetClientRect(hwnd, &r); - width = r.right; - - GetClientRect(infoPtr->hwndUpDown, &r); - width -= r.right; - - if ((selected->rect.right - - selected->rect.left) >= width ) - { - /* Special case: width of selected item is greater than visible - * part of control. - */ - infoPtr->leftmostVisible = iSelected; - } - else - { - for (i = infoPtr->leftmostVisible; i < infoPtr->uNumItem; i++) - { - if ((selected->rect.right - TAB_GetItem(infoPtr, i)->rect.left) < width) - break; - } - infoPtr->leftmostVisible = i; - } - } - - if (infoPtr->leftmostVisible != iOrigLeftmostVisible) - TAB_RecalcHotTrack(hwnd, NULL, NULL, NULL); - - SendMessageW(infoPtr->hwndUpDown, UDM_SETPOS, 0, - MAKELONG(infoPtr->leftmostVisible, 0)); -} - -/****************************************************************************** - * TAB_InvalidateTabArea - * - * This method will invalidate the portion of the control that contains the - * tabs. It is called when the state of the control changes and needs - * to be redisplayed - */ -static void TAB_InvalidateTabArea( - HWND hwnd, - TAB_INFO* infoPtr) -{ - RECT clientRect, rInvalidate, rAdjClient; - DWORD lStyle = GetWindowLongA(hwnd, GWL_STYLE); - INT lastRow = infoPtr->uNumRows - 1; - RECT rect; - - if (lastRow < 0) return; - - GetClientRect(hwnd, &clientRect); - rInvalidate = clientRect; - rAdjClient = clientRect; - - TAB_AdjustRect(hwnd, 0, &rAdjClient); - - TAB_InternalGetItemRect(hwnd, infoPtr, infoPtr->uNumItem-1 , &rect, NULL); - if ((lStyle & TCS_BOTTOM) && (lStyle & TCS_VERTICAL)) - { - rInvalidate.left = rAdjClient.right; - if (infoPtr->uNumRows == 1) - rInvalidate.bottom = clientRect.top + rect.bottom + 2 * SELECTED_TAB_OFFSET; - } - else if(lStyle & TCS_VERTICAL) - { - rInvalidate.right = rAdjClient.left; - if (infoPtr->uNumRows == 1) - rInvalidate.bottom = clientRect.top + rect.bottom + 2 * SELECTED_TAB_OFFSET; - } - else if (lStyle & TCS_BOTTOM) - { - rInvalidate.top = rAdjClient.bottom; - if (infoPtr->uNumRows == 1) - rInvalidate.right = clientRect.left + rect.right + 2 * SELECTED_TAB_OFFSET; - } - else - { - rInvalidate.bottom = rAdjClient.top; - if (infoPtr->uNumRows == 1) - rInvalidate.right = clientRect.left + rect.right + 2 * SELECTED_TAB_OFFSET; - } - - /* Punch out the updown control */ - if (infoPtr->needsScrolling && (rInvalidate.right > 0)) { - RECT r; - GetClientRect(infoPtr->hwndUpDown, &r); - if (rInvalidate.right > clientRect.right - r.left) - rInvalidate.right = rInvalidate.right - (r.right - r.left); - else - rInvalidate.right = clientRect.right - r.left; - } - - TRACE("invalidate (%ld,%ld)-(%ld,%ld)\n", - rInvalidate.left, rInvalidate.top, - rInvalidate.right, rInvalidate.bottom); - - InvalidateRect(hwnd, &rInvalidate, TRUE); -} - -static LRESULT -TAB_Paint (HWND hwnd, WPARAM wParam) -{ - HDC hdc; - PAINTSTRUCT ps; - - if (wParam == 0) - { - hdc = BeginPaint (hwnd, &ps); - TRACE("erase %d, rect=(%ld,%ld)-(%ld,%ld)\n", - ps.fErase, - ps.rcPaint.left,ps.rcPaint.top,ps.rcPaint.right,ps.rcPaint.bottom); - } else { - hdc = (HDC)wParam; - } - - TAB_Refresh (hwnd, hdc); - - if(!wParam) - EndPaint (hwnd, &ps); - - return 0; -} - -static LRESULT -TAB_InsertItemAW (HWND hwnd, WPARAM wParam, LPARAM lParam, BOOL bUnicode) -{ - TAB_INFO *infoPtr = TAB_GetInfoPtr(hwnd); - TAB_ITEM *item; - TCITEMA *pti; - INT iItem; - RECT rect; - - GetClientRect (hwnd, &rect); - TRACE("Rect: %p T %li, L %li, B %li, R %li\n", hwnd, - rect.top, rect.left, rect.bottom, rect.right); - - pti = (TCITEMA *)lParam; - iItem = (INT)wParam; - - if (iItem < 0) return -1; - if (iItem > infoPtr->uNumItem) - iItem = infoPtr->uNumItem; - - if (bUnicode) - TAB_DumpItemExternalW((TCITEMW*)pti, iItem); - else - TAB_DumpItemExternalA(pti, iItem); - - - if (infoPtr->uNumItem == 0) { - infoPtr->items = Alloc (TAB_ITEM_SIZE(infoPtr)); - infoPtr->uNumItem++; - infoPtr->iSelected = 0; - } - else { - LPBYTE oldItems = (LPBYTE)infoPtr->items; - - infoPtr->uNumItem++; - infoPtr->items = Alloc (TAB_ITEM_SIZE(infoPtr) * infoPtr->uNumItem); - - /* pre insert copy */ - if (iItem > 0) { - memcpy (infoPtr->items, oldItems, - iItem * TAB_ITEM_SIZE(infoPtr)); - } - - /* post insert copy */ - if (iItem < infoPtr->uNumItem - 1) { - memcpy (TAB_GetItem(infoPtr, iItem + 1), - oldItems + iItem * TAB_ITEM_SIZE(infoPtr), - (infoPtr->uNumItem - iItem - 1) * TAB_ITEM_SIZE(infoPtr)); - - } - - if (iItem <= infoPtr->iSelected) - infoPtr->iSelected++; - - Free (oldItems); - } - - item = TAB_GetItem(infoPtr, iItem); - - item->mask = pti->mask; - item->pszText = NULL; - - if (pti->mask & TCIF_TEXT) - { - if (bUnicode) - Str_SetPtrW (&item->pszText, (WCHAR*)pti->pszText); - else - Str_SetPtrAtoW (&item->pszText, pti->pszText); - } - - if (pti->mask & TCIF_IMAGE) - item->iImage = pti->iImage; - else - item->iImage = -1; - - if (pti->mask & TCIF_PARAM) - memcpy(item->extra, &pti->lParam, infoPtr->cbInfo); - else - memset(item->extra, 0, infoPtr->cbInfo); - - TAB_SetItemBounds(hwnd); - if (infoPtr->uNumItem > 1) - TAB_InvalidateTabArea(hwnd, infoPtr); - else - InvalidateRect(hwnd, NULL, TRUE); - - TRACE("[%p]: added item %d %s\n", - hwnd, iItem, debugstr_w(item->pszText)); - - return iItem; -} - -static LRESULT -TAB_SetItemSize (HWND hwnd, WPARAM wParam, LPARAM lParam) -{ - TAB_INFO *infoPtr = TAB_GetInfoPtr(hwnd); - LONG lStyle = GetWindowLongA(hwnd, GWL_STYLE); - LONG lResult = 0; - BOOL bNeedPaint = FALSE; - - lResult = MAKELONG(infoPtr->tabWidth, infoPtr->tabHeight); - - /* UNDOCUMENTED: If requested Width or Height is 0 this means that program wants to use auto size. */ - if (lStyle & TCS_FIXEDWIDTH && (infoPtr->tabWidth != (INT)LOWORD(lParam))) - { - infoPtr->tabWidth = max((INT)LOWORD(lParam), infoPtr->tabMinWidth); - bNeedPaint = TRUE; - } - - if (infoPtr->tabHeight != (INT)HIWORD(lParam)) - { - if ((infoPtr->fHeightSet = ((INT)HIWORD(lParam) != 0))) - infoPtr->tabHeight = (INT)HIWORD(lParam); - - bNeedPaint = TRUE; - } - TRACE("was h=%d,w=%d, now h=%d,w=%d\n", - HIWORD(lResult), LOWORD(lResult), - infoPtr->tabHeight, infoPtr->tabWidth); - - if (bNeedPaint) - { - TAB_SetItemBounds(hwnd); - RedrawWindow(hwnd, NULL, NULL, RDW_ERASE | RDW_INVALIDATE | RDW_UPDATENOW); - } - - return lResult; -} - -static LRESULT -TAB_SetMinTabWidth (HWND hwnd, LPARAM lParam) -{ - TAB_INFO *infoPtr = TAB_GetInfoPtr(hwnd); - INT cx = (INT)lParam; - INT oldcx; - - if (infoPtr) { - oldcx = infoPtr->tabMinWidth; - infoPtr->tabMinWidth = (cx==-1)?DEFAULT_TAB_WIDTH:cx; - } else - return 0; - - return oldcx; -} - -static LRESULT -TAB_HighlightItem (HWND hwnd, WPARAM wParam, LPARAM lParam) -{ - TAB_INFO *infoPtr = TAB_GetInfoPtr(hwnd); - INT iItem = (INT)wParam; - BOOL fHighlight = (BOOL)LOWORD(lParam); - - if ((infoPtr) && (iItem>=0) && (iItemuNumItem)) { - if (fHighlight) - TAB_GetItem(infoPtr, iItem)->dwState |= TCIS_HIGHLIGHTED; - else - TAB_GetItem(infoPtr, iItem)->dwState &= ~TCIS_HIGHLIGHTED; - } else - return FALSE; - - return TRUE; -} - -static LRESULT -TAB_SetItemAW (HWND hwnd, WPARAM wParam, LPARAM lParam, BOOL bUnicode) -{ - TAB_INFO *infoPtr = TAB_GetInfoPtr(hwnd); - TCITEMA *tabItem; - TAB_ITEM *wineItem; - INT iItem; - - iItem = (INT)wParam; - tabItem = (LPTCITEMA)lParam; - - TRACE("%d %p\n", iItem, tabItem); - if ((iItem<0) || (iItem>=infoPtr->uNumItem)) return FALSE; - - if (bUnicode) - TAB_DumpItemExternalW((TCITEMW *)tabItem, iItem); - else - TAB_DumpItemExternalA(tabItem, iItem); - - wineItem = TAB_GetItem(infoPtr, iItem); - - if (tabItem->mask & TCIF_IMAGE) - wineItem->iImage = tabItem->iImage; - - if (tabItem->mask & TCIF_PARAM) - memcpy(wineItem->extra, &tabItem->lParam, infoPtr->cbInfo); - - if (tabItem->mask & TCIF_RTLREADING) - FIXME("TCIF_RTLREADING\n"); - - if (tabItem->mask & TCIF_STATE) - wineItem->dwState = tabItem->dwState; - - if (tabItem->mask & TCIF_TEXT) - { - if (wineItem->pszText) - { - Free(wineItem->pszText); - wineItem->pszText = NULL; - } - if (bUnicode) - Str_SetPtrW(&wineItem->pszText, (WCHAR*)tabItem->pszText); - else - Str_SetPtrAtoW(&wineItem->pszText, tabItem->pszText); - } - - /* Update and repaint tabs */ - TAB_SetItemBounds(hwnd); - TAB_InvalidateTabArea(hwnd,infoPtr); - - return TRUE; -} - -static LRESULT -TAB_GetItemCount (HWND hwnd, WPARAM wParam, LPARAM lParam) -{ - TAB_INFO *infoPtr = TAB_GetInfoPtr(hwnd); - - return infoPtr->uNumItem; -} - - -static LRESULT -TAB_GetItemAW (HWND hwnd, WPARAM wParam, LPARAM lParam, BOOL bUnicode) -{ - TAB_INFO *infoPtr = TAB_GetInfoPtr(hwnd); - TCITEMA *tabItem; - TAB_ITEM *wineItem; - INT iItem; - - iItem = (INT)wParam; - tabItem = (LPTCITEMA)lParam; - TRACE("\n"); - if ((iItem<0) || (iItem>=infoPtr->uNumItem)) - return FALSE; - - wineItem = TAB_GetItem(infoPtr, iItem); - - if (tabItem->mask & TCIF_IMAGE) - tabItem->iImage = wineItem->iImage; - - if (tabItem->mask & TCIF_PARAM) - memcpy(&tabItem->lParam, wineItem->extra, infoPtr->cbInfo); - - if (tabItem->mask & TCIF_RTLREADING) - FIXME("TCIF_RTLREADING\n"); - - if (tabItem->mask & TCIF_STATE) - tabItem->dwState = wineItem->dwState; - - if (tabItem->mask & TCIF_TEXT) - { - if (bUnicode) - Str_GetPtrW (wineItem->pszText, (WCHAR*)tabItem->pszText, tabItem->cchTextMax); - else - Str_GetPtrWtoA (wineItem->pszText, tabItem->pszText, tabItem->cchTextMax); - } - - if (bUnicode) - TAB_DumpItemExternalW((TCITEMW*)tabItem, iItem); - else - TAB_DumpItemExternalA(tabItem, iItem); - - return TRUE; -} - - -static LRESULT -TAB_DeleteItem (HWND hwnd, WPARAM wParam, LPARAM lParam) -{ - TAB_INFO *infoPtr = TAB_GetInfoPtr(hwnd); - INT iItem = (INT) wParam; - BOOL bResult = FALSE; - - if ((iItem >= 0) && (iItem < infoPtr->uNumItem)) - { - TAB_ITEM *item = TAB_GetItem(infoPtr, iItem); - LPBYTE oldItems = (LPBYTE)infoPtr->items; - - TAB_InvalidateTabArea(hwnd, infoPtr); - - if ((item->mask & TCIF_TEXT) && item->pszText) - Free(item->pszText); - - infoPtr->uNumItem--; - - if (!infoPtr->uNumItem) - { - infoPtr->items = NULL; - if (infoPtr->iHotTracked >= 0) - { - KillTimer(hwnd, TAB_HOTTRACK_TIMER); - infoPtr->iHotTracked = -1; - } - } - else - { - infoPtr->items = Alloc(TAB_ITEM_SIZE(infoPtr) * infoPtr->uNumItem); - - if (iItem > 0) - memcpy(infoPtr->items, oldItems, iItem * TAB_ITEM_SIZE(infoPtr)); - - if (iItem < infoPtr->uNumItem) - memcpy(TAB_GetItem(infoPtr, iItem), - oldItems + (iItem + 1) * TAB_ITEM_SIZE(infoPtr), - (infoPtr->uNumItem - iItem) * TAB_ITEM_SIZE(infoPtr)); - - if (iItem <= infoPtr->iHotTracked) - { - /* When tabs move left/up, the hot track item may change */ - FIXME("Recalc hot track"); - } - } - Free(oldItems); - - /* Readjust the selected index */ - if ((iItem == infoPtr->iSelected) && (iItem > 0)) - infoPtr->iSelected--; - - if (iItem < infoPtr->iSelected) - infoPtr->iSelected--; - - if (infoPtr->uNumItem == 0) - infoPtr->iSelected = -1; - - /* Reposition and repaint tabs */ - TAB_SetItemBounds(hwnd); - - bResult = TRUE; - } - - return bResult; -} - -static LRESULT -TAB_DeleteAllItems (HWND hwnd, WPARAM wParam, LPARAM lParam) -{ - TAB_INFO *infoPtr = TAB_GetInfoPtr(hwnd); - - while (infoPtr->uNumItem) - TAB_DeleteItem (hwnd, 0, 0); - return TRUE; -} - - -static LRESULT -TAB_GetFont (HWND hwnd, WPARAM wParam, LPARAM lParam) -{ - TAB_INFO *infoPtr = TAB_GetInfoPtr(hwnd); - - TRACE("\n"); - return (LRESULT)infoPtr->hFont; -} - -static LRESULT -TAB_SetFont (HWND hwnd, WPARAM wParam, LPARAM lParam) - -{ - TAB_INFO *infoPtr = TAB_GetInfoPtr(hwnd); - - TRACE("%x %lx\n",wParam, lParam); - - infoPtr->hFont = (HFONT)wParam; - - TAB_SetItemBounds(hwnd); - - TAB_InvalidateTabArea(hwnd, infoPtr); - - return 0; -} - - -static LRESULT -TAB_GetImageList (HWND hwnd, WPARAM wParam, LPARAM lParam) -{ - TAB_INFO *infoPtr = TAB_GetInfoPtr(hwnd); - - TRACE("\n"); - return (LRESULT)infoPtr->himl; -} - -static LRESULT -TAB_SetImageList (HWND hwnd, WPARAM wParam, LPARAM lParam) -{ - TAB_INFO *infoPtr = TAB_GetInfoPtr(hwnd); - HIMAGELIST himlPrev; - - TRACE("\n"); - himlPrev = infoPtr->himl; - infoPtr->himl= (HIMAGELIST)lParam; - return (LRESULT)himlPrev; -} - -static LRESULT -TAB_GetUnicodeFormat (HWND hwnd) -{ - TAB_INFO *infoPtr = TAB_GetInfoPtr (hwnd); - return infoPtr->bUnicode; -} - -static LRESULT -TAB_SetUnicodeFormat (HWND hwnd, WPARAM wParam) -{ - TAB_INFO *infoPtr = TAB_GetInfoPtr (hwnd); - BOOL bTemp = infoPtr->bUnicode; - - infoPtr->bUnicode = (BOOL)wParam; - - return bTemp; -} - -static LRESULT -TAB_Size (HWND hwnd, WPARAM wParam, LPARAM lParam) - -{ -/* I'm not really sure what the following code was meant to do. - This is what it is doing: - When WM_SIZE is sent with SIZE_RESTORED, the control - gets positioned in the top left corner. - - RECT parent_rect; - HWND parent; - UINT uPosFlags,cx,cy; - - uPosFlags=0; - if (!wParam) { - parent = GetParent (hwnd); - GetClientRect(parent, &parent_rect); - cx=LOWORD (lParam); - cy=HIWORD (lParam); - if (GetWindowLongA(hwnd, GWL_STYLE) & CCS_NORESIZE) - uPosFlags |= (SWP_NOSIZE | SWP_NOMOVE); - - SetWindowPos (hwnd, 0, parent_rect.left, parent_rect.top, - cx, cy, uPosFlags | SWP_NOZORDER); - } else { - FIXME("WM_SIZE flag %x %lx not handled\n", wParam, lParam); - } */ - - /* Recompute the size/position of the tabs. */ - TAB_SetItemBounds (hwnd); - - /* Force a repaint of the control. */ - InvalidateRect(hwnd, NULL, TRUE); - - return 0; -} - - -static LRESULT -TAB_Create (HWND hwnd, WPARAM wParam, LPARAM lParam) -{ - TAB_INFO *infoPtr; - TEXTMETRICA fontMetrics; - HDC hdc; - HFONT hOldFont; - DWORD dwStyle; - - infoPtr = (TAB_INFO *)Alloc (sizeof(TAB_INFO)); - - SetWindowLongA(hwnd, 0, (DWORD)infoPtr); - - infoPtr->hwndNotify = ((LPCREATESTRUCTW)lParam)->hwndParent; - infoPtr->uNumItem = 0; - infoPtr->uNumRows = 0; - infoPtr->uHItemPadding = 6; - infoPtr->uVItemPadding = 3; - infoPtr->uHItemPadding_s = 6; - infoPtr->uVItemPadding_s = 3; - infoPtr->hFont = 0; - infoPtr->items = 0; - infoPtr->hcurArrow = LoadCursorA (0, (LPSTR)IDC_ARROW); - infoPtr->iSelected = -1; - infoPtr->iHotTracked = -1; - infoPtr->uFocus = -1; - infoPtr->hwndToolTip = 0; - infoPtr->DoRedraw = TRUE; - infoPtr->needsScrolling = FALSE; - infoPtr->hwndUpDown = 0; - infoPtr->leftmostVisible = 0; - infoPtr->fHeightSet = FALSE; - infoPtr->bUnicode = IsWindowUnicode (hwnd); - infoPtr->cbInfo = sizeof(LPARAM); - - TRACE("Created tab control, hwnd [%p]\n", hwnd); - - /* The tab control always has the WS_CLIPSIBLINGS style. Even - if you don't specify it in CreateWindow. This is necessary in - order for paint to work correctly. This follows windows behaviour. */ - dwStyle = GetWindowLongA(hwnd, GWL_STYLE); - SetWindowLongA(hwnd, GWL_STYLE, dwStyle|WS_CLIPSIBLINGS); - - if (dwStyle & TCS_TOOLTIPS) { - /* Create tooltip control */ - infoPtr->hwndToolTip = - CreateWindowExA (0, TOOLTIPS_CLASSA, NULL, 0, - CW_USEDEFAULT, CW_USEDEFAULT, - CW_USEDEFAULT, CW_USEDEFAULT, - hwnd, 0, 0, 0); - - /* Send NM_TOOLTIPSCREATED notification */ - if (infoPtr->hwndToolTip) { - NMTOOLTIPSCREATED nmttc; - - nmttc.hdr.hwndFrom = hwnd; - nmttc.hdr.idFrom = GetWindowLongPtrW(hwnd, GWLP_ID); - nmttc.hdr.code = NM_TOOLTIPSCREATED; - nmttc.hwndToolTips = infoPtr->hwndToolTip; - - SendMessageW (infoPtr->hwndNotify, WM_NOTIFY, - (WPARAM)GetWindowLongPtrW(hwnd, GWLP_ID), (LPARAM)&nmttc); - } - } - - /* - * We need to get text information so we need a DC and we need to select - * a font. - */ - hdc = GetDC(hwnd); - hOldFont = SelectObject (hdc, GetStockObject (SYSTEM_FONT)); - - /* Use the system font to determine the initial height of a tab. */ - GetTextMetricsA(hdc, &fontMetrics); - - /* - * Make sure there is enough space for the letters + growing the - * selected item + extra space for the selected item. - */ - infoPtr->tabHeight = fontMetrics.tmHeight + SELECTED_TAB_OFFSET + - ((dwStyle & TCS_BUTTONS) ? 2 : 1) * - infoPtr->uVItemPadding; - - /* Initialize the width of a tab. */ - infoPtr->tabWidth = DEFAULT_TAB_WIDTH; - infoPtr->tabMinWidth = 0; - - TRACE("tabH=%d, tabW=%d\n", infoPtr->tabHeight, infoPtr->tabWidth); - - SelectObject (hdc, hOldFont); - ReleaseDC(hwnd, hdc); - - return 0; -} - -static LRESULT -TAB_Destroy (HWND hwnd, WPARAM wParam, LPARAM lParam) -{ - TAB_INFO *infoPtr = TAB_GetInfoPtr(hwnd); - UINT iItem; - - if (!infoPtr) - return 0; - - if (infoPtr->items) { - for (iItem = 0; iItem < infoPtr->uNumItem; iItem++) { - if (TAB_GetItem(infoPtr, iItem)->pszText) - Free (TAB_GetItem(infoPtr, iItem)->pszText); - } - Free (infoPtr->items); - } - - if (infoPtr->hwndToolTip) - DestroyWindow (infoPtr->hwndToolTip); - - if (infoPtr->hwndUpDown) - DestroyWindow(infoPtr->hwndUpDown); - - if (infoPtr->iHotTracked >= 0) - KillTimer(hwnd, TAB_HOTTRACK_TIMER); - - Free (infoPtr); - SetWindowLongA(hwnd, 0, 0); - return 0; -} - -static LRESULT -TAB_SetItemExtra (HWND hwnd, WPARAM wParam, LPARAM lParam) -{ - TAB_INFO *infoPtr = TAB_GetInfoPtr(hwnd); - INT cbInfo = wParam; - - if (!infoPtr || cbInfo <= 0) - return FALSE; - - if (infoPtr->uNumItem) - { - /* FIXME: MSDN says this is not allowed, but this hasn't been verified */ - return FALSE; - } - - infoPtr->cbInfo = cbInfo; - return TRUE; -} - -static LRESULT WINAPI -TAB_WindowProc (HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam) -{ - TAB_INFO *infoPtr = TAB_GetInfoPtr(hwnd); - - TRACE("hwnd=%p msg=%x wParam=%x lParam=%lx\n", hwnd, uMsg, wParam, lParam); - if (!TAB_GetInfoPtr(hwnd) && (uMsg != WM_CREATE)) - return DefWindowProcW (hwnd, uMsg, wParam, lParam); - - switch (uMsg) - { - case TCM_GETIMAGELIST: - return TAB_GetImageList (hwnd, wParam, lParam); - - case TCM_SETIMAGELIST: - return TAB_SetImageList (hwnd, wParam, lParam); - - case TCM_GETITEMCOUNT: - return TAB_GetItemCount (hwnd, wParam, lParam); - - case TCM_GETITEMA: - case TCM_GETITEMW: - return TAB_GetItemAW (hwnd, wParam, lParam, uMsg == TCM_GETITEMW); - - case TCM_SETITEMA: - case TCM_SETITEMW: - return TAB_SetItemAW (hwnd, wParam, lParam, uMsg == TCM_SETITEMW); - - case TCM_DELETEITEM: - return TAB_DeleteItem (hwnd, wParam, lParam); - - case TCM_DELETEALLITEMS: - return TAB_DeleteAllItems (hwnd, wParam, lParam); - - case TCM_GETITEMRECT: - return TAB_GetItemRect (hwnd, wParam, lParam); - - case TCM_GETCURSEL: - return TAB_GetCurSel (hwnd); - - case TCM_HITTEST: - return TAB_HitTest (hwnd, wParam, lParam); - - case TCM_SETCURSEL: - return TAB_SetCurSel (hwnd, wParam); - - case TCM_INSERTITEMA: - case TCM_INSERTITEMW: - return TAB_InsertItemAW (hwnd, wParam, lParam, uMsg == TCM_INSERTITEMW); - - case TCM_SETITEMEXTRA: - return TAB_SetItemExtra (hwnd, wParam, lParam); - - case TCM_ADJUSTRECT: - return TAB_AdjustRect (hwnd, (BOOL)wParam, (LPRECT)lParam); - - case TCM_SETITEMSIZE: - return TAB_SetItemSize (hwnd, wParam, lParam); - - case TCM_REMOVEIMAGE: - FIXME("Unimplemented msg TCM_REMOVEIMAGE\n"); - return 0; - - case TCM_SETPADDING: - return TAB_SetPadding (hwnd, wParam, lParam); - - case TCM_GETROWCOUNT: - return TAB_GetRowCount(hwnd); - - case TCM_GETUNICODEFORMAT: - return TAB_GetUnicodeFormat (hwnd); - - case TCM_SETUNICODEFORMAT: - return TAB_SetUnicodeFormat (hwnd, wParam); - - case TCM_HIGHLIGHTITEM: - return TAB_HighlightItem (hwnd, wParam, lParam); - - case TCM_GETTOOLTIPS: - return TAB_GetToolTips (hwnd, wParam, lParam); - - case TCM_SETTOOLTIPS: - return TAB_SetToolTips (hwnd, wParam, lParam); - - case TCM_GETCURFOCUS: - return TAB_GetCurFocus (hwnd); - - case TCM_SETCURFOCUS: - return TAB_SetCurFocus (hwnd, wParam); - - case TCM_SETMINTABWIDTH: - return TAB_SetMinTabWidth(hwnd, lParam); - - case TCM_DESELECTALL: - FIXME("Unimplemented msg TCM_DESELECTALL\n"); - return 0; - - case TCM_GETEXTENDEDSTYLE: - FIXME("Unimplemented msg TCM_GETEXTENDEDSTYLE\n"); - return 0; - - case TCM_SETEXTENDEDSTYLE: - FIXME("Unimplemented msg TCM_SETEXTENDEDSTYLE\n"); - return 0; - - case WM_GETFONT: - return TAB_GetFont (hwnd, wParam, lParam); - - case WM_SETFONT: - return TAB_SetFont (hwnd, wParam, lParam); - - case WM_CREATE: - return TAB_Create (hwnd, wParam, lParam); - - case WM_NCDESTROY: - return TAB_Destroy (hwnd, wParam, lParam); - - case WM_GETDLGCODE: - return DLGC_WANTARROWS | DLGC_WANTCHARS; - - case WM_LBUTTONDOWN: - return TAB_LButtonDown (hwnd, wParam, lParam); - - case WM_LBUTTONUP: - return TAB_LButtonUp (hwnd, wParam, lParam); - - case WM_NOTIFY: - return SendMessageW(infoPtr->hwndNotify, WM_NOTIFY, wParam, lParam); - - case WM_RBUTTONDOWN: - return TAB_RButtonDown (hwnd, wParam, lParam); - - case WM_MOUSEMOVE: - return TAB_MouseMove (hwnd, wParam, lParam); - - case WM_PAINT: - return TAB_Paint (hwnd, wParam); - - case WM_SIZE: - return TAB_Size (hwnd, wParam, lParam); - - case WM_SETREDRAW: - return TAB_SetRedraw (hwnd, wParam); - - case WM_HSCROLL: - return TAB_OnHScroll(hwnd, (int)LOWORD(wParam), (int)HIWORD(wParam), (HWND)lParam); - - case WM_STYLECHANGED: - TAB_SetItemBounds (hwnd); - InvalidateRect(hwnd, NULL, TRUE); - return 0; - - case WM_SYSCOLORCHANGE: - COMCTL32_RefreshSysColors(); - return 0; - - case WM_KILLFOCUS: - case WM_SETFOCUS: - return TAB_FocusChanging(hwnd, uMsg, wParam, lParam); - - case WM_KEYUP: - return TAB_KeyUp(hwnd, wParam); - case WM_NCHITTEST: - return TAB_NCHitTest(hwnd, lParam); - - default: - if ((uMsg >= WM_USER) && (uMsg < WM_APP)) - WARN("unknown msg %04x wp=%08x lp=%08lx\n", - uMsg, wParam, lParam); - return DefWindowProcW(hwnd, uMsg, wParam, lParam); - } - - return 0; -} - - -VOID -TAB_Register (void) -{ - WNDCLASSW wndClass; - - ZeroMemory (&wndClass, sizeof(WNDCLASSW)); - wndClass.style = CS_GLOBALCLASS | CS_DBLCLKS | CS_HREDRAW | CS_VREDRAW; - wndClass.lpfnWndProc = TAB_WindowProc; - wndClass.cbClsExtra = 0; - wndClass.cbWndExtra = sizeof(TAB_INFO *); - wndClass.hCursor = LoadCursorW (0, (LPWSTR)IDC_ARROW); - wndClass.hbrBackground = (HBRUSH)(COLOR_BTNFACE+1); - wndClass.lpszClassName = WC_TABCONTROLW; - - RegisterClassW (&wndClass); -} - - -VOID -TAB_Unregister (void) -{ - UnregisterClassW (WC_TABCONTROLW, NULL); -} diff --git a/reactos/lib/comctl32/tests/Makefile b/reactos/lib/comctl32/tests/Makefile deleted file mode 100644 index 66e33be3586..00000000000 --- a/reactos/lib/comctl32/tests/Makefile +++ /dev/null @@ -1,30 +0,0 @@ -# $Id: Makefile,v 1.1 2004/11/07 14:36:23 sedwards Exp $ - -PATH_TO_TOP = ../../.. - -TARGET_NORC = yes - -TARGET_TYPE = program - -TARGET_APPTYPE = console - -# require os code to explicitly request A/W version of structs/functions -TARGET_CFLAGS += -D_DISABLE_TIDENTS -D__USE_W32API -D_WIN32_IE=0x0600 \ - -D_WIN32_WINNT=0x0501 - -TARGET_NAME = comctl32_test - -TARGET_SDKLIBS = gdi32.a comctl32.a ntdll.a - -TARGET_OBJECTS = \ - testlist.o \ - dpa.o \ - imagelist.o \ - subclass.o \ - tab.o - -include $(PATH_TO_TOP)/rules.mak - -include $(TOOLS_PATH)/helper.mk - -# EOF \ No newline at end of file diff --git a/reactos/lib/comctl32/tests/dpa.c b/reactos/lib/comctl32/tests/dpa.c deleted file mode 100644 index 66da9235b35..00000000000 --- a/reactos/lib/comctl32/tests/dpa.c +++ /dev/null @@ -1,81 +0,0 @@ -/* - * Unit tests for DPA functions - * - * Copyright 2003 Uwe Bonnes - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2.1 of the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -#include - -#include "windef.h" -#include "winbase.h" -#include "wingdi.h" -#include "winuser.h" -#include "winnls.h" -#include "commctrl.h" - -#include "wine/test.h" - -static HDPA (WINAPI *pDPA_Create)(int); -static BOOL (WINAPI *pDPA_Grow)(const HDPA hdpa, INT nGrow); -static BOOL (WINAPI *pDPA_Destroy)(const HDPA hdpa); -static BOOL (WINAPI *pDPA_SetPtr)(const HDPA hdpa, INT i, LPVOID p); - -static INT CALLBACK dpa_strcmp(LPVOID pvstr1, LPVOID pvstr2, LPARAM flags) -{ - LPCSTR str1 = (LPCSTR)pvstr1; - LPCSTR str2 = (LPCSTR)pvstr2; - - return lstrcmpA (str1, str2); -} - -void DPA_test() -{ - HDPA dpa_ret; - INT int_ret; - CHAR test_str0[]="test0"; - - if (!pDPA_Create) - return; - - dpa_ret = pDPA_Create(0); - ok((dpa_ret !=0), "DPA_Create failed\n"); - int_ret = DPA_Search(dpa_ret,test_str0,0, dpa_strcmp,0, DPAS_SORTED); - ok((int_ret == -1), "DPA_Search found invalid item\n"); - int_ret = DPA_Search(dpa_ret,test_str0,0, dpa_strcmp,0, DPAS_SORTED|DPAS_INSERTBEFORE); - ok((int_ret == 0), "DPA_Search proposed bad item\n"); - int_ret = DPA_Search(dpa_ret,test_str0,0, dpa_strcmp,0, DPAS_SORTED|DPAS_INSERTAFTER); - ok((int_ret == 0), "DPA_Search proposed bad item\n"); - int_ret = pDPA_Grow(dpa_ret,0); - ok(int_ret != 0, "DPA_Grow failed\n"); - int_ret = pDPA_SetPtr(dpa_ret, 0, (void*)0xdeadbeef); - ok(int_ret != 0, "DPA_SetPtr failed\n"); - int_ret = pDPA_Destroy(dpa_ret); - ok(int_ret != 0, "DPA_Destory failed\n"); -} - -START_TEST(dpa) -{ - HMODULE hdll; - - hdll=GetModuleHandleA("comctl32.dll"); - pDPA_Create=(void*)GetProcAddress(hdll,(LPCSTR)328); - pDPA_Destroy=(void*)GetProcAddress(hdll,(LPCSTR)329); - pDPA_Grow=(void*)GetProcAddress(hdll,(LPCSTR)330); - pDPA_SetPtr=(void*)GetProcAddress(hdll,(LPCSTR)335); - - DPA_test(); -} diff --git a/reactos/lib/comctl32/tests/imagelist.c b/reactos/lib/comctl32/tests/imagelist.c deleted file mode 100644 index c23eee8b93c..00000000000 --- a/reactos/lib/comctl32/tests/imagelist.c +++ /dev/null @@ -1,560 +0,0 @@ -/* Unit test suite for imagelist control. - * - * Copyright 2004 Michael Stefaniuc - * Copyright 2002 Mike McCormack for CodeWeavers - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2.1 of the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -#include -#include -#include -#include - -#include "wine/test.h" - -#undef VISIBLE - -#ifdef VISIBLE -#define WAIT Sleep (1000) -#define REDRAW(hwnd) RedrawWindow (hwnd, NULL, 0, RDW_UPDATENOW) -#else -#define WAIT -#define REDRAW(hwnd) -#endif - - -static BOOL (WINAPI *pImageList_DrawIndirect)(IMAGELISTDRAWPARAMS*) = NULL; - -static HDC desktopDC; -static HINSTANCE hinst; - -/* These macros build cursor/bitmap data in 4x4 pixel blocks */ -#define B(x,y) ((x?0xf0:0)|(y?0xf:0)) -#define ROW1(a,b,c,d,e,f,g,h) B(a,b),B(c,d),B(e,f),B(g,h) -#define ROW32(a,b,c,d,e,f,g,h) ROW1(a,b,c,d,e,f,g,h), ROW1(a,b,c,d,e,f,g,h), \ - ROW1(a,b,c,d,e,f,g,h), ROW1(a,b,c,d,e,f,g,h) -#define ROW2(a,b,c,d,e,f,g,h,i,j,k,l) ROW1(a,b,c,d,e,f,g,h),B(i,j),B(k,l) -#define ROW48(a,b,c,d,e,f,g,h,i,j,k,l) ROW2(a,b,c,d,e,f,g,h,i,j,k,l), \ - ROW2(a,b,c,d,e,f,g,h,i,j,k,l), ROW2(a,b,c,d,e,f,g,h,i,j,k,l), \ - ROW2(a,b,c,d,e,f,g,h,i,j,k,l) - -static const BYTE empty_bits[48*48/8]; - -static const BYTE icon_bits[32*32/8] = -{ - ROW32(0,0,0,0,0,0,0,0), - ROW32(0,0,1,1,1,1,0,0), - ROW32(0,1,1,1,1,1,1,0), - ROW32(0,1,1,0,0,1,1,0), - ROW32(0,1,1,0,0,1,1,0), - ROW32(0,1,1,1,1,1,1,0), - ROW32(0,0,1,1,1,1,0,0), - ROW32(0,0,0,0,0,0,0,0) -}; - -static const BYTE bitmap_bits[48*48/8] = -{ - ROW48(0,0,0,0,0,0,0,0,0,0,0,0), - ROW48(0,1,1,1,1,1,1,1,1,1,1,0), - ROW48(0,1,1,0,0,0,0,0,0,1,1,0), - ROW48(0,1,0,0,0,0,0,0,1,0,1,0), - ROW48(0,1,0,0,0,0,0,1,0,0,1,0), - ROW48(0,1,0,0,0,0,1,0,0,0,1,0), - ROW48(0,1,0,0,0,1,0,0,0,0,1,0), - ROW48(0,1,0,0,1,0,0,0,0,0,1,0), - ROW48(0,1,0,1,0,0,0,0,0,0,1,0), - ROW48(0,1,1,0,0,0,0,0,0,1,1,0), - ROW48(0,1,1,1,1,1,1,1,1,1,1,0), - ROW48(0,0,0,0,0,0,0,0,0,0,0,0) -}; - -static HIMAGELIST createImageList(cx, cy) -{ - /* Create an ImageList and put an image into it */ - HIMAGELIST himl = ImageList_Create(cx, cy, ILC_COLOR, 1, 1); - HBITMAP hbm = CreateBitmap(48, 48, 1, 1, bitmap_bits); - ImageList_Add(himl, hbm, NULL); - return himl; -} - -static HWND create_a_window(void) -{ - char className[] = "bmwnd"; - char winName[] = "Test Bitmap"; - HWND hWnd; - static int registered = 0; - - if (!registered) - { - WNDCLASSA cls; - - cls.style = CS_HREDRAW | CS_VREDRAW | CS_GLOBALCLASS; - cls.lpfnWndProc = DefWindowProcA; - cls.cbClsExtra = 0; - cls.cbWndExtra = 0; - cls.hInstance = 0; - cls.hIcon = LoadIconA (0, (LPSTR)IDI_APPLICATION); - cls.hCursor = LoadCursorA (0, (LPSTR)IDC_ARROW); - cls.hbrBackground = (HBRUSH) GetStockObject (WHITE_BRUSH); - cls.lpszMenuName = 0; - cls.lpszClassName = className; - - RegisterClassA (&cls); - registered = 1; - } - - /* Setup window */ - hWnd = CreateWindowA (className, winName, - WS_OVERLAPPEDWINDOW , - CW_USEDEFAULT, CW_USEDEFAULT, 300, 300, 0, - 0, hinst, 0); - -#ifdef VISIBLE - ShowWindow (hWnd, SW_SHOW); -#endif - REDRAW(hWnd); - WAIT; - - return hWnd; -} - -static HDC show_image(HWND hwnd, HIMAGELIST himl, int idx, int size, - LPCSTR loc, BOOL clear) -{ - HDC hdc = NULL; -#ifdef VISIBLE - if (!himl) return NULL; - - SetWindowText(hwnd, loc); - hdc = GetDC(hwnd); - ImageList_Draw(himl, idx, hdc, 0, 0, ILD_TRANSPARENT); - - REDRAW(hwnd); - WAIT; - - if (clear) - { - BitBlt(hdc, 0, 0, size, size, hdc, size+1, size+1, SRCCOPY); - ReleaseDC(hwnd, hdc); - hdc = NULL; - } -#endif /* VISIBLE */ - return hdc; -} - -/* Useful for checking differences */ -#if 0 -static void dump_bits(const BYTE *p, const BYTE *q, int size) -{ - int i, j; - - size /= 8; - - for (i = 0; i < size * 2; i++) - { - printf("|"); - for (j = 0; j < size; j++) - printf("%c%c", p[j] & 0xf0 ? 'X' : ' ', p[j] & 0xf ? 'X' : ' '); - printf(" -- "); - for (j = 0; j < size; j++) - printf("%c%c", q[j] & 0xf0 ? 'X' : ' ', q[j] & 0xf ? 'X' : ' '); - printf("|\n"); - p += size * 4; - q += size * 4; - } - printf("\n"); -} -#endif - -static void check_bits(HWND hwnd, HIMAGELIST himl, int idx, int size, - const BYTE *checkbits, LPCSTR loc) -{ -#ifdef VISIBLE - BYTE bits[100*100/8]; - COLORREF c; - HDC hdc; - int x, y, i = -1; - - if (!himl) return; - - memset(bits, 0, sizeof(bits)); - hdc = show_image(hwnd, himl, idx, size, loc, FALSE); - - c = GetPixel(hdc, 0, 0); - - for (y = 0; y < size; y ++) - { - for (x = 0; x < size; x++) - { - if (!(x & 0x7)) i++; - if (GetPixel(hdc, x, y) != c) bits[i] |= (0x80 >> (x & 0x7)); - } - } - - BitBlt(hdc, 0, 0, size, size, hdc, size+1, size+1, SRCCOPY); - ReleaseDC(hwnd, hdc); - - ok (memcmp(bits, checkbits, (size * size)/8) == 0, - "%s: bits different\n", loc); - if (memcmp(bits, checkbits, (size * size)/8)) - dump_bits(bits, checkbits, size); -#endif /* VISIBLE */ -} - -static void testHotspot (void) -{ - struct hotspot { - int dx; - int dy; - }; - -#define SIZEX1 47 -#define SIZEY1 31 -#define SIZEX2 11 -#define SIZEY2 17 -#define HOTSPOTS_MAX 4 /* Number of entries in hotspots */ - static const struct hotspot hotspots[HOTSPOTS_MAX] = { - { 10, 7 }, - { SIZEX1, SIZEY1 }, - { -9, -8 }, - { -7, 35 } - }; - int i, j, ret; - HIMAGELIST himl1 = createImageList(SIZEX1, SIZEY1); - HIMAGELIST himl2 = createImageList(SIZEX2, SIZEY2); - HWND hwnd = create_a_window(); - - - for (i = 0; i < HOTSPOTS_MAX; i++) { - for (j = 0; j < HOTSPOTS_MAX; j++) { - int dx1 = hotspots[i].dx; - int dy1 = hotspots[i].dy; - int dx2 = hotspots[j].dx; - int dy2 = hotspots[j].dy; - int correctx, correcty, newx, newy; - char loc[256]; - HIMAGELIST himlNew; - POINT ppt; - - ret = ImageList_BeginDrag(himl1, 0, dx1, dy1); - ok(ret != 0, "BeginDrag failed for { %d, %d }\n", dx1, dy1); - sprintf(loc, "BeginDrag (%d,%d)\n", i, j); - show_image(hwnd, himl1, 0, max(SIZEX1, SIZEY1), loc, TRUE); - - /* check merging the dragged image with a second image */ - ret = ImageList_SetDragCursorImage(himl2, 0, dx2, dy2); - ok(ret != 0, "SetDragCursorImage failed for {%d, %d}{%d, %d}\n", - dx1, dy1, dx2, dy2); - sprintf(loc, "SetDragCursorImage (%d,%d)\n", i, j); - show_image(hwnd, himl2, 0, max(SIZEX2, SIZEY2), loc, TRUE); - - /* check new hotspot, it should be the same like the old one */ - himlNew = ImageList_GetDragImage(NULL, &ppt); - ok(ppt.x == dx1 && ppt.y == dy1, - "Expected drag hotspot [%d,%d] got [%ld,%ld]\n", - dx1, dy1, ppt.x, ppt.y); - /* check size of new dragged image */ - ImageList_GetIconSize(himlNew, &newx, &newy); - correctx = max(SIZEX1, max(SIZEX2 + dx2, SIZEX1 - dx2)); - correcty = max(SIZEY1, max(SIZEY2 + dy2, SIZEY1 - dy2)); - ok(newx == correctx && newy == correcty, - "Expected drag image size [%d,%d] got [%d,%d]\n", - correctx, correcty, newx, newy); - sprintf(loc, "GetDragImage (%d,%d)\n", i, j); - show_image(hwnd, himlNew, 0, max(correctx, correcty), loc, TRUE); - ImageList_EndDrag(); - } - } -#undef SIZEX1 -#undef SIZEY1 -#undef SIZEX2 -#undef SIZEY2 -#undef HOTSPOTS_MAX - DestroyWindow(hwnd); -} - -static BOOL DoTest1(void) -{ - HIMAGELIST himl ; - - HICON hicon1 ; - HICON hicon2 ; - HICON hicon3 ; - - /* create an imagelist to play with */ - himl = ImageList_Create(84,84,0x10,0,3); - ok(himl!=0,"failed to create imagelist\n"); - - /* load the icons to add to the image list */ - hicon1 = CreateIcon(hinst, 32, 32, 1, 1, icon_bits, icon_bits); - ok(hicon1 != 0, "no hicon1\n"); - hicon2 = CreateIcon(hinst, 32, 32, 1, 1, icon_bits, icon_bits); - ok(hicon2 != 0, "no hicon2\n"); - hicon3 = CreateIcon(hinst, 32, 32, 1, 1, icon_bits, icon_bits); - ok(hicon3 != 0, "no hicon3\n"); - - /* remove when nothing exists */ - ok(!ImageList_Remove(himl,0),"removed non-existent icon\n"); - /* removing everything from an empty imagelist should succeed */ - ok(ImageList_RemoveAll(himl),"removed non-existent icon\n"); - - /* add three */ - ok(0==ImageList_AddIcon(himl, hicon1),"failed to add icon1\n"); - ok(1==ImageList_AddIcon(himl, hicon2),"failed to add icon2\n"); - ok(2==ImageList_AddIcon(himl, hicon3),"failed to add icon3\n"); - - /* remove an index out of range */ - ok(!ImageList_Remove(himl,4711),"removed non-existent icon\n"); - - /* remove three */ - ok(ImageList_Remove(himl,0),"can't remove 0\n"); - ok(ImageList_Remove(himl,0),"can't remove 0\n"); - ok(ImageList_Remove(himl,0),"can't remove 0\n"); - - /* remove one extra */ - ok(!ImageList_Remove(himl,0),"removed non-existent icon\n"); - - /* destroy it */ - ok(ImageList_Destroy(himl),"destroy imagelist failed\n"); - - /* icons should be deleted by the imagelist */ - ok(!DeleteObject(hicon1),"icon 1 wasn't deleted\n"); - ok(!DeleteObject(hicon2),"icon 2 wasn't deleted\n"); - ok(!DeleteObject(hicon3),"icon 3 wasn't deleted\n"); - - return TRUE; -} - -static BOOL DoTest2(void) -{ - HIMAGELIST himl ; - - HICON hicon1 ; - HICON hicon2 ; - HICON hicon3 ; - - /* create an imagelist to play with */ - himl = ImageList_Create(84,84,0x10,0,3); - ok(himl!=0,"failed to create imagelist\n"); - - /* load the icons to add to the image list */ - hicon1 = CreateIcon(hinst, 32, 32, 1, 1, icon_bits, icon_bits); - ok(hicon1 != 0, "no hicon1\n"); - hicon2 = CreateIcon(hinst, 32, 32, 1, 1, icon_bits, icon_bits); - ok(hicon2 != 0, "no hicon2\n"); - hicon3 = CreateIcon(hinst, 32, 32, 1, 1, icon_bits, icon_bits); - ok(hicon3 != 0, "no hicon3\n"); - - /* add three */ - ok(0==ImageList_AddIcon(himl, hicon1),"failed to add icon1\n"); - ok(1==ImageList_AddIcon(himl, hicon2),"failed to add icon2\n"); - ok(2==ImageList_AddIcon(himl, hicon3),"failed to add icon3\n"); - - /* destroy it */ - ok(ImageList_Destroy(himl),"destroy imagelist failed\n"); - - /* icons should be deleted by the imagelist */ - ok(!DeleteObject(hicon1),"icon 1 wasn't deleted\n"); - ok(!DeleteObject(hicon2),"icon 2 wasn't deleted\n"); - ok(!DeleteObject(hicon3),"icon 3 wasn't deleted\n"); - - return TRUE; -} - -static BOOL DoTest3(void) -{ - HIMAGELIST himl; - - HBITMAP hbm1; - HBITMAP hbm2; - HBITMAP hbm3; - - IMAGELISTDRAWPARAMS imldp; - HDC hdc; - HWND hwndfortest; - - if (!pImageList_DrawIndirect) - { - HMODULE hComCtl32 = LoadLibraryA("comctl32.dll"); - pImageList_DrawIndirect = (void*)GetProcAddress(hComCtl32, "ImageList_DrawIndirect"); - if (!pImageList_DrawIndirect) - { - trace("ImageList_DrawIndirect not available, skipping test\n"); - return TRUE; - } - } - - hwndfortest = create_a_window(); - hdc = GetDC(hwndfortest); - ok(hdc!=NULL, "couldn't get DC\n"); - - /* create an imagelist to play with */ - himl = ImageList_Create(48,48,0x10,0,3); - ok(himl!=0,"failed to create imagelist\n"); - - /* load the icons to add to the image list */ - hbm1 = CreateBitmap(48, 48, 1, 1, bitmap_bits); - ok(hbm1 != 0, "no bitmap 1\n"); - hbm2 = CreateBitmap(48, 48, 1, 1, bitmap_bits); - ok(hbm2 != 0, "no bitmap 2\n"); - hbm3 = CreateBitmap(48, 48, 1, 1, bitmap_bits); - ok(hbm3 != 0, "no bitmap 3\n"); - - /* add three */ - ok(0==ImageList_Add(himl, hbm1, 0),"failed to add bitmap 1\n"); - ok(1==ImageList_Add(himl, hbm2, 0),"failed to add bitmap 2\n"); - - ok(ImageList_SetImageCount(himl,3),"Setimage count failed\n"); - /*ok(2==ImageList_Add(himl, hbm3, NULL),"failed to add bitmap 3\n"); */ - ok(ImageList_Replace(himl, 2, hbm3, 0),"failed to replace bitmap 3\n"); - - memset(&imldp, 0, sizeof (imldp)); - ok(!pImageList_DrawIndirect(&imldp), "zero data succeeded!\n"); - imldp.cbSize = sizeof (imldp); - ok(!pImageList_DrawIndirect(&imldp), "zero hdc succeeded!\n"); - imldp.hdcDst = hdc; - ok(!pImageList_DrawIndirect(&imldp),"zero himl succeeded!\n"); - imldp.himl = himl; - if (!pImageList_DrawIndirect(&imldp)) - { - /* Earlier versions of native comctl32 use a smaller structure */ - imldp.cbSize -= 3 * sizeof(DWORD); - ok(pImageList_DrawIndirect(&imldp),"DrawIndirect should succeed\n"); - } - REDRAW(hwndfortest); - WAIT; - - imldp.fStyle = SRCCOPY; - imldp.rgbBk = CLR_DEFAULT; - imldp.rgbFg = CLR_DEFAULT; - imldp.y = 100; - imldp.x = 100; - ok(pImageList_DrawIndirect(&imldp),"should succeed\n"); - imldp.i ++; - ok(pImageList_DrawIndirect(&imldp),"should succeed\n"); - imldp.i ++; - ok(pImageList_DrawIndirect(&imldp),"should succeed\n"); - imldp.i ++; - ok(!pImageList_DrawIndirect(&imldp),"should fail\n"); - - /* remove three */ - ok(ImageList_Remove(himl, 0), "removing 1st bitmap\n"); - ok(ImageList_Remove(himl, 0), "removing 2nd bitmap\n"); - ok(ImageList_Remove(himl, 0), "removing 3rd bitmap\n"); - - /* destroy it */ - ok(ImageList_Destroy(himl),"destroy imagelist failed\n"); - - /* bitmaps should not be deleted by the imagelist */ - ok(DeleteObject(hbm1),"bitmap 1 can't be deleted\n"); - ok(DeleteObject(hbm2),"bitmap 2 can't be deleted\n"); - ok(DeleteObject(hbm3),"bitmap 3 can't be deleted\n"); - - ReleaseDC(hwndfortest, hdc); - DestroyWindow(hwndfortest); - - return TRUE; -} - -static void testMerge() -{ - HIMAGELIST himl1, himl2, hmerge; - HICON hicon1; - HWND hwnd = create_a_window(); - - himl1 = ImageList_Create(32,32,0,0,3); - ok(himl1 != NULL,"failed to create himl1\n"); - - himl2 = ImageList_Create(32,32,0,0,3); - ok(himl2 != NULL,"failed to create himl2\n"); - - hicon1 = CreateIcon(hinst, 32, 32, 1, 1, icon_bits, icon_bits); - ok(hicon1 != NULL, "failed to create hicon1\n"); - - if (!himl1 || !himl2 || !hicon1) - return; - - ok(0==ImageList_AddIcon(himl2, hicon1),"add icon1 to himl2 failed\n"); - check_bits(hwnd, himl2, 0, 32, icon_bits, "add icon1 to himl2"); - - /* If himl1 has no images, merge still succeeds */ - hmerge = ImageList_Merge(himl1, -1, himl2, 0, 0, 0); - ok(hmerge != NULL, "merge himl1,-1 failed\n"); - check_bits(hwnd, hmerge, 0, 32, empty_bits, "merge himl1,-1"); - if (hmerge) ImageList_Destroy(hmerge); - - hmerge = ImageList_Merge(himl1, 0, himl2, 0, 0, 0); - ok(hmerge != NULL,"merge himl1,0 failed\n"); - check_bits(hwnd, hmerge, 0, 32, empty_bits, "merge himl1,0"); - if (hmerge) ImageList_Destroy(hmerge); - - /* Same happens if himl2 is empty */ - ImageList_Destroy(himl2); - himl2 = ImageList_Create(32,32,0,0,3); - ok(himl2 != NULL,"failed to recreate himl2\n"); - if (!himl2) - return; - - hmerge = ImageList_Merge(himl1, -1, himl2, -1, 0, 0); - ok(hmerge != NULL, "merge himl2,-1 failed\n"); - check_bits(hwnd, hmerge, 0, 32, empty_bits, "merge himl2,-1"); - if (hmerge) ImageList_Destroy(hmerge); - - hmerge = ImageList_Merge(himl1, -1, himl2, 0, 0, 0); - ok(hmerge != NULL, "merge himl2,0 failed\n"); - check_bits(hwnd, hmerge, 0, 32, empty_bits, "merge himl2,0"); - if (hmerge) ImageList_Destroy(hmerge); - - /* Now try merging an image with itself */ - ok(0==ImageList_AddIcon(himl2, hicon1),"re-add icon1 to himl2 failed\n"); - - hmerge = ImageList_Merge(himl2, 0, himl2, 0, 0, 0); - ok(hmerge != NULL, "merge himl2 with itself failed\n"); - check_bits(hwnd, hmerge, 0, 32, empty_bits, "merge himl2 with itself"); - if (hmerge) ImageList_Destroy(hmerge); - - /* Try merging 2 different image lists */ - ok(0==ImageList_AddIcon(himl1, hicon1),"add icon1 to himl1 failed\n"); - - hmerge = ImageList_Merge(himl1, 0, himl2, 0, 0, 0); - ok(hmerge != NULL, "merge himl1 with himl2 failed\n"); - check_bits(hwnd, hmerge, 0, 32, empty_bits, "merge himl1 with himl2"); - if (hmerge) ImageList_Destroy(hmerge); - - hmerge = ImageList_Merge(himl1, 0, himl2, 0, 8, 16); - ok(hmerge != NULL, "merge himl1 with himl2 8,16 failed\n"); - check_bits(hwnd, hmerge, 0, 32, empty_bits, "merge himl1 with himl2, 8,16"); - if (hmerge) ImageList_Destroy(hmerge); - - ImageList_Destroy(himl1); - ImageList_Destroy(himl2); - DeleteObject(hicon1); - DestroyWindow(hwnd); -} - -START_TEST(imagelist) -{ - desktopDC=GetDC(NULL); - hinst = GetModuleHandleA(NULL); - - InitCommonControls(); - - testHotspot(); - DoTest1(); - DoTest2(); - DoTest3(); - testMerge(); -} diff --git a/reactos/lib/comctl32/tests/subclass.c b/reactos/lib/comctl32/tests/subclass.c deleted file mode 100644 index 268eed912ca..00000000000 --- a/reactos/lib/comctl32/tests/subclass.c +++ /dev/null @@ -1,298 +0,0 @@ -/* Unit tests for subclassed windows. - * - * Copyright 2004 Kevin Koltzau - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2.1 of the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -#include -#include - -#define _WIN32_WINNT 0x0501 /* For SetWindowSubclass/etc */ - -#include "windef.h" -#include "winbase.h" -#include "wingdi.h" -#include "winuser.h" -#include "commctrl.h" - -#include "wine/test.h" - -static BOOL (WINAPI *pSetWindowSubclass)(HWND, SUBCLASSPROC, UINT_PTR, DWORD_PTR); -static BOOL (WINAPI *pRemoveWindowSubclass)(HWND, SUBCLASSPROC, UINT_PTR); -static LRESULT (WINAPI *pDefSubclassProc)(HWND, UINT, WPARAM, LPARAM); - -#define SEND_NEST 0x01 -#define DELETE_SELF 0x02 -#define DELETE_PREV 0x04 - -struct message { - int procnum; /* WndProc id message is expected from */ - WPARAM wParam; /* expected value of wParam */ -}; - -static int sequence_cnt, sequence_size; -static struct message* sequence; - -static const struct message Sub_BasicTest[] = { - { 2, 1 }, - { 1, 1 }, - { 2, 2 }, - { 1, 2 }, - { 0 } -}; - -static const struct message Sub_DeletedTest[] = { - { 2, 1 }, - { 1, 1 }, - { 0 } -}; - -static const struct message Sub_AfterDeletedTest[] = { - { 1, 1 }, - { 0 } -}; - -static const struct message Sub_OldAfterNewTest[] = { - { 3, 1 }, - { 2, 1 }, - { 1, 1 }, - { 3, 2 }, - { 2, 2 }, - { 1, 2 }, - { 0 } -}; - -static const struct message Sub_MixTest[] = { - { 3, 1 }, - { 4, 1 }, - { 2, 1 }, - { 1, 1 }, - { 0 } -}; - -static const struct message Sub_MixAndNestTest[] = { - { 3, 1 }, - { 4, 1 }, - { 3, 2 }, - { 4, 2 }, - { 2, 2 }, - { 1, 2 }, - { 2, 1 }, - { 1, 1 }, - { 0 } -}; - -static const struct message Sub_MixNestDelTest[] = { - { 3, 1 }, - { 4, 1 }, - { 3, 2 }, - { 2, 2 }, - { 1, 2 }, - { 2, 1 }, - { 1, 1 }, - { 0 } -}; - -static const struct message Sub_MixDelPrevTest[] = { - { 3, 1 }, - { 5, 1 }, - { 2, 1 }, - { 1, 1 }, - { 0 } -}; - -static void add_message(const struct message *msg) -{ - if (!sequence) - { - sequence_size = 10; - sequence = HeapAlloc( GetProcessHeap(), 0, sequence_size * sizeof (struct message) ); - } - if (sequence_cnt == sequence_size) - { - sequence_size *= 2; - sequence = HeapReAlloc( GetProcessHeap(), 0, sequence, sequence_size * sizeof (struct message) ); - } - assert(sequence); - - sequence[sequence_cnt].wParam = msg->wParam; - sequence[sequence_cnt].procnum = msg->procnum; - - sequence_cnt++; -} - -static void flush_sequence() -{ - HeapFree(GetProcessHeap(), 0, sequence); - sequence = 0; - sequence_cnt = sequence_size = 0; -} - -static void ok_sequence(const struct message *expected, const char *context) -{ - static const struct message end_of_sequence = { 0, 0 }; - const struct message *actual; - - add_message(&end_of_sequence); - - actual = sequence; - - while(expected->procnum && actual->procnum) - { - ok(expected->procnum == actual->procnum, - "%s: the procnum %d was expected, but got procnum %d instead\n", - context, expected->procnum, actual->procnum); - ok(expected->wParam == actual->wParam, - "%s: in procnum %d expecting wParam 0x%x got 0x%x\n", - context, expected->procnum, expected->wParam, actual->wParam); - expected++; - actual++; - } - ok(!expected->procnum, "Received fewer messages than expected\n"); - ok(!actual->procnum, "Received more messages than expected\n"); - flush_sequence(); -} - -static LRESULT WINAPI WndProc1(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam) -{ - struct message msg; - - if(message == WM_USER) { - msg.wParam = wParam; - msg.procnum = 1; - add_message(&msg); - } - return DefWindowProc(hwnd, message, wParam, lParam); -} - - -static WNDPROC origProc3; -static LRESULT WINAPI WndProc3(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam) -{ - struct message msg; - - if(message == WM_USER) { - msg.wParam = wParam; - msg.procnum = 3; - add_message(&msg); - } - return CallWindowProc(origProc3, hwnd, message, wParam, lParam); -} - -static LRESULT WINAPI WndProcSub(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam, UINT_PTR uldSubclass, DWORD_PTR dwRefData) -{ - struct message msg; - - if(message == WM_USER) { - msg.wParam = wParam; - msg.procnum = uldSubclass; - add_message(&msg); - - if(lParam) { - if(dwRefData & DELETE_SELF) { - pRemoveWindowSubclass(hwnd, WndProcSub, uldSubclass); - pRemoveWindowSubclass(hwnd, WndProcSub, uldSubclass); - } - if(dwRefData & DELETE_PREV) - pRemoveWindowSubclass(hwnd, WndProcSub, uldSubclass-1); - if(dwRefData & SEND_NEST) - SendMessage(hwnd, WM_USER, wParam+1, 0); - } - } - return pDefSubclassProc(hwnd, message, wParam, lParam); -} - -static void test_subclass() -{ - HWND hwnd = CreateWindowExA(0, "TestSubclass", "Test subclass", WS_OVERLAPPEDWINDOW, - 100, 100, 200, 200, 0, 0, 0, NULL); - assert(hwnd); - - pSetWindowSubclass(hwnd, WndProcSub, 2, 0); - SendMessage(hwnd, WM_USER, 1, 0); - SendMessage(hwnd, WM_USER, 2, 0); - ok_sequence(Sub_BasicTest, "Basic"); - - pSetWindowSubclass(hwnd, WndProcSub, 2, DELETE_SELF); - SendMessage(hwnd, WM_USER, 1, 1); - ok_sequence(Sub_DeletedTest, "Deleted"); - - SendMessage(hwnd, WM_USER, 1, 0); - ok_sequence(Sub_AfterDeletedTest, "After Deleted"); - - pSetWindowSubclass(hwnd, WndProcSub, 2, 0); - origProc3 = (WNDPROC)SetWindowLong(hwnd, GWL_WNDPROC, (LONG)WndProc3); - SendMessage(hwnd, WM_USER, 1, 0); - SendMessage(hwnd, WM_USER, 2, 0); - ok_sequence(Sub_OldAfterNewTest, "Old after New"); - - pSetWindowSubclass(hwnd, WndProcSub, 4, 0); - SendMessage(hwnd, WM_USER, 1, 0); - ok_sequence(Sub_MixTest, "Mix"); - - /* Now the fun starts */ - pSetWindowSubclass(hwnd, WndProcSub, 4, SEND_NEST); - SendMessage(hwnd, WM_USER, 1, 1); - ok_sequence(Sub_MixAndNestTest, "Mix and nest"); - - pSetWindowSubclass(hwnd, WndProcSub, 4, SEND_NEST | DELETE_SELF); - SendMessage(hwnd, WM_USER, 1, 1); - ok_sequence(Sub_MixNestDelTest, "Mix, nest, del"); - - pSetWindowSubclass(hwnd, WndProcSub, 4, 0); - pSetWindowSubclass(hwnd, WndProcSub, 5, DELETE_PREV); - SendMessage(hwnd, WM_USER, 1, 1); - ok_sequence(Sub_MixDelPrevTest, "Mix and del prev"); - - DestroyWindow(hwnd); -} - -static BOOL RegisterWindowClasses(void) -{ - WNDCLASSA cls; - - cls.style = 0; - cls.lpfnWndProc = WndProc1; - cls.cbClsExtra = 0; - cls.cbWndExtra = 0; - cls.hInstance = GetModuleHandleA(0); - cls.hIcon = 0; - cls.hCursor = NULL; - cls.hbrBackground = NULL; - cls.lpszMenuName = NULL; - cls.lpszClassName = "TestSubclass"; - if(!RegisterClassA(&cls)) return FALSE; - - return TRUE; -} - -START_TEST(subclass) -{ - HMODULE hdll; - - hdll = GetModuleHandleA("comctl32.dll"); - assert(hdll); - pSetWindowSubclass = (void*)GetProcAddress(hdll, "SetWindowSubclass"); - pRemoveWindowSubclass = (void*)GetProcAddress(hdll, "RemoveWindowSubclass"); - pDefSubclassProc = (void*)GetProcAddress(hdll, "DefSubclassProc"); - - if(!pSetWindowSubclass || !pRemoveWindowSubclass || !pDefSubclassProc) - return; - - if(!RegisterWindowClasses()) assert(0); - - test_subclass(); -} diff --git a/reactos/lib/comctl32/tests/tab.c b/reactos/lib/comctl32/tests/tab.c deleted file mode 100644 index 23234d3b6d1..00000000000 --- a/reactos/lib/comctl32/tests/tab.c +++ /dev/null @@ -1,197 +0,0 @@ -/* Unit test suite for tab control. - * - * Copyright 2003 Vitaliy Margolen - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2.1 of the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -#include -#include -#include - -#include "wine/test.h" - -#undef VISIBLE - -#define TAB_DEFAULT_WIDTH 96 -#define TAB_PADDING_X 2 -#define TAB_PADDING_Y 2 - -#ifdef VISIBLE -#define WAIT Sleep (1000) -#define REDRAW(hwnd) RedrawWindow (hwnd, NULL, 0, RDW_UPDATENOW) -#define trace_tab(str) trace(str) -#else -#define WAIT -#define REDRAW(hwnd) -#define trace_tab(str) -#endif - -HWND -create_tabcontrol (DWORD style) -{ - HWND handle; - TCITEM tcNewTab; - - handle = CreateWindow ( - WC_TABCONTROLA, - "TestTab", - WS_CLIPSIBLINGS | WS_CLIPCHILDREN | TCS_FOCUSNEVER | style, - 10, 10, 300, 100, - NULL, NULL, NULL, 0); - - assert (handle); - - SetWindowLong(handle, GWL_STYLE, WS_CLIPSIBLINGS | WS_CLIPCHILDREN | TCS_FOCUSNEVER | style); - - tcNewTab.mask = TCIF_TEXT | TCIF_IMAGE; - tcNewTab.pszText = "Tab 1"; - tcNewTab.iImage = 0; - SendMessage (handle, TCM_INSERTITEM, 0, (LPARAM) &tcNewTab); - tcNewTab.pszText = "Wide Tab 2"; - tcNewTab.iImage = 1; - SendMessage (handle, TCM_INSERTITEM, 1, (LPARAM) &tcNewTab); - tcNewTab.pszText = "T 3"; - tcNewTab.iImage = 2; - SendMessage (handle, TCM_INSERTITEM, 2, (LPARAM) &tcNewTab); - -#ifdef VISIBLE - ShowWindow (handle, SW_SHOW); -#endif - REDRAW(handle); - WAIT; - - return handle; -} - -void CheckSize(HWND hwnd, INT width, INT height) -{ - RECT rTab, r1; - - r1.left=r1.top=r1.right=r1.bottom=0; - SendMessage (hwnd, TCM_GETITEMRECT, 0, (LPARAM) &rTab); - SendMessage (hwnd, TCM_ADJUSTRECT, FALSE, (LPARAM) &r1); - /* trace ("Got (%ld,%ld)-(%ld,%ld)\n", rTab.left, rTab.top, rTab.right, rTab.bottom); */ - trace (" (%ld,%ld)-(%ld,%ld)\n", r1.left, r1.top, r1.right, r1.bottom); - if ((width >= 0) && (height < 0)) - ok (width == rTab.right - rTab.left, "Expected [%d] got [%ld]\n", width, rTab.right - rTab.left); - else if ((height >= 0) && (width < 0)) - ok (height == rTab.bottom - rTab.top, "Expected [%d] got [%ld]\n", height, rTab.bottom - rTab.top); - else - ok ((width == rTab.right - rTab.left) && - (height == rTab.bottom - rTab.top ), - "Expected [%d,%d] got [%ld,%ld]\n", width, height, rTab.right - rTab.left, rTab.bottom - rTab.top); -} - -void TabCheckSetSize(HWND hwnd, INT SetWidth, INT SetHeight, INT ExpWidth, INT ExpHeight) -{ - SendMessage (hwnd, TCM_SETITEMSIZE, 0, - (LPARAM) MAKELPARAM((SetWidth >= 0) ? SetWidth:0, (SetHeight >= 0) ? SetHeight:0)); - REDRAW(hwnd); - CheckSize(hwnd, ExpWidth, ExpHeight); - WAIT; -} - -START_TEST(tab) -{ - HWND hwTab; - HIMAGELIST himl = ImageList_Create(21, 21, ILC_COLOR, 3, 4); - - InitCommonControls(); - - - hwTab = create_tabcontrol(TCS_FIXEDWIDTH); - - trace_tab ("Testing TCS_FIXEDWIDTH tabs no icon...\n"); - trace_tab (" default width...\n"); - CheckSize(hwTab, TAB_DEFAULT_WIDTH, -1); - trace_tab (" set size...\n"); - TabCheckSetSize(hwTab, 50, 20, 50, 20); - WAIT; - trace_tab (" min size...\n"); - TabCheckSetSize(hwTab, 0, 1, 0, 1); - WAIT; - - SendMessage(hwTab, TCM_SETIMAGELIST, 0, (LPARAM)himl); - - trace_tab ("Testing TCS_FIXEDWIDTH tabs with icon...\n"); - trace_tab (" set size > icon...\n"); - TabCheckSetSize(hwTab, 50, 30, 50, 30); - trace_tab (" set size < icon...\n"); - TabCheckSetSize(hwTab, 20, 20, 25, 20); - trace_tab (" min size...\n"); - TabCheckSetSize(hwTab, 0, 1, 25, 1); - - DestroyWindow (hwTab); - - trace_tab ("Testing TCS_FIXEDWIDTH buttons no icon...\n"); - hwTab = create_tabcontrol(TCS_FIXEDWIDTH | TCS_BUTTONS); - - trace_tab (" default width...\n"); - CheckSize(hwTab, TAB_DEFAULT_WIDTH, -1); - trace_tab (" set size 1...\n"); - TabCheckSetSize(hwTab, 20, 20, 20, 20); - trace_tab (" set size 2...\n"); - TabCheckSetSize(hwTab, 10, 50, 10, 50); - trace_tab (" min size...\n"); - TabCheckSetSize(hwTab, 0, 1, 0, 1); - - SendMessage(hwTab, TCM_SETIMAGELIST, 0, (LPARAM)himl); - - trace_tab ("Testing TCS_FIXEDWIDTH buttons with icon...\n"); - trace_tab (" set size > icon...\n"); - TabCheckSetSize(hwTab, 50, 30, 50, 30); - trace_tab (" set size < icon...\n"); - TabCheckSetSize(hwTab, 20, 20, 25, 20); - trace_tab (" min size...\n"); - TabCheckSetSize(hwTab, 0, 1, 25, 1); - trace_tab (" Add padding...\n"); - SendMessage(hwTab, TCM_SETPADDING, 0, MAKELPARAM(4,4)); - trace_tab (" min size...\n"); - TabCheckSetSize(hwTab, 0, 1, 25, 1); - - DestroyWindow (hwTab); - - hwTab = create_tabcontrol(TCS_FIXEDWIDTH | TCS_BOTTOM); - trace_tab ("Testing TCS_FIXEDWIDTH | TCS_BOTTOM tabs no icon...\n"); - - trace_tab (" default width...\n"); - CheckSize(hwTab, TAB_DEFAULT_WIDTH, -1); - trace_tab (" set size 1...\n"); - TabCheckSetSize(hwTab, 20, 20, 20, 20); - trace_tab (" set size 2...\n"); - TabCheckSetSize(hwTab, 10, 50, 10, 50); - trace_tab (" min size...\n"); - TabCheckSetSize(hwTab, 0, 1, 0, 1); - - SendMessage(hwTab, TCM_SETIMAGELIST, 0, (LPARAM)himl); - - trace_tab ("Testing TCS_FIXEDWIDTH | TCS_BOTTOM tabs with icon...\n"); - trace_tab (" set size > icon...\n"); - TabCheckSetSize(hwTab, 50, 30, 50, 30); - trace_tab (" set size < icon...\n"); - TabCheckSetSize(hwTab, 20, 20, 25, 20); - trace_tab (" min size...\n"); - TabCheckSetSize(hwTab, 0, 1, 25, 1); - trace_tab (" Add padding...\n"); - SendMessage(hwTab, TCM_SETPADDING, 0, MAKELPARAM(4,4)); - trace_tab (" min size...\n"); - TabCheckSetSize(hwTab, 0, 1, 25, 1); - - DestroyWindow (hwTab); - - - ImageList_Destroy(himl); -} diff --git a/reactos/lib/comctl32/tests/testlist.c b/reactos/lib/comctl32/tests/testlist.c deleted file mode 100644 index c8bcc6f3b4d..00000000000 --- a/reactos/lib/comctl32/tests/testlist.c +++ /dev/null @@ -1,31 +0,0 @@ -/* Automatically generated file; DO NOT EDIT!! */ - -/* stdarg.h is needed for Winelib */ -#include -#include -#include -#include "windef.h" -#include "winbase.h" - -extern void func_dpa(void); -extern void func_imagelist(void); -extern void func_subclass(void); -extern void func_tab(void); - -struct test -{ - const char *name; - void (*func)(void); -}; - -static const struct test winetest_testlist[] = -{ - { "dpa", func_dpa }, - { "imagelist", func_imagelist }, - { "subclass", func_subclass }, - { "tab", func_tab }, - { 0, 0 } -}; - -#define WINETEST_WANT_MAIN -#include "wine/test.h" diff --git a/reactos/lib/comctl32/toolbar.c b/reactos/lib/comctl32/toolbar.c deleted file mode 100644 index ebd7f8df388..00000000000 --- a/reactos/lib/comctl32/toolbar.c +++ /dev/null @@ -1,7254 +0,0 @@ -/* - * Toolbar control - * - * Copyright 1998,1999 Eric Kohl - * Copyright 2000 Eric Kohl for CodeWeavers - * Copyright 2004 Robert Shearman - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2.1 of the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - * - * NOTES - * - * Differences between MSDN and actual native control operation: - * 1. MSDN says: "TBSTYLE_LIST: Creates a flat toolbar with button text - * to the right of the bitmap. Otherwise, this style is - * identical to TBSTYLE_FLAT." - * As implemented by both v4.71 and v5.80 of the native COMCTL32.DLL - * you can create a TBSTYLE_LIST without TBSTYLE_FLAT and the result - * is non-flat non-transparent buttons. Therefore TBSTYLE_LIST does - * *not* imply TBSTYLE_FLAT as documented. (GA 8/2001) - * - * This code was audited for completeness against the documented features - * of Comctl32.dll version 6.0 on Mar. 14, 2004, by Robert Shearman. - * - * Unless otherwise noted, we believe this code to be complete, as per - * the specification mentioned above. - * If you discover missing features or bugs please note them below. - * - * TODO: - * - Styles: - * - TBSTYLE_REGISTERDROP - * - TBSTYLE_EX_DOUBLEBUFFER - * - Messages: - * - TB_GETMETRICS - * - TB_GETOBJECT - * - TB_INSERTMARKHITTEST - * - TB_SAVERESTORE - * - TB_SETMETRICS - * - WM_WININICHANGE - * - Notifications: - * - NM_CHAR - * - NM_KEYDOWN - * - TBN_GETOBJECT - * - TBN_SAVE - * - Button wrapping (under construction). - * - Fix TB_SETROWS. - * - iListGap custom draw support. - * - * Testing: - * - Run tests using Waite Group Windows95 API Bible Volume 2. - * The second cdrom contains executables addstr.exe, btncount.exe, - * btnstate.exe, butstrsz.exe, chkbtn.exe, chngbmp.exe, customiz.exe, - * enablebtn.exe, getbmp.exe, getbtn.exe, getflags.exe, hidebtn.exe, - * indetbtn.exe, insbtn.exe, pressbtn.exe, setbtnsz.exe, setcmdid.exe, - * setparnt.exe, setrows.exe, toolwnd.exe. - * - Microsofts controlspy examples. - * - Charles Petzold's 'Programming Windows': gadgets.exe - */ - -#include -#include - -#include "windef.h" -#include "winbase.h" -#include "winreg.h" -#include "wingdi.h" -#include "winuser.h" -#include "wine/unicode.h" -#include "winnls.h" -#include "commctrl.h" -#include "comctl32.h" -#include "wine/debug.h" - -WINE_DEFAULT_DEBUG_CHANNEL(toolbar); - -static HCURSOR hCursorDrag = NULL; - -typedef struct -{ - INT iBitmap; - INT idCommand; - BYTE fsState; - BYTE fsStyle; - BYTE bHot; - BYTE bDropDownPressed; - DWORD dwData; - INT iString; - INT nRow; - RECT rect; - INT cx; /* manually set size */ -} TBUTTON_INFO; - -typedef struct -{ - UINT nButtons; - HINSTANCE hInst; - UINT nID; -} TBITMAP_INFO; - -typedef struct -{ - HIMAGELIST himl; - INT id; -} IMLENTRY, *PIMLENTRY; - -typedef struct -{ - DWORD dwStructSize; /* size of TBBUTTON struct */ - INT nHeight; /* height of the toolbar */ - INT nWidth; /* width of the toolbar */ - RECT client_rect; - RECT rcBound; /* bounding rectangle */ - INT nButtonHeight; - INT nButtonWidth; - INT nBitmapHeight; - INT nBitmapWidth; - INT nIndent; - INT nRows; /* number of button rows */ - INT nMaxTextRows; /* maximum number of text rows */ - INT cxMin; /* minimum button width */ - INT cxMax; /* maximum button width */ - INT nNumButtons; /* number of buttons */ - INT nNumBitmaps; /* number of bitmaps */ - INT nNumStrings; /* number of strings */ - INT nNumBitmapInfos; - INT nButtonDown; /* toolbar button being pressed or -1 if none */ - INT nButtonDrag; /* toolbar button being dragged or -1 if none */ - INT nOldHit; - INT nHotItem; /* index of the "hot" item */ - DWORD dwBaseCustDraw; /* CDRF_ response (w/o TBCDRF_) from PREPAINT */ - DWORD dwItemCustDraw; /* CDRF_ response (w/o TBCDRF_) from ITEMPREP */ - DWORD dwItemCDFlag; /* TBCDRF_ flags from last ITEMPREPAINT */ - SIZE szPadding; /* padding values around button */ - INT iListGap; /* default gap between text and image for toolbar with list style */ - HFONT hDefaultFont; - HFONT hFont; /* text font */ - HIMAGELIST himlInt; /* image list created internally */ - PIMLENTRY *himlDef; /* default image list array */ - INT cimlDef; /* default image list array count */ - PIMLENTRY *himlHot; /* hot image list array */ - INT cimlHot; /* hot image list array count */ - PIMLENTRY *himlDis; /* disabled image list array */ - INT cimlDis; /* disabled image list array count */ - HWND hwndToolTip; /* handle to tool tip control */ - HWND hwndNotify; /* handle to the window that gets notifications */ - HWND hwndSelf; /* my own handle */ - BOOL bBtnTranspnt; /* button transparency flag */ - BOOL bAutoSize; /* auto size deadlock indicator */ - BOOL bAnchor; /* anchor highlight enabled */ - BOOL bDoRedraw; /* Redraw status */ - BOOL bDragOutSent; /* has TBN_DRAGOUT notification been sent for this drag? */ - BOOL bUnicode; /* Notifications are ASCII (FALSE) or Unicode (TRUE)? */ - BOOL bCaptured; /* mouse captured? */ - DWORD dwStyle; /* regular toolbar style */ - DWORD dwExStyle; /* extended toolbar style */ - DWORD dwDTFlags; /* DrawText flags */ - - COLORREF clrInsertMark; /* insert mark color */ - COLORREF clrBtnHighlight; /* color for Flat Separator */ - COLORREF clrBtnShadow; /* color for Flag Separator */ - INT iVersion; - LPWSTR pszTooltipText; /* temporary store for a string > 80 characters - * for TTN_GETDISPINFOW notification */ - TBINSERTMARK tbim; /* info on insertion mark */ - TBUTTON_INFO *buttons; /* pointer to button array */ - LPWSTR *strings; /* pointer to string array */ - TBITMAP_INFO *bitmaps; -} TOOLBAR_INFO, *PTOOLBAR_INFO; - - -/* used by customization dialog */ -typedef struct -{ - PTOOLBAR_INFO tbInfo; - HWND tbHwnd; -} CUSTDLG_INFO, *PCUSTDLG_INFO; - -typedef struct -{ - TBBUTTON btn; - BOOL bVirtual; - BOOL bRemovable; - WCHAR text[64]; -} CUSTOMBUTTON, *PCUSTOMBUTTON; - -typedef enum -{ - IMAGE_LIST_DEFAULT, - IMAGE_LIST_HOT, - IMAGE_LIST_DISABLED -} IMAGE_LIST_TYPE; - -#define SEPARATOR_WIDTH 8 -#define TOP_BORDER 2 -#define BOTTOM_BORDER 2 -#define DDARROW_WIDTH 11 -#define ARROW_HEIGHT 3 -#define INSERTMARK_WIDTH 2 - -#define DEFPAD_CX 7 -#define DEFPAD_CY 6 - -/* gap between border of button and text/image */ -#define OFFSET_X 1 -#define OFFSET_Y 1 -/* how wide to treat the bitmap if it isn't present */ -#define LIST_IMAGE_ABSENT_WIDTH 2 - -#define TOOLBAR_NOWHERE (-1) - -#define TOOLBAR_GetInfoPtr(hwnd) ((TOOLBAR_INFO *)GetWindowLongPtrW(hwnd,0)) -#define TOOLBAR_HasText(x, y) (TOOLBAR_GetText(x, y) ? TRUE : FALSE) -#define TOOLBAR_HasDropDownArrows(exStyle) ((exStyle & TBSTYLE_EX_DRAWDDARROWS) ? TRUE : FALSE) - -static inline int TOOLBAR_GetListTextOffset(TOOLBAR_INFO *infoPtr, INT iListGap) -{ - return GetSystemMetrics(SM_CXEDGE) + iListGap - infoPtr->szPadding.cx/2; -} - -/* Used to find undocumented extended styles */ -#define TBSTYLE_EX_ALL (TBSTYLE_EX_DRAWDDARROWS | \ - TBSTYLE_EX_UNDOC1 | \ - TBSTYLE_EX_MIXEDBUTTONS | \ - TBSTYLE_EX_HIDECLIPPEDBUTTONS) - -/* all of the CCS_ styles */ -#define COMMON_STYLES (CCS_TOP|CCS_NOMOVEY|CCS_BOTTOM|CCS_NORESIZE| \ - CCS_NOPARENTALIGN|CCS_ADJUSTABLE|CCS_NODIVIDER|CCS_VERT) - -#define GETIBITMAP(infoPtr, i) (infoPtr->iVersion >= 5 ? LOWORD(i) : i) -#define GETHIMLID(infoPtr, i) (infoPtr->iVersion >= 5 ? HIWORD(i) : 0) -#define GETDEFIMAGELIST(infoPtr, id) TOOLBAR_GetImageList(infoPtr->himlDef, infoPtr->cimlDef, id) -#define GETHOTIMAGELIST(infoPtr, id) TOOLBAR_GetImageList(infoPtr->himlHot, infoPtr->cimlHot, id) -#define GETDISIMAGELIST(infoPtr, id) TOOLBAR_GetImageList(infoPtr->himlDis, infoPtr->cimlDis, id) - -static BOOL TOOLBAR_GetButtonInfo(TOOLBAR_INFO *infoPtr, NMTOOLBARW *nmtb); -static BOOL TOOLBAR_IsButtonRemovable(TOOLBAR_INFO *infoPtr, int iItem, PCUSTOMBUTTON btnInfo); -static HIMAGELIST TOOLBAR_GetImageList(PIMLENTRY *pies, INT cies, INT id); -static PIMLENTRY TOOLBAR_GetImageListEntry(PIMLENTRY *pies, INT cies, INT id); -static VOID TOOLBAR_DeleteImageList(PIMLENTRY **pies, INT *cies); -static HIMAGELIST TOOLBAR_InsertImageList(PIMLENTRY **pies, INT *cies, HIMAGELIST himl, INT id); -static LRESULT TOOLBAR_LButtonDown(HWND hwnd, WPARAM wParam, LPARAM lParam); -static void TOOLBAR_SetHotItemEx (TOOLBAR_INFO *infoPtr, INT nHit, DWORD dwReason); - -static LRESULT -TOOLBAR_NotifyFormat(TOOLBAR_INFO *infoPtr, WPARAM wParam, LPARAM lParam); - - -static LPWSTR -TOOLBAR_GetText(TOOLBAR_INFO *infoPtr, TBUTTON_INFO *btnPtr) -{ - LPWSTR lpText = NULL; - - /* NOTE: iString == -1 is undocumented */ - if ((HIWORD(btnPtr->iString) != 0) && (btnPtr->iString != -1)) - lpText = (LPWSTR)btnPtr->iString; - else if ((btnPtr->iString >= 0) && (btnPtr->iString < infoPtr->nNumStrings)) - lpText = infoPtr->strings[btnPtr->iString]; - - return lpText; -} - -static void -TOOLBAR_DumpButton(TOOLBAR_INFO *infoPtr, TBUTTON_INFO *bP, INT btn_num, BOOL internal) -{ - if (TRACE_ON(toolbar)){ - TRACE("button %d id %d, bitmap=%d, state=%02x, style=%02x, data=%08lx, stringid=0x%08x\n", - btn_num, bP->idCommand, GETIBITMAP(infoPtr, bP->iBitmap), - bP->fsState, bP->fsStyle, bP->dwData, bP->iString); - TRACE("string %s\n", debugstr_w(TOOLBAR_GetText(infoPtr,bP))); - if (internal) - TRACE("button %d id %d, hot=%s, row=%d, rect=(%ld,%ld)-(%ld,%ld)\n", - btn_num, bP->idCommand, - (bP->bHot) ? "TRUE":"FALSE", bP->nRow, - bP->rect.left, bP->rect.top, - bP->rect.right, bP->rect.bottom); - } -} - - -static void -TOOLBAR_DumpToolbar(TOOLBAR_INFO *iP, INT line) -{ - if (TRACE_ON(toolbar)) { - INT i; - - TRACE("toolbar %p at line %d, exStyle=%08lx, buttons=%d, bitmaps=%d, strings=%d, style=%08lx\n", - iP->hwndSelf, line, - iP->dwExStyle, iP->nNumButtons, iP->nNumBitmaps, - iP->nNumStrings, iP->dwStyle); - TRACE("toolbar %p at line %d, himlInt=%p, himlDef=%p, himlHot=%p, himlDis=%p, redrawable=%s\n", - iP->hwndSelf, line, - iP->himlInt, iP->himlDef, iP->himlHot, iP->himlDis, - (iP->bDoRedraw) ? "TRUE" : "FALSE"); - for(i=0; inNumButtons; i++) { - TOOLBAR_DumpButton(iP, &iP->buttons[i], i, TRUE); - } - } -} - - -/*********************************************************************** -* TOOLBAR_CheckStyle -* -* This function validates that the styles set are implemented and -* issues FIXME's warning of possible problems. In a perfect world this -* function should be null. -*/ -static void -TOOLBAR_CheckStyle (HWND hwnd, DWORD dwStyle) -{ - if (dwStyle & TBSTYLE_REGISTERDROP) - FIXME("[%p] TBSTYLE_REGISTERDROP not implemented\n", hwnd); -} - - -static INT -TOOLBAR_SendNotify (NMHDR *nmhdr, TOOLBAR_INFO *infoPtr, UINT code) -{ - if(!IsWindow(infoPtr->hwndSelf)) - return 0; /* we have just been destroyed */ - - nmhdr->idFrom = GetDlgCtrlID (infoPtr->hwndSelf); - nmhdr->hwndFrom = infoPtr->hwndSelf; - nmhdr->code = code; - - TRACE("to window %p, code=%08x, %s\n", infoPtr->hwndNotify, code, - (infoPtr->bUnicode) ? "via Unicode" : "via ANSI"); - - return SendMessageW(infoPtr->hwndNotify, WM_NOTIFY, - (WPARAM)nmhdr->idFrom, (LPARAM)nmhdr); -} - -/*********************************************************************** -* TOOLBAR_GetBitmapIndex -* -* This function returns the bitmap index associated with a button. -* If the button specifies I_IMAGECALLBACK, then the TBN_GETDISPINFO -* is issued to retrieve the index. -*/ -static INT -TOOLBAR_GetBitmapIndex(TOOLBAR_INFO *infoPtr, TBUTTON_INFO *btnPtr) -{ - INT ret = btnPtr->iBitmap; - - if (ret == I_IMAGECALLBACK) - { - /* issue TBN_GETDISPINFO */ - NMTBDISPINFOA nmgd; - - memset(&nmgd, 0, sizeof(nmgd)); - nmgd.idCommand = btnPtr->idCommand; - nmgd.lParam = btnPtr->dwData; - nmgd.dwMask = TBNF_IMAGE; - TOOLBAR_SendNotify(&nmgd.hdr, infoPtr, - infoPtr->bUnicode ? TBN_GETDISPINFOW : TBN_GETDISPINFOA); - if (nmgd.dwMask & TBNF_DI_SETITEM) - btnPtr->iBitmap = nmgd.iImage; - ret = nmgd.iImage; - TRACE("TBN_GETDISPINFO returned bitmap id %d, mask=%08lx, nNumBitmaps=%d\n", - ret, nmgd.dwMask, infoPtr->nNumBitmaps); - } - - if (ret != I_IMAGENONE) - ret = GETIBITMAP(infoPtr, ret); - - return ret; -} - - -static BOOL -TOOLBAR_IsValidBitmapIndex(TOOLBAR_INFO *infoPtr, INT index) -{ - HIMAGELIST himl; - INT id = GETHIMLID(infoPtr, index); - INT iBitmap = GETIBITMAP(infoPtr, index); - - if (((himl = GETDEFIMAGELIST(infoPtr, id)) && - iBitmap >= 0 && iBitmap < ImageList_GetImageCount(himl)) || - (index == I_IMAGECALLBACK)) - return TRUE; - else - return FALSE; -} - - -/*********************************************************************** -* TOOLBAR_GetImageListForDrawing -* -* This function validates the bitmap index (including I_IMAGECALLBACK -* functionality) and returns the corresponding image list. -*/ -static HIMAGELIST -TOOLBAR_GetImageListForDrawing (TOOLBAR_INFO *infoPtr, TBUTTON_INFO *btnPtr, IMAGE_LIST_TYPE imagelist, INT * index) -{ - HIMAGELIST himl; - - if (!TOOLBAR_IsValidBitmapIndex(infoPtr,btnPtr->iBitmap)) { - if (btnPtr->iBitmap == I_IMAGENONE) return NULL; - ERR("bitmap for ID %d, index %d is not valid, number of bitmaps in imagelist: %d\n", - HIWORD(btnPtr->iBitmap), LOWORD(btnPtr->iBitmap), infoPtr->nNumBitmaps); - return NULL; - } - - if ((*index = TOOLBAR_GetBitmapIndex(infoPtr, btnPtr)) < 0) { - if ((*index == I_IMAGECALLBACK) || - (*index == I_IMAGENONE)) return NULL; - ERR("TBN_GETDISPINFO returned invalid index %d\n", - *index); - return NULL; - } - - switch(imagelist) - { - case IMAGE_LIST_DEFAULT: - himl = GETDEFIMAGELIST(infoPtr, GETHIMLID(infoPtr, btnPtr->iBitmap)); - break; - case IMAGE_LIST_HOT: - himl = GETHOTIMAGELIST(infoPtr, GETHIMLID(infoPtr, btnPtr->iBitmap)); - break; - case IMAGE_LIST_DISABLED: - himl = GETDISIMAGELIST(infoPtr, GETHIMLID(infoPtr, btnPtr->iBitmap)); - break; - default: - himl = NULL; - FIXME("Shouldn't reach here\n"); - } - - if (!himl) - TRACE("no image list\n"); - - return himl; -} - - -/*********************************************************************** -* TOOLBAR_TestImageExist -* -* This function is similar to TOOLBAR_GetImageListForDrawing, except it does not -* return the image list. The I_IMAGECALLBACK functionality is implemented. -*/ -static BOOL -TOOLBAR_TestImageExist (TOOLBAR_INFO *infoPtr, TBUTTON_INFO *btnPtr, HIMAGELIST himl) -{ - INT index; - - if (!himl) return FALSE; - - if (!TOOLBAR_IsValidBitmapIndex(infoPtr,btnPtr->iBitmap)) { - if (btnPtr->iBitmap == I_IMAGENONE) return FALSE; - ERR("index %d is not valid, max %d\n", - btnPtr->iBitmap, infoPtr->nNumBitmaps); - return FALSE; - } - - if ((index = TOOLBAR_GetBitmapIndex(infoPtr, btnPtr)) < 0) { - if ((index == I_IMAGECALLBACK) || - (index == I_IMAGENONE)) return FALSE; - ERR("TBN_GETDISPINFO returned invalid index %d\n", - index); - return FALSE; - } - return TRUE; -} - - -static void -TOOLBAR_DrawFlatSeparator (LPRECT lpRect, HDC hdc, TOOLBAR_INFO *infoPtr) -{ - RECT myrect; - COLORREF oldcolor, newcolor; - - myrect.left = (lpRect->left + lpRect->right) / 2 - 1; - myrect.right = myrect.left + 1; - myrect.top = lpRect->top + 2; - myrect.bottom = lpRect->bottom - 2; - - newcolor = (infoPtr->clrBtnShadow == CLR_DEFAULT) ? - comctl32_color.clrBtnShadow : infoPtr->clrBtnShadow; - oldcolor = SetBkColor (hdc, newcolor); - ExtTextOutA (hdc, 0, 0, ETO_OPAQUE, &myrect, 0, 0, 0); - - myrect.left = myrect.right; - myrect.right = myrect.left + 1; - - newcolor = (infoPtr->clrBtnHighlight == CLR_DEFAULT) ? - comctl32_color.clrBtnHighlight : infoPtr->clrBtnHighlight; - SetBkColor (hdc, newcolor); - ExtTextOutA (hdc, 0, 0, ETO_OPAQUE, &myrect, 0, 0, 0); - - SetBkColor (hdc, oldcolor); -} - - -/*********************************************************************** -* TOOLBAR_DrawDDFlatSeparator -* -* This function draws the separator that was flagged as BTNS_DROPDOWN. -* In this case, the separator is a pixel high line of COLOR_BTNSHADOW, -* followed by a pixel high line of COLOR_BTNHIGHLIGHT. These separators -* are horizontal as opposed to the vertical separators for not dropdown -* type. -* -* FIXME: It is possible that the height of each line is really SM_CYBORDER. -*/ -static void -TOOLBAR_DrawDDFlatSeparator (LPRECT lpRect, HDC hdc, TBUTTON_INFO *btnPtr, TOOLBAR_INFO *infoPtr) -{ - RECT myrect; - COLORREF oldcolor, newcolor; - - myrect.left = lpRect->left; - myrect.right = lpRect->right; - myrect.top = lpRect->top + (lpRect->bottom - lpRect->top - 2)/2; - myrect.bottom = myrect.top + 1; - - InflateRect (&myrect, -2, 0); - - TRACE("rect=(%ld,%ld)-(%ld,%ld)\n", - myrect.left, myrect.top, myrect.right, myrect.bottom); - - newcolor = (infoPtr->clrBtnShadow == CLR_DEFAULT) ? - comctl32_color.clrBtnShadow : infoPtr->clrBtnShadow; - oldcolor = SetBkColor (hdc, newcolor); - ExtTextOutA (hdc, 0, 0, ETO_OPAQUE, &myrect, 0, 0, 0); - - myrect.top = myrect.bottom; - myrect.bottom = myrect.top + 1; - - newcolor = (infoPtr->clrBtnHighlight == CLR_DEFAULT) ? - comctl32_color.clrBtnHighlight : infoPtr->clrBtnHighlight; - SetBkColor (hdc, newcolor); - ExtTextOutA (hdc, 0, 0, ETO_OPAQUE, &myrect, 0, 0, 0); - - SetBkColor (hdc, oldcolor); -} - - -static void -TOOLBAR_DrawArrow (HDC hdc, INT left, INT top, COLORREF clr) -{ - INT x, y; - HPEN hPen, hOldPen; - - if (!(hPen = CreatePen( PS_SOLID, 1, clr))) return; - hOldPen = SelectObject ( hdc, hPen ); - x = left + 2; - y = top; - MoveToEx (hdc, x, y, NULL); - LineTo (hdc, x+5, y++); x++; - MoveToEx (hdc, x, y, NULL); - LineTo (hdc, x+3, y++); x++; - MoveToEx (hdc, x, y, NULL); - LineTo (hdc, x+1, y++); - SelectObject( hdc, hOldPen ); - DeleteObject( hPen ); -} - -/* - * Draw the text string for this button. - * note: infoPtr->himlDis *SHOULD* be non-zero when infoPtr->himlDef - * is non-zero, so we can simply check himlDef to see if we have - * an image list - */ -static void -TOOLBAR_DrawString (TOOLBAR_INFO *infoPtr, RECT *rcText, LPWSTR lpText, - NMTBCUSTOMDRAW *tbcd) -{ - HDC hdc = tbcd->nmcd.hdc; - HFONT hOldFont = 0; - COLORREF clrOld = 0; - COLORREF clrOldBk = 0; - int oldBkMode = 0; - UINT state = tbcd->nmcd.uItemState; - - /* draw text */ - if (lpText) { - TRACE("string=%s rect=(%ld,%ld)-(%ld,%ld)\n", debugstr_w(lpText), - rcText->left, rcText->top, rcText->right, rcText->bottom); - - hOldFont = SelectObject (hdc, infoPtr->hFont); - if ((state & CDIS_HOT) && (infoPtr->dwItemCDFlag & TBCDRF_HILITEHOTTRACK )) { - clrOld = SetTextColor (hdc, tbcd->clrTextHighlight); - } - else if (state & CDIS_DISABLED) { - clrOld = SetTextColor (hdc, tbcd->clrBtnHighlight); - OffsetRect (rcText, 1, 1); - DrawTextW (hdc, lpText, -1, rcText, infoPtr->dwDTFlags); - SetTextColor (hdc, comctl32_color.clr3dShadow); - OffsetRect (rcText, -1, -1); - } - else if (state & CDIS_INDETERMINATE) { - clrOld = SetTextColor (hdc, comctl32_color.clr3dShadow); - } - else if ((state & CDIS_MARKED) && !(infoPtr->dwItemCDFlag & TBCDRF_NOMARK)) { - clrOld = SetTextColor (hdc, tbcd->clrTextHighlight); - clrOldBk = SetBkColor (hdc, tbcd->clrMark); - oldBkMode = SetBkMode (hdc, OPAQUE); /* FIXME: should this be in the NMTBCUSTOMDRAW structure? */ - } - else { - clrOld = SetTextColor (hdc, tbcd->clrText); - } - - DrawTextW (hdc, lpText, -1, rcText, infoPtr->dwDTFlags); - SetTextColor (hdc, clrOld); - if ((state & CDIS_MARKED) && !(infoPtr->dwItemCDFlag & TBCDRF_NOMARK)) - { - SetBkColor (hdc, clrOldBk); - SetBkMode (hdc, oldBkMode); - } - SelectObject (hdc, hOldFont); - } -} - - -static void -TOOLBAR_DrawPattern (LPRECT lpRect, NMTBCUSTOMDRAW *tbcd) -{ - HDC hdc = tbcd->nmcd.hdc; - HBRUSH hbr = SelectObject (hdc, tbcd->hbrMonoDither); - COLORREF clrTextOld; - COLORREF clrBkOld; - INT cx = lpRect->right - lpRect->left; - INT cy = lpRect->bottom - lpRect->top; - INT cxEdge = GetSystemMetrics(SM_CXEDGE); - INT cyEdge = GetSystemMetrics(SM_CYEDGE); - clrTextOld = SetTextColor(hdc, tbcd->clrBtnHighlight); - clrBkOld = SetBkColor(hdc, tbcd->clrBtnFace); - PatBlt (hdc, lpRect->left + cxEdge, lpRect->top + cyEdge, - cx - (2 * cxEdge), cy - (2 * cyEdge), PATCOPY); - SetBkColor(hdc, clrBkOld); - SetTextColor(hdc, clrTextOld); - SelectObject (hdc, hbr); -} - - -static void TOOLBAR_DrawMasked(HIMAGELIST himl, int index, HDC hdc, INT x, INT y, UINT draw_flags) -{ - INT cx, cy; - HBITMAP hbmMask, hbmImage; - HDC hdcMask, hdcImage; - - ImageList_GetIconSize(himl, &cx, &cy); - - /* Create src image */ - hdcImage = CreateCompatibleDC(hdc); - hbmImage = CreateCompatibleBitmap(hdc, cx, cy); - SelectObject(hdcImage, hbmImage); - ImageList_DrawEx(himl, index, hdcImage, 0, 0, cx, cy, - RGB(0xff, 0xff, 0xff), RGB(0,0,0), draw_flags); - - /* Create Mask */ - hdcMask = CreateCompatibleDC(0); - hbmMask = CreateBitmap(cx, cy, 1, 1, NULL); - SelectObject(hdcMask, hbmMask); - - /* Remove the background and all white pixels */ - ImageList_DrawEx(himl, index, hdcMask, 0, 0, cx, cy, - RGB(0xff, 0xff, 0xff), RGB(0,0,0), ILD_MASK); - SetBkColor(hdcImage, RGB(0xff, 0xff, 0xff)); - BitBlt(hdcMask, 0, 0, cx, cy, hdcImage, 0, 0, NOTSRCERASE); - - /* draw the new mask 'etched' to hdc */ - SetBkColor(hdc, RGB(255, 255, 255)); - SelectObject(hdc, GetSysColorBrush(COLOR_3DHILIGHT)); - /* E20746 op code is (Dst ^ (Src & (Pat ^ Dst))) */ - BitBlt(hdc, x + 1, y + 1, cx, cy, hdcMask, 0, 0, 0xE20746); - SelectObject(hdc, GetSysColorBrush(COLOR_3DSHADOW)); - BitBlt(hdc, x, y, cx, cy, hdcMask, 0, 0, 0xE20746); - - /* Cleanup */ - DeleteObject(hbmImage); - DeleteDC(hdcImage); - DeleteObject (hbmMask); - DeleteDC(hdcMask); -} - - -static UINT -TOOLBAR_TranslateState(TBUTTON_INFO *btnPtr) -{ - UINT retstate = 0; - - retstate |= (btnPtr->fsState & TBSTATE_CHECKED) ? CDIS_CHECKED : 0; - retstate |= (btnPtr->fsState & TBSTATE_PRESSED) ? CDIS_SELECTED : 0; - retstate |= (btnPtr->fsState & TBSTATE_ENABLED) ? 0 : CDIS_DISABLED; - retstate |= (btnPtr->fsState & TBSTATE_MARKED ) ? CDIS_MARKED : 0; - retstate |= (btnPtr->bHot ) ? CDIS_HOT : 0; - retstate |= (btnPtr->fsState & TBSTATE_INDETERMINATE) ? CDIS_INDETERMINATE : 0; - /* NOTE: we don't set CDIS_GRAYED, CDIS_FOCUS, CDIS_DEFAULT */ - return retstate; -} - -/* draws the image on a toolbar button */ -static void -TOOLBAR_DrawImage(TOOLBAR_INFO *infoPtr, TBUTTON_INFO *btnPtr, INT left, INT top, const NMTBCUSTOMDRAW *tbcd) -{ - HIMAGELIST himl = NULL; - BOOL draw_masked = FALSE; - INT index; - INT offset = 0; - UINT draw_flags = ILD_TRANSPARENT; - - if (tbcd->nmcd.uItemState & (CDIS_DISABLED | CDIS_INDETERMINATE)) - { - himl = TOOLBAR_GetImageListForDrawing(infoPtr, btnPtr, IMAGE_LIST_DISABLED, &index); - if (!himl) - { - himl = TOOLBAR_GetImageListForDrawing(infoPtr, btnPtr, IMAGE_LIST_DEFAULT, &index); - draw_masked = TRUE; - } - } - else if ((tbcd->nmcd.uItemState & CDIS_HOT) && (infoPtr->dwStyle & TBSTYLE_FLAT)) - { - /* if hot, attempt to draw with hot image list, if fails, - use default image list */ - himl = TOOLBAR_GetImageListForDrawing(infoPtr, btnPtr, IMAGE_LIST_HOT, &index); - if (!himl) - himl = TOOLBAR_GetImageListForDrawing(infoPtr, btnPtr, IMAGE_LIST_DEFAULT, &index); - } - else - himl = TOOLBAR_GetImageListForDrawing(infoPtr, btnPtr, IMAGE_LIST_DEFAULT, &index); - - if (!himl) - return; - - if (!(infoPtr->dwItemCDFlag & TBCDRF_NOOFFSET) && - (tbcd->nmcd.uItemState & (CDIS_SELECTED | CDIS_CHECKED))) - offset = 1; - - if (!(infoPtr->dwItemCDFlag & TBCDRF_NOMARK) && - (tbcd->nmcd.uItemState & CDIS_MARKED)) - draw_flags |= ILD_BLEND50; - - TRACE("drawing index=%d, himl=%p, left=%d, top=%d, offset=%d\n", - index, himl, left, top, offset); - - if (draw_masked) - TOOLBAR_DrawMasked (himl, index, tbcd->nmcd.hdc, left + offset, top + offset, draw_flags); - else - ImageList_Draw (himl, index, tbcd->nmcd.hdc, left + offset, top + offset, draw_flags); -} - -/* draws a blank frame for a toolbar button */ -static void -TOOLBAR_DrawFrame(const TOOLBAR_INFO *infoPtr, BOOL flat, const NMTBCUSTOMDRAW *tbcd) -{ - HDC hdc = tbcd->nmcd.hdc; - RECT rc = tbcd->nmcd.rc; - /* if the state is disabled or indeterminate then the button - * cannot have an interactive look like pressed or hot */ - BOOL non_interactive_state = (tbcd->nmcd.uItemState & CDIS_DISABLED) || - (tbcd->nmcd.uItemState & CDIS_INDETERMINATE); - BOOL pressed_look = !non_interactive_state && - ((tbcd->nmcd.uItemState & CDIS_SELECTED) || - (tbcd->nmcd.uItemState & CDIS_CHECKED)); - - /* app don't want us to draw any edges */ - if (infoPtr->dwItemCDFlag & TBCDRF_NOEDGES) - return; - - if (flat) - { - if (pressed_look) - DrawEdge (hdc, &rc, BDR_SUNKENOUTER, BF_RECT); - else if ((tbcd->nmcd.uItemState & CDIS_HOT) && !non_interactive_state) - DrawEdge (hdc, &rc, BDR_RAISEDINNER, BF_RECT); - } - else - { - if (pressed_look) - DrawEdge (hdc, &rc, EDGE_SUNKEN, BF_RECT | BF_MIDDLE); - else - DrawEdge (hdc, &rc, EDGE_RAISED, - BF_SOFT | BF_RECT | BF_MIDDLE); - } -} - -static void -TOOLBAR_DrawSepDDArrow(const TOOLBAR_INFO *infoPtr, const NMTBCUSTOMDRAW *tbcd, RECT *rcArrow, BOOL bDropDownPressed) -{ - HDC hdc = tbcd->nmcd.hdc; - int offset = 0; - BOOL pressed = bDropDownPressed || - (tbcd->nmcd.uItemState & (CDIS_SELECTED | CDIS_CHECKED)); - - if (infoPtr->dwStyle & TBSTYLE_FLAT) - { - if (pressed) - DrawEdge (hdc, rcArrow, BDR_SUNKENOUTER, BF_RECT); - else if ( (tbcd->nmcd.uItemState & CDIS_HOT) && - !(tbcd->nmcd.uItemState & CDIS_DISABLED) && - !(tbcd->nmcd.uItemState & CDIS_INDETERMINATE)) - DrawEdge (hdc, rcArrow, BDR_RAISEDINNER, BF_RECT); - } - else - { - if (pressed) - DrawEdge (hdc, rcArrow, EDGE_SUNKEN, BF_RECT | BF_MIDDLE); - else - DrawEdge (hdc, rcArrow, EDGE_RAISED, - BF_SOFT | BF_RECT | BF_MIDDLE); - } - - if (pressed) - offset = (infoPtr->dwItemCDFlag & TBCDRF_NOOFFSET) ? 0 : 1; - - if (tbcd->nmcd.uItemState & (CDIS_DISABLED | CDIS_INDETERMINATE)) - { - TOOLBAR_DrawArrow(hdc, rcArrow->left+1, rcArrow->top+1 + (rcArrow->bottom - rcArrow->top - ARROW_HEIGHT) / 2, comctl32_color.clrBtnHighlight); - TOOLBAR_DrawArrow(hdc, rcArrow->left, rcArrow->top + (rcArrow->bottom - rcArrow->top - ARROW_HEIGHT) / 2, comctl32_color.clr3dShadow); - } - else - TOOLBAR_DrawArrow(hdc, rcArrow->left + offset, rcArrow->top + offset + (rcArrow->bottom - rcArrow->top - ARROW_HEIGHT) / 2, comctl32_color.clrBtnText); -} - -/* draws a complete toolbar button */ -static void -TOOLBAR_DrawButton (HWND hwnd, TBUTTON_INFO *btnPtr, HDC hdc) -{ - TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd); - DWORD dwStyle = infoPtr->dwStyle; - BOOL hasDropDownArrow = (TOOLBAR_HasDropDownArrows(infoPtr->dwExStyle) && - (btnPtr->fsStyle & BTNS_DROPDOWN)) || - (btnPtr->fsStyle & BTNS_WHOLEDROPDOWN); - BOOL drawSepDropDownArrow = hasDropDownArrow && - (~btnPtr->fsStyle & BTNS_WHOLEDROPDOWN); - RECT rc, rcArrow, rcBitmap, rcText; - LPWSTR lpText = NULL; - NMTBCUSTOMDRAW tbcd; - DWORD ntfret; - INT offset; - - rc = btnPtr->rect; - CopyRect (&rcArrow, &rc); - CopyRect(&rcBitmap, &rc); - - /* get a pointer to the text */ - lpText = TOOLBAR_GetText(infoPtr, btnPtr); - - if (hasDropDownArrow) - { - int right; - - if (dwStyle & TBSTYLE_FLAT) - right = max(rc.left, rc.right - DDARROW_WIDTH); - else - right = max(rc.left, rc.right - DDARROW_WIDTH - 2); - - if (drawSepDropDownArrow) - rc.right = right; - - rcArrow.left = right; - } - - /* copy text rect after adjusting for drop-down arrow - * so that text is centred in the rectangle not containing - * the arrow */ - CopyRect(&rcText, &rc); - - /* Center the bitmap horizontally and vertically */ - if (dwStyle & TBSTYLE_LIST) - rcBitmap.left += GetSystemMetrics(SM_CXEDGE); - else - rcBitmap.left+=(infoPtr->nButtonWidth - infoPtr->nBitmapWidth) / 2; - - if(lpText) - rcBitmap.top+= GetSystemMetrics(SM_CYEDGE); - else - rcBitmap.top+=(infoPtr->nButtonHeight - infoPtr->nBitmapHeight) / 2; - - TRACE("iBitmap: %d, start=(%ld,%ld) w=%d, h=%d\n", - btnPtr->iBitmap, rcBitmap.left, rcBitmap.top, - infoPtr->nBitmapWidth, infoPtr->nBitmapHeight); - TRACE ("iString: %x\n", btnPtr->iString); - TRACE ("Stringtext: %s\n", debugstr_w(lpText)); - - /* draw text */ - if (lpText) { - rcText.left += GetSystemMetrics(SM_CXEDGE) + OFFSET_X; - rcText.right -= GetSystemMetrics(SM_CXEDGE) + OFFSET_X; - if (GETDEFIMAGELIST(infoPtr, GETHIMLID(infoPtr,btnPtr->iBitmap)) && - TOOLBAR_IsValidBitmapIndex(infoPtr,btnPtr->iBitmap)) - { - if (dwStyle & TBSTYLE_LIST) - rcText.left += infoPtr->nBitmapWidth + TOOLBAR_GetListTextOffset(infoPtr, infoPtr->iListGap); - else - rcText.top += GetSystemMetrics(SM_CYEDGE) + OFFSET_Y + infoPtr->nBitmapHeight + infoPtr->szPadding.cy/2; - } - else - if (dwStyle & TBSTYLE_LIST) - rcText.left += LIST_IMAGE_ABSENT_WIDTH + TOOLBAR_GetListTextOffset(infoPtr, infoPtr->iListGap); - - if (!(infoPtr->dwItemCDFlag & TBCDRF_NOOFFSET) && - (btnPtr->fsState & (TBSTATE_PRESSED | TBSTATE_CHECKED))) - OffsetRect(&rcText, 1, 1); - } - - /* Initialize fields in all cases, because we use these later - * NOTE: applications can and do alter these to customize their - * toolbars */ - ZeroMemory (&tbcd, sizeof(NMTBCUSTOMDRAW)); - tbcd.clrText = comctl32_color.clrBtnText; - tbcd.clrTextHighlight = comctl32_color.clrHighlightText; - tbcd.clrBtnFace = comctl32_color.clrBtnFace; - tbcd.clrBtnHighlight = comctl32_color.clrBtnHighlight; - tbcd.clrMark = comctl32_color.clrHighlight; - tbcd.clrHighlightHotTrack = 0; - tbcd.nStringBkMode = (infoPtr->bBtnTranspnt) ? TRANSPARENT : OPAQUE; - tbcd.nHLStringBkMode = (infoPtr->bBtnTranspnt) ? TRANSPARENT : OPAQUE; - /* MSDN says that this is the text rectangle. - * But (why always a but) tracing of v5.7 of native shows - * that this is really a *relative* rectangle based on the - * the nmcd.rc. Also the left and top are always 0 ignoring - * any bitmap that might be present. */ - tbcd.rcText.left = 0; - tbcd.rcText.top = 0; - tbcd.rcText.right = rcText.right - rc.left; - tbcd.rcText.bottom = rcText.bottom - rc.top; - tbcd.nmcd.uItemState = TOOLBAR_TranslateState(btnPtr); - tbcd.nmcd.hdc = hdc; - tbcd.nmcd.rc = rc; - tbcd.hbrMonoDither = COMCTL32_hPattern55AABrush; - - /* FIXME: what are these used for? */ - tbcd.hbrLines = 0; - tbcd.hpenLines = 0; - - /* Issue Item Prepaint notify */ - infoPtr->dwItemCustDraw = 0; - infoPtr->dwItemCDFlag = 0; - if (infoPtr->dwBaseCustDraw & CDRF_NOTIFYITEMDRAW) - { - tbcd.nmcd.dwDrawStage = CDDS_ITEMPREPAINT; - tbcd.nmcd.dwItemSpec = btnPtr->idCommand; - tbcd.nmcd.lItemlParam = btnPtr->dwData; - ntfret = TOOLBAR_SendNotify(&tbcd.nmcd.hdr, infoPtr, NM_CUSTOMDRAW); - /* reset these fields so the user can't alter the behaviour like native */ - tbcd.nmcd.hdc = hdc; - tbcd.nmcd.rc = rc; - - infoPtr->dwItemCustDraw = ntfret & 0xffff; - infoPtr->dwItemCDFlag = ntfret & 0xffff0000; - if (infoPtr->dwItemCustDraw & CDRF_SKIPDEFAULT) - return; - /* save the only part of the rect that the user can change */ - rcText.right = tbcd.rcText.right + rc.left; - rcText.bottom = tbcd.rcText.bottom + rc.top; - } - - /* separator */ - if (btnPtr->fsStyle & BTNS_SEP) { - /* with the FLAT style, iBitmap is the width and has already */ - /* been taken into consideration in calculating the width */ - /* so now we need to draw the vertical separator */ - /* empirical tests show that iBitmap can/will be non-zero */ - /* when drawing the vertical bar... */ - if ((dwStyle & TBSTYLE_FLAT) /* && (btnPtr->iBitmap == 0) */) { - if (btnPtr->fsStyle & BTNS_DROPDOWN) - TOOLBAR_DrawDDFlatSeparator (&rc, hdc, btnPtr, infoPtr); - else - TOOLBAR_DrawFlatSeparator (&rc, hdc, infoPtr); - } - else if (btnPtr->fsStyle != BTNS_SEP) { - FIXME("Draw some kind of separator: fsStyle=%x\n", - btnPtr->fsStyle); - } - goto FINALNOTIFY; - } - - if (!(tbcd.nmcd.uItemState & CDIS_HOT) && - ((tbcd.nmcd.uItemState & CDIS_CHECKED) || (tbcd.nmcd.uItemState & CDIS_INDETERMINATE))) - TOOLBAR_DrawPattern (&rc, &tbcd); - - if ((dwStyle & TBSTYLE_FLAT) && (tbcd.nmcd.uItemState & CDIS_HOT)) - { - if ( infoPtr->dwItemCDFlag & TBCDRF_HILITEHOTTRACK ) - { - COLORREF oldclr; - - oldclr = SetBkColor(hdc, tbcd.clrHighlightHotTrack); - ExtTextOutA(hdc, 0, 0, ETO_OPAQUE, &rc, NULL, 0, 0); - if (hasDropDownArrow) - ExtTextOutA(hdc, 0, 0, ETO_OPAQUE, &rcArrow, NULL, 0, 0); - SetBkColor(hdc, oldclr); - } - } - - TOOLBAR_DrawFrame(infoPtr, dwStyle & TBSTYLE_FLAT, &tbcd); - - if (drawSepDropDownArrow) - TOOLBAR_DrawSepDDArrow(infoPtr, &tbcd, &rcArrow, btnPtr->bDropDownPressed); - - if (!(infoPtr->dwExStyle & TBSTYLE_EX_MIXEDBUTTONS) || (btnPtr->fsStyle & BTNS_SHOWTEXT)) - TOOLBAR_DrawString (infoPtr, &rcText, lpText, &tbcd); - - TOOLBAR_DrawImage(infoPtr, btnPtr, rcBitmap.left, rcBitmap.top, &tbcd); - - if (hasDropDownArrow && !drawSepDropDownArrow) - { - if (tbcd.nmcd.uItemState & (CDIS_DISABLED | CDIS_INDETERMINATE)) - { - TOOLBAR_DrawArrow(hdc, rcArrow.left+1, rcArrow.top+1 + (rcArrow.bottom - rcArrow.top - ARROW_HEIGHT) / 2, comctl32_color.clrBtnHighlight); - TOOLBAR_DrawArrow(hdc, rcArrow.left, rcArrow.top + (rcArrow.bottom - rcArrow.top - ARROW_HEIGHT) / 2, comctl32_color.clr3dShadow); - } - else if (tbcd.nmcd.uItemState & (CDIS_SELECTED | CDIS_CHECKED)) - { - offset = (infoPtr->dwItemCDFlag & TBCDRF_NOOFFSET) ? 0 : 1; - TOOLBAR_DrawArrow(hdc, rcArrow.left + offset, rcArrow.top + offset + (rcArrow.bottom - rcArrow.top - ARROW_HEIGHT) / 2, comctl32_color.clrBtnText); - } - else - TOOLBAR_DrawArrow(hdc, rcArrow.left, rcArrow.top + (rcArrow.bottom - rcArrow.top - ARROW_HEIGHT) / 2, comctl32_color.clrBtnText); - } - -FINALNOTIFY: - if (infoPtr->dwItemCustDraw & CDRF_NOTIFYPOSTPAINT) - { - tbcd.nmcd.dwDrawStage = CDDS_ITEMPOSTPAINT; - tbcd.nmcd.hdc = hdc; - tbcd.nmcd.rc = rc; - tbcd.nmcd.dwItemSpec = btnPtr->idCommand; - tbcd.nmcd.uItemState = TOOLBAR_TranslateState(btnPtr); - tbcd.nmcd.lItemlParam = btnPtr->dwData; - tbcd.rcText = rcText; - tbcd.nStringBkMode = (infoPtr->bBtnTranspnt) ? TRANSPARENT : OPAQUE; - tbcd.nHLStringBkMode = (infoPtr->bBtnTranspnt) ? TRANSPARENT : OPAQUE; - ntfret = TOOLBAR_SendNotify(&tbcd.nmcd.hdr, infoPtr, NM_CUSTOMDRAW); - } - -} - - -static void -TOOLBAR_Refresh (HWND hwnd, HDC hdc, PAINTSTRUCT* ps) -{ - TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd); - TBUTTON_INFO *btnPtr; - INT i, oldBKmode = 0; - RECT rcTemp, rcClient; - NMTBCUSTOMDRAW tbcd; - DWORD ntfret; - - /* the app has told us not to redraw the toolbar */ - if (!infoPtr->bDoRedraw) - return; - - /* if imagelist belongs to the app, it can be changed - by the app after setting it */ - if (GETDEFIMAGELIST(infoPtr, 0) != infoPtr->himlInt) - { - infoPtr->nNumBitmaps = 0; - for (i = 0; i < infoPtr->cimlDef; i++) - infoPtr->nNumBitmaps += ImageList_GetImageCount(infoPtr->himlDef[i]->himl); - } - - TOOLBAR_DumpToolbar (infoPtr, __LINE__); - - /* Send initial notify */ - ZeroMemory (&tbcd, sizeof(NMTBCUSTOMDRAW)); - tbcd.nmcd.dwDrawStage = CDDS_PREPAINT; - tbcd.nmcd.hdc = hdc; - tbcd.nmcd.rc = ps->rcPaint; - ntfret = TOOLBAR_SendNotify(&tbcd.nmcd.hdr, infoPtr, NM_CUSTOMDRAW); - infoPtr->dwBaseCustDraw = ntfret & 0xffff; - - if (infoPtr->bBtnTranspnt) - oldBKmode = SetBkMode (hdc, TRANSPARENT); - - GetClientRect(hwnd, &rcClient); - - /* redraw necessary buttons */ - btnPtr = infoPtr->buttons; - for (i = 0; i < infoPtr->nNumButtons; i++, btnPtr++) - { - BOOL bDraw; - if (infoPtr->dwExStyle & TBSTYLE_EX_HIDECLIPPEDBUTTONS) - { - IntersectRect(&rcTemp, &rcClient, &btnPtr->rect); - bDraw = EqualRect(&rcTemp, &btnPtr->rect); - } - else - bDraw = TRUE; - bDraw &= IntersectRect(&rcTemp, &(ps->rcPaint), &(btnPtr->rect)); - bDraw = (btnPtr->fsState & TBSTATE_HIDDEN) ? FALSE : bDraw; - if (bDraw) - TOOLBAR_DrawButton (hwnd, btnPtr, hdc); - } - - /* draw insert mark if required */ - if (infoPtr->tbim.iButton != -1) - { - RECT rcButton = infoPtr->buttons[infoPtr->tbim.iButton].rect; - RECT rcInsertMark; - rcInsertMark.top = rcButton.top; - rcInsertMark.bottom = rcButton.bottom; - if (infoPtr->tbim.dwFlags & TBIMHT_AFTER) - rcInsertMark.left = rcInsertMark.right = rcButton.right; - else - rcInsertMark.left = rcInsertMark.right = rcButton.left - INSERTMARK_WIDTH; - COMCTL32_DrawInsertMark(hdc, &rcInsertMark, infoPtr->clrInsertMark, FALSE); - } - - if (infoPtr->bBtnTranspnt && (oldBKmode != TRANSPARENT)) - SetBkMode (hdc, oldBKmode); - - if (infoPtr->dwBaseCustDraw & CDRF_NOTIFYPOSTPAINT) - { - ZeroMemory (&tbcd, sizeof(NMTBCUSTOMDRAW)); - tbcd.nmcd.dwDrawStage = CDDS_POSTPAINT; - tbcd.nmcd.hdc = hdc; - tbcd.nmcd.rc = ps->rcPaint; - ntfret = TOOLBAR_SendNotify(&tbcd.nmcd.hdr, infoPtr, NM_CUSTOMDRAW); - } -} - -/*********************************************************************** -* TOOLBAR_MeasureString -* -* This function gets the width and height of a string in pixels. This -* is done first by using GetTextExtentPoint to get the basic width -* and height. The DrawText is called with DT_CALCRECT to get the exact -* width. The reason is because the text may have more than one "&" (or -* prefix characters as M$ likes to call them). The prefix character -* indicates where the underline goes, except for the string "&&" which -* is reduced to a single "&". GetTextExtentPoint does not process these -* only DrawText does. Note that the BTNS_NOPREFIX is handled here. -*/ -static void -TOOLBAR_MeasureString(TOOLBAR_INFO *infoPtr, TBUTTON_INFO *btnPtr, - HDC hdc, LPSIZE lpSize) -{ - RECT myrect; - - lpSize->cx = 0; - lpSize->cy = 0; - - if (infoPtr->nMaxTextRows > 0 && - !(btnPtr->fsState & TBSTATE_HIDDEN) && - (!(infoPtr->dwExStyle & TBSTYLE_EX_MIXEDBUTTONS) || - (btnPtr->fsStyle & BTNS_SHOWTEXT)) ) - { - LPWSTR lpText = TOOLBAR_GetText(infoPtr, btnPtr); - - if(lpText != NULL) { - /* first get size of all the text */ - GetTextExtentPoint32W (hdc, lpText, strlenW (lpText), lpSize); - - /* feed above size into the rectangle for DrawText */ - myrect.left = myrect.top = 0; - myrect.right = lpSize->cx; - myrect.bottom = lpSize->cy; - - /* Use DrawText to get true size as drawn (less pesky "&") */ - DrawTextW (hdc, lpText, -1, &myrect, DT_VCENTER | DT_SINGLELINE | - DT_CALCRECT | ((btnPtr->fsStyle & BTNS_NOPREFIX) ? - DT_NOPREFIX : 0)); - - /* feed back to caller */ - lpSize->cx = myrect.right; - lpSize->cy = myrect.bottom; - } - } - - TRACE("string size %ld x %ld!\n", lpSize->cx, lpSize->cy); -} - -/*********************************************************************** -* TOOLBAR_CalcStrings -* -* This function walks through each string and measures it and returns -* the largest height and width to caller. -*/ -static void -TOOLBAR_CalcStrings (HWND hwnd, LPSIZE lpSize) -{ - TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd); - TBUTTON_INFO *btnPtr; - INT i; - SIZE sz; - HDC hdc; - HFONT hOldFont; - - lpSize->cx = 0; - lpSize->cy = 0; - - if(infoPtr->nMaxTextRows == 0) - return; - - hdc = GetDC (hwnd); - hOldFont = SelectObject (hdc, infoPtr->hFont); - - btnPtr = infoPtr->buttons; - for (i = 0; i < infoPtr->nNumButtons; i++, btnPtr++) { - if(TOOLBAR_HasText(infoPtr, btnPtr)) - { - TOOLBAR_MeasureString(infoPtr, btnPtr, hdc, &sz); - if (sz.cx > lpSize->cx) - lpSize->cx = sz.cx; - if (sz.cy > lpSize->cy) - lpSize->cy = sz.cy; - } - } - - SelectObject (hdc, hOldFont); - ReleaseDC (hwnd, hdc); - - TRACE("max string size %ld x %ld!\n", lpSize->cx, lpSize->cy); -} - -/*********************************************************************** -* TOOLBAR_WrapToolbar -* -* This function walks through the buttons and separators in the -* toolbar, and sets the TBSTATE_WRAP flag only on those items where -* wrapping should occur based on the width of the toolbar window. -* It does *not* calculate button placement itself. That task -* takes place in TOOLBAR_CalcToolbar. If the program wants to manage -* the toolbar wrapping on its own, it can use the TBSTYLE_WRAPABLE -* flag, and set the TBSTATE_WRAP flags manually on the appropriate items. -* -* Note: TBSTYLE_WRAPABLE or TBSTYLE_EX_UNDOC1 can be used also to allow -* vertical toolbar lists. -*/ - -static void -TOOLBAR_WrapToolbar( HWND hwnd, DWORD dwStyle ) -{ - TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd); - TBUTTON_INFO *btnPtr; - INT x, cx, i, j; - RECT rc; - BOOL bWrap, bButtonWrap; - - /* When the toolbar window style is not TBSTYLE_WRAPABLE, */ - /* no layout is necessary. Applications may use this style */ - /* to perform their own layout on the toolbar. */ - if( !(dwStyle & TBSTYLE_WRAPABLE) && - !(infoPtr->dwExStyle & TBSTYLE_EX_UNDOC1) ) return; - - btnPtr = infoPtr->buttons; - x = infoPtr->nIndent; - - /* this can get the parents width, to know how far we can extend - * this toolbar. We cannot use its height, as there may be multiple - * toolbars in a rebar control - */ - GetClientRect( GetParent(hwnd), &rc ); - infoPtr->nWidth = rc.right - rc.left; - bButtonWrap = FALSE; - - TRACE("start ButtonWidth=%d, BitmapWidth=%d, nWidth=%d, nIndent=%d\n", - infoPtr->nButtonWidth, infoPtr->nBitmapWidth, infoPtr->nWidth, - infoPtr->nIndent); - - for (i = 0; i < infoPtr->nNumButtons; i++ ) - { - bWrap = FALSE; - btnPtr[i].fsState &= ~TBSTATE_WRAP; - - if (btnPtr[i].fsState & TBSTATE_HIDDEN) - continue; - - /* UNDOCUMENTED: If a separator has a non zero bitmap index, */ - /* it is the actual width of the separator. This is used for */ - /* custom controls in toolbars. */ - /* */ - /* BTNS_DROPDOWN separators are treated as buttons for */ - /* width. - GA 8/01 */ - if ((btnPtr[i].fsStyle & BTNS_SEP) && - !(btnPtr[i].fsStyle & BTNS_DROPDOWN)) - cx = (btnPtr[i].iBitmap > 0) ? - btnPtr[i].iBitmap : SEPARATOR_WIDTH; - else - cx = infoPtr->nButtonWidth; - - /* Two or more adjacent separators form a separator group. */ - /* The first separator in a group should be wrapped to the */ - /* next row if the previous wrapping is on a button. */ - if( bButtonWrap && - (btnPtr[i].fsStyle & BTNS_SEP) && - (i + 1 < infoPtr->nNumButtons ) && - (btnPtr[i + 1].fsStyle & BTNS_SEP) ) - { - TRACE("wrap point 1 btn %d style %02x\n", i, btnPtr[i].fsStyle); - btnPtr[i].fsState |= TBSTATE_WRAP; - x = infoPtr->nIndent; - i++; - bButtonWrap = FALSE; - continue; - } - - /* The layout makes sure the bitmap is visible, but not the button. */ - /* Test added to also wrap after a button that starts a row but */ - /* is bigger than the area. - GA 8/01 */ - if (( x + cx - (infoPtr->nButtonWidth - infoPtr->nBitmapWidth) / 2 - > infoPtr->nWidth ) || - ((x == infoPtr->nIndent) && (cx > infoPtr->nWidth))) - { - BOOL bFound = FALSE; - - /* If the current button is a separator and not hidden, */ - /* go to the next until it reaches a non separator. */ - /* Wrap the last separator if it is before a button. */ - while( ( ((btnPtr[i].fsStyle & BTNS_SEP) && - !(btnPtr[i].fsStyle & BTNS_DROPDOWN)) || - (btnPtr[i].fsState & TBSTATE_HIDDEN) ) && - i < infoPtr->nNumButtons ) - { - i++; - bFound = TRUE; - } - - if( bFound && i < infoPtr->nNumButtons ) - { - i--; - TRACE("wrap point 2 btn %d style %02x, x=%d, cx=%d\n", - i, btnPtr[i].fsStyle, x, cx); - btnPtr[i].fsState |= TBSTATE_WRAP; - x = infoPtr->nIndent; - bButtonWrap = FALSE; - continue; - } - else if ( i >= infoPtr->nNumButtons) - break; - - /* If the current button is not a separator, find the last */ - /* separator and wrap it. */ - for ( j = i - 1; j >= 0 && !(btnPtr[j].fsState & TBSTATE_WRAP); j--) - { - if ((btnPtr[j].fsStyle & BTNS_SEP) && - !(btnPtr[j].fsState & TBSTATE_HIDDEN)) - { - bFound = TRUE; - i = j; - TRACE("wrap point 3 btn %d style %02x, x=%d, cx=%d\n", - i, btnPtr[i].fsStyle, x, cx); - x = infoPtr->nIndent; - btnPtr[j].fsState |= TBSTATE_WRAP; - bButtonWrap = FALSE; - break; - } - } - - /* If no separator available for wrapping, wrap one of */ - /* non-hidden previous button. */ - if (!bFound) - { - for ( j = i - 1; - j >= 0 && !(btnPtr[j].fsState & TBSTATE_WRAP); j--) - { - if (btnPtr[j].fsState & TBSTATE_HIDDEN) - continue; - - bFound = TRUE; - i = j; - TRACE("wrap point 4 btn %d style %02x, x=%d, cx=%d\n", - i, btnPtr[i].fsStyle, x, cx); - x = infoPtr->nIndent; - btnPtr[j].fsState |= TBSTATE_WRAP; - bButtonWrap = TRUE; - break; - } - } - - /* If all above failed, wrap the current button. */ - if (!bFound) - { - TRACE("wrap point 5 btn %d style %02x, x=%d, cx=%d\n", - i, btnPtr[i].fsStyle, x, cx); - btnPtr[i].fsState |= TBSTATE_WRAP; - bFound = TRUE; - x = infoPtr->nIndent; - if (btnPtr[i].fsStyle & BTNS_SEP ) - bButtonWrap = FALSE; - else - bButtonWrap = TRUE; - } - } - else { - TRACE("wrap point 6 btn %d style %02x, x=%d, cx=%d\n", - i, btnPtr[i].fsStyle, x, cx); - x += cx; - } - } -} - - -/*********************************************************************** -* TOOLBAR_CalcToolbar -* -* This function calculates button and separator placement. It first -* calculates the button sizes, gets the toolbar window width and then -* calls TOOLBAR_WrapToolbar to determine which buttons we need to wrap -* on. It assigns a new location to each item and sends this location to -* the tooltip window if appropriate. Finally, it updates the rcBound -* rect and calculates the new required toolbar window height. -*/ - -static void -TOOLBAR_CalcToolbar (HWND hwnd) -{ - TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr(hwnd); - DWORD dwStyle = infoPtr->dwStyle; - TBUTTON_INFO *btnPtr; - INT i, nRows, nSepRows; - INT x, y, cx, cy; - SIZE sizeString; - BOOL bWrap; - BOOL usesBitmaps = FALSE; - BOOL hasDropDownArrows = TOOLBAR_HasDropDownArrows(infoPtr->dwExStyle); - - TOOLBAR_CalcStrings (hwnd, &sizeString); - - TOOLBAR_DumpToolbar (infoPtr, __LINE__); - - for (i = 0; i < infoPtr->nNumButtons && !usesBitmaps; i++) - { - if (TOOLBAR_IsValidBitmapIndex(infoPtr,infoPtr->buttons[i].iBitmap)) - usesBitmaps = TRUE; - } - if (dwStyle & TBSTYLE_LIST) - { - infoPtr->nButtonHeight = max((usesBitmaps) ? infoPtr->nBitmapHeight : - 0, sizeString.cy) + infoPtr->szPadding.cy; - infoPtr->nButtonWidth = ((usesBitmaps) ? infoPtr->nBitmapWidth : - LIST_IMAGE_ABSENT_WIDTH) + sizeString.cx + infoPtr->szPadding.cx; - if (sizeString.cx > 0) - infoPtr->nButtonWidth += TOOLBAR_GetListTextOffset(infoPtr, infoPtr->iListGap) + infoPtr->szPadding.cx/2; - TRACE("LIST style, But w=%d h=%d, useBitmaps=%d, Bit w=%d h=%d\n", - infoPtr->nButtonWidth, infoPtr->nButtonHeight, usesBitmaps, - infoPtr->nBitmapWidth, infoPtr->nBitmapHeight); - } - else { - if (sizeString.cy > 0) - { - if (usesBitmaps) - infoPtr->nButtonHeight = sizeString.cy + - infoPtr->szPadding.cy/2 + /* this is the space to separate text from bitmap */ - infoPtr->nBitmapHeight + infoPtr->szPadding.cy; - else - infoPtr->nButtonHeight = sizeString.cy + infoPtr->szPadding.cy; - } - else - infoPtr->nButtonHeight = infoPtr->nBitmapHeight + infoPtr->szPadding.cy; - - if (sizeString.cx > infoPtr->nBitmapWidth) - infoPtr->nButtonWidth = sizeString.cx + infoPtr->szPadding.cx; - else - infoPtr->nButtonWidth = infoPtr->nBitmapWidth + infoPtr->szPadding.cx; - } - - if ( infoPtr->cxMin >= 0 && infoPtr->nButtonWidth < infoPtr->cxMin ) - infoPtr->nButtonWidth = infoPtr->cxMin; - if ( infoPtr->cxMax > 0 && infoPtr->nButtonWidth > infoPtr->cxMax ) - infoPtr->nButtonWidth = infoPtr->cxMax; - - TOOLBAR_WrapToolbar( hwnd, dwStyle ); - - x = infoPtr->nIndent; - y = 0; - - /* from above, minimum is a button, and possible text */ - cx = infoPtr->nButtonWidth; - - /* cannot use just ButtonHeight, we may have no buttons! */ - if (infoPtr->nNumButtons > 0) - infoPtr->nHeight = infoPtr->nButtonHeight; - - cy = infoPtr->nHeight; - - nRows = nSepRows = 0; - - infoPtr->rcBound.top = y; - infoPtr->rcBound.left = x; - infoPtr->rcBound.bottom = y + cy; - infoPtr->rcBound.right = x; - - btnPtr = infoPtr->buttons; - - TRACE("cy=%d\n", cy); - - for (i = 0; i < infoPtr->nNumButtons; i++, btnPtr++ ) - { - bWrap = FALSE; - if (btnPtr->fsState & TBSTATE_HIDDEN) - { - SetRectEmpty (&btnPtr->rect); - continue; - } - - cy = infoPtr->nHeight; - - /* UNDOCUMENTED: If a separator has a non zero bitmap index, */ - /* it is the actual width of the separator. This is used for */ - /* custom controls in toolbars. */ - if (btnPtr->fsStyle & BTNS_SEP) { - if (btnPtr->fsStyle & BTNS_DROPDOWN) { - cy = (btnPtr->iBitmap > 0) ? - btnPtr->iBitmap : SEPARATOR_WIDTH; - cx = infoPtr->nButtonWidth; - } - else - cx = (btnPtr->iBitmap > 0) ? - btnPtr->iBitmap : SEPARATOR_WIDTH; - } - else - { - if (btnPtr->cx) - cx = btnPtr->cx; - else if ((infoPtr->dwExStyle & TBSTYLE_EX_MIXEDBUTTONS) || - (btnPtr->fsStyle & BTNS_AUTOSIZE)) - { - SIZE sz; - HDC hdc; - HFONT hOldFont; - - hdc = GetDC (hwnd); - hOldFont = SelectObject (hdc, infoPtr->hFont); - - TOOLBAR_MeasureString(infoPtr, btnPtr, hdc, &sz); - - SelectObject (hdc, hOldFont); - ReleaseDC (hwnd, hdc); - - /* add space on for button frame, etc */ - cx = sz.cx + infoPtr->szPadding.cx; - - /* add list padding */ - if ((dwStyle & TBSTYLE_LIST) && sz.cx > 0) - cx += TOOLBAR_GetListTextOffset(infoPtr, infoPtr->iListGap) + infoPtr->szPadding.cx/2; - - if (TOOLBAR_TestImageExist (infoPtr, btnPtr, GETDEFIMAGELIST(infoPtr,0))) - { - if (dwStyle & TBSTYLE_LIST) - cx += infoPtr->nBitmapWidth; - else if (cx < (infoPtr->nBitmapWidth+infoPtr->szPadding.cx)) - cx = infoPtr->nBitmapWidth+infoPtr->szPadding.cx; - } - else if (dwStyle & TBSTYLE_LIST) - cx += LIST_IMAGE_ABSENT_WIDTH; - } - else - cx = infoPtr->nButtonWidth; - - /* if size has been set manually then don't add on extra space - * for the drop down arrow */ - if (!btnPtr->cx && hasDropDownArrows && - ((btnPtr->fsStyle & BTNS_DROPDOWN) || (btnPtr->fsStyle & BTNS_WHOLEDROPDOWN))) - cx += DDARROW_WIDTH; - } - if (btnPtr->fsState & TBSTATE_WRAP ) - bWrap = TRUE; - - SetRect (&btnPtr->rect, x, y, x + cx, y + cy); - - if (infoPtr->rcBound.left > x) - infoPtr->rcBound.left = x; - if (infoPtr->rcBound.right < x + cx) - infoPtr->rcBound.right = x + cx; - if (infoPtr->rcBound.bottom < y + cy) - infoPtr->rcBound.bottom = y + cy; - - /* Set the toolTip only for non-hidden, non-separator button */ - if (infoPtr->hwndToolTip && !(btnPtr->fsStyle & BTNS_SEP )) - { - TTTOOLINFOW ti; - - ZeroMemory (&ti, sizeof(ti)); - ti.cbSize = sizeof(ti); - ti.hwnd = hwnd; - ti.uId = btnPtr->idCommand; - ti.rect = btnPtr->rect; - SendMessageW (infoPtr->hwndToolTip, TTM_NEWTOOLRECTW, - 0, (LPARAM)&ti); - } - - /* btnPtr->nRow is zero based. The space between the rows is */ - /* also considered as a row. */ - btnPtr->nRow = nRows + nSepRows; - - TRACE("button %d style=%x, bWrap=%d, nRows=%d, nSepRows=%d, btnrow=%d, (%d,%d)-(%d,%d)\n", - i, btnPtr->fsStyle, bWrap, nRows, nSepRows, btnPtr->nRow, - x, y, x+cx, y+cy); - - if( bWrap ) - { - if ( !(btnPtr->fsStyle & BTNS_SEP) ) - y += cy; - else - { - /* UNDOCUMENTED: If a separator has a non zero bitmap index, */ - /* it is the actual width of the separator. This is used for */ - /* custom controls in toolbars. */ - if ( !(btnPtr->fsStyle & BTNS_DROPDOWN)) - y += cy + ( (btnPtr->iBitmap > 0 ) ? - btnPtr->iBitmap : SEPARATOR_WIDTH) * 2 /3; - else - y += cy; - - /* nSepRows is used to calculate the extra height follwoing */ - /* the last row. */ - nSepRows++; - } - x = infoPtr->nIndent; - - /* Increment row number unless this is the last button */ - /* and it has Wrap set. */ - if (i != infoPtr->nNumButtons-1) - nRows++; - } - else - x += cx; - } - - /* infoPtr->nRows is the number of rows on the toolbar */ - infoPtr->nRows = nRows + nSepRows + 1; - -#if 0 - /******************************************************************** - * The following while interesting, does not match the values * - * created above for the button rectangles, nor the rcBound rect. * - * We will comment it out and remove it later. * - * * - * The problem showed up as heights in the pager control that was * - * wrong. * - ********************************************************************/ - - /* nSepRows * (infoPtr->nBitmapHeight + 1) is the space following */ - /* the last row. */ - infoPtr->nHeight = TOP_BORDER + (nRows + 1) * infoPtr->nButtonHeight + - nSepRows * (SEPARATOR_WIDTH * 2 / 3) + - nSepRows * (infoPtr->nBitmapHeight + 1) + - BOTTOM_BORDER; -#endif - - infoPtr->nHeight = infoPtr->rcBound.bottom - infoPtr->rcBound.top; - - TRACE("toolbar height %d, button width %d\n", infoPtr->nHeight, infoPtr->nButtonWidth); -} - - -static INT -TOOLBAR_InternalHitTest (HWND hwnd, LPPOINT lpPt) -{ - TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd); - TBUTTON_INFO *btnPtr; - INT i; - - btnPtr = infoPtr->buttons; - for (i = 0; i < infoPtr->nNumButtons; i++, btnPtr++) { - if (btnPtr->fsState & TBSTATE_HIDDEN) - continue; - - if (btnPtr->fsStyle & BTNS_SEP) { - if (PtInRect (&btnPtr->rect, *lpPt)) { - TRACE(" ON SEPARATOR %d!\n", i); - return -i; - } - } - else { - if (PtInRect (&btnPtr->rect, *lpPt)) { - TRACE(" ON BUTTON %d!\n", i); - return i; - } - } - } - - TRACE(" NOWHERE!\n"); - return TOOLBAR_NOWHERE; -} - - -static INT -TOOLBAR_GetButtonIndex (TOOLBAR_INFO *infoPtr, INT idCommand, BOOL CommandIsIndex) -{ - TBUTTON_INFO *btnPtr; - INT i; - - if (CommandIsIndex) { - TRACE("command is really index command=%d\n", idCommand); - if (idCommand >= infoPtr->nNumButtons) return -1; - return idCommand; - } - btnPtr = infoPtr->buttons; - for (i = 0; i < infoPtr->nNumButtons; i++, btnPtr++) { - if (btnPtr->idCommand == idCommand) { - TRACE("command=%d index=%d\n", idCommand, i); - return i; - } - } - TRACE("no index found for command=%d\n", idCommand); - return -1; -} - - -static INT -TOOLBAR_GetCheckedGroupButtonIndex (TOOLBAR_INFO *infoPtr, INT nIndex) -{ - TBUTTON_INFO *btnPtr; - INT nRunIndex; - - if ((nIndex < 0) || (nIndex > infoPtr->nNumButtons)) - return -1; - - /* check index button */ - btnPtr = &infoPtr->buttons[nIndex]; - if ((btnPtr->fsStyle & BTNS_CHECKGROUP) == BTNS_CHECKGROUP) { - if (btnPtr->fsState & TBSTATE_CHECKED) - return nIndex; - } - - /* check previous buttons */ - nRunIndex = nIndex - 1; - while (nRunIndex >= 0) { - btnPtr = &infoPtr->buttons[nRunIndex]; - if ((btnPtr->fsStyle & BTNS_CHECKGROUP) == BTNS_CHECKGROUP) { - if (btnPtr->fsState & TBSTATE_CHECKED) - return nRunIndex; - } - else - break; - nRunIndex--; - } - - /* check next buttons */ - nRunIndex = nIndex + 1; - while (nRunIndex < infoPtr->nNumButtons) { - btnPtr = &infoPtr->buttons[nRunIndex]; - if ((btnPtr->fsStyle & BTNS_CHECKGROUP) == BTNS_CHECKGROUP) { - if (btnPtr->fsState & TBSTATE_CHECKED) - return nRunIndex; - } - else - break; - nRunIndex++; - } - - return -1; -} - - -static VOID -TOOLBAR_RelayEvent (HWND hwndTip, HWND hwndMsg, UINT uMsg, - WPARAM wParam, LPARAM lParam) -{ - MSG msg; - - msg.hwnd = hwndMsg; - msg.message = uMsg; - msg.wParam = wParam; - msg.lParam = lParam; - msg.time = GetMessageTime (); - msg.pt.x = LOWORD(GetMessagePos ()); - msg.pt.y = HIWORD(GetMessagePos ()); - - SendMessageW (hwndTip, TTM_RELAYEVENT, 0, (LPARAM)&msg); -} - -/* keeps available button list box sorted by button id */ -static void TOOLBAR_Cust_InsertAvailButton(HWND hwnd, PCUSTOMBUTTON btnInfoNew) -{ - int i; - int count; - PCUSTOMBUTTON btnInfo; - HWND hwndAvail = GetDlgItem(hwnd, IDC_AVAILBTN_LBOX); - - TRACE("button %s, idCommand %d\n", debugstr_w(btnInfoNew->text), btnInfoNew->btn.idCommand); - - count = SendMessageW(hwndAvail, LB_GETCOUNT, 0, 0); - - /* position 0 is always separator */ - for (i = 1; i < count; i++) - { - btnInfo = (PCUSTOMBUTTON)SendMessageW(hwndAvail, LB_GETITEMDATA, i, 0); - if (btnInfoNew->btn.idCommand < btnInfo->btn.idCommand) - { - i = SendMessageW(hwndAvail, LB_INSERTSTRING, i, 0); - SendMessageW(hwndAvail, LB_SETITEMDATA, i, (LPARAM)btnInfoNew); - return; - } - } - /* id higher than all others add to end */ - i = SendMessageW(hwndAvail, LB_ADDSTRING, 0, 0); - SendMessageW(hwndAvail, LB_SETITEMDATA, i, (LPARAM)btnInfoNew); -} - -static void TOOLBAR_Cust_MoveButton(PCUSTDLG_INFO custInfo, HWND hwnd, INT nIndexFrom, INT nIndexTo) -{ - NMTOOLBARW nmtb; - - TRACE("index from %d, index to %d\n", nIndexFrom, nIndexTo); - - if (nIndexFrom == nIndexTo) - return; - - /* MSDN states that iItem is the index of the button, rather than the - * command ID as used by every other NMTOOLBAR notification */ - nmtb.iItem = nIndexFrom; - if (TOOLBAR_SendNotify(&nmtb.hdr, custInfo->tbInfo, TBN_QUERYINSERT)) - { - PCUSTOMBUTTON btnInfo; - NMHDR hdr; - HWND hwndList = GetDlgItem(hwnd, IDC_TOOLBARBTN_LBOX); - int count = SendMessageW(hwndList, LB_GETCOUNT, 0, 0); - - btnInfo = (PCUSTOMBUTTON)SendMessageW(hwndList, LB_GETITEMDATA, nIndexFrom, 0); - - SendMessageW(hwndList, LB_DELETESTRING, nIndexFrom, 0); - SendMessageW(hwndList, LB_INSERTSTRING, nIndexTo, 0); - SendMessageW(hwndList, LB_SETITEMDATA, nIndexTo, (LPARAM)btnInfo); - SendMessageW(hwndList, LB_SETCURSEL, nIndexTo, 0); - - if (nIndexTo <= 0) - EnableWindow(GetDlgItem(hwnd,IDC_MOVEUP_BTN), FALSE); - else - EnableWindow(GetDlgItem(hwnd,IDC_MOVEUP_BTN), TRUE); - - /* last item is always separator, so -2 instead of -1 */ - if (nIndexTo >= (count - 2)) - EnableWindow(GetDlgItem(hwnd,IDC_MOVEDN_BTN), FALSE); - else - EnableWindow(GetDlgItem(hwnd,IDC_MOVEDN_BTN), TRUE); - - SendMessageW(custInfo->tbHwnd, TB_DELETEBUTTON, nIndexFrom, 0); - SendMessageW(custInfo->tbHwnd, TB_INSERTBUTTONW, nIndexTo, (LPARAM)&(btnInfo->btn)); - - TOOLBAR_SendNotify(&hdr, custInfo->tbInfo, TBN_TOOLBARCHANGE); - } -} - -static void TOOLBAR_Cust_AddButton(PCUSTDLG_INFO custInfo, HWND hwnd, INT nIndexAvail, INT nIndexTo) -{ - NMTOOLBARW nmtb; - - TRACE("Add: nIndexAvail %d, nIndexTo %d\n", nIndexAvail, nIndexTo); - - /* MSDN states that iItem is the index of the button, rather than the - * command ID as used by every other NMTOOLBAR notification */ - nmtb.iItem = nIndexAvail; - if (TOOLBAR_SendNotify(&nmtb.hdr, custInfo->tbInfo, TBN_QUERYINSERT)) - { - PCUSTOMBUTTON btnInfo; - NMHDR hdr; - HWND hwndList = GetDlgItem(hwnd, IDC_TOOLBARBTN_LBOX); - HWND hwndAvail = GetDlgItem(hwnd, IDC_AVAILBTN_LBOX); - int count = SendMessageW(hwndAvail, LB_GETCOUNT, 0, 0); - - btnInfo = (PCUSTOMBUTTON)SendMessageW(hwndAvail, LB_GETITEMDATA, nIndexAvail, 0); - - if (nIndexAvail != 0) /* index == 0 indicates separator */ - { - /* remove from 'available buttons' list */ - SendMessageW(hwndAvail, LB_DELETESTRING, nIndexAvail, 0); - if (nIndexAvail == count-1) - SendMessageW(hwndAvail, LB_SETCURSEL, nIndexAvail-1 , 0); - else - SendMessageW(hwndAvail, LB_SETCURSEL, nIndexAvail , 0); - } - else - { - PCUSTOMBUTTON btnNew; - - /* duplicate 'separator' button */ - btnNew = (PCUSTOMBUTTON)Alloc(sizeof(CUSTOMBUTTON)); - memcpy(btnNew, btnInfo, sizeof(CUSTOMBUTTON)); - btnInfo = btnNew; - } - - /* insert into 'toolbar button' list */ - SendMessageW(hwndList, LB_INSERTSTRING, nIndexTo, 0); - SendMessageW(hwndList, LB_SETITEMDATA, nIndexTo, (LPARAM)btnInfo); - - SendMessageW(custInfo->tbHwnd, TB_INSERTBUTTONW, nIndexTo, (LPARAM)&(btnInfo->btn)); - - TOOLBAR_SendNotify(&hdr, custInfo->tbInfo, TBN_TOOLBARCHANGE); - } -} - -static void TOOLBAR_Cust_RemoveButton(PCUSTDLG_INFO custInfo, HWND hwnd, INT index) -{ - PCUSTOMBUTTON btnInfo; - HWND hwndList = GetDlgItem(hwnd, IDC_TOOLBARBTN_LBOX); - - TRACE("Remove: index %d\n", index); - - btnInfo = (PCUSTOMBUTTON)SendMessageW(hwndList, LB_GETITEMDATA, index, 0); - - /* send TBN_QUERYDELETE notification */ - if (TOOLBAR_IsButtonRemovable(custInfo->tbInfo, index, btnInfo)) - { - NMHDR hdr; - - SendMessageW(hwndList, LB_DELETESTRING, index, 0); - SendMessageW(hwndList, LB_SETCURSEL, index , 0); - - SendMessageW(custInfo->tbHwnd, TB_DELETEBUTTON, index, 0); - - /* insert into 'available button' list */ - if (!(btnInfo->btn.fsStyle & BTNS_SEP)) - TOOLBAR_Cust_InsertAvailButton(hwnd, btnInfo); - else - Free(btnInfo); - - TOOLBAR_SendNotify(&hdr, custInfo->tbInfo, TBN_TOOLBARCHANGE); - } -} - -/* drag list notification function for toolbar buttons list box */ -static LRESULT TOOLBAR_Cust_ToolbarDragListNotification(PCUSTDLG_INFO custInfo, HWND hwnd, DRAGLISTINFO *pDLI) -{ - HWND hwndList = GetDlgItem(hwnd, IDC_TOOLBARBTN_LBOX); - switch (pDLI->uNotification) - { - case DL_BEGINDRAG: - { - INT nCurrentItem = LBItemFromPt(hwndList, pDLI->ptCursor, TRUE); - INT nCount = SendMessageW(hwndList, LB_GETCOUNT, 0, 0); - /* no dragging for last item (separator) */ - if (nCurrentItem >= (nCount - 1)) return FALSE; - return TRUE; - } - case DL_DRAGGING: - { - INT nCurrentItem = LBItemFromPt(hwndList, pDLI->ptCursor, TRUE); - INT nCount = SendMessageW(hwndList, LB_GETCOUNT, 0, 0); - /* no dragging past last item (separator) */ - if ((nCurrentItem >= 0) && (nCurrentItem < (nCount - 1))) - { - DrawInsert(hwnd, hwndList, nCurrentItem); - /* FIXME: native uses "move button" cursor */ - return DL_COPYCURSOR; - } - - /* not over toolbar buttons list */ - if (nCurrentItem < 0) - { - POINT ptWindow = pDLI->ptCursor; - HWND hwndListAvail = GetDlgItem(hwnd, IDC_AVAILBTN_LBOX); - MapWindowPoints(NULL, hwnd, &ptWindow, 1); - /* over available buttons list? */ - if (ChildWindowFromPoint(hwnd, ptWindow) == hwndListAvail) - /* FIXME: native uses "move button" cursor */ - return DL_COPYCURSOR; - } - /* clear drag arrow */ - DrawInsert(hwnd, hwndList, -1); - return DL_STOPCURSOR; - } - case DL_DROPPED: - { - INT nIndexTo = LBItemFromPt(hwndList, pDLI->ptCursor, TRUE); - INT nIndexFrom = SendMessageW(hwndList, LB_GETCURSEL, 0, 0); - INT nCount = SendMessageW(hwndList, LB_GETCOUNT, 0, 0); - if ((nIndexTo >= 0) && (nIndexTo < (nCount - 1))) - { - /* clear drag arrow */ - DrawInsert(hwnd, hwndList, -1); - /* move item */ - TOOLBAR_Cust_MoveButton(custInfo, hwnd, nIndexFrom, nIndexTo); - } - /* not over toolbar buttons list */ - if (nIndexTo < 0) - { - POINT ptWindow = pDLI->ptCursor; - HWND hwndListAvail = GetDlgItem(hwnd, IDC_AVAILBTN_LBOX); - MapWindowPoints(NULL, hwnd, &ptWindow, 1); - /* over available buttons list? */ - if (ChildWindowFromPoint(hwnd, ptWindow) == hwndListAvail) - TOOLBAR_Cust_RemoveButton(custInfo, hwnd, nIndexFrom); - } - break; - } - case DL_CANCELDRAG: - /* Clear drag arrow */ - DrawInsert(hwnd, hwndList, -1); - break; - } - - return 0; -} - -/* drag list notification function for available buttons list box */ -static LRESULT TOOLBAR_Cust_AvailDragListNotification(PCUSTDLG_INFO custInfo, HWND hwnd, DRAGLISTINFO *pDLI) -{ - HWND hwndList = GetDlgItem(hwnd, IDC_TOOLBARBTN_LBOX); - switch (pDLI->uNotification) - { - case DL_BEGINDRAG: - return TRUE; - case DL_DRAGGING: - { - INT nCurrentItem = LBItemFromPt(hwndList, pDLI->ptCursor, TRUE); - INT nCount = SendMessageW(hwndList, LB_GETCOUNT, 0, 0); - /* no dragging past last item (separator) */ - if ((nCurrentItem >= 0) && (nCurrentItem < nCount)) - { - DrawInsert(hwnd, hwndList, nCurrentItem); - /* FIXME: native uses "move button" cursor */ - return DL_COPYCURSOR; - } - - /* not over toolbar buttons list */ - if (nCurrentItem < 0) - { - POINT ptWindow = pDLI->ptCursor; - HWND hwndListAvail = GetDlgItem(hwnd, IDC_AVAILBTN_LBOX); - MapWindowPoints(NULL, hwnd, &ptWindow, 1); - /* over available buttons list? */ - if (ChildWindowFromPoint(hwnd, ptWindow) == hwndListAvail) - /* FIXME: native uses "move button" cursor */ - return DL_COPYCURSOR; - } - /* clear drag arrow */ - DrawInsert(hwnd, hwndList, -1); - return DL_STOPCURSOR; - } - case DL_DROPPED: - { - INT nIndexTo = LBItemFromPt(hwndList, pDLI->ptCursor, TRUE); - INT nCount = SendMessageW(hwndList, LB_GETCOUNT, 0, 0); - INT nIndexFrom = SendDlgItemMessageW(hwnd, IDC_AVAILBTN_LBOX, LB_GETCURSEL, 0, 0); - if ((nIndexTo >= 0) && (nIndexTo < nCount)) - { - /* clear drag arrow */ - DrawInsert(hwnd, hwndList, -1); - /* add item */ - TOOLBAR_Cust_AddButton(custInfo, hwnd, nIndexFrom, nIndexTo); - } - } - case DL_CANCELDRAG: - /* Clear drag arrow */ - DrawInsert(hwnd, hwndList, -1); - break; - } - return 0; -} - -extern UINT uDragListMessage; - -/*********************************************************************** - * TOOLBAR_CustomizeDialogProc - * This function implements the toolbar customization dialog. - */ -static INT_PTR CALLBACK -TOOLBAR_CustomizeDialogProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam) -{ - PCUSTDLG_INFO custInfo = (PCUSTDLG_INFO)GetWindowLongPtrW (hwnd, DWLP_USER); - PCUSTOMBUTTON btnInfo; - NMTOOLBARA nmtb; - TOOLBAR_INFO *infoPtr = custInfo ? custInfo->tbInfo : NULL; - - switch (uMsg) - { - case WM_INITDIALOG: - custInfo = (PCUSTDLG_INFO)lParam; - SetWindowLongPtrW (hwnd, DWLP_USER, (LONG_PTR)custInfo); - - if (custInfo) - { - WCHAR Buffer[256]; - int i = 0; - int index; - - infoPtr = custInfo->tbInfo; - - /* send TBN_QUERYINSERT notification */ - nmtb.iItem = custInfo->tbInfo->nNumButtons; - - if (!TOOLBAR_SendNotify(&nmtb.hdr, infoPtr, TBN_QUERYINSERT)) - return FALSE; - - /* UNDOCUMENTED: dialog hwnd immediately follows NMHDR */ - /* FIXME: this hack won't work on 64-bit - we need to declare a structure for this */ - nmtb.iItem = (int)hwnd; - /* Send TBN_INITCUSTOMIZE notification */ - if (TOOLBAR_SendNotify ((NMHDR *) &nmtb, infoPtr, TBN_INITCUSTOMIZE) == - TBNRF_HIDEHELP) - { - TRACE("TBNRF_HIDEHELP requested\n"); - ShowWindow(GetDlgItem(hwnd, IDC_HELP_BTN), SW_HIDE); - } - - /* add items to 'toolbar buttons' list and check if removable */ - for (i = 0; i < custInfo->tbInfo->nNumButtons; i++) - { - btnInfo = (PCUSTOMBUTTON)Alloc(sizeof(CUSTOMBUTTON)); - memset (&btnInfo->btn, 0, sizeof(TBBUTTON)); - btnInfo->btn.fsStyle = BTNS_SEP; - btnInfo->bVirtual = FALSE; - LoadStringW (COMCTL32_hModule, IDS_SEPARATOR, btnInfo->text, 64); - - /* send TBN_QUERYDELETE notification */ - btnInfo->bRemovable = TOOLBAR_IsButtonRemovable(infoPtr, i, btnInfo); - - index = (int)SendDlgItemMessageW (hwnd, IDC_TOOLBARBTN_LBOX, LB_ADDSTRING, 0, 0); - SendDlgItemMessageW (hwnd, IDC_TOOLBARBTN_LBOX, LB_SETITEMDATA, index, (LPARAM)btnInfo); - } - - SendDlgItemMessageW (hwnd, IDC_TOOLBARBTN_LBOX, LB_SETITEMHEIGHT, 0, infoPtr->nBitmapHeight + 8); - - /* insert separator button into 'available buttons' list */ - btnInfo = (PCUSTOMBUTTON)Alloc(sizeof(CUSTOMBUTTON)); - memset (&btnInfo->btn, 0, sizeof(TBBUTTON)); - btnInfo->btn.fsStyle = BTNS_SEP; - btnInfo->bVirtual = FALSE; - btnInfo->bRemovable = TRUE; - LoadStringW (COMCTL32_hModule, IDS_SEPARATOR, btnInfo->text, 64); - index = (int)SendDlgItemMessageW (hwnd, IDC_AVAILBTN_LBOX, LB_ADDSTRING, 0, (LPARAM)btnInfo); - SendDlgItemMessageW (hwnd, IDC_AVAILBTN_LBOX, LB_SETITEMDATA, index, (LPARAM)btnInfo); - - /* insert all buttons into dsa */ - for (i = 0;; i++) - { - /* send TBN_GETBUTTONINFO notification */ - NMTOOLBARW nmtb; - nmtb.iItem = i; - nmtb.pszText = Buffer; - nmtb.cchText = 256; - - /* Clear previous button's text */ - ZeroMemory(nmtb.pszText, nmtb.cchText * sizeof(WCHAR)); - - if (!TOOLBAR_GetButtonInfo(infoPtr, &nmtb)) - break; - - TRACE("WM_INITDIALOG style: %x iItem(%d) idCommand(%d) iString(%d) %s\n", - nmtb.tbButton.fsStyle, i, - nmtb.tbButton.idCommand, - nmtb.tbButton.iString, - nmtb.tbButton.iString >= 0 ? debugstr_w(infoPtr->strings[nmtb.tbButton.iString]) - : ""); - - /* insert button into the apropriate list */ - index = TOOLBAR_GetButtonIndex (custInfo->tbInfo, nmtb.tbButton.idCommand, FALSE); - if (index == -1) - { - btnInfo = (PCUSTOMBUTTON)Alloc(sizeof(CUSTOMBUTTON)); - btnInfo->bVirtual = FALSE; - btnInfo->bRemovable = TRUE; - } - else - { - btnInfo = (PCUSTOMBUTTON)SendDlgItemMessageW (hwnd, - IDC_TOOLBARBTN_LBOX, LB_GETITEMDATA, index, 0); - } - - memcpy (&btnInfo->btn, &nmtb.tbButton, sizeof(TBBUTTON)); - if (!(nmtb.tbButton.fsStyle & BTNS_SEP)) - { - if (lstrlenW(nmtb.pszText)) - lstrcpyW(btnInfo->text, nmtb.pszText); - else if (nmtb.tbButton.iString >= 0 && - nmtb.tbButton.iString < infoPtr->nNumStrings) - { - lstrcpyW(btnInfo->text, - infoPtr->strings[nmtb.tbButton.iString]); - } - } - - if (index == -1) - TOOLBAR_Cust_InsertAvailButton(hwnd, btnInfo); - } - - SendDlgItemMessageW (hwnd, IDC_AVAILBTN_LBOX, LB_SETITEMHEIGHT, 0, infoPtr->nBitmapHeight + 8); - - /* select first item in the 'available' list */ - SendDlgItemMessageW (hwnd, IDC_AVAILBTN_LBOX, LB_SETCURSEL, 0, 0); - - /* append 'virtual' separator button to the 'toolbar buttons' list */ - btnInfo = (PCUSTOMBUTTON)Alloc(sizeof(CUSTOMBUTTON)); - memset (&btnInfo->btn, 0, sizeof(TBBUTTON)); - btnInfo->btn.fsStyle = BTNS_SEP; - btnInfo->bVirtual = TRUE; - btnInfo->bRemovable = FALSE; - LoadStringW (COMCTL32_hModule, IDS_SEPARATOR, btnInfo->text, 64); - index = (int)SendDlgItemMessageW (hwnd, IDC_TOOLBARBTN_LBOX, LB_ADDSTRING, 0, (LPARAM)btnInfo); - SendDlgItemMessageW (hwnd, IDC_TOOLBARBTN_LBOX, LB_SETITEMDATA, index, (LPARAM)btnInfo); - - /* select last item in the 'toolbar' list */ - SendDlgItemMessageW (hwnd, IDC_TOOLBARBTN_LBOX, LB_SETCURSEL, index, 0); - SendDlgItemMessageW (hwnd, IDC_TOOLBARBTN_LBOX, LB_SETTOPINDEX, index, 0); - - MakeDragList(GetDlgItem(hwnd, IDC_TOOLBARBTN_LBOX)); - MakeDragList(GetDlgItem(hwnd, IDC_AVAILBTN_LBOX)); - - /* set focus and disable buttons */ - PostMessageW (hwnd, WM_USER, 0, 0); - } - return TRUE; - - case WM_USER: - EnableWindow (GetDlgItem (hwnd,IDC_MOVEUP_BTN), FALSE); - EnableWindow (GetDlgItem (hwnd,IDC_MOVEDN_BTN), FALSE); - EnableWindow (GetDlgItem (hwnd,IDC_REMOVE_BTN), FALSE); - SetFocus (GetDlgItem (hwnd, IDC_TOOLBARBTN_LBOX)); - return TRUE; - - case WM_CLOSE: - EndDialog(hwnd, FALSE); - return TRUE; - - case WM_COMMAND: - switch (LOWORD(wParam)) - { - case IDC_TOOLBARBTN_LBOX: - if (HIWORD(wParam) == LBN_SELCHANGE) - { - PCUSTOMBUTTON btnInfo; - NMTOOLBARA nmtb; - int count; - int index; - - count = SendDlgItemMessageW (hwnd, IDC_TOOLBARBTN_LBOX, LB_GETCOUNT, 0, 0); - index = SendDlgItemMessageW (hwnd, IDC_TOOLBARBTN_LBOX, LB_GETCURSEL, 0, 0); - - /* send TBN_QUERYINSERT notification */ - nmtb.iItem = index; - TOOLBAR_SendNotify(&nmtb.hdr, infoPtr, TBN_QUERYINSERT); - - /* get list box item */ - btnInfo = (PCUSTOMBUTTON)SendDlgItemMessageW (hwnd, IDC_TOOLBARBTN_LBOX, LB_GETITEMDATA, index, 0); - - if (index == (count - 1)) - { - /* last item (virtual separator) */ - EnableWindow (GetDlgItem (hwnd,IDC_MOVEUP_BTN), FALSE); - EnableWindow (GetDlgItem (hwnd,IDC_MOVEDN_BTN), FALSE); - } - else if (index == (count - 2)) - { - /* second last item (last non-virtual item) */ - EnableWindow (GetDlgItem (hwnd,IDC_MOVEUP_BTN), TRUE); - EnableWindow (GetDlgItem (hwnd,IDC_MOVEDN_BTN), FALSE); - } - else if (index == 0) - { - /* first item */ - EnableWindow (GetDlgItem (hwnd,IDC_MOVEUP_BTN), FALSE); - EnableWindow (GetDlgItem (hwnd,IDC_MOVEDN_BTN), TRUE); - } - else - { - EnableWindow (GetDlgItem (hwnd,IDC_MOVEUP_BTN), TRUE); - EnableWindow (GetDlgItem (hwnd,IDC_MOVEDN_BTN), TRUE); - } - - EnableWindow (GetDlgItem (hwnd,IDC_REMOVE_BTN), btnInfo->bRemovable); - } - break; - - case IDC_MOVEUP_BTN: - { - int index = SendDlgItemMessageW (hwnd, IDC_TOOLBARBTN_LBOX, LB_GETCURSEL, 0, 0); - TOOLBAR_Cust_MoveButton(custInfo, hwnd, index, index-1); - } - break; - - case IDC_MOVEDN_BTN: /* move down */ - { - int index = SendDlgItemMessageW (hwnd, IDC_TOOLBARBTN_LBOX, LB_GETCURSEL, 0, 0); - TOOLBAR_Cust_MoveButton(custInfo, hwnd, index, index+1); - } - break; - - case IDC_REMOVE_BTN: /* remove button */ - { - int index = SendDlgItemMessageW (hwnd, IDC_TOOLBARBTN_LBOX, LB_GETCURSEL, 0, 0); - - if (LB_ERR == index) - break; - - TOOLBAR_Cust_RemoveButton(custInfo, hwnd, index); - } - break; - case IDC_HELP_BTN: - TOOLBAR_SendNotify(&nmtb.hdr, infoPtr, TBN_CUSTHELP); - break; - case IDC_RESET_BTN: - TOOLBAR_SendNotify(&nmtb.hdr, infoPtr, TBN_RESET); - break; - - case IDOK: /* Add button */ - { - int index; - int indexto; - - index = SendDlgItemMessageW(hwnd, IDC_AVAILBTN_LBOX, LB_GETCURSEL, 0, 0); - indexto = SendDlgItemMessageW(hwnd, IDC_TOOLBARBTN_LBOX, LB_GETCURSEL, 0, 0); - - TOOLBAR_Cust_AddButton(custInfo, hwnd, index, indexto); - } - break; - - case IDCANCEL: - EndDialog(hwnd, FALSE); - break; - } - return TRUE; - - case WM_DESTROY: - { - int count; - int i; - - /* delete items from 'toolbar buttons' listbox*/ - count = SendDlgItemMessageW (hwnd, IDC_TOOLBARBTN_LBOX, LB_GETCOUNT, 0, 0); - for (i = 0; i < count; i++) - { - btnInfo = (PCUSTOMBUTTON)SendDlgItemMessageW (hwnd, IDC_TOOLBARBTN_LBOX, LB_GETITEMDATA, i, 0); - Free(btnInfo); - SendDlgItemMessageW (hwnd, IDC_TOOLBARBTN_LBOX, LB_SETITEMDATA, 0, 0); - } - SendDlgItemMessageW (hwnd, IDC_TOOLBARBTN_LBOX, LB_RESETCONTENT, 0, 0); - - - /* delete items from 'available buttons' listbox*/ - count = SendDlgItemMessageW (hwnd, IDC_AVAILBTN_LBOX, LB_GETCOUNT, 0, 0); - for (i = 0; i < count; i++) - { - btnInfo = (PCUSTOMBUTTON)SendDlgItemMessageW (hwnd, IDC_AVAILBTN_LBOX, LB_GETITEMDATA, i, 0); - Free(btnInfo); - SendDlgItemMessageW (hwnd, IDC_AVAILBTN_LBOX, LB_SETITEMDATA, i, 0); - } - SendDlgItemMessageW (hwnd, IDC_AVAILBTN_LBOX, LB_RESETCONTENT, 0, 0); - } - return TRUE; - - case WM_DRAWITEM: - if (wParam == IDC_AVAILBTN_LBOX || wParam == IDC_TOOLBARBTN_LBOX) - { - LPDRAWITEMSTRUCT lpdis = (LPDRAWITEMSTRUCT)lParam; - RECT rcButton; - RECT rcText; - HPEN hPen, hOldPen; - HBRUSH hOldBrush; - COLORREF oldText = 0; - COLORREF oldBk = 0; - - /* get item data */ - btnInfo = (PCUSTOMBUTTON)SendDlgItemMessageW (hwnd, wParam, LB_GETITEMDATA, (WPARAM)lpdis->itemID, 0); - if (btnInfo == NULL) - { - FIXME("btnInfo invalid!\n"); - return TRUE; - } - - /* set colors and select objects */ - oldBk = SetBkColor (lpdis->hDC, (lpdis->itemState & ODS_FOCUS)?comctl32_color.clrHighlight:comctl32_color.clrWindow); - if (btnInfo->bVirtual) - oldText = SetTextColor (lpdis->hDC, comctl32_color.clrGrayText); - else - oldText = SetTextColor (lpdis->hDC, (lpdis->itemState & ODS_FOCUS)?comctl32_color.clrHighlightText:comctl32_color.clrWindowText); - hPen = CreatePen( PS_SOLID, 1, - GetSysColor( (lpdis->itemState & ODS_SELECTED)?COLOR_HIGHLIGHT:COLOR_WINDOW)); - hOldPen = SelectObject (lpdis->hDC, hPen ); - hOldBrush = SelectObject (lpdis->hDC, GetSysColorBrush ((lpdis->itemState & ODS_FOCUS)?COLOR_HIGHLIGHT:COLOR_WINDOW)); - - /* fill background rectangle */ - Rectangle (lpdis->hDC, lpdis->rcItem.left, lpdis->rcItem.top, - lpdis->rcItem.right, lpdis->rcItem.bottom); - - /* calculate button and text rectangles */ - CopyRect (&rcButton, &lpdis->rcItem); - InflateRect (&rcButton, -1, -1); - CopyRect (&rcText, &rcButton); - rcButton.right = rcButton.left + custInfo->tbInfo->nBitmapWidth + 6; - rcText.left = rcButton.right + 2; - - /* draw focus rectangle */ - if (lpdis->itemState & ODS_FOCUS) - DrawFocusRect (lpdis->hDC, &lpdis->rcItem); - - /* draw button */ - if (!(infoPtr->dwStyle & TBSTYLE_FLAT)) - DrawEdge (lpdis->hDC, &rcButton, EDGE_RAISED, BF_RECT|BF_MIDDLE|BF_SOFT); - - /* draw image and text */ - if ((btnInfo->btn.fsStyle & BTNS_SEP) == 0) { - HIMAGELIST himl = GETDEFIMAGELIST(infoPtr, GETHIMLID(infoPtr, - btnInfo->btn.iBitmap)); - ImageList_Draw (himl, GETIBITMAP(infoPtr, btnInfo->btn.iBitmap), - lpdis->hDC, rcButton.left+3, rcButton.top+3, ILD_NORMAL); - } - DrawTextW (lpdis->hDC, btnInfo->text, -1, &rcText, - DT_LEFT | DT_VCENTER | DT_SINGLELINE); - - /* delete objects and reset colors */ - SelectObject (lpdis->hDC, hOldBrush); - SelectObject (lpdis->hDC, hOldPen); - SetBkColor (lpdis->hDC, oldBk); - SetTextColor (lpdis->hDC, oldText); - DeleteObject( hPen ); - return TRUE; - } - return FALSE; - - case WM_MEASUREITEM: - if (wParam == IDC_AVAILBTN_LBOX || wParam == IDC_TOOLBARBTN_LBOX) - { - MEASUREITEMSTRUCT *lpmis = (MEASUREITEMSTRUCT*)lParam; - - lpmis->itemHeight = 15 + 8; /* default height */ - - return TRUE; - } - return FALSE; - - default: - if (uDragListMessage && (uMsg == uDragListMessage)) - { - if (wParam == IDC_TOOLBARBTN_LBOX) - { - LRESULT res = TOOLBAR_Cust_ToolbarDragListNotification( - custInfo, hwnd, (DRAGLISTINFO *)lParam); - SetWindowLongPtrW(hwnd, DWLP_MSGRESULT, res); - return TRUE; - } - else if (wParam == IDC_AVAILBTN_LBOX) - { - LRESULT res = TOOLBAR_Cust_AvailDragListNotification( - custInfo, hwnd, (DRAGLISTINFO *)lParam); - SetWindowLongPtrW(hwnd, DWLP_MSGRESULT, res); - return TRUE; - } - } - return FALSE; - } -} - - -/*********************************************************************** - * TOOLBAR_AddBitmap: Add the bitmaps to the default image list. - * - */ -static LRESULT -TOOLBAR_AddBitmap (HWND hwnd, WPARAM wParam, LPARAM lParam) -{ - TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd); - LPTBADDBITMAP lpAddBmp = (LPTBADDBITMAP)lParam; - INT nIndex = 0, nButtons, nCount; - HBITMAP hbmLoad; - HIMAGELIST himlDef; - - TRACE("hwnd=%p wParam=%x lParam=%lx\n", hwnd, wParam, lParam); - if (!lpAddBmp) - return -1; - - if (lpAddBmp->hInst == HINST_COMMCTRL) - { - if ((lpAddBmp->nID & ~1) == IDB_STD_SMALL_COLOR) - nButtons = 15; - else if ((lpAddBmp->nID & ~1) == IDB_VIEW_SMALL_COLOR) - nButtons = 13; - else if ((lpAddBmp->nID & ~1) == IDB_HIST_SMALL_COLOR) - nButtons = 5; - else - return -1; - - TRACE ("adding %d internal bitmaps!\n", nButtons); - - /* Windows resize all the buttons to the size of a newly added standard image */ - if (lpAddBmp->nID & 1) - { - /* large icons */ - /* FIXME: on windows the size of the images is 25x24 but the size of the bitmap - * in rsrc is only 24x24. Fix the bitmap (how?) and then fix this - */ - SendMessageW (hwnd, TB_SETBITMAPSIZE, 0, - MAKELPARAM((WORD)24, (WORD)24)); - SendMessageW (hwnd, TB_SETBUTTONSIZE, 0, - MAKELPARAM((WORD)31, (WORD)30)); - } - else - { - /* small icons */ - SendMessageW (hwnd, TB_SETBITMAPSIZE, 0, - MAKELPARAM((WORD)16, (WORD)16)); - SendMessageW (hwnd, TB_SETBUTTONSIZE, 0, - MAKELPARAM((WORD)22, (WORD)22)); - } - - TOOLBAR_CalcToolbar (hwnd); - } - else - { - nButtons = (INT)wParam; - if (nButtons <= 0) - return -1; - - TRACE ("adding %d bitmaps!\n", nButtons); - } - - if (!infoPtr->cimlDef) { - /* create new default image list */ - TRACE ("creating default image list!\n"); - - himlDef = ImageList_Create (infoPtr->nBitmapWidth, infoPtr->nBitmapHeight, - ILC_COLORDDB | ILC_MASK, nButtons, 2); - TOOLBAR_InsertImageList(&infoPtr->himlDef, &infoPtr->cimlDef, himlDef, 0); - infoPtr->himlInt = himlDef; - } - else { - himlDef = GETDEFIMAGELIST(infoPtr, 0); - } - - if (!himlDef) { - WARN("No default image list available\n"); - return -1; - } - - nCount = ImageList_GetImageCount(himlDef); - - /* Add bitmaps to the default image list */ - if (lpAddBmp->hInst == NULL) - { - BITMAP bmp; - HBITMAP hOldBitmapBitmap, hOldBitmapLoad; - HDC hdcImage, hdcBitmap; - - /* copy the bitmap before adding it so that the user's bitmap - * doesn't get modified. - */ - GetObjectA ((HBITMAP)lpAddBmp->nID, sizeof(BITMAP), (LPVOID)&bmp); - - hdcImage = CreateCompatibleDC(0); - hdcBitmap = CreateCompatibleDC(0); - - /* create new bitmap */ - hbmLoad = CreateBitmap (bmp.bmWidth, bmp.bmHeight, bmp.bmPlanes, bmp.bmBitsPixel, NULL); - hOldBitmapBitmap = SelectObject(hdcBitmap, (HBITMAP)lpAddBmp->nID); - hOldBitmapLoad = SelectObject(hdcImage, hbmLoad); - - /* Copy the user's image */ - BitBlt (hdcImage, 0, 0, bmp.bmWidth, bmp.bmHeight, - hdcBitmap, 0, 0, SRCCOPY); - - SelectObject (hdcImage, hOldBitmapLoad); - SelectObject (hdcBitmap, hOldBitmapBitmap); - DeleteDC (hdcImage); - DeleteDC (hdcBitmap); - - nIndex = ImageList_AddMasked (himlDef, hbmLoad, comctl32_color.clrBtnFace); - DeleteObject (hbmLoad); - } - else if (lpAddBmp->hInst == HINST_COMMCTRL) - { - /* Add system bitmaps */ - switch (lpAddBmp->nID) - { - case IDB_STD_SMALL_COLOR: - hbmLoad = LoadBitmapA (COMCTL32_hModule, - MAKEINTRESOURCEA(IDB_STD_SMALL)); - nIndex = ImageList_AddMasked (himlDef, - hbmLoad, comctl32_color.clrBtnFace); - DeleteObject (hbmLoad); - break; - - case IDB_STD_LARGE_COLOR: - hbmLoad = LoadBitmapA (COMCTL32_hModule, - MAKEINTRESOURCEA(IDB_STD_LARGE)); - nIndex = ImageList_AddMasked (himlDef, - hbmLoad, comctl32_color.clrBtnFace); - DeleteObject (hbmLoad); - break; - - case IDB_VIEW_SMALL_COLOR: - hbmLoad = LoadBitmapA (COMCTL32_hModule, - MAKEINTRESOURCEA(IDB_VIEW_SMALL)); - nIndex = ImageList_AddMasked (himlDef, - hbmLoad, comctl32_color.clrBtnFace); - DeleteObject (hbmLoad); - break; - - case IDB_VIEW_LARGE_COLOR: - hbmLoad = LoadBitmapA (COMCTL32_hModule, - MAKEINTRESOURCEA(IDB_VIEW_LARGE)); - nIndex = ImageList_AddMasked (himlDef, - hbmLoad, comctl32_color.clrBtnFace); - DeleteObject (hbmLoad); - break; - - case IDB_HIST_SMALL_COLOR: - hbmLoad = LoadBitmapA (COMCTL32_hModule, - MAKEINTRESOURCEA(IDB_HIST_SMALL)); - nIndex = ImageList_AddMasked (himlDef, - hbmLoad, comctl32_color.clrBtnFace); - DeleteObject (hbmLoad); - break; - - case IDB_HIST_LARGE_COLOR: - hbmLoad = LoadBitmapA (COMCTL32_hModule, - MAKEINTRESOURCEA(IDB_HIST_LARGE)); - nIndex = ImageList_AddMasked (himlDef, - hbmLoad, comctl32_color.clrBtnFace); - DeleteObject (hbmLoad); - break; - - default: - nIndex = ImageList_GetImageCount (himlDef); - ERR ("invalid imagelist!\n"); - break; - } - } - else - { - hbmLoad = LoadBitmapA (lpAddBmp->hInst, (LPSTR)lpAddBmp->nID); - nIndex = ImageList_AddMasked (himlDef, hbmLoad, comctl32_color.clrBtnFace); - DeleteObject (hbmLoad); - } - - TRACE("Number of bitmap infos: %d\n", infoPtr->nNumBitmapInfos); - - if (infoPtr->nNumBitmapInfos == 0) - { - infoPtr->bitmaps = Alloc(sizeof(TBITMAP_INFO)); - } - else - { - TBITMAP_INFO *oldBitmaps = infoPtr->bitmaps; - infoPtr->bitmaps = Alloc((infoPtr->nNumBitmapInfos + 1) * sizeof(TBITMAP_INFO)); - memcpy(&infoPtr->bitmaps[0], &oldBitmaps[0], infoPtr->nNumBitmapInfos); - } - - infoPtr->bitmaps[infoPtr->nNumBitmapInfos].nButtons = nButtons; - infoPtr->bitmaps[infoPtr->nNumBitmapInfos].hInst = lpAddBmp->hInst; - infoPtr->bitmaps[infoPtr->nNumBitmapInfos].nID = lpAddBmp->nID; - - infoPtr->nNumBitmapInfos++; - TRACE("Number of bitmap infos: %d\n", infoPtr->nNumBitmapInfos); - - if (nIndex != -1) - { - INT imagecount = ImageList_GetImageCount(himlDef); - - if (infoPtr->nNumBitmaps + nButtons != imagecount) - { - WARN("Desired images do not match received images : Previous image number %i Previous images in list %i added %i expecting total %i, Images in list %i\n", - infoPtr->nNumBitmaps, nCount, imagecount - nCount, - infoPtr->nNumBitmaps+nButtons,imagecount); - - infoPtr->nNumBitmaps = imagecount; - } - else - infoPtr->nNumBitmaps += nButtons; - } - - InvalidateRect(hwnd, NULL, TRUE); - - return nIndex; -} - - -static LRESULT -TOOLBAR_AddButtonsA (HWND hwnd, WPARAM wParam, LPARAM lParam) -{ - TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd); - LPTBBUTTON lpTbb = (LPTBBUTTON)lParam; - INT nOldButtons, nNewButtons, nAddButtons, nCount; - - TRACE("adding %d buttons!\n", wParam); - - nAddButtons = (UINT)wParam; - nOldButtons = infoPtr->nNumButtons; - nNewButtons = nOldButtons + nAddButtons; - - if (infoPtr->nNumButtons == 0) { - infoPtr->buttons = - Alloc (sizeof(TBUTTON_INFO) * nNewButtons); - } - else { - TBUTTON_INFO *oldButtons = infoPtr->buttons; - infoPtr->buttons = - Alloc (sizeof(TBUTTON_INFO) * nNewButtons); - memcpy (&infoPtr->buttons[0], &oldButtons[0], - nOldButtons * sizeof(TBUTTON_INFO)); - Free (oldButtons); - } - - infoPtr->nNumButtons = nNewButtons; - - /* insert new button data */ - for (nCount = 0; nCount < nAddButtons; nCount++) { - TBUTTON_INFO *btnPtr = &infoPtr->buttons[nOldButtons+nCount]; - btnPtr->iBitmap = lpTbb[nCount].iBitmap; - btnPtr->idCommand = lpTbb[nCount].idCommand; - btnPtr->fsState = lpTbb[nCount].fsState; - btnPtr->fsStyle = lpTbb[nCount].fsStyle; - btnPtr->dwData = lpTbb[nCount].dwData; - if(HIWORD(lpTbb[nCount].iString) && lpTbb[nCount].iString != -1) - Str_SetPtrAtoW ((LPWSTR*)&btnPtr->iString, (LPSTR)lpTbb[nCount].iString ); - else - btnPtr->iString = lpTbb[nCount].iString; - btnPtr->bHot = FALSE; - - if ((infoPtr->hwndToolTip) && !(btnPtr->fsStyle & BTNS_SEP)) { - TTTOOLINFOW ti; - - ZeroMemory (&ti, sizeof(ti)); - ti.cbSize = sizeof(ti); - ti.hwnd = hwnd; - ti.uId = btnPtr->idCommand; - ti.hinst = 0; - ti.lpszText = LPSTR_TEXTCALLBACKW; - - SendMessageW (infoPtr->hwndToolTip, TTM_ADDTOOLW, - 0, (LPARAM)&ti); - } - } - - TOOLBAR_CalcToolbar (hwnd); - - TOOLBAR_DumpToolbar (infoPtr, __LINE__); - - InvalidateRect(hwnd, NULL, TRUE); - - return TRUE; -} - - -static LRESULT -TOOLBAR_AddButtonsW (HWND hwnd, WPARAM wParam, LPARAM lParam) -{ - TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd); - LPTBBUTTON lpTbb = (LPTBBUTTON)lParam; - INT nOldButtons, nNewButtons, nAddButtons, nCount; - - TRACE("adding %d buttons!\n", wParam); - - nAddButtons = (UINT)wParam; - nOldButtons = infoPtr->nNumButtons; - nNewButtons = nOldButtons + nAddButtons; - - if (infoPtr->nNumButtons == 0) { - infoPtr->buttons = - Alloc (sizeof(TBUTTON_INFO) * nNewButtons); - } - else { - TBUTTON_INFO *oldButtons = infoPtr->buttons; - infoPtr->buttons = - Alloc (sizeof(TBUTTON_INFO) * nNewButtons); - memcpy (&infoPtr->buttons[0], &oldButtons[0], - nOldButtons * sizeof(TBUTTON_INFO)); - Free (oldButtons); - } - - infoPtr->nNumButtons = nNewButtons; - - /* insert new button data */ - for (nCount = 0; nCount < nAddButtons; nCount++) { - TBUTTON_INFO *btnPtr = &infoPtr->buttons[nOldButtons+nCount]; - btnPtr->iBitmap = lpTbb[nCount].iBitmap; - btnPtr->idCommand = lpTbb[nCount].idCommand; - btnPtr->fsState = lpTbb[nCount].fsState; - btnPtr->fsStyle = lpTbb[nCount].fsStyle; - btnPtr->dwData = lpTbb[nCount].dwData; - if(HIWORD(lpTbb[nCount].iString) && lpTbb[nCount].iString != -1) - Str_SetPtrW ((LPWSTR*)&btnPtr->iString, (LPWSTR)lpTbb[nCount].iString ); - else - btnPtr->iString = lpTbb[nCount].iString; - btnPtr->bHot = FALSE; - - if ((infoPtr->hwndToolTip) && !(btnPtr->fsStyle & BTNS_SEP)) { - TTTOOLINFOW ti; - - ZeroMemory (&ti, sizeof(TTTOOLINFOW)); - ti.cbSize = sizeof (TTTOOLINFOW); - ti.hwnd = hwnd; - ti.uId = btnPtr->idCommand; - ti.hinst = 0; - ti.lpszText = LPSTR_TEXTCALLBACKW; - ti.lParam = lParam; - - SendMessageW (infoPtr->hwndToolTip, TTM_ADDTOOLW, - 0, (LPARAM)&ti); - } - } - - TOOLBAR_CalcToolbar (hwnd); - - TOOLBAR_DumpToolbar (infoPtr, __LINE__); - - InvalidateRect(hwnd, NULL, TRUE); - - return TRUE; -} - - -static LRESULT -TOOLBAR_AddStringA (HWND hwnd, WPARAM wParam, LPARAM lParam) -{ - TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd); - INT nIndex; - - if ((wParam) && (HIWORD(lParam) == 0)) { - char szString[256]; - INT len; - TRACE("adding string from resource!\n"); - - len = LoadStringA ((HINSTANCE)wParam, (UINT)lParam, - szString, 256); - - TRACE("len=%d \"%s\"\n", len, szString); - nIndex = infoPtr->nNumStrings; - if (infoPtr->nNumStrings == 0) { - infoPtr->strings = - Alloc (sizeof(LPWSTR)); - } - else { - LPWSTR *oldStrings = infoPtr->strings; - infoPtr->strings = - Alloc (sizeof(LPWSTR) * (infoPtr->nNumStrings + 1)); - memcpy (&infoPtr->strings[0], &oldStrings[0], - sizeof(LPWSTR) * infoPtr->nNumStrings); - Free (oldStrings); - } - - /*Alloc zeros out the allocated memory*/ - Str_SetPtrAtoW (&infoPtr->strings[infoPtr->nNumStrings], szString ); - infoPtr->nNumStrings++; - } - else { - LPSTR p = (LPSTR)lParam; - INT len; - - if (p == NULL) - return -1; - TRACE("adding string(s) from array!\n"); - - nIndex = infoPtr->nNumStrings; - while (*p) { - len = strlen (p); - TRACE("len=%d \"%s\"\n", len, p); - - if (infoPtr->nNumStrings == 0) { - infoPtr->strings = - Alloc (sizeof(LPWSTR)); - } - else { - LPWSTR *oldStrings = infoPtr->strings; - infoPtr->strings = - Alloc (sizeof(LPWSTR) * (infoPtr->nNumStrings + 1)); - memcpy (&infoPtr->strings[0], &oldStrings[0], - sizeof(LPWSTR) * infoPtr->nNumStrings); - Free (oldStrings); - } - - Str_SetPtrAtoW (&infoPtr->strings[infoPtr->nNumStrings], p ); - infoPtr->nNumStrings++; - - p += (len+1); - } - } - - return nIndex; -} - - -static LRESULT -TOOLBAR_AddStringW (HWND hwnd, WPARAM wParam, LPARAM lParam) -{ -#define MAX_RESOURCE_STRING_LENGTH 512 - TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd); - INT nIndex; - - if ((wParam) && (HIWORD(lParam) == 0)) { - WCHAR szString[MAX_RESOURCE_STRING_LENGTH]; - INT len; - TRACE("adding string from resource!\n"); - - len = LoadStringW ((HINSTANCE)wParam, (UINT)lParam, - szString, MAX_RESOURCE_STRING_LENGTH); - - TRACE("len=%d %s\n", len, debugstr_w(szString)); - TRACE("First char: 0x%x\n", *szString); - if (szString[0] == L'|') - { - PWSTR p = szString + 1; - - nIndex = infoPtr->nNumStrings; - while (*p != L'|' && *p != L'\0') { - PWSTR np; - - if (infoPtr->nNumStrings == 0) { - infoPtr->strings = Alloc (sizeof(LPWSTR)); - } - else - { - LPWSTR *oldStrings = infoPtr->strings; - infoPtr->strings = Alloc(sizeof(LPWSTR) * (infoPtr->nNumStrings + 1)); - memcpy(&infoPtr->strings[0], &oldStrings[0], - sizeof(LPWSTR) * infoPtr->nNumStrings); - Free(oldStrings); - } - - np=strchrW (p, '|'); - if (np!=NULL) { - len = np - p; - np++; - } else { - len = strlenW(p); - np = p + len; - } - TRACE("len=%d %s\n", len, debugstr_w(p)); - infoPtr->strings[infoPtr->nNumStrings] = - Alloc (sizeof(WCHAR)*(len+1)); - lstrcpynW (infoPtr->strings[infoPtr->nNumStrings], p, len+1); - infoPtr->nNumStrings++; - - p = np; - } - } - else - { - nIndex = infoPtr->nNumStrings; - if (infoPtr->nNumStrings == 0) { - infoPtr->strings = - Alloc (sizeof(LPWSTR)); - } - else { - LPWSTR *oldStrings = infoPtr->strings; - infoPtr->strings = - Alloc (sizeof(LPWSTR) * (infoPtr->nNumStrings + 1)); - memcpy (&infoPtr->strings[0], &oldStrings[0], - sizeof(LPWSTR) * infoPtr->nNumStrings); - Free (oldStrings); - } - - Str_SetPtrW (&infoPtr->strings[infoPtr->nNumStrings], szString); - infoPtr->nNumStrings++; - } - } - else { - LPWSTR p = (LPWSTR)lParam; - INT len; - - if (p == NULL) - return -1; - TRACE("adding string(s) from array!\n"); - nIndex = infoPtr->nNumStrings; - while (*p) { - len = strlenW (p); - - TRACE("len=%d %s\n", len, debugstr_w(p)); - if (infoPtr->nNumStrings == 0) { - infoPtr->strings = - Alloc (sizeof(LPWSTR)); - } - else { - LPWSTR *oldStrings = infoPtr->strings; - infoPtr->strings = - Alloc (sizeof(LPWSTR) * (infoPtr->nNumStrings + 1)); - memcpy (&infoPtr->strings[0], &oldStrings[0], - sizeof(LPWSTR) * infoPtr->nNumStrings); - Free (oldStrings); - } - - Str_SetPtrW (&infoPtr->strings[infoPtr->nNumStrings], p); - infoPtr->nNumStrings++; - - p += (len+1); - } - } - - return nIndex; -} - - -static LRESULT -TOOLBAR_AutoSize (HWND hwnd) -{ - TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd); - RECT parent_rect; - RECT window_rect; - HWND parent; - INT x, y; - INT cx, cy; - UINT uPosFlags = SWP_NOZORDER; - - TRACE("resize forced, style=%lx!\n", infoPtr->dwStyle); - - parent = GetParent (hwnd); - GetClientRect(parent, &parent_rect); - - x = parent_rect.left; - y = parent_rect.top; - - /* FIXME: we should be able to early out if nothing */ - /* has changed with nWidth != parent_rect width */ - - if (infoPtr->dwStyle & CCS_NORESIZE) { - uPosFlags |= (SWP_NOSIZE | SWP_NOMOVE); - cx = 0; - cy = 0; - TOOLBAR_CalcToolbar (hwnd); - } - else { - infoPtr->nWidth = parent_rect.right - parent_rect.left; - TOOLBAR_CalcToolbar (hwnd); - InvalidateRect( hwnd, NULL, TRUE ); - cy = infoPtr->nHeight; - cx = infoPtr->nWidth; - - if ((infoPtr->dwStyle & CCS_BOTTOM) == CCS_NOMOVEY) { - GetWindowRect(hwnd, &window_rect); - ScreenToClient(parent, (LPPOINT)&window_rect.left); - y = window_rect.top; - } - if ((infoPtr->dwStyle & CCS_BOTTOM) == CCS_BOTTOM) { - GetWindowRect(hwnd, &window_rect); - y = parent_rect.bottom - ( window_rect.bottom - window_rect.top); - } - } - - if (infoPtr->dwStyle & CCS_NOPARENTALIGN) - uPosFlags |= SWP_NOMOVE; - - if (!(infoPtr->dwStyle & CCS_NODIVIDER)) - cy += GetSystemMetrics(SM_CYEDGE); - - if (infoPtr->dwStyle & WS_BORDER) - { - x = y = 1; - cy += GetSystemMetrics(SM_CYEDGE); - cx += GetSystemMetrics(SM_CXEDGE); - } - - infoPtr->bAutoSize = TRUE; - SetWindowPos (hwnd, HWND_TOP, x, y, cx, cy, uPosFlags); - /* The following line makes sure that the infoPtr->bAutoSize is turned off - * after the setwindowpos calls */ - infoPtr->bAutoSize = FALSE; - - return 0; -} - - -static LRESULT -TOOLBAR_ButtonCount (HWND hwnd, WPARAM wParam, LPARAM lParam) -{ - TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd); - - return infoPtr->nNumButtons; -} - - -static LRESULT -TOOLBAR_ButtonStructSize (HWND hwnd, WPARAM wParam, LPARAM lParam) -{ - TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd); - - infoPtr->dwStructSize = (DWORD)wParam; - - return 0; -} - - -static LRESULT -TOOLBAR_ChangeBitmap (HWND hwnd, WPARAM wParam, LPARAM lParam) -{ - TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd); - TBUTTON_INFO *btnPtr; - INT nIndex; - - TRACE("button %d, iBitmap now %d\n", wParam, LOWORD(lParam)); - - nIndex = TOOLBAR_GetButtonIndex (infoPtr, (INT)wParam, FALSE); - if (nIndex == -1) - return FALSE; - - btnPtr = &infoPtr->buttons[nIndex]; - btnPtr->iBitmap = LOWORD(lParam); - - /* we HAVE to erase the background, the new bitmap could be */ - /* transparent */ - InvalidateRect(hwnd, &btnPtr->rect, TRUE); - - return TRUE; -} - - -static LRESULT -TOOLBAR_CheckButton (HWND hwnd, WPARAM wParam, LPARAM lParam) -{ - TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd); - TBUTTON_INFO *btnPtr; - INT nIndex; - INT nOldIndex = -1; - BOOL bChecked = FALSE; - - nIndex = TOOLBAR_GetButtonIndex (infoPtr, (INT)wParam, FALSE); - - TRACE("hwnd=%p, btn index=%d, lParam=0x%08lx\n", hwnd, nIndex, lParam); - - if (nIndex == -1) - return FALSE; - - btnPtr = &infoPtr->buttons[nIndex]; - - bChecked = (btnPtr->fsState & TBSTATE_CHECKED) ? TRUE : FALSE; - - if (LOWORD(lParam) == FALSE) - btnPtr->fsState &= ~TBSTATE_CHECKED; - else { - if (btnPtr->fsStyle & BTNS_GROUP) { - nOldIndex = - TOOLBAR_GetCheckedGroupButtonIndex (infoPtr, nIndex); - if (nOldIndex == nIndex) - return 0; - if (nOldIndex != -1) - infoPtr->buttons[nOldIndex].fsState &= ~TBSTATE_CHECKED; - } - btnPtr->fsState |= TBSTATE_CHECKED; - } - - if( bChecked != LOWORD(lParam) ) - { - if (nOldIndex != -1) - InvalidateRect(hwnd, &infoPtr->buttons[nOldIndex].rect, TRUE); - InvalidateRect(hwnd, &btnPtr->rect, TRUE); - } - - /* FIXME: Send a WM_NOTIFY?? */ - - return TRUE; -} - - -static LRESULT -TOOLBAR_CommandToIndex (HWND hwnd, WPARAM wParam, LPARAM lParam) -{ - TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd); - - return TOOLBAR_GetButtonIndex (infoPtr, (INT)wParam, FALSE); -} - - -static LRESULT -TOOLBAR_Customize (HWND hwnd) -{ - TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd); - CUSTDLG_INFO custInfo; - LRESULT ret; - LPCVOID template; - HRSRC hRes; - NMHDR nmhdr; - - custInfo.tbInfo = infoPtr; - custInfo.tbHwnd = hwnd; - - /* send TBN_BEGINADJUST notification */ - TOOLBAR_SendNotify (&nmhdr, infoPtr, TBN_BEGINADJUST); - - if (!(hRes = FindResourceW (COMCTL32_hModule, - MAKEINTRESOURCEW(IDD_TBCUSTOMIZE), - (LPWSTR)RT_DIALOG))) - return FALSE; - - if(!(template = (LPVOID)LoadResource (COMCTL32_hModule, hRes))) - return FALSE; - - ret = DialogBoxIndirectParamW ((HINSTANCE)GetWindowLongPtrW(hwnd, GWLP_HINSTANCE), - (LPDLGTEMPLATEW)template, - hwnd, - TOOLBAR_CustomizeDialogProc, - (LPARAM)&custInfo); - - /* send TBN_ENDADJUST notification */ - TOOLBAR_SendNotify (&nmhdr, infoPtr, TBN_ENDADJUST); - - return ret; -} - - -static LRESULT -TOOLBAR_DeleteButton (HWND hwnd, WPARAM wParam, LPARAM lParam) -{ - TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd); - INT nIndex = (INT)wParam; - NMTOOLBARW nmtb; - TBUTTON_INFO *btnPtr = &infoPtr->buttons[nIndex]; - - if ((nIndex < 0) || (nIndex >= infoPtr->nNumButtons)) - return FALSE; - - memset(&nmtb, 0, sizeof(nmtb)); - nmtb.iItem = btnPtr->idCommand; - nmtb.tbButton.iBitmap = btnPtr->iBitmap; - nmtb.tbButton.idCommand = btnPtr->idCommand; - nmtb.tbButton.fsState = btnPtr->fsState; - nmtb.tbButton.fsStyle = btnPtr->fsStyle; - nmtb.tbButton.dwData = btnPtr->dwData; - nmtb.tbButton.iString = btnPtr->iString; - TOOLBAR_SendNotify(&nmtb.hdr, infoPtr, TBN_DELETINGBUTTON); - - if ((infoPtr->hwndToolTip) && - !(btnPtr->fsStyle & BTNS_SEP)) { - TTTOOLINFOW ti; - - ZeroMemory (&ti, sizeof(ti)); - ti.cbSize = sizeof(ti); - ti.hwnd = hwnd; - ti.uId = infoPtr->buttons[nIndex].idCommand; - - SendMessageW (infoPtr->hwndToolTip, TTM_DELTOOLW, 0, (LPARAM)&ti); - } - - if (infoPtr->nNumButtons == 1) { - TRACE(" simple delete!\n"); - Free (infoPtr->buttons); - infoPtr->buttons = NULL; - infoPtr->nNumButtons = 0; - } - else { - TBUTTON_INFO *oldButtons = infoPtr->buttons; - TRACE("complex delete! [nIndex=%d]\n", nIndex); - - infoPtr->nNumButtons--; - infoPtr->buttons = Alloc (sizeof (TBUTTON_INFO) * infoPtr->nNumButtons); - if (nIndex > 0) { - memcpy (&infoPtr->buttons[0], &oldButtons[0], - nIndex * sizeof(TBUTTON_INFO)); - } - - if (nIndex < infoPtr->nNumButtons) { - memcpy (&infoPtr->buttons[nIndex], &oldButtons[nIndex+1], - (infoPtr->nNumButtons - nIndex) * sizeof(TBUTTON_INFO)); - } - - Free (oldButtons); - } - - TOOLBAR_CalcToolbar (hwnd); - - InvalidateRect (hwnd, NULL, TRUE); - - return TRUE; -} - - -static LRESULT -TOOLBAR_EnableButton (HWND hwnd, WPARAM wParam, LPARAM lParam) -{ - TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd); - TBUTTON_INFO *btnPtr; - INT nIndex; - DWORD bState; - - nIndex = TOOLBAR_GetButtonIndex (infoPtr, (INT)wParam, FALSE); - - TRACE("hwnd=%p, btn index=%d, lParam=0x%08lx\n", hwnd, wParam, lParam); - - if (nIndex == -1) - return FALSE; - - btnPtr = &infoPtr->buttons[nIndex]; - - bState = btnPtr->fsState & TBSTATE_ENABLED; - - /* update the toolbar button state */ - if(LOWORD(lParam) == FALSE) { - btnPtr->fsState &= ~(TBSTATE_ENABLED | TBSTATE_PRESSED); - } else { - btnPtr->fsState |= TBSTATE_ENABLED; - } - - /* redraw the button only if the state of the button changed */ - if(bState != (btnPtr->fsState & TBSTATE_ENABLED)) - InvalidateRect(hwnd, &btnPtr->rect, TRUE); - - return TRUE; -} - - -static inline LRESULT -TOOLBAR_GetAnchorHighlight (HWND hwnd) -{ - TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd); - - return infoPtr->bAnchor; -} - - -static LRESULT -TOOLBAR_GetBitmap (HWND hwnd, WPARAM wParam, LPARAM lParam) -{ - TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd); - INT nIndex; - - nIndex = TOOLBAR_GetButtonIndex (infoPtr, (INT)wParam, FALSE); - if (nIndex == -1) - return -1; - - return infoPtr->buttons[nIndex].iBitmap; -} - - -static inline LRESULT -TOOLBAR_GetBitmapFlags (HWND hwnd, WPARAM wParam, LPARAM lParam) -{ - return (GetDeviceCaps (0, LOGPIXELSX) >= 120) ? TBBF_LARGE : 0; -} - - -static LRESULT -TOOLBAR_GetButton (HWND hwnd, WPARAM wParam, LPARAM lParam) -{ - TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd); - LPTBBUTTON lpTbb = (LPTBBUTTON)lParam; - INT nIndex = (INT)wParam; - TBUTTON_INFO *btnPtr; - - if (lpTbb == NULL) - return FALSE; - - if ((nIndex < 0) || (nIndex >= infoPtr->nNumButtons)) - return FALSE; - - btnPtr = &infoPtr->buttons[nIndex]; - lpTbb->iBitmap = btnPtr->iBitmap; - lpTbb->idCommand = btnPtr->idCommand; - lpTbb->fsState = btnPtr->fsState; - lpTbb->fsStyle = btnPtr->fsStyle; - lpTbb->bReserved[0] = 0; - lpTbb->bReserved[1] = 0; - lpTbb->dwData = btnPtr->dwData; - lpTbb->iString = btnPtr->iString; - - return TRUE; -} - - -static LRESULT -TOOLBAR_GetButtonInfoA (HWND hwnd, WPARAM wParam, LPARAM lParam) -{ - TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd); - LPTBBUTTONINFOA lpTbInfo = (LPTBBUTTONINFOA)lParam; - TBUTTON_INFO *btnPtr; - INT nIndex; - - if (lpTbInfo == NULL) - return -1; - if (lpTbInfo->cbSize < sizeof(TBBUTTONINFOA)) - return -1; - - nIndex = TOOLBAR_GetButtonIndex (infoPtr, (INT)wParam, - lpTbInfo->dwMask & 0x80000000); - if (nIndex == -1) - return -1; - - if (!(btnPtr = &infoPtr->buttons[nIndex])) return -1; - - if (lpTbInfo->dwMask & TBIF_COMMAND) - lpTbInfo->idCommand = btnPtr->idCommand; - if (lpTbInfo->dwMask & TBIF_IMAGE) - lpTbInfo->iImage = btnPtr->iBitmap; - if (lpTbInfo->dwMask & TBIF_LPARAM) - lpTbInfo->lParam = btnPtr->dwData; - if (lpTbInfo->dwMask & TBIF_SIZE) - lpTbInfo->cx = (WORD)(btnPtr->rect.right - btnPtr->rect.left); - if (lpTbInfo->dwMask & TBIF_STATE) - lpTbInfo->fsState = btnPtr->fsState; - if (lpTbInfo->dwMask & TBIF_STYLE) - lpTbInfo->fsStyle = btnPtr->fsStyle; - if (lpTbInfo->dwMask & TBIF_TEXT) { - /* TB_GETBUTTONINFO doesn't retrieve text from the string list, so we - can't use TOOLBAR_GetText here */ - LPWSTR lpText; - if (HIWORD(btnPtr->iString) && (btnPtr->iString != -1)) { - lpText = (LPWSTR)btnPtr->iString; - Str_GetPtrWtoA (lpText, lpTbInfo->pszText,lpTbInfo->cchText); - } else - lpTbInfo->pszText[0] = '\0'; - } - return nIndex; -} - - -static LRESULT -TOOLBAR_GetButtonInfoW (HWND hwnd, WPARAM wParam, LPARAM lParam) -{ - TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd); - LPTBBUTTONINFOW lpTbInfo = (LPTBBUTTONINFOW)lParam; - TBUTTON_INFO *btnPtr; - INT nIndex; - - if (lpTbInfo == NULL) - return -1; - if (lpTbInfo->cbSize < sizeof(TBBUTTONINFOW)) - return -1; - - nIndex = TOOLBAR_GetButtonIndex (infoPtr, (INT)wParam, - lpTbInfo->dwMask & 0x80000000); - if (nIndex == -1) - return -1; - - btnPtr = &infoPtr->buttons[nIndex]; - - if(!btnPtr) - return -1; - - if (lpTbInfo->dwMask & TBIF_COMMAND) - lpTbInfo->idCommand = btnPtr->idCommand; - if (lpTbInfo->dwMask & TBIF_IMAGE) - lpTbInfo->iImage = btnPtr->iBitmap; - if (lpTbInfo->dwMask & TBIF_LPARAM) - lpTbInfo->lParam = btnPtr->dwData; - if (lpTbInfo->dwMask & TBIF_SIZE) - lpTbInfo->cx = (WORD)(btnPtr->rect.right - btnPtr->rect.left); - if (lpTbInfo->dwMask & TBIF_STATE) - lpTbInfo->fsState = btnPtr->fsState; - if (lpTbInfo->dwMask & TBIF_STYLE) - lpTbInfo->fsStyle = btnPtr->fsStyle; - if (lpTbInfo->dwMask & TBIF_TEXT) { - /* TB_GETBUTTONINFO doesn't retrieve text from the string list, so we - can't use TOOLBAR_GetText here */ - LPWSTR lpText; - if (HIWORD(btnPtr->iString) && (btnPtr->iString != -1)) { - lpText = (LPWSTR)btnPtr->iString; - Str_GetPtrW (lpText,lpTbInfo->pszText,lpTbInfo->cchText); - } else - lpTbInfo->pszText[0] = '\0'; - } - - return nIndex; -} - - -static LRESULT -TOOLBAR_GetButtonSize (HWND hwnd) -{ - TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd); - - if (infoPtr->nNumButtons > 0) - return MAKELONG((WORD)infoPtr->nButtonWidth, - (WORD)infoPtr->nButtonHeight); - else - return MAKELONG(8,7); -} - - -static LRESULT -TOOLBAR_GetButtonTextA (HWND hwnd, WPARAM wParam, LPARAM lParam) -{ - TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd); - INT nIndex; - LPWSTR lpText; - - if (lParam == 0) - return -1; - - nIndex = TOOLBAR_GetButtonIndex (infoPtr, (INT)wParam, FALSE); - if (nIndex == -1) - return -1; - - lpText = TOOLBAR_GetText(infoPtr,&infoPtr->buttons[nIndex]); - - return WideCharToMultiByte( CP_ACP, 0, lpText, -1, - (LPSTR)lParam, 0x7fffffff, NULL, NULL ) - 1; -} - - -static LRESULT -TOOLBAR_GetButtonTextW (HWND hwnd, WPARAM wParam, LPARAM lParam) -{ - TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd); - INT nIndex; - LPWSTR lpText; - LRESULT ret = 0; - - nIndex = TOOLBAR_GetButtonIndex (infoPtr, (INT)wParam, FALSE); - if (nIndex == -1) - return -1; - - lpText = TOOLBAR_GetText(infoPtr,&infoPtr->buttons[nIndex]); - - if (lpText) - { - ret = strlenW (lpText); - - if (lParam) - strcpyW ((LPWSTR)lParam, lpText); - } - - return ret; -} - - -static LRESULT -TOOLBAR_GetDisabledImageList (HWND hwnd, WPARAM wParam, LPARAM lParam) -{ - TRACE("hwnd=%p, wParam=%d, lParam=0x%lx\n", hwnd, wParam, lParam); - /* UNDOCUMENTED: wParam is actually the ID of the image list to return */ - return (LRESULT)GETDISIMAGELIST(TOOLBAR_GetInfoPtr (hwnd), wParam); -} - - -inline static LRESULT -TOOLBAR_GetExtendedStyle (HWND hwnd) -{ - TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd); - - TRACE("\n"); - - return infoPtr->dwExStyle; -} - - -static LRESULT -TOOLBAR_GetHotImageList (HWND hwnd, WPARAM wParam, LPARAM lParam) -{ - TRACE("hwnd=%p, wParam=%d, lParam=0x%lx\n", hwnd, wParam, lParam); - /* UNDOCUMENTED: wParam is actually the ID of the image list to return */ - return (LRESULT)GETHOTIMAGELIST(TOOLBAR_GetInfoPtr (hwnd), wParam); -} - - -static LRESULT -TOOLBAR_GetHotItem (HWND hwnd) -{ - TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd); - - if (!(infoPtr->dwStyle & TBSTYLE_FLAT)) - return -1; - - if (infoPtr->nHotItem < 0) - return -1; - - return (LRESULT)infoPtr->nHotItem; -} - - -static LRESULT -TOOLBAR_GetDefImageList (HWND hwnd, WPARAM wParam, LPARAM lParam) -{ - TRACE("hwnd=%p, wParam=%d, lParam=0x%lx\n", hwnd, wParam, lParam); - /* UNDOCUMENTED: wParam is actually the ID of the image list to return */ - return (LRESULT) GETDEFIMAGELIST(TOOLBAR_GetInfoPtr(hwnd), wParam); -} - - -static LRESULT -TOOLBAR_GetInsertMark (HWND hwnd, WPARAM wParam, LPARAM lParam) -{ - TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd); - TBINSERTMARK *lptbim = (TBINSERTMARK*)lParam; - - TRACE("hwnd = %p, lptbim = %p\n", hwnd, lptbim); - - *lptbim = infoPtr->tbim; - - return 0; -} - - -static LRESULT -TOOLBAR_GetInsertMarkColor (HWND hwnd, WPARAM wParam, LPARAM lParam) -{ - TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd); - - TRACE("hwnd = %p\n", hwnd); - - return (LRESULT)infoPtr->clrInsertMark; -} - - -static LRESULT -TOOLBAR_GetItemRect (HWND hwnd, WPARAM wParam, LPARAM lParam) -{ - TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd); - TBUTTON_INFO *btnPtr; - LPRECT lpRect; - INT nIndex; - - nIndex = (INT)wParam; - btnPtr = &infoPtr->buttons[nIndex]; - if ((nIndex < 0) || (nIndex >= infoPtr->nNumButtons)) - return FALSE; - lpRect = (LPRECT)lParam; - if (lpRect == NULL) - return FALSE; - if (btnPtr->fsState & TBSTATE_HIDDEN) - return FALSE; - - lpRect->left = btnPtr->rect.left; - lpRect->right = btnPtr->rect.right; - lpRect->bottom = btnPtr->rect.bottom; - lpRect->top = btnPtr->rect.top; - - return TRUE; -} - - -static LRESULT -TOOLBAR_GetMaxSize (HWND hwnd, WPARAM wParam, LPARAM lParam) -{ - TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd); - LPSIZE lpSize = (LPSIZE)lParam; - - if (lpSize == NULL) - return FALSE; - - lpSize->cx = infoPtr->rcBound.right - infoPtr->rcBound.left; - lpSize->cy = infoPtr->rcBound.bottom - infoPtr->rcBound.top; - - TRACE("maximum size %ld x %ld\n", - infoPtr->rcBound.right - infoPtr->rcBound.left, - infoPtr->rcBound.bottom - infoPtr->rcBound.top); - - return TRUE; -} - - -/* << TOOLBAR_GetObject >> */ - - -static LRESULT -TOOLBAR_GetPadding (HWND hwnd) -{ - TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd); - DWORD oldPad; - - oldPad = MAKELONG(infoPtr->szPadding.cx, infoPtr->szPadding.cy); - return (LRESULT) oldPad; -} - - -static LRESULT -TOOLBAR_GetRect (HWND hwnd, WPARAM wParam, LPARAM lParam) -{ - TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd); - TBUTTON_INFO *btnPtr; - LPRECT lpRect; - INT nIndex; - - nIndex = TOOLBAR_GetButtonIndex (infoPtr, (INT)wParam, FALSE); - btnPtr = &infoPtr->buttons[nIndex]; - if ((nIndex < 0) || (nIndex >= infoPtr->nNumButtons)) - return FALSE; - lpRect = (LPRECT)lParam; - if (lpRect == NULL) - return FALSE; - - lpRect->left = btnPtr->rect.left; - lpRect->right = btnPtr->rect.right; - lpRect->bottom = btnPtr->rect.bottom; - lpRect->top = btnPtr->rect.top; - - return TRUE; -} - - -static LRESULT -TOOLBAR_GetRows (HWND hwnd, WPARAM wParam, LPARAM lParam) -{ - TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd); - - if (infoPtr->dwStyle & TBSTYLE_WRAPABLE) - return infoPtr->nRows; - else - return 1; -} - - -static LRESULT -TOOLBAR_GetState (HWND hwnd, WPARAM wParam, LPARAM lParam) -{ - TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd); - INT nIndex; - - nIndex = TOOLBAR_GetButtonIndex (infoPtr, (INT)wParam, FALSE); - if (nIndex == -1) - return -1; - - return infoPtr->buttons[nIndex].fsState; -} - - -static LRESULT -TOOLBAR_GetStyle (HWND hwnd, WPARAM wParam, LPARAM lParam) -{ - return GetWindowLongW(hwnd, GWL_STYLE); -} - - -static LRESULT -TOOLBAR_GetTextRows (HWND hwnd, WPARAM wParam, LPARAM lParam) -{ - TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd); - - return infoPtr->nMaxTextRows; -} - - -static LRESULT -TOOLBAR_GetToolTips (HWND hwnd, WPARAM wParam, LPARAM lParam) -{ - TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd); - - return (LRESULT)infoPtr->hwndToolTip; -} - - -static LRESULT -TOOLBAR_GetUnicodeFormat (HWND hwnd, WPARAM wParam, LPARAM lParam) -{ - TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd); - - TRACE("%s hwnd=%p\n", - infoPtr->bUnicode ? "TRUE" : "FALSE", hwnd); - - return infoPtr->bUnicode; -} - - -inline static LRESULT -TOOLBAR_GetVersion (HWND hwnd) -{ - TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd); - return infoPtr->iVersion; -} - - -static LRESULT -TOOLBAR_HideButton (HWND hwnd, WPARAM wParam, LPARAM lParam) -{ - TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd); - TBUTTON_INFO *btnPtr; - INT nIndex; - - TRACE("\n"); - - nIndex = TOOLBAR_GetButtonIndex (infoPtr, (INT)wParam, FALSE); - if (nIndex == -1) - return FALSE; - - btnPtr = &infoPtr->buttons[nIndex]; - if (LOWORD(lParam) == FALSE) - btnPtr->fsState &= ~TBSTATE_HIDDEN; - else - btnPtr->fsState |= TBSTATE_HIDDEN; - - TOOLBAR_CalcToolbar (hwnd); - - InvalidateRect (hwnd, NULL, TRUE); - - return TRUE; -} - - -inline static LRESULT -TOOLBAR_HitTest (HWND hwnd, WPARAM wParam, LPARAM lParam) -{ - return TOOLBAR_InternalHitTest (hwnd, (LPPOINT)lParam); -} - - -static LRESULT -TOOLBAR_Indeterminate (HWND hwnd, WPARAM wParam, LPARAM lParam) -{ - TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd); - TBUTTON_INFO *btnPtr; - INT nIndex; - DWORD oldState; - - nIndex = TOOLBAR_GetButtonIndex (infoPtr, (INT)wParam, FALSE); - if (nIndex == -1) - return FALSE; - - btnPtr = &infoPtr->buttons[nIndex]; - oldState = btnPtr->fsState; - if (LOWORD(lParam) == FALSE) - btnPtr->fsState &= ~TBSTATE_INDETERMINATE; - else - btnPtr->fsState |= TBSTATE_INDETERMINATE; - - if(oldState != btnPtr->fsState) - InvalidateRect(hwnd, &btnPtr->rect, TRUE); - - return TRUE; -} - - -static LRESULT -TOOLBAR_InsertButtonA (HWND hwnd, WPARAM wParam, LPARAM lParam) -{ - TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd); - LPTBBUTTON lpTbb = (LPTBBUTTON)lParam; - INT nIndex = (INT)wParam; - TBUTTON_INFO *oldButtons; - - if (lpTbb == NULL) - return FALSE; - - TOOLBAR_DumpButton(infoPtr, (TBUTTON_INFO *)lpTbb, nIndex, FALSE); - - if (nIndex == -1) { - /* EPP: this seems to be an undocumented call (from my IE4) - * I assume in that case that: - * - lpTbb->iString is a string pointer (not a string index in strings[] table - * - index of insertion is at the end of existing buttons - * I only see this happen with nIndex == -1, but it could have a special - * meaning (like -nIndex (or ~nIndex) to get the real position of insertion). - */ - nIndex = infoPtr->nNumButtons; - - } else if (nIndex < 0) - return FALSE; - - /* If the string passed is not an index, assume address of string - and do our own AddString */ - if ((HIWORD(lpTbb->iString) != 0) && (lpTbb->iString != -1)) { - LPSTR ptr; - INT len; - - TRACE("string %s passed instead of index, adding string\n", - debugstr_a((LPSTR)lpTbb->iString)); - len = strlen((LPSTR)lpTbb->iString) + 2; - ptr = Alloc(len); - strcpy(ptr, (LPSTR)lpTbb->iString); - ptr[len - 1] = 0; /* ended by two '\0' */ - lpTbb->iString = TOOLBAR_AddStringA(hwnd, 0, (LPARAM)ptr); - Free(ptr); - } - - TRACE("inserting button index=%d\n", nIndex); - if (nIndex > infoPtr->nNumButtons) { - nIndex = infoPtr->nNumButtons; - TRACE("adjust index=%d\n", nIndex); - } - - oldButtons = infoPtr->buttons; - infoPtr->nNumButtons++; - infoPtr->buttons = Alloc (sizeof (TBUTTON_INFO) * infoPtr->nNumButtons); - /* pre insert copy */ - if (nIndex > 0) { - memcpy (&infoPtr->buttons[0], &oldButtons[0], - nIndex * sizeof(TBUTTON_INFO)); - } - - /* insert new button */ - infoPtr->buttons[nIndex].iBitmap = lpTbb->iBitmap; - infoPtr->buttons[nIndex].idCommand = lpTbb->idCommand; - infoPtr->buttons[nIndex].fsState = lpTbb->fsState; - infoPtr->buttons[nIndex].fsStyle = lpTbb->fsStyle; - infoPtr->buttons[nIndex].dwData = lpTbb->dwData; - /* if passed string and not index, then add string */ - if(HIWORD(lpTbb->iString) && lpTbb->iString!=-1) { - Str_SetPtrAtoW ((LPWSTR *)&infoPtr->buttons[nIndex].iString, (LPCSTR )lpTbb->iString); - } - else - infoPtr->buttons[nIndex].iString = lpTbb->iString; - - if ((infoPtr->hwndToolTip) && !(lpTbb->fsStyle & BTNS_SEP)) { - TTTOOLINFOW ti; - - ZeroMemory (&ti, sizeof(ti)); - ti.cbSize = sizeof (ti); - ti.hwnd = hwnd; - ti.uId = lpTbb->idCommand; - ti.hinst = 0; - ti.lpszText = LPSTR_TEXTCALLBACKW; - - SendMessageW (infoPtr->hwndToolTip, TTM_ADDTOOLW, - 0, (LPARAM)&ti); - } - - /* post insert copy */ - if (nIndex < infoPtr->nNumButtons - 1) { - memcpy (&infoPtr->buttons[nIndex+1], &oldButtons[nIndex], - (infoPtr->nNumButtons - nIndex - 1) * sizeof(TBUTTON_INFO)); - } - - Free (oldButtons); - - TOOLBAR_CalcToolbar (hwnd); - - InvalidateRect (hwnd, NULL, TRUE); - - return TRUE; -} - - -static LRESULT -TOOLBAR_InsertButtonW (HWND hwnd, WPARAM wParam, LPARAM lParam) -{ - TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd); - LPTBBUTTON lpTbb = (LPTBBUTTON)lParam; - INT nIndex = (INT)wParam; - TBUTTON_INFO *oldButtons; - - if (lpTbb == NULL) - return FALSE; - - TOOLBAR_DumpButton(infoPtr, (TBUTTON_INFO *)lpTbb, nIndex, FALSE); - - if (nIndex == -1) { - /* EPP: this seems to be an undocumented call (from my IE4) - * I assume in that case that: - * - lpTbb->iString is a string pointer (not a string index in strings[] table - * - index of insertion is at the end of existing buttons - * I only see this happen with nIndex == -1, but it could have a special - * meaning (like -nIndex (or ~nIndex) to get the real position of insertion). - */ - nIndex = infoPtr->nNumButtons; - - } else if (nIndex < 0) - return FALSE; - - /* If the string passed is not an index, assume address of string - and do our own AddString */ - if ((HIWORD(lpTbb->iString) != 0) && (lpTbb->iString != -1)) { - LPWSTR ptr; - INT len; - - TRACE("string %s passed instead of index, adding string\n", - debugstr_w((LPWSTR)lpTbb->iString)); - len = strlenW((LPWSTR)lpTbb->iString) + 2; - ptr = Alloc(len*sizeof(WCHAR)); - strcpyW(ptr, (LPWSTR)lpTbb->iString); - ptr[len - 1] = 0; /* ended by two '\0' */ - lpTbb->iString = TOOLBAR_AddStringW(hwnd, 0, (LPARAM)ptr); - Free(ptr); - } - - TRACE("inserting button index=%d\n", nIndex); - if (nIndex > infoPtr->nNumButtons) { - nIndex = infoPtr->nNumButtons; - TRACE("adjust index=%d\n", nIndex); - } - - oldButtons = infoPtr->buttons; - infoPtr->nNumButtons++; - infoPtr->buttons = Alloc (sizeof (TBUTTON_INFO) * infoPtr->nNumButtons); - /* pre insert copy */ - if (nIndex > 0) { - memcpy (&infoPtr->buttons[0], &oldButtons[0], - nIndex * sizeof(TBUTTON_INFO)); - } - - /* insert new button */ - infoPtr->buttons[nIndex].iBitmap = lpTbb->iBitmap; - infoPtr->buttons[nIndex].idCommand = lpTbb->idCommand; - infoPtr->buttons[nIndex].fsState = lpTbb->fsState; - infoPtr->buttons[nIndex].fsStyle = lpTbb->fsStyle; - infoPtr->buttons[nIndex].dwData = lpTbb->dwData; - /* if passed string and not index, then add string */ - if(HIWORD(lpTbb->iString) && lpTbb->iString!=-1) { - Str_SetPtrW ((LPWSTR *)&infoPtr->buttons[nIndex].iString, (LPWSTR)lpTbb->iString); - } - else - infoPtr->buttons[nIndex].iString = lpTbb->iString; - - if ((infoPtr->hwndToolTip) && !(lpTbb->fsStyle & BTNS_SEP)) { - TTTOOLINFOW ti; - - ZeroMemory (&ti, sizeof(TTTOOLINFOW)); - ti.cbSize = sizeof (TTTOOLINFOW); - ti.hwnd = hwnd; - ti.uId = lpTbb->idCommand; - ti.hinst = 0; - ti.lpszText = LPSTR_TEXTCALLBACKW; - - SendMessageW (infoPtr->hwndToolTip, TTM_ADDTOOLW, - 0, (LPARAM)&ti); - } - - /* post insert copy */ - if (nIndex < infoPtr->nNumButtons - 1) { - memcpy (&infoPtr->buttons[nIndex+1], &oldButtons[nIndex], - (infoPtr->nNumButtons - nIndex - 1) * sizeof(TBUTTON_INFO)); - } - - Free (oldButtons); - - TOOLBAR_CalcToolbar (hwnd); - - InvalidateRect (hwnd, NULL, TRUE); - - return TRUE; -} - - -/* << TOOLBAR_InsertMarkHitTest >> */ - - -static LRESULT -TOOLBAR_IsButtonChecked (HWND hwnd, WPARAM wParam, LPARAM lParam) -{ - TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd); - INT nIndex; - - nIndex = TOOLBAR_GetButtonIndex (infoPtr, (INT)wParam, FALSE); - if (nIndex == -1) - return FALSE; - - return (infoPtr->buttons[nIndex].fsState & TBSTATE_CHECKED); -} - - -static LRESULT -TOOLBAR_IsButtonEnabled (HWND hwnd, WPARAM wParam, LPARAM lParam) -{ - TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd); - INT nIndex; - - nIndex = TOOLBAR_GetButtonIndex (infoPtr, (INT)wParam, FALSE); - if (nIndex == -1) - return FALSE; - - return (infoPtr->buttons[nIndex].fsState & TBSTATE_ENABLED); -} - - -static LRESULT -TOOLBAR_IsButtonHidden (HWND hwnd, WPARAM wParam, LPARAM lParam) -{ - TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd); - INT nIndex; - - nIndex = TOOLBAR_GetButtonIndex (infoPtr, (INT)wParam, FALSE); - if (nIndex == -1) - return TRUE; - - return (infoPtr->buttons[nIndex].fsState & TBSTATE_HIDDEN); -} - - -static LRESULT -TOOLBAR_IsButtonHighlighted (HWND hwnd, WPARAM wParam, LPARAM lParam) -{ - TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd); - INT nIndex; - - nIndex = TOOLBAR_GetButtonIndex (infoPtr, (INT)wParam, FALSE); - if (nIndex == -1) - return FALSE; - - return (infoPtr->buttons[nIndex].fsState & TBSTATE_MARKED); -} - - -static LRESULT -TOOLBAR_IsButtonIndeterminate (HWND hwnd, WPARAM wParam, LPARAM lParam) -{ - TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd); - INT nIndex; - - nIndex = TOOLBAR_GetButtonIndex (infoPtr, (INT)wParam, FALSE); - if (nIndex == -1) - return FALSE; - - return (infoPtr->buttons[nIndex].fsState & TBSTATE_INDETERMINATE); -} - - -static LRESULT -TOOLBAR_IsButtonPressed (HWND hwnd, WPARAM wParam, LPARAM lParam) -{ - TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd); - INT nIndex; - - nIndex = TOOLBAR_GetButtonIndex (infoPtr, (INT)wParam, FALSE); - if (nIndex == -1) - return FALSE; - - return (infoPtr->buttons[nIndex].fsState & TBSTATE_PRESSED); -} - - -static LRESULT -TOOLBAR_LoadImages (HWND hwnd, WPARAM wParam, LPARAM lParam) -{ - TBADDBITMAP tbab; - tbab.hInst = (HINSTANCE)lParam; - tbab.nID = (UINT_PTR)wParam; - - TRACE("hwnd = %p, hInst = %p, nID = %u\n", hwnd, tbab.hInst, tbab.nID); - - return TOOLBAR_AddBitmap(hwnd, 0, (LPARAM)&tbab); -} - - -static LRESULT -TOOLBAR_MapAccelerator (HWND hwnd, WPARAM wParam, LPARAM lParam) -{ - TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd); - WCHAR wAccel = (WCHAR)wParam; - UINT* pIDButton = (UINT*)lParam; - WCHAR wszAccel[] = {'&',wAccel,0}; - int i; - - TRACE("hwnd = %p, wAccel = %x(%s), pIDButton = %p\n", - hwnd, wAccel, debugstr_wn(&wAccel,1), pIDButton); - - for (i = 0; i < infoPtr->nNumButtons; i++) - { - TBUTTON_INFO *btnPtr = infoPtr->buttons+i; - if (!(btnPtr->fsStyle & BTNS_NOPREFIX) && - !(btnPtr->fsState & TBSTATE_HIDDEN)) - { - int iLen = strlenW(wszAccel); - LPCWSTR lpszStr = TOOLBAR_GetText(infoPtr, btnPtr); - - if (!lpszStr) - continue; - - while (*lpszStr) - { - if ((lpszStr[0] == '&') && (lpszStr[1] == '&')) - { - lpszStr += 2; - continue; - } - if (!strncmpiW(lpszStr, wszAccel, iLen)) - { - *pIDButton = btnPtr->idCommand; - return TRUE; - } - lpszStr++; - } - } - } - return FALSE; -} - - -static LRESULT -TOOLBAR_MarkButton (HWND hwnd, WPARAM wParam, LPARAM lParam) -{ - TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd); - INT nIndex; - DWORD oldState; - TBUTTON_INFO *btnPtr; - - TRACE("hwnd = %p, wParam = %d, lParam = 0x%08lx\n", hwnd, wParam, lParam); - - nIndex = TOOLBAR_GetButtonIndex (infoPtr, (INT)wParam, FALSE); - if (nIndex == -1) - return FALSE; - - btnPtr = &infoPtr->buttons[nIndex]; - oldState = btnPtr->fsState; - - if (LOWORD(lParam)) - btnPtr->fsState |= TBSTATE_MARKED; - else - btnPtr->fsState &= ~TBSTATE_MARKED; - - if(oldState != btnPtr->fsState) - InvalidateRect(hwnd, &btnPtr->rect, TRUE); - - return TRUE; -} - - -/* fixes up an index of a button affected by a move */ -inline static void TOOLBAR_MoveFixupIndex(INT* pIndex, INT nIndex, INT nMoveIndex, BOOL bMoveUp) -{ - if (bMoveUp) - { - if (*pIndex > nIndex && *pIndex <= nMoveIndex) - (*pIndex)--; - else if (*pIndex == nIndex) - *pIndex = nMoveIndex; - } - else - { - if (*pIndex >= nMoveIndex && *pIndex < nIndex) - (*pIndex)++; - else if (*pIndex == nIndex) - *pIndex = nMoveIndex; - } -} - - -static LRESULT -TOOLBAR_MoveButton (HWND hwnd, WPARAM wParam, LPARAM lParam) -{ - TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd); - INT nIndex; - INT nCount; - INT nMoveIndex = (INT)lParam; - TBUTTON_INFO button; - - TRACE("hwnd=%p, wParam=%d, lParam=%ld\n", hwnd, wParam, lParam); - - nIndex = TOOLBAR_GetButtonIndex (infoPtr, (INT)wParam, TRUE); - if ((nIndex == -1) || (nMoveIndex < 0)) - return FALSE; - - if (nMoveIndex > infoPtr->nNumButtons - 1) - nMoveIndex = infoPtr->nNumButtons - 1; - - button = infoPtr->buttons[nIndex]; - - /* move button right */ - if (nIndex < nMoveIndex) - { - nCount = nMoveIndex - nIndex; - memmove(&infoPtr->buttons[nIndex], &infoPtr->buttons[nIndex+1], nCount*sizeof(TBUTTON_INFO)); - infoPtr->buttons[nMoveIndex] = button; - - TOOLBAR_MoveFixupIndex(&infoPtr->nButtonDown, nIndex, nMoveIndex, TRUE); - TOOLBAR_MoveFixupIndex(&infoPtr->nButtonDrag, nIndex, nMoveIndex, TRUE); - TOOLBAR_MoveFixupIndex(&infoPtr->nOldHit, nIndex, nMoveIndex, TRUE); - TOOLBAR_MoveFixupIndex(&infoPtr->nHotItem, nIndex, nMoveIndex, TRUE); - } - else if (nIndex > nMoveIndex) /* move button left */ - { - nCount = nIndex - nMoveIndex; - memmove(&infoPtr->buttons[nMoveIndex+1], &infoPtr->buttons[nMoveIndex], nCount*sizeof(TBUTTON_INFO)); - infoPtr->buttons[nMoveIndex] = button; - - TOOLBAR_MoveFixupIndex(&infoPtr->nButtonDown, nIndex, nMoveIndex, FALSE); - TOOLBAR_MoveFixupIndex(&infoPtr->nButtonDrag, nIndex, nMoveIndex, FALSE); - TOOLBAR_MoveFixupIndex(&infoPtr->nOldHit, nIndex, nMoveIndex, FALSE); - TOOLBAR_MoveFixupIndex(&infoPtr->nHotItem, nIndex, nMoveIndex, FALSE); - } - - TOOLBAR_CalcToolbar(hwnd); - InvalidateRect(hwnd, NULL, TRUE); - - return TRUE; -} - - -static LRESULT -TOOLBAR_PressButton (HWND hwnd, WPARAM wParam, LPARAM lParam) -{ - TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd); - TBUTTON_INFO *btnPtr; - INT nIndex; - DWORD oldState; - - nIndex = TOOLBAR_GetButtonIndex (infoPtr, (INT)wParam, FALSE); - if (nIndex == -1) - return FALSE; - - btnPtr = &infoPtr->buttons[nIndex]; - oldState = btnPtr->fsState; - if (LOWORD(lParam) == FALSE) - btnPtr->fsState &= ~TBSTATE_PRESSED; - else - btnPtr->fsState |= TBSTATE_PRESSED; - - if(oldState != btnPtr->fsState) - InvalidateRect(hwnd, &btnPtr->rect, TRUE); - - return TRUE; -} - -/* FIXME: there might still be some confusion her between number of buttons - * and number of bitmaps */ -static LRESULT -TOOLBAR_ReplaceBitmap (HWND hwnd, WPARAM wParam, LPARAM lParam) -{ - TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd); - LPTBREPLACEBITMAP lpReplace = (LPTBREPLACEBITMAP) lParam; - HBITMAP hBitmap; - int i = 0, nOldButtons = 0, pos = 0; - int nOldBitmaps, nNewBitmaps; - HIMAGELIST himlDef = 0; - - TRACE("hInstOld %p nIDOld %x hInstNew %p nIDNew %x nButtons %x\n", - lpReplace->hInstOld, lpReplace->nIDOld, lpReplace->hInstNew, lpReplace->nIDNew, - lpReplace->nButtons); - - if (lpReplace->hInstOld == HINST_COMMCTRL) - { - FIXME("changing standard bitmaps not implemented\n"); - return FALSE; - } - else if (lpReplace->hInstOld != 0) - { - FIXME("resources not in the current module not implemented\n"); - return FALSE; - } - else - { - hBitmap = (HBITMAP) lpReplace->nIDNew; - } - - TRACE("To be replaced hInstOld %p nIDOld %x\n", lpReplace->hInstOld, lpReplace->nIDOld); - for (i = 0; i < infoPtr->nNumBitmapInfos; i++) { - TBITMAP_INFO *tbi = &infoPtr->bitmaps[i]; - TRACE("tbimapinfo %d hInstOld %p nIDOld %x\n", i, tbi->hInst, tbi->nID); - if (tbi->hInst == lpReplace->hInstOld && tbi->nID == lpReplace->nIDOld) - { - TRACE("Found: nButtons %d hInst %p nID %x\n", tbi->nButtons, tbi->hInst, tbi->nID); - nOldButtons = tbi->nButtons; - tbi->nButtons = lpReplace->nButtons; - tbi->hInst = lpReplace->hInstNew; - tbi->nID = lpReplace->nIDNew; - TRACE("tbimapinfo changed %d hInstOld %p nIDOld %x\n", i, tbi->hInst, tbi->nID); - break; - } - pos += tbi->nButtons; - } - - if (nOldButtons == 0) - { - WARN("No hinst/bitmap found! hInst %p nID %x\n", lpReplace->hInstOld, lpReplace->nIDOld); - return FALSE; - } - - himlDef = GETDEFIMAGELIST(infoPtr, 0); /* fixme: correct? */ - nOldBitmaps = ImageList_GetImageCount(himlDef); - - /* ImageList_Replace(GETDEFIMAGELIST(), pos, hBitmap, NULL); */ - - for (i = pos + nOldBitmaps - 1; i >= pos; i--) - ImageList_Remove(himlDef, i); - - { - BITMAP bmp; - HBITMAP hOldBitmapBitmap, hOldBitmapLoad, hbmLoad; - HDC hdcImage, hdcBitmap; - - /* copy the bitmap before adding it so that the user's bitmap - * doesn't get modified. - */ - GetObjectA (hBitmap, sizeof(BITMAP), (LPVOID)&bmp); - - hdcImage = CreateCompatibleDC(0); - hdcBitmap = CreateCompatibleDC(0); - - /* create new bitmap */ - hbmLoad = CreateBitmap (bmp.bmWidth, bmp.bmHeight, bmp.bmPlanes, bmp.bmBitsPixel, NULL); - hOldBitmapBitmap = SelectObject(hdcBitmap, hBitmap); - hOldBitmapLoad = SelectObject(hdcImage, hbmLoad); - - /* Copy the user's image */ - BitBlt (hdcImage, 0, 0, bmp.bmWidth, bmp.bmHeight, - hdcBitmap, 0, 0, SRCCOPY); - - SelectObject (hdcImage, hOldBitmapLoad); - SelectObject (hdcBitmap, hOldBitmapBitmap); - DeleteDC (hdcImage); - DeleteDC (hdcBitmap); - - ImageList_AddMasked (himlDef, hbmLoad, comctl32_color.clrBtnFace); - nNewBitmaps = ImageList_GetImageCount(himlDef); - DeleteObject (hbmLoad); - } - - infoPtr->nNumBitmaps = infoPtr->nNumBitmaps - nOldBitmaps + nNewBitmaps; - - TRACE(" pos %d %d old bitmaps replaced by %d new ones.\n", - pos, nOldBitmaps, nNewBitmaps); - - InvalidateRect(hwnd, NULL, TRUE); - - return TRUE; -} - - -/* helper for TOOLBAR_SaveRestoreW */ -static BOOL -TOOLBAR_Save(TOOLBAR_INFO *infoPtr, LPTBSAVEPARAMSW lpSave) -{ - FIXME("save to %s %s\n", debugstr_w(lpSave->pszSubKey), - debugstr_w(lpSave->pszValueName)); - - return FALSE; -} - - -/* helper for TOOLBAR_Restore */ -static void -TOOLBAR_DeleteAllButtons(TOOLBAR_INFO *infoPtr) -{ - INT i; - TTTOOLINFOW ti; - - ZeroMemory(&ti, sizeof(ti)); - ti.cbSize = sizeof(ti); - ti.hwnd = infoPtr->hwndSelf; - - for (i = 0; i < infoPtr->nNumButtons; i++) - { - if ((infoPtr->hwndToolTip) && - !(infoPtr->buttons[i].fsStyle & BTNS_SEP)) - { - ti.uId = infoPtr->buttons[i].idCommand; - SendMessageW(infoPtr->hwndToolTip, TTM_DELTOOLW, 0, (LPARAM)&ti); - } - } - - Free(infoPtr->buttons); - infoPtr->buttons = NULL; - infoPtr->nNumButtons = 0; -} - - -/* helper for TOOLBAR_SaveRestoreW */ -static BOOL -TOOLBAR_Restore(TOOLBAR_INFO *infoPtr, LPTBSAVEPARAMSW lpSave) -{ - LONG res; - HKEY hkey = NULL; - BOOL ret = FALSE; - DWORD dwType; - DWORD dwSize = 0; - NMTBRESTORE nmtbr; - - /* restore toolbar information */ - TRACE("restore from %s %s\n", debugstr_w(lpSave->pszSubKey), - debugstr_w(lpSave->pszValueName)); - - memset(&nmtbr, 0, sizeof(nmtbr)); - - res = RegOpenKeyExW(lpSave->hkr, lpSave->pszSubKey, 0, - KEY_QUERY_VALUE, &hkey); - if (!res) - res = RegQueryValueExW(hkey, lpSave->pszValueName, NULL, &dwType, - NULL, &dwSize); - if (!res && dwType != REG_BINARY) - res = ERROR_FILE_NOT_FOUND; - if (!res) - { - nmtbr.pData = HeapAlloc(GetProcessHeap(), 0, dwSize); - nmtbr.cbData = (UINT)dwSize; - if (!nmtbr.pData) res = ERROR_OUTOFMEMORY; - } - if (!res) - res = RegQueryValueExW(hkey, lpSave->pszValueName, NULL, &dwType, - (LPBYTE)nmtbr.pData, &dwSize); - if (!res) - { - nmtbr.pCurrent = nmtbr.pData; - nmtbr.iItem = -1; - nmtbr.cbBytesPerRecord = sizeof(DWORD); - nmtbr.cButtons = nmtbr.cbData / nmtbr.cbBytesPerRecord; - - if (!TOOLBAR_SendNotify(&nmtbr.hdr, infoPtr, TBN_RESTORE)) - { - INT i; - - /* remove all existing buttons as this function is designed to - * restore the toolbar to a previously saved state */ - TOOLBAR_DeleteAllButtons(infoPtr); - - for (i = 0; i < nmtbr.cButtons; i++) - { - nmtbr.iItem = i; - nmtbr.tbButton.iBitmap = -1; - nmtbr.tbButton.fsState = 0; - nmtbr.tbButton.fsStyle = 0; - nmtbr.tbButton.idCommand = 0; - if (*nmtbr.pCurrent == (DWORD)-1) - { - /* separator */ - nmtbr.tbButton.fsStyle = TBSTYLE_SEP; - nmtbr.tbButton.iBitmap = SEPARATOR_WIDTH; - } - else if (*nmtbr.pCurrent == (DWORD)-2) - /* hidden button */ - nmtbr.tbButton.fsState = TBSTATE_HIDDEN; - else - nmtbr.tbButton.idCommand = (int)*nmtbr.pCurrent; - - nmtbr.pCurrent++; - - TOOLBAR_SendNotify(&nmtbr.hdr, infoPtr, TBN_RESTORE); - - /* can't contain real string as we don't know whether - * the client put an ANSI or Unicode string in there */ - if (HIWORD(nmtbr.tbButton.iString)) - nmtbr.tbButton.iString = 0; - - TOOLBAR_InsertButtonW(infoPtr->hwndSelf, -1, - (LPARAM)&nmtbr.tbButton); - } - - /* do legacy notifications */ - if (infoPtr->iVersion < 5) - { - /* FIXME: send TBN_BEGINADJUST */ - FIXME("send TBN_GETBUTTONINFO for each button\n"); - /* FIXME: send TBN_ENDADJUST */ - } - - /* remove all uninitialised buttons - * note: loop backwards to avoid having to fixup i on a - * delete */ - for (i = infoPtr->nNumButtons - 1; i >= 0; i--) - if (infoPtr->buttons[i].iBitmap == -1) - TOOLBAR_DeleteButton(infoPtr->hwndSelf, i, 0); - - /* only indicate success if at least one button survived */ - if (infoPtr->nNumButtons > 0) ret = TRUE; - } - } - HeapFree(GetProcessHeap(), 0, nmtbr.pData); - RegCloseKey(hkey); - - return ret; -} - - -static LRESULT -TOOLBAR_SaveRestoreW (HWND hwnd, WPARAM wParam, LPTBSAVEPARAMSW lpSave) -{ - TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd); - - if (lpSave == NULL) return 0; - - if (wParam) - return TOOLBAR_Save(infoPtr, lpSave); - else - return TOOLBAR_Restore(infoPtr, lpSave); -} - - -static LRESULT -TOOLBAR_SaveRestoreA (HWND hwnd, WPARAM wParam, LPTBSAVEPARAMSA lpSave) -{ - TBSAVEPARAMSW SaveW; - int len; - - if (lpSave == NULL) return 0; - - SaveW.hkr = lpSave->hkr; - - len = MultiByteToWideChar(CP_ACP, 0, lpSave->pszSubKey, -1, NULL, 0); - SaveW.pszSubKey = HeapAlloc(GetProcessHeap(), 0, len * sizeof(WCHAR)); - MultiByteToWideChar(CP_ACP, 0, lpSave->pszSubKey, -1, (LPWSTR)SaveW.pszSubKey, len); - - len = MultiByteToWideChar(CP_ACP, 0, lpSave->pszValueName, -1, NULL, 0); - SaveW.pszValueName = HeapAlloc(GetProcessHeap(), 0, len * sizeof(WCHAR)); - MultiByteToWideChar(CP_ACP, 0, lpSave->pszValueName, -1, (LPWSTR)SaveW.pszValueName, len); - - return TOOLBAR_SaveRestoreW(hwnd, wParam, &SaveW); -} - - -static LRESULT -TOOLBAR_SetAnchorHighlight (HWND hwnd, WPARAM wParam) -{ - TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd); - BOOL bOldAnchor = infoPtr->bAnchor; - - TRACE("hwnd=%p, bAnchor = %s\n", hwnd, wParam ? "TRUE" : "FALSE"); - - infoPtr->bAnchor = (BOOL)wParam; - - /* Native does not remove the hot effect from an already hot button */ - - return (LRESULT)bOldAnchor; -} - - -static LRESULT -TOOLBAR_SetBitmapSize (HWND hwnd, WPARAM wParam, LPARAM lParam) -{ - TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd); - HIMAGELIST himlDef = GETDEFIMAGELIST(infoPtr, 0); - - TRACE("hwnd=%p, wParam=%d, lParam=%ld\n", hwnd, wParam, lParam); - - if (wParam != 0) - FIXME("wParam is %d. Perhaps image list index?\n", wParam); - - if ((LOWORD(lParam) <= 0) || (HIWORD(lParam)<=0)) - return FALSE; - - if (infoPtr->nNumButtons > 0) - WARN("%d buttons, undoc increase to bitmap size : %d-%d -> %d-%d\n", - infoPtr->nNumButtons, - infoPtr->nBitmapWidth, infoPtr->nBitmapHeight, - LOWORD(lParam), HIWORD(lParam)); - - infoPtr->nBitmapWidth = (INT)LOWORD(lParam); - infoPtr->nBitmapHeight = (INT)HIWORD(lParam); - - - if ((himlDef == infoPtr->himlInt) && - (ImageList_GetImageCount(infoPtr->himlInt) == 0)) - { - ImageList_SetIconSize(infoPtr->himlInt, infoPtr->nBitmapWidth, - infoPtr->nBitmapHeight); - } - - return TRUE; -} - - -static LRESULT -TOOLBAR_SetButtonInfoA (HWND hwnd, WPARAM wParam, LPARAM lParam) -{ - TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd); - LPTBBUTTONINFOA lptbbi = (LPTBBUTTONINFOA)lParam; - TBUTTON_INFO *btnPtr; - INT nIndex; - RECT oldBtnRect; - - if (lptbbi == NULL) - return FALSE; - if (lptbbi->cbSize < sizeof(TBBUTTONINFOA)) - return FALSE; - - nIndex = TOOLBAR_GetButtonIndex (infoPtr, (INT)wParam, - lptbbi->dwMask & 0x80000000); - if (nIndex == -1) - return FALSE; - - btnPtr = &infoPtr->buttons[nIndex]; - if (lptbbi->dwMask & TBIF_COMMAND) - btnPtr->idCommand = lptbbi->idCommand; - if (lptbbi->dwMask & TBIF_IMAGE) - btnPtr->iBitmap = lptbbi->iImage; - if (lptbbi->dwMask & TBIF_LPARAM) - btnPtr->dwData = lptbbi->lParam; - if (lptbbi->dwMask & TBIF_SIZE) - btnPtr->cx = lptbbi->cx; - if (lptbbi->dwMask & TBIF_STATE) - btnPtr->fsState = lptbbi->fsState; - if (lptbbi->dwMask & TBIF_STYLE) - btnPtr->fsStyle = lptbbi->fsStyle; - - if ((lptbbi->dwMask & TBIF_TEXT) && ((INT)lptbbi->pszText != -1)) { - if ((HIWORD(btnPtr->iString) == 0) || (btnPtr->iString == -1)) - /* iString is index, zero it to make Str_SetPtr succeed */ - btnPtr->iString=0; - - Str_SetPtrAtoW ((LPWSTR *)&btnPtr->iString, lptbbi->pszText); - } - - /* save the button rect to see if we need to redraw the whole toolbar */ - oldBtnRect = btnPtr->rect; - TOOLBAR_CalcToolbar(hwnd); - - if (!EqualRect(&oldBtnRect, &btnPtr->rect)) - InvalidateRect(hwnd, NULL, TRUE); - else - InvalidateRect(hwnd, &btnPtr->rect, TRUE); - - return TRUE; -} - - -static LRESULT -TOOLBAR_SetButtonInfoW (HWND hwnd, WPARAM wParam, LPARAM lParam) -{ - TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd); - LPTBBUTTONINFOW lptbbi = (LPTBBUTTONINFOW)lParam; - TBUTTON_INFO *btnPtr; - INT nIndex; - RECT oldBtnRect; - - if (lptbbi == NULL) - return FALSE; - if (lptbbi->cbSize < sizeof(TBBUTTONINFOW)) - return FALSE; - - nIndex = TOOLBAR_GetButtonIndex (infoPtr, (INT)wParam, - lptbbi->dwMask & 0x80000000); - if (nIndex == -1) - return FALSE; - - btnPtr = &infoPtr->buttons[nIndex]; - if (lptbbi->dwMask & TBIF_COMMAND) - btnPtr->idCommand = lptbbi->idCommand; - if (lptbbi->dwMask & TBIF_IMAGE) - btnPtr->iBitmap = lptbbi->iImage; - if (lptbbi->dwMask & TBIF_LPARAM) - btnPtr->dwData = lptbbi->lParam; - if (lptbbi->dwMask & TBIF_SIZE) - btnPtr->cx = lptbbi->cx; - if (lptbbi->dwMask & TBIF_STATE) - btnPtr->fsState = lptbbi->fsState; - if (lptbbi->dwMask & TBIF_STYLE) - btnPtr->fsStyle = lptbbi->fsStyle; - - if ((lptbbi->dwMask & TBIF_TEXT) && ((INT)lptbbi->pszText != -1)) { - if ((HIWORD(btnPtr->iString) == 0) || (btnPtr->iString == -1)) - /* iString is index, zero it to make Str_SetPtr succeed */ - btnPtr->iString=0; - Str_SetPtrW ((LPWSTR *)&btnPtr->iString, lptbbi->pszText); - } - - /* save the button rect to see if we need to redraw the whole toolbar */ - oldBtnRect = btnPtr->rect; - TOOLBAR_CalcToolbar(hwnd); - - if (!EqualRect(&oldBtnRect, &btnPtr->rect)) - InvalidateRect(hwnd, NULL, TRUE); - else - InvalidateRect(hwnd, &btnPtr->rect, TRUE); - - return TRUE; -} - - -static LRESULT -TOOLBAR_SetButtonSize (HWND hwnd, WPARAM wParam, LPARAM lParam) -{ - TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd); - INT cx = LOWORD(lParam), cy = HIWORD(lParam); - - if ((cx < 0) || (cy < 0)) - { - ERR("invalid parameter 0x%08lx\n", (DWORD)lParam); - return FALSE; - } - - TRACE("%p, cx = %d, cy = %d\n", hwnd, cx, cy); - - /* The documentation claims you can only change the button size before - * any button has been added. But this is wrong. - * WINZIP32.EXE (ver 8) calls this on one of its buttons after adding - * it to the toolbar, and it checks that the return value is nonzero - mjm - * Further testing shows that we must actually perform the change too. - */ - /* - * The documentation also does not mention that if 0 is supplied for - * either size, the system changes it to the default of 24 wide and - * 22 high. Demonstarted in ControlSpy Toolbar. GLA 3/02 - */ - infoPtr->nButtonWidth = (cx) ? cx : 24; - infoPtr->nButtonHeight = (cy) ? cy : 22; - return TRUE; -} - - -static LRESULT -TOOLBAR_SetButtonWidth (HWND hwnd, WPARAM wParam, LPARAM lParam) -{ - TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd); - - /* if setting to current values, ignore */ - if ((infoPtr->cxMin == (INT)LOWORD(lParam)) && - (infoPtr->cxMax == (INT)HIWORD(lParam))) { - TRACE("matches current width, min=%d, max=%d, no recalc\n", - infoPtr->cxMin, infoPtr->cxMax); - return TRUE; - } - - /* save new values */ - infoPtr->cxMin = (INT)LOWORD(lParam); - infoPtr->cxMax = (INT)HIWORD(lParam); - - /* if both values are 0 then we are done */ - if (lParam == 0) { - TRACE("setting both min and max to 0, norecalc\n"); - return TRUE; - } - - /* otherwise we need to recalc the toolbar and in some cases - recalc the bounding rectangle (does DrawText w/ DT_CALCRECT - which doesn't actually draw - GA). */ - TRACE("number of buttons %d, cx=%d, cy=%d, recalcing\n", - infoPtr->nNumButtons, infoPtr->cxMin, infoPtr->cxMax); - - TOOLBAR_CalcToolbar (hwnd); - - InvalidateRect (hwnd, NULL, TRUE); - - return TRUE; -} - - -static LRESULT -TOOLBAR_SetCmdId (HWND hwnd, WPARAM wParam, LPARAM lParam) -{ - TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd); - INT nIndex = (INT)wParam; - - if ((nIndex < 0) || (nIndex >= infoPtr->nNumButtons)) - return FALSE; - - infoPtr->buttons[nIndex].idCommand = (INT)lParam; - - if (infoPtr->hwndToolTip) { - - FIXME("change tool tip!\n"); - - } - - return TRUE; -} - - -static LRESULT -TOOLBAR_SetDisabledImageList (HWND hwnd, WPARAM wParam, LPARAM lParam) -{ - TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd); - HIMAGELIST himl = (HIMAGELIST)lParam; - HIMAGELIST himlTemp; - INT id = 0; - - if (infoPtr->iVersion >= 5) - id = wParam; - - himlTemp = TOOLBAR_InsertImageList(&infoPtr->himlDis, - &infoPtr->cimlDis, himl, id); - - /* FIXME: redraw ? */ - - return (LRESULT)himlTemp; -} - - -static LRESULT -TOOLBAR_SetDrawTextFlags (HWND hwnd, WPARAM wParam, LPARAM lParam) -{ - TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd); - DWORD dwTemp; - - TRACE("hwnd = %p, dwMask = 0x%08lx, dwDTFlags = 0x%08lx\n", hwnd, (DWORD)wParam, (DWORD)lParam); - - dwTemp = infoPtr->dwDTFlags; - infoPtr->dwDTFlags = - (infoPtr->dwDTFlags & (DWORD)wParam) | (DWORD)lParam; - - return (LRESULT)dwTemp; -} - -/* This function differs a bit from what MSDN says it does: - * 1. lParam contains extended style flags to OR with current style - * (MSDN isn't clear on the OR bit) - * 2. wParam appears to contain extended style flags to be reset - * (MSDN says that this parameter is reserved) - */ -static LRESULT -TOOLBAR_SetExtendedStyle (HWND hwnd, WPARAM wParam, LPARAM lParam) -{ - TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd); - DWORD dwTemp; - - dwTemp = infoPtr->dwExStyle; - infoPtr->dwExStyle &= ~wParam; - infoPtr->dwExStyle |= (DWORD)lParam; - - TRACE("new style 0x%08lx\n", infoPtr->dwExStyle); - - if (infoPtr->dwExStyle & ~TBSTYLE_EX_ALL) - FIXME("Unknown Toolbar Extended Style 0x%08lx. Please report.\n", - (infoPtr->dwExStyle & ~TBSTYLE_EX_ALL)); - - TOOLBAR_CalcToolbar (hwnd); - - TOOLBAR_AutoSize(hwnd); - - InvalidateRect(hwnd, NULL, TRUE); - - return (LRESULT)dwTemp; -} - - -static LRESULT -TOOLBAR_SetHotImageList (HWND hwnd, WPARAM wParam, LPARAM lParam) -{ - TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr(hwnd); - HIMAGELIST himlTemp; - HIMAGELIST himl = (HIMAGELIST)lParam; - INT id = 0; - - if (infoPtr->iVersion >= 5) - id = wParam; - - TRACE("hwnd = %p, himl = %p, id = %d\n", hwnd, himl, id); - - himlTemp = TOOLBAR_InsertImageList(&infoPtr->himlHot, - &infoPtr->cimlHot, himl, id); - - /* FIXME: redraw ? */ - - return (LRESULT)himlTemp; -} - - -/* Makes previous hot button no longer hot, makes the specified - * button hot and sends appropriate notifications. dwReason is one or - * more HICF_ flags. Specify nHit < 0 to make no buttons hot. - * NOTE 1: this function does not validate nHit - * NOTE 2: the name of this function is completely made up and - * not based on any documentation from Microsoft. */ -static void -TOOLBAR_SetHotItemEx (TOOLBAR_INFO *infoPtr, INT nHit, DWORD dwReason) -{ - if (infoPtr->nHotItem != nHit) - { - NMTBHOTITEM nmhotitem; - TBUTTON_INFO *btnPtr = NULL, *oldBtnPtr = NULL; - LRESULT no_highlight; - - /* Remove the effect of an old hot button if the button was - drawn with the hot button effect */ - if(infoPtr->nHotItem >= 0) - { - oldBtnPtr = &infoPtr->buttons[infoPtr->nHotItem]; - oldBtnPtr->bHot = FALSE; - } - - infoPtr->nHotItem = nHit; - - /* It's not a separator or in nowhere. It's a hot button. */ - if (nHit >= 0) - btnPtr = &infoPtr->buttons[nHit]; - - nmhotitem.dwFlags = dwReason; - if (oldBtnPtr) - nmhotitem.idOld = oldBtnPtr->idCommand; - else - nmhotitem.dwFlags |= HICF_ENTERING; - if (btnPtr) - nmhotitem.idNew = btnPtr->idCommand; - else - nmhotitem.dwFlags |= HICF_LEAVING; - - no_highlight = TOOLBAR_SendNotify(&nmhotitem.hdr, infoPtr, TBN_HOTITEMCHANGE); - - /* now invalidate the old and new buttons so they will be painted */ - if (oldBtnPtr) - InvalidateRect(infoPtr->hwndSelf, &oldBtnPtr->rect, TRUE); - if (btnPtr && !no_highlight) - { - btnPtr->bHot = TRUE; - InvalidateRect(infoPtr->hwndSelf, &btnPtr->rect, TRUE); - } - } -} - -static LRESULT -TOOLBAR_SetHotItem (HWND hwnd, WPARAM wParam) -{ - TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr(hwnd); - INT nOldHotItem = infoPtr->nHotItem; - - TRACE("hwnd = %p, nHit = %d\n", hwnd, (INT)wParam); - - if ((INT) wParam < 0 || (INT)wParam > infoPtr->nNumButtons) - wParam = -1; - - /* NOTE: an application can still remove the hot item even if anchor - * highlighting is enabled */ - - if (infoPtr->dwStyle & TBSTYLE_FLAT) - TOOLBAR_SetHotItemEx(infoPtr, wParam, HICF_OTHER); - - if (nOldHotItem < 0) - return -1; - - return (LRESULT)nOldHotItem; -} - - -static LRESULT -TOOLBAR_SetImageList (HWND hwnd, WPARAM wParam, LPARAM lParam) -{ - TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd); - HIMAGELIST himlTemp; - HIMAGELIST himl = (HIMAGELIST)lParam; - INT i, id = 0; - - if (infoPtr->iVersion >= 5) - id = wParam; - - himlTemp = TOOLBAR_InsertImageList(&infoPtr->himlDef, - &infoPtr->cimlDef, himl, id); - - infoPtr->nNumBitmaps = 0; - for (i = 0; i < infoPtr->cimlDef; i++) - infoPtr->nNumBitmaps += ImageList_GetImageCount(infoPtr->himlDef[i]->himl); - - if (!ImageList_GetIconSize(himl, &infoPtr->nBitmapWidth, - &infoPtr->nBitmapHeight)) - { - infoPtr->nBitmapWidth = 0; - infoPtr->nBitmapHeight = 0; - } - - TRACE("hwnd %p, new himl=%p, id = %d, count=%d, bitmap w=%d, h=%d\n", - hwnd, infoPtr->himlDef, id, infoPtr->nNumBitmaps, - infoPtr->nBitmapWidth, infoPtr->nBitmapHeight); - - InvalidateRect(hwnd, NULL, TRUE); - - return (LRESULT)himlTemp; -} - - -static LRESULT -TOOLBAR_SetIndent (HWND hwnd, WPARAM wParam, LPARAM lParam) -{ - TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd); - - infoPtr->nIndent = (INT)wParam; - - TRACE("\n"); - - /* process only on indent changing */ - if(infoPtr->nIndent != (INT)wParam) - { - infoPtr->nIndent = (INT)wParam; - TOOLBAR_CalcToolbar (hwnd); - InvalidateRect(hwnd, NULL, FALSE); - } - - return TRUE; -} - - -static LRESULT -TOOLBAR_SetInsertMark (HWND hwnd, WPARAM wParam, LPARAM lParam) -{ - TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd); - TBINSERTMARK *lptbim = (TBINSERTMARK*)lParam; - - TRACE("hwnd = %p, lptbim = { %d, 0x%08lx}\n", hwnd, lptbim->iButton, lptbim->dwFlags); - - if ((lptbim->dwFlags & ~TBIMHT_AFTER) != 0) - { - FIXME("Unrecognized flag(s): 0x%08lx\n", (lptbim->dwFlags & ~TBIMHT_AFTER)); - return 0; - } - - if ((lptbim->iButton == -1) || - ((lptbim->iButton < infoPtr->nNumButtons) && - (lptbim->iButton >= 0))) - { - infoPtr->tbim = *lptbim; - /* FIXME: don't need to update entire toolbar */ - InvalidateRect(hwnd, NULL, TRUE); - } - else - ERR("Invalid button index %d\n", lptbim->iButton); - - return 0; -} - - -static LRESULT -TOOLBAR_SetInsertMarkColor (HWND hwnd, WPARAM wParam, LPARAM lParam) -{ - TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd); - - infoPtr->clrInsertMark = (COLORREF)lParam; - - /* FIXME: don't need to update entire toolbar */ - InvalidateRect(hwnd, NULL, TRUE); - - return 0; -} - - -static LRESULT -TOOLBAR_SetMaxTextRows (HWND hwnd, WPARAM wParam, LPARAM lParam) -{ - TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd); - - infoPtr->nMaxTextRows = (INT)wParam; - - TOOLBAR_CalcToolbar(hwnd); - return TRUE; -} - - -/* MSDN gives slightly wrong info on padding. - * 1. It is not only used on buttons with the BTNS_AUTOSIZE style - * 2. It is not used to create a blank area between the edge of the button - * and the text or image if TBSTYLE_LIST is set. It is used to control - * the gap between the image and text. - * 3. It is not applied to both sides. If TBSTYLE_LIST is set it is used - * to control the bottom and right borders [with the border being - * szPadding.cx - (GetSystemMetrics(SM_CXEDGE)+1)], otherwise the padding - * is shared evenly on both sides of the button. - */ -static LRESULT -TOOLBAR_SetPadding (HWND hwnd, WPARAM wParam, LPARAM lParam) -{ - TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd); - DWORD oldPad; - - oldPad = MAKELONG(infoPtr->szPadding.cx, infoPtr->szPadding.cy); - infoPtr->szPadding.cx = LOWORD((DWORD)lParam); - infoPtr->szPadding.cy = HIWORD((DWORD)lParam); - TRACE("cx=%ld, cy=%ld\n", - infoPtr->szPadding.cx, infoPtr->szPadding.cy); - return (LRESULT) oldPad; -} - - -static LRESULT -TOOLBAR_SetParent (HWND hwnd, WPARAM wParam, LPARAM lParam) -{ - TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd); - HWND hwndOldNotify; - - TRACE("\n"); - - hwndOldNotify = infoPtr->hwndNotify; - infoPtr->hwndNotify = (HWND)wParam; - - return (LRESULT)hwndOldNotify; -} - - -static LRESULT -TOOLBAR_SetRows (HWND hwnd, WPARAM wParam, LPARAM lParam) -{ - TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd); - LPRECT lprc = (LPRECT)lParam; - - TRACE("\n"); - - if (LOWORD(wParam) > 1) { - FIXME("multiple rows not supported!\n"); - } - - if(infoPtr->nRows != LOWORD(wParam)) - { - infoPtr->nRows = LOWORD(wParam); - - /* recalculate toolbar */ - TOOLBAR_CalcToolbar (hwnd); - - /* repaint toolbar */ - InvalidateRect(hwnd, NULL, TRUE); - } - - /* return bounding rectangle */ - if (lprc) { - lprc->left = infoPtr->rcBound.left; - lprc->right = infoPtr->rcBound.right; - lprc->top = infoPtr->rcBound.top; - lprc->bottom = infoPtr->rcBound.bottom; - } - - return 0; -} - - -static LRESULT -TOOLBAR_SetState (HWND hwnd, WPARAM wParam, LPARAM lParam) -{ - TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd); - TBUTTON_INFO *btnPtr; - INT nIndex; - - nIndex = TOOLBAR_GetButtonIndex (infoPtr, (INT)wParam, FALSE); - if (nIndex == -1) - return FALSE; - - btnPtr = &infoPtr->buttons[nIndex]; - - /* if hidden state has changed the invalidate entire window and recalc */ - if ((btnPtr->fsState & TBSTATE_HIDDEN) != (LOWORD(lParam) & TBSTATE_HIDDEN)) { - btnPtr->fsState = LOWORD(lParam); - TOOLBAR_CalcToolbar (hwnd); - InvalidateRect(hwnd, 0, TRUE); - return TRUE; - } - - /* process state changing if current state doesn't match new state */ - if(btnPtr->fsState != LOWORD(lParam)) - { - btnPtr->fsState = LOWORD(lParam); - InvalidateRect(hwnd, &btnPtr->rect, TRUE); - } - - return TRUE; -} - - -static LRESULT -TOOLBAR_SetStyle (HWND hwnd, WPARAM wParam, LPARAM lParam) -{ - SetWindowLongW(hwnd, GWL_STYLE, lParam); - - return TRUE; -} - - -inline static LRESULT -TOOLBAR_SetToolTips (HWND hwnd, WPARAM wParam, LPARAM lParam) -{ - TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd); - - TRACE("hwnd=%p, hwndTooltip=%p, lParam=0x%lx\n", hwnd, (HWND)wParam, lParam); - - infoPtr->hwndToolTip = (HWND)wParam; - return 0; -} - - -static LRESULT -TOOLBAR_SetUnicodeFormat (HWND hwnd, WPARAM wParam, LPARAM lParam) -{ - TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd); - BOOL bTemp; - - TRACE("%s hwnd=%p\n", - ((BOOL)wParam) ? "TRUE" : "FALSE", hwnd); - - bTemp = infoPtr->bUnicode; - infoPtr->bUnicode = (BOOL)wParam; - - return bTemp; -} - - -static LRESULT -TOOLBAR_GetColorScheme (HWND hwnd, LPCOLORSCHEME lParam) -{ - TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd); - - lParam->clrBtnHighlight = (infoPtr->clrBtnHighlight == CLR_DEFAULT) ? - comctl32_color.clrBtnHighlight : - infoPtr->clrBtnHighlight; - lParam->clrBtnShadow = (infoPtr->clrBtnShadow == CLR_DEFAULT) ? - comctl32_color.clrBtnShadow : infoPtr->clrBtnShadow; - return 1; -} - - -static LRESULT -TOOLBAR_SetColorScheme (HWND hwnd, LPCOLORSCHEME lParam) -{ - TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd); - - TRACE("new colors Hl=%lx Shd=%lx, old colors Hl=%lx Shd=%lx\n", - lParam->clrBtnHighlight, lParam->clrBtnShadow, - infoPtr->clrBtnHighlight, infoPtr->clrBtnShadow); - - infoPtr->clrBtnHighlight = lParam->clrBtnHighlight; - infoPtr->clrBtnShadow = lParam->clrBtnShadow; - InvalidateRect(hwnd, NULL, TRUE); - return 0; -} - - -static LRESULT -TOOLBAR_SetVersion (HWND hwnd, INT iVersion) -{ - TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd); - INT iOldVersion = infoPtr->iVersion; - - infoPtr->iVersion = iVersion; - - if (infoPtr->iVersion >= 5) - TOOLBAR_SetUnicodeFormat(hwnd, (WPARAM)TRUE, (LPARAM)0); - - return iOldVersion; -} - - -static LRESULT -TOOLBAR_GetStringA (HWND hwnd, WPARAM wParam, LPARAM lParam) -{ - TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr(hwnd); - WORD iString = HIWORD(wParam); - WORD buffersize = LOWORD(wParam); - LPSTR str = (LPSTR)lParam; - LRESULT ret = -1; - - TRACE("hwnd=%p, iString=%d, buffersize=%d, string=%p\n", hwnd, iString, buffersize, str); - - if (iString < infoPtr->nNumStrings) - { - ret = WideCharToMultiByte(CP_ACP, 0, infoPtr->strings[iString], -1, str, buffersize, NULL, NULL); - - TRACE("returning %s\n", debugstr_a(str)); - } - else - ERR("String index %d out of range (largest is %d)\n", iString, infoPtr->nNumStrings - 1); - - return ret; -} - - -static LRESULT -TOOLBAR_GetStringW (HWND hwnd, WPARAM wParam, LPARAM lParam) -{ - TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr(hwnd); - WORD iString = HIWORD(wParam); - WORD len = LOWORD(wParam)/sizeof(WCHAR) - 1; - LPWSTR str = (LPWSTR)lParam; - LRESULT ret = -1; - - TRACE("hwnd=%p, iString=%d, buffersize=%d, string=%p\n", hwnd, iString, LOWORD(wParam), str); - - if (iString < infoPtr->nNumStrings) - { - len = min(len, strlenW(infoPtr->strings[iString])); - ret = (len+1)*sizeof(WCHAR); - memcpy(str, infoPtr->strings[iString], ret); - str[len] = '\0'; - - TRACE("returning %s\n", debugstr_w(str)); - } - else - ERR("String index %d out of range (largest is %d)\n", iString, infoPtr->nNumStrings - 1); - - return ret; -} - -/* UNDOCUMENTED MESSAGE: This appears to set some kind of size. Perhaps it - * is the maximum size of the toolbar? */ -static LRESULT TOOLBAR_Unkwn45D(HWND hwnd, WPARAM wParam, LPARAM lParam) -{ - SIZE * pSize = (SIZE*)lParam; - FIXME("hwnd=%p, wParam=0x%08x, size.cx=%ld, size.cy=%ld stub!\n", hwnd, wParam, pSize->cx, pSize->cy); - return 0; -} - - -/* UNDOCUMENTED MESSAGE: This is an extended version of the - * TB_SETHOTITEM message. It allows the caller to specify a reason why the - * hot item changed (rather than just the HICF_OTHER that TB_SETHOTITEM - * sends). */ -static LRESULT -TOOLBAR_Unkwn45E (HWND hwnd, WPARAM wParam, LPARAM lParam) -{ - TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr(hwnd); - INT nOldHotItem = infoPtr->nHotItem; - - TRACE("old item=%d, new item=%d, flags=%08lx\n", - nOldHotItem, infoPtr->nHotItem, (DWORD)lParam); - - if ((INT) wParam < 0 || (INT)wParam > infoPtr->nNumButtons) - wParam = -1; - - /* NOTE: an application can still remove the hot item even if anchor - * highlighting is enabled */ - - TOOLBAR_SetHotItemEx(infoPtr, wParam, lParam); - - GetFocus(); - - return (nOldHotItem < 0) ? -1 : (LRESULT)nOldHotItem; -} - -/* UNDOCUMENTED MESSAGE: This sets the toolbar global iListGap parameter - * which controls the amount of spacing between the image and the text - * of buttons for TBSTYLE_LIST toolbars. */ -static LRESULT TOOLBAR_Unkwn460(HWND hwnd, WPARAM wParam, LPARAM lParam) -{ - TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr(hwnd); - - TRACE("hwnd=%p iListGap=%d\n", hwnd, wParam); - - if (lParam != 0) - FIXME("lParam = 0x%08lx. Please report\n", lParam); - - infoPtr->iListGap = (INT)wParam; - - InvalidateRect(hwnd, NULL, TRUE); - - return 0; -} - -/* UNDOCUMENTED MESSAGE: This returns the number of maximum number - * of image lists associated with the various states. */ -static LRESULT TOOLBAR_Unkwn462(HWND hwnd, WPARAM wParam, LPARAM lParam) -{ - TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr(hwnd); - - TRACE("hwnd=%p wParam %08x lParam %08lx\n", hwnd, wParam, lParam); - - return max(infoPtr->cimlDef, max(infoPtr->cimlHot, infoPtr->cimlDis)); -} - -static LRESULT -TOOLBAR_Unkwn463 (HWND hwnd, WPARAM wParam, LPARAM lParam) -{ - TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd); - LPSIZE lpsize = (LPSIZE)lParam; - - if (lpsize == NULL) - return FALSE; - - /* - * Testing shows the following: - * wParam = 0 adjust cx value - * = 1 set cy value to max size. - * lParam pointer to SIZE structure - * - */ - TRACE("[0463] wParam %d, lParam 0x%08lx -> 0x%08lx 0x%08lx\n", - wParam, lParam, lpsize->cx, lpsize->cy); - - switch(wParam) { - case 0: - if (lpsize->cx == -1) { - /* **** this is wrong, native measures each button and sets it */ - lpsize->cx = infoPtr->rcBound.right - infoPtr->rcBound.left; - } - else if(HIWORD(lpsize->cx)) { - RECT rc; - HWND hwndParent = GetParent(hwnd); - - GetWindowRect(hwnd, &rc); - MapWindowPoints(0, hwndParent, (LPPOINT)&rc, 2); - TRACE("mapped to (%ld,%ld)-(%ld,%ld)\n", - rc.left, rc.top, rc.right, rc.bottom); - lpsize->cx = max(rc.right-rc.left, - infoPtr->rcBound.right - infoPtr->rcBound.left); - } - else { - lpsize->cx = infoPtr->rcBound.right - infoPtr->rcBound.left; - } - break; - case 1: - lpsize->cy = infoPtr->rcBound.bottom - infoPtr->rcBound.top; - /* lpsize->cy = infoPtr->nHeight; */ - break; - default: - ERR("Unknown wParam %d for Toolbar message [0463]. Please report\n", - wParam); - return 0; - } - TRACE("[0463] set to -> 0x%08lx 0x%08lx\n", - lpsize->cx, lpsize->cy); - return 1; -} - -static LRESULT TOOLBAR_Unkwn464(HWND hwnd, WPARAM wParam, LPARAM lParam) -{ - FIXME("hwnd=%p wParam %08x lParam %08lx\n", hwnd, wParam, lParam); - - InvalidateRect(hwnd, NULL, TRUE); - return 1; -} - - -static LRESULT -TOOLBAR_Create (HWND hwnd, WPARAM wParam, LPARAM lParam) -{ - TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd); - DWORD dwStyle = GetWindowLongW (hwnd, GWL_STYLE); - LOGFONTA logFont; - - TRACE("hwnd = %p\n", hwnd); - - /* initialize info structure */ - infoPtr->nButtonHeight = 22; - infoPtr->nButtonWidth = 24; - infoPtr->nBitmapHeight = 15; - infoPtr->nBitmapWidth = 16; - - infoPtr->nHeight = infoPtr->nButtonHeight + TOP_BORDER + BOTTOM_BORDER; - infoPtr->nMaxTextRows = 1; - infoPtr->cxMin = -1; - infoPtr->cxMax = -1; - infoPtr->nNumBitmaps = 0; - infoPtr->nNumStrings = 0; - - infoPtr->bCaptured = FALSE; - infoPtr->nButtonDown = -1; - infoPtr->nButtonDrag = -1; - infoPtr->nOldHit = -1; - infoPtr->nHotItem = -1; - infoPtr->hwndNotify = ((LPCREATESTRUCTW)lParam)->hwndParent; - infoPtr->bBtnTranspnt = (dwStyle & (TBSTYLE_FLAT | TBSTYLE_LIST)); - infoPtr->dwDTFlags = (dwStyle & TBSTYLE_LIST) ? DT_LEFT | DT_VCENTER | DT_SINGLELINE | DT_END_ELLIPSIS: DT_CENTER | DT_END_ELLIPSIS; - infoPtr->bAnchor = FALSE; /* no anchor highlighting */ - infoPtr->bDragOutSent = FALSE; - infoPtr->iVersion = 0; - infoPtr->hwndSelf = hwnd; - infoPtr->bDoRedraw = TRUE; - infoPtr->clrBtnHighlight = CLR_DEFAULT; - infoPtr->clrBtnShadow = CLR_DEFAULT; - infoPtr->szPadding.cx = DEFPAD_CX; - infoPtr->szPadding.cy = DEFPAD_CY; - infoPtr->iListGap = infoPtr->szPadding.cx / 2; - infoPtr->dwStyle = dwStyle; - infoPtr->tbim.iButton = -1; - GetClientRect(hwnd, &infoPtr->client_rect); - infoPtr->bUnicode = infoPtr->hwndNotify && - (NFR_UNICODE == SendMessageW(hwnd, WM_NOTIFYFORMAT, (WPARAM)hwnd, (LPARAM)NF_REQUERY)); - - SystemParametersInfoA (SPI_GETICONTITLELOGFONT, 0, &logFont, 0); - infoPtr->hFont = infoPtr->hDefaultFont = CreateFontIndirectA (&logFont); - - if (dwStyle & TBSTYLE_TOOLTIPS) { - /* Create tooltip control */ - infoPtr->hwndToolTip = - CreateWindowExA (0, TOOLTIPS_CLASSA, NULL, 0, - CW_USEDEFAULT, CW_USEDEFAULT, - CW_USEDEFAULT, CW_USEDEFAULT, - hwnd, 0, 0, 0); - - /* Send NM_TOOLTIPSCREATED notification */ - if (infoPtr->hwndToolTip) - { - NMTOOLTIPSCREATED nmttc; - - nmttc.hwndToolTips = infoPtr->hwndToolTip; - - TOOLBAR_SendNotify (&nmttc.hdr, infoPtr, NM_TOOLTIPSCREATED); - } - } - - TOOLBAR_CheckStyle (hwnd, dwStyle); - - TOOLBAR_CalcToolbar(hwnd); - - return 0; -} - - -static LRESULT -TOOLBAR_Destroy (HWND hwnd, WPARAM wParam, LPARAM lParam) -{ - TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd); - - /* delete tooltip control */ - if (infoPtr->hwndToolTip) - DestroyWindow (infoPtr->hwndToolTip); - - /* delete temporary buffer for tooltip text */ - if (infoPtr->pszTooltipText) - HeapFree(GetProcessHeap(), 0, infoPtr->pszTooltipText); - - /* delete button data */ - if (infoPtr->buttons) - Free (infoPtr->buttons); - - /* delete strings */ - if (infoPtr->strings) { - INT i; - for (i = 0; i < infoPtr->nNumStrings; i++) - if (infoPtr->strings[i]) - Free (infoPtr->strings[i]); - - Free (infoPtr->strings); - } - - /* destroy internal image list */ - if (infoPtr->himlInt) - ImageList_Destroy (infoPtr->himlInt); - - TOOLBAR_DeleteImageList(&infoPtr->himlDef, &infoPtr->cimlDef); - TOOLBAR_DeleteImageList(&infoPtr->himlDis, &infoPtr->cimlDis); - TOOLBAR_DeleteImageList(&infoPtr->himlHot, &infoPtr->cimlHot); - - /* delete default font */ - if (infoPtr->hFont) - DeleteObject (infoPtr->hDefaultFont); - - /* free toolbar info data */ - Free (infoPtr); - SetWindowLongPtrW (hwnd, 0, 0); - - return 0; -} - - -static LRESULT -TOOLBAR_EraseBackground (HWND hwnd, WPARAM wParam, LPARAM lParam) -{ - TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd); - NMTBCUSTOMDRAW tbcd; - INT ret = FALSE; - DWORD ntfret; - - /* the app has told us not to redraw the toolbar */ - if (!infoPtr->bDoRedraw) - return FALSE; - - if (infoPtr->dwStyle & TBSTYLE_CUSTOMERASE) { - ZeroMemory (&tbcd, sizeof(NMTBCUSTOMDRAW)); - tbcd.nmcd.dwDrawStage = CDDS_PREERASE; - tbcd.nmcd.hdc = (HDC)wParam; - ntfret = TOOLBAR_SendNotify (&tbcd.nmcd.hdr, infoPtr, NM_CUSTOMDRAW); - infoPtr->dwBaseCustDraw = ntfret & 0xffff; - - /* FIXME: in general the return flags *can* be or'ed together */ - switch (infoPtr->dwBaseCustDraw) - { - case CDRF_DODEFAULT: - break; - case CDRF_SKIPDEFAULT: - return TRUE; - default: - FIXME("[%p] response %ld not handled to NM_CUSTOMDRAW (CDDS_PREERASE)\n", - hwnd, ntfret); - } - } - - /* If the toolbar is "transparent" then pass the WM_ERASEBKGND up - * to my parent for processing. - */ - if (infoPtr->dwStyle & TBSTYLE_TRANSPARENT) { - POINT pt, ptorig; - HDC hdc = (HDC)wParam; - HWND parent; - - pt.x = 0; - pt.y = 0; - parent = GetParent(hwnd); - MapWindowPoints(hwnd, parent, &pt, 1); - OffsetWindowOrgEx (hdc, pt.x, pt.y, &ptorig); - ret = SendMessageW (parent, WM_ERASEBKGND, wParam, lParam); - SetWindowOrgEx (hdc, ptorig.x, ptorig.y, 0); - } - if (!ret) - ret = DefWindowProcW (hwnd, WM_ERASEBKGND, wParam, lParam); - - if ((infoPtr->dwStyle & TBSTYLE_CUSTOMERASE) && - (infoPtr->dwBaseCustDraw & CDRF_NOTIFYPOSTERASE)) { - ZeroMemory (&tbcd, sizeof(NMTBCUSTOMDRAW)); - tbcd.nmcd.dwDrawStage = CDDS_POSTERASE; - tbcd.nmcd.hdc = (HDC)wParam; - ntfret = TOOLBAR_SendNotify (&tbcd.nmcd.hdr, infoPtr, NM_CUSTOMDRAW); - infoPtr->dwBaseCustDraw = ntfret & 0xffff; - switch (infoPtr->dwBaseCustDraw) - { - case CDRF_DODEFAULT: - break; - case CDRF_SKIPDEFAULT: - return TRUE; - default: - FIXME("[%p] response %ld not handled to NM_CUSTOMDRAW (CDDS_POSTERASE)\n", - hwnd, ntfret); - } - } - return ret; -} - - -static LRESULT -TOOLBAR_GetFont (HWND hwnd, WPARAM wParam, LPARAM lParam) -{ - TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd); - - return (LRESULT)infoPtr->hFont; -} - - -static LRESULT -TOOLBAR_LButtonDblClk (HWND hwnd, WPARAM wParam, LPARAM lParam) -{ - POINT pt; - INT nHit; - - pt.x = (INT)LOWORD(lParam); - pt.y = (INT)HIWORD(lParam); - nHit = TOOLBAR_InternalHitTest (hwnd, &pt); - - if (nHit >= 0) - TOOLBAR_LButtonDown (hwnd, wParam, lParam); - else if (GetWindowLongA (hwnd, GWL_STYLE) & CCS_ADJUSTABLE) - TOOLBAR_Customize (hwnd); - - return 0; -} - - -static LRESULT -TOOLBAR_LButtonDown (HWND hwnd, WPARAM wParam, LPARAM lParam) -{ - TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd); - TBUTTON_INFO *btnPtr; - POINT pt; - INT nHit; - NMTOOLBARA nmtb; - NMMOUSE nmmouse; - BOOL bDragKeyPressed; - - TRACE("\n"); - - if (infoPtr->dwStyle & TBSTYLE_ALTDRAG) - bDragKeyPressed = (GetKeyState(VK_MENU) < 0); - else - bDragKeyPressed = (wParam & MK_SHIFT); - - if (infoPtr->hwndToolTip) - TOOLBAR_RelayEvent (infoPtr->hwndToolTip, hwnd, - WM_LBUTTONDOWN, wParam, lParam); - - pt.x = (INT)LOWORD(lParam); - pt.y = (INT)HIWORD(lParam); - nHit = TOOLBAR_InternalHitTest (hwnd, &pt); - - btnPtr = &infoPtr->buttons[nHit]; - - if ((nHit >= 0) && bDragKeyPressed && (infoPtr->dwStyle & CCS_ADJUSTABLE)) - { - infoPtr->nButtonDrag = nHit; - SetCapture (hwnd); - - /* If drag cursor has not been loaded, load it. - * Note: it doesn't need to be freed */ - if (!hCursorDrag) - hCursorDrag = LoadCursorW(COMCTL32_hModule, (LPCWSTR)IDC_MOVEBUTTON); - SetCursor(hCursorDrag); - } - else if (nHit >= 0) - { - RECT arrowRect; - infoPtr->nOldHit = nHit; - - CopyRect(&arrowRect, &btnPtr->rect); - arrowRect.left = max(btnPtr->rect.left, btnPtr->rect.right - DDARROW_WIDTH); - - /* for EX_DRAWDDARROWS style, click must be in the drop-down arrow rect */ - if ((btnPtr->fsState & TBSTATE_ENABLED) && - ((btnPtr->fsStyle & BTNS_WHOLEDROPDOWN) || - ((btnPtr->fsStyle & BTNS_DROPDOWN) && - ((TOOLBAR_HasDropDownArrows(infoPtr->dwExStyle) && PtInRect(&arrowRect, pt)) || - (!TOOLBAR_HasDropDownArrows(infoPtr->dwExStyle)))))) - { - LRESULT res; - - /* draw in pressed state */ - if (btnPtr->fsStyle & BTNS_WHOLEDROPDOWN) - btnPtr->fsState |= TBSTATE_PRESSED; - else - btnPtr->bDropDownPressed = TRUE; - RedrawWindow(hwnd,&btnPtr->rect,0, - RDW_ERASE|RDW_INVALIDATE|RDW_UPDATENOW); - - memset(&nmtb, 0, sizeof(nmtb)); - nmtb.iItem = btnPtr->idCommand; - nmtb.rcButton = btnPtr->rect; - res = TOOLBAR_SendNotify ((NMHDR *) &nmtb, infoPtr, - TBN_DROPDOWN); - TRACE("TBN_DROPDOWN responded with %ld\n", res); - - if (res != TBDDRET_TREATPRESSED) - { - MSG msg; - - /* redraw button in unpressed state */ - if (btnPtr->fsStyle & BTNS_WHOLEDROPDOWN) - btnPtr->fsState &= ~TBSTATE_PRESSED; - else - btnPtr->bDropDownPressed = FALSE; - InvalidateRect(hwnd, &btnPtr->rect, TRUE); - - /* find and set hot item - * NOTE: native doesn't do this, but that is a bug */ - GetCursorPos(&pt); - ScreenToClient(hwnd, &pt); - nHit = TOOLBAR_InternalHitTest(hwnd, &pt); - if (!infoPtr->bAnchor || (nHit >= 0)) - TOOLBAR_SetHotItemEx(infoPtr, nHit, HICF_MOUSE | HICF_LMOUSE); - - /* remove any left mouse button down or double-click messages - * so that we can get a toggle effect on the button */ - while (PeekMessageW(&msg, hwnd, WM_LBUTTONDOWN, WM_LBUTTONDOWN, PM_REMOVE) || - PeekMessageW(&msg, hwnd, WM_LBUTTONDBLCLK, WM_LBUTTONDBLCLK, PM_REMOVE)) - ; - - return 0; - } - /* otherwise drop through and process as pushed */ - } - infoPtr->bCaptured = TRUE; - infoPtr->nButtonDown = nHit; - infoPtr->bDragOutSent = FALSE; - - btnPtr->fsState |= TBSTATE_PRESSED; - - TOOLBAR_SetHotItemEx(infoPtr, nHit, HICF_MOUSE | HICF_LMOUSE); - - if (btnPtr->fsState & TBSTATE_ENABLED) - InvalidateRect(hwnd, &btnPtr->rect, TRUE); - UpdateWindow(hwnd); - SetCapture (hwnd); - } - - if (nHit >=0) - { - memset(&nmtb, 0, sizeof(nmtb)); - nmtb.iItem = btnPtr->idCommand; - TOOLBAR_SendNotify((NMHDR *)&nmtb, infoPtr, TBN_BEGINDRAG); - } - - nmmouse.dwHitInfo = nHit; - - /* !!! Undocumented - sends NM_LDOWN with the NMMOUSE structure. */ - if (nHit < 0) - nmmouse.dwItemSpec = -1; - else - { - nmmouse.dwItemSpec = infoPtr->buttons[nmmouse.dwHitInfo].idCommand; - nmmouse.dwItemData = infoPtr->buttons[nmmouse.dwHitInfo].dwData; - } - - ClientToScreen(hwnd, &pt); - nmmouse.pt = pt; - - if (!TOOLBAR_SendNotify(&nmmouse.hdr, infoPtr, NM_LDOWN)) - return DefWindowProcW(hwnd, WM_LBUTTONDOWN, wParam, lParam); - - return 0; -} - -static LRESULT -TOOLBAR_LButtonUp (HWND hwnd, WPARAM wParam, LPARAM lParam) -{ - TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd); - TBUTTON_INFO *btnPtr; - POINT pt; - INT nHit; - INT nOldIndex = -1; - BOOL bSendMessage = TRUE; - NMHDR hdr; - NMMOUSE nmmouse; - NMTOOLBARA nmtb; - - if (infoPtr->hwndToolTip) - TOOLBAR_RelayEvent (infoPtr->hwndToolTip, hwnd, - WM_LBUTTONUP, wParam, lParam); - - pt.x = (INT)LOWORD(lParam); - pt.y = (INT)HIWORD(lParam); - nHit = TOOLBAR_InternalHitTest (hwnd, &pt); - - if (!infoPtr->bAnchor || (nHit >= 0)) - TOOLBAR_SetHotItemEx(infoPtr, nHit, HICF_MOUSE | HICF_LMOUSE); - - if (infoPtr->nButtonDrag >= 0) { - RECT rcClient; - NMHDR hdr; - - btnPtr = &infoPtr->buttons[infoPtr->nButtonDrag]; - ReleaseCapture(); - /* reset cursor */ - SetCursor(LoadCursorW(NULL, (LPCWSTR)IDC_ARROW)); - - GetClientRect(hwnd, &rcClient); - if (PtInRect(&rcClient, pt)) - { - INT nButton = -1; - if (nHit >= 0) - nButton = nHit; - else if (nHit < -1) - nButton = -nHit; - else if ((nHit == -1) && PtInRect(&infoPtr->buttons[-nHit].rect, pt)) - nButton = -nHit; - - if (nButton == infoPtr->nButtonDrag) - { - /* if the button is moved sightly left and we have a - * separator there then remove it */ - if (pt.x < (btnPtr->rect.left + (btnPtr->rect.right - btnPtr->rect.left)/2)) - { - if ((nButton > 0) && (infoPtr->buttons[nButton-1].fsStyle & BTNS_SEP)) - TOOLBAR_DeleteButton(hwnd, nButton - 1, 0); - } - else /* else insert a separator before the dragged button */ - { - TBBUTTON tbb; - memset(&tbb, 0, sizeof(tbb)); - tbb.fsStyle = BTNS_SEP; - tbb.iString = -1; - TOOLBAR_InsertButtonW(hwnd, nButton, (LPARAM)&tbb); - } - } - else - { - if (nButton == -1) - { - if ((infoPtr->nNumButtons > 0) && (pt.x < infoPtr->buttons[0].rect.left)) - TOOLBAR_MoveButton(hwnd, infoPtr->nButtonDrag, 0); - else - TOOLBAR_MoveButton(hwnd, infoPtr->nButtonDrag, infoPtr->nNumButtons); - } - else - TOOLBAR_MoveButton(hwnd, infoPtr->nButtonDrag, nButton); - } - } - else - { - TRACE("button %d dragged out of toolbar\n", infoPtr->nButtonDrag); - TOOLBAR_DeleteButton(hwnd, (WPARAM)infoPtr->nButtonDrag, 0); - } - - /* button under cursor changed so need to re-set hot item */ - TOOLBAR_SetHotItemEx(infoPtr, nHit, HICF_MOUSE | HICF_LMOUSE); - infoPtr->nButtonDrag = -1; - - TOOLBAR_SendNotify(&hdr, infoPtr, TBN_TOOLBARCHANGE); - } - else if (infoPtr->nButtonDown >= 0) { - btnPtr = &infoPtr->buttons[infoPtr->nButtonDown]; - btnPtr->fsState &= ~TBSTATE_PRESSED; - - if (btnPtr->fsStyle & BTNS_CHECK) { - if (btnPtr->fsStyle & BTNS_GROUP) { - nOldIndex = TOOLBAR_GetCheckedGroupButtonIndex (infoPtr, - nHit); - if (nOldIndex == nHit) - bSendMessage = FALSE; - if ((nOldIndex != nHit) && - (nOldIndex != -1)) - infoPtr->buttons[nOldIndex].fsState &= ~TBSTATE_CHECKED; - btnPtr->fsState |= TBSTATE_CHECKED; - } - else { - if (btnPtr->fsState & TBSTATE_CHECKED) - btnPtr->fsState &= ~TBSTATE_CHECKED; - else - btnPtr->fsState |= TBSTATE_CHECKED; - } - } - - if (nOldIndex != -1) - InvalidateRect(hwnd, &infoPtr->buttons[nOldIndex].rect, TRUE); - - /* - * now we can ReleaseCapture, which triggers CAPTURECHANGED msg, - * that resets bCaptured and btn TBSTATE_PRESSED flags, - * and obliterates nButtonDown and nOldHit (see TOOLBAR_CaptureChanged) - */ - if ((infoPtr->bCaptured) && (infoPtr->nButtonDown >= 0)) - ReleaseCapture (); - infoPtr->nButtonDown = -1; - - /* Issue NM_RELEASEDCAPTURE to parent to let him know it is released */ - TOOLBAR_SendNotify ((NMHDR *) &hdr, infoPtr, - NM_RELEASEDCAPTURE); - - /* native issues TBN_ENDDRAG here, if _LBUTTONDOWN issued the - * TBN_BEGINDRAG - */ - memset(&nmtb, 0, sizeof(nmtb)); - nmtb.iItem = btnPtr->idCommand; - TOOLBAR_SendNotify ((NMHDR *) &nmtb, infoPtr, - TBN_ENDDRAG); - - if (btnPtr->fsState & TBSTATE_ENABLED) - { - SendMessageW (infoPtr->hwndNotify, WM_COMMAND, - MAKEWPARAM(infoPtr->buttons[nHit].idCommand, 0), (LPARAM)hwnd); - } - } - - /* !!! Undocumented - toolbar at 4.71 level and above sends - * NM_CLICK with the NMMOUSE structure. */ - nmmouse.dwHitInfo = nHit; - - if (nmmouse.dwHitInfo < 0) - nmmouse.dwItemSpec = -1; - else - { - nmmouse.dwItemSpec = infoPtr->buttons[nmmouse.dwHitInfo].idCommand; - nmmouse.dwItemData = infoPtr->buttons[nmmouse.dwHitInfo].dwData; - } - - ClientToScreen(hwnd, &pt); - nmmouse.pt = pt; - - if (!TOOLBAR_SendNotify((LPNMHDR)&nmmouse, infoPtr, NM_CLICK)) - return DefWindowProcW(hwnd, WM_LBUTTONUP, wParam, lParam); - - return 0; -} - -static LRESULT -TOOLBAR_RButtonUp( HWND hwnd, WPARAM wParam, LPARAM lParam) -{ - TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd); - INT nHit; - NMMOUSE nmmouse; - POINT pt; - - pt.x = LOWORD(lParam); - pt.y = HIWORD(lParam); - - nHit = TOOLBAR_InternalHitTest(hwnd, &pt); - nmmouse.dwHitInfo = nHit; - - if (nHit < 0) { - nmmouse.dwItemSpec = -1; - } else { - nmmouse.dwItemSpec = infoPtr->buttons[nmmouse.dwHitInfo].idCommand; - nmmouse.dwItemData = infoPtr->buttons[nmmouse.dwHitInfo].dwData; - } - - ClientToScreen(hwnd, &pt); - nmmouse.pt = pt; - - if (!TOOLBAR_SendNotify((LPNMHDR)&nmmouse, infoPtr, NM_RCLICK)) - return DefWindowProcW(hwnd, WM_RBUTTONUP, wParam, lParam); - - return 0; -} - -static LRESULT -TOOLBAR_RButtonDblClk( HWND hwnd, WPARAM wParam, LPARAM lParam) -{ - TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd); - NMHDR nmhdr; - - if (!TOOLBAR_SendNotify(&nmhdr, infoPtr, NM_RDBLCLK)) - return DefWindowProcW(hwnd, WM_RBUTTONDBLCLK, wParam, lParam); - - return 0; -} - -static LRESULT -TOOLBAR_CaptureChanged(HWND hwnd) -{ - TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd); - TBUTTON_INFO *btnPtr; - - infoPtr->bCaptured = FALSE; - - if (infoPtr->nButtonDown >= 0) - { - btnPtr = &infoPtr->buttons[infoPtr->nButtonDown]; - btnPtr->fsState &= ~TBSTATE_PRESSED; - - infoPtr->nOldHit = -1; - - if (btnPtr->fsState & TBSTATE_ENABLED) - InvalidateRect(hwnd, &btnPtr->rect, TRUE); - } - return 0; -} - -static LRESULT -TOOLBAR_MouseLeave (HWND hwnd, WPARAM wParam, LPARAM lParam) -{ - TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd); - TBUTTON_INFO *hotBtnPtr; - - hotBtnPtr = &infoPtr->buttons[infoPtr->nOldHit]; - - /* don't remove hot effects when in anchor highlighting mode or when a - * drop-down button is pressed */ - if (!infoPtr->bAnchor && (infoPtr->nOldHit < 0 || !hotBtnPtr->bDropDownPressed)) - TOOLBAR_SetHotItemEx(infoPtr, TOOLBAR_NOWHERE, HICF_MOUSE); - - if (infoPtr->nOldHit < 0) - return TRUE; - - /* If the last button we were over is depressed then make it not */ - /* depressed and redraw it */ - if(infoPtr->nOldHit == infoPtr->nButtonDown) - { - TBUTTON_INFO *btnPtr; - RECT rc1; - - btnPtr = &infoPtr->buttons[infoPtr->nButtonDown]; - - btnPtr->fsState &= ~TBSTATE_PRESSED; - - rc1 = hotBtnPtr->rect; - InflateRect (&rc1, 1, 1); - InvalidateRect (hwnd, &rc1, TRUE); - } - - if (infoPtr->bCaptured && !infoPtr->bDragOutSent) - { - NMTOOLBARW nmt; - ZeroMemory(&nmt, sizeof(nmt)); - nmt.iItem = infoPtr->buttons[infoPtr->nButtonDown].idCommand; - TOOLBAR_SendNotify(&nmt.hdr, infoPtr, TBN_DRAGOUT); - infoPtr->bDragOutSent = TRUE; - } - - infoPtr->nOldHit = -1; /* reset the old hit index as we've left the toolbar */ - - return TRUE; -} - -static LRESULT -TOOLBAR_MouseMove (HWND hwnd, WPARAM wParam, LPARAM lParam) -{ - TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd); - POINT pt; - TRACKMOUSEEVENT trackinfo; - INT nHit; - TBUTTON_INFO *btnPtr; - - /* fill in the TRACKMOUSEEVENT struct */ - trackinfo.cbSize = sizeof(TRACKMOUSEEVENT); - trackinfo.dwFlags = TME_QUERY; - trackinfo.hwndTrack = hwnd; - trackinfo.dwHoverTime = HOVER_DEFAULT; - - /* call _TrackMouseEvent to see if we are currently tracking for this hwnd */ - _TrackMouseEvent(&trackinfo); - - /* Make sure tracking is enabled so we receive a WM_MOUSELEAVE message */ - if(!(trackinfo.dwFlags & TME_LEAVE)) { - trackinfo.dwFlags = TME_LEAVE; /* notify upon leaving */ - - /* call TRACKMOUSEEVENT so we receive a WM_MOUSELEAVE message */ - /* and can properly deactivate the hot toolbar button */ - _TrackMouseEvent(&trackinfo); - } - - if (infoPtr->hwndToolTip) - TOOLBAR_RelayEvent (infoPtr->hwndToolTip, hwnd, - WM_MOUSEMOVE, wParam, lParam); - - pt.x = (INT)LOWORD(lParam); - pt.y = (INT)HIWORD(lParam); - - nHit = TOOLBAR_InternalHitTest (hwnd, &pt); - - if (!infoPtr->bAnchor || (nHit >= 0)) - TOOLBAR_SetHotItemEx(infoPtr, nHit, HICF_MOUSE); - - if (infoPtr->nOldHit != nHit) - { - if (infoPtr->bCaptured) - { - if (!infoPtr->bDragOutSent) - { - NMTOOLBARW nmt; - ZeroMemory(&nmt, sizeof(nmt)); - nmt.iItem = infoPtr->buttons[infoPtr->nButtonDown].idCommand; - TOOLBAR_SendNotify(&nmt.hdr, infoPtr, TBN_DRAGOUT); - infoPtr->bDragOutSent = TRUE; - } - - btnPtr = &infoPtr->buttons[infoPtr->nButtonDown]; - if (infoPtr->nOldHit == infoPtr->nButtonDown) { - btnPtr->fsState &= ~TBSTATE_PRESSED; - InvalidateRect(hwnd, &btnPtr->rect, TRUE); - } - else if (nHit == infoPtr->nButtonDown) { - btnPtr->fsState |= TBSTATE_PRESSED; - InvalidateRect(hwnd, &btnPtr->rect, TRUE); - } - infoPtr->nOldHit = nHit; - } - } - - return 0; -} - - -inline static LRESULT -TOOLBAR_NCActivate (HWND hwnd, WPARAM wParam, LPARAM lParam) -{ -/* if (wndPtr->dwStyle & CCS_NODIVIDER) */ - return DefWindowProcW (hwnd, WM_NCACTIVATE, wParam, lParam); -/* else */ -/* return TOOLBAR_NCPaint (wndPtr, wParam, lParam); */ -} - - -inline static LRESULT -TOOLBAR_NCCalcSize (HWND hwnd, WPARAM wParam, LPARAM lParam) -{ - if (!(GetWindowLongW(hwnd, GWL_STYLE) & CCS_NODIVIDER)) - ((LPRECT)lParam)->top += GetSystemMetrics(SM_CYEDGE); - - return DefWindowProcW (hwnd, WM_NCCALCSIZE, wParam, lParam); -} - - -static LRESULT -TOOLBAR_NCCreate (HWND hwnd, WPARAM wParam, LPARAM lParam) -{ - TOOLBAR_INFO *infoPtr; - LPCREATESTRUCTA cs = (LPCREATESTRUCTA)lParam; - DWORD styleadd = 0; - - /* allocate memory for info structure */ - infoPtr = (TOOLBAR_INFO *)Alloc (sizeof(TOOLBAR_INFO)); - SetWindowLongPtrW (hwnd, 0, (LONG_PTR)infoPtr); - - /* paranoid!! */ - infoPtr->dwStructSize = sizeof(TBBUTTON); - infoPtr->nRows = 1; - - /* fix instance handle, if the toolbar was created by CreateToolbarEx() */ - if (!GetWindowLongPtrW (hwnd, GWLP_HINSTANCE)) { - HINSTANCE hInst = (HINSTANCE)GetWindowLongPtrW (GetParent (hwnd), GWLP_HINSTANCE); - SetWindowLongPtrW (hwnd, GWLP_HINSTANCE, (LONG_PTR)hInst); - } - - /* native control does: - * Get a lot of colors and brushes - * WM_NOTIFYFORMAT - * SystemParametersInfoA(0x1f, 0x3c, adr1, 0) - * CreateFontIndirectA(adr1) - * CreateBitmap(0x27, 0x24, 1, 1, 0) - * hdc = GetDC(toolbar) - * GetSystemMetrics(0x48) - * fnt2=CreateFontA(0xe, 0, 0, 0, 0x190, 0, 0, 0, 0, 2, - * 0, 0, 0, 0, "MARLETT") - * oldfnt = SelectObject(hdc, fnt2) - * GetCharWidthA(hdc, 0x36, 0x36, adr2) - * GetTextMetricsA(hdc, adr3) - * SelectObject(hdc, oldfnt) - * DeleteObject(fnt2) - * ReleaseDC(hdc) - * InvalidateRect(toolbar, 0, 1) - * SetWindowLongA(toolbar, 0, addr) - * SetWindowLongA(toolbar, -16, xxx) **sometimes** - * WM_STYLECHANGING - * CallWinEx old new - * ie 1 0x56000a4c 0x46000a4c 0x56008a4d - * ie 2 0x4600094c 0x4600094c 0x4600894d - * ie 3 0x56000b4c 0x46000b4c 0x56008b4d - * rebar 0x50008844 0x40008844 0x50008845 - * pager 0x50000844 0x40000844 0x50008845 - * IC35mgr 0x5400084e **nochange** - * on entry to _NCCREATE 0x5400084e - * rowlist 0x5400004e **nochange** - * on entry to _NCCREATE 0x5400004e - * - */ - - /* I think the code below is a bug, but it is the way that the native - * controls seem to work. The effect is that if the user of TBSTYLE_FLAT - * forgets to specify TBSTYLE_TRANSPARENT but does specify either - * CCS_TOP or CCS_BOTTOM (_NOMOVEY and _TOP), then the control - * does *not* set TBSTYLE_TRANSPARENT even though it should!!!! - * Some how, the only cases of this seem to be MFC programs. - * - * Note also that the addition of _TRANSPARENT occurs *only* here. It - * does not occur in the WM_STYLECHANGING routine. - * (Guy Albertelli 9/2001) - * - */ - if ((cs->style & TBSTYLE_FLAT) && !(cs->style & TBSTYLE_TRANSPARENT)) - styleadd |= TBSTYLE_TRANSPARENT; - if (!(cs->style & (CCS_TOP | CCS_NOMOVEY))) { - styleadd |= CCS_TOP; /* default to top */ - SetWindowLongW (hwnd, GWL_STYLE, cs->style | styleadd); - } - - return DefWindowProcW (hwnd, WM_NCCREATE, wParam, lParam); -} - - -static LRESULT -TOOLBAR_NCPaint (HWND hwnd, WPARAM wParam, LPARAM lParam) -{ - DWORD dwStyle = GetWindowLongW(hwnd, GWL_STYLE); - RECT rcWindow; - HDC hdc; - - if (dwStyle & WS_MINIMIZE) - return 0; /* Nothing to do */ - - DefWindowProcW (hwnd, WM_NCPAINT, wParam, lParam); - - if (!(hdc = GetDCEx (hwnd, 0, DCX_USESTYLE | DCX_WINDOW))) - return 0; - - if (!(dwStyle & CCS_NODIVIDER)) - { - GetWindowRect (hwnd, &rcWindow); - OffsetRect (&rcWindow, -rcWindow.left, -rcWindow.top); - if( dwStyle & WS_BORDER ) - OffsetRect (&rcWindow, 1, 1); - DrawEdge (hdc, &rcWindow, EDGE_ETCHED, BF_TOP); - } - - ReleaseDC( hwnd, hdc ); - - return 0; -} - - -/* handles requests from the tooltip control on what text to display */ -static LRESULT TOOLBAR_TTGetDispInfo (TOOLBAR_INFO *infoPtr, NMTTDISPINFOW *lpnmtdi) -{ - int index = TOOLBAR_GetButtonIndex(infoPtr, lpnmtdi->hdr.idFrom, FALSE); - - TRACE("button index = %d\n", index); - - if (infoPtr->pszTooltipText) - { - HeapFree(GetProcessHeap(), 0, infoPtr->pszTooltipText); - infoPtr->pszTooltipText = NULL; - } - - if (index < 0) - return 0; - - if (infoPtr->bUnicode) - { - WCHAR wszBuffer[INFOTIPSIZE+1]; - NMTBGETINFOTIPW tbgit; - unsigned int len; /* in chars */ - - wszBuffer[0] = '\0'; - wszBuffer[INFOTIPSIZE] = '\0'; - - tbgit.pszText = wszBuffer; - tbgit.cchTextMax = INFOTIPSIZE; - tbgit.iItem = lpnmtdi->hdr.idFrom; - tbgit.lParam = infoPtr->buttons[index].dwData; - - TOOLBAR_SendNotify(&tbgit.hdr, infoPtr, TBN_GETINFOTIPW); - - TRACE("TBN_GETINFOTIPW - got string %s\n", debugstr_w(tbgit.pszText)); - - len = strlenW(tbgit.pszText); - if (len > sizeof(lpnmtdi->szText)/sizeof(lpnmtdi->szText[0])-1) - { - /* need to allocate temporary buffer in infoPtr as there - * isn't enough space in buffer passed to us by the - * tooltip control */ - infoPtr->pszTooltipText = HeapAlloc(GetProcessHeap(), 0, (len+1)*sizeof(WCHAR)); - if (infoPtr->pszTooltipText) - { - memcpy(infoPtr->pszTooltipText, tbgit.pszText, (len+1)*sizeof(WCHAR)); - lpnmtdi->lpszText = infoPtr->pszTooltipText; - return 0; - } - } - else if (len > 0) - { - memcpy(lpnmtdi->lpszText, tbgit.pszText, (len+1)*sizeof(WCHAR)); - return 0; - } - } - else - { - CHAR szBuffer[INFOTIPSIZE+1]; - NMTBGETINFOTIPA tbgit; - unsigned int len; /* in chars */ - - szBuffer[0] = '\0'; - szBuffer[INFOTIPSIZE] = '\0'; - - tbgit.pszText = szBuffer; - tbgit.cchTextMax = INFOTIPSIZE; - tbgit.iItem = lpnmtdi->hdr.idFrom; - tbgit.lParam = infoPtr->buttons[index].dwData; - - TOOLBAR_SendNotify(&tbgit.hdr, infoPtr, TBN_GETINFOTIPA); - - TRACE("TBN_GETINFOTIPA - got string %s\n", debugstr_a(tbgit.pszText)); - - len = -1 + MultiByteToWideChar(CP_ACP, 0, tbgit.pszText, -1, NULL, 0); - if (len > sizeof(lpnmtdi->szText)/sizeof(lpnmtdi->szText[0])-1) - { - /* need to allocate temporary buffer in infoPtr as there - * isn't enough space in buffer passed to us by the - * tooltip control */ - infoPtr->pszTooltipText = HeapAlloc(GetProcessHeap(), 0, (len+1)*sizeof(WCHAR)); - if (infoPtr->pszTooltipText) - { - MultiByteToWideChar(CP_ACP, 0, tbgit.pszText, len+1, infoPtr->pszTooltipText, (len+1)*sizeof(WCHAR)); - lpnmtdi->lpszText = infoPtr->pszTooltipText; - return 0; - } - } - else if (len > 0) - { - MultiByteToWideChar(CP_ACP, 0, tbgit.pszText, len+1, lpnmtdi->lpszText, (len+1)*sizeof(WCHAR)); - return 0; - } - } - - /* if button has text, but it is not shown then automatically - * use that text as tooltip */ - if ((infoPtr->dwExStyle & TBSTYLE_EX_MIXEDBUTTONS) && - !(infoPtr->buttons[index].fsStyle & BTNS_SHOWTEXT)) - { - LPWSTR pszText = TOOLBAR_GetText(infoPtr, &infoPtr->buttons[index]); - unsigned int len = pszText ? strlenW(pszText) : 0; - - TRACE("using button hidden text %s\n", debugstr_w(pszText)); - - if (len > sizeof(lpnmtdi->szText)/sizeof(lpnmtdi->szText[0])-1) - { - /* need to allocate temporary buffer in infoPtr as there - * isn't enough space in buffer passed to us by the - * tooltip control */ - infoPtr->pszTooltipText = HeapAlloc(GetProcessHeap(), 0, (len+1)*sizeof(WCHAR)); - if (infoPtr->pszTooltipText) - { - memcpy(infoPtr->pszTooltipText, pszText, (len+1)*sizeof(WCHAR)); - lpnmtdi->lpszText = infoPtr->pszTooltipText; - return 0; - } - } - else if (len > 0) - { - memcpy(lpnmtdi->lpszText, pszText, (len+1)*sizeof(WCHAR)); - return 0; - } - } - - TRACE("Sending tooltip notification to %p\n", infoPtr->hwndNotify); - - /* last resort: send notification on to app */ - /* FIXME: find out what is really used here */ - return SendMessageW(infoPtr->hwndNotify, WM_NOTIFY, 0, (LPARAM)lpnmtdi); -} - - -inline static LRESULT -TOOLBAR_Notify (HWND hwnd, WPARAM wParam, LPARAM lParam) -{ - TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd); - LPNMHDR lpnmh = (LPNMHDR)lParam; - - switch (lpnmh->code) - { - case PGN_CALCSIZE: - { - LPNMPGCALCSIZE lppgc = (LPNMPGCALCSIZE)lParam; - - if (lppgc->dwFlag == PGF_CALCWIDTH) { - lppgc->iWidth = infoPtr->rcBound.right - infoPtr->rcBound.left; - TRACE("processed PGN_CALCSIZE, returning horz size = %d\n", - lppgc->iWidth); - } - else { - lppgc->iHeight = infoPtr->rcBound.bottom - infoPtr->rcBound.top; - TRACE("processed PGN_CALCSIZE, returning vert size = %d\n", - lppgc->iHeight); - } - return 0; - } - - case PGN_SCROLL: - { - LPNMPGSCROLL lppgs = (LPNMPGSCROLL)lParam; - - lppgs->iScroll = (lppgs->iDir & (PGF_SCROLLLEFT | PGF_SCROLLRIGHT)) ? - infoPtr->nButtonWidth : infoPtr->nButtonHeight; - TRACE("processed PGN_SCROLL, returning scroll=%d, dir=%d\n", - lppgs->iScroll, lppgs->iDir); - return 0; - } - - case TTN_GETDISPINFOW: - return TOOLBAR_TTGetDispInfo(infoPtr, (LPNMTTDISPINFOW)lParam); - - case TTN_GETDISPINFOA: - FIXME("TTN_GETDISPINFOA - should not be received; please report\n"); - return 0; - - default: - return 0; - } -} - - -static LRESULT -TOOLBAR_NotifyFormat(TOOLBAR_INFO *infoPtr, WPARAM wParam, LPARAM lParam) -{ - LRESULT format; - - TRACE("wParam = 0x%x, lParam = 0x%08lx\n", wParam, lParam); - - if (lParam == NF_QUERY) - return NFR_UNICODE; - - if (lParam == NF_REQUERY) { - format = SendMessageW(infoPtr->hwndNotify, - WM_NOTIFYFORMAT, (WPARAM)infoPtr->hwndSelf, NF_QUERY); - if ((format != NFR_ANSI) && (format != NFR_UNICODE)) { - ERR("wrong response to WM_NOTIFYFORMAT (%ld), assuming ANSI\n", - format); - format = NFR_ANSI; - } - return format; - } - return 0; -} - - -static LRESULT -TOOLBAR_Paint (HWND hwnd, WPARAM wParam) -{ - TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr(hwnd); - HDC hdc; - PAINTSTRUCT ps; - - /* fill ps.rcPaint with a default rect */ - memcpy(&(ps.rcPaint), &(infoPtr->rcBound), sizeof(infoPtr->rcBound)); - - hdc = wParam==0 ? BeginPaint(hwnd, &ps) : (HDC)wParam; - - TRACE("psrect=(%ld,%ld)-(%ld,%ld)\n", - ps.rcPaint.left, ps.rcPaint.top, - ps.rcPaint.right, ps.rcPaint.bottom); - - TOOLBAR_Refresh (hwnd, hdc, &ps); - if (!wParam) EndPaint (hwnd, &ps); - - return 0; -} - - -static LRESULT -TOOLBAR_SetRedraw (HWND hwnd, WPARAM wParam, LPARAM lParam) - /***************************************************** - * - * Function; - * Handles the WM_SETREDRAW message. - * - * Documentation: - * According to testing V4.71 of COMCTL32 returns the - * *previous* status of the redraw flag (either 0 or 1) - * instead of the MSDN documented value of 0 if handled. - * (For laughs see the "consistency" with same function - * in rebar.) - * - *****************************************************/ -{ - TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd); - BOOL oldredraw = infoPtr->bDoRedraw; - - TRACE("set to %s\n", - (wParam) ? "TRUE" : "FALSE"); - infoPtr->bDoRedraw = (BOOL) wParam; - if (wParam) { - InvalidateRect (infoPtr->hwndSelf, 0, TRUE); - } - return (oldredraw) ? 1 : 0; -} - - -static LRESULT -TOOLBAR_Size (HWND hwnd, WPARAM wParam, LPARAM lParam) -{ - TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd); - DWORD dwStyle = infoPtr->dwStyle; - RECT parent_rect; - RECT window_rect; - HWND parent; - INT x, y; - INT cx, cy; - INT flags; - UINT uPosFlags = 0; - - /* Resize deadlock check */ - if (infoPtr->bAutoSize) { - infoPtr->bAutoSize = FALSE; - return 0; - } - - /* FIXME: optimize to only update size if the new size doesn't */ - /* match the current size */ - - flags = (INT) wParam; - - /* FIXME for flags = - * SIZE_MAXIMIZED, SIZE_MAXSHOW, SIZE_MINIMIZED - */ - - TRACE("sizing toolbar!\n"); - - if (flags == SIZE_RESTORED) { - /* width and height don't apply */ - parent = GetParent (hwnd); - GetClientRect(parent, &parent_rect); - x = parent_rect.left; - y = parent_rect.top; - - if (dwStyle & CCS_NORESIZE) { - uPosFlags |= (SWP_NOSIZE | SWP_NOMOVE); - - /* - * this sets the working width of the toolbar, and - * Calc Toolbar will not adjust it, only the height - */ - infoPtr->nWidth = parent_rect.right - parent_rect.left; - cy = infoPtr->nHeight; - cx = infoPtr->nWidth; - TOOLBAR_CalcToolbar (hwnd); - infoPtr->nWidth = cx; - infoPtr->nHeight = cy; - } - else { - infoPtr->nWidth = parent_rect.right - parent_rect.left; - TOOLBAR_CalcToolbar (hwnd); - cy = infoPtr->nHeight; - cx = infoPtr->nWidth; - - if ((dwStyle & CCS_BOTTOM) == CCS_NOMOVEY) { - GetWindowRect(hwnd, &window_rect); - ScreenToClient(parent, (LPPOINT)&window_rect.left); - y = window_rect.top; - } - if ((dwStyle & CCS_BOTTOM) == CCS_BOTTOM) { - GetWindowRect(hwnd, &window_rect); - y = parent_rect.bottom - - ( window_rect.bottom - window_rect.top); - } - } - - if (dwStyle & CCS_NOPARENTALIGN) { - uPosFlags |= SWP_NOMOVE; - cy = infoPtr->nHeight; - cx = infoPtr->nWidth; - } - - if (!(dwStyle & CCS_NODIVIDER)) - cy += GetSystemMetrics(SM_CYEDGE); - - if (dwStyle & WS_BORDER) - { - x = y = 1; - cy += GetSystemMetrics(SM_CYEDGE); - cx += GetSystemMetrics(SM_CXEDGE); - } - - if(infoPtr->dwExStyle & TBSTYLE_EX_HIDECLIPPEDBUTTONS) - { - RECT delta_width, delta_height, client, dummy; - DWORD min_x, max_x, min_y, max_y; - TBUTTON_INFO *btnPtr; - INT i; - - GetClientRect(hwnd, &client); - if(client.right > infoPtr->client_rect.right) - { - min_x = infoPtr->client_rect.right; - max_x = client.right; - } - else - { - max_x = infoPtr->client_rect.right; - min_x = client.right; - } - if(client.bottom > infoPtr->client_rect.bottom) - { - min_y = infoPtr->client_rect.bottom; - max_y = client.bottom; - } - else - { - max_y = infoPtr->client_rect.bottom; - min_y = client.bottom; - } - - SetRect(&delta_width, min_x, 0, max_x, min_y); - SetRect(&delta_height, 0, min_y, max_x, max_y); - - TRACE("delta_width %s delta_height %s\n", wine_dbgstr_rect(&delta_width), wine_dbgstr_rect(&delta_height)); - btnPtr = infoPtr->buttons; - for (i = 0; i < infoPtr->nNumButtons; i++, btnPtr++) - if(IntersectRect(&dummy, &delta_width, &btnPtr->rect) || - IntersectRect(&dummy, &delta_height, &btnPtr->rect)) - InvalidateRect(hwnd, &btnPtr->rect, TRUE); - } - - if((uPosFlags & (SWP_NOSIZE | SWP_NOMOVE)) != (SWP_NOSIZE | SWP_NOMOVE)) - SetWindowPos (hwnd, 0, x, y, cx, cy, uPosFlags | SWP_NOZORDER); - } - GetClientRect(hwnd, &infoPtr->client_rect); - return 0; -} - - -static LRESULT -TOOLBAR_StyleChanged (HWND hwnd, INT nType, LPSTYLESTRUCT lpStyle) -{ - TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd); - - if (nType == GWL_STYLE) - { - if (lpStyle->styleNew & TBSTYLE_LIST) - infoPtr->dwDTFlags = DT_LEFT | DT_VCENTER | DT_SINGLELINE | DT_END_ELLIPSIS; - else - infoPtr->dwDTFlags = DT_CENTER | DT_END_ELLIPSIS; - - infoPtr->bBtnTranspnt = (lpStyle->styleNew & - (TBSTYLE_FLAT | TBSTYLE_LIST)); - TOOLBAR_CheckStyle (hwnd, lpStyle->styleNew); - - TRACE("new style 0x%08lx\n", lpStyle->styleNew); - - infoPtr->dwStyle = lpStyle->styleNew; - - /* only resize if one of the CCS_* styles was changed */ - if ((infoPtr->dwStyle ^ lpStyle->styleNew) & COMMON_STYLES) - { - TOOLBAR_AutoSize (hwnd); - - InvalidateRect(hwnd, NULL, TRUE); - } - } - - return 0; -} - - -static LRESULT -TOOLBAR_SysColorChange (HWND hwnd) -{ - COMCTL32_RefreshSysColors(); - - return 0; -} - - - -static LRESULT WINAPI -ToolbarWindowProc (HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam) -{ - TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr (hwnd); - - TRACE("hwnd=%p msg=%x wparam=%x lparam=%lx\n", - hwnd, uMsg, /* SPY_GetMsgName(uMsg), */ wParam, lParam); - - if (!infoPtr && (uMsg != WM_NCCREATE)) - return DefWindowProcW( hwnd, uMsg, wParam, lParam ); - - switch (uMsg) - { - case TB_ADDBITMAP: - return TOOLBAR_AddBitmap (hwnd, wParam, lParam); - - case TB_ADDBUTTONSA: - return TOOLBAR_AddButtonsA (hwnd, wParam, lParam); - - case TB_ADDBUTTONSW: - return TOOLBAR_AddButtonsW (hwnd, wParam, lParam); - - case TB_ADDSTRINGA: - return TOOLBAR_AddStringA (hwnd, wParam, lParam); - - case TB_ADDSTRINGW: - return TOOLBAR_AddStringW (hwnd, wParam, lParam); - - case TB_AUTOSIZE: - return TOOLBAR_AutoSize (hwnd); - - case TB_BUTTONCOUNT: - return TOOLBAR_ButtonCount (hwnd, wParam, lParam); - - case TB_BUTTONSTRUCTSIZE: - return TOOLBAR_ButtonStructSize (hwnd, wParam, lParam); - - case TB_CHANGEBITMAP: - return TOOLBAR_ChangeBitmap (hwnd, wParam, lParam); - - case TB_CHECKBUTTON: - return TOOLBAR_CheckButton (hwnd, wParam, lParam); - - case TB_COMMANDTOINDEX: - return TOOLBAR_CommandToIndex (hwnd, wParam, lParam); - - case TB_CUSTOMIZE: - return TOOLBAR_Customize (hwnd); - - case TB_DELETEBUTTON: - return TOOLBAR_DeleteButton (hwnd, wParam, lParam); - - case TB_ENABLEBUTTON: - return TOOLBAR_EnableButton (hwnd, wParam, lParam); - - case TB_GETANCHORHIGHLIGHT: - return TOOLBAR_GetAnchorHighlight (hwnd); - - case TB_GETBITMAP: - return TOOLBAR_GetBitmap (hwnd, wParam, lParam); - - case TB_GETBITMAPFLAGS: - return TOOLBAR_GetBitmapFlags (hwnd, wParam, lParam); - - case TB_GETBUTTON: - return TOOLBAR_GetButton (hwnd, wParam, lParam); - - case TB_GETBUTTONINFOA: - return TOOLBAR_GetButtonInfoA (hwnd, wParam, lParam); - - case TB_GETBUTTONINFOW: - return TOOLBAR_GetButtonInfoW (hwnd, wParam, lParam); - - case TB_GETBUTTONSIZE: - return TOOLBAR_GetButtonSize (hwnd); - - case TB_GETBUTTONTEXTA: - return TOOLBAR_GetButtonTextA (hwnd, wParam, lParam); - - case TB_GETBUTTONTEXTW: - return TOOLBAR_GetButtonTextW (hwnd, wParam, lParam); - - case TB_GETDISABLEDIMAGELIST: - return TOOLBAR_GetDisabledImageList (hwnd, wParam, lParam); - - case TB_GETEXTENDEDSTYLE: - return TOOLBAR_GetExtendedStyle (hwnd); - - case TB_GETHOTIMAGELIST: - return TOOLBAR_GetHotImageList (hwnd, wParam, lParam); - - case TB_GETHOTITEM: - return TOOLBAR_GetHotItem (hwnd); - - case TB_GETIMAGELIST: - return TOOLBAR_GetDefImageList (hwnd, wParam, lParam); - - case TB_GETINSERTMARK: - return TOOLBAR_GetInsertMark (hwnd, wParam, lParam); - - case TB_GETINSERTMARKCOLOR: - return TOOLBAR_GetInsertMarkColor (hwnd, wParam, lParam); - - case TB_GETITEMRECT: - return TOOLBAR_GetItemRect (hwnd, wParam, lParam); - - case TB_GETMAXSIZE: - return TOOLBAR_GetMaxSize (hwnd, wParam, lParam); - -/* case TB_GETOBJECT: */ /* 4.71 */ - - case TB_GETPADDING: - return TOOLBAR_GetPadding (hwnd); - - case TB_GETRECT: - return TOOLBAR_GetRect (hwnd, wParam, lParam); - - case TB_GETROWS: - return TOOLBAR_GetRows (hwnd, wParam, lParam); - - case TB_GETSTATE: - return TOOLBAR_GetState (hwnd, wParam, lParam); - - case TB_GETSTRINGA: - return TOOLBAR_GetStringA (hwnd, wParam, lParam); - - case TB_GETSTRINGW: - return TOOLBAR_GetStringW (hwnd, wParam, lParam); - - case TB_GETSTYLE: - return TOOLBAR_GetStyle (hwnd, wParam, lParam); - - case TB_GETTEXTROWS: - return TOOLBAR_GetTextRows (hwnd, wParam, lParam); - - case TB_GETTOOLTIPS: - return TOOLBAR_GetToolTips (hwnd, wParam, lParam); - - case TB_GETUNICODEFORMAT: - return TOOLBAR_GetUnicodeFormat (hwnd, wParam, lParam); - - case TB_HIDEBUTTON: - return TOOLBAR_HideButton (hwnd, wParam, lParam); - - case TB_HITTEST: - return TOOLBAR_HitTest (hwnd, wParam, lParam); - - case TB_INDETERMINATE: - return TOOLBAR_Indeterminate (hwnd, wParam, lParam); - - case TB_INSERTBUTTONA: - return TOOLBAR_InsertButtonA (hwnd, wParam, lParam); - - case TB_INSERTBUTTONW: - return TOOLBAR_InsertButtonW (hwnd, wParam, lParam); - -/* case TB_INSERTMARKHITTEST: */ /* 4.71 */ - - case TB_ISBUTTONCHECKED: - return TOOLBAR_IsButtonChecked (hwnd, wParam, lParam); - - case TB_ISBUTTONENABLED: - return TOOLBAR_IsButtonEnabled (hwnd, wParam, lParam); - - case TB_ISBUTTONHIDDEN: - return TOOLBAR_IsButtonHidden (hwnd, wParam, lParam); - - case TB_ISBUTTONHIGHLIGHTED: - return TOOLBAR_IsButtonHighlighted (hwnd, wParam, lParam); - - case TB_ISBUTTONINDETERMINATE: - return TOOLBAR_IsButtonIndeterminate (hwnd, wParam, lParam); - - case TB_ISBUTTONPRESSED: - return TOOLBAR_IsButtonPressed (hwnd, wParam, lParam); - - case TB_LOADIMAGES: - return TOOLBAR_LoadImages (hwnd, wParam, lParam); - - case TB_MAPACCELERATORA: - case TB_MAPACCELERATORW: - return TOOLBAR_MapAccelerator (hwnd, wParam, lParam); - - case TB_MARKBUTTON: - return TOOLBAR_MarkButton (hwnd, wParam, lParam); - - case TB_MOVEBUTTON: - return TOOLBAR_MoveButton (hwnd, wParam, lParam); - - case TB_PRESSBUTTON: - return TOOLBAR_PressButton (hwnd, wParam, lParam); - - case TB_REPLACEBITMAP: - return TOOLBAR_ReplaceBitmap (hwnd, wParam, lParam); - - case TB_SAVERESTOREA: - return TOOLBAR_SaveRestoreA (hwnd, wParam, (LPTBSAVEPARAMSA)lParam); - - case TB_SAVERESTOREW: - return TOOLBAR_SaveRestoreW (hwnd, wParam, (LPTBSAVEPARAMSW)lParam); - - case TB_SETANCHORHIGHLIGHT: - return TOOLBAR_SetAnchorHighlight (hwnd, wParam); - - case TB_SETBITMAPSIZE: - return TOOLBAR_SetBitmapSize (hwnd, wParam, lParam); - - case TB_SETBUTTONINFOA: - return TOOLBAR_SetButtonInfoA (hwnd, wParam, lParam); - - case TB_SETBUTTONINFOW: - return TOOLBAR_SetButtonInfoW (hwnd, wParam, lParam); - - case TB_SETBUTTONSIZE: - return TOOLBAR_SetButtonSize (hwnd, wParam, lParam); - - case TB_SETBUTTONWIDTH: - return TOOLBAR_SetButtonWidth (hwnd, wParam, lParam); - - case TB_SETCMDID: - return TOOLBAR_SetCmdId (hwnd, wParam, lParam); - - case TB_SETDISABLEDIMAGELIST: - return TOOLBAR_SetDisabledImageList (hwnd, wParam, lParam); - - case TB_SETDRAWTEXTFLAGS: - return TOOLBAR_SetDrawTextFlags (hwnd, wParam, lParam); - - case TB_SETEXTENDEDSTYLE: - return TOOLBAR_SetExtendedStyle (hwnd, wParam, lParam); - - case TB_SETHOTIMAGELIST: - return TOOLBAR_SetHotImageList (hwnd, wParam, lParam); - - case TB_SETHOTITEM: - return TOOLBAR_SetHotItem (hwnd, wParam); - - case TB_SETIMAGELIST: - return TOOLBAR_SetImageList (hwnd, wParam, lParam); - - case TB_SETINDENT: - return TOOLBAR_SetIndent (hwnd, wParam, lParam); - - case TB_SETINSERTMARK: - return TOOLBAR_SetInsertMark (hwnd, wParam, lParam); - - case TB_SETINSERTMARKCOLOR: - return TOOLBAR_SetInsertMarkColor (hwnd, wParam, lParam); - - case TB_SETMAXTEXTROWS: - return TOOLBAR_SetMaxTextRows (hwnd, wParam, lParam); - - case TB_SETPADDING: - return TOOLBAR_SetPadding (hwnd, wParam, lParam); - - case TB_SETPARENT: - return TOOLBAR_SetParent (hwnd, wParam, lParam); - - case TB_SETROWS: - return TOOLBAR_SetRows (hwnd, wParam, lParam); - - case TB_SETSTATE: - return TOOLBAR_SetState (hwnd, wParam, lParam); - - case TB_SETSTYLE: - return TOOLBAR_SetStyle (hwnd, wParam, lParam); - - case TB_SETTOOLTIPS: - return TOOLBAR_SetToolTips (hwnd, wParam, lParam); - - case TB_SETUNICODEFORMAT: - return TOOLBAR_SetUnicodeFormat (hwnd, wParam, lParam); - - case TB_UNKWN45D: - return TOOLBAR_Unkwn45D(hwnd, wParam, lParam); - - case TB_UNKWN45E: - return TOOLBAR_Unkwn45E (hwnd, wParam, lParam); - - case TB_UNKWN460: - return TOOLBAR_Unkwn460(hwnd, wParam, lParam); - - case TB_UNKWN462: - return TOOLBAR_Unkwn462(hwnd, wParam, lParam); - - case TB_UNKWN463: - return TOOLBAR_Unkwn463 (hwnd, wParam, lParam); - - case TB_UNKWN464: - return TOOLBAR_Unkwn464(hwnd, wParam, lParam); - -/* Common Control Messages */ - -/* case TB_GETCOLORSCHEME: */ /* identical to CCM_ */ - case CCM_GETCOLORSCHEME: - return TOOLBAR_GetColorScheme (hwnd, (LPCOLORSCHEME)lParam); - -/* case TB_SETCOLORSCHEME: */ /* identical to CCM_ */ - case CCM_SETCOLORSCHEME: - return TOOLBAR_SetColorScheme (hwnd, (LPCOLORSCHEME)lParam); - - case CCM_GETVERSION: - return TOOLBAR_GetVersion (hwnd); - - case CCM_SETVERSION: - return TOOLBAR_SetVersion (hwnd, (INT)wParam); - - -/* case WM_CHAR: */ - - case WM_CREATE: - return TOOLBAR_Create (hwnd, wParam, lParam); - - case WM_DESTROY: - return TOOLBAR_Destroy (hwnd, wParam, lParam); - - case WM_ERASEBKGND: - return TOOLBAR_EraseBackground (hwnd, wParam, lParam); - - case WM_GETFONT: - return TOOLBAR_GetFont (hwnd, wParam, lParam); - -/* case WM_KEYDOWN: */ -/* case WM_KILLFOCUS: */ - - case WM_LBUTTONDBLCLK: - return TOOLBAR_LButtonDblClk (hwnd, wParam, lParam); - - case WM_LBUTTONDOWN: - return TOOLBAR_LButtonDown (hwnd, wParam, lParam); - - case WM_LBUTTONUP: - return TOOLBAR_LButtonUp (hwnd, wParam, lParam); - - case WM_RBUTTONUP: - return TOOLBAR_RButtonUp (hwnd, wParam, lParam); - - case WM_RBUTTONDBLCLK: - return TOOLBAR_RButtonDblClk (hwnd, wParam, lParam); - - case WM_MOUSEMOVE: - return TOOLBAR_MouseMove (hwnd, wParam, lParam); - - case WM_MOUSELEAVE: - return TOOLBAR_MouseLeave (hwnd, wParam, lParam); - - case WM_CAPTURECHANGED: - return TOOLBAR_CaptureChanged(hwnd); - - case WM_NCACTIVATE: - return TOOLBAR_NCActivate (hwnd, wParam, lParam); - - case WM_NCCALCSIZE: - return TOOLBAR_NCCalcSize (hwnd, wParam, lParam); - - case WM_NCCREATE: - return TOOLBAR_NCCreate (hwnd, wParam, lParam); - - case WM_NCPAINT: - return TOOLBAR_NCPaint (hwnd, wParam, lParam); - - case WM_NOTIFY: - return TOOLBAR_Notify (hwnd, wParam, lParam); - - case WM_NOTIFYFORMAT: - return TOOLBAR_NotifyFormat (infoPtr, wParam, lParam); - - case WM_PAINT: - return TOOLBAR_Paint (hwnd, wParam); - - case WM_SETREDRAW: - return TOOLBAR_SetRedraw (hwnd, wParam, lParam); - - case WM_SIZE: - return TOOLBAR_Size (hwnd, wParam, lParam); - - case WM_STYLECHANGED: - return TOOLBAR_StyleChanged (hwnd, (INT)wParam, (LPSTYLESTRUCT)lParam); - - case WM_SYSCOLORCHANGE: - return TOOLBAR_SysColorChange (hwnd); - -/* case WM_WININICHANGE: */ - - case WM_CHARTOITEM: - case WM_COMMAND: - case WM_DRAWITEM: - case WM_MEASUREITEM: - case WM_VKEYTOITEM: - return SendMessageW (infoPtr->hwndNotify, uMsg, wParam, lParam); - - /* We see this in Outlook Express 5.x and just does DefWindowProc */ - case PGM_FORWARDMOUSE: - return DefWindowProcW (hwnd, uMsg, wParam, lParam); - - default: - if ((uMsg >= WM_USER) && (uMsg < WM_APP)) - ERR("unknown msg %04x wp=%08x lp=%08lx\n", - uMsg, wParam, lParam); - return DefWindowProcW (hwnd, uMsg, wParam, lParam); - } - return 0; -} - - -VOID -TOOLBAR_Register (void) -{ - WNDCLASSW wndClass; - - ZeroMemory (&wndClass, sizeof(WNDCLASSW)); - wndClass.style = CS_GLOBALCLASS | CS_DBLCLKS; - wndClass.lpfnWndProc = ToolbarWindowProc; - wndClass.cbClsExtra = 0; - wndClass.cbWndExtra = sizeof(TOOLBAR_INFO *); - wndClass.hCursor = LoadCursorW (0, (LPWSTR)IDC_ARROW); - wndClass.hbrBackground = (HBRUSH)(COLOR_BTNFACE + 1); - wndClass.lpszClassName = TOOLBARCLASSNAMEW; - - RegisterClassW (&wndClass); -} - - -VOID -TOOLBAR_Unregister (void) -{ - UnregisterClassW (TOOLBARCLASSNAMEW, NULL); -} - -static HIMAGELIST TOOLBAR_InsertImageList(PIMLENTRY **pies, INT *cies, HIMAGELIST himl, INT id) -{ - HIMAGELIST himlold; - PIMLENTRY c = NULL; - - /* Check if the entry already exists */ - c = TOOLBAR_GetImageListEntry(*pies, *cies, id); - - /* If this is a new entry we must create it and insert into the array */ - if (!c) - { - PIMLENTRY *pnies; - - c = (PIMLENTRY) Alloc(sizeof(IMLENTRY)); - c->id = id; - - pnies = Alloc((*cies + 1) * sizeof(PIMLENTRY)); - memcpy(pnies, *pies, ((*cies) * sizeof(PIMLENTRY))); - pnies[*cies] = c; - (*cies)++; - - Free(*pies); - *pies = pnies; - } - - himlold = c->himl; - c->himl = himl; - - return himlold; -} - - -static VOID TOOLBAR_DeleteImageList(PIMLENTRY **pies, INT *cies) -{ - int i; - - for (i = 0; i < *cies; i++) - Free((*pies)[i]); - - Free(*pies); - - *cies = 0; - *pies = NULL; -} - - -static PIMLENTRY TOOLBAR_GetImageListEntry(PIMLENTRY *pies, INT cies, INT id) -{ - PIMLENTRY c = NULL; - - if (pies != NULL) - { - int i; - - for (i = 0; i < cies; i++) - { - if (pies[i]->id == id) - { - c = pies[i]; - break; - } - } - } - - return c; -} - - -static HIMAGELIST TOOLBAR_GetImageList(PIMLENTRY *pies, INT cies, INT id) -{ - HIMAGELIST himlDef = 0; - PIMLENTRY pie = TOOLBAR_GetImageListEntry(pies, cies, id); - - if (pie) - himlDef = pie->himl; - - return himlDef; -} - - -static BOOL TOOLBAR_GetButtonInfo(TOOLBAR_INFO *infoPtr, NMTOOLBARW *nmtb) -{ - if (infoPtr->bUnicode) - return TOOLBAR_SendNotify(&nmtb->hdr, infoPtr, TBN_GETBUTTONINFOW); - else - { - CHAR Buffer[256]; - NMTOOLBARA nmtba; - BOOL bRet = FALSE; - - nmtba.iItem = nmtb->iItem; - nmtba.pszText = Buffer; - nmtba.cchText = 256; - ZeroMemory(nmtba.pszText, nmtba.cchText); - - if (TOOLBAR_SendNotify(&nmtba.hdr, infoPtr, TBN_GETBUTTONINFOA)) - { - int ccht = strlen(nmtba.pszText); - if (ccht) - MultiByteToWideChar(CP_ACP, 0, (LPCSTR)nmtba.pszText, -1, - nmtb->pszText, nmtb->cchText); - - memcpy(&nmtb->tbButton, &nmtba.tbButton, sizeof(TBBUTTON)); - bRet = TRUE; - } - - return bRet; - } -} - - -static BOOL TOOLBAR_IsButtonRemovable(TOOLBAR_INFO *infoPtr, - int iItem, PCUSTOMBUTTON btnInfo) -{ - NMTOOLBARW nmtb; - - /* MSDN states that iItem is the index of the button, rather than the - * command ID as used by every other NMTOOLBAR notification */ - nmtb.iItem = iItem; - memcpy(&nmtb.tbButton, &btnInfo->btn, sizeof(TBBUTTON)); - - return TOOLBAR_SendNotify(&nmtb.hdr, infoPtr, TBN_QUERYDELETE); -} diff --git a/reactos/lib/comctl32/tooltips.c b/reactos/lib/comctl32/tooltips.c deleted file mode 100644 index b31f71917e4..00000000000 --- a/reactos/lib/comctl32/tooltips.c +++ /dev/null @@ -1,2842 +0,0 @@ -/* - * Tool tip control - * - * Copyright 1998, 1999 Eric Kohl - * Copyright 2004 Robert Shearman - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2.1 of the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - * - * This code was audited for completeness against the documented features - * of Comctl32.dll version 6.0 on Sep. 08, 2004, by Robert Shearman. - * - * Unless otherwise noted, we believe this code to be complete, as per - * the specification mentioned above. - * If you discover missing features or bugs please note them below. - * - * TODO: - * - Custom draw support. - * - Animation. - * - Links. - * - Messages: - * o TTM_ADJUSTRECT - * o TTM_GETTITLEA - * o TTM_GETTTILEW - * o TTM_POPUP - * - Styles: - * o TTS_NOANIMATE - * o TTS_NOFADE - * o TTS_CLOSE - * - * Testing: - * - Run tests using Waite Group Windows95 API Bible Volume 2. - * The second cdrom (chapter 3) contains executables activate.exe, - * curtool.exe, deltool.exe, enumtools.exe, getinfo.exe, getiptxt.exe, - * hittest.exe, needtext.exe, newrect.exe, updtext.exe and winfrpt.exe. - * - * Timer logic. - * - * One important point to remember is that tools don't necessarily get - * a WM_MOUSEMOVE once the cursor leaves the tool, an example is when - * a tool sets TTF_IDISHWND (i.e. an entire window is a tool) because - * here WM_MOUSEMOVEs only get sent when the cursor is inside the - * client area. Therefore the only reliable way to know that the - * cursor has left a tool is to keep a timer running and check the - * position every time it expires. This is the role of timer - * ID_TIMERLEAVE. - * - * - * On entering a tool (detected in a relayed WM_MOUSEMOVE) we start - * ID_TIMERSHOW, if this times out and we're still in the tool we show - * the tip. On showing a tip we start both ID_TIMERPOP and - * ID_TIMERLEAVE. On hiding a tooltip we kill ID_TIMERPOP. - * ID_TIMERPOP is restarted on every relayed WM_MOUSEMOVE. If - * ID_TIMERPOP expires the tool is hidden and ID_TIMERPOP is killed. - * ID_TIMERLEAVE remains running - this is important as we need to - * determine when the cursor leaves the tool. - * - * When ID_TIMERLEAVE expires or on a relayed WM_MOUSEMOVE if we're - * still in the tool do nothing (apart from restart ID_TIMERPOP if - * this is a WM_MOUSEMOVE) (ID_TIMERLEAVE remains running). If we've - * left the tool and entered another one then hide the tip and start - * ID_TIMERSHOW with time ReshowTime and kill ID_TIMERLEAVE. If we're - * outside all tools hide the tip and kill ID_TIMERLEAVE. On Relayed - * mouse button messages hide the tip but leave ID_TIMERLEAVE running, - * this again will let us keep track of when the cursor leaves the - * tool. - * - * - * infoPtr->nTool is the tool the mouse was on on the last relayed MM - * or timer expiry or -1 if the mouse was not on a tool. - * - * infoPtr->nCurrentTool is the tool for which the tip is currently - * displaying text for or -1 if the tip is not shown. Actually this - * will only ever be infoPtr-nTool or -1, so it could be changed to a - * BOOL. - * - */ - - - -#include -#include - -#include "windef.h" -#include "winbase.h" -#include "wine/unicode.h" -#include "wingdi.h" -#include "winuser.h" -#include "winnls.h" -#include "commctrl.h" -#include "comctl32.h" -#include "wine/debug.h" - -WINE_DEFAULT_DEBUG_CHANNEL(tooltips); - -static HICON hTooltipIcons[TTI_ERROR+1]; - -typedef struct -{ - UINT uFlags; - HWND hwnd; - BOOL bNotifyUnicode; - UINT uId; - RECT rect; - HINSTANCE hinst; - LPWSTR lpszText; - LPARAM lParam; -} TTTOOL_INFO; - - -typedef struct -{ - WCHAR szTipText[INFOTIPSIZE]; - BOOL bActive; - BOOL bTrackActive; - UINT uNumTools; - COLORREF clrBk; - COLORREF clrText; - HFONT hFont; - HFONT hTitleFont; - INT xTrackPos; - INT yTrackPos; - INT nMaxTipWidth; - INT nTool; /* tool that mouse was on on last relayed mouse move */ - INT nCurrentTool; - INT nTrackTool; - INT nReshowTime; - INT nAutoPopTime; - INT nInitialTime; - RECT rcMargin; - BOOL bToolBelow; - LPWSTR pszTitle; - HICON hTitleIcon; - - TTTOOL_INFO *tools; -} TOOLTIPS_INFO; - -#define ID_TIMERSHOW 1 /* show delay timer */ -#define ID_TIMERPOP 2 /* auto pop timer */ -#define ID_TIMERLEAVE 3 /* tool leave timer */ - - -#define TOOLTIPS_GetInfoPtr(hWindow) ((TOOLTIPS_INFO *)GetWindowLongPtrW (hWindow, 0)) - -/* offsets from window edge to start of text */ -#define NORMAL_TEXT_MARGIN 2 -#define BALLOON_TEXT_MARGIN (NORMAL_TEXT_MARGIN+8) -/* value used for CreateRoundRectRgn that specifies how much - * each corner is curved */ -#define BALLOON_ROUNDEDNESS 20 -#define BALLOON_STEMHEIGHT 13 -#define BALLOON_STEMWIDTH 10 -#define BALLOON_STEMINDENT 20 - -#define BALLOON_ICON_TITLE_SPACING 8 /* horizontal spacing between icon and title */ -#define BALLOON_TITLE_TEXT_SPACING 8 /* vertical spacing between icon/title and main text */ -#define ICON_HEIGHT 16 -#define ICON_WIDTH 16 - -static LRESULT CALLBACK -TOOLTIPS_SubclassProc (HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam, UINT_PTR uId, DWORD_PTR dwRef); - - -inline static UINT_PTR -TOOLTIPS_GetTitleIconIndex(HICON hIcon) -{ - UINT i; - for (i = 0; i <= TTI_ERROR; i++) - if (hTooltipIcons[i] == hIcon) - return i; - return (UINT_PTR)hIcon; -} - -static void -TOOLTIPS_InitSystemSettings (TOOLTIPS_INFO *infoPtr) -{ - NONCLIENTMETRICSW nclm; - - infoPtr->clrBk = GetSysColor (COLOR_INFOBK); - infoPtr->clrText = GetSysColor (COLOR_INFOTEXT); - - DeleteObject (infoPtr->hFont); - nclm.cbSize = sizeof(nclm); - SystemParametersInfoW (SPI_GETNONCLIENTMETRICS, sizeof(nclm), &nclm, 0); - infoPtr->hFont = CreateFontIndirectW (&nclm.lfStatusFont); - - DeleteObject (infoPtr->hTitleFont); - nclm.lfStatusFont.lfWeight = FW_BOLD; - infoPtr->hTitleFont = CreateFontIndirectW (&nclm.lfStatusFont); -} - -static void -TOOLTIPS_Refresh (HWND hwnd, HDC hdc) -{ - TOOLTIPS_INFO *infoPtr = TOOLTIPS_GetInfoPtr(hwnd); - RECT rc; - INT oldBkMode; - HFONT hOldFont; - HBRUSH hBrush; - UINT uFlags = DT_EXTERNALLEADING; - HRGN hRgn = NULL; - DWORD dwStyle = GetWindowLongW(hwnd, GWL_STYLE); - - if (infoPtr->nMaxTipWidth > -1) - uFlags |= DT_WORDBREAK; - if (GetWindowLongA (hwnd, GWL_STYLE) & TTS_NOPREFIX) - uFlags |= DT_NOPREFIX; - GetClientRect (hwnd, &rc); - - hBrush = CreateSolidBrush(infoPtr->clrBk); - - oldBkMode = SetBkMode (hdc, TRANSPARENT); - SetTextColor (hdc, infoPtr->clrText); - - if (dwStyle & TTS_BALLOON) - { - /* create a region to store result into */ - hRgn = CreateRectRgn(0, 0, 0, 0); - - GetWindowRgn(hwnd, hRgn); - - /* fill the background */ - FillRgn(hdc, hRgn, hBrush); - DeleteObject(hBrush); - hBrush = NULL; - } - else - { - /* fill the background */ - FillRect(hdc, &rc, hBrush); - DeleteObject(hBrush); - hBrush = NULL; - } - - if ((dwStyle & TTS_BALLOON) || infoPtr->pszTitle) - { - /* calculate text rectangle */ - rc.left += (BALLOON_TEXT_MARGIN + infoPtr->rcMargin.left); - rc.top += (BALLOON_TEXT_MARGIN + infoPtr->rcMargin.top); - rc.right -= (BALLOON_TEXT_MARGIN + infoPtr->rcMargin.right); - rc.bottom -= (BALLOON_TEXT_MARGIN + infoPtr->rcMargin.bottom); - if(infoPtr->bToolBelow) rc.top += BALLOON_STEMHEIGHT; - - if (infoPtr->pszTitle) - { - RECT rcTitle = {rc.left, rc.top, rc.right, rc.bottom}; - int height; - BOOL icon_present; - - /* draw icon */ - icon_present = infoPtr->hTitleIcon && - DrawIconEx(hdc, rc.left, rc.top, infoPtr->hTitleIcon, - ICON_WIDTH, ICON_HEIGHT, 0, NULL, DI_NORMAL); - if (icon_present) - rcTitle.left += ICON_WIDTH + BALLOON_ICON_TITLE_SPACING; - - rcTitle.bottom = rc.top + ICON_HEIGHT; - - /* draw title text */ - hOldFont = SelectObject (hdc, infoPtr->hTitleFont); - height = DrawTextW(hdc, infoPtr->pszTitle, -1, &rcTitle, DT_BOTTOM | DT_SINGLELINE | DT_NOPREFIX); - SelectObject (hdc, hOldFont); - rc.top += height + BALLOON_TITLE_TEXT_SPACING; - } - } - else - { - /* calculate text rectangle */ - rc.left += (NORMAL_TEXT_MARGIN + infoPtr->rcMargin.left); - rc.top += (NORMAL_TEXT_MARGIN + infoPtr->rcMargin.top); - rc.right -= (NORMAL_TEXT_MARGIN + infoPtr->rcMargin.right); - rc.bottom -= (NORMAL_TEXT_MARGIN + infoPtr->rcMargin.bottom); - } - - /* draw text */ - hOldFont = SelectObject (hdc, infoPtr->hFont); - DrawTextW (hdc, infoPtr->szTipText, -1, &rc, uFlags); - /* be polite and reset the things we changed in the dc */ - SelectObject (hdc, hOldFont); - SetBkMode (hdc, oldBkMode); - - if (dwStyle & TTS_BALLOON) - { - /* frame region because default window proc doesn't do it */ - INT width = GetSystemMetrics(SM_CXDLGFRAME) - GetSystemMetrics(SM_CXEDGE); - INT height = GetSystemMetrics(SM_CYDLGFRAME) - GetSystemMetrics(SM_CYEDGE); - - hBrush = GetSysColorBrush(COLOR_WINDOWFRAME); - FrameRgn(hdc, hRgn, hBrush, width, height); - } - - if (hRgn) - DeleteObject(hRgn); -} - -static void TOOLTIPS_GetDispInfoA(HWND hwnd, TOOLTIPS_INFO *infoPtr, TTTOOL_INFO *toolPtr) -{ - NMTTDISPINFOA ttnmdi; - - /* fill NMHDR struct */ - ZeroMemory (&ttnmdi, sizeof(NMTTDISPINFOA)); - ttnmdi.hdr.hwndFrom = hwnd; - ttnmdi.hdr.idFrom = toolPtr->uId; - ttnmdi.hdr.code = TTN_GETDISPINFOA; - ttnmdi.lpszText = (LPSTR)&ttnmdi.szText; - ttnmdi.uFlags = toolPtr->uFlags; - ttnmdi.lParam = toolPtr->lParam; - - TRACE("hdr.idFrom = %x\n", ttnmdi.hdr.idFrom); - SendMessageW(toolPtr->hwnd, WM_NOTIFY, - (WPARAM)toolPtr->uId, (LPARAM)&ttnmdi); - - if (HIWORD((UINT)ttnmdi.lpszText) == 0) { - LoadStringW(ttnmdi.hinst, (UINT)ttnmdi.lpszText, - infoPtr->szTipText, INFOTIPSIZE); - if (ttnmdi.uFlags & TTF_DI_SETITEM) { - toolPtr->hinst = ttnmdi.hinst; - toolPtr->lpszText = (LPWSTR)ttnmdi.lpszText; - } - } - else if (ttnmdi.lpszText == 0) { - /* no text available */ - infoPtr->szTipText[0] = '\0'; - } - else if (ttnmdi.lpszText != LPSTR_TEXTCALLBACKA) { - INT max_len = (ttnmdi.lpszText == &ttnmdi.szText[0]) ? - sizeof(ttnmdi.szText)/sizeof(ttnmdi.szText[0]) : -1; - MultiByteToWideChar(CP_ACP, 0, ttnmdi.lpszText, max_len, - infoPtr->szTipText, INFOTIPSIZE); - if (ttnmdi.uFlags & TTF_DI_SETITEM) { - INT len = MultiByteToWideChar(CP_ACP, 0, ttnmdi.lpszText, - max_len, NULL, 0); - toolPtr->hinst = 0; - toolPtr->lpszText = Alloc (len * sizeof(WCHAR)); - MultiByteToWideChar(CP_ACP, 0, ttnmdi.lpszText, -1, - toolPtr->lpszText, len); - } - } - else { - ERR("recursive text callback!\n"); - infoPtr->szTipText[0] = '\0'; - } -} - -static void TOOLTIPS_GetDispInfoW(HWND hwnd, TOOLTIPS_INFO *infoPtr, TTTOOL_INFO *toolPtr) -{ - NMTTDISPINFOW ttnmdi; - - /* fill NMHDR struct */ - ZeroMemory (&ttnmdi, sizeof(NMTTDISPINFOW)); - ttnmdi.hdr.hwndFrom = hwnd; - ttnmdi.hdr.idFrom = toolPtr->uId; - ttnmdi.hdr.code = TTN_GETDISPINFOW; - ttnmdi.lpszText = (LPWSTR)&ttnmdi.szText; - ttnmdi.uFlags = toolPtr->uFlags; - ttnmdi.lParam = toolPtr->lParam; - - TRACE("hdr.idFrom = %x\n", ttnmdi.hdr.idFrom); - SendMessageW(toolPtr->hwnd, WM_NOTIFY, - (WPARAM)toolPtr->uId, (LPARAM)&ttnmdi); - - if (HIWORD((UINT)ttnmdi.lpszText) == 0) { - LoadStringW(ttnmdi.hinst, (UINT)ttnmdi.lpszText, - infoPtr->szTipText, INFOTIPSIZE); - if (ttnmdi.uFlags & TTF_DI_SETITEM) { - toolPtr->hinst = ttnmdi.hinst; - toolPtr->lpszText = ttnmdi.lpszText; - } - } - else if (ttnmdi.lpszText == 0) { - /* no text available */ - infoPtr->szTipText[0] = '\0'; - } - else if (ttnmdi.lpszText != LPSTR_TEXTCALLBACKW) { - INT max_len = (ttnmdi.lpszText == &ttnmdi.szText[0]) ? - sizeof(ttnmdi.szText)/sizeof(ttnmdi.szText[0]) : INFOTIPSIZE-1; - strncpyW(infoPtr->szTipText, ttnmdi.lpszText, max_len); - if (ttnmdi.uFlags & TTF_DI_SETITEM) { - INT len = max(strlenW(ttnmdi.lpszText), max_len); - toolPtr->hinst = 0; - toolPtr->lpszText = Alloc ((len+1) * sizeof(WCHAR)); - memcpy(toolPtr->lpszText, ttnmdi.lpszText, (len+1) * sizeof(WCHAR)); - } - } - else { - ERR("recursive text callback!\n"); - infoPtr->szTipText[0] = '\0'; - } -} - -static void -TOOLTIPS_GetTipText (HWND hwnd, TOOLTIPS_INFO *infoPtr, INT nTool) -{ - TTTOOL_INFO *toolPtr = &infoPtr->tools[nTool]; - - if (HIWORD((UINT)toolPtr->lpszText) == 0 && toolPtr->hinst) { - /* load a resource */ - TRACE("load res string %p %x\n", - toolPtr->hinst, (int)toolPtr->lpszText); - LoadStringW (toolPtr->hinst, (UINT)toolPtr->lpszText, - infoPtr->szTipText, INFOTIPSIZE); - } - else if (toolPtr->lpszText) { - if (toolPtr->lpszText == LPSTR_TEXTCALLBACKW) { - if (toolPtr->bNotifyUnicode) - TOOLTIPS_GetDispInfoW(hwnd, infoPtr, toolPtr); - else - TOOLTIPS_GetDispInfoA(hwnd, infoPtr, toolPtr); - } - else { - /* the item is a usual (unicode) text */ - lstrcpynW (infoPtr->szTipText, toolPtr->lpszText, INFOTIPSIZE); - } - } - else { - /* no text available */ - infoPtr->szTipText[0] = L'\0'; - } - - TRACE("%s\n", debugstr_w(infoPtr->szTipText)); -} - - -static void -TOOLTIPS_CalcTipSize (HWND hwnd, TOOLTIPS_INFO *infoPtr, LPSIZE lpSize) -{ - HDC hdc; - HFONT hOldFont; - DWORD style = GetWindowLongW(hwnd, GWL_STYLE); - UINT uFlags = DT_EXTERNALLEADING | DT_CALCRECT; - RECT rc = {0, 0, 0, 0}; - SIZE title = {0, 0}; - - if (infoPtr->nMaxTipWidth > -1) { - rc.right = infoPtr->nMaxTipWidth; - uFlags |= DT_WORDBREAK; - } - if (style & TTS_NOPREFIX) - uFlags |= DT_NOPREFIX; - TRACE("%s\n", debugstr_w(infoPtr->szTipText)); - - hdc = GetDC (hwnd); - if (infoPtr->pszTitle) - { - RECT rcTitle = {0, 0, 0, 0}; - TRACE("title %s\n", debugstr_w(infoPtr->pszTitle)); - if (infoPtr->hTitleIcon) - { - title.cx = ICON_WIDTH; - title.cy = ICON_HEIGHT; - } - if (title.cx != 0) title.cx += BALLOON_ICON_TITLE_SPACING; - hOldFont = SelectObject (hdc, infoPtr->hTitleFont); - DrawTextW(hdc, infoPtr->pszTitle, -1, &rcTitle, DT_SINGLELINE | DT_NOPREFIX | DT_CALCRECT); - SelectObject (hdc, hOldFont); - title.cy = max(title.cy, rcTitle.bottom - rcTitle.top) + BALLOON_TITLE_TEXT_SPACING; - title.cx += (rcTitle.right - rcTitle.left); - } - hOldFont = SelectObject (hdc, infoPtr->hFont); - DrawTextW (hdc, infoPtr->szTipText, -1, &rc, uFlags); - SelectObject (hdc, hOldFont); - ReleaseDC (hwnd, hdc); - - if ((style & TTS_BALLOON) || infoPtr->pszTitle) - { - lpSize->cx = max(rc.right - rc.left, title.cx) + 2*BALLOON_TEXT_MARGIN + - infoPtr->rcMargin.left + infoPtr->rcMargin.right; - lpSize->cy = title.cy + rc.bottom - rc.top + 2*BALLOON_TEXT_MARGIN + - infoPtr->rcMargin.bottom + infoPtr->rcMargin.top + - BALLOON_STEMHEIGHT; - } - else - { - lpSize->cx = rc.right - rc.left + 2*NORMAL_TEXT_MARGIN + - infoPtr->rcMargin.left + infoPtr->rcMargin.right; - lpSize->cy = rc.bottom - rc.top + 2*NORMAL_TEXT_MARGIN + - infoPtr->rcMargin.bottom + infoPtr->rcMargin.top; - } -} - - -static void -TOOLTIPS_Show (HWND hwnd, TOOLTIPS_INFO *infoPtr) -{ - TTTOOL_INFO *toolPtr; - RECT rect, wndrect; - SIZE size; - NMHDR hdr; - int ptfx = 0; - DWORD style = GetWindowLongW(hwnd, GWL_STYLE); - - if (infoPtr->nTool == -1) { - TRACE("invalid tool (-1)!\n"); - return; - } - - infoPtr->nCurrentTool = infoPtr->nTool; - - TRACE("Show tooltip pre %d! (%p)\n", infoPtr->nTool, hwnd); - - TOOLTIPS_GetTipText (hwnd, infoPtr, infoPtr->nCurrentTool); - - if (infoPtr->szTipText[0] == L'\0') { - infoPtr->nCurrentTool = -1; - return; - } - - TRACE("Show tooltip %d!\n", infoPtr->nCurrentTool); - toolPtr = &infoPtr->tools[infoPtr->nCurrentTool]; - - hdr.hwndFrom = hwnd; - hdr.idFrom = toolPtr->uId; - hdr.code = TTN_SHOW; - SendMessageW (toolPtr->hwnd, WM_NOTIFY, - (WPARAM)toolPtr->uId, (LPARAM)&hdr); - - TRACE("%s\n", debugstr_w(infoPtr->szTipText)); - - TOOLTIPS_CalcTipSize (hwnd, infoPtr, &size); - TRACE("size %ld x %ld\n", size.cx, size.cy); - - if (toolPtr->uFlags & TTF_CENTERTIP) { - RECT rc; - - if (toolPtr->uFlags & TTF_IDISHWND) - GetWindowRect ((HWND)toolPtr->uId, &rc); - else { - rc = toolPtr->rect; - MapWindowPoints (toolPtr->hwnd, NULL, (LPPOINT)&rc, 2); - } - rect.left = (rc.left + rc.right - size.cx) / 2; - if (style & TTS_BALLOON) - { - ptfx = rc.left + ((rc.right - rc.left) / 2); - if(rect.top - size.cy >= 0) - { - rect.top -= size.cy; - infoPtr->bToolBelow = FALSE; - } - else - { - infoPtr->bToolBelow = TRUE; - rect.top += 20; - } - rect.left = max(0, rect.left - BALLOON_STEMINDENT); - } - else - { - rect.top = rc.bottom + 2; - infoPtr->bToolBelow = TRUE; - } - } - else { - GetCursorPos ((LPPOINT)&rect); - if (style & TTS_BALLOON) - { - ptfx = rect.left; - if(rect.top - size.cy >= 0) - { - rect.top -= size.cy; - infoPtr->bToolBelow = FALSE; - } - else - { - infoPtr->bToolBelow = TRUE; - rect.top += 20; - } - rect.left = max(0, rect.left - BALLOON_STEMINDENT); - } - else - { - rect.top += 20; - infoPtr->bToolBelow = TRUE; - } - } - - TRACE("pos %ld - %ld\n", rect.left, rect.top); - - rect.right = rect.left + size.cx; - rect.bottom = rect.top + size.cy; - - /* check position */ - wndrect.right = GetSystemMetrics( SM_CXSCREEN ); - if( rect.right > wndrect.right ) { - rect.left -= rect.right - wndrect.right + 2; - rect.right = wndrect.right - 2; - } - wndrect.bottom = GetSystemMetrics( SM_CYSCREEN ); - if( rect.bottom > wndrect.bottom ) { - RECT rc; - - if (toolPtr->uFlags & TTF_IDISHWND) - GetWindowRect ((HWND)toolPtr->uId, &rc); - else { - rc = toolPtr->rect; - MapWindowPoints (toolPtr->hwnd, NULL, (LPPOINT)&rc, 2); - } - rect.bottom = rc.top - 2; - rect.top = rect.bottom - size.cy; - } - - AdjustWindowRectEx (&rect, GetWindowLongA (hwnd, GWL_STYLE), - FALSE, GetWindowLongA (hwnd, GWL_EXSTYLE)); - - if (style & TTS_BALLOON) - { - HRGN hRgn; - HRGN hrStem; - POINT pts[3]; - - ptfx -= rect.left; - - if(infoPtr->bToolBelow) - { - pts[0].x = ptfx; - pts[0].y = 0; - pts[1].x = max(BALLOON_STEMINDENT, ptfx - (BALLOON_STEMWIDTH / 2)); - pts[1].y = BALLOON_STEMHEIGHT; - pts[2].x = pts[1].x + BALLOON_STEMWIDTH; - pts[2].y = pts[1].y; - if(pts[2].x > (rect.right - rect.left) - BALLOON_STEMINDENT) - { - pts[2].x = (rect.right - rect.left) - BALLOON_STEMINDENT; - pts[1].x = pts[2].x - BALLOON_STEMWIDTH; - } - } - else - { - pts[0].x = max(BALLOON_STEMINDENT, ptfx - (BALLOON_STEMWIDTH / 2)); - pts[0].y = (rect.bottom - rect.top) - BALLOON_STEMHEIGHT; - pts[1].x = pts[0].x + BALLOON_STEMWIDTH; - pts[1].y = pts[0].y; - pts[2].x = ptfx; - pts[2].y = (rect.bottom - rect.top); - if(pts[1].x > (rect.right - rect.left) - BALLOON_STEMINDENT) - { - pts[1].x = (rect.right - rect.left) - BALLOON_STEMINDENT; - pts[0].x = pts[1].x - BALLOON_STEMWIDTH; - } - } - - hrStem = CreatePolygonRgn(pts, sizeof(pts) / sizeof(pts[0]), ALTERNATE); - - hRgn = CreateRoundRectRgn(0, - (infoPtr->bToolBelow ? BALLOON_STEMHEIGHT : 0), - rect.right - rect.left, - (infoPtr->bToolBelow ? rect.bottom - rect.top : rect.bottom - rect.top - BALLOON_STEMHEIGHT), - BALLOON_ROUNDEDNESS, BALLOON_ROUNDEDNESS); - - CombineRgn(hRgn, hRgn, hrStem, RGN_OR); - DeleteObject(hrStem); - - SetWindowRgn(hwnd, hRgn, FALSE); - /* we don't free the region handle as the system deletes it when - * it is no longer needed */ - } - - SetWindowPos (hwnd, HWND_TOP, rect.left, rect.top, - rect.right - rect.left, rect.bottom - rect.top, - SWP_SHOWWINDOW | SWP_NOACTIVATE); - - /* repaint the tooltip */ - InvalidateRect(hwnd, NULL, TRUE); - UpdateWindow(hwnd); - - SetTimer (hwnd, ID_TIMERPOP, infoPtr->nAutoPopTime, 0); - TRACE("timer 2 started!\n"); - SetTimer (hwnd, ID_TIMERLEAVE, infoPtr->nReshowTime, 0); - TRACE("timer 3 started!\n"); -} - - -static void -TOOLTIPS_Hide (HWND hwnd, TOOLTIPS_INFO *infoPtr) -{ - TTTOOL_INFO *toolPtr; - NMHDR hdr; - - TRACE("Hide tooltip %d! (%p)\n", infoPtr->nCurrentTool, hwnd); - - if (infoPtr->nCurrentTool == -1) - return; - - toolPtr = &infoPtr->tools[infoPtr->nCurrentTool]; - KillTimer (hwnd, ID_TIMERPOP); - - hdr.hwndFrom = hwnd; - hdr.idFrom = toolPtr->uId; - hdr.code = TTN_POP; - SendMessageW (toolPtr->hwnd, WM_NOTIFY, - (WPARAM)toolPtr->uId, (LPARAM)&hdr); - - infoPtr->nCurrentTool = -1; - - SetWindowPos (hwnd, HWND_TOP, 0, 0, 0, 0, - SWP_NOZORDER | SWP_HIDEWINDOW | SWP_NOACTIVATE); -} - - -static void -TOOLTIPS_TrackShow (HWND hwnd, TOOLTIPS_INFO *infoPtr) -{ - TTTOOL_INFO *toolPtr; - RECT rect; - SIZE size; - NMHDR hdr; - - if (infoPtr->nTrackTool == -1) { - TRACE("invalid tracking tool (-1)!\n"); - return; - } - - TRACE("show tracking tooltip pre %d!\n", infoPtr->nTrackTool); - - TOOLTIPS_GetTipText (hwnd, infoPtr, infoPtr->nTrackTool); - - if (infoPtr->szTipText[0] == L'\0') { - infoPtr->nTrackTool = -1; - return; - } - - TRACE("show tracking tooltip %d!\n", infoPtr->nTrackTool); - toolPtr = &infoPtr->tools[infoPtr->nTrackTool]; - - hdr.hwndFrom = hwnd; - hdr.idFrom = toolPtr->uId; - hdr.code = TTN_SHOW; - SendMessageW (toolPtr->hwnd, WM_NOTIFY, - (WPARAM)toolPtr->uId, (LPARAM)&hdr); - - TRACE("%s\n", debugstr_w(infoPtr->szTipText)); - - TOOLTIPS_CalcTipSize (hwnd, infoPtr, &size); - TRACE("size %ld x %ld\n", size.cx, size.cy); - - if (toolPtr->uFlags & TTF_ABSOLUTE) { - rect.left = infoPtr->xTrackPos; - rect.top = infoPtr->yTrackPos; - - if (toolPtr->uFlags & TTF_CENTERTIP) { - rect.left -= (size.cx / 2); - rect.top -= (size.cy / 2); - } - } - else { - RECT rcTool; - - if (toolPtr->uFlags & TTF_IDISHWND) - GetWindowRect ((HWND)toolPtr->uId, &rcTool); - else { - rcTool = toolPtr->rect; - MapWindowPoints (toolPtr->hwnd, NULL, (LPPOINT)&rcTool, 2); - } - - GetCursorPos ((LPPOINT)&rect); - rect.top += 20; - - if (toolPtr->uFlags & TTF_CENTERTIP) { - rect.left -= (size.cx / 2); - rect.top -= (size.cy / 2); - } - - /* smart placement */ - if ((rect.left + size.cx > rcTool.left) && (rect.left < rcTool.right) && - (rect.top + size.cy > rcTool.top) && (rect.top < rcTool.bottom)) - rect.left = rcTool.right; - } - - TRACE("pos %ld - %ld\n", rect.left, rect.top); - - rect.right = rect.left + size.cx; - rect.bottom = rect.top + size.cy; - - AdjustWindowRectEx (&rect, GetWindowLongA (hwnd, GWL_STYLE), - FALSE, GetWindowLongA (hwnd, GWL_EXSTYLE)); - - if (GetWindowLongW(hwnd, GWL_STYLE) & TTS_BALLOON) - { - HRGN hRgn; - - /* FIXME: need to add pointy bit using CreatePolyRgn & CombinRgn */ - hRgn = CreateRoundRectRgn(0, 0, rect.right - rect.left, rect.bottom - rect.top, BALLOON_ROUNDEDNESS, BALLOON_ROUNDEDNESS); - - SetWindowRgn(hwnd, hRgn, FALSE); - /* we don't free the region handle as the system deletes it when - * it is no longer needed */ - } - - SetWindowPos (hwnd, HWND_TOP, rect.left, rect.top, - rect.right - rect.left, rect.bottom - rect.top, - SWP_SHOWWINDOW | SWP_NOACTIVATE ); - - InvalidateRect(hwnd, NULL, TRUE); - UpdateWindow(hwnd); -} - - -static void -TOOLTIPS_TrackHide (HWND hwnd, TOOLTIPS_INFO *infoPtr) -{ - TTTOOL_INFO *toolPtr; - NMHDR hdr; - - TRACE("hide tracking tooltip %d\n", infoPtr->nTrackTool); - - if (infoPtr->nTrackTool == -1) - return; - - toolPtr = &infoPtr->tools[infoPtr->nTrackTool]; - - hdr.hwndFrom = hwnd; - hdr.idFrom = toolPtr->uId; - hdr.code = TTN_POP; - SendMessageW (toolPtr->hwnd, WM_NOTIFY, - (WPARAM)toolPtr->uId, (LPARAM)&hdr); - - SetWindowPos (hwnd, HWND_TOP, 0, 0, 0, 0, - SWP_NOZORDER | SWP_HIDEWINDOW | SWP_NOACTIVATE); -} - - -static INT -TOOLTIPS_GetToolFromInfoA (TOOLTIPS_INFO *infoPtr, LPTTTOOLINFOA lpToolInfo) -{ - TTTOOL_INFO *toolPtr; - INT nTool; - - for (nTool = 0; nTool < infoPtr->uNumTools; nTool++) { - toolPtr = &infoPtr->tools[nTool]; - - if (!(toolPtr->uFlags & TTF_IDISHWND) && - (lpToolInfo->hwnd == toolPtr->hwnd) && - (lpToolInfo->uId == toolPtr->uId)) - return nTool; - } - - for (nTool = 0; nTool < infoPtr->uNumTools; nTool++) { - toolPtr = &infoPtr->tools[nTool]; - - if ((toolPtr->uFlags & TTF_IDISHWND) && - (lpToolInfo->uId == toolPtr->uId)) - return nTool; - } - - return -1; -} - - -static INT -TOOLTIPS_GetToolFromInfoW (TOOLTIPS_INFO *infoPtr, LPTTTOOLINFOW lpToolInfo) -{ - TTTOOL_INFO *toolPtr; - INT nTool; - - for (nTool = 0; nTool < infoPtr->uNumTools; nTool++) { - toolPtr = &infoPtr->tools[nTool]; - - if (!(toolPtr->uFlags & TTF_IDISHWND) && - (lpToolInfo->hwnd == toolPtr->hwnd) && - (lpToolInfo->uId == toolPtr->uId)) - return nTool; - } - - for (nTool = 0; nTool < infoPtr->uNumTools; nTool++) { - toolPtr = &infoPtr->tools[nTool]; - - if ((toolPtr->uFlags & TTF_IDISHWND) && - (lpToolInfo->uId == toolPtr->uId)) - return nTool; - } - - return -1; -} - - -static INT -TOOLTIPS_GetToolFromPoint (TOOLTIPS_INFO *infoPtr, HWND hwnd, LPPOINT lpPt) -{ - TTTOOL_INFO *toolPtr; - INT nTool; - - for (nTool = 0; nTool < infoPtr->uNumTools; nTool++) { - toolPtr = &infoPtr->tools[nTool]; - - if (!(toolPtr->uFlags & TTF_IDISHWND)) { - if (hwnd != toolPtr->hwnd) - continue; - if (!PtInRect (&toolPtr->rect, *lpPt)) - continue; - return nTool; - } - } - - for (nTool = 0; nTool < infoPtr->uNumTools; nTool++) { - toolPtr = &infoPtr->tools[nTool]; - - if (toolPtr->uFlags & TTF_IDISHWND) { - if ((HWND)toolPtr->uId == hwnd) - return nTool; - } - } - - return -1; -} - - -static BOOL -TOOLTIPS_IsWindowActive (HWND hwnd) -{ - HWND hwndActive = GetActiveWindow (); - if (!hwndActive) - return FALSE; - if (hwndActive == hwnd) - return TRUE; - return IsChild (hwndActive, hwnd); -} - - -static INT -TOOLTIPS_CheckTool (HWND hwnd, BOOL bShowTest) -{ - TOOLTIPS_INFO *infoPtr = TOOLTIPS_GetInfoPtr (hwnd); - POINT pt; - HWND hwndTool; - INT nTool; - - GetCursorPos (&pt); - hwndTool = (HWND)SendMessageW (hwnd, TTM_WINDOWFROMPOINT, 0, (LPARAM)&pt); - if (hwndTool == 0) - return -1; - - ScreenToClient (hwndTool, &pt); - nTool = TOOLTIPS_GetToolFromPoint (infoPtr, hwndTool, &pt); - if (nTool == -1) - return -1; - - if (!(GetWindowLongA (hwnd, GWL_STYLE) & TTS_ALWAYSTIP) && bShowTest) { - if (!TOOLTIPS_IsWindowActive (GetWindow (hwnd, GW_OWNER))) - return -1; - } - - TRACE("tool %d\n", nTool); - - return nTool; -} - - -static LRESULT -TOOLTIPS_Activate (HWND hwnd, WPARAM wParam, LPARAM lParam) -{ - TOOLTIPS_INFO *infoPtr = TOOLTIPS_GetInfoPtr (hwnd); - - infoPtr->bActive = (BOOL)wParam; - - if (infoPtr->bActive) - TRACE("activate!\n"); - - if (!(infoPtr->bActive) && (infoPtr->nCurrentTool != -1)) - TOOLTIPS_Hide (hwnd, infoPtr); - - return 0; -} - - -static LRESULT -TOOLTIPS_AddToolA (HWND hwnd, WPARAM wParam, LPARAM lParam) -{ - TOOLTIPS_INFO *infoPtr = TOOLTIPS_GetInfoPtr (hwnd); - LPTTTOOLINFOA lpToolInfo = (LPTTTOOLINFOA)lParam; - TTTOOL_INFO *toolPtr; - INT nResult; - - if (lpToolInfo == NULL) - return FALSE; - if (lpToolInfo->cbSize < TTTOOLINFOA_V1_SIZE) - return FALSE; - - TRACE("add tool (%p) %p %d%s!\n", - hwnd, lpToolInfo->hwnd, lpToolInfo->uId, - (lpToolInfo->uFlags & TTF_IDISHWND) ? " TTF_IDISHWND" : ""); - - if (infoPtr->uNumTools == 0) { - infoPtr->tools = Alloc (sizeof(TTTOOL_INFO)); - toolPtr = infoPtr->tools; - } - else { - TTTOOL_INFO *oldTools = infoPtr->tools; - infoPtr->tools = - Alloc (sizeof(TTTOOL_INFO) * (infoPtr->uNumTools + 1)); - memcpy (infoPtr->tools, oldTools, - infoPtr->uNumTools * sizeof(TTTOOL_INFO)); - Free (oldTools); - toolPtr = &infoPtr->tools[infoPtr->uNumTools]; - } - - infoPtr->uNumTools++; - - /* copy tool data */ - toolPtr->uFlags = lpToolInfo->uFlags; - toolPtr->hwnd = lpToolInfo->hwnd; - toolPtr->uId = lpToolInfo->uId; - toolPtr->rect = lpToolInfo->rect; - toolPtr->hinst = lpToolInfo->hinst; - - if (HIWORD(lpToolInfo->lpszText) == 0) { - TRACE("add string id %x!\n", (int)lpToolInfo->lpszText); - toolPtr->lpszText = (LPWSTR)lpToolInfo->lpszText; - } - else if (lpToolInfo->lpszText) { - if (lpToolInfo->lpszText == LPSTR_TEXTCALLBACKA) { - TRACE("add CALLBACK!\n"); - toolPtr->lpszText = LPSTR_TEXTCALLBACKW; - } - else { - INT len = MultiByteToWideChar(CP_ACP, 0, lpToolInfo->lpszText, -1, - NULL, 0); - TRACE("add text \"%s\"!\n", lpToolInfo->lpszText); - toolPtr->lpszText = Alloc (len * sizeof(WCHAR)); - MultiByteToWideChar(CP_ACP, 0, lpToolInfo->lpszText, -1, - toolPtr->lpszText, len); - } - } - - if (lpToolInfo->cbSize >= sizeof(TTTOOLINFOA)) - toolPtr->lParam = lpToolInfo->lParam; - - /* install subclassing hook */ - if (toolPtr->uFlags & TTF_SUBCLASS) { - if (toolPtr->uFlags & TTF_IDISHWND) { - SetWindowSubclass((HWND)toolPtr->uId, TOOLTIPS_SubclassProc, 1, - (DWORD_PTR)hwnd); - } - else { - SetWindowSubclass(toolPtr->hwnd, TOOLTIPS_SubclassProc, 1, - (DWORD_PTR)hwnd); - } - TRACE("subclassing installed!\n"); - } - - nResult = (INT) SendMessageW (toolPtr->hwnd, WM_NOTIFYFORMAT, - (WPARAM)hwnd, (LPARAM)NF_QUERY); - if (nResult == NFR_ANSI) { - toolPtr->bNotifyUnicode = FALSE; - TRACE(" -- WM_NOTIFYFORMAT returns: NFR_ANSI\n"); - } else if (nResult == NFR_UNICODE) { - toolPtr->bNotifyUnicode = TRUE; - TRACE(" -- WM_NOTIFYFORMAT returns: NFR_UNICODE\n"); - } else { - TRACE (" -- WM_NOTIFYFORMAT returns: error!\n"); - } - - return TRUE; -} - - -static LRESULT -TOOLTIPS_AddToolW (HWND hwnd, WPARAM wParam, LPARAM lParam) -{ - TOOLTIPS_INFO *infoPtr = TOOLTIPS_GetInfoPtr (hwnd); - LPTTTOOLINFOW lpToolInfo = (LPTTTOOLINFOW)lParam; - TTTOOL_INFO *toolPtr; - INT nResult; - - if (lpToolInfo == NULL) - return FALSE; - if (lpToolInfo->cbSize < TTTOOLINFOW_V1_SIZE) - return FALSE; - - TRACE("add tool (%p) %p %d%s!\n", - hwnd, lpToolInfo->hwnd, lpToolInfo->uId, - (lpToolInfo->uFlags & TTF_IDISHWND) ? " TTF_IDISHWND" : ""); - - if (infoPtr->uNumTools == 0) { - infoPtr->tools = Alloc (sizeof(TTTOOL_INFO)); - toolPtr = infoPtr->tools; - } - else { - TTTOOL_INFO *oldTools = infoPtr->tools; - infoPtr->tools = - Alloc (sizeof(TTTOOL_INFO) * (infoPtr->uNumTools + 1)); - memcpy (infoPtr->tools, oldTools, - infoPtr->uNumTools * sizeof(TTTOOL_INFO)); - Free (oldTools); - toolPtr = &infoPtr->tools[infoPtr->uNumTools]; - } - - infoPtr->uNumTools++; - - /* copy tool data */ - toolPtr->uFlags = lpToolInfo->uFlags; - toolPtr->hwnd = lpToolInfo->hwnd; - toolPtr->uId = lpToolInfo->uId; - toolPtr->rect = lpToolInfo->rect; - toolPtr->hinst = lpToolInfo->hinst; - - if (HIWORD(lpToolInfo->lpszText) == 0) { - TRACE("add string id %x!\n", (int)lpToolInfo->lpszText); - toolPtr->lpszText = (LPWSTR)lpToolInfo->lpszText; - } - else if (lpToolInfo->lpszText) { - if (lpToolInfo->lpszText == LPSTR_TEXTCALLBACKW) { - TRACE("add CALLBACK!\n"); - toolPtr->lpszText = LPSTR_TEXTCALLBACKW; - } - else { - INT len = lstrlenW (lpToolInfo->lpszText); - TRACE("add text %s!\n", - debugstr_w(lpToolInfo->lpszText)); - toolPtr->lpszText = Alloc ((len + 1)*sizeof(WCHAR)); - strcpyW (toolPtr->lpszText, lpToolInfo->lpszText); - } - } - - if (lpToolInfo->cbSize >= sizeof(TTTOOLINFOW)) - toolPtr->lParam = lpToolInfo->lParam; - - /* install subclassing hook */ - if (toolPtr->uFlags & TTF_SUBCLASS) { - if (toolPtr->uFlags & TTF_IDISHWND) { - SetWindowSubclass((HWND)toolPtr->uId, TOOLTIPS_SubclassProc, 1, - (DWORD_PTR)hwnd); - } - else { - SetWindowSubclass(toolPtr->hwnd, TOOLTIPS_SubclassProc, 1, - (DWORD_PTR)hwnd); - } - TRACE("subclassing installed!\n"); - } - - nResult = (INT) SendMessageW (toolPtr->hwnd, WM_NOTIFYFORMAT, - (WPARAM)hwnd, (LPARAM)NF_QUERY); - if (nResult == NFR_ANSI) { - toolPtr->bNotifyUnicode = FALSE; - TRACE(" -- WM_NOTIFYFORMAT returns: NFR_ANSI\n"); - } else if (nResult == NFR_UNICODE) { - toolPtr->bNotifyUnicode = TRUE; - TRACE(" -- WM_NOTIFYFORMAT returns: NFR_UNICODE\n"); - } else { - TRACE (" -- WM_NOTIFYFORMAT returns: error!\n"); - } - - return TRUE; -} - - -static void -TOOLTIPS_DelToolCommon (HWND hwnd, TOOLTIPS_INFO *infoPtr, INT nTool) -{ - TTTOOL_INFO *toolPtr; - - TRACE("tool %d\n", nTool); - - if (nTool == -1) - return; - - /* make sure the tooltip has disappeared before deleting it */ - TOOLTIPS_Hide(hwnd, infoPtr); - - /* delete text string */ - toolPtr = &infoPtr->tools[nTool]; - if (toolPtr->lpszText) { - if ( (toolPtr->lpszText != LPSTR_TEXTCALLBACKW) && - (HIWORD((INT)toolPtr->lpszText) != 0) ) - Free (toolPtr->lpszText); - } - - /* remove subclassing */ - if (toolPtr->uFlags & TTF_SUBCLASS) { - if (toolPtr->uFlags & TTF_IDISHWND) { - RemoveWindowSubclass((HWND)toolPtr->uId, TOOLTIPS_SubclassProc, 1); - } - else { - RemoveWindowSubclass(toolPtr->hwnd, TOOLTIPS_SubclassProc, 1); - } - } - - /* delete tool from tool list */ - if (infoPtr->uNumTools == 1) { - Free (infoPtr->tools); - infoPtr->tools = NULL; - } - else { - TTTOOL_INFO *oldTools = infoPtr->tools; - infoPtr->tools = - Alloc (sizeof(TTTOOL_INFO) * (infoPtr->uNumTools - 1)); - - if (nTool > 0) - memcpy (&infoPtr->tools[0], &oldTools[0], - nTool * sizeof(TTTOOL_INFO)); - - if (nTool < infoPtr->uNumTools - 1) - memcpy (&infoPtr->tools[nTool], &oldTools[nTool + 1], - (infoPtr->uNumTools - nTool - 1) * sizeof(TTTOOL_INFO)); - - Free (oldTools); - } - - /* update any indices affected by delete */ - - /* destroying tool that mouse was on on last relayed mouse move */ - if (infoPtr->nTool == nTool) - /* -1 means no current tool (0 means first tool) */ - infoPtr->nTool = -1; - else if (infoPtr->nTool > nTool) - infoPtr->nTool--; - - if (infoPtr->nTrackTool == nTool) - /* -1 means no current tool (0 means first tool) */ - infoPtr->nTrackTool = -1; - else if (infoPtr->nTrackTool > nTool) - infoPtr->nTrackTool--; - - if (infoPtr->nCurrentTool == nTool) - /* -1 means no current tool (0 means first tool) */ - infoPtr->nCurrentTool = -1; - else if (infoPtr->nCurrentTool > nTool) - infoPtr->nCurrentTool--; - - infoPtr->uNumTools--; -} - -static LRESULT -TOOLTIPS_DelToolA (HWND hwnd, WPARAM wParam, LPARAM lParam) -{ - TOOLTIPS_INFO *infoPtr = TOOLTIPS_GetInfoPtr (hwnd); - LPTTTOOLINFOA lpToolInfo = (LPTTTOOLINFOA)lParam; - INT nTool; - - if (lpToolInfo == NULL) - return 0; - if (lpToolInfo->cbSize < TTTOOLINFOA_V1_SIZE) - return 0; - if (infoPtr->uNumTools == 0) - return 0; - - nTool = TOOLTIPS_GetToolFromInfoA (infoPtr, lpToolInfo); - - TOOLTIPS_DelToolCommon (hwnd, infoPtr, nTool); - - return 0; -} - - -static LRESULT -TOOLTIPS_DelToolW (HWND hwnd, WPARAM wParam, LPARAM lParam) -{ - TOOLTIPS_INFO *infoPtr = TOOLTIPS_GetInfoPtr (hwnd); - LPTTTOOLINFOW lpToolInfo = (LPTTTOOLINFOW)lParam; - INT nTool; - - if (lpToolInfo == NULL) - return 0; - if (lpToolInfo->cbSize < TTTOOLINFOW_V1_SIZE) - return 0; - if (infoPtr->uNumTools == 0) - return 0; - - nTool = TOOLTIPS_GetToolFromInfoW (infoPtr, lpToolInfo); - - TOOLTIPS_DelToolCommon (hwnd, infoPtr, nTool); - - return 0; -} - - -static LRESULT -TOOLTIPS_EnumToolsA (HWND hwnd, WPARAM wParam, LPARAM lParam) -{ - TOOLTIPS_INFO *infoPtr = TOOLTIPS_GetInfoPtr (hwnd); - UINT uIndex = (UINT)wParam; - LPTTTOOLINFOA lpToolInfo = (LPTTTOOLINFOA)lParam; - TTTOOL_INFO *toolPtr; - - if (lpToolInfo == NULL) - return FALSE; - if (lpToolInfo->cbSize < TTTOOLINFOA_V1_SIZE) - return FALSE; - if (uIndex >= infoPtr->uNumTools) - return FALSE; - - TRACE("index=%u\n", uIndex); - - toolPtr = &infoPtr->tools[uIndex]; - - /* copy tool data */ - lpToolInfo->uFlags = toolPtr->uFlags; - lpToolInfo->hwnd = toolPtr->hwnd; - lpToolInfo->uId = toolPtr->uId; - lpToolInfo->rect = toolPtr->rect; - lpToolInfo->hinst = toolPtr->hinst; -/* lpToolInfo->lpszText = toolPtr->lpszText; */ - lpToolInfo->lpszText = NULL; /* FIXME */ - - if (lpToolInfo->cbSize >= sizeof(TTTOOLINFOA)) - lpToolInfo->lParam = toolPtr->lParam; - - return TRUE; -} - - -static LRESULT -TOOLTIPS_EnumToolsW (HWND hwnd, WPARAM wParam, LPARAM lParam) -{ - TOOLTIPS_INFO *infoPtr = TOOLTIPS_GetInfoPtr (hwnd); - UINT uIndex = (UINT)wParam; - LPTTTOOLINFOW lpToolInfo = (LPTTTOOLINFOW)lParam; - TTTOOL_INFO *toolPtr; - - if (lpToolInfo == NULL) - return FALSE; - if (lpToolInfo->cbSize < TTTOOLINFOW_V1_SIZE) - return FALSE; - if (uIndex >= infoPtr->uNumTools) - return FALSE; - - TRACE("index=%u\n", uIndex); - - toolPtr = &infoPtr->tools[uIndex]; - - /* copy tool data */ - lpToolInfo->uFlags = toolPtr->uFlags; - lpToolInfo->hwnd = toolPtr->hwnd; - lpToolInfo->uId = toolPtr->uId; - lpToolInfo->rect = toolPtr->rect; - lpToolInfo->hinst = toolPtr->hinst; -/* lpToolInfo->lpszText = toolPtr->lpszText; */ - lpToolInfo->lpszText = NULL; /* FIXME */ - - if (lpToolInfo->cbSize >= sizeof(TTTOOLINFOW)) - lpToolInfo->lParam = toolPtr->lParam; - - return TRUE; -} - -static LRESULT -TOOLTIPS_GetBubbleSize (HWND hwnd, WPARAM wParam, LPARAM lParam) -{ - TOOLTIPS_INFO *infoPtr = TOOLTIPS_GetInfoPtr (hwnd); - LPTTTOOLINFOW lpToolInfo = (LPTTTOOLINFOW)lParam; - INT nTool; - SIZE size; - - if (lpToolInfo == NULL) - return FALSE; - if (lpToolInfo->cbSize < TTTOOLINFOW_V1_SIZE) - return FALSE; - - nTool = TOOLTIPS_GetToolFromInfoW (infoPtr, lpToolInfo); - if (nTool == -1) return 0; - - TRACE("tool %d\n", nTool); - - TOOLTIPS_CalcTipSize (hwnd, infoPtr, &size); - TRACE("size %ld x %ld\n", size.cx, size.cy); - - return MAKELRESULT(size.cx, size.cy); -} - -static LRESULT -TOOLTIPS_GetCurrentToolA (HWND hwnd, WPARAM wParam, LPARAM lParam) -{ - TOOLTIPS_INFO *infoPtr = TOOLTIPS_GetInfoPtr (hwnd); - LPTTTOOLINFOA lpToolInfo = (LPTTTOOLINFOA)lParam; - TTTOOL_INFO *toolPtr; - - if (lpToolInfo == NULL) - return FALSE; - if (lpToolInfo->cbSize < TTTOOLINFOA_V1_SIZE) - return FALSE; - - if (lpToolInfo) { - if (infoPtr->nCurrentTool > -1) { - toolPtr = &infoPtr->tools[infoPtr->nCurrentTool]; - - /* copy tool data */ - lpToolInfo->uFlags = toolPtr->uFlags; - lpToolInfo->rect = toolPtr->rect; - lpToolInfo->hinst = toolPtr->hinst; -/* lpToolInfo->lpszText = toolPtr->lpszText; */ - lpToolInfo->lpszText = NULL; /* FIXME */ - - if (lpToolInfo->cbSize >= sizeof(TTTOOLINFOA)) - lpToolInfo->lParam = toolPtr->lParam; - - return TRUE; - } - else - return FALSE; - } - else - return (infoPtr->nCurrentTool != -1); - - return FALSE; -} - - -static LRESULT -TOOLTIPS_GetCurrentToolW (HWND hwnd, WPARAM wParam, LPARAM lParam) -{ - TOOLTIPS_INFO *infoPtr = TOOLTIPS_GetInfoPtr (hwnd); - LPTTTOOLINFOW lpToolInfo = (LPTTTOOLINFOW)lParam; - TTTOOL_INFO *toolPtr; - - if (lpToolInfo == NULL) - return FALSE; - if (lpToolInfo->cbSize < TTTOOLINFOW_V1_SIZE) - return FALSE; - - if (lpToolInfo) { - if (infoPtr->nCurrentTool > -1) { - toolPtr = &infoPtr->tools[infoPtr->nCurrentTool]; - - /* copy tool data */ - lpToolInfo->uFlags = toolPtr->uFlags; - lpToolInfo->rect = toolPtr->rect; - lpToolInfo->hinst = toolPtr->hinst; -/* lpToolInfo->lpszText = toolPtr->lpszText; */ - lpToolInfo->lpszText = NULL; /* FIXME */ - - if (lpToolInfo->cbSize >= sizeof(TTTOOLINFOW)) - lpToolInfo->lParam = toolPtr->lParam; - - return TRUE; - } - else - return FALSE; - } - else - return (infoPtr->nCurrentTool != -1); - - return FALSE; -} - - -static LRESULT -TOOLTIPS_GetDelayTime (HWND hwnd, WPARAM wParam, LPARAM lParam) -{ - TOOLTIPS_INFO *infoPtr = TOOLTIPS_GetInfoPtr (hwnd); - - switch (wParam) { - case TTDT_RESHOW: - return infoPtr->nReshowTime; - - case TTDT_AUTOPOP: - return infoPtr->nAutoPopTime; - - case TTDT_INITIAL: - case TTDT_AUTOMATIC: /* Apparently TTDT_AUTOMATIC returns TTDT_INITIAL */ - return infoPtr->nInitialTime; - - default: - WARN("Invalid wParam %x\n", wParam); - break; - } - - return -1; -} - - -static LRESULT -TOOLTIPS_GetMargin (HWND hwnd, WPARAM wParam, LPARAM lParam) -{ - TOOLTIPS_INFO *infoPtr = TOOLTIPS_GetInfoPtr (hwnd); - LPRECT lpRect = (LPRECT)lParam; - - lpRect->left = infoPtr->rcMargin.left; - lpRect->right = infoPtr->rcMargin.right; - lpRect->bottom = infoPtr->rcMargin.bottom; - lpRect->top = infoPtr->rcMargin.top; - - return 0; -} - - -inline static LRESULT -TOOLTIPS_GetMaxTipWidth (HWND hwnd, WPARAM wParam, LPARAM lParam) -{ - TOOLTIPS_INFO *infoPtr = TOOLTIPS_GetInfoPtr (hwnd); - - return infoPtr->nMaxTipWidth; -} - - -static LRESULT -TOOLTIPS_GetTextA (HWND hwnd, WPARAM wParam, LPARAM lParam) -{ - TOOLTIPS_INFO *infoPtr = TOOLTIPS_GetInfoPtr (hwnd); - LPTTTOOLINFOA lpToolInfo = (LPTTTOOLINFOA)lParam; - INT nTool; - - if (lpToolInfo == NULL) - return 0; - if (lpToolInfo->cbSize < TTTOOLINFOA_V1_SIZE) - return 0; - - nTool = TOOLTIPS_GetToolFromInfoA (infoPtr, lpToolInfo); - if (nTool == -1) return 0; - - /* NB this API is broken, there is no way for the app to determine - what size buffer it requires nor a way to specify how long the - one it supplies is. We'll assume it's upto INFOTIPSIZE */ - - WideCharToMultiByte(CP_ACP, 0, infoPtr->tools[nTool].lpszText, -1, - lpToolInfo->lpszText, INFOTIPSIZE, NULL, NULL); - - return 0; -} - - -static LRESULT -TOOLTIPS_GetTextW (HWND hwnd, WPARAM wParam, LPARAM lParam) -{ - TOOLTIPS_INFO *infoPtr = TOOLTIPS_GetInfoPtr (hwnd); - LPTTTOOLINFOW lpToolInfo = (LPTTTOOLINFOW)lParam; - INT nTool; - - if (lpToolInfo == NULL) - return 0; - if (lpToolInfo->cbSize < TTTOOLINFOW_V1_SIZE) - return 0; - - nTool = TOOLTIPS_GetToolFromInfoW (infoPtr, lpToolInfo); - if (nTool == -1) return 0; - - strcpyW (lpToolInfo->lpszText, infoPtr->tools[nTool].lpszText); - - return 0; -} - - -inline static LRESULT -TOOLTIPS_GetTipBkColor (HWND hwnd, WPARAM wParam, LPARAM lParam) -{ - TOOLTIPS_INFO *infoPtr = TOOLTIPS_GetInfoPtr (hwnd); - return infoPtr->clrBk; -} - - -inline static LRESULT -TOOLTIPS_GetTipTextColor (HWND hwnd, WPARAM wParam, LPARAM lParam) -{ - TOOLTIPS_INFO *infoPtr = TOOLTIPS_GetInfoPtr (hwnd); - return infoPtr->clrText; -} - - -inline static LRESULT -TOOLTIPS_GetToolCount (HWND hwnd, WPARAM wParam, LPARAM lParam) -{ - TOOLTIPS_INFO *infoPtr = TOOLTIPS_GetInfoPtr (hwnd); - return infoPtr->uNumTools; -} - - -static LRESULT -TOOLTIPS_GetToolInfoA (HWND hwnd, WPARAM wParam, LPARAM lParam) -{ - TOOLTIPS_INFO *infoPtr = TOOLTIPS_GetInfoPtr (hwnd); - LPTTTOOLINFOA lpToolInfo = (LPTTTOOLINFOA)lParam; - TTTOOL_INFO *toolPtr; - INT nTool; - - if (lpToolInfo == NULL) - return FALSE; - if (lpToolInfo->cbSize < TTTOOLINFOA_V1_SIZE) - return FALSE; - if (infoPtr->uNumTools == 0) - return FALSE; - - nTool = TOOLTIPS_GetToolFromInfoA (infoPtr, lpToolInfo); - if (nTool == -1) - return FALSE; - - TRACE("tool %d\n", nTool); - - toolPtr = &infoPtr->tools[nTool]; - - /* copy tool data */ - lpToolInfo->uFlags = toolPtr->uFlags; - lpToolInfo->rect = toolPtr->rect; - lpToolInfo->hinst = toolPtr->hinst; -/* lpToolInfo->lpszText = toolPtr->lpszText; */ - lpToolInfo->lpszText = NULL; /* FIXME */ - - if (lpToolInfo->cbSize >= sizeof(TTTOOLINFOA)) - lpToolInfo->lParam = toolPtr->lParam; - - return TRUE; -} - - -static LRESULT -TOOLTIPS_GetToolInfoW (HWND hwnd, WPARAM wParam, LPARAM lParam) -{ - TOOLTIPS_INFO *infoPtr = TOOLTIPS_GetInfoPtr (hwnd); - LPTTTOOLINFOW lpToolInfo = (LPTTTOOLINFOW)lParam; - TTTOOL_INFO *toolPtr; - INT nTool; - - if (lpToolInfo == NULL) - return FALSE; - if (lpToolInfo->cbSize < TTTOOLINFOW_V1_SIZE) - return FALSE; - if (infoPtr->uNumTools == 0) - return FALSE; - - nTool = TOOLTIPS_GetToolFromInfoW (infoPtr, lpToolInfo); - if (nTool == -1) - return FALSE; - - TRACE("tool %d\n", nTool); - - toolPtr = &infoPtr->tools[nTool]; - - /* copy tool data */ - lpToolInfo->uFlags = toolPtr->uFlags; - lpToolInfo->rect = toolPtr->rect; - lpToolInfo->hinst = toolPtr->hinst; -/* lpToolInfo->lpszText = toolPtr->lpszText; */ - lpToolInfo->lpszText = NULL; /* FIXME */ - - if (lpToolInfo->cbSize >= sizeof(TTTOOLINFOW)) - lpToolInfo->lParam = toolPtr->lParam; - - return TRUE; -} - - -static LRESULT -TOOLTIPS_HitTestA (HWND hwnd, WPARAM wParam, LPARAM lParam) -{ - TOOLTIPS_INFO *infoPtr = TOOLTIPS_GetInfoPtr (hwnd); - LPTTHITTESTINFOA lptthit = (LPTTHITTESTINFOA)lParam; - TTTOOL_INFO *toolPtr; - INT nTool; - - if (lptthit == 0) - return FALSE; - - nTool = TOOLTIPS_GetToolFromPoint (infoPtr, lptthit->hwnd, &lptthit->pt); - if (nTool == -1) - return FALSE; - - TRACE("tool %d!\n", nTool); - - /* copy tool data */ - if (lptthit->ti.cbSize >= sizeof(TTTOOLINFOA)) { - toolPtr = &infoPtr->tools[nTool]; - - lptthit->ti.uFlags = toolPtr->uFlags; - lptthit->ti.hwnd = toolPtr->hwnd; - lptthit->ti.uId = toolPtr->uId; - lptthit->ti.rect = toolPtr->rect; - lptthit->ti.hinst = toolPtr->hinst; -/* lptthit->ti.lpszText = toolPtr->lpszText; */ - lptthit->ti.lpszText = NULL; /* FIXME */ - lptthit->ti.lParam = toolPtr->lParam; - } - - return TRUE; -} - - -static LRESULT -TOOLTIPS_HitTestW (HWND hwnd, WPARAM wParam, LPARAM lParam) -{ - TOOLTIPS_INFO *infoPtr = TOOLTIPS_GetInfoPtr (hwnd); - LPTTHITTESTINFOW lptthit = (LPTTHITTESTINFOW)lParam; - TTTOOL_INFO *toolPtr; - INT nTool; - - if (lptthit == 0) - return FALSE; - - nTool = TOOLTIPS_GetToolFromPoint (infoPtr, lptthit->hwnd, &lptthit->pt); - if (nTool == -1) - return FALSE; - - TRACE("tool %d!\n", nTool); - - /* copy tool data */ - if (lptthit->ti.cbSize >= sizeof(TTTOOLINFOW)) { - toolPtr = &infoPtr->tools[nTool]; - - lptthit->ti.uFlags = toolPtr->uFlags; - lptthit->ti.hwnd = toolPtr->hwnd; - lptthit->ti.uId = toolPtr->uId; - lptthit->ti.rect = toolPtr->rect; - lptthit->ti.hinst = toolPtr->hinst; -/* lptthit->ti.lpszText = toolPtr->lpszText; */ - lptthit->ti.lpszText = NULL; /* FIXME */ - lptthit->ti.lParam = toolPtr->lParam; - } - - return TRUE; -} - - -static LRESULT -TOOLTIPS_NewToolRectA (HWND hwnd, WPARAM wParam, LPARAM lParam) -{ - TOOLTIPS_INFO *infoPtr = TOOLTIPS_GetInfoPtr (hwnd); - LPTTTOOLINFOA lpti = (LPTTTOOLINFOA)lParam; - INT nTool; - - if (lpti == NULL) - return 0; - if (lpti->cbSize < TTTOOLINFOA_V1_SIZE) - return FALSE; - - nTool = TOOLTIPS_GetToolFromInfoA (infoPtr, lpti); - - TRACE("nTool = %d, rect = %s\n", nTool, wine_dbgstr_rect(&lpti->rect)); - - if (nTool == -1) return 0; - - infoPtr->tools[nTool].rect = lpti->rect; - - return 0; -} - - -static LRESULT -TOOLTIPS_NewToolRectW (HWND hwnd, WPARAM wParam, LPARAM lParam) -{ - TOOLTIPS_INFO *infoPtr = TOOLTIPS_GetInfoPtr (hwnd); - LPTTTOOLINFOW lpti = (LPTTTOOLINFOW)lParam; - INT nTool; - - if (lpti == NULL) - return 0; - if (lpti->cbSize < TTTOOLINFOW_V1_SIZE) - return FALSE; - - nTool = TOOLTIPS_GetToolFromInfoW (infoPtr, lpti); - - TRACE("nTool = %d, rect = %s\n", nTool, wine_dbgstr_rect(&lpti->rect)); - - if (nTool == -1) return 0; - - infoPtr->tools[nTool].rect = lpti->rect; - - return 0; -} - - -inline static LRESULT -TOOLTIPS_Pop (HWND hwnd, WPARAM wParam, LPARAM lParam) -{ - TOOLTIPS_INFO *infoPtr = TOOLTIPS_GetInfoPtr (hwnd); - TOOLTIPS_Hide (hwnd, infoPtr); - - return 0; -} - - -static LRESULT -TOOLTIPS_RelayEvent (HWND hwnd, WPARAM wParam, LPARAM lParam) -{ - TOOLTIPS_INFO *infoPtr = TOOLTIPS_GetInfoPtr (hwnd); - LPMSG lpMsg = (LPMSG)lParam; - POINT pt; - INT nOldTool; - - if (lParam == 0) { - ERR("lpMsg == NULL!\n"); - return 0; - } - - switch (lpMsg->message) { - case WM_LBUTTONDOWN: - case WM_LBUTTONUP: - case WM_MBUTTONDOWN: - case WM_MBUTTONUP: - case WM_RBUTTONDOWN: - case WM_RBUTTONUP: - TOOLTIPS_Hide (hwnd, infoPtr); - break; - - case WM_MOUSEMOVE: - pt.x = LOWORD(lpMsg->lParam); - pt.y = HIWORD(lpMsg->lParam); - nOldTool = infoPtr->nTool; - infoPtr->nTool = TOOLTIPS_GetToolFromPoint(infoPtr, lpMsg->hwnd, - &pt); - TRACE("tool (%p) %d %d %d\n", hwnd, nOldTool, - infoPtr->nTool, infoPtr->nCurrentTool); - TRACE("WM_MOUSEMOVE (%p %ld %ld)\n", hwnd, pt.x, pt.y); - - if (infoPtr->nTool != nOldTool) { - if(infoPtr->nTool == -1) { /* Moved out of all tools */ - TOOLTIPS_Hide(hwnd, infoPtr); - KillTimer(hwnd, ID_TIMERLEAVE); - } else if (nOldTool == -1) { /* Moved from outside */ - if(infoPtr->bActive) { - SetTimer(hwnd, ID_TIMERSHOW, infoPtr->nInitialTime, 0); - TRACE("timer 1 started!\n"); - } - } else { /* Moved from one to another */ - TOOLTIPS_Hide (hwnd, infoPtr); - KillTimer(hwnd, ID_TIMERLEAVE); - if(infoPtr->bActive) { - SetTimer (hwnd, ID_TIMERSHOW, infoPtr->nReshowTime, 0); - TRACE("timer 1 started!\n"); - } - } - } else if(infoPtr->nCurrentTool != -1) { /* restart autopop */ - KillTimer(hwnd, ID_TIMERPOP); - SetTimer(hwnd, ID_TIMERPOP, infoPtr->nAutoPopTime, 0); - TRACE("timer 2 restarted\n"); - } else if(infoPtr->nTool != -1 && infoPtr->bActive) { - /* previous show attempt didn't result in tooltip so try again */ - SetTimer(hwnd, ID_TIMERSHOW, infoPtr->nInitialTime, 0); - TRACE("timer 1 started!\n"); - } - break; - } - - return 0; -} - - -static LRESULT -TOOLTIPS_SetDelayTime (HWND hwnd, WPARAM wParam, LPARAM lParam) -{ - TOOLTIPS_INFO *infoPtr = TOOLTIPS_GetInfoPtr (hwnd); - INT nTime = (INT)LOWORD(lParam); - - switch (wParam) { - case TTDT_AUTOMATIC: - if (nTime <= 0) - nTime = GetDoubleClickTime(); - infoPtr->nReshowTime = nTime / 5; - infoPtr->nAutoPopTime = nTime * 10; - infoPtr->nInitialTime = nTime; - break; - - case TTDT_RESHOW: - if(nTime < 0) - nTime = GetDoubleClickTime() / 5; - infoPtr->nReshowTime = nTime; - break; - - case TTDT_AUTOPOP: - if(nTime < 0) - nTime = GetDoubleClickTime() * 10; - infoPtr->nAutoPopTime = nTime; - break; - - case TTDT_INITIAL: - if(nTime < 0) - nTime = GetDoubleClickTime(); - infoPtr->nInitialTime = nTime; - break; - - default: - WARN("Invalid wParam %x\n", wParam); - break; - } - - return 0; -} - - -static LRESULT -TOOLTIPS_SetMargin (HWND hwnd, WPARAM wParam, LPARAM lParam) -{ - TOOLTIPS_INFO *infoPtr = TOOLTIPS_GetInfoPtr (hwnd); - LPRECT lpRect = (LPRECT)lParam; - - infoPtr->rcMargin.left = lpRect->left; - infoPtr->rcMargin.right = lpRect->right; - infoPtr->rcMargin.bottom = lpRect->bottom; - infoPtr->rcMargin.top = lpRect->top; - - return 0; -} - - -inline static LRESULT -TOOLTIPS_SetMaxTipWidth (HWND hwnd, WPARAM wParam, LPARAM lParam) -{ - TOOLTIPS_INFO *infoPtr = TOOLTIPS_GetInfoPtr (hwnd); - INT nTemp = infoPtr->nMaxTipWidth; - - infoPtr->nMaxTipWidth = (INT)lParam; - - return nTemp; -} - - -inline static LRESULT -TOOLTIPS_SetTipBkColor (HWND hwnd, WPARAM wParam, LPARAM lParam) -{ - TOOLTIPS_INFO *infoPtr = TOOLTIPS_GetInfoPtr (hwnd); - - infoPtr->clrBk = (COLORREF)wParam; - - return 0; -} - - -inline static LRESULT -TOOLTIPS_SetTipTextColor (HWND hwnd, WPARAM wParam, LPARAM lParam) -{ - TOOLTIPS_INFO *infoPtr = TOOLTIPS_GetInfoPtr (hwnd); - - infoPtr->clrText = (COLORREF)wParam; - - return 0; -} - - -static LRESULT -TOOLTIPS_SetTitleA (HWND hwnd, WPARAM wParam, LPARAM lParam) -{ - TOOLTIPS_INFO *infoPtr = TOOLTIPS_GetInfoPtr (hwnd); - LPCSTR pszTitle = (LPCSTR)lParam; - UINT_PTR uTitleIcon = (UINT_PTR)wParam; - UINT size; - - TRACE("hwnd = %p, title = %s, icon = %p\n", hwnd, debugstr_a(pszTitle), - (void*)uTitleIcon); - - Free(infoPtr->pszTitle); - - if (pszTitle) - { - size = sizeof(WCHAR)*MultiByteToWideChar(CP_ACP, 0, pszTitle, -1, NULL, 0); - infoPtr->pszTitle = Alloc(size); - if (!infoPtr->pszTitle) - return FALSE; - MultiByteToWideChar(CP_ACP, 0, pszTitle, -1, infoPtr->pszTitle, size/sizeof(WCHAR)); - } - else - infoPtr->pszTitle = NULL; - - if (uTitleIcon <= TTI_ERROR) - infoPtr->hTitleIcon = hTooltipIcons[uTitleIcon]; - else - infoPtr->hTitleIcon = CopyIcon((HICON)wParam); - - return TRUE; -} - - -static LRESULT -TOOLTIPS_SetTitleW (HWND hwnd, WPARAM wParam, LPARAM lParam) -{ - TOOLTIPS_INFO *infoPtr = TOOLTIPS_GetInfoPtr (hwnd); - LPCWSTR pszTitle = (LPCWSTR)lParam; - UINT_PTR uTitleIcon = (UINT_PTR)wParam; - UINT size; - - TRACE("hwnd = %p, title = %s, icon = %p\n", hwnd, debugstr_w(pszTitle), - (void*)uTitleIcon); - - Free(infoPtr->pszTitle); - - if (pszTitle) - { - size = (strlenW(pszTitle)+1)*sizeof(WCHAR); - infoPtr->pszTitle = Alloc(size); - if (!infoPtr->pszTitle) - return FALSE; - memcpy(infoPtr->pszTitle, pszTitle, size); - } - else - infoPtr->pszTitle = NULL; - - if (uTitleIcon <= TTI_ERROR) - infoPtr->hTitleIcon = hTooltipIcons[uTitleIcon]; - else - infoPtr->hTitleIcon = CopyIcon((HICON)wParam); - - TRACE("icon = %p\n", infoPtr->hTitleIcon); - - return TRUE; -} - - -static LRESULT -TOOLTIPS_SetToolInfoA (HWND hwnd, WPARAM wParam, LPARAM lParam) -{ - TOOLTIPS_INFO *infoPtr = TOOLTIPS_GetInfoPtr (hwnd); - LPTTTOOLINFOA lpToolInfo = (LPTTTOOLINFOA)lParam; - TTTOOL_INFO *toolPtr; - INT nTool; - - if (lpToolInfo == NULL) - return 0; - if (lpToolInfo->cbSize < TTTOOLINFOA_V1_SIZE) - return 0; - - nTool = TOOLTIPS_GetToolFromInfoA (infoPtr, lpToolInfo); - if (nTool == -1) return 0; - - TRACE("tool %d\n", nTool); - - toolPtr = &infoPtr->tools[nTool]; - - /* copy tool data */ - toolPtr->uFlags = lpToolInfo->uFlags; - toolPtr->hwnd = lpToolInfo->hwnd; - toolPtr->uId = lpToolInfo->uId; - toolPtr->rect = lpToolInfo->rect; - toolPtr->hinst = lpToolInfo->hinst; - - if (HIWORD(lpToolInfo->lpszText) == 0) { - TRACE("set string id %x!\n", (INT)lpToolInfo->lpszText); - toolPtr->lpszText = (LPWSTR)lpToolInfo->lpszText; - } - else if (lpToolInfo->lpszText) { - if (lpToolInfo->lpszText == LPSTR_TEXTCALLBACKA) - toolPtr->lpszText = LPSTR_TEXTCALLBACKW; - else { - if ( (toolPtr->lpszText) && - (HIWORD((INT)toolPtr->lpszText) != 0) ) { - Free (toolPtr->lpszText); - toolPtr->lpszText = NULL; - } - if (lpToolInfo->lpszText) { - INT len = MultiByteToWideChar(CP_ACP, 0, lpToolInfo->lpszText, - -1, NULL, 0); - toolPtr->lpszText = Alloc (len * sizeof(WCHAR)); - MultiByteToWideChar(CP_ACP, 0, lpToolInfo->lpszText, -1, - toolPtr->lpszText, len); - } - } - } - - if (lpToolInfo->cbSize >= sizeof(TTTOOLINFOA)) - toolPtr->lParam = lpToolInfo->lParam; - - return 0; -} - - -static LRESULT -TOOLTIPS_SetToolInfoW (HWND hwnd, WPARAM wParam, LPARAM lParam) -{ - TOOLTIPS_INFO *infoPtr = TOOLTIPS_GetInfoPtr (hwnd); - LPTTTOOLINFOW lpToolInfo = (LPTTTOOLINFOW)lParam; - TTTOOL_INFO *toolPtr; - INT nTool; - - if (lpToolInfo == NULL) - return 0; - if (lpToolInfo->cbSize < TTTOOLINFOW_V1_SIZE) - return 0; - - nTool = TOOLTIPS_GetToolFromInfoW (infoPtr, lpToolInfo); - if (nTool == -1) return 0; - - TRACE("tool %d\n", nTool); - - toolPtr = &infoPtr->tools[nTool]; - - /* copy tool data */ - toolPtr->uFlags = lpToolInfo->uFlags; - toolPtr->hwnd = lpToolInfo->hwnd; - toolPtr->uId = lpToolInfo->uId; - toolPtr->rect = lpToolInfo->rect; - toolPtr->hinst = lpToolInfo->hinst; - - if (HIWORD(lpToolInfo->lpszText) == 0) { - TRACE("set string id %x!\n", (INT)lpToolInfo->lpszText); - toolPtr->lpszText = lpToolInfo->lpszText; - } - else { - if (lpToolInfo->lpszText == LPSTR_TEXTCALLBACKW) - toolPtr->lpszText = LPSTR_TEXTCALLBACKW; - else { - if ( (toolPtr->lpszText) && - (HIWORD((INT)toolPtr->lpszText) != 0) ) { - Free (toolPtr->lpszText); - toolPtr->lpszText = NULL; - } - if (lpToolInfo->lpszText) { - INT len = lstrlenW (lpToolInfo->lpszText); - toolPtr->lpszText = Alloc ((len+1)*sizeof(WCHAR)); - strcpyW (toolPtr->lpszText, lpToolInfo->lpszText); - } - } - } - - if (lpToolInfo->cbSize >= sizeof(TTTOOLINFOW)) - toolPtr->lParam = lpToolInfo->lParam; - - if (infoPtr->nCurrentTool == nTool) - { - TOOLTIPS_GetTipText (hwnd, infoPtr, infoPtr->nCurrentTool); - - if (infoPtr->szTipText[0] == 0) - TOOLTIPS_Hide(hwnd, infoPtr); - else - TOOLTIPS_Show (hwnd, infoPtr); - } - - return 0; -} - - -static LRESULT -TOOLTIPS_TrackActivate (HWND hwnd, WPARAM wParam, LPARAM lParam) -{ - TOOLTIPS_INFO *infoPtr = TOOLTIPS_GetInfoPtr (hwnd); - - if ((BOOL)wParam) { - LPTTTOOLINFOA lpToolInfo = (LPTTTOOLINFOA)lParam; - - if (lpToolInfo == NULL) - return 0; - if (lpToolInfo->cbSize < TTTOOLINFOA_V1_SIZE) - return FALSE; - - /* activate */ - infoPtr->nTrackTool = TOOLTIPS_GetToolFromInfoA (infoPtr, lpToolInfo); - if (infoPtr->nTrackTool != -1) { - TRACE("activated!\n"); - infoPtr->bTrackActive = TRUE; - TOOLTIPS_TrackShow (hwnd, infoPtr); - } - } - else { - /* deactivate */ - TOOLTIPS_TrackHide (hwnd, infoPtr); - - infoPtr->bTrackActive = FALSE; - infoPtr->nTrackTool = -1; - - TRACE("deactivated!\n"); - } - - return 0; -} - - -static LRESULT -TOOLTIPS_TrackPosition (HWND hwnd, WPARAM wParam, LPARAM lParam) -{ - TOOLTIPS_INFO *infoPtr = TOOLTIPS_GetInfoPtr (hwnd); - - infoPtr->xTrackPos = (INT)LOWORD(lParam); - infoPtr->yTrackPos = (INT)HIWORD(lParam); - - if (infoPtr->bTrackActive) { - TRACE("[%d %d]\n", - infoPtr->xTrackPos, infoPtr->yTrackPos); - - TOOLTIPS_TrackShow (hwnd, infoPtr); - } - - return 0; -} - - -static LRESULT -TOOLTIPS_Update (HWND hwnd, WPARAM wParam, LPARAM lParam) -{ - TOOLTIPS_INFO *infoPtr = TOOLTIPS_GetInfoPtr (hwnd); - - if (infoPtr->nCurrentTool != -1) - UpdateWindow (hwnd); - - return 0; -} - - -static LRESULT -TOOLTIPS_UpdateTipTextA (HWND hwnd, WPARAM wParam, LPARAM lParam) -{ - TOOLTIPS_INFO *infoPtr = TOOLTIPS_GetInfoPtr (hwnd); - LPTTTOOLINFOA lpToolInfo = (LPTTTOOLINFOA)lParam; - TTTOOL_INFO *toolPtr; - INT nTool; - - if (lpToolInfo == NULL) - return 0; - if (lpToolInfo->cbSize < TTTOOLINFOA_V1_SIZE) - return FALSE; - - nTool = TOOLTIPS_GetToolFromInfoA (infoPtr, lpToolInfo); - if (nTool == -1) return 0; - - TRACE("tool %d\n", nTool); - - toolPtr = &infoPtr->tools[nTool]; - - /* copy tool text */ - toolPtr->hinst = lpToolInfo->hinst; - - if (HIWORD(lpToolInfo->lpszText) == 0){ - toolPtr->lpszText = (LPWSTR)lpToolInfo->lpszText; - } - else if (lpToolInfo->lpszText) { - if (lpToolInfo->lpszText == LPSTR_TEXTCALLBACKA) - toolPtr->lpszText = LPSTR_TEXTCALLBACKW; - else { - if ( (toolPtr->lpszText) && - (HIWORD((INT)toolPtr->lpszText) != 0) ) { - Free (toolPtr->lpszText); - toolPtr->lpszText = NULL; - } - if (lpToolInfo->lpszText) { - INT len = MultiByteToWideChar(CP_ACP, 0, lpToolInfo->lpszText, - -1, NULL, 0); - toolPtr->lpszText = Alloc (len * sizeof(WCHAR)); - MultiByteToWideChar(CP_ACP, 0, lpToolInfo->lpszText, -1, - toolPtr->lpszText, len); - } - } - } - - if(infoPtr->nCurrentTool == -1) return 0; - /* force repaint */ - if (infoPtr->bActive) - TOOLTIPS_Show (hwnd, infoPtr); - else if (infoPtr->bTrackActive) - TOOLTIPS_TrackShow (hwnd, infoPtr); - - return 0; -} - - -static LRESULT -TOOLTIPS_UpdateTipTextW (HWND hwnd, WPARAM wParam, LPARAM lParam) -{ - TOOLTIPS_INFO *infoPtr = TOOLTIPS_GetInfoPtr (hwnd); - LPTTTOOLINFOW lpToolInfo = (LPTTTOOLINFOW)lParam; - TTTOOL_INFO *toolPtr; - INT nTool; - - if (lpToolInfo == NULL) - return 0; - if (lpToolInfo->cbSize < TTTOOLINFOW_V1_SIZE) - return FALSE; - - nTool = TOOLTIPS_GetToolFromInfoW (infoPtr, lpToolInfo); - if (nTool == -1) - return 0; - - TRACE("tool %d\n", nTool); - - toolPtr = &infoPtr->tools[nTool]; - - /* copy tool text */ - toolPtr->hinst = lpToolInfo->hinst; - - if (HIWORD(lpToolInfo->lpszText) == 0){ - toolPtr->lpszText = lpToolInfo->lpszText; - } - else if (lpToolInfo->lpszText) { - if (lpToolInfo->lpszText == LPSTR_TEXTCALLBACKW) - toolPtr->lpszText = LPSTR_TEXTCALLBACKW; - else { - if ( (toolPtr->lpszText) && - (HIWORD((INT)toolPtr->lpszText) != 0) ) { - Free (toolPtr->lpszText); - toolPtr->lpszText = NULL; - } - if (lpToolInfo->lpszText) { - INT len = lstrlenW (lpToolInfo->lpszText); - toolPtr->lpszText = Alloc ((len+1)*sizeof(WCHAR)); - strcpyW (toolPtr->lpszText, lpToolInfo->lpszText); - } - } - } - - if(infoPtr->nCurrentTool == -1) return 0; - /* force repaint */ - if (infoPtr->bActive) - TOOLTIPS_Show (hwnd, infoPtr); - else if (infoPtr->bTrackActive) - TOOLTIPS_TrackShow (hwnd, infoPtr); - - return 0; -} - - -static LRESULT -TOOLTIPS_WindowFromPoint (HWND hwnd, WPARAM wParam, LPARAM lParam) -{ - return (LRESULT)WindowFromPoint (*((LPPOINT)lParam)); -} - - - -static LRESULT -TOOLTIPS_Create (HWND hwnd, const CREATESTRUCTW *lpcs) -{ - TOOLTIPS_INFO *infoPtr; - - /* allocate memory for info structure */ - infoPtr = (TOOLTIPS_INFO *)Alloc (sizeof(TOOLTIPS_INFO)); - SetWindowLongPtrW (hwnd, 0, (DWORD_PTR)infoPtr); - - /* initialize info structure */ - infoPtr->bActive = TRUE; - infoPtr->bTrackActive = FALSE; - - infoPtr->nMaxTipWidth = -1; - infoPtr->nTool = -1; - infoPtr->nCurrentTool = -1; - infoPtr->nTrackTool = -1; - - /* initialize colours and fonts */ - TOOLTIPS_InitSystemSettings(infoPtr); - - TOOLTIPS_SetDelayTime(hwnd, TTDT_AUTOMATIC, 0L); - - SetWindowPos (hwnd, HWND_TOP, 0, 0, 0, 0, SWP_NOZORDER | SWP_HIDEWINDOW | SWP_NOACTIVATE); - - return 0; -} - - -static LRESULT -TOOLTIPS_Destroy (HWND hwnd, WPARAM wParam, LPARAM lParam) -{ - TOOLTIPS_INFO *infoPtr = TOOLTIPS_GetInfoPtr (hwnd); - TTTOOL_INFO *toolPtr; - UINT i; - - /* free tools */ - if (infoPtr->tools) { - for (i = 0; i < infoPtr->uNumTools; i++) { - toolPtr = &infoPtr->tools[i]; - if (toolPtr->lpszText) { - if ( (toolPtr->lpszText != LPSTR_TEXTCALLBACKW) && - (HIWORD((INT)toolPtr->lpszText) != 0) ) - { - Free (toolPtr->lpszText); - toolPtr->lpszText = NULL; - } - } - - /* remove subclassing */ - if (toolPtr->uFlags & TTF_SUBCLASS) { - if (toolPtr->uFlags & TTF_IDISHWND) { - RemoveWindowSubclass((HWND)toolPtr->uId, TOOLTIPS_SubclassProc, 1); - } - else { - RemoveWindowSubclass(toolPtr->hwnd, TOOLTIPS_SubclassProc, 1); - } - } - } - Free (infoPtr->tools); - } - - /* free title string */ - Free (infoPtr->pszTitle); - /* free title icon if not a standard one */ - if (TOOLTIPS_GetTitleIconIndex(infoPtr->hTitleIcon) > TTI_ERROR) - DeleteObject(infoPtr->hTitleIcon); - - /* delete fonts */ - DeleteObject (infoPtr->hFont); - DeleteObject (infoPtr->hTitleFont); - - /* free tool tips info data */ - Free (infoPtr); - SetWindowLongPtrW(hwnd, 0, 0); - return 0; -} - - -static LRESULT -TOOLTIPS_GetFont (HWND hwnd, WPARAM wParam, LPARAM lParam) -{ - TOOLTIPS_INFO *infoPtr = TOOLTIPS_GetInfoPtr (hwnd); - - return (LRESULT)infoPtr->hFont; -} - - -static LRESULT -TOOLTIPS_MouseMessage (HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam) -{ - TOOLTIPS_INFO *infoPtr = TOOLTIPS_GetInfoPtr (hwnd); - - TOOLTIPS_Hide (hwnd, infoPtr); - - return 0; -} - - -static LRESULT -TOOLTIPS_NCCreate (HWND hwnd, WPARAM wParam, LPARAM lParam) -{ - DWORD dwStyle = GetWindowLongA (hwnd, GWL_STYLE); - DWORD dwExStyle = GetWindowLongA (hwnd, GWL_EXSTYLE); - - dwStyle &= 0x0000FFFF; - dwStyle |= (WS_POPUP | WS_BORDER | WS_CLIPSIBLINGS); - - /* WS_BORDER only draws a border round the window rect, not the - * window region, therefore it is useless to us in balloon mode */ - if (dwStyle & TTS_BALLOON) dwStyle &= ~WS_BORDER; - - SetWindowLongA (hwnd, GWL_STYLE, dwStyle); - - dwExStyle |= WS_EX_TOOLWINDOW; - SetWindowLongA (hwnd, GWL_EXSTYLE, dwExStyle); - - return TRUE; -} - - -static LRESULT -TOOLTIPS_NCHitTest (HWND hwnd, WPARAM wParam, LPARAM lParam) -{ - TOOLTIPS_INFO *infoPtr = TOOLTIPS_GetInfoPtr (hwnd); - INT nTool = (infoPtr->bTrackActive) ? infoPtr->nTrackTool : infoPtr->nTool; - - TRACE(" nTool=%d\n", nTool); - - if ((nTool > -1) && (nTool < infoPtr->uNumTools)) { - if (infoPtr->tools[nTool].uFlags & TTF_TRANSPARENT) { - TRACE("-- in transparent mode!\n"); - return HTTRANSPARENT; - } - } - - return DefWindowProcW (hwnd, WM_NCHITTEST, wParam, lParam); -} - - -static LRESULT -TOOLTIPS_NotifyFormat (HWND hwnd, WPARAM wParam, LPARAM lParam) -{ - FIXME ("hwnd=%p wParam=%x lParam=%lx\n", hwnd, wParam, lParam); - - return 0; -} - - -static LRESULT -TOOLTIPS_Paint (HWND hwnd, WPARAM wParam, LPARAM lParam) -{ - HDC hdc; - PAINTSTRUCT ps; - - hdc = (wParam == 0) ? BeginPaint (hwnd, &ps) : (HDC)wParam; - TOOLTIPS_Refresh (hwnd, hdc); - if (!wParam) - EndPaint (hwnd, &ps); - return 0; -} - - -static LRESULT -TOOLTIPS_SetFont (HWND hwnd, WPARAM wParam, LPARAM lParam) -{ - TOOLTIPS_INFO *infoPtr = TOOLTIPS_GetInfoPtr (hwnd); - LOGFONTW lf; - - if(!GetObjectW((HFONT)wParam, sizeof(lf), &lf)) - return 0; - - DeleteObject (infoPtr->hFont); - infoPtr->hFont = CreateFontIndirectW(&lf); - - DeleteObject (infoPtr->hTitleFont); - lf.lfWeight = FW_BOLD; - infoPtr->hTitleFont = CreateFontIndirectW(&lf); - - if ((LOWORD(lParam)) & (infoPtr->nCurrentTool != -1)) { - FIXME("full redraw needed!\n"); - } - - return 0; -} - -/****************************************************************** - * TOOLTIPS_GetTextLength - * - * This function is called when the tooltip receive a - * WM_GETTEXTLENGTH message. - * wParam : not used - * lParam : not used - * - * returns the length, in characters, of the tip text - */ -static LRESULT -TOOLTIPS_GetTextLength(HWND hwnd, WPARAM wParam, LPARAM lParam) -{ - TOOLTIPS_INFO *infoPtr = TOOLTIPS_GetInfoPtr (hwnd); - return strlenW(infoPtr->szTipText); -} - -/****************************************************************** - * TOOLTIPS_OnWMGetText - * - * This function is called when the tooltip receive a - * WM_GETTEXT message. - * wParam : specifies the maximum number of characters to be copied - * lParam : is the pointer to the buffer that will receive - * the tip text - * - * returns the number of characters copied - */ -static LRESULT -TOOLTIPS_OnWMGetText (HWND hwnd, WPARAM wParam, LPARAM lParam) -{ - TOOLTIPS_INFO *infoPtr = TOOLTIPS_GetInfoPtr (hwnd); - LRESULT res; - LPWSTR pszText = (LPWSTR)lParam; - - if(!infoPtr->szTipText || !wParam) - return 0; - - res = min(strlenW(infoPtr->szTipText)+1, wParam); - memcpy(pszText, infoPtr->szTipText, res*sizeof(WCHAR)); - pszText[res-1] = '\0'; - return res-1; -} - -static LRESULT -TOOLTIPS_Timer (HWND hwnd, WPARAM wParam, LPARAM lParam) -{ - TOOLTIPS_INFO *infoPtr = TOOLTIPS_GetInfoPtr (hwnd); - INT nOldTool; - - TRACE("timer %d (%p) expired!\n", wParam, hwnd); - - switch (wParam) { - case ID_TIMERSHOW: - KillTimer (hwnd, ID_TIMERSHOW); - nOldTool = infoPtr->nTool; - if ((infoPtr->nTool = TOOLTIPS_CheckTool (hwnd, TRUE)) == nOldTool) - TOOLTIPS_Show (hwnd, infoPtr); - break; - - case ID_TIMERPOP: - TOOLTIPS_Hide (hwnd, infoPtr); - break; - - case ID_TIMERLEAVE: - nOldTool = infoPtr->nTool; - infoPtr->nTool = TOOLTIPS_CheckTool (hwnd, FALSE); - TRACE("tool (%p) %d %d %d\n", hwnd, nOldTool, - infoPtr->nTool, infoPtr->nCurrentTool); - if (infoPtr->nTool != nOldTool) { - if(infoPtr->nTool == -1) { /* Moved out of all tools */ - TOOLTIPS_Hide(hwnd, infoPtr); - KillTimer(hwnd, ID_TIMERLEAVE); - } else if (nOldTool == -1) { /* Moved from outside */ - ERR("How did this happen?\n"); - } else { /* Moved from one to another */ - TOOLTIPS_Hide (hwnd, infoPtr); - KillTimer(hwnd, ID_TIMERLEAVE); - if(infoPtr->bActive) { - SetTimer (hwnd, ID_TIMERSHOW, infoPtr->nReshowTime, 0); - TRACE("timer 1 started!\n"); - } - } - } - break; - - default: - ERR("Unknown timer id %d\n", wParam); - break; - } - return 0; -} - - -static LRESULT -TOOLTIPS_WinIniChange (HWND hwnd, WPARAM wParam, LPARAM lParam) -{ - TOOLTIPS_INFO *infoPtr = TOOLTIPS_GetInfoPtr (hwnd); - - TOOLTIPS_InitSystemSettings (infoPtr); - - return 0; -} - - -static LRESULT CALLBACK -TOOLTIPS_SubclassProc (HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam, UINT_PTR uID, DWORD_PTR dwRef) -{ - MSG msg; - - switch(uMsg) { - case WM_MOUSEMOVE: - case WM_LBUTTONDOWN: - case WM_LBUTTONUP: - case WM_MBUTTONDOWN: - case WM_MBUTTONUP: - case WM_RBUTTONDOWN: - case WM_RBUTTONUP: - msg.hwnd = hwnd; - msg.message = uMsg; - msg.wParam = wParam; - msg.lParam = lParam; - TOOLTIPS_RelayEvent((HWND)dwRef, 0, (LPARAM)&msg); - break; - - default: - break; - } - return DefSubclassProc(hwnd, uMsg, wParam, lParam); -} - - -static LRESULT CALLBACK -TOOLTIPS_WindowProc (HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam) -{ - TRACE("hwnd=%p msg=%x wparam=%x lParam=%lx\n", hwnd, uMsg, wParam, lParam); - if (!TOOLTIPS_GetInfoPtr(hwnd) && (uMsg != WM_CREATE) && (uMsg != WM_NCCREATE)) - return DefWindowProcW (hwnd, uMsg, wParam, lParam); - switch (uMsg) - { - case TTM_ACTIVATE: - return TOOLTIPS_Activate (hwnd, wParam, lParam); - - case TTM_ADDTOOLA: - return TOOLTIPS_AddToolA (hwnd, wParam, lParam); - - case TTM_ADDTOOLW: - return TOOLTIPS_AddToolW (hwnd, wParam, lParam); - - case TTM_DELTOOLA: - return TOOLTIPS_DelToolA (hwnd, wParam, lParam); - - case TTM_DELTOOLW: - return TOOLTIPS_DelToolW (hwnd, wParam, lParam); - - case TTM_ENUMTOOLSA: - return TOOLTIPS_EnumToolsA (hwnd, wParam, lParam); - - case TTM_ENUMTOOLSW: - return TOOLTIPS_EnumToolsW (hwnd, wParam, lParam); - - case TTM_GETBUBBLESIZE: - return TOOLTIPS_GetBubbleSize (hwnd, wParam, lParam); - - case TTM_GETCURRENTTOOLA: - return TOOLTIPS_GetCurrentToolA (hwnd, wParam, lParam); - - case TTM_GETCURRENTTOOLW: - return TOOLTIPS_GetCurrentToolW (hwnd, wParam, lParam); - - case TTM_GETDELAYTIME: - return TOOLTIPS_GetDelayTime (hwnd, wParam, lParam); - - case TTM_GETMARGIN: - return TOOLTIPS_GetMargin (hwnd, wParam, lParam); - - case TTM_GETMAXTIPWIDTH: - return TOOLTIPS_GetMaxTipWidth (hwnd, wParam, lParam); - - case TTM_GETTEXTA: - return TOOLTIPS_GetTextA (hwnd, wParam, lParam); - - case TTM_GETTEXTW: - return TOOLTIPS_GetTextW (hwnd, wParam, lParam); - - case TTM_GETTIPBKCOLOR: - return TOOLTIPS_GetTipBkColor (hwnd, wParam, lParam); - - case TTM_GETTIPTEXTCOLOR: - return TOOLTIPS_GetTipTextColor (hwnd, wParam, lParam); - - case TTM_GETTOOLCOUNT: - return TOOLTIPS_GetToolCount (hwnd, wParam, lParam); - - case TTM_GETTOOLINFOA: - return TOOLTIPS_GetToolInfoA (hwnd, wParam, lParam); - - case TTM_GETTOOLINFOW: - return TOOLTIPS_GetToolInfoW (hwnd, wParam, lParam); - - case TTM_HITTESTA: - return TOOLTIPS_HitTestA (hwnd, wParam, lParam); - - case TTM_HITTESTW: - return TOOLTIPS_HitTestW (hwnd, wParam, lParam); - - case TTM_NEWTOOLRECTA: - return TOOLTIPS_NewToolRectA (hwnd, wParam, lParam); - - case TTM_NEWTOOLRECTW: - return TOOLTIPS_NewToolRectW (hwnd, wParam, lParam); - - case TTM_POP: - return TOOLTIPS_Pop (hwnd, wParam, lParam); - - case TTM_RELAYEVENT: - return TOOLTIPS_RelayEvent (hwnd, wParam, lParam); - - case TTM_SETDELAYTIME: - return TOOLTIPS_SetDelayTime (hwnd, wParam, lParam); - - case TTM_SETMARGIN: - return TOOLTIPS_SetMargin (hwnd, wParam, lParam); - - case TTM_SETMAXTIPWIDTH: - return TOOLTIPS_SetMaxTipWidth (hwnd, wParam, lParam); - - case TTM_SETTIPBKCOLOR: - return TOOLTIPS_SetTipBkColor (hwnd, wParam, lParam); - - case TTM_SETTIPTEXTCOLOR: - return TOOLTIPS_SetTipTextColor (hwnd, wParam, lParam); - - case TTM_SETTITLEA: - return TOOLTIPS_SetTitleA (hwnd, wParam, lParam); - - case TTM_SETTITLEW: - return TOOLTIPS_SetTitleW (hwnd, wParam, lParam); - - case TTM_SETTOOLINFOA: - return TOOLTIPS_SetToolInfoA (hwnd, wParam, lParam); - - case TTM_SETTOOLINFOW: - return TOOLTIPS_SetToolInfoW (hwnd, wParam, lParam); - - case TTM_TRACKACTIVATE: - return TOOLTIPS_TrackActivate (hwnd, wParam, lParam); - - case TTM_TRACKPOSITION: - return TOOLTIPS_TrackPosition (hwnd, wParam, lParam); - - case TTM_UPDATE: - return TOOLTIPS_Update (hwnd, wParam, lParam); - - case TTM_UPDATETIPTEXTA: - return TOOLTIPS_UpdateTipTextA (hwnd, wParam, lParam); - - case TTM_UPDATETIPTEXTW: - return TOOLTIPS_UpdateTipTextW (hwnd, wParam, lParam); - - case TTM_WINDOWFROMPOINT: - return TOOLTIPS_WindowFromPoint (hwnd, wParam, lParam); - - - case WM_CREATE: - return TOOLTIPS_Create (hwnd, (LPCREATESTRUCTW)lParam); - - case WM_DESTROY: - return TOOLTIPS_Destroy (hwnd, wParam, lParam); - - case WM_ERASEBKGND: - /* we draw the background in WM_PAINT */ - return 0; - - case WM_GETFONT: - return TOOLTIPS_GetFont (hwnd, wParam, lParam); - - case WM_GETTEXT: - return TOOLTIPS_OnWMGetText (hwnd, wParam, lParam); - - case WM_GETTEXTLENGTH: - return TOOLTIPS_GetTextLength (hwnd, wParam, lParam); - - case WM_LBUTTONDOWN: - case WM_LBUTTONUP: - case WM_MBUTTONDOWN: - case WM_MBUTTONUP: - case WM_RBUTTONDOWN: - case WM_RBUTTONUP: - case WM_MOUSEMOVE: - return TOOLTIPS_MouseMessage (hwnd, uMsg, wParam, lParam); - - case WM_NCCREATE: - return TOOLTIPS_NCCreate (hwnd, wParam, lParam); - - case WM_NCHITTEST: - return TOOLTIPS_NCHitTest (hwnd, wParam, lParam); - - case WM_NOTIFYFORMAT: - return TOOLTIPS_NotifyFormat (hwnd, wParam, lParam); - - case WM_PAINT: - return TOOLTIPS_Paint (hwnd, wParam, lParam); - - case WM_SETFONT: - return TOOLTIPS_SetFont (hwnd, wParam, lParam); - - case WM_TIMER: - return TOOLTIPS_Timer (hwnd, wParam, lParam); - - case WM_WININICHANGE: - return TOOLTIPS_WinIniChange (hwnd, wParam, lParam); - - default: - if ((uMsg >= WM_USER) && (uMsg < WM_APP)) - ERR("unknown msg %04x wp=%08x lp=%08lx\n", - uMsg, wParam, lParam); - return DefWindowProcW (hwnd, uMsg, wParam, lParam); - } - return 0; -} - - -VOID -TOOLTIPS_Register (void) -{ - WNDCLASSW wndClass; - - ZeroMemory (&wndClass, sizeof(WNDCLASSW)); - wndClass.style = CS_GLOBALCLASS | CS_DBLCLKS | CS_SAVEBITS; - wndClass.lpfnWndProc = TOOLTIPS_WindowProc; - wndClass.cbClsExtra = 0; - wndClass.cbWndExtra = sizeof(TOOLTIPS_INFO *); - wndClass.hCursor = LoadCursorW (0, (LPWSTR)IDC_ARROW); - wndClass.hbrBackground = 0; - wndClass.lpszClassName = TOOLTIPS_CLASSW; - - RegisterClassW (&wndClass); - - hTooltipIcons[TTI_NONE] = NULL; - hTooltipIcons[TTI_INFO] = LoadImageW(COMCTL32_hModule, - (LPCWSTR)MAKEINTRESOURCE(IDI_TT_INFO_SM), IMAGE_ICON, 0, 0, 0); - hTooltipIcons[TTI_WARNING] = LoadImageW(COMCTL32_hModule, - (LPCWSTR)MAKEINTRESOURCE(IDI_TT_WARN_SM), IMAGE_ICON, 0, 0, 0); - hTooltipIcons[TTI_ERROR] = LoadImageW(COMCTL32_hModule, - (LPCWSTR)MAKEINTRESOURCE(IDI_TT_ERROR_SM), IMAGE_ICON, 0, 0, 0); -} - - -VOID -TOOLTIPS_Unregister (void) -{ - int i; - for (i = TTI_INFO; i <= TTI_ERROR; i++) - DestroyIcon(hTooltipIcons[i]); - UnregisterClassW (TOOLTIPS_CLASSW, NULL); -} diff --git a/reactos/lib/comctl32/trackbar.c b/reactos/lib/comctl32/trackbar.c deleted file mode 100644 index afd04428172..00000000000 --- a/reactos/lib/comctl32/trackbar.c +++ /dev/null @@ -1,1837 +0,0 @@ -/* - * Trackbar control - * - * Copyright 1998, 1999 Eric Kohl - * Copyright 1998, 1999 Alex Priem - * Copyright 2002 Dimitrie O. Paun - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2.1 of the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - * - * NOTE - * - * This code was audited for completeness against the documented features - * of Comctl32.dll version 6.0 on Sep. 12, 2002, 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. - * - */ - -#include -#include -#include -#include - -#include "windef.h" -#include "winbase.h" -#include "wingdi.h" -#include "winuser.h" -#include "winnls.h" -#include "commctrl.h" -#include "wine/debug.h" - -#include "comctl32.h" - -WINE_DEFAULT_DEBUG_CHANNEL(trackbar); - -typedef struct -{ - HWND hwndSelf; - LONG lRangeMin; - LONG lRangeMax; - LONG lLineSize; - LONG lPageSize; - LONG lSelMin; - LONG lSelMax; - LONG lPos; - UINT uThumbLen; - UINT uNumTics; - UINT uTicFreq; - HWND hwndNotify; - HWND hwndToolTip; - HWND hwndBuddyLA; - HWND hwndBuddyRB; - INT fLocation; - INT flags; - BOOL bUnicode; - BOOL bFocussed; - RECT rcChannel; - RECT rcSelection; - RECT rcThumb; - LPLONG tics; -} TRACKBAR_INFO; - -#define TB_REFRESH_TIMER 1 -#define TB_REFRESH_DELAY 500 - -#define TOOLTIP_OFFSET 2 /* distance from ctrl edge to tooltip */ - -/* Used by TRACKBAR_Refresh to find out which parts of the control - need to be recalculated */ - -#define TB_THUMBPOSCHANGED 1 -#define TB_THUMBSIZECHANGED 2 -#define TB_THUMBCHANGED (TB_THUMBPOSCHANGED | TB_THUMBSIZECHANGED) -#define TB_SELECTIONCHANGED 4 -#define TB_DRAG_MODE 8 /* we're dragging the slider */ -#define TB_AUTO_PAGE_LEFT 16 -#define TB_AUTO_PAGE_RIGHT 32 -#define TB_AUTO_PAGE (TB_AUTO_PAGE_LEFT | TB_AUTO_PAGE_RIGHT) - -/* helper defines for TRACKBAR_DrawTic */ -#define TIC_EDGE 0x20 -#define TIC_SELECTIONMARKMAX 0x80 -#define TIC_SELECTIONMARKMIN 0x100 -#define TIC_SELECTIONMARK (TIC_SELECTIONMARKMAX | TIC_SELECTIONMARKMIN) - -static inline int -notify_customdraw(TRACKBAR_INFO *infoPtr, NMCUSTOMDRAW *pnmcd, int stage) -{ - pnmcd->dwDrawStage = stage; - return SendMessageW (infoPtr->hwndNotify, WM_NOTIFY, - pnmcd->hdr.idFrom, (LPARAM)pnmcd); -} - -static LRESULT notify_hdr(TRACKBAR_INFO *infoPtr, INT code, LPNMHDR pnmh) -{ - LRESULT result; - - TRACE("(code=%d)\n", code); - - pnmh->hwndFrom = infoPtr->hwndSelf; - pnmh->idFrom = GetWindowLongPtrW(infoPtr->hwndSelf, GWLP_ID); - pnmh->code = code; - result = SendMessageW(infoPtr->hwndNotify, WM_NOTIFY, - (WPARAM)pnmh->idFrom, (LPARAM)pnmh); - - TRACE(" <= %ld\n", result); - - return result; -} - -static inline int notify(TRACKBAR_INFO *infoPtr, INT code) -{ - NMHDR nmh; - return notify_hdr(infoPtr, code, &nmh); -} - -static BOOL -notify_with_scroll (TRACKBAR_INFO *infoPtr, UINT code) -{ - BOOL bVert = GetWindowLongW (infoPtr->hwndSelf, GWL_STYLE) & TBS_VERT; - - TRACE("%x\n", code); - - return (BOOL) SendMessageW (infoPtr->hwndNotify, - bVert ? WM_VSCROLL : WM_HSCROLL, - (WPARAM)code, (LPARAM)infoPtr->hwndSelf); -} - -static void TRACKBAR_RecalculateTics (TRACKBAR_INFO *infoPtr) -{ - int i, tic, nrTics; - - if (infoPtr->uTicFreq && infoPtr->lRangeMax >= infoPtr->lRangeMin) - nrTics=(infoPtr->lRangeMax - infoPtr->lRangeMin)/infoPtr->uTicFreq; - else { - nrTics = 0; - Free (infoPtr->tics); - infoPtr->tics = NULL; - infoPtr->uNumTics = 0; - return; - } - - if (nrTics != infoPtr->uNumTics) { - infoPtr->tics=ReAlloc (infoPtr->tics, - (nrTics+1)*sizeof (DWORD)); - if (!infoPtr->tics) { - infoPtr->uNumTics = 0; - notify(infoPtr, NM_OUTOFMEMORY); - return; - } - infoPtr->uNumTics = nrTics; - } - - tic = infoPtr->lRangeMin + infoPtr->uTicFreq; - for (i = 0; i < nrTics; i++, tic += infoPtr->uTicFreq) - infoPtr->tics[i] = tic; -} - -/* converts from physical (mouse) position to logical position - (in range of trackbar) */ - -static inline LONG -TRACKBAR_ConvertPlaceToPosition (TRACKBAR_INFO *infoPtr, int place, - int vertical) -{ - double range, width, pos, offsetthumb; - - range = infoPtr->lRangeMax - infoPtr->lRangeMin; - if (vertical) { - offsetthumb = (infoPtr->rcThumb.bottom - infoPtr->rcThumb.top)/2; - width = infoPtr->rcChannel.bottom - infoPtr->rcChannel.top - (offsetthumb * 2) - 1; - pos = (range*(place - infoPtr->rcChannel.top - offsetthumb)) / width; - } else { - offsetthumb = (infoPtr->rcThumb.right - infoPtr->rcThumb.left)/2; - width = infoPtr->rcChannel.right - infoPtr->rcChannel.left - (offsetthumb * 2) - 1; - pos = (range*(place - infoPtr->rcChannel.left - offsetthumb)) / width; - } - pos += infoPtr->lRangeMin; - if (pos > infoPtr->lRangeMax) - pos = infoPtr->lRangeMax; - else if (pos < infoPtr->lRangeMin) - pos = infoPtr->lRangeMin; - - TRACE("%.2f\n", pos); - return (LONG)(pos + 0.5); -} - - -/* return: 0> prev, 0 none, >0 next */ -static LONG -TRACKBAR_GetAutoPageDirection (TRACKBAR_INFO *infoPtr, POINT clickPoint) -{ - DWORD dwStyle = GetWindowLongW (infoPtr->hwndSelf, GWL_STYLE); - RECT pageRect; - - if (dwStyle & TBS_VERT) { - pageRect.top = infoPtr->rcChannel.top; - pageRect.bottom = infoPtr->rcChannel.bottom; - pageRect.left = infoPtr->rcThumb.left; - pageRect.right = infoPtr->rcThumb.right; - } else { - pageRect.top = infoPtr->rcThumb.top; - pageRect.bottom = infoPtr->rcThumb.bottom; - pageRect.left = infoPtr->rcChannel.left; - pageRect.right = infoPtr->rcChannel.right; - } - - - if (PtInRect(&pageRect, clickPoint)) - { - int clickPlace = (dwStyle & TBS_VERT) ? clickPoint.y : clickPoint.x; - - LONG clickPos = TRACKBAR_ConvertPlaceToPosition(infoPtr, clickPlace, - dwStyle & TBS_VERT); - return clickPos - infoPtr->lPos; - } - - return 0; -} - -static void inline -TRACKBAR_PageDown (TRACKBAR_INFO *infoPtr) -{ - if (infoPtr->lPos == infoPtr->lRangeMax) return; - - infoPtr->lPos += infoPtr->lPageSize; - if (infoPtr->lPos > infoPtr->lRangeMax) - infoPtr->lPos = infoPtr->lRangeMax; - notify_with_scroll (infoPtr, TB_PAGEDOWN); -} - - -static void inline -TRACKBAR_PageUp (TRACKBAR_INFO *infoPtr) -{ - if (infoPtr->lPos == infoPtr->lRangeMin) return; - - infoPtr->lPos -= infoPtr->lPageSize; - if (infoPtr->lPos < infoPtr->lRangeMin) - infoPtr->lPos = infoPtr->lRangeMin; - notify_with_scroll (infoPtr, TB_PAGEUP); -} - -static void inline TRACKBAR_LineUp(TRACKBAR_INFO *infoPtr) -{ - if (infoPtr->lPos == infoPtr->lRangeMin) return; - infoPtr->lPos -= infoPtr->lLineSize; - if (infoPtr->lPos < infoPtr->lRangeMin) - infoPtr->lPos = infoPtr->lRangeMin; - notify_with_scroll (infoPtr, TB_LINEUP); -} - -static void inline TRACKBAR_LineDown(TRACKBAR_INFO *infoPtr) -{ - if (infoPtr->lPos == infoPtr->lRangeMax) return; - infoPtr->lPos += infoPtr->lLineSize; - if (infoPtr->lPos > infoPtr->lRangeMax) - infoPtr->lPos = infoPtr->lRangeMax; - notify_with_scroll (infoPtr, TB_LINEDOWN); -} - -static void -TRACKBAR_CalcChannel (TRACKBAR_INFO *infoPtr) -{ - DWORD dwStyle = GetWindowLongW (infoPtr->hwndSelf, GWL_STYLE); - INT cyChannel, offsetthumb, offsetedge; - RECT lpRect, *channel = & infoPtr->rcChannel; - - GetClientRect (infoPtr->hwndSelf, &lpRect); - - offsetthumb = infoPtr->uThumbLen / 4; - offsetedge = offsetthumb + 3; - cyChannel = (dwStyle & TBS_ENABLESELRANGE) ? offsetthumb*3 : 4; - if (dwStyle & TBS_VERT) { - channel->top = lpRect.top + offsetedge; - channel->bottom = lpRect.bottom - offsetedge; - if (dwStyle & TBS_ENABLESELRANGE) - channel->left = lpRect.left + ((infoPtr->uThumbLen - cyChannel + 2) / 2); - else - channel->left = lpRect.left + (infoPtr->uThumbLen / 2) - 1; - if (dwStyle & TBS_BOTH) { - if (dwStyle & TBS_NOTICKS) - channel->left += 1; - else - channel->left += 9; - } - else if (dwStyle & TBS_TOP) { - if (dwStyle & TBS_NOTICKS) - channel->left += 2; - else - channel->left += 10; - } - channel->right = channel->left + cyChannel; - } else { - channel->left = lpRect.left + offsetedge; - channel->right = lpRect.right - offsetedge; - if (dwStyle & TBS_ENABLESELRANGE) - channel->top = lpRect.top + ((infoPtr->uThumbLen - cyChannel + 2) / 2); - else - channel->top = lpRect.top + (infoPtr->uThumbLen / 2) - 1; - if (dwStyle & TBS_BOTH) { - if (dwStyle & TBS_NOTICKS) - channel->top += 1; - else - channel->top += 9; - } - else if (dwStyle & TBS_TOP) { - if (dwStyle & TBS_NOTICKS) - channel->top += 2; - else - channel->top += 10; - } - channel->bottom = channel->top + cyChannel; - } -} - -static void -TRACKBAR_CalcThumb (TRACKBAR_INFO *infoPtr, LONG lPos, RECT *thumb) -{ - int range, width, height, thumbwidth; - DWORD dwStyle = GetWindowLongW (infoPtr->hwndSelf, GWL_STYLE); - RECT lpRect; - - range = infoPtr->lRangeMax - infoPtr->lRangeMin; - thumbwidth = (infoPtr->uThumbLen / 2) | 1; - - if (!range) range = 1; - - GetClientRect(infoPtr->hwndSelf, &lpRect); - if (dwStyle & TBS_VERT) - { - height = infoPtr->rcChannel.bottom - infoPtr->rcChannel.top - thumbwidth; - - if ((dwStyle & (TBS_BOTH | TBS_LEFT)) && !(dwStyle & TBS_NOTICKS)) - thumb->left = 10; - else - thumb->left = 2; - thumb->right = thumb->left + infoPtr->uThumbLen; - thumb->top = infoPtr->rcChannel.top + - (height*(lPos - infoPtr->lRangeMin))/range; - thumb->bottom = thumb->top + thumbwidth; - } - else - { - width = infoPtr->rcChannel.right - infoPtr->rcChannel.left - thumbwidth; - - thumb->left = infoPtr->rcChannel.left + - (width*(lPos - infoPtr->lRangeMin))/range; - thumb->right = thumb->left + thumbwidth; - if ((dwStyle & (TBS_BOTH | TBS_TOP)) && !(dwStyle & TBS_NOTICKS)) - thumb->top = 10; - else - thumb->top = 2; - thumb->bottom = thumb->top + infoPtr->uThumbLen; - } -} - -inline static void -TRACKBAR_UpdateThumb (TRACKBAR_INFO *infoPtr) -{ - TRACKBAR_CalcThumb(infoPtr, infoPtr->lPos, &infoPtr->rcThumb); -} - -static inline void -TRACKBAR_InvalidateAll(TRACKBAR_INFO * infoPtr) -{ - InvalidateRect(infoPtr->hwndSelf, NULL, FALSE); -} - -static void -TRACKBAR_InvalidateThumb (TRACKBAR_INFO *infoPtr, LONG thumbPos) -{ - RECT rcThumb; - - TRACKBAR_CalcThumb(infoPtr, thumbPos, &rcThumb); - InflateRect(&rcThumb, 1, 1); - InvalidateRect(infoPtr->hwndSelf, &rcThumb, FALSE); -} - -static inline void -TRACKBAR_InvalidateThumbMove (TRACKBAR_INFO *infoPtr, LONG oldPos, LONG newPos) -{ - TRACKBAR_InvalidateThumb (infoPtr, oldPos); - if (newPos != oldPos) - TRACKBAR_InvalidateThumb (infoPtr, newPos); -} - -static BOOL inline -TRACKBAR_HasSelection (TRACKBAR_INFO *infoPtr) -{ - return infoPtr->lSelMin != infoPtr->lSelMax; -} - -static void -TRACKBAR_CalcSelection (TRACKBAR_INFO *infoPtr) -{ - RECT *selection = &infoPtr->rcSelection; - int range = infoPtr->lRangeMax - infoPtr->lRangeMin; - int offsetthumb, height, width; - - if (range <= 0) { - SetRectEmpty (selection); - } else { - if (GetWindowLongW (infoPtr->hwndSelf, GWL_STYLE) & TBS_VERT) { - offsetthumb = (infoPtr->rcThumb.bottom - infoPtr->rcThumb.top)/2; - height = infoPtr->rcChannel.bottom - infoPtr->rcChannel.top - offsetthumb*2; - selection->top = infoPtr->rcChannel.top + offsetthumb + - (height*infoPtr->lSelMin)/range; - selection->bottom = infoPtr->rcChannel.top + offsetthumb + - (height*infoPtr->lSelMax)/range; - selection->left = infoPtr->rcChannel.left + 3; - selection->right = infoPtr->rcChannel.right - 3; - } else { - offsetthumb = (infoPtr->rcThumb.right - infoPtr->rcThumb.left)/2; - width = infoPtr->rcChannel.right - infoPtr->rcChannel.left - offsetthumb*2; - selection->left = infoPtr->rcChannel.left + offsetthumb + - (width*infoPtr->lSelMin)/range; - selection->right = infoPtr->rcChannel.left + offsetthumb + - (width*infoPtr->lSelMax)/range; - selection->top = infoPtr->rcChannel.top + 3; - selection->bottom = infoPtr->rcChannel.bottom - 3; - } - } - - TRACE("selection[left=%ld, top=%ld, right=%ld, bottom=%ld]\n", - selection->left, selection->top, selection->right, selection->bottom); -} - -static BOOL -TRACKBAR_AutoPage (TRACKBAR_INFO *infoPtr, POINT clickPoint) -{ - LONG dir = TRACKBAR_GetAutoPageDirection(infoPtr, clickPoint); - LONG prevPos = infoPtr->lPos; - - TRACE("x=%ld, y=%ld, dir=%ld\n", clickPoint.x, clickPoint.y, dir); - - if (dir > 0 && (infoPtr->flags & TB_AUTO_PAGE_RIGHT)) - TRACKBAR_PageDown(infoPtr); - else if (dir < 0 && (infoPtr->flags & TB_AUTO_PAGE_LEFT)) - TRACKBAR_PageUp(infoPtr); - else return FALSE; - - infoPtr->flags |= TB_THUMBPOSCHANGED; - TRACKBAR_InvalidateThumbMove (infoPtr, prevPos, infoPtr->lPos); - - return TRUE; -} - -/* Trackbar drawing code. I like my spaghetti done milanese. */ - -static void -TRACKBAR_DrawChannel (TRACKBAR_INFO *infoPtr, HDC hdc, DWORD dwStyle) -{ - RECT rcChannel = infoPtr->rcChannel; - - DrawEdge (hdc, &rcChannel, EDGE_SUNKEN, BF_RECT | BF_ADJUST); - if (dwStyle & TBS_ENABLESELRANGE) { /* fill the channel */ - FillRect (hdc, &rcChannel, GetStockObject(WHITE_BRUSH)); - if (TRACKBAR_HasSelection(infoPtr)) - FillRect (hdc, &infoPtr->rcSelection, GetSysColorBrush(COLOR_HIGHLIGHT)); - } -} - -static void -TRACKBAR_DrawOneTic (TRACKBAR_INFO *infoPtr, HDC hdc, LONG ticPos, int flags) -{ - int x, y, ox, oy, range, side, indent = 0, len = 3; - int offsetthumb; - RECT rcTics; - - if (flags & TBS_VERT) { - offsetthumb = (infoPtr->rcThumb.bottom - infoPtr->rcThumb.top)/2; - rcTics.left = infoPtr->rcThumb.left - 2; - rcTics.right = infoPtr->rcThumb.right + 2; - rcTics.top = infoPtr->rcChannel.top + offsetthumb + 1; - rcTics.bottom = infoPtr->rcChannel.bottom - offsetthumb; - } else { - offsetthumb = (infoPtr->rcThumb.right - infoPtr->rcThumb.left)/2; - rcTics.left = infoPtr->rcChannel.left + offsetthumb + 1; - rcTics.right = infoPtr->rcChannel.right - offsetthumb; - rcTics.top = infoPtr->rcThumb.top - 2; - rcTics.bottom = infoPtr->rcThumb.bottom + 2; - } - - if (flags & (TBS_TOP | TBS_LEFT)) { - x = rcTics.left; - y = rcTics.top; - side = -1; - } else { - x = rcTics.right; - y = rcTics.bottom; - side = 1; - } - - range = infoPtr->lRangeMax - infoPtr->lRangeMin; - if (range <= 0) - range = 1; /* to avoid division by zero */ - - if (flags & TIC_SELECTIONMARK) { - indent = (flags & TIC_SELECTIONMARKMIN) ? -1 : 1; - } else if (flags & TIC_EDGE) { - len++; - } - - if (flags & TBS_VERT) { - int height = rcTics.bottom - rcTics.top; - y = rcTics.top + (height*(ticPos - infoPtr->lRangeMin))/range; - } else { - int width = rcTics.right - rcTics.left; - x = rcTics.left + (width*(ticPos - infoPtr->lRangeMin))/range; - } - - ox = x; - oy = y; - MoveToEx(hdc, x, y, 0); - if (flags & TBS_VERT) x += len * side; - else y += len * side; - LineTo(hdc, x, y); - - if (flags & TIC_SELECTIONMARK) { - if (flags & TBS_VERT) { - x -= side; - } else { - y -= side; - } - MoveToEx(hdc, x, y, 0); - if (flags & TBS_VERT) { - y += 2 * indent; - } else { - x += 2 * indent; - } - - LineTo(hdc, x, y); - LineTo(hdc, ox, oy); - } -} - - -static inline void -TRACKBAR_DrawTic (TRACKBAR_INFO *infoPtr, HDC hdc, LONG ticPos, int flags) -{ - if ((flags & (TBS_LEFT | TBS_TOP)) || (flags & TBS_BOTH)) - TRACKBAR_DrawOneTic (infoPtr, hdc, ticPos, flags | TBS_LEFT); - - if (!(flags & (TBS_LEFT | TBS_TOP)) || (flags & TBS_BOTH)) - TRACKBAR_DrawOneTic (infoPtr, hdc, ticPos, flags & ~TBS_LEFT); -} - -static void -TRACKBAR_DrawTics (TRACKBAR_INFO *infoPtr, HDC hdc, DWORD dwStyle) -{ - unsigned int i; - int ticFlags = dwStyle & 0x0f; - LOGPEN ticPen = { PS_SOLID, {1, 0}, GetSysColor (COLOR_3DDKSHADOW) }; - HPEN hOldPen, hTicPen; - - /* create the pen to draw the tics with */ - hTicPen = CreatePenIndirect(&ticPen); - hOldPen = hTicPen ? SelectObject(hdc, hTicPen) : 0; - - /* actually draw the tics */ - for (i=0; iuNumTics; i++) - TRACKBAR_DrawTic (infoPtr, hdc, infoPtr->tics[i], ticFlags); - - TRACKBAR_DrawTic (infoPtr, hdc, infoPtr->lRangeMin, ticFlags | TIC_EDGE); - TRACKBAR_DrawTic (infoPtr, hdc, infoPtr->lRangeMax, ticFlags | TIC_EDGE); - - if ((dwStyle & TBS_ENABLESELRANGE) && TRACKBAR_HasSelection(infoPtr)) { - TRACKBAR_DrawTic (infoPtr, hdc, infoPtr->lSelMin, - ticFlags | TIC_SELECTIONMARKMIN); - TRACKBAR_DrawTic (infoPtr, hdc, infoPtr->lSelMax, - ticFlags | TIC_SELECTIONMARKMAX); - } - - /* clean up the pen, if we created one */ - if (hTicPen) { - SelectObject(hdc, hOldPen); - DeleteObject(hTicPen); - } -} - -static void -TRACKBAR_DrawThumb(TRACKBAR_INFO *infoPtr, HDC hdc, DWORD dwStyle) -{ - HBRUSH oldbr; - HPEN oldpen; - RECT thumb = infoPtr->rcThumb; - int BlackUntil = 3; - int PointCount = 6; - POINT points[6]; - int fillClr; - int PointDepth; - - fillClr = infoPtr->flags & TB_DRAG_MODE ? COLOR_BTNHILIGHT : COLOR_BTNFACE; - oldbr = SelectObject (hdc, GetSysColorBrush(fillClr)); - SetPolyFillMode (hdc, WINDING); - - if (dwStyle & TBS_BOTH) - { - points[0].x=thumb.right; - points[0].y=thumb.top; - points[1].x=thumb.right; - points[1].y=thumb.bottom; - points[2].x=thumb.left; - points[2].y=thumb.bottom; - points[3].x=thumb.left; - points[3].y=thumb.top; - points[4].x=points[0].x; - points[4].y=points[0].y; - PointCount = 5; - BlackUntil = 3; - } - else - { - if (dwStyle & TBS_VERT) - { - PointDepth = (thumb.bottom - thumb.top) / 2; - if (dwStyle & TBS_LEFT) - { - points[0].x=thumb.right; - points[0].y=thumb.top; - points[1].x=thumb.right; - points[1].y=thumb.bottom; - points[2].x=thumb.left + PointDepth; - points[2].y=thumb.bottom; - points[3].x=thumb.left; - points[3].y=(thumb.bottom - thumb.top) / 2 + thumb.top + 1; - points[4].x=thumb.left + PointDepth; - points[4].y=thumb.top; - points[5].x=points[0].x; - points[5].y=points[0].y; - BlackUntil = 4; - } - else - { - points[0].x=thumb.right; - points[0].y=(thumb.bottom - thumb.top) / 2 + thumb.top + 1; - points[1].x=thumb.right - PointDepth; - points[1].y=thumb.bottom; - points[2].x=thumb.left; - points[2].y=thumb.bottom; - points[3].x=thumb.left; - points[3].y=thumb.top; - points[4].x=thumb.right - PointDepth; - points[4].y=thumb.top; - points[5].x=points[0].x; - points[5].y=points[0].y; - } - } - else - { - PointDepth = (thumb.right - thumb.left) / 2; - if (dwStyle & TBS_TOP) - { - points[0].x=(thumb.right - thumb.left) / 2 + thumb.left + 1; - points[0].y=thumb.top; - points[1].x=thumb.right; - points[1].y=thumb.top + PointDepth; - points[2].x=thumb.right; - points[2].y=thumb.bottom; - points[3].x=thumb.left; - points[3].y=thumb.bottom; - points[4].x=thumb.left; - points[4].y=thumb.top + PointDepth; - points[5].x=points[0].x; - points[5].y=points[0].y; - BlackUntil = 4; - } - else - { - points[0].x=thumb.right; - points[0].y=thumb.top; - points[1].x=thumb.right; - points[1].y=thumb.bottom - PointDepth; - points[2].x=(thumb.right - thumb.left) / 2 + thumb.left + 1; - points[2].y=thumb.bottom; - points[3].x=thumb.left; - points[3].y=thumb.bottom - PointDepth; - points[4].x=thumb.left; - points[4].y=thumb.top; - points[5].x=points[0].x; - points[5].y=points[0].y; - } - } - - } - - /* Draw the thumb now */ - Polygon (hdc, points, PointCount); - oldpen = SelectObject(hdc, GetStockObject(BLACK_PEN)); - Polyline(hdc,points, BlackUntil); - SelectObject(hdc, GetStockObject(WHITE_PEN)); - Polyline(hdc, &points[BlackUntil-1], PointCount+1-BlackUntil); - SelectObject(hdc, oldpen); - SelectObject(hdc, oldbr); -} - - -static void inline -TRACKBAR_ActivateToolTip (TRACKBAR_INFO *infoPtr, BOOL fShow) -{ - TTTOOLINFOW ti; - - if (!infoPtr->hwndToolTip) return; - - ZeroMemory(&ti, sizeof(ti)); - ti.cbSize = sizeof(ti); - ti.hwnd = infoPtr->hwndSelf; - - SendMessageW (infoPtr->hwndToolTip, TTM_TRACKACTIVATE, fShow, (LPARAM)&ti); -} - - -static void -TRACKBAR_UpdateToolTip (TRACKBAR_INFO *infoPtr) -{ - DWORD dwStyle = GetWindowLongW (infoPtr->hwndSelf, GWL_STYLE); - WCHAR buf[80]; - static const WCHAR fmt[] = { '%', 'l', 'd', 0 }; - TTTOOLINFOW ti; - POINT pt; - RECT rcClient; - LRESULT size; - - if (!infoPtr->hwndToolTip) return; - - ZeroMemory(&ti, sizeof(ti)); - ti.cbSize = sizeof(ti); - ti.hwnd = infoPtr->hwndSelf; - ti.uFlags = TTF_IDISHWND | TTF_TRACK | TTF_ABSOLUTE; - - wsprintfW (buf, fmt, infoPtr->lPos); - ti.lpszText = buf; - SendMessageW (infoPtr->hwndToolTip, TTM_UPDATETIPTEXTW, 0, (LPARAM)&ti); - - GetClientRect (infoPtr->hwndSelf, &rcClient); - size = SendMessageW (infoPtr->hwndToolTip, TTM_GETBUBBLESIZE, 0, (LPARAM)&ti); - if (dwStyle & TBS_VERT) { - if (infoPtr->fLocation == TBTS_LEFT) - pt.x = 0 - LOWORD(size) - TOOLTIP_OFFSET; - else - pt.x = rcClient.right + TOOLTIP_OFFSET; - pt.y = (infoPtr->rcThumb.top + infoPtr->rcThumb.bottom - HIWORD(size))/2; - } else { - if (infoPtr->fLocation == TBTS_TOP) - pt.y = 0 - HIWORD(size) - TOOLTIP_OFFSET; - else - pt.y = rcClient.bottom + TOOLTIP_OFFSET; - pt.x = (infoPtr->rcThumb.left + infoPtr->rcThumb.right - LOWORD(size))/2; - } - ClientToScreen(infoPtr->hwndSelf, &pt); - - SendMessageW (infoPtr->hwndToolTip, TTM_TRACKPOSITION, - 0, (LPARAM)MAKELPARAM(pt.x, pt.y)); -} - - -static void -TRACKBAR_Refresh (TRACKBAR_INFO *infoPtr, HDC hdcDst) -{ - DWORD dwStyle = GetWindowLongW (infoPtr->hwndSelf, GWL_STYLE); - RECT rcClient; - HDC hdc; - HBITMAP hOldBmp = 0, hOffScreenBmp = 0; - NMCUSTOMDRAW nmcd; - int gcdrf, icdrf; - - if (infoPtr->flags & TB_THUMBCHANGED) { - TRACKBAR_UpdateThumb (infoPtr); - if (infoPtr->flags & TB_THUMBSIZECHANGED) - TRACKBAR_CalcChannel (infoPtr); - } - if (infoPtr->flags & TB_SELECTIONCHANGED) - TRACKBAR_CalcSelection (infoPtr); - - if (infoPtr->flags & TB_DRAG_MODE) - TRACKBAR_UpdateToolTip (infoPtr); - - infoPtr->flags &= ~ (TB_THUMBCHANGED | TB_SELECTIONCHANGED); - - GetClientRect (infoPtr->hwndSelf, &rcClient); - - /* try to render offscreen, if we fail, carrry onscreen */ - hdc = CreateCompatibleDC(hdcDst); - if (hdc) { - hOffScreenBmp = CreateCompatibleBitmap(hdcDst, rcClient.right, rcClient.bottom); - if (hOffScreenBmp) { - hOldBmp = SelectObject(hdc, hOffScreenBmp); - } else { - DeleteObject(hdc); - hdc = hdcDst; - } - } else { - hdc = hdcDst; - } - - ZeroMemory(&nmcd, sizeof(nmcd)); - nmcd.hdr.hwndFrom = infoPtr->hwndSelf; - nmcd.hdr.idFrom = GetWindowLongPtrW (infoPtr->hwndSelf, GWLP_ID); - nmcd.hdr.code = NM_CUSTOMDRAW; - nmcd.hdc = hdc; - - /* start the paint cycle */ - nmcd.rc = rcClient; - gcdrf = notify_customdraw(infoPtr, &nmcd, CDDS_PREPAINT); - if (gcdrf & CDRF_SKIPDEFAULT) goto cleanup; - - /* Erase backbround */ - if (gcdrf == CDRF_DODEFAULT || - notify_customdraw(infoPtr, &nmcd, CDDS_PREERASE) != CDRF_SKIPDEFAULT) { - FillRect (hdc, &rcClient, GetSysColorBrush(COLOR_BTNFACE)); - if (gcdrf != CDRF_DODEFAULT) - notify_customdraw(infoPtr, &nmcd, CDDS_POSTERASE); - } - - /* draw channel */ - if (gcdrf & CDRF_NOTIFYITEMDRAW) { - nmcd.dwItemSpec = TBCD_CHANNEL; - nmcd.uItemState = CDIS_DEFAULT; - nmcd.rc = infoPtr->rcChannel; - icdrf = notify_customdraw(infoPtr, &nmcd, CDDS_ITEMPREPAINT); - } else icdrf = CDRF_DODEFAULT; - if ( !(icdrf & CDRF_SKIPDEFAULT) ) { - TRACKBAR_DrawChannel (infoPtr, hdc, dwStyle); - if (icdrf & CDRF_NOTIFYPOSTPAINT) - notify_customdraw(infoPtr, &nmcd, CDDS_ITEMPOSTPAINT); - } - - - /* draw tics */ - if (!(dwStyle & TBS_NOTICKS)) { - if (gcdrf & CDRF_NOTIFYITEMDRAW) { - nmcd.dwItemSpec = TBCD_TICS; - nmcd.uItemState = CDIS_DEFAULT; - nmcd.rc = rcClient; - icdrf = notify_customdraw(infoPtr, &nmcd, CDDS_ITEMPREPAINT); - } else icdrf = CDRF_DODEFAULT; - if ( !(icdrf & CDRF_SKIPDEFAULT) ) { - TRACKBAR_DrawTics (infoPtr, hdc, dwStyle); - if (icdrf & CDRF_NOTIFYPOSTPAINT) - notify_customdraw(infoPtr, &nmcd, CDDS_ITEMPOSTPAINT); - } - } - - /* draw thumb */ - if (!(dwStyle & TBS_NOTHUMB)) { - if (gcdrf & CDRF_NOTIFYITEMDRAW) { - nmcd.dwItemSpec = TBCD_THUMB; - nmcd.uItemState = infoPtr->flags & TB_DRAG_MODE ? CDIS_HOT : CDIS_DEFAULT; - nmcd.rc = infoPtr->rcThumb; - icdrf = notify_customdraw(infoPtr, &nmcd, CDDS_ITEMPREPAINT); - } else icdrf = CDRF_DODEFAULT; - if ( !(icdrf & CDRF_SKIPDEFAULT) ) { - TRACKBAR_DrawThumb(infoPtr, hdc, dwStyle); - if (icdrf & CDRF_NOTIFYPOSTPAINT) - notify_customdraw(infoPtr, &nmcd, CDDS_ITEMPOSTPAINT); - } - } - - /* draw focus rectangle */ - if (infoPtr->bFocussed) { - DrawFocusRect(hdc, &rcClient); - } - - /* finish up the painting */ - if (gcdrf & CDRF_NOTIFYPOSTPAINT) - notify_customdraw(infoPtr, &nmcd, CDDS_POSTPAINT); - -cleanup: - /* cleanup, if we rendered offscreen */ - if (hdc != hdcDst) { - BitBlt(hdcDst, 0, 0, rcClient.right, rcClient.bottom, hdc, 0, 0, SRCCOPY); - SelectObject(hdc, hOldBmp); - DeleteObject(hOffScreenBmp); - DeleteObject(hdc); - } -} - - -static void -TRACKBAR_AlignBuddies (TRACKBAR_INFO *infoPtr) -{ - DWORD dwStyle = GetWindowLongW (infoPtr->hwndSelf, GWL_STYLE); - HWND hwndParent = GetParent (infoPtr->hwndSelf); - RECT rcSelf, rcBuddy; - INT x, y; - - GetWindowRect (infoPtr->hwndSelf, &rcSelf); - MapWindowPoints (HWND_DESKTOP, hwndParent, (LPPOINT)&rcSelf, 2); - - /* align buddy left or above */ - if (infoPtr->hwndBuddyLA) { - GetWindowRect (infoPtr->hwndBuddyLA, &rcBuddy); - MapWindowPoints (HWND_DESKTOP, hwndParent, (LPPOINT)&rcBuddy, 2); - - if (dwStyle & TBS_VERT) { - x = (infoPtr->rcChannel.right + infoPtr->rcChannel.left) / 2 - - (rcBuddy.right - rcBuddy.left) / 2 + rcSelf.left; - y = rcSelf.top - (rcBuddy.bottom - rcBuddy.top); - } - else { - x = rcSelf.left - (rcBuddy.right - rcBuddy.left); - y = (infoPtr->rcChannel.bottom + infoPtr->rcChannel.top) / 2 - - (rcBuddy.bottom - rcBuddy.top) / 2 + rcSelf.top; - } - - SetWindowPos (infoPtr->hwndBuddyLA, 0, x, y, 0, 0, - SWP_NOZORDER | SWP_NOSIZE); - } - - - /* align buddy right or below */ - if (infoPtr->hwndBuddyRB) { - GetWindowRect (infoPtr->hwndBuddyRB, &rcBuddy); - MapWindowPoints (HWND_DESKTOP, hwndParent, (LPPOINT)&rcBuddy, 2); - - if (dwStyle & TBS_VERT) { - x = (infoPtr->rcChannel.right + infoPtr->rcChannel.left) / 2 - - (rcBuddy.right - rcBuddy.left) / 2 + rcSelf.left; - y = rcSelf.bottom; - } - else { - x = rcSelf.right; - y = (infoPtr->rcChannel.bottom + infoPtr->rcChannel.top) / 2 - - (rcBuddy.bottom - rcBuddy.top) / 2 + rcSelf.top; - } - SetWindowPos (infoPtr->hwndBuddyRB, 0, x, y, 0, 0, - SWP_NOZORDER | SWP_NOSIZE); - } -} - - -static LRESULT -TRACKBAR_ClearSel (TRACKBAR_INFO *infoPtr, BOOL fRedraw) -{ - infoPtr->lSelMin = 0; - infoPtr->lSelMax = 0; - infoPtr->flags |= TB_SELECTIONCHANGED; - - if (fRedraw) TRACKBAR_InvalidateAll(infoPtr); - - return 0; -} - - -static LRESULT -TRACKBAR_ClearTics (TRACKBAR_INFO *infoPtr, BOOL fRedraw) -{ - if (infoPtr->tics) { - Free (infoPtr->tics); - infoPtr->tics = NULL; - infoPtr->uNumTics = 0; - } - - if (fRedraw) TRACKBAR_InvalidateAll(infoPtr); - - return 0; -} - - -static LRESULT inline -TRACKBAR_GetChannelRect (TRACKBAR_INFO *infoPtr, LPRECT lprc) -{ - if (lprc == NULL) return 0; - - lprc->left = infoPtr->rcChannel.left; - lprc->right = infoPtr->rcChannel.right; - lprc->bottom = infoPtr->rcChannel.bottom; - lprc->top = infoPtr->rcChannel.top; - - return 0; -} - - -static LONG inline -TRACKBAR_GetNumTics (TRACKBAR_INFO *infoPtr) -{ - if (GetWindowLongW (infoPtr->hwndSelf, GWL_STYLE) & TBS_NOTICKS) - return 0; - - return infoPtr->uNumTics + 2; -} - - -static int comp_tics(const void *ap, const void *bp) -{ - DWORD a = *((DWORD *)ap); - DWORD b = *((DWORD *)bp); - - TRACE("(a=%ld, b=%ld)\n", a, b); - if (a < b) return -1; - if (a > b) return 1; - return 0; -} - - -static LONG inline -TRACKBAR_GetTic (TRACKBAR_INFO *infoPtr, INT iTic) -{ - if ((iTic < 0) || (iTic >= infoPtr->uNumTics) || !infoPtr->tics) - return -1; - - qsort(infoPtr->tics, infoPtr->uNumTics, sizeof(DWORD), comp_tics); - return infoPtr->tics[iTic]; -} - - -static LONG inline -TRACKBAR_GetTicPos (TRACKBAR_INFO *infoPtr, INT iTic) -{ - LONG range, width, pos, tic; - int offsetthumb; - - if ((iTic < 0) || (iTic >= infoPtr->uNumTics) || !infoPtr->tics) - return -1; - - tic = TRACKBAR_GetTic (infoPtr, iTic); - range = infoPtr->lRangeMax - infoPtr->lRangeMin; - if (range <= 0) range = 1; - offsetthumb = (infoPtr->rcThumb.right - infoPtr->rcThumb.left)/2; - width = infoPtr->rcChannel.right - infoPtr->rcChannel.left - offsetthumb*2; - pos = infoPtr->rcChannel.left + offsetthumb + (width * tic) / range; - - return pos; -} - - -static HWND -TRACKBAR_SetBuddy (TRACKBAR_INFO *infoPtr, BOOL fLocation, HWND hwndBuddy) -{ - HWND hwndTemp; - - if (fLocation) { - /* buddy is left or above */ - hwndTemp = infoPtr->hwndBuddyLA; - infoPtr->hwndBuddyLA = hwndBuddy; - } - else { - /* buddy is right or below */ - hwndTemp = infoPtr->hwndBuddyRB; - infoPtr->hwndBuddyRB = hwndBuddy; - } - - TRACKBAR_AlignBuddies (infoPtr); - - return hwndTemp; -} - - -static LONG inline -TRACKBAR_SetLineSize (TRACKBAR_INFO *infoPtr, LONG lLineSize) -{ - LONG lTemp = infoPtr->lLineSize; - - infoPtr->lLineSize = lLineSize; - - return lTemp; -} - - -static LONG inline -TRACKBAR_SetPageSize (TRACKBAR_INFO *infoPtr, LONG lPageSize) -{ - LONG lTemp = infoPtr->lPageSize; - - infoPtr->lPageSize = lPageSize; - - return lTemp; -} - - -static LRESULT inline -TRACKBAR_SetPos (TRACKBAR_INFO *infoPtr, BOOL fPosition, LONG lPosition) -{ - LONG oldPos = infoPtr->lPos; - infoPtr->lPos = lPosition; - - if (infoPtr->lPos < infoPtr->lRangeMin) - infoPtr->lPos = infoPtr->lRangeMin; - - if (infoPtr->lPos > infoPtr->lRangeMax) - infoPtr->lPos = infoPtr->lRangeMax; - infoPtr->flags |= TB_THUMBPOSCHANGED; - - if (fPosition) TRACKBAR_InvalidateThumbMove(infoPtr, oldPos, lPosition); - - return 0; -} - - -static LRESULT inline -TRACKBAR_SetRange (TRACKBAR_INFO *infoPtr, BOOL fRedraw, LONG lRange) -{ - infoPtr->lRangeMin = (SHORT)LOWORD(lRange); - infoPtr->lRangeMax = (SHORT)HIWORD(lRange); - - if (infoPtr->lPos < infoPtr->lRangeMin) { - infoPtr->lPos = infoPtr->lRangeMin; - infoPtr->flags |= TB_THUMBPOSCHANGED; - } - - if (infoPtr->lPos > infoPtr->lRangeMax) { - infoPtr->lPos = infoPtr->lRangeMax; - infoPtr->flags |= TB_THUMBPOSCHANGED; - } - - infoPtr->lPageSize = (infoPtr->lRangeMax - infoPtr->lRangeMin) / 5; - if (infoPtr->lPageSize == 0) infoPtr->lPageSize = 1; - - if (fRedraw) TRACKBAR_InvalidateAll(infoPtr); - - return 0; -} - - -static LRESULT inline -TRACKBAR_SetRangeMax (TRACKBAR_INFO *infoPtr, BOOL fRedraw, LONG lMax) -{ - infoPtr->lRangeMax = lMax; - if (infoPtr->lPos > infoPtr->lRangeMax) { - infoPtr->lPos = infoPtr->lRangeMax; - infoPtr->flags |= TB_THUMBPOSCHANGED; - } - - infoPtr->lPageSize = (infoPtr->lRangeMax - infoPtr->lRangeMin) / 5; - if (infoPtr->lPageSize == 0) infoPtr->lPageSize = 1; - - if (fRedraw) TRACKBAR_InvalidateAll(infoPtr); - - return 0; -} - - -static LRESULT inline -TRACKBAR_SetRangeMin (TRACKBAR_INFO *infoPtr, BOOL fRedraw, LONG lMin) -{ - infoPtr->lRangeMin = lMin; - if (infoPtr->lPos < infoPtr->lRangeMin) { - infoPtr->lPos = infoPtr->lRangeMin; - infoPtr->flags |= TB_THUMBPOSCHANGED; - } - - infoPtr->lPageSize = (infoPtr->lRangeMax - infoPtr->lRangeMin) / 5; - if (infoPtr->lPageSize == 0) infoPtr->lPageSize = 1; - - if (fRedraw) TRACKBAR_InvalidateAll(infoPtr); - - return 0; -} - - -static LRESULT inline -TRACKBAR_SetSel (TRACKBAR_INFO *infoPtr, BOOL fRedraw, LONG lSel) -{ - if (!GetWindowLongW (infoPtr->hwndSelf, GWL_STYLE) & TBS_ENABLESELRANGE) - return 0; - - infoPtr->lSelMin = (SHORT)LOWORD(lSel); - infoPtr->lSelMax = (SHORT)HIWORD(lSel); - infoPtr->flags |= TB_SELECTIONCHANGED; - - if (infoPtr->lSelMin < infoPtr->lRangeMin) - infoPtr->lSelMin = infoPtr->lRangeMin; - if (infoPtr->lSelMax > infoPtr->lRangeMax) - infoPtr->lSelMax = infoPtr->lRangeMax; - - if (fRedraw) TRACKBAR_InvalidateAll(infoPtr); - - return 0; -} - - -static LRESULT inline -TRACKBAR_SetSelEnd (TRACKBAR_INFO *infoPtr, BOOL fRedraw, LONG lEnd) -{ - if (!GetWindowLongW (infoPtr->hwndSelf, GWL_STYLE) & TBS_ENABLESELRANGE) - return 0; - - infoPtr->lSelMax = lEnd; - infoPtr->flags |= TB_SELECTIONCHANGED; - - if (infoPtr->lSelMax > infoPtr->lRangeMax) - infoPtr->lSelMax = infoPtr->lRangeMax; - - if (fRedraw) TRACKBAR_InvalidateAll(infoPtr); - - return 0; -} - - -static LRESULT inline -TRACKBAR_SetSelStart (TRACKBAR_INFO *infoPtr, BOOL fRedraw, LONG lStart) -{ - if (!GetWindowLongW (infoPtr->hwndSelf, GWL_STYLE) & TBS_ENABLESELRANGE) - return 0; - - infoPtr->lSelMin = lStart; - infoPtr->flags |=TB_SELECTIONCHANGED; - - if (infoPtr->lSelMin < infoPtr->lRangeMin) - infoPtr->lSelMin = infoPtr->lRangeMin; - - if (fRedraw) TRACKBAR_InvalidateAll(infoPtr); - - return 0; -} - - -static LRESULT inline -TRACKBAR_SetThumbLength (TRACKBAR_INFO *infoPtr, UINT iLength) -{ - if (GetWindowLongW (infoPtr->hwndSelf, GWL_STYLE) & TBS_FIXEDLENGTH) { - infoPtr->uThumbLen = iLength; - infoPtr->flags |= TB_THUMBSIZECHANGED; - InvalidateRect (infoPtr->hwndSelf, &infoPtr->rcThumb, FALSE); - } - - return 0; -} - - -static LRESULT inline -TRACKBAR_SetTic (TRACKBAR_INFO *infoPtr, LONG lPos) -{ - if (GetWindowLongW (infoPtr->hwndSelf, GWL_STYLE) & TBS_AUTOTICKS) - return FALSE; - - if ((lPos < infoPtr->lRangeMin) || (lPos> infoPtr->lRangeMax)) - return FALSE; - - TRACE("lPos=%ld\n", lPos); - - infoPtr->uNumTics++; - infoPtr->tics=ReAlloc( infoPtr->tics, - (infoPtr->uNumTics)*sizeof (DWORD)); - if (!infoPtr->tics) { - infoPtr->uNumTics = 0; - notify(infoPtr, NM_OUTOFMEMORY); - return FALSE; - } - infoPtr->tics[infoPtr->uNumTics-1] = lPos; - - TRACKBAR_InvalidateAll(infoPtr); - - return TRUE; -} - - -static LRESULT inline -TRACKBAR_SetTicFreq (TRACKBAR_INFO *infoPtr, WORD wFreq) -{ - if (GetWindowLongW (infoPtr->hwndSelf, GWL_STYLE) & TBS_AUTOTICKS) { - infoPtr->uTicFreq = wFreq; - TRACKBAR_RecalculateTics (infoPtr); - TRACKBAR_InvalidateAll(infoPtr); - } - - return 0; -} - - -static INT inline -TRACKBAR_SetTipSide (TRACKBAR_INFO *infoPtr, INT fLocation) -{ - INT fTemp = infoPtr->fLocation; - - infoPtr->fLocation = fLocation; - - return fTemp; -} - - -static LRESULT inline -TRACKBAR_SetToolTips (TRACKBAR_INFO *infoPtr, HWND hwndTT) -{ - infoPtr->hwndToolTip = hwndTT; - - return 0; -} - - -static BOOL inline -TRACKBAR_SetUnicodeFormat (TRACKBAR_INFO *infoPtr, BOOL fUnicode) -{ - BOOL bTemp = infoPtr->bUnicode; - - infoPtr->bUnicode = fUnicode; - - return bTemp; -} - - -static LRESULT -TRACKBAR_InitializeThumb (TRACKBAR_INFO *infoPtr) -{ - DWORD dwStyle = GetWindowLongW (infoPtr->hwndSelf, GWL_STYLE); - RECT rect; - int clientWidth, clientMetric; - - /* initial thumb length */ - clientMetric = (dwStyle & TBS_ENABLESELRANGE) ? 23 : 21; - GetClientRect(infoPtr->hwndSelf,&rect); - if (dwStyle & TBS_VERT) { - clientWidth = rect.right - rect.left; - } else { - clientWidth = rect.bottom - rect.top; - } - if (clientWidth >= clientMetric) - infoPtr->uThumbLen = clientMetric; - else - infoPtr->uThumbLen = clientWidth > 9 ? clientWidth - 6 : 4; - - TRACKBAR_CalcChannel (infoPtr); - TRACKBAR_UpdateThumb (infoPtr); - infoPtr->flags &= ~TB_SELECTIONCHANGED; - - return 0; -} - - -static LRESULT -TRACKBAR_Create (HWND hwnd, LPCREATESTRUCTW lpcs) -{ - TRACKBAR_INFO *infoPtr; - DWORD oldStyle, newStyle; - - infoPtr = (TRACKBAR_INFO *)Alloc (sizeof(TRACKBAR_INFO)); - if (!infoPtr) return -1; - SetWindowLongPtrW (hwnd, 0, (DWORD_PTR)infoPtr); - - /* set default values */ - infoPtr->hwndSelf = hwnd; - infoPtr->lRangeMin = 0; - infoPtr->lRangeMax = 100; - infoPtr->lLineSize = 1; - infoPtr->lPageSize = 20; - infoPtr->lSelMin = 0; - infoPtr->lSelMax = 0; - infoPtr->lPos = 0; - infoPtr->fLocation = -1; - infoPtr->uNumTics = 0; /* start and end tic are not included in count*/ - infoPtr->uTicFreq = 1; - infoPtr->tics = NULL; - infoPtr->hwndNotify= lpcs->hwndParent; - - TRACKBAR_InitializeThumb (infoPtr); - - oldStyle = newStyle = GetWindowLongW (hwnd, GWL_STYLE); - if (oldStyle & TBS_VERT) { - if (! (oldStyle & (TBS_LEFT | TBS_RIGHT | TBS_BOTH)) ) - newStyle |= TBS_RIGHT; - } else { - if (! (oldStyle & (TBS_TOP | TBS_BOTTOM | TBS_BOTH)) ) - newStyle |= TBS_BOTTOM; - } - if (newStyle != oldStyle) - SetWindowLongW (hwnd, GWL_STYLE, newStyle); - - /* Create tooltip control */ - if (newStyle & TBS_TOOLTIPS) { - - infoPtr->hwndToolTip = - CreateWindowExW (0, TOOLTIPS_CLASSW, NULL, 0, - CW_USEDEFAULT, CW_USEDEFAULT, - CW_USEDEFAULT, CW_USEDEFAULT, - hwnd, 0, 0, 0); - - if (infoPtr->hwndToolTip) { - TTTOOLINFOW ti; - ZeroMemory (&ti, sizeof(ti)); - ti.cbSize = sizeof(ti); - ti.uFlags = TTF_IDISHWND | TTF_TRACK | TTF_ABSOLUTE; - ti.hwnd = hwnd; - - SendMessageW (infoPtr->hwndToolTip, TTM_ADDTOOLW, 0, (LPARAM)&ti); - } - } - - return 0; -} - - -static LRESULT -TRACKBAR_Destroy (TRACKBAR_INFO *infoPtr) -{ - /* delete tooltip control */ - if (infoPtr->hwndToolTip) - DestroyWindow (infoPtr->hwndToolTip); - - Free (infoPtr); - SetWindowLongPtrW (infoPtr->hwndSelf, 0, 0); - return 0; -} - - -static LRESULT -TRACKBAR_KillFocus (TRACKBAR_INFO *infoPtr, HWND hwndGetFocus) -{ - TRACE("\n"); - infoPtr->bFocussed = FALSE; - TRACKBAR_InvalidateAll(infoPtr); - - return 0; -} - -static LRESULT -TRACKBAR_LButtonDown (TRACKBAR_INFO *infoPtr, DWORD fwKeys, INT x, INT y) -{ - POINT clickPoint; - - clickPoint.x = x; - clickPoint.y = y; - - SetFocus(infoPtr->hwndSelf); - - if (PtInRect(&infoPtr->rcThumb, clickPoint)) { - infoPtr->flags |= TB_DRAG_MODE; - SetCapture (infoPtr->hwndSelf); - TRACKBAR_UpdateToolTip (infoPtr); - TRACKBAR_ActivateToolTip (infoPtr, TRUE); - TRACKBAR_InvalidateThumb(infoPtr, infoPtr->lPos); - } else { - LONG dir = TRACKBAR_GetAutoPageDirection(infoPtr, clickPoint); - if (dir == 0) return 0; - infoPtr->flags |= (dir < 0) ? TB_AUTO_PAGE_LEFT : TB_AUTO_PAGE_RIGHT; - TRACKBAR_AutoPage (infoPtr, clickPoint); - SetCapture (infoPtr->hwndSelf); - SetTimer(infoPtr->hwndSelf, TB_REFRESH_TIMER, TB_REFRESH_DELAY, 0); - } - - return 0; -} - - -static LRESULT -TRACKBAR_LButtonUp (TRACKBAR_INFO *infoPtr, DWORD fwKeys, INT x, INT y) -{ - if (infoPtr->flags & TB_DRAG_MODE) { - notify_with_scroll (infoPtr, TB_THUMBPOSITION | (infoPtr->lPos<<16)); - notify_with_scroll (infoPtr, TB_ENDTRACK); - infoPtr->flags &= ~TB_DRAG_MODE; - ReleaseCapture (); - notify(infoPtr, NM_RELEASEDCAPTURE); - TRACKBAR_ActivateToolTip(infoPtr, FALSE); - TRACKBAR_InvalidateThumb(infoPtr, infoPtr->lPos); - } - if (infoPtr->flags & TB_AUTO_PAGE) { - KillTimer (infoPtr->hwndSelf, TB_REFRESH_TIMER); - infoPtr->flags &= ~TB_AUTO_PAGE; - notify_with_scroll (infoPtr, TB_ENDTRACK); - ReleaseCapture (); - notify(infoPtr, NM_RELEASEDCAPTURE); - } - - return 0; -} - - -static LRESULT -TRACKBAR_CaptureChanged (TRACKBAR_INFO *infoPtr) -{ - notify_with_scroll (infoPtr, TB_ENDTRACK); - return 0; -} - - -static LRESULT -TRACKBAR_Paint (TRACKBAR_INFO *infoPtr, HDC hdc) -{ - if (hdc) { - TRACKBAR_Refresh(infoPtr, hdc); - } else { - PAINTSTRUCT ps; - hdc = BeginPaint (infoPtr->hwndSelf, &ps); - TRACKBAR_Refresh (infoPtr, hdc); - EndPaint (infoPtr->hwndSelf, &ps); - } - - return 0; -} - - -static LRESULT -TRACKBAR_SetFocus (TRACKBAR_INFO *infoPtr, HWND hwndLoseFocus) -{ - TRACE("\n"); - infoPtr->bFocussed = TRUE; - TRACKBAR_InvalidateAll(infoPtr); - - return 0; -} - - -static LRESULT -TRACKBAR_Size (TRACKBAR_INFO *infoPtr, DWORD fwSizeType, INT nWidth, INT nHeight) -{ - TRACKBAR_InitializeThumb (infoPtr); - TRACKBAR_AlignBuddies (infoPtr); - - return 0; -} - - -static LRESULT -TRACKBAR_Timer (TRACKBAR_INFO *infoPtr, INT wTimerID, TIMERPROC *tmrpc) -{ - if (infoPtr->flags & TB_AUTO_PAGE) { - POINT pt; - if (GetCursorPos(&pt)) - if (ScreenToClient(infoPtr->hwndSelf, &pt)) - TRACKBAR_AutoPage(infoPtr, pt); - } - return 0; -} - - -static LRESULT -TRACKBAR_MouseMove (TRACKBAR_INFO *infoPtr, DWORD fwKeys, INT x, INT y) -{ - DWORD dwStyle = GetWindowLongW (infoPtr->hwndSelf, GWL_STYLE); - INT clickPlace = (dwStyle & TBS_VERT) ? y : x; - LONG dragPos, oldPos = infoPtr->lPos; - - TRACE("(x=%d. y=%d)\n", x, y); - - if (infoPtr->flags & TB_AUTO_PAGE) { - POINT pt; - pt.x = x; - pt.y = y; - TRACKBAR_AutoPage (infoPtr, pt); - return TRUE; - } - - if (!(infoPtr->flags & TB_DRAG_MODE)) return TRUE; - - dragPos = TRACKBAR_ConvertPlaceToPosition (infoPtr, clickPlace, - dwStyle & TBS_VERT); - if (dragPos == oldPos) return TRUE; - - infoPtr->lPos = dragPos; - - infoPtr->flags |= TB_THUMBPOSCHANGED; - notify_with_scroll (infoPtr, TB_THUMBTRACK | (infoPtr->lPos<<16)); - - - TRACKBAR_InvalidateThumbMove(infoPtr, oldPos, dragPos); - UpdateWindow (infoPtr->hwndSelf); - - return TRUE; -} - -static BOOL -TRACKBAR_KeyDown (TRACKBAR_INFO *infoPtr, INT nVirtKey, DWORD lKeyData) -{ - DWORD style = GetWindowLongW (infoPtr->hwndSelf, GWL_STYLE); - BOOL downIsLeft = style & TBS_DOWNISLEFT; - BOOL vert = style & TBS_VERT; - LONG pos = infoPtr->lPos; - - TRACE("%x\n", nVirtKey); - - switch (nVirtKey) { - case VK_UP: - if (!vert && downIsLeft) TRACKBAR_LineDown(infoPtr); - else TRACKBAR_LineUp(infoPtr); - break; - case VK_LEFT: - if (vert && downIsLeft) TRACKBAR_LineDown(infoPtr); - else TRACKBAR_LineUp(infoPtr); - break; - case VK_DOWN: - if (!vert && downIsLeft) TRACKBAR_LineUp(infoPtr); - else TRACKBAR_LineDown(infoPtr); - break; - case VK_RIGHT: - if (vert && downIsLeft) TRACKBAR_LineUp(infoPtr); - else TRACKBAR_LineDown(infoPtr); - break; - case VK_NEXT: - if (!vert && downIsLeft) TRACKBAR_PageUp(infoPtr); - else TRACKBAR_PageDown(infoPtr); - break; - case VK_PRIOR: - if (!vert && downIsLeft) TRACKBAR_PageDown(infoPtr); - else TRACKBAR_PageUp(infoPtr); - break; - case VK_HOME: - if (infoPtr->lPos == infoPtr->lRangeMin) return FALSE; - infoPtr->lPos = infoPtr->lRangeMin; - notify_with_scroll (infoPtr, TB_TOP); - break; - case VK_END: - if (infoPtr->lPos == infoPtr->lRangeMax) return FALSE; - infoPtr->lPos = infoPtr->lRangeMax; - notify_with_scroll (infoPtr, TB_BOTTOM); - break; - } - - if (pos != infoPtr->lPos) { - infoPtr->flags |=TB_THUMBPOSCHANGED; - TRACKBAR_InvalidateThumbMove (infoPtr, pos, infoPtr->lPos); - } - - return TRUE; -} - - -static BOOL inline -TRACKBAR_KeyUp (TRACKBAR_INFO *infoPtr, INT nVirtKey, DWORD lKeyData) -{ - switch (nVirtKey) { - case VK_LEFT: - case VK_UP: - case VK_RIGHT: - case VK_DOWN: - case VK_NEXT: - case VK_PRIOR: - case VK_HOME: - case VK_END: - notify_with_scroll (infoPtr, TB_ENDTRACK); - } - return TRUE; -} - - -static LRESULT WINAPI -TRACKBAR_WindowProc (HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam) -{ - TRACKBAR_INFO *infoPtr = (TRACKBAR_INFO *)GetWindowLongPtrW (hwnd, 0); - - TRACE("hwnd=%p msg=%x wparam=%x lparam=%lx\n", hwnd, uMsg, wParam, lParam); - - if (!infoPtr && (uMsg != WM_CREATE)) - return DefWindowProcW (hwnd, uMsg, wParam, lParam); - - switch (uMsg) - { - case TBM_CLEARSEL: - return TRACKBAR_ClearSel (infoPtr, (BOOL)wParam); - - case TBM_CLEARTICS: - return TRACKBAR_ClearTics (infoPtr, (BOOL)wParam); - - case TBM_GETBUDDY: - return (LRESULT)(wParam ? infoPtr->hwndBuddyLA : infoPtr->hwndBuddyRB); - - case TBM_GETCHANNELRECT: - return TRACKBAR_GetChannelRect (infoPtr, (LPRECT)lParam); - - case TBM_GETLINESIZE: - return infoPtr->lLineSize; - - case TBM_GETNUMTICS: - return TRACKBAR_GetNumTics (infoPtr); - - case TBM_GETPAGESIZE: - return infoPtr->lPageSize; - - case TBM_GETPOS: - return infoPtr->lPos; - - case TBM_GETPTICS: - return (LRESULT)infoPtr->tics; - - case TBM_GETRANGEMAX: - return infoPtr->lRangeMax; - - case TBM_GETRANGEMIN: - return infoPtr->lRangeMin; - - case TBM_GETSELEND: - return infoPtr->lSelMax; - - case TBM_GETSELSTART: - return infoPtr->lSelMin; - - case TBM_GETTHUMBLENGTH: - return infoPtr->uThumbLen; - - case TBM_GETTHUMBRECT: - return CopyRect((LPRECT)lParam, &infoPtr->rcThumb); - - case TBM_GETTIC: - return TRACKBAR_GetTic (infoPtr, (INT)wParam); - - case TBM_GETTICPOS: - return TRACKBAR_GetTicPos (infoPtr, (INT)wParam); - - case TBM_GETTOOLTIPS: - return (LRESULT)infoPtr->hwndToolTip; - - case TBM_GETUNICODEFORMAT: - return infoPtr->bUnicode; - - case TBM_SETBUDDY: - return (LRESULT) TRACKBAR_SetBuddy(infoPtr, (BOOL)wParam, (HWND)lParam); - - case TBM_SETLINESIZE: - return TRACKBAR_SetLineSize (infoPtr, (LONG)lParam); - - case TBM_SETPAGESIZE: - return TRACKBAR_SetPageSize (infoPtr, (LONG)lParam); - - case TBM_SETPOS: - return TRACKBAR_SetPos (infoPtr, (BOOL)wParam, (LONG)lParam); - - case TBM_SETRANGE: - return TRACKBAR_SetRange (infoPtr, (BOOL)wParam, (LONG)lParam); - - case TBM_SETRANGEMAX: - return TRACKBAR_SetRangeMax (infoPtr, (BOOL)wParam, (LONG)lParam); - - case TBM_SETRANGEMIN: - return TRACKBAR_SetRangeMin (infoPtr, (BOOL)wParam, (LONG)lParam); - - case TBM_SETSEL: - return TRACKBAR_SetSel (infoPtr, (BOOL)wParam, (LONG)lParam); - - case TBM_SETSELEND: - return TRACKBAR_SetSelEnd (infoPtr, (BOOL)wParam, (LONG)lParam); - - case TBM_SETSELSTART: - return TRACKBAR_SetSelStart (infoPtr, (BOOL)wParam, (LONG)lParam); - - case TBM_SETTHUMBLENGTH: - return TRACKBAR_SetThumbLength (infoPtr, (UINT)wParam); - - case TBM_SETTIC: - return TRACKBAR_SetTic (infoPtr, (LONG)lParam); - - case TBM_SETTICFREQ: - return TRACKBAR_SetTicFreq (infoPtr, (WORD)wParam); - - case TBM_SETTIPSIDE: - return TRACKBAR_SetTipSide (infoPtr, (INT)wParam); - - case TBM_SETTOOLTIPS: - return TRACKBAR_SetToolTips (infoPtr, (HWND)wParam); - - case TBM_SETUNICODEFORMAT: - return TRACKBAR_SetUnicodeFormat (infoPtr, (BOOL)wParam); - - - case WM_CAPTURECHANGED: - return TRACKBAR_CaptureChanged (infoPtr); - - case WM_CREATE: - return TRACKBAR_Create (hwnd, (LPCREATESTRUCTW)lParam); - - case WM_DESTROY: - return TRACKBAR_Destroy (infoPtr); - -/* case WM_ENABLE: */ - - case WM_ERASEBKGND: - return 0; - - case WM_GETDLGCODE: - return DLGC_WANTARROWS; - - case WM_KEYDOWN: - return TRACKBAR_KeyDown (infoPtr, (INT)wParam, (DWORD)lParam); - - case WM_KEYUP: - return TRACKBAR_KeyUp (infoPtr, (INT)wParam, (DWORD)lParam); - - case WM_KILLFOCUS: - return TRACKBAR_KillFocus (infoPtr, (HWND)wParam); - - case WM_LBUTTONDOWN: - return TRACKBAR_LButtonDown (infoPtr, wParam, (SHORT)LOWORD(lParam), (SHORT)HIWORD(lParam)); - - case WM_LBUTTONUP: - return TRACKBAR_LButtonUp (infoPtr, wParam, (SHORT)LOWORD(lParam), (SHORT)HIWORD(lParam)); - - case WM_MOUSEMOVE: - return TRACKBAR_MouseMove (infoPtr, wParam, (SHORT)LOWORD(lParam), (SHORT)HIWORD(lParam)); - - case WM_PAINT: - return TRACKBAR_Paint (infoPtr, (HDC)wParam); - - case WM_SETFOCUS: - return TRACKBAR_SetFocus (infoPtr, (HWND)wParam); - - case WM_SIZE: - return TRACKBAR_Size (infoPtr, wParam, LOWORD(lParam), HIWORD(lParam)); - - case WM_TIMER: - return TRACKBAR_Timer (infoPtr, (INT)wParam, (TIMERPROC *)lParam); - - case WM_WININICHANGE: - return TRACKBAR_InitializeThumb (infoPtr); - - default: - if ((uMsg >= WM_USER) && (uMsg < WM_APP)) - ERR("unknown msg %04x wp=%08x lp=%08lx\n", uMsg, wParam, lParam); - return DefWindowProcW (hwnd, uMsg, wParam, lParam); - } - return 0; -} - - -void TRACKBAR_Register (void) -{ - WNDCLASSW wndClass; - - ZeroMemory (&wndClass, sizeof(WNDCLASSW)); - wndClass.style = CS_GLOBALCLASS; - wndClass.lpfnWndProc = TRACKBAR_WindowProc; - wndClass.cbClsExtra = 0; - wndClass.cbWndExtra = sizeof(TRACKBAR_INFO *); - wndClass.hCursor = LoadCursorW (0, (LPWSTR)IDC_ARROW); - wndClass.hbrBackground = (HBRUSH)(COLOR_BTNFACE + 1); - wndClass.lpszClassName = TRACKBAR_CLASSW; - - RegisterClassW (&wndClass); -} - - -void TRACKBAR_Unregister (void) -{ - UnregisterClassW (TRACKBAR_CLASSW, NULL); -} diff --git a/reactos/lib/comctl32/treeview.c b/reactos/lib/comctl32/treeview.c deleted file mode 100644 index af6ca487512..00000000000 --- a/reactos/lib/comctl32/treeview.c +++ /dev/null @@ -1,5518 +0,0 @@ -/* Treeview control - * - * Copyright 1998 Eric Kohl - * Copyright 1998,1999 Alex Priem - * Copyright 1999 Sylvain St-Germain - * Copyright 2002 CodeWeavers, Aric Stewart - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2.1 of the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - * - * Note that TREEVIEW_INFO * and HTREEITEM are the same thing. - * - * Note2: All items always! have valid (allocated) pszText field. - * If item's text == LPSTR_TEXTCALLBACKA we allocate buffer - * of size TEXT_CALLBACK_SIZE in DoSetItem. - * We use callbackMask to keep track of fields to be updated. - * - * TODO: - * missing notifications: NM_SETCURSOR, TVN_GETINFOTIP, TVN_KEYDOWN, - * TVN_SETDISPINFO, TVN_SINGLEEXPAND - * - * missing styles: TVS_FULLROWSELECT, TVS_INFOTIP, TVS_RTLREADING, - * TVS_TRACKSELECT - * - * missing item styles: TVIS_CUT, TVIS_EXPANDPARTIAL - * - * Make the insertion mark look right. - * Scroll (instead of repaint) as much as possible. - */ - -#include "config.h" -#include "wine/port.h" - -#include -#include -#include -#include -#include -#include - -#define NONAMELESSUNION -#define NONAMELESSSTRUCT -#include "windef.h" -#include "winbase.h" -#include "wingdi.h" -#include "winuser.h" -#include "winnls.h" -#include "commctrl.h" -#include "comctl32.h" -#include "wine/unicode.h" -#include "wine/debug.h" - -/* internal structures */ - -typedef struct _TREEITEM /* HTREEITEM is a _TREEINFO *. */ -{ - UINT callbackMask; - UINT state; - UINT stateMask; - LPWSTR pszText; - int cchTextMax; - int iImage; - int iSelectedImage; - int cChildren; - LPARAM lParam; - int iIntegral; /* item height multiplier (1 is normal) */ - int iLevel; /* indentation level:0=root level */ - HTREEITEM parent; /* handle to parent or 0 if at root */ - HTREEITEM firstChild; /* handle to first child or 0 if no child */ - HTREEITEM lastChild; - HTREEITEM prevSibling; /* handle to prev item in list, 0 if first */ - HTREEITEM nextSibling; /* handle to next item in list, 0 if last */ - RECT rect; - LONG linesOffset; - LONG stateOffset; - LONG imageOffset; - LONG textOffset; - LONG textWidth; /* horizontal text extent for pszText */ - LONG visibleOrder; /* visible ordering, 0 is first visible item */ -} TREEVIEW_ITEM; - - -typedef struct tagTREEVIEW_INFO -{ - HWND hwnd; - HWND hwndNotify; /* Owner window to send notifications to */ - DWORD dwStyle; - HTREEITEM root; - UINT uInternalStatus; - INT Timer; - UINT uNumItems; /* number of valid TREEVIEW_ITEMs */ - INT cdmode; /* last custom draw setting */ - UINT uScrollTime; /* max. time for scrolling in milliseconds */ - BOOL bRedraw; /* if FALSE we validate but don't redraw in TREEVIEW_Paint() */ - - UINT uItemHeight; /* item height */ - BOOL bHeightSet; - - LONG clientWidth; /* width of control window */ - LONG clientHeight; /* height of control window */ - - LONG treeWidth; /* width of visible tree items */ - LONG treeHeight; /* height of visible tree items */ - - UINT uIndent; /* indentation in pixels */ - HTREEITEM selectedItem; /* handle to selected item or 0 if none */ - HTREEITEM hotItem; /* handle currently under cursor, 0 if none */ - HTREEITEM focusedItem; /* item that was under the cursor when WM_LBUTTONDOWN was received */ - - HTREEITEM firstVisible; /* handle to first visible item */ - LONG maxVisibleOrder; - HTREEITEM dropItem; /* handle to item selected by drag cursor */ - HTREEITEM insertMarkItem; /* item after which insertion mark is placed */ - BOOL insertBeforeorAfter; /* flag used by TVM_SETINSERTMARK */ - HIMAGELIST dragList; /* Bitmap of dragged item */ - LONG scrollX; - COLORREF clrBk; - COLORREF clrText; - COLORREF clrLine; - COLORREF clrInsertMark; - HFONT hFont; - HFONT hDefaultFont; - HFONT hBoldFont; - HWND hwndToolTip; - - HWND hwndEdit; - WNDPROC wpEditOrig; /* orig window proc for subclassing edit */ - BOOL bIgnoreEditKillFocus; - BOOL bLabelChanged; - - BOOL bNtfUnicode; /* TRUE if should send NOTIFY with W */ - HIMAGELIST himlNormal; - int normalImageHeight; - int normalImageWidth; - HIMAGELIST himlState; - int stateImageHeight; - int stateImageWidth; - HDPA items; - - DWORD lastKeyPressTimestamp; /* Added */ - WPARAM charCode; /* Added */ - INT nSearchParamLength; /* Added */ - WCHAR szSearchParam[ MAX_PATH ]; /* Added */ -} TREEVIEW_INFO; - - -/******** Defines that TREEVIEW_ProcessLetterKeys uses ****************/ -#define KEY_DELAY 450 - -/* bitflags for infoPtr->uInternalStatus */ - -#define TV_HSCROLL 0x01 /* treeview too large to fit in window */ -#define TV_VSCROLL 0x02 /* (horizontal/vertical) */ -#define TV_LDRAG 0x04 /* Lbutton pushed to start drag */ -#define TV_LDRAGGING 0x08 /* Lbutton pushed, mouse moved. */ -#define TV_RDRAG 0x10 /* dito Rbutton */ -#define TV_RDRAGGING 0x20 - -/* bitflags for infoPtr->timer */ - -#define TV_EDIT_TIMER 2 -#define TV_EDIT_TIMER_SET 2 - - -VOID TREEVIEW_Register (VOID); -VOID TREEVIEW_Unregister (VOID); - - -WINE_DEFAULT_DEBUG_CHANNEL(treeview); - - -#define TEXT_CALLBACK_SIZE 260 - -#define TREEVIEW_LEFT_MARGIN 8 - -#define MINIMUM_INDENT 19 - -#define CALLBACK_MASK_ALL (TVIF_TEXT|TVIF_CHILDREN|TVIF_IMAGE|TVIF_SELECTEDIMAGE) - -#define STATEIMAGEINDEX(x) (((x) >> 12) & 0x0f) -#define OVERLAYIMAGEINDEX(x) (((x) >> 8) & 0x0f) -#define ISVISIBLE(x) ((x)->visibleOrder >= 0) - - -typedef VOID (*TREEVIEW_ItemEnumFunc)(TREEVIEW_INFO *, TREEVIEW_ITEM *,LPVOID); - - -static VOID TREEVIEW_Invalidate(TREEVIEW_INFO *, TREEVIEW_ITEM *); - -static LRESULT TREEVIEW_DoSelectItem(TREEVIEW_INFO *, INT, HTREEITEM, INT); -static VOID TREEVIEW_SetFirstVisible(TREEVIEW_INFO *, TREEVIEW_ITEM *, BOOL); -static LRESULT TREEVIEW_EnsureVisible(TREEVIEW_INFO *, HTREEITEM, BOOL); -static LRESULT TREEVIEW_RButtonUp(TREEVIEW_INFO *, LPPOINT); -static LRESULT TREEVIEW_EndEditLabelNow(TREEVIEW_INFO *infoPtr, BOOL bCancel); -static VOID TREEVIEW_UpdateScrollBars(TREEVIEW_INFO *infoPtr); -static LRESULT TREEVIEW_HScroll(TREEVIEW_INFO *, WPARAM); -static INT TREEVIEW_NotifyFormat (TREEVIEW_INFO *infoPtr, HWND wParam, UINT lParam); - - -/* Random Utilities *****************************************************/ - -#ifndef NDEBUG -static inline void -TREEVIEW_VerifyTree(TREEVIEW_INFO *infoPtr) -{ - (void)infoPtr; -} -#else -/* The definition is at the end of the file. */ -static void TREEVIEW_VerifyTree(TREEVIEW_INFO *infoPtr); -#endif - -/* Returns the treeview private data if hwnd is a treeview. - * Otherwise returns an undefined value. */ -static TREEVIEW_INFO * -TREEVIEW_GetInfoPtr(HWND hwnd) -{ - return (TREEVIEW_INFO *)GetWindowLongPtrW(hwnd, 0); -} - -/* Don't call this. Nothing wants an item index. */ -static inline int -TREEVIEW_GetItemIndex(TREEVIEW_INFO *infoPtr, HTREEITEM handle) -{ - assert(infoPtr != NULL); - - return DPA_GetPtrIndex(infoPtr->items, handle); -} - -/*************************************************************************** - * This method checks that handle is an item for this tree. - */ -static BOOL -TREEVIEW_ValidItem(TREEVIEW_INFO *infoPtr, HTREEITEM handle) -{ - if (TREEVIEW_GetItemIndex(infoPtr, handle) == -1) - { - TRACE("invalid item %p\n", handle); - return FALSE; - } - else - return TRUE; -} - -static HFONT -TREEVIEW_CreateBoldFont(HFONT hOrigFont) -{ - LOGFONTW font; - - GetObjectW(hOrigFont, sizeof(font), &font); - font.lfWeight = FW_BOLD; - return CreateFontIndirectW(&font); -} - -static inline HFONT -TREEVIEW_FontForItem(TREEVIEW_INFO *infoPtr, TREEVIEW_ITEM *item) -{ - return (item->state & TVIS_BOLD) ? infoPtr->hBoldFont : infoPtr->hFont; -} - -/* for trace/debugging purposes only */ -static const char * -TREEVIEW_ItemName(TREEVIEW_ITEM *item) -{ - if (item == NULL) return ""; - if (item->pszText == LPSTR_TEXTCALLBACKW) return ""; - if (item->pszText == NULL) return ""; - return debugstr_w(item->pszText); -} - -/* An item is not a child of itself. */ -static BOOL -TREEVIEW_IsChildOf(TREEVIEW_ITEM *parent, TREEVIEW_ITEM *child) -{ - do - { - child = child->parent; - if (child == parent) return TRUE; - } while (child != NULL); - - return FALSE; -} - - -/* Tree Traversal *******************************************************/ - -/*************************************************************************** - * This method returns the last expanded sibling or child child item - * of a tree node - */ -static TREEVIEW_ITEM * -TREEVIEW_GetLastListItem(TREEVIEW_INFO *infoPtr, TREEVIEW_ITEM *wineItem) -{ - if (!wineItem) - return NULL; - - while (wineItem->lastChild) - { - if (wineItem->state & TVIS_EXPANDED) - wineItem = wineItem->lastChild; - else - break; - } - - if (wineItem == infoPtr->root) - return NULL; - - return wineItem; -} - -/*************************************************************************** - * This method returns the previous non-hidden item in the list not - * considering the tree hierarchy. - */ -static TREEVIEW_ITEM * -TREEVIEW_GetPrevListItem(TREEVIEW_INFO *infoPtr, TREEVIEW_ITEM *tvItem) -{ - if (tvItem->prevSibling) - { - /* This item has a prevSibling, get the last item in the sibling's tree. */ - TREEVIEW_ITEM *upItem = tvItem->prevSibling; - - if ((upItem->state & TVIS_EXPANDED) && upItem->lastChild != NULL) - return TREEVIEW_GetLastListItem(infoPtr, upItem->lastChild); - else - return upItem; - } - else - { - /* this item does not have a prevSibling, get the parent */ - return (tvItem->parent != infoPtr->root) ? tvItem->parent : NULL; - } -} - - -/*************************************************************************** - * This method returns the next physical item in the treeview not - * considering the tree hierarchy. - */ -static TREEVIEW_ITEM * -TREEVIEW_GetNextListItem(TREEVIEW_INFO *infoPtr, TREEVIEW_ITEM *tvItem) -{ - assert(tvItem != NULL); - - /* - * If this item has children and is expanded, return the first child - */ - if ((tvItem->state & TVIS_EXPANDED) && tvItem->firstChild != NULL) - { - return tvItem->firstChild; - } - - - /* - * try to get the sibling - */ - if (tvItem->nextSibling) - return tvItem->nextSibling; - - /* - * Otherwise, get the parent's sibling. - */ - while (tvItem->parent) - { - tvItem = tvItem->parent; - - if (tvItem->nextSibling) - return tvItem->nextSibling; - } - - return NULL; -} - -/*************************************************************************** - * This method returns the nth item starting at the given item. It returns - * the last item (or first) we we run out of items. - * - * Will scroll backward if count is <0. - * forward if count is >0. - */ -static TREEVIEW_ITEM * -TREEVIEW_GetListItem(TREEVIEW_INFO *infoPtr, TREEVIEW_ITEM *wineItem, - LONG count) -{ - TREEVIEW_ITEM *(*next_item)(TREEVIEW_INFO *, TREEVIEW_ITEM *); - TREEVIEW_ITEM *previousItem; - - assert(wineItem != NULL); - - if (count > 0) - { - next_item = TREEVIEW_GetNextListItem; - } - else if (count < 0) - { - count = -count; - next_item = TREEVIEW_GetPrevListItem; - } - else - return wineItem; - - do - { - previousItem = wineItem; - wineItem = next_item(infoPtr, wineItem); - - } while (--count && wineItem != NULL); - - - return wineItem ? wineItem : previousItem; -} - -/* Notifications ************************************************************/ - -static INT get_notifycode(TREEVIEW_INFO *infoPtr, INT code) -{ - if (!infoPtr->bNtfUnicode) { - switch (code) { - case TVN_SELCHANGINGW: return TVN_SELCHANGINGA; - case TVN_SELCHANGEDW: return TVN_SELCHANGEDA; - case TVN_GETDISPINFOW: return TVN_GETDISPINFOA; - case TVN_SETDISPINFOW: return TVN_SETDISPINFOA; - case TVN_ITEMEXPANDINGW: return TVN_ITEMEXPANDINGA; - case TVN_ITEMEXPANDEDW: return TVN_ITEMEXPANDEDA; - case TVN_BEGINDRAGW: return TVN_BEGINDRAGA; - case TVN_BEGINRDRAGW: return TVN_BEGINRDRAGA; - case TVN_DELETEITEMW: return TVN_DELETEITEMA; - case TVN_BEGINLABELEDITW: return TVN_BEGINLABELEDITA; - case TVN_ENDLABELEDITW: return TVN_ENDLABELEDITA; - case TVN_GETINFOTIPW: return TVN_GETINFOTIPA; - } - } - return code; -} - -static LRESULT -TREEVIEW_SendRealNotify(TREEVIEW_INFO *infoPtr, WPARAM wParam, LPARAM lParam) -{ - TRACE("wParam=%d, lParam=%ld\n", wParam, lParam); - return SendMessageW(infoPtr->hwndNotify, WM_NOTIFY, wParam, lParam); -} - -static BOOL -TREEVIEW_SendSimpleNotify(TREEVIEW_INFO *infoPtr, UINT code) -{ - NMHDR nmhdr; - HWND hwnd = infoPtr->hwnd; - - TRACE("%d\n", code); - nmhdr.hwndFrom = hwnd; - nmhdr.idFrom = GetWindowLongPtrW(hwnd, GWLP_ID); - nmhdr.code = get_notifycode(infoPtr, code); - - return (BOOL)TREEVIEW_SendRealNotify(infoPtr, - (WPARAM)nmhdr.idFrom, (LPARAM)&nmhdr); -} - -static VOID -TREEVIEW_TVItemFromItem(TREEVIEW_INFO *infoPtr, UINT mask, TVITEMW *tvItem, TREEVIEW_ITEM *item) -{ - tvItem->mask = mask; - tvItem->hItem = item; - tvItem->state = item->state; - tvItem->stateMask = 0; - tvItem->iImage = item->iImage; - tvItem->iImage = item->iImage; - tvItem->iSelectedImage = item->iSelectedImage; - tvItem->cChildren = item->cChildren; - tvItem->lParam = item->lParam; - - if(mask & TVIF_TEXT) - { - if (!infoPtr->bNtfUnicode) - { - tvItem->cchTextMax = WideCharToMultiByte( CP_ACP, 0, item->pszText, -1, NULL, 0, NULL, NULL ); - tvItem->pszText = Alloc (tvItem->cchTextMax); - WideCharToMultiByte( CP_ACP, 0, item->pszText, -1, (LPSTR)tvItem->pszText, tvItem->cchTextMax, 0, 0 ); - } - else - { - tvItem->cchTextMax = item->cchTextMax; - tvItem->pszText = item->pszText; - } - } - else - { - tvItem->cchTextMax = 0; - tvItem->pszText = NULL; - } -} - -static BOOL -TREEVIEW_SendTreeviewNotify(TREEVIEW_INFO *infoPtr, UINT code, UINT action, - UINT mask, HTREEITEM oldItem, HTREEITEM newItem) -{ - HWND hwnd = infoPtr->hwnd; - NMTREEVIEWW nmhdr; - BOOL ret; - - TRACE("code:%d action:%x olditem:%p newitem:%p\n", - code, action, oldItem, newItem); - - ZeroMemory(&nmhdr, sizeof(NMTREEVIEWA)); - - nmhdr.hdr.hwndFrom = hwnd; - nmhdr.hdr.idFrom = GetWindowLongPtrW(hwnd, GWLP_ID); - nmhdr.hdr.code = get_notifycode(infoPtr, code); - nmhdr.action = action; - - if (oldItem) - TREEVIEW_TVItemFromItem(infoPtr, mask, &nmhdr.itemOld, oldItem); - - if (newItem) - TREEVIEW_TVItemFromItem(infoPtr, mask, &nmhdr.itemNew, newItem); - - nmhdr.ptDrag.x = 0; - nmhdr.ptDrag.y = 0; - - ret = (BOOL)TREEVIEW_SendRealNotify(infoPtr, - (WPARAM)nmhdr.hdr.idFrom, - (LPARAM)&nmhdr); - if (!infoPtr->bNtfUnicode) - { - Free(nmhdr.itemOld.pszText); - Free(nmhdr.itemNew.pszText); - } - return ret; -} - -static BOOL -TREEVIEW_SendTreeviewDnDNotify(TREEVIEW_INFO *infoPtr, UINT code, - HTREEITEM dragItem, POINT pt) -{ - HWND hwnd = infoPtr->hwnd; - NMTREEVIEWW nmhdr; - - TRACE("code:%d dragitem:%p\n", code, dragItem); - - nmhdr.hdr.hwndFrom = hwnd; - nmhdr.hdr.idFrom = GetWindowLongPtrW(hwnd, GWLP_ID); - nmhdr.hdr.code = get_notifycode(infoPtr, code); - nmhdr.action = 0; - nmhdr.itemNew.mask = TVIF_STATE | TVIF_PARAM | TVIF_HANDLE; - nmhdr.itemNew.hItem = dragItem; - nmhdr.itemNew.state = dragItem->state; - nmhdr.itemNew.lParam = dragItem->lParam; - - nmhdr.ptDrag.x = pt.x; - nmhdr.ptDrag.y = pt.y; - - return (BOOL)TREEVIEW_SendRealNotify(infoPtr, - (WPARAM)nmhdr.hdr.idFrom, - (LPARAM)&nmhdr); -} - - -static BOOL -TREEVIEW_SendCustomDrawNotify(TREEVIEW_INFO *infoPtr, DWORD dwDrawStage, - HDC hdc, RECT rc) -{ - HWND hwnd = infoPtr->hwnd; - NMTVCUSTOMDRAW nmcdhdr; - LPNMCUSTOMDRAW nmcd; - - TRACE("drawstage:%lx hdc:%p\n", dwDrawStage, hdc); - - nmcd = &nmcdhdr.nmcd; - nmcd->hdr.hwndFrom = hwnd; - nmcd->hdr.idFrom = GetWindowLongPtrW(hwnd, GWLP_ID); - nmcd->hdr.code = NM_CUSTOMDRAW; - nmcd->dwDrawStage = dwDrawStage; - nmcd->hdc = hdc; - nmcd->rc = rc; - nmcd->dwItemSpec = 0; - nmcd->uItemState = 0; - nmcd->lItemlParam = 0; - nmcdhdr.clrText = infoPtr->clrText; - nmcdhdr.clrTextBk = infoPtr->clrBk; - nmcdhdr.iLevel = 0; - - return (BOOL)TREEVIEW_SendRealNotify(infoPtr, - (WPARAM)nmcd->hdr.idFrom, - (LPARAM)&nmcdhdr); -} - - - -/* FIXME: need to find out when the flags in uItemState need to be set */ - -static BOOL -TREEVIEW_SendCustomDrawItemNotify(TREEVIEW_INFO *infoPtr, HDC hdc, - TREEVIEW_ITEM *wineItem, UINT uItemDrawState) -{ - HWND hwnd = infoPtr->hwnd; - NMTVCUSTOMDRAW nmcdhdr; - LPNMCUSTOMDRAW nmcd; - DWORD dwDrawStage, dwItemSpec; - UINT uItemState; - INT retval; - - dwDrawStage = CDDS_ITEM | uItemDrawState; - dwItemSpec = (DWORD)wineItem; - uItemState = 0; - if (wineItem->state & TVIS_SELECTED) - uItemState |= CDIS_SELECTED; - if (wineItem == infoPtr->selectedItem) - uItemState |= CDIS_FOCUS; - if (wineItem == infoPtr->hotItem) - uItemState |= CDIS_HOT; - - nmcd = &nmcdhdr.nmcd; - nmcd->hdr.hwndFrom = hwnd; - nmcd->hdr.idFrom = GetWindowLongPtrW(hwnd, GWLP_ID); - nmcd->hdr.code = NM_CUSTOMDRAW; - nmcd->dwDrawStage = dwDrawStage; - nmcd->hdc = hdc; - nmcd->rc = wineItem->rect; - nmcd->dwItemSpec = dwItemSpec; - nmcd->uItemState = uItemState; - nmcd->lItemlParam = wineItem->lParam; - nmcdhdr.clrText = infoPtr->clrText; - nmcdhdr.clrTextBk = infoPtr->clrBk; - nmcdhdr.iLevel = wineItem->iLevel; - - TRACE("drawstage:%lx hdc:%p item:%lx, itemstate:%x, lItemlParam:%lx\n", - nmcd->dwDrawStage, nmcd->hdc, nmcd->dwItemSpec, - nmcd->uItemState, nmcd->lItemlParam); - - retval = TREEVIEW_SendRealNotify(infoPtr, - (WPARAM)nmcd->hdr.idFrom, - (LPARAM)&nmcdhdr); - - infoPtr->clrText = nmcdhdr.clrText; - infoPtr->clrBk = nmcdhdr.clrTextBk; - return (BOOL)retval; -} - -static BOOL -TREEVIEW_BeginLabelEditNotify(TREEVIEW_INFO *infoPtr, TREEVIEW_ITEM *editItem) -{ - HWND hwnd = infoPtr->hwnd; - NMTVDISPINFOW tvdi; - BOOL ret; - - tvdi.hdr.hwndFrom = hwnd; - tvdi.hdr.idFrom = GetWindowLongPtrW(hwnd, GWLP_ID); - tvdi.hdr.code = get_notifycode(infoPtr, TVN_BEGINLABELEDITW); - - TREEVIEW_TVItemFromItem(infoPtr, TVIF_HANDLE | TVIF_STATE | TVIF_PARAM | TVIF_TEXT, - &tvdi.item, editItem); - - ret = (BOOL)TREEVIEW_SendRealNotify(infoPtr, tvdi.hdr.idFrom, (LPARAM)&tvdi); - - if (!infoPtr->bNtfUnicode) - Free(tvdi.item.pszText); - - return ret; -} - -static void -TREEVIEW_UpdateDispInfo(TREEVIEW_INFO *infoPtr, TREEVIEW_ITEM *wineItem, - UINT mask) -{ - NMTVDISPINFOW callback; - HWND hwnd = infoPtr->hwnd; - - TRACE("mask %x callbackMask %x\n", mask, wineItem->callbackMask); - mask &= wineItem->callbackMask; - - if (mask == 0) return; - - callback.hdr.hwndFrom = hwnd; - callback.hdr.idFrom = GetWindowLongPtrW(hwnd, GWLP_ID); - callback.hdr.code = get_notifycode(infoPtr, TVN_GETDISPINFOW); - - /* 'state' always contains valid value, as well as 'lParam'. - * All other parameters are uninitialized. - */ - callback.item.pszText = wineItem->pszText; - callback.item.cchTextMax = wineItem->cchTextMax; - callback.item.mask = mask; - callback.item.hItem = wineItem; - callback.item.state = wineItem->state; - callback.item.lParam = wineItem->lParam; - - /* If text is changed we need to recalculate textWidth */ - if (mask & TVIF_TEXT) - wineItem->textWidth = 0; - - TREEVIEW_SendRealNotify(infoPtr, - (WPARAM)callback.hdr.idFrom, (LPARAM)&callback); - - /* It may have changed due to a call to SetItem. */ - mask &= wineItem->callbackMask; - - if ((mask & TVIF_TEXT) && callback.item.pszText != wineItem->pszText) - { - /* Instead of copying text into our buffer user specified its own */ - if (!infoPtr->bNtfUnicode) { - LPWSTR newText; - int buflen; - int len = MultiByteToWideChar( CP_ACP, 0, - (LPSTR)callback.item.pszText, -1, - NULL, 0); - buflen = max((len)*sizeof(WCHAR), TEXT_CALLBACK_SIZE); - newText = (LPWSTR)ReAlloc(wineItem->pszText, buflen); - - TRACE("returned str %s, len=%d, buflen=%d\n", - debugstr_a((LPSTR)callback.item.pszText), len, buflen); - - if (newText) - { - wineItem->pszText = newText; - MultiByteToWideChar( CP_ACP, 0, - (LPSTR)callback.item.pszText, -1, - wineItem->pszText, buflen); - wineItem->cchTextMax = buflen; - } - /* If ReAlloc fails we have nothing to do, but keep original text */ - } - else { - int len = max(lstrlenW(callback.item.pszText) + 1, - TEXT_CALLBACK_SIZE); - LPWSTR newText = ReAlloc(wineItem->pszText, len); - - TRACE("returned wstr %s, len=%d\n", - debugstr_w(callback.item.pszText), len); - - if (newText) - { - wineItem->pszText = newText; - strcpyW(wineItem->pszText, callback.item.pszText); - wineItem->cchTextMax = len; - } - /* If ReAlloc fails we have nothing to do, but keep original text */ - } - } - else if (mask & TVIF_TEXT) { - /* User put text into our buffer, that is ok unless A string */ - if (!infoPtr->bNtfUnicode) { - LPWSTR newText; - LPWSTR oldText = NULL; - int buflen; - int len = MultiByteToWideChar( CP_ACP, 0, - (LPSTR)callback.item.pszText, -1, - NULL, 0); - buflen = max((len)*sizeof(WCHAR), TEXT_CALLBACK_SIZE); - newText = (LPWSTR)Alloc(buflen); - - TRACE("same buffer str %s, len=%d, buflen=%d\n", - debugstr_a((LPSTR)callback.item.pszText), len, buflen); - - if (newText) - { - oldText = wineItem->pszText; - wineItem->pszText = newText; - MultiByteToWideChar( CP_ACP, 0, - (LPSTR)callback.item.pszText, -1, - wineItem->pszText, buflen); - wineItem->cchTextMax = buflen; - if (oldText) - Free(oldText); - } - } - } - - if (mask & TVIF_IMAGE) - wineItem->iImage = callback.item.iImage; - - if (mask & TVIF_SELECTEDIMAGE) - wineItem->iSelectedImage = callback.item.iSelectedImage; - - if (mask & TVIF_CHILDREN) - wineItem->cChildren = callback.item.cChildren; - - /* These members are now permanently set. */ - if (callback.item.mask & TVIF_DI_SETITEM) - wineItem->callbackMask &= ~callback.item.mask; -} - -/*************************************************************************** - * This function uses cChildren field to decide whether the item has - * children or not. - * Note: if this returns TRUE, the child items may not actually exist, - * they could be virtual. - * - * Just use wineItem->firstChild to check for physical children. - */ -static BOOL -TREEVIEW_HasChildren(TREEVIEW_INFO *infoPtr, TREEVIEW_ITEM *wineItem) -{ - TREEVIEW_UpdateDispInfo(infoPtr, wineItem, TVIF_CHILDREN); - - return wineItem->cChildren > 0; -} - - -/* Item Position ********************************************************/ - -/* Compute linesOffset, stateOffset, imageOffset, textOffset of an item. */ -static VOID -TREEVIEW_ComputeItemInternalMetrics(TREEVIEW_INFO *infoPtr, - TREEVIEW_ITEM *item) -{ - /* Same effect, different optimisation. */ -#if 0 - BOOL lar = ((infoPtr->dwStyle & TVS_LINESATROOT) - && (infoPtr->dwStyle & (TVS_HASLINES|TVS_HASBUTTONS))); -#else - BOOL lar = ((infoPtr->dwStyle - & (TVS_LINESATROOT|TVS_HASLINES|TVS_HASBUTTONS)) - > TVS_LINESATROOT); -#endif - - item->linesOffset = infoPtr->uIndent * (item->iLevel + lar - 1) - - infoPtr->scrollX; - item->stateOffset = item->linesOffset + infoPtr->uIndent; - item->imageOffset = item->stateOffset - + (STATEIMAGEINDEX(item->state) ? infoPtr->stateImageWidth : 0); - item->textOffset = item->imageOffset + infoPtr->normalImageWidth; -} - -static VOID -TREEVIEW_ComputeTextWidth(TREEVIEW_INFO *infoPtr, TREEVIEW_ITEM *item, HDC hDC) -{ - HDC hdc; - HFONT hOldFont=0; - SIZE sz; - - /* DRAW's OM docker creates items like this */ - if (item->pszText == NULL) - { - item->textWidth = 0; - return; - } - - if (hDC != 0) - { - hdc = hDC; - } - else - { - hdc = GetDC(infoPtr->hwnd); - hOldFont = SelectObject(hdc, TREEVIEW_FontForItem(infoPtr, item)); - } - - GetTextExtentPoint32W(hdc, item->pszText, strlenW(item->pszText), &sz); - item->textWidth = sz.cx; - - if (hDC == 0) - { - SelectObject(hdc, hOldFont); - ReleaseDC(0, hdc); - } -} - -static VOID -TREEVIEW_ComputeItemRect(TREEVIEW_INFO *infoPtr, TREEVIEW_ITEM *item) -{ - item->rect.top = infoPtr->uItemHeight * - (item->visibleOrder - infoPtr->firstVisible->visibleOrder); - - item->rect.bottom = item->rect.top - + infoPtr->uItemHeight * item->iIntegral - 1; - - item->rect.left = 0; - item->rect.right = infoPtr->clientWidth; -} - -/* We know that only items after start need their order updated. */ -static void -TREEVIEW_RecalculateVisibleOrder(TREEVIEW_INFO *infoPtr, TREEVIEW_ITEM *start) -{ - TREEVIEW_ITEM *item; - int order; - - if (!start) - { - start = infoPtr->root->firstChild; - order = 0; - } - else - order = start->visibleOrder; - - for (item = start; item != NULL; - item = TREEVIEW_GetNextListItem(infoPtr, item)) - { - item->visibleOrder = order; - order += item->iIntegral; - } - - infoPtr->maxVisibleOrder = order; - - for (item = start; item != NULL; - item = TREEVIEW_GetNextListItem(infoPtr, item)) - { - TREEVIEW_ComputeItemRect(infoPtr, item); - } -} - - -/* Update metrics of all items in selected subtree. - * root must be expanded - */ -static VOID -TREEVIEW_UpdateSubTree(TREEVIEW_INFO *infoPtr, TREEVIEW_ITEM *root) -{ - TREEVIEW_ITEM *sibling; - HDC hdc; - HFONT hOldFont; - - if (!root->firstChild || !(root->state & TVIS_EXPANDED)) - return; - - root->state &= ~TVIS_EXPANDED; - sibling = TREEVIEW_GetNextListItem(infoPtr, root); - root->state |= TVIS_EXPANDED; - - hdc = GetDC(infoPtr->hwnd); - hOldFont = SelectObject(hdc, infoPtr->hFont); - - for (; root != sibling; - root = TREEVIEW_GetNextListItem(infoPtr, root)) - { - TREEVIEW_ComputeItemInternalMetrics(infoPtr, root); - - if (root->callbackMask & TVIF_TEXT) - TREEVIEW_UpdateDispInfo(infoPtr, root, TVIF_TEXT); - - if (root->textWidth == 0) - { - SelectObject(hdc, TREEVIEW_FontForItem(infoPtr, root)); - TREEVIEW_ComputeTextWidth(infoPtr, root, hdc); - } - } - - SelectObject(hdc, hOldFont); - ReleaseDC(infoPtr->hwnd, hdc); -} - -/* Item Allocation **********************************************************/ - -static TREEVIEW_ITEM * -TREEVIEW_AllocateItem(TREEVIEW_INFO *infoPtr) -{ - TREEVIEW_ITEM *newItem = Alloc(sizeof(TREEVIEW_ITEM)); - - if (!newItem) - return NULL; - - if (DPA_InsertPtr(infoPtr->items, INT_MAX, newItem) == -1) - { - Free(newItem); - return NULL; - } - - return newItem; -} - -/* Exact opposite of TREEVIEW_AllocateItem. In particular, it does not - * free item->pszText. */ -static void -TREEVIEW_FreeItem(TREEVIEW_INFO *infoPtr, TREEVIEW_ITEM *item) -{ - DPA_DeletePtr(infoPtr->items, DPA_GetPtrIndex(infoPtr->items, item)); - Free(item); - if (infoPtr->selectedItem == item) - infoPtr->selectedItem = NULL; - if (infoPtr->hotItem == item) - infoPtr->hotItem = NULL; - if (infoPtr->focusedItem == item) - infoPtr->focusedItem = NULL; - if (infoPtr->firstVisible == item) - infoPtr->firstVisible = NULL; - if (infoPtr->dropItem == item) - infoPtr->dropItem = NULL; - if (infoPtr->insertMarkItem == item) - infoPtr->insertMarkItem = NULL; -} - - -/* Item Insertion *******************************************************/ - -/*************************************************************************** - * This method inserts newItem before sibling as a child of parent. - * sibling can be NULL, but only if parent has no children. - */ -static void -TREEVIEW_InsertBefore(TREEVIEW_ITEM *newItem, TREEVIEW_ITEM *sibling, - TREEVIEW_ITEM *parent) -{ - assert(newItem != NULL); - assert(parent != NULL); - - if (sibling != NULL) - { - assert(sibling->parent == parent); - - if (sibling->prevSibling != NULL) - sibling->prevSibling->nextSibling = newItem; - - newItem->prevSibling = sibling->prevSibling; - sibling->prevSibling = newItem; - } - else - newItem->prevSibling = NULL; - - newItem->nextSibling = sibling; - - if (parent->firstChild == sibling) - parent->firstChild = newItem; - - if (parent->lastChild == NULL) - parent->lastChild = newItem; -} - -/*************************************************************************** - * This method inserts newItem after sibling as a child of parent. - * sibling can be NULL, but only if parent has no children. - */ -static void -TREEVIEW_InsertAfter(TREEVIEW_ITEM *newItem, TREEVIEW_ITEM *sibling, - TREEVIEW_ITEM *parent) -{ - assert(newItem != NULL); - assert(parent != NULL); - - if (sibling != NULL) - { - assert(sibling->parent == parent); - - if (sibling->nextSibling != NULL) - sibling->nextSibling->prevSibling = newItem; - - newItem->nextSibling = sibling->nextSibling; - sibling->nextSibling = newItem; - } - else - newItem->nextSibling = NULL; - - newItem->prevSibling = sibling; - - if (parent->lastChild == sibling) - parent->lastChild = newItem; - - if (parent->firstChild == NULL) - parent->firstChild = newItem; -} - -static BOOL -TREEVIEW_DoSetItemT(TREEVIEW_INFO *infoPtr, TREEVIEW_ITEM *wineItem, - const TVITEMEXW *tvItem, BOOL isW) -{ - UINT callbackClear = 0; - UINT callbackSet = 0; - - TRACE("item %p\n", wineItem); - /* Do this first in case it fails. */ - if (tvItem->mask & TVIF_TEXT) - { - wineItem->textWidth = 0; /* force width recalculation */ - if (tvItem->pszText != LPSTR_TEXTCALLBACKW) /* covers != TEXTCALLBACKA too */ - { - int len; - LPWSTR newText; - if (isW) - len = lstrlenW(tvItem->pszText) + 1; - else - len = MultiByteToWideChar(CP_ACP, 0, (LPSTR)tvItem->pszText, -1, NULL, 0); - - newText = ReAlloc(wineItem->pszText, len * sizeof(WCHAR)); - - if (newText == NULL) return FALSE; - - callbackClear |= TVIF_TEXT; - - wineItem->pszText = newText; - wineItem->cchTextMax = len; - if (isW) - lstrcpynW(wineItem->pszText, tvItem->pszText, len); - else - MultiByteToWideChar(CP_ACP, 0, (LPSTR)tvItem->pszText, -1, - wineItem->pszText, len); - - TRACE("setting text %s, item %p\n", debugstr_w(wineItem->pszText), wineItem); - } - else - { - callbackSet |= TVIF_TEXT; - - wineItem->pszText = ReAlloc(wineItem->pszText, - TEXT_CALLBACK_SIZE * sizeof(WCHAR)); - wineItem->cchTextMax = TEXT_CALLBACK_SIZE; - TRACE("setting callback, item %p\n", wineItem); - } - } - - if (tvItem->mask & TVIF_CHILDREN) - { - wineItem->cChildren = tvItem->cChildren; - - if (wineItem->cChildren == I_CHILDRENCALLBACK) - callbackSet |= TVIF_CHILDREN; - else - callbackClear |= TVIF_CHILDREN; - } - - if (tvItem->mask & TVIF_IMAGE) - { - wineItem->iImage = tvItem->iImage; - - if (wineItem->iImage == I_IMAGECALLBACK) - callbackSet |= TVIF_IMAGE; - else - callbackClear |= TVIF_IMAGE; - } - - if (tvItem->mask & TVIF_SELECTEDIMAGE) - { - wineItem->iSelectedImage = tvItem->iSelectedImage; - - if (wineItem->iSelectedImage == I_IMAGECALLBACK) - callbackSet |= TVIF_SELECTEDIMAGE; - else - callbackClear |= TVIF_SELECTEDIMAGE; - } - - if (tvItem->mask & TVIF_PARAM) - wineItem->lParam = tvItem->lParam; - - /* If the application sets TVIF_INTEGRAL without - * supplying a TVITEMEX structure, it's toast. */ - if (tvItem->mask & TVIF_INTEGRAL) - wineItem->iIntegral = tvItem->iIntegral; - - if (tvItem->mask & TVIF_STATE) - { - TRACE("prevstate,state,mask:%x,%x,%x\n", wineItem->state, tvItem->state, - tvItem->stateMask); - wineItem->state &= ~tvItem->stateMask; - wineItem->state |= (tvItem->state & tvItem->stateMask); - } - - wineItem->callbackMask |= callbackSet; - wineItem->callbackMask &= ~callbackClear; - - return TRUE; -} - -/* Note that the new item is pre-zeroed. */ -static LRESULT -TREEVIEW_InsertItemT(TREEVIEW_INFO *infoPtr, const TVINSERTSTRUCTW *ptdi, BOOL isW) -{ - const TVITEMEXW *tvItem = &ptdi->u.itemex; - HTREEITEM insertAfter; - TREEVIEW_ITEM *newItem, *parentItem; - BOOL bTextUpdated = FALSE; - - if (ptdi->hParent == TVI_ROOT || ptdi->hParent == 0) - { - parentItem = infoPtr->root; - } - else - { - parentItem = ptdi->hParent; - - if (!TREEVIEW_ValidItem(infoPtr, parentItem)) - { - WARN("invalid parent %p\n", parentItem); - return (LRESULT)(HTREEITEM)NULL; - } - } - - insertAfter = ptdi->hInsertAfter; - - /* Validate this now for convenience. */ - switch ((DWORD)insertAfter) - { - case (DWORD)TVI_FIRST: - case (DWORD)TVI_LAST: - case (DWORD)TVI_SORT: - break; - - default: - if (!TREEVIEW_ValidItem(infoPtr, insertAfter) || - insertAfter->parent != parentItem) - { - WARN("invalid insert after %p\n", insertAfter); - insertAfter = TVI_LAST; - } - } - - TRACE("parent %p position %p: %s\n", parentItem, insertAfter, - (tvItem->mask & TVIF_TEXT) - ? ((tvItem->pszText == LPSTR_TEXTCALLBACKW) ? "" - : (isW ? debugstr_w(tvItem->pszText) : debugstr_a((LPSTR)tvItem->pszText))) - : ""); - - newItem = TREEVIEW_AllocateItem(infoPtr); - if (newItem == NULL) - return (LRESULT)(HTREEITEM)NULL; - - newItem->parent = parentItem; - newItem->iIntegral = 1; - - if (!TREEVIEW_DoSetItemT(infoPtr, newItem, tvItem, isW)) - return (LRESULT)(HTREEITEM)NULL; - - /* After this point, nothing can fail. (Except for TVI_SORT.) */ - - infoPtr->uNumItems++; - - switch ((DWORD)insertAfter) - { - case (DWORD)TVI_FIRST: - { - TREEVIEW_ITEM *originalFirst = parentItem->firstChild; - TREEVIEW_InsertBefore(newItem, parentItem->firstChild, parentItem); - if (infoPtr->firstVisible == originalFirst) - TREEVIEW_SetFirstVisible(infoPtr, newItem, TRUE); - } - break; - - case (DWORD)TVI_LAST: - TREEVIEW_InsertAfter(newItem, parentItem->lastChild, parentItem); - break; - - /* hInsertAfter names a specific item we want to insert after */ - default: - TREEVIEW_InsertAfter(newItem, insertAfter, insertAfter->parent); - break; - - case (DWORD)TVI_SORT: - { - TREEVIEW_ITEM *aChild; - TREEVIEW_ITEM *previousChild = NULL; - BOOL bItemInserted = FALSE; - - aChild = parentItem->firstChild; - - bTextUpdated = TRUE; - TREEVIEW_UpdateDispInfo(infoPtr, newItem, TVIF_TEXT); - - /* Iterate the parent children to see where we fit in */ - while (aChild != NULL) - { - INT comp; - - TREEVIEW_UpdateDispInfo(infoPtr, aChild, TVIF_TEXT); - comp = lstrcmpW(newItem->pszText, aChild->pszText); - - if (comp < 0) /* we are smaller than the current one */ - { - TREEVIEW_InsertBefore(newItem, aChild, parentItem); - bItemInserted = TRUE; - break; - } - else if (comp > 0) /* we are bigger than the current one */ - { - previousChild = aChild; - - /* This will help us to exit if there is no more sibling */ - aChild = (aChild->nextSibling == 0) - ? NULL - : aChild->nextSibling; - - /* Look at the next item */ - continue; - } - else if (comp == 0) - { - /* - * An item with this name is already existing, therefore, - * we add after the one we found - */ - TREEVIEW_InsertAfter(newItem, aChild, parentItem); - bItemInserted = TRUE; - break; - } - } - - /* - * we reach the end of the child list and the item has not - * yet been inserted, therefore, insert it after the last child. - */ - if ((!bItemInserted) && (aChild == NULL)) - TREEVIEW_InsertAfter(newItem, previousChild, parentItem); - - break; - } - } - - - TRACE("new item %p; parent %p, mask %x\n", newItem, - newItem->parent, tvItem->mask); - - newItem->iLevel = newItem->parent->iLevel + 1; - - if (newItem->parent->cChildren == 0) - newItem->parent->cChildren = 1; - - if (infoPtr->dwStyle & TVS_CHECKBOXES) - { - if (STATEIMAGEINDEX(newItem->state) == 0) - newItem->state |= INDEXTOSTATEIMAGEMASK(1); - } - - if (infoPtr->firstVisible == NULL) - infoPtr->firstVisible = newItem; - - TREEVIEW_VerifyTree(infoPtr); - - if (parentItem == infoPtr->root || - (ISVISIBLE(parentItem) && parentItem->state & TVIS_EXPANDED)) - { - TREEVIEW_ITEM *item; - TREEVIEW_ITEM *prev = TREEVIEW_GetPrevListItem(infoPtr, newItem); - - TREEVIEW_RecalculateVisibleOrder(infoPtr, prev); - TREEVIEW_ComputeItemInternalMetrics(infoPtr, newItem); - - if (!bTextUpdated) - TREEVIEW_UpdateDispInfo(infoPtr, newItem, TVIF_TEXT); - - TREEVIEW_ComputeTextWidth(infoPtr, newItem, 0); - TREEVIEW_UpdateScrollBars(infoPtr); - /* - * if the item was inserted in a visible part of the tree, - * invalidate it, as well as those after it - */ - for (item = newItem; - item != NULL; - item = TREEVIEW_GetNextListItem(infoPtr, item)) - TREEVIEW_Invalidate(infoPtr, item); - } - else - { - newItem->visibleOrder = -1; - - /* refresh treeview if newItem is the first item inserted under parentItem */ - if (ISVISIBLE(parentItem) && newItem->prevSibling == newItem->nextSibling) - { - /* parent got '+' - update it */ - TREEVIEW_Invalidate(infoPtr, parentItem); - } - } - - return (LRESULT)newItem; -} - -/* Item Deletion ************************************************************/ -static void -TREEVIEW_RemoveItem(TREEVIEW_INFO *infoPtr, TREEVIEW_ITEM *wineItem); - -static void -TREEVIEW_RemoveAllChildren(TREEVIEW_INFO *infoPtr, TREEVIEW_ITEM *parentItem) -{ - TREEVIEW_ITEM *kill = parentItem->firstChild; - - while (kill != NULL) - { - TREEVIEW_ITEM *next = kill->nextSibling; - - TREEVIEW_RemoveItem(infoPtr, kill); - - kill = next; - } - - assert(parentItem->cChildren <= 0); /* I_CHILDRENCALLBACK or 0 */ - assert(parentItem->firstChild == NULL); - assert(parentItem->lastChild == NULL); -} - -static void -TREEVIEW_UnlinkItem(TREEVIEW_ITEM *item) -{ - TREEVIEW_ITEM *parentItem = item->parent; - - assert(item != NULL); - assert(item->parent != NULL); /* i.e. it must not be the root */ - - if (parentItem->firstChild == item) - parentItem->firstChild = item->nextSibling; - - if (parentItem->lastChild == item) - parentItem->lastChild = item->prevSibling; - - if (parentItem->firstChild == NULL && parentItem->lastChild == NULL - && parentItem->cChildren > 0) - parentItem->cChildren = 0; - - if (item->prevSibling) - item->prevSibling->nextSibling = item->nextSibling; - - if (item->nextSibling) - item->nextSibling->prevSibling = item->prevSibling; -} - -static void -TREEVIEW_RemoveItem(TREEVIEW_INFO *infoPtr, TREEVIEW_ITEM *wineItem) -{ - TRACE("%p, (%s)\n", wineItem, TREEVIEW_ItemName(wineItem)); - - TREEVIEW_SendTreeviewNotify(infoPtr, TVN_DELETEITEMW, TVC_UNKNOWN, - TVIF_HANDLE | TVIF_PARAM, wineItem, 0); - - if (wineItem->firstChild) - TREEVIEW_RemoveAllChildren(infoPtr, wineItem); - - TREEVIEW_UnlinkItem(wineItem); - - infoPtr->uNumItems--; - - if (wineItem->pszText && wineItem->pszText != LPSTR_TEXTCALLBACKW) - Free(wineItem->pszText); - - TREEVIEW_FreeItem(infoPtr, wineItem); -} - - -/* Empty out the tree. */ -static void -TREEVIEW_RemoveTree(TREEVIEW_INFO *infoPtr) -{ - TREEVIEW_RemoveAllChildren(infoPtr, infoPtr->root); - - assert(infoPtr->uNumItems == 0); /* root isn't counted in uNumItems */ -} - -static LRESULT -TREEVIEW_DeleteItem(TREEVIEW_INFO *infoPtr, HTREEITEM wineItem) -{ - TREEVIEW_ITEM *newSelection = NULL; - TREEVIEW_ITEM *newFirstVisible = NULL; - TREEVIEW_ITEM *parent, *prev = NULL; - BOOL visible = FALSE; - - if (wineItem == TVI_ROOT) - { - TRACE("TVI_ROOT\n"); - parent = infoPtr->root; - newSelection = NULL; - visible = TRUE; - TREEVIEW_RemoveTree(infoPtr); - } - else - { - if (!TREEVIEW_ValidItem(infoPtr, wineItem)) - return FALSE; - - TRACE("%p (%s)\n", wineItem, TREEVIEW_ItemName(wineItem)); - parent = wineItem->parent; - - if (ISVISIBLE(wineItem)) - { - prev = TREEVIEW_GetPrevListItem(infoPtr, wineItem); - visible = TRUE; - } - - if (infoPtr->selectedItem != NULL - && (wineItem == infoPtr->selectedItem - || TREEVIEW_IsChildOf(wineItem, infoPtr->selectedItem))) - { - if (wineItem->nextSibling) - newSelection = wineItem->nextSibling; - else if (wineItem->parent != infoPtr->root) - newSelection = wineItem->parent; - else - newSelection = wineItem->prevSibling; - TRACE("newSelection = %p\n", newSelection); - } - - if (infoPtr->firstVisible == wineItem) - { - if (wineItem->nextSibling) - newFirstVisible = wineItem->nextSibling; - else if (wineItem->prevSibling) - newFirstVisible = wineItem->prevSibling; - else if (wineItem->parent != infoPtr->root) - newFirstVisible = wineItem->parent; - TREEVIEW_SetFirstVisible(infoPtr, NULL, TRUE); - } - else - newFirstVisible = infoPtr->firstVisible; - - TREEVIEW_RemoveItem(infoPtr, wineItem); - } - - /* Don't change if somebody else already has (infoPtr->selectedItem is cleared by FreeItem). */ - if (!infoPtr->selectedItem && newSelection) - { - if (TREEVIEW_ValidItem(infoPtr, newSelection)) - TREEVIEW_DoSelectItem(infoPtr, TVGN_CARET, newSelection, TVC_UNKNOWN); - } - - /* Validate insertMark dropItem. - * hotItem ??? - used for comparison only. - */ - if (!TREEVIEW_ValidItem(infoPtr, infoPtr->insertMarkItem)) - infoPtr->insertMarkItem = 0; - - if (!TREEVIEW_ValidItem(infoPtr, infoPtr->dropItem)) - infoPtr->dropItem = 0; - - if (!TREEVIEW_ValidItem(infoPtr, newFirstVisible)) - newFirstVisible = infoPtr->root->firstChild; - - TREEVIEW_VerifyTree(infoPtr); - - - if (visible) - { - TREEVIEW_SetFirstVisible(infoPtr, newFirstVisible, TRUE); - TREEVIEW_RecalculateVisibleOrder(infoPtr, prev); - TREEVIEW_UpdateScrollBars(infoPtr); - TREEVIEW_Invalidate(infoPtr, NULL); - } - else if (ISVISIBLE(parent) && !TREEVIEW_HasChildren(infoPtr, parent)) - { - /* parent lost '+/-' - update it */ - TREEVIEW_Invalidate(infoPtr, parent); - } - - return TRUE; -} - - -/* Get/Set Messages *********************************************************/ -static LRESULT -TREEVIEW_SetRedraw(TREEVIEW_INFO* infoPtr, WPARAM wParam, LPARAM lParam) -{ - if(wParam) - infoPtr->bRedraw = TRUE; - else - infoPtr->bRedraw = FALSE; - - return 0; -} - -static LRESULT -TREEVIEW_GetIndent(TREEVIEW_INFO *infoPtr) -{ - TRACE("\n"); - return infoPtr->uIndent; -} - -static LRESULT -TREEVIEW_SetIndent(TREEVIEW_INFO *infoPtr, UINT newIndent) -{ - TRACE("\n"); - - if (newIndent < MINIMUM_INDENT) - newIndent = MINIMUM_INDENT; - - if (infoPtr->uIndent != newIndent) - { - infoPtr->uIndent = newIndent; - TREEVIEW_UpdateSubTree(infoPtr, infoPtr->root); - TREEVIEW_UpdateScrollBars(infoPtr); - TREEVIEW_Invalidate(infoPtr, NULL); - } - - return 0; -} - - -static LRESULT -TREEVIEW_GetToolTips(TREEVIEW_INFO *infoPtr) -{ - TRACE("\n"); - return (LRESULT)infoPtr->hwndToolTip; -} - -static LRESULT -TREEVIEW_SetToolTips(TREEVIEW_INFO *infoPtr, HWND hwndTT) -{ - HWND prevToolTip; - - TRACE("\n"); - prevToolTip = infoPtr->hwndToolTip; - infoPtr->hwndToolTip = hwndTT; - - return (LRESULT)prevToolTip; -} - -static LRESULT -TREEVIEW_SetUnicodeFormat(TREEVIEW_INFO *infoPtr, BOOL fUnicode) -{ - BOOL rc = infoPtr->bNtfUnicode; - infoPtr->bNtfUnicode = fUnicode; - return rc; -} - -static LRESULT -TREEVIEW_GetUnicodeFormat(TREEVIEW_INFO *infoPtr) -{ - return infoPtr->bNtfUnicode; -} - -static LRESULT -TREEVIEW_GetScrollTime(TREEVIEW_INFO *infoPtr) -{ - return infoPtr->uScrollTime; -} - -static LRESULT -TREEVIEW_SetScrollTime(TREEVIEW_INFO *infoPtr, UINT uScrollTime) -{ - UINT uOldScrollTime = infoPtr->uScrollTime; - - infoPtr->uScrollTime = min(uScrollTime, 100); - - return uOldScrollTime; -} - - -static LRESULT -TREEVIEW_GetImageList(TREEVIEW_INFO *infoPtr, WPARAM wParam) -{ - TRACE("\n"); - - switch (wParam) - { - case (WPARAM)TVSIL_NORMAL: - return (LRESULT)infoPtr->himlNormal; - - case (WPARAM)TVSIL_STATE: - return (LRESULT)infoPtr->himlState; - - default: - return 0; - } -} - -#define TVHEIGHT_MIN 16 -#define TVHEIGHT_FONT_ADJUST 3 /* 2 for focus border + 1 for margin some apps assume */ - -/* Compute the natural height for items. */ -static UINT -TREEVIEW_NaturalHeight(TREEVIEW_INFO *infoPtr) -{ - TEXTMETRICW tm; - HDC hdc = GetDC(0); - HFONT hOldFont = SelectObject(hdc, infoPtr->hFont); - UINT height; - - /* Height is the maximum of: - * 16 (a hack because our fonts are tiny), and - * The text height + border & margin, and - * The size of the normal image list - */ - GetTextMetricsW(hdc, &tm); - SelectObject(hdc, hOldFont); - ReleaseDC(0, hdc); - - height = TVHEIGHT_MIN; - if (height < tm.tmHeight + tm.tmExternalLeading + TVHEIGHT_FONT_ADJUST) - height = tm.tmHeight + tm.tmExternalLeading + TVHEIGHT_FONT_ADJUST; - if (height < infoPtr->normalImageHeight) - height = infoPtr->normalImageHeight; - return height; -} - -static LRESULT -TREEVIEW_SetImageList(TREEVIEW_INFO *infoPtr, WPARAM wParam, HIMAGELIST himlNew) -{ - HIMAGELIST himlOld = 0; - int oldWidth = infoPtr->normalImageWidth; - int oldHeight = infoPtr->normalImageHeight; - - - TRACE("%x,%p\n", wParam, himlNew); - - switch (wParam) - { - case (WPARAM)TVSIL_NORMAL: - himlOld = infoPtr->himlNormal; - infoPtr->himlNormal = himlNew; - - if (himlNew != NULL) - ImageList_GetIconSize(himlNew, &infoPtr->normalImageWidth, - &infoPtr->normalImageHeight); - else - { - infoPtr->normalImageWidth = 0; - infoPtr->normalImageHeight = 0; - } - - break; - - case (WPARAM)TVSIL_STATE: - himlOld = infoPtr->himlState; - infoPtr->himlState = himlNew; - - if (himlNew != NULL) - ImageList_GetIconSize(himlNew, &infoPtr->stateImageWidth, - &infoPtr->stateImageHeight); - else - { - infoPtr->stateImageWidth = 0; - infoPtr->stateImageHeight = 0; - } - - break; - } - - if (oldWidth != infoPtr->normalImageWidth || - oldHeight != infoPtr->normalImageHeight) - { - BOOL bRecalcVisible = FALSE; - - if (oldHeight != infoPtr->normalImageHeight && - !infoPtr->bHeightSet) - { - infoPtr->uItemHeight = TREEVIEW_NaturalHeight(infoPtr); - bRecalcVisible = TRUE; - } - - if (infoPtr->normalImageWidth > MINIMUM_INDENT && - infoPtr->normalImageWidth != infoPtr->uIndent) - { - infoPtr->uIndent = infoPtr->normalImageWidth; - bRecalcVisible = TRUE; - } - - if (bRecalcVisible) - TREEVIEW_RecalculateVisibleOrder(infoPtr, NULL); - - TREEVIEW_UpdateSubTree(infoPtr, infoPtr->root); - TREEVIEW_UpdateScrollBars(infoPtr); - } - - TREEVIEW_Invalidate(infoPtr, NULL); - - return (LRESULT)himlOld; -} - -static LRESULT -TREEVIEW_SetItemHeight(TREEVIEW_INFO *infoPtr, INT newHeight) -{ - INT prevHeight = infoPtr->uItemHeight; - - TRACE("%d \n", newHeight); - if (newHeight == -1) - { - infoPtr->uItemHeight = TREEVIEW_NaturalHeight(infoPtr); - infoPtr->bHeightSet = FALSE; - } - else - { - infoPtr->uItemHeight = newHeight; - infoPtr->bHeightSet = TRUE; - } - - /* Round down, unless we support odd ("non even") heights. */ - if (!(infoPtr->dwStyle) & TVS_NONEVENHEIGHT) - infoPtr->uItemHeight &= ~1; - - if (infoPtr->uItemHeight != prevHeight) - { - TREEVIEW_RecalculateVisibleOrder(infoPtr, NULL); - TREEVIEW_UpdateScrollBars(infoPtr); - TREEVIEW_Invalidate(infoPtr, NULL); - } - - return prevHeight; -} - -static LRESULT -TREEVIEW_GetItemHeight(TREEVIEW_INFO *infoPtr) -{ - TRACE("\n"); - return infoPtr->uItemHeight; -} - - -static LRESULT -TREEVIEW_GetFont(TREEVIEW_INFO *infoPtr) -{ - TRACE("%p\n", infoPtr->hFont); - return (LRESULT)infoPtr->hFont; -} - - -static INT CALLBACK -TREEVIEW_ResetTextWidth(LPVOID pItem, LPVOID unused) -{ - (void)unused; - - ((TREEVIEW_ITEM *)pItem)->textWidth = 0; - - return 1; -} - -static LRESULT -TREEVIEW_SetFont(TREEVIEW_INFO *infoPtr, HFONT hFont, BOOL bRedraw) -{ - UINT uHeight = infoPtr->uItemHeight; - - TRACE("%p %i\n", hFont, bRedraw); - - infoPtr->hFont = hFont ? hFont : infoPtr->hDefaultFont; - - DeleteObject(infoPtr->hBoldFont); - infoPtr->hBoldFont = TREEVIEW_CreateBoldFont(infoPtr->hFont); - - if (!infoPtr->bHeightSet) - infoPtr->uItemHeight = TREEVIEW_NaturalHeight(infoPtr); - - if (uHeight != infoPtr->uItemHeight) - TREEVIEW_RecalculateVisibleOrder(infoPtr, NULL); - - DPA_EnumCallback(infoPtr->items, TREEVIEW_ResetTextWidth, 0); - - TREEVIEW_UpdateSubTree(infoPtr, infoPtr->root); - TREEVIEW_UpdateScrollBars(infoPtr); - - if (bRedraw) - TREEVIEW_Invalidate(infoPtr, NULL); - - return 0; -} - - -static LRESULT -TREEVIEW_GetLineColor(TREEVIEW_INFO *infoPtr) -{ - TRACE("\n"); - return (LRESULT)infoPtr->clrLine; -} - -static LRESULT -TREEVIEW_SetLineColor(TREEVIEW_INFO *infoPtr, COLORREF color) -{ - COLORREF prevColor = infoPtr->clrLine; - - TRACE("\n"); - infoPtr->clrLine = color; - return (LRESULT)prevColor; -} - - -static LRESULT -TREEVIEW_GetTextColor(TREEVIEW_INFO *infoPtr) -{ - TRACE("\n"); - return (LRESULT)infoPtr->clrText; -} - -static LRESULT -TREEVIEW_SetTextColor(TREEVIEW_INFO *infoPtr, COLORREF color) -{ - COLORREF prevColor = infoPtr->clrText; - - TRACE("\n"); - infoPtr->clrText = color; - - if (infoPtr->clrText != prevColor) - TREEVIEW_Invalidate(infoPtr, NULL); - - return (LRESULT)prevColor; -} - - -static LRESULT -TREEVIEW_GetBkColor(TREEVIEW_INFO *infoPtr) -{ - TRACE("\n"); - return (LRESULT)infoPtr->clrBk; -} - -static LRESULT -TREEVIEW_SetBkColor(TREEVIEW_INFO *infoPtr, COLORREF newColor) -{ - COLORREF prevColor = infoPtr->clrBk; - - TRACE("\n"); - infoPtr->clrBk = newColor; - - if (newColor != prevColor) - TREEVIEW_Invalidate(infoPtr, NULL); - - return (LRESULT)prevColor; -} - - -static LRESULT -TREEVIEW_GetInsertMarkColor(TREEVIEW_INFO *infoPtr) -{ - TRACE("\n"); - return (LRESULT)infoPtr->clrInsertMark; -} - -static LRESULT -TREEVIEW_SetInsertMarkColor(TREEVIEW_INFO *infoPtr, COLORREF color) -{ - COLORREF prevColor = infoPtr->clrInsertMark; - - TRACE("%lx\n", color); - infoPtr->clrInsertMark = color; - - return (LRESULT)prevColor; -} - - -static LRESULT -TREEVIEW_SetInsertMark(TREEVIEW_INFO *infoPtr, BOOL wParam, HTREEITEM item) -{ - TRACE("%d %p\n", wParam, item); - - if (!TREEVIEW_ValidItem(infoPtr, item)) - return 0; - - infoPtr->insertBeforeorAfter = wParam; - infoPtr->insertMarkItem = item; - - TREEVIEW_Invalidate(infoPtr, NULL); - - return 1; -} - - -/************************************************************************ - * Some serious braindamage here. lParam is a pointer to both the - * input HTREEITEM and the output RECT. - */ -static LRESULT -TREEVIEW_GetItemRect(TREEVIEW_INFO *infoPtr, BOOL fTextRect, LPRECT lpRect) -{ - TREEVIEW_ITEM *wineItem; - const HTREEITEM *pItem = (HTREEITEM *)lpRect; - - TRACE("\n"); - /* - * validate parameters - */ - if (pItem == NULL) - return FALSE; - - wineItem = *pItem; - if (!TREEVIEW_ValidItem(infoPtr, wineItem) || !ISVISIBLE(wineItem)) - return FALSE; - - /* - * If wParam is TRUE return the text size otherwise return - * the whole item size - */ - if (fTextRect) - { - /* Windows does not send TVN_GETDISPINFO here. */ - - lpRect->top = wineItem->rect.top; - lpRect->bottom = wineItem->rect.bottom; - - lpRect->left = wineItem->textOffset; - lpRect->right = wineItem->textOffset + wineItem->textWidth; - } - else - { - *lpRect = wineItem->rect; - } - - TRACE("%s [L:%ld R:%ld T:%ld B:%ld]\n", fTextRect ? "text" : "item", - lpRect->left, lpRect->right, lpRect->top, lpRect->bottom); - - return TRUE; -} - -static inline LRESULT -TREEVIEW_GetVisibleCount(TREEVIEW_INFO *infoPtr) -{ - /* Suprise! This does not take integral height into account. */ - return infoPtr->clientHeight / infoPtr->uItemHeight; -} - - -static LRESULT -TREEVIEW_GetItemT(TREEVIEW_INFO *infoPtr, LPTVITEMEXW tvItem, BOOL isW) -{ - TREEVIEW_ITEM *wineItem; - - wineItem = tvItem->hItem; - if (!TREEVIEW_ValidItem(infoPtr, wineItem)) - return FALSE; - - TREEVIEW_UpdateDispInfo(infoPtr, wineItem, tvItem->mask); - - if (tvItem->mask & TVIF_CHILDREN) - { - if (wineItem->cChildren==I_CHILDRENCALLBACK) - FIXME("I_CHILDRENCALLBACK not supported\n"); - tvItem->cChildren = wineItem->cChildren; - } - - if (tvItem->mask & TVIF_HANDLE) - tvItem->hItem = wineItem; - - if (tvItem->mask & TVIF_IMAGE) - tvItem->iImage = wineItem->iImage; - - if (tvItem->mask & TVIF_INTEGRAL) - tvItem->iIntegral = wineItem->iIntegral; - - /* undocumented: windows ignores TVIF_PARAM and - * * always sets lParam - */ - tvItem->lParam = wineItem->lParam; - - if (tvItem->mask & TVIF_SELECTEDIMAGE) - tvItem->iSelectedImage = wineItem->iSelectedImage; - - if (tvItem->mask & TVIF_STATE) - /* Careful here - Windows ignores the stateMask when you get the state - That contradicts the documentation, but makes more common sense, masking - retrieval in this way seems overkill */ - tvItem->state = wineItem->state; - - if (tvItem->mask & TVIF_TEXT) - { - if (isW) - { - if (wineItem->pszText == LPSTR_TEXTCALLBACKW) - { - tvItem->pszText = LPSTR_TEXTCALLBACKW; - FIXME(" GetItem called with LPSTR_TEXTCALLBACK\n"); - } - else - { - lstrcpynW(tvItem->pszText, wineItem->pszText, tvItem->cchTextMax); - } - } - else - { - if (wineItem->pszText == LPSTR_TEXTCALLBACKW) - { - tvItem->pszText = (LPWSTR)LPSTR_TEXTCALLBACKA; - FIXME(" GetItem called with LPSTR_TEXTCALLBACK\n"); - } - else - { - WideCharToMultiByte(CP_ACP, 0, wineItem->pszText, -1, - (LPSTR)tvItem->pszText, tvItem->cchTextMax, NULL, NULL); - } - } - } - TRACE("item <%p>, txt %p, img %p, mask %x\n", - wineItem, tvItem->pszText, &tvItem->iImage, tvItem->mask); - - return TRUE; -} - -/* Beware MSDN Library Visual Studio 6.0. It says -1 on failure, 0 on success, - * which is wrong. */ -static LRESULT -TREEVIEW_SetItemT(TREEVIEW_INFO *infoPtr, LPTVITEMEXW tvItem, BOOL isW) -{ - TREEVIEW_ITEM *wineItem; - TREEVIEW_ITEM originalItem; - - wineItem = tvItem->hItem; - - TRACE("item %d,mask %x\n", TREEVIEW_GetItemIndex(infoPtr, wineItem), - tvItem->mask); - - if (!TREEVIEW_ValidItem(infoPtr, wineItem)) - return FALSE; - - /* store the orignal item values */ - originalItem = *wineItem; - - if (!TREEVIEW_DoSetItemT(infoPtr, wineItem, tvItem, isW)) - return FALSE; - - /* If the text or TVIS_BOLD was changed, and it is visible, recalculate. */ - if ((tvItem->mask & TVIF_TEXT - || (tvItem->mask & TVIF_STATE && tvItem->stateMask & TVIS_BOLD)) - && ISVISIBLE(wineItem)) - { - TREEVIEW_UpdateDispInfo(infoPtr, wineItem, TVIF_TEXT); - TREEVIEW_ComputeTextWidth(infoPtr, wineItem, 0); - } - - if (tvItem->mask != 0 && ISVISIBLE(wineItem)) - { - /* The refresh updates everything, but we can't wait until then. */ - TREEVIEW_ComputeItemInternalMetrics(infoPtr, wineItem); - - /* if any of the items values changed, redraw the item */ - if(memcmp(&originalItem, wineItem, sizeof(TREEVIEW_ITEM)) || - (tvItem->stateMask & TVIS_BOLD)) - { - if (tvItem->mask & TVIF_INTEGRAL) - { - TREEVIEW_RecalculateVisibleOrder(infoPtr, wineItem); - TREEVIEW_UpdateScrollBars(infoPtr); - - TREEVIEW_Invalidate(infoPtr, NULL); - } - else - { - TREEVIEW_UpdateScrollBars(infoPtr); - TREEVIEW_Invalidate(infoPtr, wineItem); - } - } - } - - return TRUE; -} - -static LRESULT -TREEVIEW_GetItemState(TREEVIEW_INFO *infoPtr, HTREEITEM wineItem, UINT mask) -{ - TRACE("\n"); - - if (!wineItem || !TREEVIEW_ValidItem(infoPtr, wineItem)) - return 0; - - return (wineItem->state & mask); -} - -static LRESULT -TREEVIEW_GetNextItem(TREEVIEW_INFO *infoPtr, UINT which, HTREEITEM wineItem) -{ - TREEVIEW_ITEM *retval; - - retval = 0; - - /* handle all the global data here */ - switch (which) - { - case TVGN_CHILD: /* Special case: child of 0 is root */ - if (wineItem) - break; - /* fall through */ - case TVGN_ROOT: - retval = infoPtr->root->firstChild; - break; - - case TVGN_CARET: - retval = infoPtr->selectedItem; - break; - - case TVGN_FIRSTVISIBLE: - retval = infoPtr->firstVisible; - break; - - case TVGN_DROPHILITE: - retval = infoPtr->dropItem; - break; - - case TVGN_LASTVISIBLE: - retval = TREEVIEW_GetLastListItem(infoPtr, infoPtr->root); - break; - } - - if (retval) - { - TRACE("flags:%x, returns %p\n", which, retval); - return (LRESULT)retval; - } - - if (wineItem == TVI_ROOT) wineItem = infoPtr->root; - - if (!TREEVIEW_ValidItem(infoPtr, wineItem)) - return FALSE; - - switch (which) - { - case TVGN_NEXT: - retval = wineItem->nextSibling; - break; - case TVGN_PREVIOUS: - retval = wineItem->prevSibling; - break; - case TVGN_PARENT: - retval = (wineItem->parent != infoPtr->root) ? wineItem->parent : NULL; - break; - case TVGN_CHILD: - retval = wineItem->firstChild; - break; - case TVGN_NEXTVISIBLE: - retval = TREEVIEW_GetNextListItem(infoPtr, wineItem); - break; - case TVGN_PREVIOUSVISIBLE: - retval = TREEVIEW_GetPrevListItem(infoPtr, wineItem); - break; - default: - TRACE("Unknown msg %x,item %p\n", which, wineItem); - break; - } - - TRACE("flags:%x, item %p;returns %p\n", which, wineItem, retval); - return (LRESULT)retval; -} - - -static LRESULT -TREEVIEW_GetCount(TREEVIEW_INFO *infoPtr) -{ - TRACE(" %d\n", infoPtr->uNumItems); - return (LRESULT)infoPtr->uNumItems; -} - -static VOID -TREEVIEW_ToggleItemState(TREEVIEW_INFO *infoPtr, TREEVIEW_ITEM *item) -{ - if (infoPtr->dwStyle & TVS_CHECKBOXES) - { - static const unsigned int state_table[] = { 0, 2, 1 }; - - unsigned int state; - - state = STATEIMAGEINDEX(item->state); - TRACE("state:%x\n", state); - item->state &= ~TVIS_STATEIMAGEMASK; - - if (state < 3) - state = state_table[state]; - - item->state |= INDEXTOSTATEIMAGEMASK(state); - - TRACE("state:%x\n", state); - TREEVIEW_Invalidate(infoPtr, item); - } -} - - -/* Painting *************************************************************/ - -/* Draw the lines and expand button for an item. Also draws one section - * of the line from item's parent to item's parent's next sibling. */ -static void -TREEVIEW_DrawItemLines(TREEVIEW_INFO *infoPtr, HDC hdc, TREEVIEW_ITEM *item) -{ - LONG centerx, centery; - BOOL lar = ((infoPtr->dwStyle - & (TVS_LINESATROOT|TVS_HASLINES|TVS_HASBUTTONS)) - > TVS_LINESATROOT); - - if (!lar && item->iLevel == 0) - return; - - centerx = (item->linesOffset + item->stateOffset) / 2; - centery = (item->rect.top + item->rect.bottom) / 2; - - if (infoPtr->dwStyle & TVS_HASLINES) - { - HPEN hOldPen, hNewPen; - HTREEITEM parent; - - /* - * Get a dotted grey pen - */ - hNewPen = CreatePen(PS_ALTERNATE, 0, infoPtr->clrLine); - hOldPen = SelectObject(hdc, hNewPen); - - MoveToEx(hdc, item->stateOffset, centery, NULL); - LineTo(hdc, centerx - 1, centery); - - if (item->prevSibling || item->parent != infoPtr->root) - { - MoveToEx(hdc, centerx, item->rect.top, NULL); - LineTo(hdc, centerx, centery); - } - - if (item->nextSibling) - { - MoveToEx(hdc, centerx, centery, NULL); - LineTo(hdc, centerx, item->rect.bottom + 1); - } - - /* Draw the line from our parent to its next sibling. */ - parent = item->parent; - while (parent != infoPtr->root) - { - int pcenterx = (parent->linesOffset + parent->stateOffset) / 2; - - if (parent->nextSibling - /* skip top-levels unless TVS_LINESATROOT */ - && parent->stateOffset > parent->linesOffset) - { - MoveToEx(hdc, pcenterx, item->rect.top, NULL); - LineTo(hdc, pcenterx, item->rect.bottom + 1); - } - - parent = parent->parent; - } - - SelectObject(hdc, hOldPen); - DeleteObject(hNewPen); - } - - /* - * Display the (+/-) signs - */ - - if (infoPtr->dwStyle & TVS_HASBUTTONS) - { - if (item->cChildren) - { - LONG height = item->rect.bottom - item->rect.top; - LONG width = item->stateOffset - item->linesOffset; - LONG rectsize = min(height, width) / 4; - /* plussize = ceil(rectsize * 3/4) */ - LONG plussize = (rectsize + 1) * 3 / 4; - - HPEN hNewPen = CreatePen(PS_SOLID, 0, infoPtr->clrLine); - HPEN hOldPen = SelectObject(hdc, hNewPen); - HBRUSH hbr = CreateSolidBrush(infoPtr->clrBk); - HBRUSH hbrOld = SelectObject(hdc, hbr); - - Rectangle(hdc, centerx - rectsize - 1, centery - rectsize - 1, - centerx + rectsize + 2, centery + rectsize + 2); - - SelectObject(hdc, hbrOld); - DeleteObject(hbr); - - SelectObject(hdc, hOldPen); - DeleteObject(hNewPen); - - if (height < 18 || width < 18) - { - MoveToEx(hdc, centerx - plussize + 1, centery, NULL); - LineTo(hdc, centerx + plussize, centery); - - if (!(item->state & TVIS_EXPANDED)) - { - MoveToEx(hdc, centerx, centery - plussize + 1, NULL); - LineTo(hdc, centerx, centery + plussize); - } - } - else - { - Rectangle(hdc, centerx - plussize + 1, centery - 1, - centerx + plussize, centery + 2); - - if (!(item->state & TVIS_EXPANDED)) - { - Rectangle(hdc, centerx - 1, centery - plussize + 1, - centerx + 2, centery + plussize); - SetPixel(hdc, centerx - 1, centery, infoPtr->clrBk); - SetPixel(hdc, centerx + 1, centery, infoPtr->clrBk); - } - } - } - } -} - -static void -TREEVIEW_DrawItem(TREEVIEW_INFO *infoPtr, HDC hdc, TREEVIEW_ITEM *wineItem) -{ - INT cditem; - HFONT hOldFont; - int centery; - - hOldFont = SelectObject(hdc, TREEVIEW_FontForItem(infoPtr, wineItem)); - - TREEVIEW_UpdateDispInfo(infoPtr, wineItem, CALLBACK_MASK_ALL); - - /* The custom draw handler can query the text rectangle, - * so get ready. */ - TREEVIEW_ComputeTextWidth(infoPtr, wineItem, hdc); - - cditem = 0; - - if (infoPtr->cdmode & CDRF_NOTIFYITEMDRAW) - { - cditem = TREEVIEW_SendCustomDrawItemNotify - (infoPtr, hdc, wineItem, CDDS_ITEMPREPAINT); - TRACE("prepaint:cditem-app returns 0x%x\n", cditem); - - if (cditem & CDRF_SKIPDEFAULT) - { - SelectObject(hdc, hOldFont); - return; - } - } - - if (cditem & CDRF_NEWFONT) - TREEVIEW_ComputeTextWidth(infoPtr, wineItem, hdc); - - TREEVIEW_DrawItemLines(infoPtr, hdc, wineItem); - - centery = (wineItem->rect.top + wineItem->rect.bottom) / 2; - - /* - * Display the images associated with this item - */ - { - INT imageIndex; - - /* State images are displayed to the left of the Normal image - * image number is in state; zero should be `display no image'. - */ - imageIndex = STATEIMAGEINDEX(wineItem->state); - - if (infoPtr->himlState && imageIndex) - { - ImageList_Draw(infoPtr->himlState, imageIndex, hdc, - wineItem->stateOffset, - centery - infoPtr->stateImageHeight / 2, - ILD_NORMAL); - } - - /* Now, draw the normal image; can be either selected or - * non-selected image. - */ - - if ((wineItem->state & TVIS_SELECTED) && (wineItem->iSelectedImage)) - { - /* The item is currently selected */ - imageIndex = wineItem->iSelectedImage; - } - else - { - /* The item is not selected */ - imageIndex = wineItem->iImage; - } - - if (infoPtr->himlNormal) - { - int ovlIdx = wineItem->state & TVIS_OVERLAYMASK; - - ImageList_Draw(infoPtr->himlNormal, imageIndex, hdc, - wineItem->imageOffset, - centery - infoPtr->normalImageHeight / 2, - ILD_NORMAL | ovlIdx); - } - } - - - /* - * Display the text associated with this item - */ - - /* Don't paint item's text if it's being edited */ - if (!infoPtr->hwndEdit || (infoPtr->selectedItem != wineItem)) - { - if (wineItem->pszText) - { - COLORREF oldTextColor = 0; - INT oldBkMode; - HBRUSH hbrBk = 0; - BOOL inFocus = (GetFocus() == infoPtr->hwnd); - RECT rcText; - - oldBkMode = SetBkMode(hdc, TRANSPARENT); - - /* - If item is drop target or it is selected and window is in focus - - * use blue background (COLOR_HIGHLIGHT). - * - If item is selected, window is not in focus, but it has style - * TVS_SHOWSELALWAYS - use grey background (COLOR_BTNFACE) - * - Otherwise - don't fill background - */ - if ((wineItem->state & TVIS_DROPHILITED) || ((wineItem == infoPtr->focusedItem) && !(wineItem->state & TVIS_SELECTED)) || - ((wineItem->state & TVIS_SELECTED) && (!infoPtr->focusedItem) && - (inFocus || (infoPtr->dwStyle & TVS_SHOWSELALWAYS)))) - { - if ((wineItem->state & TVIS_DROPHILITED) || inFocus) - { - hbrBk = CreateSolidBrush(GetSysColor(COLOR_HIGHLIGHT)); - oldTextColor = - SetTextColor(hdc, GetSysColor(COLOR_HIGHLIGHTTEXT)); - } - else - { - hbrBk = CreateSolidBrush(GetSysColor(COLOR_BTNFACE)); - - if (infoPtr->clrText == -1) - oldTextColor = - SetTextColor(hdc, GetSysColor(COLOR_WINDOWTEXT)); - else - oldTextColor = SetTextColor(hdc, infoPtr->clrText); - } - } - else - { - if (infoPtr->clrText == -1) - oldTextColor = - SetTextColor(hdc, GetSysColor(COLOR_WINDOWTEXT)); - else - oldTextColor = SetTextColor(hdc, infoPtr->clrText); - } - - rcText.top = wineItem->rect.top; - rcText.bottom = wineItem->rect.bottom; - rcText.left = wineItem->textOffset; - rcText.right = rcText.left + wineItem->textWidth + 4; - - if (hbrBk) - { - FillRect(hdc, &rcText, hbrBk); - DeleteObject(hbrBk); - } - - /* Draw the box around the selected item */ - if ((wineItem == infoPtr->selectedItem) && inFocus) - { - DrawFocusRect(hdc,&rcText); - } - - InflateRect(&rcText, -2, -1); /* allow for the focus rect */ - - TRACE("drawing text %s at (%ld,%ld)-(%ld,%ld)\n", - debugstr_w(wineItem->pszText), - rcText.left, rcText.top, rcText.right, rcText.bottom); - - /* Draw it */ - DrawTextW(hdc, - wineItem->pszText, - lstrlenW(wineItem->pszText), - &rcText, - DT_CENTER | DT_VCENTER | DT_SINGLELINE | DT_NOPREFIX); - - /* Restore the hdc state */ - SetTextColor(hdc, oldTextColor); - - if (oldBkMode != TRANSPARENT) - SetBkMode(hdc, oldBkMode); - } - } - - /* Draw insertion mark if necessary */ - - if (infoPtr->insertMarkItem) - TRACE("item:%d,mark:%d\n", - TREEVIEW_GetItemIndex(infoPtr, wineItem), - (int)infoPtr->insertMarkItem); - - if (wineItem == infoPtr->insertMarkItem) - { - HPEN hNewPen, hOldPen; - int offset; - int left, right; - - hNewPen = CreatePen(PS_SOLID, 2, infoPtr->clrInsertMark); - hOldPen = SelectObject(hdc, hNewPen); - - if (infoPtr->insertBeforeorAfter) - offset = wineItem->rect.bottom - 1; - else - offset = wineItem->rect.top + 1; - - left = wineItem->textOffset - 2; - right = wineItem->textOffset + wineItem->textWidth + 2; - - MoveToEx(hdc, left, offset - 3, NULL); - LineTo(hdc, left, offset + 4); - - MoveToEx(hdc, left, offset, NULL); - LineTo(hdc, right + 1, offset); - - MoveToEx(hdc, right, offset + 3, NULL); - LineTo(hdc, right, offset - 4); - - SelectObject(hdc, hOldPen); - DeleteObject(hNewPen); - } - - if (cditem & CDRF_NOTIFYPOSTPAINT) - { - cditem = TREEVIEW_SendCustomDrawItemNotify - (infoPtr, hdc, wineItem, CDDS_ITEMPOSTPAINT); - TRACE("postpaint:cditem-app returns 0x%x\n", cditem); - } - - SelectObject(hdc, hOldFont); -} - -/* Computes treeHeight and treeWidth and updates the scroll bars. - */ -static void -TREEVIEW_UpdateScrollBars(TREEVIEW_INFO *infoPtr) -{ - TREEVIEW_ITEM *wineItem; - HWND hwnd = infoPtr->hwnd; - BOOL vert = FALSE; - BOOL horz = FALSE; - SCROLLINFO si; - LONG scrollX = infoPtr->scrollX; - - infoPtr->treeWidth = 0; - infoPtr->treeHeight = 0; - - /* We iterate through all visible items in order to get the tree height - * and width */ - wineItem = infoPtr->root->firstChild; - - while (wineItem != NULL) - { - if (ISVISIBLE(wineItem)) - { - /* actually we draw text at textOffset + 2 */ - if (2+wineItem->textOffset+wineItem->textWidth > infoPtr->treeWidth) - infoPtr->treeWidth = wineItem->textOffset+wineItem->textWidth+2; - - /* This is scroll-adjusted, but we fix this below. */ - infoPtr->treeHeight = wineItem->rect.bottom; - } - - wineItem = TREEVIEW_GetNextListItem(infoPtr, wineItem); - } - - /* Fix the scroll adjusted treeHeight and treeWidth. */ - if (infoPtr->root->firstChild) - infoPtr->treeHeight -= infoPtr->root->firstChild->rect.top; - - infoPtr->treeWidth += infoPtr->scrollX; - - if (infoPtr->dwStyle & TVS_NOSCROLL) return; - - /* Adding one scroll bar may take up enough space that it forces us - * to add the other as well. */ - if (infoPtr->treeHeight > infoPtr->clientHeight) - { - vert = TRUE; - - if (infoPtr->treeWidth - > infoPtr->clientWidth - GetSystemMetrics(SM_CXVSCROLL)) - horz = TRUE; - } - else if (infoPtr->treeWidth > infoPtr->clientWidth) - horz = TRUE; - - if (!vert && horz && infoPtr->treeHeight - > infoPtr->clientHeight - GetSystemMetrics(SM_CYVSCROLL)) - vert = TRUE; - - if (horz && (infoPtr->dwStyle & TVS_NOHSCROLL)) horz = FALSE; - - si.cbSize = sizeof(SCROLLINFO); - si.fMask = SIF_POS|SIF_RANGE|SIF_PAGE; - si.nMin = 0; - - if (vert) - { - si.nPage = TREEVIEW_GetVisibleCount(infoPtr); - if ( si.nPage && NULL != infoPtr->firstVisible) - { - si.nPos = infoPtr->firstVisible->visibleOrder; - si.nMax = infoPtr->maxVisibleOrder - 1; - - SetScrollInfo(hwnd, SB_VERT, &si, TRUE); - - if (!(infoPtr->uInternalStatus & TV_VSCROLL)) - ShowScrollBar(hwnd, SB_VERT, TRUE); - infoPtr->uInternalStatus |= TV_VSCROLL; - } - else - { - if (infoPtr->uInternalStatus & TV_VSCROLL) - ShowScrollBar(hwnd, SB_VERT, FALSE); - infoPtr->uInternalStatus &= ~TV_VSCROLL; - } - } - else - { - if (infoPtr->uInternalStatus & TV_VSCROLL) - ShowScrollBar(hwnd, SB_VERT, FALSE); - infoPtr->uInternalStatus &= ~TV_VSCROLL; - } - - if (horz) - { - si.nPage = infoPtr->clientWidth; - si.nPos = infoPtr->scrollX; - si.nMax = infoPtr->treeWidth - 1; - - if (si.nPos > si.nMax - max( si.nPage-1, 0 )) - { - si.nPos = si.nMax - max( si.nPage-1, 0 ); - scrollX = si.nPos; - } - - if (!(infoPtr->uInternalStatus & TV_HSCROLL)) - ShowScrollBar(hwnd, SB_HORZ, TRUE); - infoPtr->uInternalStatus |= TV_HSCROLL; - - SetScrollInfo(hwnd, SB_HORZ, &si, TRUE); - } - else - { - if (infoPtr->uInternalStatus & TV_HSCROLL) - ShowScrollBar(hwnd, SB_HORZ, FALSE); - infoPtr->uInternalStatus &= ~TV_HSCROLL; - - scrollX = 0; - } - - if (infoPtr->scrollX != scrollX) - { - TREEVIEW_HScroll(infoPtr, - MAKEWPARAM(SB_THUMBPOSITION, scrollX)); - } - - if (!horz) - infoPtr->uInternalStatus &= ~TV_HSCROLL; -} - -/* CtrlSpy doesn't mention this, but CorelDRAW's object manager needs it. */ -static LRESULT -TREEVIEW_EraseBackground(TREEVIEW_INFO *infoPtr, HDC hDC) -{ - HBRUSH hBrush = CreateSolidBrush(infoPtr->clrBk); - RECT rect; - - GetClientRect(infoPtr->hwnd, &rect); - FillRect(hDC, &rect, hBrush); - DeleteObject(hBrush); - - return 1; -} - -static void -TREEVIEW_Refresh(TREEVIEW_INFO *infoPtr, HDC hdc, RECT *rc) -{ - HWND hwnd = infoPtr->hwnd; - RECT rect = *rc; - TREEVIEW_ITEM *wineItem; - - if (infoPtr->clientHeight == 0 || infoPtr->clientWidth == 0) - { - TRACE("empty window\n"); - return; - } - - infoPtr->cdmode = TREEVIEW_SendCustomDrawNotify(infoPtr, CDDS_PREPAINT, - hdc, rect); - - if (infoPtr->cdmode == CDRF_SKIPDEFAULT) - { - ReleaseDC(hwnd, hdc); - return; - } - - for (wineItem = infoPtr->root->firstChild; - wineItem != NULL; - wineItem = TREEVIEW_GetNextListItem(infoPtr, wineItem)) - { - if (ISVISIBLE(wineItem)) - { - /* Avoid unneeded calculations */ - if (wineItem->rect.top > rect.bottom) - break; - if (wineItem->rect.bottom < rect.top) - continue; - - TREEVIEW_DrawItem(infoPtr, hdc, wineItem); - } - } - - TREEVIEW_UpdateScrollBars(infoPtr); - - if (infoPtr->cdmode & CDRF_NOTIFYPOSTPAINT) - infoPtr->cdmode = - TREEVIEW_SendCustomDrawNotify(infoPtr, CDDS_POSTPAINT, hdc, rect); -} - -static void -TREEVIEW_Invalidate(TREEVIEW_INFO *infoPtr, TREEVIEW_ITEM *item) -{ - if (item != NULL) - InvalidateRect(infoPtr->hwnd, &item->rect, TRUE); - else - InvalidateRect(infoPtr->hwnd, NULL, TRUE); -} - -static LRESULT -TREEVIEW_Paint(TREEVIEW_INFO *infoPtr, WPARAM wParam) -{ - HDC hdc; - PAINTSTRUCT ps; - RECT rc; - - TRACE("\n"); - - if (wParam) - { - hdc = (HDC)wParam; - if (!GetUpdateRect(infoPtr->hwnd, &rc, TRUE)) - { - HBITMAP hbitmap; - BITMAP bitmap; - hbitmap = GetCurrentObject(hdc, OBJ_BITMAP); - if (!hbitmap) return 0; - GetObjectA(hbitmap, sizeof(BITMAP), &bitmap); - rc.left = 0; rc.top = 0; - rc.right = bitmap.bmWidth; - rc.bottom = bitmap.bmHeight; - TREEVIEW_EraseBackground(infoPtr, (HDC)wParam); - } - } - else - { - hdc = BeginPaint(infoPtr->hwnd, &ps); - rc = ps.rcPaint; - } - - if(infoPtr->bRedraw) /* WM_SETREDRAW sets bRedraw */ - TREEVIEW_Refresh(infoPtr, hdc, &rc); - - if (!wParam) - EndPaint(infoPtr->hwnd, &ps); - - return 0; -} - - -/* Sorting **************************************************************/ - -/*************************************************************************** - * Forward the DPA local callback to the treeview owner callback - */ -static INT WINAPI -TREEVIEW_CallBackCompare(TREEVIEW_ITEM *first, TREEVIEW_ITEM *second, LPTVSORTCB pCallBackSort) -{ - /* Forward the call to the client-defined callback */ - return pCallBackSort->lpfnCompare(first->lParam, - second->lParam, - pCallBackSort->lParam); -} - -/*************************************************************************** - * Treeview native sort routine: sort on item text. - */ -static INT WINAPI -TREEVIEW_SortOnName(TREEVIEW_ITEM *first, TREEVIEW_ITEM *second, - TREEVIEW_INFO *infoPtr) -{ - TREEVIEW_UpdateDispInfo(infoPtr, first, TVIF_TEXT); - TREEVIEW_UpdateDispInfo(infoPtr, second, TVIF_TEXT); - - if(first->pszText && second->pszText) - return lstrcmpiW(first->pszText, second->pszText); - else if(first->pszText) - return -1; - else if(second->pszText) - return 1; - else - return 0; -} - -/* Returns the number of physical children belonging to item. */ -static INT -TREEVIEW_CountChildren(TREEVIEW_INFO *infoPtr, TREEVIEW_ITEM *item) -{ - INT cChildren = 0; - HTREEITEM hti; - - for (hti = item->firstChild; hti != NULL; hti = hti->nextSibling) - cChildren++; - - return cChildren; -} - -/* Returns a DPA containing a pointer to each physical child of item in - * sibling order. If item has no children, an empty DPA is returned. */ -static HDPA -TREEVIEW_BuildChildDPA(TREEVIEW_INFO *infoPtr, TREEVIEW_ITEM *item) -{ - HTREEITEM child = item->firstChild; - - HDPA list = DPA_Create(8); - if (list == 0) return NULL; - - for (child = item->firstChild; child != NULL; child = child->nextSibling) - { - if (DPA_InsertPtr(list, INT_MAX, child) == -1) - { - DPA_Destroy(list); - return NULL; - } - } - - return list; -} - -/*************************************************************************** - * Setup the treeview structure with regards of the sort method - * and sort the children of the TV item specified in lParam - * fRecurse: currently unused. Should be zero. - * parent: if pSort!=NULL, should equal pSort->hParent. - * otherwise, item which child items are to be sorted. - * pSort: sort method info. if NULL, sort on item text. - * if non-NULL, sort on item's lParam content, and let the - * application decide what that means. See also TVM_SORTCHILDRENCB. - */ - -static LRESULT -TREEVIEW_Sort(TREEVIEW_INFO *infoPtr, BOOL fRecurse, HTREEITEM parent, - LPTVSORTCB pSort) -{ - INT cChildren; - PFNDPACOMPARE pfnCompare; - LPARAM lpCompare; - - /* undocumented feature: TVI_ROOT or NULL means `sort the whole tree' */ - if (parent == TVI_ROOT || parent == NULL) - parent = infoPtr->root; - - /* Check for a valid handle to the parent item */ - if (!TREEVIEW_ValidItem(infoPtr, parent)) - { - ERR("invalid item hParent=%x\n", (INT)parent); - return FALSE; - } - - if (pSort) - { - pfnCompare = (PFNDPACOMPARE)TREEVIEW_CallBackCompare; - lpCompare = (LPARAM)pSort; - } - else - { - pfnCompare = (PFNDPACOMPARE)TREEVIEW_SortOnName; - lpCompare = (LPARAM)infoPtr; - } - - cChildren = TREEVIEW_CountChildren(infoPtr, parent); - - /* Make sure there is something to sort */ - if (cChildren > 1) - { - /* TREEVIEW_ITEM rechaining */ - INT count = 0; - HTREEITEM item = 0; - HTREEITEM nextItem = 0; - HTREEITEM prevItem = 0; - - HDPA sortList = TREEVIEW_BuildChildDPA(infoPtr, parent); - - if (sortList == NULL) - return FALSE; - - /* let DPA sort the list */ - DPA_Sort(sortList, pfnCompare, lpCompare); - - /* The order of DPA entries has been changed, so fixup the - * nextSibling and prevSibling pointers. */ - - item = (HTREEITEM)DPA_GetPtr(sortList, count++); - while ((nextItem = (HTREEITEM)DPA_GetPtr(sortList, count++)) != NULL) - { - /* link the two current item toghether */ - item->nextSibling = nextItem; - nextItem->prevSibling = item; - - if (prevItem == NULL) - { - /* this is the first item, update the parent */ - parent->firstChild = item; - item->prevSibling = NULL; - } - else - { - /* fix the back chaining */ - item->prevSibling = prevItem; - } - - /* get ready for the next one */ - prevItem = item; - item = nextItem; - } - - /* the last item is pointed to by item and never has a sibling */ - item->nextSibling = NULL; - parent->lastChild = item; - - DPA_Destroy(sortList); - - TREEVIEW_VerifyTree(infoPtr); - - if (parent->state & TVIS_EXPANDED) - { - int visOrder = infoPtr->firstVisible->visibleOrder; - - if (parent == infoPtr->root) - TREEVIEW_RecalculateVisibleOrder(infoPtr, NULL); - else - TREEVIEW_RecalculateVisibleOrder(infoPtr, parent); - - if (TREEVIEW_IsChildOf(parent, infoPtr->firstVisible)) - { - TREEVIEW_ITEM *item; - - for (item = infoPtr->root->firstChild; item != NULL; - item = TREEVIEW_GetNextListItem(infoPtr, item)) - { - if (item->visibleOrder == visOrder) - break; - } - - if (!item) item = parent->firstChild; - TREEVIEW_SetFirstVisible(infoPtr, item, FALSE); - } - - TREEVIEW_Invalidate(infoPtr, NULL); - } - - return TRUE; - } - return FALSE; -} - - -/*************************************************************************** - * Setup the treeview structure with regards of the sort method - * and sort the children of the TV item specified in lParam - */ -static LRESULT -TREEVIEW_SortChildrenCB(TREEVIEW_INFO *infoPtr, WPARAM wParam, LPTVSORTCB pSort) -{ - return TREEVIEW_Sort(infoPtr, wParam, pSort->hParent, pSort); -} - - -/*************************************************************************** - * Sort the children of the TV item specified in lParam. - */ -static LRESULT -TREEVIEW_SortChildren(TREEVIEW_INFO *infoPtr, WPARAM wParam, LPARAM lParam) -{ - return TREEVIEW_Sort(infoPtr, (BOOL)wParam, (HTREEITEM)lParam, NULL); -} - - -/* Expansion/Collapse ***************************************************/ - -static BOOL -TREEVIEW_SendExpanding(TREEVIEW_INFO *infoPtr, TREEVIEW_ITEM *wineItem, - UINT action) -{ - return !TREEVIEW_SendTreeviewNotify(infoPtr, TVN_ITEMEXPANDINGW, action, - TVIF_HANDLE | TVIF_STATE | TVIF_PARAM - | TVIF_IMAGE | TVIF_SELECTEDIMAGE, - 0, wineItem); -} - -static VOID -TREEVIEW_SendExpanded(TREEVIEW_INFO *infoPtr, TREEVIEW_ITEM *wineItem, - UINT action) -{ - TREEVIEW_SendTreeviewNotify(infoPtr, TVN_ITEMEXPANDEDW, action, - TVIF_HANDLE | TVIF_STATE | TVIF_PARAM - | TVIF_IMAGE | TVIF_SELECTEDIMAGE, - 0, wineItem); -} - - -/* This corresponds to TVM_EXPAND with TVE_COLLAPSE. - * bRemoveChildren corresponds to TVE_COLLAPSERESET. */ -static BOOL -TREEVIEW_Collapse(TREEVIEW_INFO *infoPtr, TREEVIEW_ITEM *wineItem, - BOOL bRemoveChildren, BOOL bUser) -{ - UINT action = TVE_COLLAPSE | (bRemoveChildren ? TVE_COLLAPSERESET : 0); - BOOL bSetSelection, bSetFirstVisible; - - TRACE("TVE_COLLAPSE %p %s\n", wineItem, TREEVIEW_ItemName(wineItem)); - - if (!(wineItem->state & TVIS_EXPANDED)) - return FALSE; - - if (bUser || !(wineItem->state & TVIS_EXPANDEDONCE)) - TREEVIEW_SendExpanding(infoPtr, wineItem, action); - - if (wineItem->firstChild == NULL) - return FALSE; - - wineItem->state &= ~TVIS_EXPANDED; - - if (bUser || !(wineItem->state & TVIS_EXPANDEDONCE)) - TREEVIEW_SendExpanded(infoPtr, wineItem, action); - - bSetSelection = (infoPtr->selectedItem != NULL - && TREEVIEW_IsChildOf(wineItem, infoPtr->selectedItem)); - - bSetFirstVisible = (infoPtr->firstVisible != NULL - && TREEVIEW_IsChildOf(wineItem, infoPtr->firstVisible)); - - if (bRemoveChildren) - { - INT old_cChildren = wineItem->cChildren; - TRACE("TVE_COLLAPSERESET\n"); - wineItem->state &= ~TVIS_EXPANDEDONCE; - TREEVIEW_RemoveAllChildren(infoPtr, wineItem); - wineItem->cChildren = old_cChildren; - } - - if (wineItem->firstChild) - { - TREEVIEW_ITEM *item, *sibling; - - sibling = TREEVIEW_GetNextListItem(infoPtr, wineItem); - - for (item = wineItem->firstChild; item != sibling; - item = TREEVIEW_GetNextListItem(infoPtr, item)) - { - item->visibleOrder = -1; - } - } - - TREEVIEW_RecalculateVisibleOrder(infoPtr, wineItem); - - TREEVIEW_SetFirstVisible(infoPtr, bSetFirstVisible ? wineItem - : infoPtr->firstVisible, TRUE); - - if (bSetSelection) - { - /* Don't call DoSelectItem, it sends notifications. */ - if (TREEVIEW_ValidItem(infoPtr, infoPtr->selectedItem)) - infoPtr->selectedItem->state &= ~TVIS_SELECTED; - wineItem->state |= TVIS_SELECTED; - infoPtr->selectedItem = wineItem; - - TREEVIEW_EnsureVisible(infoPtr, wineItem, FALSE); - } - - TREEVIEW_UpdateScrollBars(infoPtr); - TREEVIEW_Invalidate(infoPtr, NULL); - - return TRUE; -} - -static BOOL -TREEVIEW_Expand(TREEVIEW_INFO *infoPtr, TREEVIEW_ITEM *wineItem, - BOOL bExpandPartial, BOOL bUser) -{ - TRACE("\n"); - - if (wineItem->state & TVIS_EXPANDED) - return TRUE; - - TRACE("TVE_EXPAND %p %s\n", wineItem, TREEVIEW_ItemName(wineItem)); - - if (bUser || ((wineItem->cChildren != 0) && - !(wineItem->state & TVIS_EXPANDEDONCE))) - { - if (!TREEVIEW_SendExpanding(infoPtr, wineItem, TVE_EXPAND)) - { - TRACE(" TVN_ITEMEXPANDING returned TRUE, exiting...\n"); - return FALSE; - } - - if (!wineItem->firstChild) - return FALSE; - - wineItem->state |= TVIS_EXPANDED; - TREEVIEW_SendExpanded(infoPtr, wineItem, TVE_EXPAND); - wineItem->state |= TVIS_EXPANDEDONCE; - } - else - { - if (!wineItem->firstChild) - return FALSE; - - /* this item has already been expanded */ - wineItem->state |= TVIS_EXPANDED; - } - - if (bExpandPartial) - FIXME("TVE_EXPANDPARTIAL not implemented\n"); - - TREEVIEW_RecalculateVisibleOrder(infoPtr, wineItem); - TREEVIEW_UpdateSubTree(infoPtr, wineItem); - TREEVIEW_UpdateScrollBars(infoPtr); - - /* Scroll up so that as many children as possible are visible. - * This looses when expanding causes an HScroll bar to appear, but we - * don't know that yet, so the last item is obscured. */ - if (wineItem->firstChild != NULL) - { - int nChildren = wineItem->lastChild->visibleOrder - - wineItem->firstChild->visibleOrder + 1; - - int visible_pos = wineItem->visibleOrder - - infoPtr->firstVisible->visibleOrder; - - int rows_below = TREEVIEW_GetVisibleCount(infoPtr) - visible_pos - 1; - - if (visible_pos > 0 && nChildren > rows_below) - { - int scroll = nChildren - rows_below; - - if (scroll > visible_pos) - scroll = visible_pos; - - if (scroll > 0) - { - TREEVIEW_ITEM *newFirstVisible - = TREEVIEW_GetListItem(infoPtr, infoPtr->firstVisible, - scroll); - - - TREEVIEW_SetFirstVisible(infoPtr, newFirstVisible, TRUE); - } - } - } - - TREEVIEW_Invalidate(infoPtr, NULL); - - return TRUE; -} - -static BOOL -TREEVIEW_Toggle(TREEVIEW_INFO *infoPtr, TREEVIEW_ITEM *wineItem, BOOL bUser) -{ - TRACE("\n"); - - if (wineItem->state & TVIS_EXPANDED) - return TREEVIEW_Collapse(infoPtr, wineItem, FALSE, bUser); - else - return TREEVIEW_Expand(infoPtr, wineItem, FALSE, bUser); -} - -static VOID -TREEVIEW_ExpandAll(TREEVIEW_INFO *infoPtr, TREEVIEW_ITEM *item) -{ - TREEVIEW_Expand(infoPtr, item, FALSE, TRUE); - - for (item = item->firstChild; item != NULL; item = item->nextSibling) - { - if (TREEVIEW_HasChildren(infoPtr, item)) - TREEVIEW_ExpandAll(infoPtr, item); - } -} - -/* Note:If the specified item is the child of a collapsed parent item, - the parent's list of child items is (recursively) expanded to reveal the - specified item. This is mentioned for TREEVIEW_SelectItem; don't - know if it also applies here. -*/ - -static LRESULT -TREEVIEW_ExpandMsg(TREEVIEW_INFO *infoPtr, UINT flag, HTREEITEM wineItem) -{ - if (!TREEVIEW_ValidItem(infoPtr, wineItem)) - return 0; - - TRACE("For (%s) item:%d, flags %x, state:%d\n", - TREEVIEW_ItemName(wineItem), flag, - TREEVIEW_GetItemIndex(infoPtr, wineItem), wineItem->state); - - switch (flag & TVE_TOGGLE) - { - case TVE_COLLAPSE: - return TREEVIEW_Collapse(infoPtr, wineItem, flag & TVE_COLLAPSERESET, - FALSE); - - case TVE_EXPAND: - return TREEVIEW_Expand(infoPtr, wineItem, flag & TVE_EXPANDPARTIAL, - FALSE); - - case TVE_TOGGLE: - return TREEVIEW_Toggle(infoPtr, wineItem, TRUE); - - default: - return 0; - } - -#if 0 - TRACE("Exiting, Item %p state is now %d...\n", wineItem, wineItem->state); -#endif -} - -/* Hit-Testing **********************************************************/ - -static TREEVIEW_ITEM * -TREEVIEW_HitTestPoint(TREEVIEW_INFO *infoPtr, POINT pt) -{ - TREEVIEW_ITEM *wineItem; - LONG row; - - if (!infoPtr->firstVisible) - return NULL; - - row = pt.y / infoPtr->uItemHeight + infoPtr->firstVisible->visibleOrder; - - for (wineItem = infoPtr->firstVisible; wineItem != NULL; - wineItem = TREEVIEW_GetNextListItem(infoPtr, wineItem)) - { - if (row >= wineItem->visibleOrder - && row < wineItem->visibleOrder + wineItem->iIntegral) - break; - } - - return wineItem; -} - -static LRESULT -TREEVIEW_HitTest(TREEVIEW_INFO *infoPtr, LPTVHITTESTINFO lpht) -{ - TREEVIEW_ITEM *wineItem; - RECT rect; - UINT status; - LONG x, y; - - lpht->hItem = 0; - GetClientRect(infoPtr->hwnd, &rect); - status = 0; - x = lpht->pt.x; - y = lpht->pt.y; - - if (x < rect.left) - { - status |= TVHT_TOLEFT; - } - else if (x > rect.right) - { - status |= TVHT_TORIGHT; - } - - if (y < rect.top) - { - status |= TVHT_ABOVE; - } - else if (y > rect.bottom) - { - status |= TVHT_BELOW; - } - - if (status) - { - lpht->flags = status; - return (LRESULT)(HTREEITEM)NULL; - } - - wineItem = TREEVIEW_HitTestPoint(infoPtr, lpht->pt); - if (!wineItem) - { - lpht->flags = TVHT_NOWHERE; - return (LRESULT)(HTREEITEM)NULL; - } - - if (x >= wineItem->textOffset + wineItem->textWidth) - { - lpht->flags = TVHT_ONITEMRIGHT; - } - else if (x >= wineItem->textOffset) - { - lpht->flags = TVHT_ONITEMLABEL; - } - else if (x >= wineItem->imageOffset) - { - lpht->flags = TVHT_ONITEMICON; - } - else if (x >= wineItem->stateOffset) - { - lpht->flags = TVHT_ONITEMSTATEICON; - } - else if (x >= wineItem->linesOffset && infoPtr->dwStyle & TVS_HASBUTTONS) - { - lpht->flags = TVHT_ONITEMBUTTON; - } - else - { - lpht->flags = TVHT_ONITEMINDENT; - } - - lpht->hItem = wineItem; - TRACE("(%ld,%ld):result %x\n", lpht->pt.x, lpht->pt.y, lpht->flags); - - return (LRESULT)wineItem; -} - -/* Item Label Editing ***************************************************/ - -static LRESULT -TREEVIEW_GetEditControl(TREEVIEW_INFO *infoPtr) -{ - return (LRESULT)infoPtr->hwndEdit; -} - -static LRESULT CALLBACK -TREEVIEW_Edit_SubclassProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam) -{ - TREEVIEW_INFO *infoPtr = TREEVIEW_GetInfoPtr(GetParent(hwnd)); - BOOL bCancel = FALSE; - LRESULT rc; - - switch (uMsg) - { - case WM_PAINT: - TRACE("WM_PAINT start\n"); - rc = CallWindowProcW(infoPtr->wpEditOrig, hwnd, uMsg, wParam, - lParam); - TRACE("WM_PAINT done\n"); - return rc; - - case WM_KILLFOCUS: - if (infoPtr->bIgnoreEditKillFocus) - return TRUE; - break; - - case WM_GETDLGCODE: - return DLGC_WANTARROWS | DLGC_WANTALLKEYS; - - case WM_KEYDOWN: - if (wParam == (WPARAM)VK_ESCAPE) - { - bCancel = TRUE; - break; - } - else if (wParam == (WPARAM)VK_RETURN) - { - break; - } - - /* fall through */ - default: - return CallWindowProcW(infoPtr->wpEditOrig, hwnd, uMsg, wParam, lParam); - } - - /* Processing TVN_ENDLABELEDIT message could kill the focus */ - /* eg. Using a messagebox */ - - infoPtr->bIgnoreEditKillFocus = TRUE; - TREEVIEW_EndEditLabelNow(infoPtr, bCancel || !infoPtr->bLabelChanged); - infoPtr->bIgnoreEditKillFocus = FALSE; - - return 0; -} - - -/* should handle edit control messages here */ - -static LRESULT -TREEVIEW_Command(TREEVIEW_INFO *infoPtr, WPARAM wParam, LPARAM lParam) -{ - TRACE("%x %ld\n", wParam, lParam); - - switch (HIWORD(wParam)) - { - case EN_UPDATE: - { - /* - * Adjust the edit window size - */ - WCHAR buffer[1024]; - TREEVIEW_ITEM *editItem = infoPtr->selectedItem; - HDC hdc = GetDC(infoPtr->hwndEdit); - SIZE sz; - int len; - HFONT hFont, hOldFont = 0; - - infoPtr->bLabelChanged = TRUE; - - len = GetWindowTextW(infoPtr->hwndEdit, buffer, sizeof(buffer)); - - /* Select font to get the right dimension of the string */ - hFont = (HFONT)SendMessageW(infoPtr->hwndEdit, WM_GETFONT, 0, 0); - - if (hFont != 0) - { - hOldFont = SelectObject(hdc, hFont); - } - - if (GetTextExtentPoint32W(hdc, buffer, strlenW(buffer), &sz)) - { - TEXTMETRICW textMetric; - - /* Add Extra spacing for the next character */ - GetTextMetricsW(hdc, &textMetric); - sz.cx += (textMetric.tmMaxCharWidth * 2); - - sz.cx = max(sz.cx, textMetric.tmMaxCharWidth * 3); - sz.cx = min(sz.cx, - infoPtr->clientWidth - editItem->textOffset + 2); - - SetWindowPos(infoPtr->hwndEdit, - HWND_TOP, - 0, - 0, - sz.cx, - editItem->rect.bottom - editItem->rect.top + 3, - SWP_NOMOVE | SWP_DRAWFRAME); - } - - if (hFont != 0) - { - SelectObject(hdc, hOldFont); - } - - ReleaseDC(infoPtr->hwnd, hdc); - break; - } - - default: - return SendMessageW(infoPtr->hwndNotify, WM_COMMAND, wParam, lParam); - } - - return 0; -} - -static HWND -TREEVIEW_EditLabel(TREEVIEW_INFO *infoPtr, HTREEITEM hItem) -{ - HWND hwnd = infoPtr->hwnd; - HWND hwndEdit; - SIZE sz; - TREEVIEW_ITEM *editItem = hItem; - HINSTANCE hinst = (HINSTANCE)GetWindowLongPtrW(hwnd, GWLP_HINSTANCE); - HDC hdc; - HFONT hOldFont=0; - TEXTMETRICW textMetric; - static const WCHAR EditW[] = {'E','d','i','t',0}; - - TRACE("%x %p\n", (unsigned)hwnd, hItem); - if (!TREEVIEW_ValidItem(infoPtr, editItem)) - return NULL; - - if (infoPtr->hwndEdit) - return infoPtr->hwndEdit; - - infoPtr->bLabelChanged = FALSE; - - /* Make sure that edit item is selected */ - TREEVIEW_DoSelectItem(infoPtr, TVGN_CARET, hItem, TVC_UNKNOWN); - TREEVIEW_EnsureVisible(infoPtr, hItem, TRUE); - - TREEVIEW_UpdateDispInfo(infoPtr, editItem, TVIF_TEXT); - - hdc = GetDC(hwnd); - /* Select the font to get appropriate metric dimensions */ - if (infoPtr->hFont != 0) - { - hOldFont = SelectObject(hdc, infoPtr->hFont); - } - - /* Get string length in pixels */ - GetTextExtentPoint32W(hdc, editItem->pszText, strlenW(editItem->pszText), - &sz); - - /* Add Extra spacing for the next character */ - GetTextMetricsW(hdc, &textMetric); - sz.cx += (textMetric.tmMaxCharWidth * 2); - - sz.cx = max(sz.cx, textMetric.tmMaxCharWidth * 3); - sz.cx = min(sz.cx, infoPtr->clientWidth - editItem->textOffset + 2); - - if (infoPtr->hFont != 0) - { - SelectObject(hdc, hOldFont); - } - - ReleaseDC(hwnd, hdc); - hwndEdit = CreateWindowExW(WS_EX_LEFT, - EditW, - 0, - WS_CHILD | WS_BORDER | ES_AUTOHSCROLL | - WS_CLIPSIBLINGS | ES_WANTRETURN | - ES_LEFT, editItem->textOffset - 2, - editItem->rect.top - 1, sz.cx + 3, - editItem->rect.bottom - - editItem->rect.top + 3, hwnd, 0, hinst, 0); -/* FIXME: (HMENU)IDTVEDIT,pcs->hInstance,0); */ - - infoPtr->hwndEdit = hwndEdit; - - /* Get a 2D border. */ - SetWindowLongW(hwndEdit, GWL_EXSTYLE, - GetWindowLongW(hwndEdit, GWL_EXSTYLE) & ~WS_EX_CLIENTEDGE); - SetWindowLongW(hwndEdit, GWL_STYLE, - GetWindowLongW(hwndEdit, GWL_STYLE) | WS_BORDER); - - SendMessageW(hwndEdit, WM_SETFONT, - (WPARAM)TREEVIEW_FontForItem(infoPtr, editItem), FALSE); - - infoPtr->wpEditOrig = (WNDPROC)SetWindowLongPtrW(hwndEdit, GWLP_WNDPROC, - (DWORD_PTR) - TREEVIEW_Edit_SubclassProc); - - if (TREEVIEW_BeginLabelEditNotify(infoPtr, editItem)) - { - DestroyWindow(hwndEdit); - infoPtr->hwndEdit = 0; - return NULL; - } - - infoPtr->selectedItem = hItem; - SetWindowTextW(hwndEdit, editItem->pszText); - SetFocus(hwndEdit); - SendMessageW(hwndEdit, EM_SETSEL, 0, -1); - ShowWindow(hwndEdit, SW_SHOW); - - return hwndEdit; -} - - -static LRESULT -TREEVIEW_EndEditLabelNow(TREEVIEW_INFO *infoPtr, BOOL bCancel) -{ - HWND hwnd = infoPtr->hwnd; - TREEVIEW_ITEM *editedItem = infoPtr->selectedItem; - NMTVDISPINFOW tvdi; - BOOL bCommit; - WCHAR tmpText[1024] = { '\0' }; - WCHAR *newText = tmpText; - int iLength = 0; - - if (!infoPtr->hwndEdit) - return FALSE; - - tvdi.hdr.hwndFrom = hwnd; - tvdi.hdr.idFrom = GetWindowLongPtrW(hwnd, GWLP_ID); - tvdi.hdr.code = get_notifycode(infoPtr, TVN_ENDLABELEDITW); - tvdi.item.mask = 0; - tvdi.item.hItem = editedItem; - tvdi.item.state = editedItem->state; - tvdi.item.lParam = editedItem->lParam; - - if (!bCancel) - { - if (!infoPtr->bNtfUnicode) - iLength = GetWindowTextA(infoPtr->hwndEdit, (LPSTR)tmpText, 1023); - else - iLength = GetWindowTextW(infoPtr->hwndEdit, tmpText, 1023); - - if (iLength >= 1023) - { - ERR("Insufficient space to retrieve new item label\n"); - } - - tvdi.item.mask = TVIF_TEXT; - tvdi.item.pszText = tmpText; - tvdi.item.cchTextMax = iLength + 1; - } - else - { - tvdi.item.pszText = NULL; - tvdi.item.cchTextMax = 0; - } - - bCommit = (BOOL)TREEVIEW_SendRealNotify(infoPtr, - (WPARAM)tvdi.hdr.idFrom, (LPARAM)&tvdi); - - if (!bCancel && bCommit) /* Apply the changes */ - { - if (!infoPtr->bNtfUnicode) - { - DWORD len = MultiByteToWideChar( CP_ACP, 0, (LPSTR)tmpText, -1, NULL, 0 ); - newText = Alloc(len * sizeof(WCHAR)); - MultiByteToWideChar( CP_ACP, 0, (LPSTR)tmpText, -1, newText, len ); - iLength = len - 1; - } - - if (strcmpW(newText, editedItem->pszText) != 0) - { - if (NULL == ReAlloc(editedItem->pszText, iLength + 1)) - { - ERR("OutOfMemory, cannot allocate space for label\n"); - DestroyWindow(infoPtr->hwndEdit); - infoPtr->hwndEdit = 0; - return FALSE; - } - else - { - editedItem->cchTextMax = iLength + 1; - strcpyW(editedItem->pszText, newText); - } - } - if(newText != tmpText) Free(newText); - } - - ShowWindow(infoPtr->hwndEdit, SW_HIDE); - DestroyWindow(infoPtr->hwndEdit); - infoPtr->hwndEdit = 0; - return TRUE; -} - -static LRESULT -TREEVIEW_HandleTimer(TREEVIEW_INFO *infoPtr, WPARAM wParam) -{ - if (wParam != TV_EDIT_TIMER) - { - ERR("got unknown timer\n"); - return 1; - } - - KillTimer(infoPtr->hwnd, TV_EDIT_TIMER); - infoPtr->Timer &= ~TV_EDIT_TIMER_SET; - - TREEVIEW_EditLabel(infoPtr, infoPtr->selectedItem); - - return 0; -} - - -/* Mouse Tracking/Drag **************************************************/ - -/*************************************************************************** - * This is quite unusual piece of code, but that's how it's implemented in - * Windows. - */ -static LRESULT -TREEVIEW_TrackMouse(TREEVIEW_INFO *infoPtr, POINT pt) -{ - INT cxDrag = GetSystemMetrics(SM_CXDRAG); - INT cyDrag = GetSystemMetrics(SM_CYDRAG); - RECT r; - MSG msg; - - r.top = pt.y - cyDrag; - r.left = pt.x - cxDrag; - r.bottom = pt.y + cyDrag; - r.right = pt.x + cxDrag; - - SetCapture(infoPtr->hwnd); - - while (1) - { - if (PeekMessageA(&msg, 0, 0, 0, PM_REMOVE | PM_NOYIELD)) - { - if (msg.message == WM_MOUSEMOVE) - { - pt.x = (short)LOWORD(msg.lParam); - pt.y = (short)HIWORD(msg.lParam); - if (PtInRect(&r, pt)) - continue; - else - { - ReleaseCapture(); - return 1; - } - } - else if (msg.message >= WM_LBUTTONDOWN && - msg.message <= WM_RBUTTONDBLCLK) - { - if (msg.message == WM_RBUTTONUP) - TREEVIEW_RButtonUp(infoPtr, &pt); - break; - } - - DispatchMessageA(&msg); - } - - if (GetCapture() != infoPtr->hwnd) - return 0; - } - - ReleaseCapture(); - return 0; -} - - -static LRESULT -TREEVIEW_LButtonDoubleClick(TREEVIEW_INFO *infoPtr, LPARAM lParam) -{ - TREEVIEW_ITEM *wineItem; - TVHITTESTINFO hit; - - TRACE("\n"); - SetFocus(infoPtr->hwnd); - - if (infoPtr->Timer & TV_EDIT_TIMER_SET) - { - /* If there is pending 'edit label' event - kill it now */ - KillTimer(infoPtr->hwnd, TV_EDIT_TIMER); - } - - hit.pt.x = (short)LOWORD(lParam); - hit.pt.y = (short)HIWORD(lParam); - - wineItem = (TREEVIEW_ITEM *)TREEVIEW_HitTest(infoPtr, &hit); - if (!wineItem) - return 0; - TRACE("item %d\n", TREEVIEW_GetItemIndex(infoPtr, wineItem)); - - if (TREEVIEW_SendSimpleNotify(infoPtr, NM_DBLCLK) == FALSE) - { /* FIXME! */ - switch (hit.flags) - { - case TVHT_ONITEMRIGHT: - /* FIXME: we should not have sent NM_DBLCLK in this case. */ - break; - - case TVHT_ONITEMINDENT: - if (!(infoPtr->dwStyle & TVS_HASLINES)) - { - break; - } - else - { - int level = hit.pt.x / infoPtr->uIndent; - if (!(infoPtr->dwStyle & TVS_LINESATROOT)) level++; - - while (wineItem->iLevel > level) - { - wineItem = wineItem->parent; - } - - /* fall through */ - } - - case TVHT_ONITEMLABEL: - case TVHT_ONITEMICON: - case TVHT_ONITEMBUTTON: - TREEVIEW_Toggle(infoPtr, wineItem, TRUE); - break; - - case TVHT_ONITEMSTATEICON: - if (infoPtr->dwStyle & TVS_CHECKBOXES) - TREEVIEW_ToggleItemState(infoPtr, wineItem); - else - TREEVIEW_Toggle(infoPtr, wineItem, TRUE); - break; - } - } - return TRUE; -} - - -static LRESULT -TREEVIEW_LButtonDown(TREEVIEW_INFO *infoPtr, LPARAM lParam) -{ - HWND hwnd = infoPtr->hwnd; - TVHITTESTINFO ht; - BOOL bTrack, bDoLabelEdit; - HTREEITEM tempItem; - - /* If Edit control is active - kill it and return. - * The best way to do it is to set focus to itself. - * Edit control subclassed procedure will automatically call - * EndEditLabelNow. - */ - if (infoPtr->hwndEdit) - { - SetFocus(hwnd); - return 0; - } - - ht.pt.x = (short)LOWORD(lParam); - ht.pt.y = (short)HIWORD(lParam); - - TREEVIEW_HitTest(infoPtr, &ht); - TRACE("item %d\n", TREEVIEW_GetItemIndex(infoPtr, ht.hItem)); - - /* update focusedItem and redraw both items */ - if(ht.hItem && (ht.flags & TVHT_ONITEM)) - { - infoPtr->focusedItem = ht.hItem; - InvalidateRect(hwnd, &(((HTREEITEM)(ht.hItem))->rect), TRUE); - - if(infoPtr->selectedItem) - InvalidateRect(hwnd, &(infoPtr->selectedItem->rect), TRUE); - } - - bTrack = (ht.flags & TVHT_ONITEM) - && !(infoPtr->dwStyle & TVS_DISABLEDRAGDROP); - - /* - * If the style allows editing and the node is already selected - * and the click occurred on the item label... - */ - bDoLabelEdit = (infoPtr->dwStyle & TVS_EDITLABELS) && - (ht.flags & TVHT_ONITEMLABEL) && (infoPtr->selectedItem == ht.hItem); - - /* Send NM_CLICK right away */ - if (!bTrack) - if (TREEVIEW_SendSimpleNotify(infoPtr, NM_CLICK)) - goto setfocus; - - if (ht.flags & TVHT_ONITEMBUTTON) - { - TREEVIEW_Toggle(infoPtr, ht.hItem, TRUE); - goto setfocus; - } - else if (bTrack) - { /* if TREEVIEW_TrackMouse == 1 dragging occurred and the cursor left the dragged item's rectangle */ - if (TREEVIEW_TrackMouse(infoPtr, ht.pt)) - { - TREEVIEW_SendTreeviewDnDNotify(infoPtr, TVN_BEGINDRAGW, ht.hItem, ht.pt); - infoPtr->dropItem = ht.hItem; - - /* clean up focusedItem as we dragged and won't select this item */ - if(infoPtr->focusedItem) - { - /* refresh the item that was focused */ - tempItem = infoPtr->focusedItem; - infoPtr->focusedItem = 0; - InvalidateRect(infoPtr->hwnd, &tempItem->rect, TRUE); - - /* refresh the selected item to return the filled background */ - InvalidateRect(infoPtr->hwnd, &(infoPtr->selectedItem->rect), TRUE); - } - - return 0; - } - } - - if (bTrack && TREEVIEW_SendSimpleNotify(infoPtr, NM_CLICK)) - goto setfocus; - - if (bDoLabelEdit) - { - if (infoPtr->Timer & TV_EDIT_TIMER_SET) - KillTimer(hwnd, TV_EDIT_TIMER); - - SetTimer(hwnd, TV_EDIT_TIMER, GetDoubleClickTime(), 0); - infoPtr->Timer |= TV_EDIT_TIMER_SET; - } - else if (ht.flags & (TVHT_ONITEMICON|TVHT_ONITEMLABEL)) /* select the item if the hit was inside of the icon or text */ - { - /* - * if we are TVS_SINGLEEXPAND then we want this single click to - * do a bunch of things. - */ - if((infoPtr->dwStyle & TVS_SINGLEEXPAND) && - (infoPtr->hwndEdit == 0)) - { - TREEVIEW_ITEM *SelItem; - - /* - * Send the notification - */ - TREEVIEW_SendTreeviewNotify(infoPtr, TVN_SINGLEEXPAND, TVC_UNKNOWN, TVIF_HANDLE | TVIF_PARAM, ht.hItem, 0); - - /* - * Close the previous selection all the way to the root - * as long as the new selection is not a child - */ - if((infoPtr->selectedItem) - && (infoPtr->selectedItem != ht.hItem)) - { - BOOL closeit = TRUE; - SelItem = ht.hItem; - - /* determine if the hitItem is a child of the currently selected item */ - while(closeit && SelItem && TREEVIEW_ValidItem(infoPtr, SelItem) && (SelItem != infoPtr->root)) - { - closeit = (SelItem != infoPtr->selectedItem); - SelItem = SelItem->parent; - } - - if(closeit) - { - if(TREEVIEW_ValidItem(infoPtr, infoPtr->selectedItem)) - SelItem = infoPtr->selectedItem; - - while(SelItem && (SelItem != ht.hItem) && TREEVIEW_ValidItem(infoPtr, SelItem) && (SelItem != infoPtr->root)) - { - TREEVIEW_Collapse(infoPtr, SelItem, FALSE, FALSE); - SelItem = SelItem->parent; - } - } - } - - /* - * Expand the current item - */ - TREEVIEW_Expand(infoPtr, ht.hItem, TVE_TOGGLE, FALSE); - } - - /* Select the current item */ - TREEVIEW_DoSelectItem(infoPtr, TVGN_CARET, ht.hItem, TVC_BYMOUSE); - } - else if (ht.flags & TVHT_ONITEMSTATEICON) - { - /* TVS_CHECKBOXES requires us to toggle the current state */ - if (infoPtr->dwStyle & TVS_CHECKBOXES) - TREEVIEW_ToggleItemState(infoPtr, ht.hItem); - } - - setfocus: - SetFocus(hwnd); - return 0; -} - - -static LRESULT -TREEVIEW_RButtonDown(TREEVIEW_INFO *infoPtr, LPARAM lParam) -{ - TVHITTESTINFO ht; - - if (infoPtr->hwndEdit) - { - SetFocus(infoPtr->hwnd); - return 0; - } - - ht.pt.x = (short)LOWORD(lParam); - ht.pt.y = (short)HIWORD(lParam); - - TREEVIEW_HitTest(infoPtr, &ht); - - if (TREEVIEW_TrackMouse(infoPtr, ht.pt)) - { - if (ht.hItem) - { - TREEVIEW_SendTreeviewDnDNotify(infoPtr, TVN_BEGINRDRAGW, ht.hItem, ht.pt); - infoPtr->dropItem = ht.hItem; - } - } - else - { - SetFocus(infoPtr->hwnd); - TREEVIEW_SendSimpleNotify(infoPtr, NM_RCLICK); - } - - return 0; -} - -static LRESULT -TREEVIEW_RButtonUp(TREEVIEW_INFO *infoPtr, LPPOINT pPt) -{ - return 0; -} - - -static LRESULT -TREEVIEW_CreateDragImage(TREEVIEW_INFO *infoPtr, WPARAM wParam, LPARAM lParam) -{ - TREEVIEW_ITEM *dragItem = (HTREEITEM)lParam; - INT cx, cy; - HDC hdc, htopdc; - HWND hwtop; - HBITMAP hbmp, hOldbmp; - SIZE size; - RECT rc; - HFONT hOldFont; - - TRACE("\n"); - - if (!(infoPtr->himlNormal)) - return 0; - - if (!dragItem || !TREEVIEW_ValidItem(infoPtr, dragItem)) - return 0; - - TREEVIEW_UpdateDispInfo(infoPtr, dragItem, TVIF_TEXT); - - hwtop = GetDesktopWindow(); - htopdc = GetDC(hwtop); - hdc = CreateCompatibleDC(htopdc); - - hOldFont = SelectObject(hdc, infoPtr->hFont); - GetTextExtentPoint32W(hdc, dragItem->pszText, strlenW(dragItem->pszText), - &size); - TRACE("%ld %ld %s %d\n", size.cx, size.cy, debugstr_w(dragItem->pszText), - strlenW(dragItem->pszText)); - hbmp = CreateCompatibleBitmap(htopdc, size.cx, size.cy); - hOldbmp = SelectObject(hdc, hbmp); - - ImageList_GetIconSize(infoPtr->himlNormal, &cx, &cy); - size.cx += cx; - if (cy > size.cy) - size.cy = cy; - - infoPtr->dragList = ImageList_Create(size.cx, size.cy, ILC_COLOR, 10, 10); - ImageList_Draw(infoPtr->himlNormal, dragItem->iImage, hdc, 0, 0, - ILD_NORMAL); - -/* - ImageList_GetImageInfo (infoPtr->himlNormal, dragItem->hItem, &iminfo); - ImageList_AddMasked (infoPtr->dragList, iminfo.hbmImage, CLR_DEFAULT); -*/ - -/* draw item text */ - - SetRect(&rc, cx, 0, size.cx, size.cy); - DrawTextW(hdc, dragItem->pszText, strlenW(dragItem->pszText), &rc, - DT_LEFT); - SelectObject(hdc, hOldFont); - SelectObject(hdc, hOldbmp); - - ImageList_Add(infoPtr->dragList, hbmp, 0); - - DeleteDC(hdc); - DeleteObject(hbmp); - ReleaseDC(hwtop, htopdc); - - return (LRESULT)infoPtr->dragList; -} - -/* Selection ************************************************************/ - -static LRESULT -TREEVIEW_DoSelectItem(TREEVIEW_INFO *infoPtr, INT action, HTREEITEM newSelect, - INT cause) -{ - TREEVIEW_ITEM *prevSelect; - RECT rcFocused; - - assert(newSelect == NULL || TREEVIEW_ValidItem(infoPtr, newSelect)); - - TRACE("Entering item %p (%s), flag %x, cause %x, state %d\n", - newSelect, TREEVIEW_ItemName(newSelect), action, cause, - newSelect ? newSelect->state : 0); - - /* reset and redraw focusedItem if focusedItem was set so we don't */ - /* have to worry about the previously focused item when we set a new one */ - if(infoPtr->focusedItem) - { - rcFocused = (infoPtr->focusedItem)->rect; - infoPtr->focusedItem = 0; - InvalidateRect(infoPtr->hwnd, &rcFocused, TRUE); - } - - switch (action) - { - case TVGN_CARET: - prevSelect = infoPtr->selectedItem; - - if (prevSelect == newSelect) - return FALSE; - - if (TREEVIEW_SendTreeviewNotify(infoPtr, - TVN_SELCHANGINGW, - cause, - TVIF_HANDLE | TVIF_STATE | TVIF_PARAM, - prevSelect, - newSelect)) - return FALSE; - - if (prevSelect) - prevSelect->state &= ~TVIS_SELECTED; - if (newSelect) - newSelect->state |= TVIS_SELECTED; - - infoPtr->selectedItem = newSelect; - - TREEVIEW_EnsureVisible(infoPtr, infoPtr->selectedItem, FALSE); - - TREEVIEW_SendTreeviewNotify(infoPtr, - TVN_SELCHANGEDW, - cause, - TVIF_HANDLE | TVIF_STATE | TVIF_PARAM, - prevSelect, - newSelect); - TREEVIEW_Invalidate(infoPtr, prevSelect); - TREEVIEW_Invalidate(infoPtr, newSelect); - break; - - case TVGN_DROPHILITE: - prevSelect = infoPtr->dropItem; - - if (prevSelect) - prevSelect->state &= ~TVIS_DROPHILITED; - - infoPtr->dropItem = newSelect; - - if (newSelect) - newSelect->state |= TVIS_DROPHILITED; - - TREEVIEW_Invalidate(infoPtr, prevSelect); - TREEVIEW_Invalidate(infoPtr, newSelect); - break; - - case TVGN_FIRSTVISIBLE: - TREEVIEW_EnsureVisible(infoPtr, newSelect, FALSE); - TREEVIEW_SetFirstVisible(infoPtr, newSelect, TRUE); - TREEVIEW_Invalidate(infoPtr, NULL); - break; - } - - TRACE("Leaving state %d\n", newSelect ? newSelect->state : 0); - return TRUE; -} - -/* FIXME: handle NM_KILLFOCUS etc */ -static LRESULT -TREEVIEW_SelectItem(TREEVIEW_INFO *infoPtr, INT wParam, HTREEITEM item) -{ - if (item != NULL && !TREEVIEW_ValidItem(infoPtr, item)) - return FALSE; - - TRACE("%p (%s) %d\n", item, TREEVIEW_ItemName(item), wParam); - - if (!TREEVIEW_DoSelectItem(infoPtr, wParam, item, TVC_UNKNOWN)) - return FALSE; - - return TRUE; -} - -/************************************************************************* - * TREEVIEW_ProcessLetterKeys - * - * Processes keyboard messages generated by pressing the letter keys - * on the keyboard. - * What this does is perform a case insensitive search from the - * current position with the following quirks: - * - If two chars or more are pressed in quick succession we search - * for the corresponding string (e.g. 'abc'). - * - If there is a delay we wipe away the current search string and - * restart with just that char. - * - If the user keeps pressing the same character, whether slowly or - * fast, so that the search string is entirely composed of this - * character ('aaaaa' for instance), then we search for first item - * that starting with that character. - * - If the user types the above character in quick succession, then - * we must also search for the corresponding string ('aaaaa'), and - * go to that string if there is a match. - * - * RETURNS - * - * Zero. - * - * BUGS - * - * - The current implementation has a list of characters it will - * accept and it ignores averything else. In particular it will - * ignore accentuated characters which seems to match what - * Windows does. But I'm not sure it makes sense to follow - * Windows there. - * - We don't sound a beep when the search fails. - * - The search should start from the focused item, not from the selected - * item. One reason for this is to allow for multiple selections in trees. - * But currently infoPtr->focusedItem does not seem very usable. - * - * SEE ALSO - * - * TREEVIEW_ProcessLetterKeys - */ -static INT TREEVIEW_ProcessLetterKeys( - HWND hwnd, /* handle to the window */ - WPARAM charCode, /* the character code, the actual character */ - LPARAM keyData /* key data */ - ) -{ - TREEVIEW_INFO *infoPtr; - HTREEITEM nItem; - HTREEITEM endidx,idx; - TVITEMEXW item; - WCHAR buffer[MAX_PATH]; - DWORD timestamp,elapsed; - - /* simple parameter checking */ - if (!hwnd || !charCode || !keyData) - return 0; - - infoPtr=(TREEVIEW_INFO*)GetWindowLongPtrW(hwnd, 0); - if (!infoPtr) - return 0; - - /* only allow the valid WM_CHARs through */ - if (!isalnum(charCode) && - charCode != '.' && charCode != '`' && charCode != '!' && - charCode != '@' && charCode != '#' && charCode != '$' && - charCode != '%' && charCode != '^' && charCode != '&' && - charCode != '*' && charCode != '(' && charCode != ')' && - charCode != '-' && charCode != '_' && charCode != '+' && - charCode != '=' && charCode != '\\'&& charCode != ']' && - charCode != '}' && charCode != '[' && charCode != '{' && - charCode != '/' && charCode != '?' && charCode != '>' && - charCode != '<' && charCode != ',' && charCode != '~') - return 0; - - /* compute how much time elapsed since last keypress */ - timestamp = GetTickCount(); - if (timestamp > infoPtr->lastKeyPressTimestamp) { - elapsed=timestamp-infoPtr->lastKeyPressTimestamp; - } else { - elapsed=infoPtr->lastKeyPressTimestamp-timestamp; - } - - /* update the search parameters */ - infoPtr->lastKeyPressTimestamp=timestamp; - if (elapsed < KEY_DELAY) { - if (infoPtr->nSearchParamLength < sizeof(infoPtr->szSearchParam) / sizeof(WCHAR)) { - infoPtr->szSearchParam[infoPtr->nSearchParamLength++]=charCode; - } - if (infoPtr->charCode != charCode) { - infoPtr->charCode=charCode=0; - } - } else { - infoPtr->charCode=charCode; - infoPtr->szSearchParam[0]=charCode; - infoPtr->nSearchParamLength=1; - /* Redundant with the 1 char string */ - charCode=0; - } - - /* and search from the current position */ - nItem=NULL; - if (infoPtr->selectedItem != NULL) { - endidx=infoPtr->selectedItem; - /* if looking for single character match, - * then we must always move forward - */ - if (infoPtr->nSearchParamLength == 1) - idx=TREEVIEW_GetNextListItem(infoPtr,endidx); - else - idx=endidx; - } else { - endidx=NULL; - idx=infoPtr->root->firstChild; - } - do { - if (idx == NULL) { - if (endidx == NULL) - break; - idx=infoPtr->root->firstChild; - } - - /* get item */ - ZeroMemory(&item, sizeof(item)); - item.mask = TVIF_TEXT; - item.hItem = idx; - item.pszText = buffer; - item.cchTextMax = sizeof(buffer); - TREEVIEW_GetItemT( infoPtr, &item, TRUE ); - - /* check for a match */ - if (strncmpiW(item.pszText,infoPtr->szSearchParam,infoPtr->nSearchParamLength) == 0) { - nItem=idx; - break; - } else if ( (charCode != 0) && (nItem == NULL) && - (nItem != infoPtr->selectedItem) && - (strncmpiW(item.pszText,infoPtr->szSearchParam,1) == 0) ) { - /* This would work but we must keep looking for a longer match */ - nItem=idx; - } - idx=TREEVIEW_GetNextListItem(infoPtr,idx); - } while (idx != endidx); - - if (nItem != NULL) { - if (TREEVIEW_DoSelectItem(infoPtr, TVGN_CARET, nItem, TVC_BYKEYBOARD)) { - TREEVIEW_EnsureVisible(infoPtr, nItem, FALSE); - } - } - - return 0; -} - -/* Scrolling ************************************************************/ - -static LRESULT -TREEVIEW_EnsureVisible(TREEVIEW_INFO *infoPtr, HTREEITEM item, BOOL bHScroll) -{ - int viscount; - BOOL hasFirstVisible = infoPtr->firstVisible != NULL; - HTREEITEM newFirstVisible = NULL; - int visible_pos = -1; - - if (!TREEVIEW_ValidItem(infoPtr, item)) - return FALSE; - - if (!ISVISIBLE(item)) - { - /* Expand parents as necessary. */ - HTREEITEM parent; - - /* see if we are trying to ensure that root is vislble */ - if((item != infoPtr->root) && TREEVIEW_ValidItem(infoPtr, item)) - parent = item->parent; - else - parent = item; /* this item is the topmost item */ - - while (parent != infoPtr->root) - { - if (!(parent->state & TVIS_EXPANDED)) - TREEVIEW_Expand(infoPtr, parent, FALSE, FALSE); - - parent = parent->parent; - } - } - - viscount = TREEVIEW_GetVisibleCount(infoPtr); - - TRACE("%p (%s) %ld - %ld viscount(%d)\n", item, TREEVIEW_ItemName(item), item->visibleOrder, - hasFirstVisible ? infoPtr->firstVisible->visibleOrder : -1, viscount); - - if (hasFirstVisible) - visible_pos = item->visibleOrder - infoPtr->firstVisible->visibleOrder; - - if (visible_pos < 0) - { - /* item is before the start of the list: put it at the top. */ - newFirstVisible = item; - } - else if (visible_pos >= viscount - /* Sometimes, before we are displayed, GVC is 0, causing us to - * spuriously scroll up. */ - && visible_pos > 0 && !(infoPtr->dwStyle & TVS_NOSCROLL) ) - { - /* item is past the end of the list. */ - int scroll = visible_pos - viscount; - - newFirstVisible = TREEVIEW_GetListItem(infoPtr, infoPtr->firstVisible, - scroll + 1); - } - - if (bHScroll) - { - /* Scroll window so item's text is visible as much as possible */ - /* Calculation of amount of extra space is taken from EditLabel code */ - INT pos, x; - TEXTMETRICW textMetric; - HDC hdc = GetWindowDC(infoPtr->hwnd); - - x = item->textWidth; - - GetTextMetricsW(hdc, &textMetric); - ReleaseDC(infoPtr->hwnd, hdc); - - x += (textMetric.tmMaxCharWidth * 2); - x = max(x, textMetric.tmMaxCharWidth * 3); - - if (item->textOffset < 0) - pos = item->textOffset; - else if (item->textOffset + x > infoPtr->clientWidth) - { - if (x > infoPtr->clientWidth) - pos = item->textOffset; - else - pos = item->textOffset + x - infoPtr->clientWidth; - } - else - pos = 0; - - TREEVIEW_HScroll(infoPtr, MAKEWPARAM(SB_THUMBPOSITION, infoPtr->scrollX + pos)); - } - - if (newFirstVisible != NULL && newFirstVisible != infoPtr->firstVisible) - { - TREEVIEW_SetFirstVisible(infoPtr, newFirstVisible, TRUE); - - return TRUE; - } - - return FALSE; -} - -static VOID -TREEVIEW_SetFirstVisible(TREEVIEW_INFO *infoPtr, - TREEVIEW_ITEM *newFirstVisible, - BOOL bUpdateScrollPos) -{ - int gap_size; - - TRACE("%p: %s\n", newFirstVisible, TREEVIEW_ItemName(newFirstVisible)); - - if (newFirstVisible != NULL) - { - /* Prevent an empty gap from appearing at the bottom... */ - gap_size = TREEVIEW_GetVisibleCount(infoPtr) - - infoPtr->maxVisibleOrder + newFirstVisible->visibleOrder; - - if (gap_size > 0) - { - newFirstVisible = TREEVIEW_GetListItem(infoPtr, newFirstVisible, - -gap_size); - - /* ... unless we just don't have enough items. */ - if (newFirstVisible == NULL) - newFirstVisible = infoPtr->root->firstChild; - } - } - - if (infoPtr->firstVisible != newFirstVisible) - { - if (infoPtr->firstVisible == NULL || newFirstVisible == NULL) - { - infoPtr->firstVisible = newFirstVisible; - TREEVIEW_Invalidate(infoPtr, NULL); - } - else - { - TREEVIEW_ITEM *item; - int scroll = infoPtr->uItemHeight * - (infoPtr->firstVisible->visibleOrder - - newFirstVisible->visibleOrder); - - infoPtr->firstVisible = newFirstVisible; - - for (item = infoPtr->root->firstChild; item != NULL; - item = TREEVIEW_GetNextListItem(infoPtr, item)) - { - item->rect.top += scroll; - item->rect.bottom += scroll; - } - - if (bUpdateScrollPos) - SetScrollPos(infoPtr->hwnd, SB_VERT, - newFirstVisible->visibleOrder, TRUE); - - ScrollWindowEx(infoPtr->hwnd, 0, scroll, NULL, NULL, NULL, NULL, SW_ERASE | SW_INVALIDATE); - } - } -} - -/************************************************************************ - * VScroll is always in units of visible items. i.e. we always have a - * visible item aligned to the top of the control. (Unless we have no - * items at all.) - */ -static LRESULT -TREEVIEW_VScroll(TREEVIEW_INFO *infoPtr, WPARAM wParam) -{ - TREEVIEW_ITEM *oldFirstVisible = infoPtr->firstVisible; - TREEVIEW_ITEM *newFirstVisible = NULL; - - int nScrollCode = LOWORD(wParam); - - TRACE("wp %x\n", wParam); - - if (!(infoPtr->uInternalStatus & TV_VSCROLL)) - return 0; - - if (infoPtr->hwndEdit) - SetFocus(infoPtr->hwnd); - - if (!oldFirstVisible) - { - assert(infoPtr->root->firstChild == NULL); - return 0; - } - - switch (nScrollCode) - { - case SB_TOP: - newFirstVisible = infoPtr->root->firstChild; - break; - - case SB_BOTTOM: - newFirstVisible = TREEVIEW_GetLastListItem(infoPtr, infoPtr->root); - break; - - case SB_LINEUP: - newFirstVisible = TREEVIEW_GetPrevListItem(infoPtr, oldFirstVisible); - break; - - case SB_LINEDOWN: - newFirstVisible = TREEVIEW_GetNextListItem(infoPtr, oldFirstVisible); - break; - - case SB_PAGEUP: - newFirstVisible = TREEVIEW_GetListItem(infoPtr, oldFirstVisible, - -max(1, TREEVIEW_GetVisibleCount(infoPtr))); - break; - - case SB_PAGEDOWN: - newFirstVisible = TREEVIEW_GetListItem(infoPtr, oldFirstVisible, - max(1, TREEVIEW_GetVisibleCount(infoPtr))); - break; - - case SB_THUMBTRACK: - case SB_THUMBPOSITION: - newFirstVisible = TREEVIEW_GetListItem(infoPtr, - infoPtr->root->firstChild, - (LONG)(SHORT)HIWORD(wParam)); - break; - - case SB_ENDSCROLL: - return 0; - } - - if (newFirstVisible != NULL) - { - if (newFirstVisible != oldFirstVisible) - TREEVIEW_SetFirstVisible(infoPtr, newFirstVisible, - nScrollCode != SB_THUMBTRACK); - else if (nScrollCode == SB_THUMBPOSITION) - SetScrollPos(infoPtr->hwnd, SB_VERT, - newFirstVisible->visibleOrder, TRUE); - } - - return 0; -} - -static LRESULT -TREEVIEW_HScroll(TREEVIEW_INFO *infoPtr, WPARAM wParam) -{ - int maxWidth; - int scrollX = infoPtr->scrollX; - int nScrollCode = LOWORD(wParam); - - TRACE("wp %x\n", wParam); - - if (!(infoPtr->uInternalStatus & TV_HSCROLL)) - return FALSE; - - if (infoPtr->hwndEdit) - SetFocus(infoPtr->hwnd); - - maxWidth = infoPtr->treeWidth - infoPtr->clientWidth; - /* shall never occur */ - if (maxWidth <= 0) - { - scrollX = 0; - goto scroll; - } - - switch (nScrollCode) - { - case SB_LINELEFT: - scrollX -= infoPtr->uItemHeight; - break; - case SB_LINERIGHT: - scrollX += infoPtr->uItemHeight; - break; - case SB_PAGELEFT: - scrollX -= infoPtr->clientWidth; - break; - case SB_PAGERIGHT: - scrollX += infoPtr->clientWidth; - break; - - case SB_THUMBTRACK: - case SB_THUMBPOSITION: - scrollX = (int)(SHORT)HIWORD(wParam); - break; - - case SB_ENDSCROLL: - return 0; - } - - if (scrollX > maxWidth) - scrollX = maxWidth; - else if (scrollX < 0) - scrollX = 0; - -scroll: - if (scrollX != infoPtr->scrollX) - { - TREEVIEW_ITEM *item; - LONG scroll_pixels = infoPtr->scrollX - scrollX; - - for (item = infoPtr->root->firstChild; item != NULL; - item = TREEVIEW_GetNextListItem(infoPtr, item)) - { - item->linesOffset += scroll_pixels; - item->stateOffset += scroll_pixels; - item->imageOffset += scroll_pixels; - item->textOffset += scroll_pixels; - } - - ScrollWindow(infoPtr->hwnd, scroll_pixels, 0, NULL, NULL); - infoPtr->scrollX = scrollX; - UpdateWindow(infoPtr->hwnd); - } - - if (nScrollCode != SB_THUMBTRACK) - SetScrollPos(infoPtr->hwnd, SB_HORZ, scrollX, TRUE); - - return 0; -} - -static LRESULT -TREEVIEW_MouseWheel(TREEVIEW_INFO *infoPtr, WPARAM wParam) -{ - short gcWheelDelta; - UINT pulScrollLines = 3; - - if (infoPtr->firstVisible == NULL) - return TRUE; - - SystemParametersInfoW(SPI_GETWHEELSCROLLLINES, 0, &pulScrollLines, 0); - - gcWheelDelta = -(short)HIWORD(wParam); - pulScrollLines *= (gcWheelDelta / WHEEL_DELTA); - - if (abs(gcWheelDelta) >= WHEEL_DELTA && pulScrollLines) - { - int newDy = infoPtr->firstVisible->visibleOrder + pulScrollLines; - int maxDy = infoPtr->maxVisibleOrder; - - if (newDy > maxDy) - newDy = maxDy; - - if (newDy < 0) - newDy = 0; - - TREEVIEW_VScroll(infoPtr, MAKEWPARAM(SB_THUMBPOSITION, newDy)); - } - return TRUE; -} - -/* Create/Destroy *******************************************************/ - -static LRESULT -TREEVIEW_Create(HWND hwnd, const CREATESTRUCTW *lpcs) -{ - static const WCHAR szDisplayW[] = { 'D','I','S','P','L','A','Y','\0' }; - RECT rcClient; - TREEVIEW_INFO *infoPtr; - LOGFONTW lf; - - TRACE("wnd %p, style %lx\n", hwnd, GetWindowLongW(hwnd, GWL_STYLE)); - - infoPtr = (TREEVIEW_INFO *)Alloc(sizeof(TREEVIEW_INFO)); - - if (infoPtr == NULL) - { - ERR("could not allocate info memory!\n"); - return 0; - } - - SetWindowLongPtrW(hwnd, 0, (DWORD_PTR)infoPtr); - - infoPtr->hwnd = hwnd; - infoPtr->dwStyle = GetWindowLongW(hwnd, GWL_STYLE); - infoPtr->uInternalStatus = 0; - infoPtr->Timer = 0; - infoPtr->uNumItems = 0; - infoPtr->cdmode = 0; - infoPtr->uScrollTime = 300; /* milliseconds */ - infoPtr->bRedraw = TRUE; - - GetClientRect(hwnd, &rcClient); - - /* No scroll bars yet. */ - infoPtr->clientWidth = rcClient.right; - infoPtr->clientHeight = rcClient.bottom; - - infoPtr->treeWidth = 0; - infoPtr->treeHeight = 0; - - infoPtr->uIndent = MINIMUM_INDENT; - infoPtr->selectedItem = 0; - infoPtr->focusedItem = 0; - /* hotItem? */ - infoPtr->firstVisible = 0; - infoPtr->maxVisibleOrder = 0; - infoPtr->dropItem = 0; - infoPtr->insertMarkItem = 0; - infoPtr->insertBeforeorAfter = 0; - /* dragList */ - - infoPtr->scrollX = 0; - - infoPtr->clrBk = GetSysColor(COLOR_WINDOW); - infoPtr->clrText = -1; /* use system color */ - infoPtr->clrLine = RGB(128, 128, 128); - infoPtr->clrInsertMark = GetSysColor(COLOR_BTNTEXT); - - /* hwndToolTip */ - - infoPtr->hwndEdit = 0; - infoPtr->wpEditOrig = NULL; - infoPtr->bIgnoreEditKillFocus = FALSE; - infoPtr->bLabelChanged = FALSE; - - infoPtr->himlNormal = NULL; - infoPtr->himlState = NULL; - infoPtr->normalImageWidth = 0; - infoPtr->normalImageHeight = 0; - infoPtr->stateImageWidth = 0; - infoPtr->stateImageHeight = 0; - - infoPtr->items = DPA_Create(16); - - SystemParametersInfoW(SPI_GETICONTITLELOGFONT, sizeof(lf), &lf, 0); - infoPtr->hFont = infoPtr->hDefaultFont = CreateFontIndirectW(&lf); - infoPtr->hBoldFont = TREEVIEW_CreateBoldFont(infoPtr->hFont); - - infoPtr->uItemHeight = TREEVIEW_NaturalHeight(infoPtr); - - infoPtr->root = TREEVIEW_AllocateItem(infoPtr); - infoPtr->root->state = TVIS_EXPANDED; - infoPtr->root->iLevel = -1; - infoPtr->root->visibleOrder = -1; - - infoPtr->hwndNotify = lpcs->hwndParent; -#if 0 - infoPtr->bTransparent = ( GetWindowLongW( hwnd, GWL_STYLE) & TBSTYLE_FLAT); -#endif - - infoPtr->hwndToolTip = 0; - - infoPtr->bNtfUnicode = IsWindowUnicode (hwnd); - - /* Determine what type of notify should be issued */ - /* sets infoPtr->bNtfUnicode */ - TREEVIEW_NotifyFormat(infoPtr, infoPtr->hwndNotify, NF_REQUERY); - - if (!(infoPtr->dwStyle & TVS_NOTOOLTIPS)) - infoPtr->hwndToolTip = COMCTL32_CreateToolTip(hwnd); - - if (infoPtr->dwStyle & TVS_CHECKBOXES) - { - RECT rc; - HBITMAP hbm, hbmOld; - HDC hdc,hdcScreen; - int nIndex; - - infoPtr->himlState = - ImageList_Create(16, 16, ILC_COLOR | ILC_MASK, 3, 0); - - hdcScreen = CreateDCW(szDisplayW, NULL, NULL, NULL); - - /* Create a coloured bitmap compatible with the screen depth - because checkboxes are not black&white */ - hdc = CreateCompatibleDC(hdcScreen); - hbm = CreateCompatibleBitmap(hdcScreen, 48, 16); - hbmOld = SelectObject(hdc, hbm); - - rc.left = 0; rc.top = 0; - rc.right = 48; rc.bottom = 16; - FillRect(hdc, &rc, (HBRUSH)(COLOR_WINDOW+1)); - - rc.left = 18; rc.top = 2; - rc.right = 30; rc.bottom = 14; - DrawFrameControl(hdc, &rc, DFC_BUTTON, - DFCS_BUTTONCHECK|DFCS_FLAT); - - rc.left = 34; rc.right = 46; - DrawFrameControl(hdc, &rc, DFC_BUTTON, - DFCS_BUTTONCHECK|DFCS_FLAT|DFCS_CHECKED); - - SelectObject(hdc, hbmOld); - nIndex = ImageList_AddMasked(infoPtr->himlState, hbm, - GetSysColor(COLOR_WINDOW)); - TRACE("checkbox index %d\n", nIndex); - - DeleteObject(hbm); - DeleteDC(hdc); - DeleteDC(hdcScreen); - - infoPtr->stateImageWidth = 16; - infoPtr->stateImageHeight = 16; - } - return 0; -} - - -static LRESULT -TREEVIEW_Destroy(TREEVIEW_INFO *infoPtr) -{ - TRACE("\n"); - - TREEVIEW_RemoveTree(infoPtr); - - /* tool tip is automatically destroyed: we are its owner */ - - /* Restore original wndproc */ - if (infoPtr->hwndEdit) - SetWindowLongPtrW(infoPtr->hwndEdit, GWLP_WNDPROC, - (DWORD_PTR)infoPtr->wpEditOrig); - - /* Deassociate treeview from the window before doing anything drastic. */ - SetWindowLongPtrW(infoPtr->hwnd, 0, (DWORD_PTR)NULL); - - DeleteObject(infoPtr->hDefaultFont); - DeleteObject(infoPtr->hBoldFont); - Free(infoPtr); - - return 0; -} - -/* Miscellaneous Messages ***********************************************/ - -static LRESULT -TREEVIEW_ScrollKeyDown(TREEVIEW_INFO *infoPtr, WPARAM key) -{ - static const struct - { - unsigned char code; - } - scroll[] = - { -#define SCROLL_ENTRY(dir, code) { ((dir) << 7) | (code) } - SCROLL_ENTRY(SB_VERT, SB_PAGEUP), /* VK_PRIOR */ - SCROLL_ENTRY(SB_VERT, SB_PAGEDOWN), /* VK_NEXT */ - SCROLL_ENTRY(SB_VERT, SB_BOTTOM), /* VK_END */ - SCROLL_ENTRY(SB_VERT, SB_TOP), /* VK_HOME */ - SCROLL_ENTRY(SB_HORZ, SB_LINEUP), /* VK_LEFT */ - SCROLL_ENTRY(SB_VERT, SB_LINEUP), /* VK_UP */ - SCROLL_ENTRY(SB_HORZ, SB_LINEDOWN), /* VK_RIGHT */ - SCROLL_ENTRY(SB_VERT, SB_LINEDOWN) /* VK_DOWN */ -#undef SCROLL_ENTRY - }; - - if (key >= VK_PRIOR && key <= VK_DOWN) - { - unsigned char code = scroll[key - VK_PRIOR].code; - - (((code & (1 << 7)) == (SB_HORZ << 7)) - ? TREEVIEW_HScroll - : TREEVIEW_VScroll)(infoPtr, code & 0x7F); - } - - return 0; -} - -/************************************************************************ - * TREEVIEW_KeyDown - * - * VK_UP Move selection to the previous non-hidden item. - * VK_DOWN Move selection to the next non-hidden item. - * VK_HOME Move selection to the first item. - * VK_END Move selection to the last item. - * VK_LEFT If expanded then collapse, otherwise move to parent. - * VK_RIGHT If collapsed then expand, otherwise move to first child. - * VK_ADD Expand. - * VK_SUBTRACT Collapse. - * VK_MULTIPLY Expand all. - * VK_PRIOR Move up GetVisibleCount items. - * VK_NEXT Move down GetVisibleCount items. - * VK_BACK Move to parent. - * CTRL-Left,Right,Up,Down,PgUp,PgDown,Home,End: Scroll without changing selection - */ -static LRESULT -TREEVIEW_KeyDown(TREEVIEW_INFO *infoPtr, WPARAM wParam) -{ - /* If it is non-NULL and different, it will be selected and visible. */ - TREEVIEW_ITEM *newSelection = NULL; - - TREEVIEW_ITEM *prevItem = infoPtr->selectedItem; - - TRACE("%x\n", wParam); - - if (prevItem == NULL) - return FALSE; - - if (GetAsyncKeyState(VK_CONTROL) & 0x8000) - return TREEVIEW_ScrollKeyDown(infoPtr, wParam); - - switch (wParam) - { - case VK_UP: - newSelection = TREEVIEW_GetPrevListItem(infoPtr, prevItem); - if (!newSelection) - newSelection = infoPtr->root->firstChild; - break; - - case VK_DOWN: - newSelection = TREEVIEW_GetNextListItem(infoPtr, prevItem); - break; - - case VK_HOME: - newSelection = infoPtr->root->firstChild; - break; - - case VK_END: - newSelection = TREEVIEW_GetLastListItem(infoPtr, infoPtr->root); - break; - - case VK_LEFT: - if (prevItem->state & TVIS_EXPANDED) - { - TREEVIEW_Collapse(infoPtr, prevItem, FALSE, TRUE); - } - else if (prevItem->parent != infoPtr->root) - { - newSelection = prevItem->parent; - } - break; - - case VK_RIGHT: - if (TREEVIEW_HasChildren(infoPtr, prevItem)) - { - if (!(prevItem->state & TVIS_EXPANDED)) - TREEVIEW_Expand(infoPtr, prevItem, FALSE, TRUE); - else - { - newSelection = prevItem->firstChild; - } - } - - break; - - case VK_MULTIPLY: - TREEVIEW_ExpandAll(infoPtr, prevItem); - break; - - case VK_ADD: - if (!(prevItem->state & TVIS_EXPANDED)) - TREEVIEW_Expand(infoPtr, prevItem, FALSE, TRUE); - break; - - case VK_SUBTRACT: - if (prevItem->state & TVIS_EXPANDED) - TREEVIEW_Collapse(infoPtr, prevItem, FALSE, TRUE); - break; - - case VK_PRIOR: - newSelection - = TREEVIEW_GetListItem(infoPtr, prevItem, - -TREEVIEW_GetVisibleCount(infoPtr)); - break; - - case VK_NEXT: - newSelection - = TREEVIEW_GetListItem(infoPtr, prevItem, - TREEVIEW_GetVisibleCount(infoPtr)); - break; - - case VK_BACK: - newSelection = prevItem->parent; - if (newSelection == infoPtr->root) - newSelection = NULL; - break; - - case VK_SPACE: - if (infoPtr->dwStyle & TVS_CHECKBOXES) - TREEVIEW_ToggleItemState(infoPtr, prevItem); - break; - } - - if (newSelection && newSelection != prevItem) - { - if (TREEVIEW_DoSelectItem(infoPtr, TVGN_CARET, newSelection, - TVC_BYKEYBOARD)) - { - TREEVIEW_EnsureVisible(infoPtr, newSelection, FALSE); - } - } - - return FALSE; -} - -static LRESULT -TREEVIEW_Notify(TREEVIEW_INFO *infoPtr, WPARAM wParam, LPARAM lParam) -{ - LPNMHDR lpnmh = (LPNMHDR)lParam; - - if (lpnmh->code == PGN_CALCSIZE) { - LPNMPGCALCSIZE lppgc = (LPNMPGCALCSIZE)lParam; - - if (lppgc->dwFlag == PGF_CALCWIDTH) { - lppgc->iWidth = infoPtr->treeWidth; - TRACE("got PGN_CALCSIZE, returning horz size = %ld, client=%ld\n", - infoPtr->treeWidth, infoPtr->clientWidth); - } - else { - lppgc->iHeight = infoPtr->treeHeight; - TRACE("got PGN_CALCSIZE, returning vert size = %ld, client=%ld\n", - infoPtr->treeHeight, infoPtr->clientHeight); - } - return 0; - } - return DefWindowProcA(infoPtr->hwnd, WM_NOTIFY, wParam, lParam); -} - -static INT TREEVIEW_NotifyFormat (TREEVIEW_INFO *infoPtr, HWND hwndFrom, UINT nCommand) -{ - INT format; - - TRACE("(hwndFrom=%p, nCommand=%d)\n", hwndFrom, nCommand); - - if (nCommand != NF_REQUERY) return 0; - - format = SendMessageW(hwndFrom, WM_NOTIFYFORMAT, (WPARAM)infoPtr->hwnd, NF_QUERY); - TRACE("format=%d\n", format); - - if (format != NFR_ANSI && format != NFR_UNICODE) return 0; - - infoPtr->bNtfUnicode = (format == NFR_UNICODE); - - return format; -} - -static LRESULT -TREEVIEW_Size(TREEVIEW_INFO *infoPtr, WPARAM wParam, LPARAM lParam) -{ - if (wParam == SIZE_RESTORED) - { - infoPtr->clientWidth = (short)LOWORD(lParam); - infoPtr->clientHeight = (short)HIWORD(lParam); - - TREEVIEW_RecalculateVisibleOrder(infoPtr, NULL); - TREEVIEW_SetFirstVisible(infoPtr, infoPtr->firstVisible, TRUE); - TREEVIEW_UpdateScrollBars(infoPtr); - } - else - { - FIXME("WM_SIZE flag %x %lx not handled\n", wParam, lParam); - } - - TREEVIEW_Invalidate(infoPtr, NULL); - return 0; -} - -static LRESULT -TREEVIEW_StyleChanged(TREEVIEW_INFO *infoPtr, WPARAM wParam, LPARAM lParam) -{ - TRACE("(%x %lx)\n", wParam, lParam); - - if (wParam == GWL_STYLE) - { - DWORD dwNewStyle = ((LPSTYLESTRUCT)lParam)->styleNew; - - /* we have to take special care about tooltips */ - if ((infoPtr->dwStyle ^ dwNewStyle) & TVS_NOTOOLTIPS) - { - if (infoPtr->dwStyle & TVS_NOTOOLTIPS) - { - infoPtr->hwndToolTip = COMCTL32_CreateToolTip(infoPtr->hwnd); - TRACE("\n"); - } - else - { - DestroyWindow(infoPtr->hwndToolTip); - infoPtr->hwndToolTip = 0; - } - } - - infoPtr->dwStyle = dwNewStyle; - } - - TREEVIEW_UpdateSubTree(infoPtr, infoPtr->root); - TREEVIEW_UpdateScrollBars(infoPtr); - TREEVIEW_Invalidate(infoPtr, NULL); - - return 0; -} - -static LRESULT -TREEVIEW_SetFocus(TREEVIEW_INFO *infoPtr) -{ - TRACE("\n"); - - if (!infoPtr->selectedItem) - { - TREEVIEW_DoSelectItem(infoPtr, TVGN_CARET, infoPtr->firstVisible, - TVC_UNKNOWN); - } - - TREEVIEW_SendSimpleNotify(infoPtr, NM_SETFOCUS); - TREEVIEW_Invalidate(infoPtr, infoPtr->selectedItem); - return 0; -} - -static LRESULT -TREEVIEW_KillFocus(TREEVIEW_INFO *infoPtr) -{ - TRACE("\n"); - - TREEVIEW_SendSimpleNotify(infoPtr, NM_KILLFOCUS); - TREEVIEW_Invalidate(infoPtr, infoPtr->selectedItem); - return 0; -} - - -static LRESULT WINAPI -TREEVIEW_WindowProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam) -{ - TREEVIEW_INFO *infoPtr = TREEVIEW_GetInfoPtr(hwnd); - - TRACE("hwnd %p msg %04x wp=%08x lp=%08lx\n", hwnd, uMsg, wParam, lParam); - - if (infoPtr) TREEVIEW_VerifyTree(infoPtr); - else - { - if (uMsg == WM_CREATE) - TREEVIEW_Create(hwnd, (LPCREATESTRUCTW)lParam); - else - goto def; - } - - switch (uMsg) - { - case TVM_CREATEDRAGIMAGE: - return TREEVIEW_CreateDragImage(infoPtr, wParam, lParam); - - case TVM_DELETEITEM: - return TREEVIEW_DeleteItem(infoPtr, (HTREEITEM)lParam); - - case TVM_EDITLABELA: - return (LRESULT)TREEVIEW_EditLabel(infoPtr, (HTREEITEM)lParam); - - case TVM_EDITLABELW: - return (LRESULT)TREEVIEW_EditLabel(infoPtr, (HTREEITEM)lParam); - - case TVM_ENDEDITLABELNOW: - return TREEVIEW_EndEditLabelNow(infoPtr, (BOOL)wParam); - - case TVM_ENSUREVISIBLE: - return TREEVIEW_EnsureVisible(infoPtr, (HTREEITEM)lParam, TRUE); - - case TVM_EXPAND: - return TREEVIEW_ExpandMsg(infoPtr, (UINT)wParam, (HTREEITEM)lParam); - - case TVM_GETBKCOLOR: - return TREEVIEW_GetBkColor(infoPtr); - - case TVM_GETCOUNT: - return TREEVIEW_GetCount(infoPtr); - - case TVM_GETEDITCONTROL: - return TREEVIEW_GetEditControl(infoPtr); - - case TVM_GETIMAGELIST: - return TREEVIEW_GetImageList(infoPtr, wParam); - - case TVM_GETINDENT: - return TREEVIEW_GetIndent(infoPtr); - - case TVM_GETINSERTMARKCOLOR: - return TREEVIEW_GetInsertMarkColor(infoPtr); - - case TVM_GETISEARCHSTRINGA: - FIXME("Unimplemented msg TVM_GETISEARCHSTRINGA\n"); - return 0; - - case TVM_GETISEARCHSTRINGW: - FIXME("Unimplemented msg TVM_GETISEARCHSTRINGW\n"); - return 0; - - case TVM_GETITEMA: - return TREEVIEW_GetItemT(infoPtr, (LPTVITEMEXW)lParam, FALSE); - - case TVM_GETITEMW: - return TREEVIEW_GetItemT(infoPtr, (LPTVITEMEXW)lParam, TRUE); - - case TVM_GETITEMHEIGHT: - return TREEVIEW_GetItemHeight(infoPtr); - - case TVM_GETITEMRECT: - return TREEVIEW_GetItemRect(infoPtr, (BOOL)wParam, (LPRECT)lParam); - - case TVM_GETITEMSTATE: - return TREEVIEW_GetItemState(infoPtr, (HTREEITEM)wParam, (UINT)lParam); - - case TVM_GETLINECOLOR: - return TREEVIEW_GetLineColor(infoPtr); - - case TVM_GETNEXTITEM: - return TREEVIEW_GetNextItem(infoPtr, (UINT)wParam, (HTREEITEM)lParam); - - case TVM_GETSCROLLTIME: - return TREEVIEW_GetScrollTime(infoPtr); - - case TVM_GETTEXTCOLOR: - return TREEVIEW_GetTextColor(infoPtr); - - case TVM_GETTOOLTIPS: - return TREEVIEW_GetToolTips(infoPtr); - - case TVM_GETUNICODEFORMAT: - return TREEVIEW_GetUnicodeFormat(infoPtr); - - case TVM_GETVISIBLECOUNT: - return TREEVIEW_GetVisibleCount(infoPtr); - - case TVM_HITTEST: - return TREEVIEW_HitTest(infoPtr, (LPTVHITTESTINFO)lParam); - - case TVM_INSERTITEMA: - return TREEVIEW_InsertItemT(infoPtr, (LPTVINSERTSTRUCTW)lParam, FALSE); - - case TVM_INSERTITEMW: - return TREEVIEW_InsertItemT(infoPtr, (LPTVINSERTSTRUCTW)lParam, TRUE); - - case TVM_SELECTITEM: - return TREEVIEW_SelectItem(infoPtr, (INT)wParam, (HTREEITEM)lParam); - - case TVM_SETBKCOLOR: - return TREEVIEW_SetBkColor(infoPtr, (COLORREF)lParam); - - case TVM_SETIMAGELIST: - return TREEVIEW_SetImageList(infoPtr, wParam, (HIMAGELIST)lParam); - - case TVM_SETINDENT: - return TREEVIEW_SetIndent(infoPtr, (UINT)wParam); - - case TVM_SETINSERTMARK: - return TREEVIEW_SetInsertMark(infoPtr, (BOOL)wParam, (HTREEITEM)lParam); - - case TVM_SETINSERTMARKCOLOR: - return TREEVIEW_SetInsertMarkColor(infoPtr, (COLORREF)lParam); - - case TVM_SETITEMA: - return TREEVIEW_SetItemT(infoPtr, (LPTVITEMEXW)lParam, FALSE); - - case TVM_SETITEMW: - return TREEVIEW_SetItemT(infoPtr, (LPTVITEMEXW)lParam, TRUE); - - case TVM_SETLINECOLOR: - return TREEVIEW_SetLineColor(infoPtr, (COLORREF)lParam); - - case TVM_SETITEMHEIGHT: - return TREEVIEW_SetItemHeight(infoPtr, (INT)(SHORT)wParam); - - case TVM_SETSCROLLTIME: - return TREEVIEW_SetScrollTime(infoPtr, (UINT)wParam); - - case TVM_SETTEXTCOLOR: - return TREEVIEW_SetTextColor(infoPtr, (COLORREF)lParam); - - case TVM_SETTOOLTIPS: - return TREEVIEW_SetToolTips(infoPtr, (HWND)wParam); - - case TVM_SETUNICODEFORMAT: - return TREEVIEW_SetUnicodeFormat(infoPtr, (BOOL)wParam); - - case TVM_SORTCHILDREN: - return TREEVIEW_SortChildren(infoPtr, wParam, lParam); - - case TVM_SORTCHILDRENCB: - return TREEVIEW_SortChildrenCB(infoPtr, wParam, (LPTVSORTCB)lParam); - - case WM_CHAR: - return TREEVIEW_ProcessLetterKeys( hwnd, wParam, lParam ); - - case WM_COMMAND: - return TREEVIEW_Command(infoPtr, wParam, lParam); - - case WM_DESTROY: - return TREEVIEW_Destroy(infoPtr); - - /* WM_ENABLE */ - - case WM_ERASEBKGND: - return TREEVIEW_EraseBackground(infoPtr, (HDC)wParam); - - case WM_GETDLGCODE: - return DLGC_WANTARROWS | DLGC_WANTCHARS; - - case WM_GETFONT: - return TREEVIEW_GetFont(infoPtr); - - case WM_HSCROLL: - return TREEVIEW_HScroll(infoPtr, wParam); - - case WM_KEYDOWN: - return TREEVIEW_KeyDown(infoPtr, wParam); - - case WM_KILLFOCUS: - return TREEVIEW_KillFocus(infoPtr); - - case WM_LBUTTONDBLCLK: - return TREEVIEW_LButtonDoubleClick(infoPtr, lParam); - - case WM_LBUTTONDOWN: - return TREEVIEW_LButtonDown(infoPtr, lParam); - - /* WM_MBUTTONDOWN */ - - /* WM_MOUSEMOVE */ - - case WM_NOTIFY: - return TREEVIEW_Notify(infoPtr, wParam, lParam); - - case WM_NOTIFYFORMAT: - return TREEVIEW_NotifyFormat(infoPtr, (HWND)wParam, (UINT)lParam); - - case WM_PAINT: - return TREEVIEW_Paint(infoPtr, wParam); - - /* WM_PRINTCLIENT */ - - case WM_RBUTTONDOWN: - return TREEVIEW_RButtonDown(infoPtr, lParam); - - case WM_SETFOCUS: - return TREEVIEW_SetFocus(infoPtr); - - case WM_SETFONT: - return TREEVIEW_SetFont(infoPtr, (HFONT)wParam, (BOOL)lParam); - - case WM_SETREDRAW: - return TREEVIEW_SetRedraw(infoPtr, wParam, lParam); - - case WM_SIZE: - return TREEVIEW_Size(infoPtr, wParam, lParam); - - case WM_STYLECHANGED: - return TREEVIEW_StyleChanged(infoPtr, wParam, lParam); - - /* WM_SYSCOLORCHANGE */ - - /* WM_SYSKEYDOWN */ - - case WM_TIMER: - return TREEVIEW_HandleTimer(infoPtr, wParam); - - case WM_VSCROLL: - return TREEVIEW_VScroll(infoPtr, wParam); - - /* WM_WININICHANGE */ - - case WM_MOUSEWHEEL: - if (wParam & (MK_SHIFT | MK_CONTROL)) - goto def; - return TREEVIEW_MouseWheel(infoPtr, wParam); - - case WM_DRAWITEM: - TRACE("drawItem\n"); - goto def; - - default: - /* This mostly catches MFC and Delphi messages. :( */ - if ((uMsg >= WM_USER) && (uMsg < WM_APP)) - TRACE("Unknown msg %04x wp=%08x lp=%08lx\n", uMsg, wParam, lParam); -def: - return DefWindowProcA(hwnd, uMsg, wParam, lParam); - } - return 0; -} - - -/* Class Registration ***************************************************/ - -VOID -TREEVIEW_Register(void) -{ - WNDCLASSA wndClass; - - TRACE("\n"); - - ZeroMemory(&wndClass, sizeof(WNDCLASSA)); - wndClass.style = CS_GLOBALCLASS | CS_DBLCLKS; - wndClass.lpfnWndProc = TREEVIEW_WindowProc; - wndClass.cbClsExtra = 0; - wndClass.cbWndExtra = sizeof(TREEVIEW_INFO *); - - wndClass.hCursor = LoadCursorA(0, (LPSTR)IDC_ARROW); - wndClass.hbrBackground = 0; - wndClass.lpszClassName = WC_TREEVIEWA; - - RegisterClassA(&wndClass); -} - - -VOID -TREEVIEW_Unregister(void) -{ - UnregisterClassA(WC_TREEVIEWA, NULL); -} - - -/* Tree Verification ****************************************************/ - -#ifdef NDEBUG -static inline void -TREEVIEW_VerifyChildren(TREEVIEW_INFO *infoPtr, TREEVIEW_ITEM *item); - -static inline void TREEVIEW_VerifyItemCommon(TREEVIEW_INFO *infoPtr, - TREEVIEW_ITEM *item) -{ - assert(infoPtr != NULL); - assert(item != NULL); - - /* both NULL, or both non-null */ - assert((item->firstChild == NULL) == (item->lastChild == NULL)); - - assert(item->firstChild != item); - assert(item->lastChild != item); - - if (item->firstChild) - { - assert(item->firstChild->parent == item); - assert(item->firstChild->prevSibling == NULL); - } - - if (item->lastChild) - { - assert(item->lastChild->parent == item); - assert(item->lastChild->nextSibling == NULL); - } - - assert(item->nextSibling != item); - if (item->nextSibling) - { - assert(item->nextSibling->parent == item->parent); - assert(item->nextSibling->prevSibling == item); - } - - assert(item->prevSibling != item); - if (item->prevSibling) - { - assert(item->prevSibling->parent == item->parent); - assert(item->prevSibling->nextSibling == item); - } -} - -static inline void -TREEVIEW_VerifyItem(TREEVIEW_INFO *infoPtr, TREEVIEW_ITEM *item) -{ - assert(item != NULL); - - assert(item->parent != NULL); - assert(item->parent != item); - assert(item->iLevel == item->parent->iLevel + 1); - - assert(DPA_GetPtrIndex(infoPtr->items, item) != -1); - - TREEVIEW_VerifyItemCommon(infoPtr, item); - - TREEVIEW_VerifyChildren(infoPtr, item); -} - -static inline void -TREEVIEW_VerifyChildren(TREEVIEW_INFO *infoPtr, TREEVIEW_ITEM *item) -{ - TREEVIEW_ITEM *child; - assert(item != NULL); - - for (child = item->firstChild; child != NULL; child = child->nextSibling) - TREEVIEW_VerifyItem(infoPtr, child); -} - -static inline void -TREEVIEW_VerifyRoot(TREEVIEW_INFO *infoPtr) -{ - TREEVIEW_ITEM *root = infoPtr->root; - - assert(root != NULL); - assert(root->iLevel == -1); - assert(root->parent == NULL); - assert(root->prevSibling == NULL); - - TREEVIEW_VerifyItemCommon(infoPtr, root); - - TREEVIEW_VerifyChildren(infoPtr, root); -} - -static void -TREEVIEW_VerifyTree(TREEVIEW_INFO *infoPtr) -{ - assert(infoPtr != NULL); - - TREEVIEW_VerifyRoot(infoPtr); -} -#endif diff --git a/reactos/lib/comctl32/updown.c b/reactos/lib/comctl32/updown.c deleted file mode 100644 index 08d01f87656..00000000000 --- a/reactos/lib/comctl32/updown.c +++ /dev/null @@ -1,1005 +0,0 @@ -/* - * Updown control - * - * Copyright 1997, 2002 Dimitrie O. Paun - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2.1 of the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - * - * NOTE - * - * This code was audited for completeness against the documented features - * of Comctl32.dll version 6.0 on Sep. 9, 2002, 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. - * - */ - -#include -#include -#include -#include - -#include "windef.h" -#include "winbase.h" -#include "wingdi.h" -#include "winuser.h" -#include "winnls.h" -#include "commctrl.h" -#include "comctl32.h" -#include "wine/unicode.h" -#include "wine/debug.h" - -WINE_DEFAULT_DEBUG_CHANNEL(updown); - -typedef struct -{ - HWND Self; /* Handle to this up-down control */ - HWND Notify; /* Handle to the parent window */ - UINT AccelCount; /* Number of elements in AccelVect */ - UDACCEL* AccelVect; /* Vector containing AccelCount elements */ - INT AccelIndex; /* Current accel index, -1 if not accel'ing */ - INT Base; /* Base to display nr in the buddy window */ - INT CurVal; /* Current up-down value */ - INT MinVal; /* Minimum up-down value */ - INT MaxVal; /* Maximum up-down value */ - HWND Buddy; /* Handle to the buddy window */ - INT BuddyType; /* Remembers the buddy type BUDDY_TYPE_* */ - INT Flags; /* Internal Flags FLAG_* */ - BOOL UnicodeFormat; /* Marks the use of Unicode internally */ -} UPDOWN_INFO; - -/* Control configuration constants */ - -#define INITIAL_DELAY 500 /* initial timer until auto-inc kicks in */ -#define AUTOPRESS_DELAY 250 /* time to keep arrow pressed on KEY_DOWN */ -#define REPEAT_DELAY 50 /* delay between auto-increments */ - -#define DEFAULT_WIDTH 14 /* default width of the ctrl */ -#define DEFAULT_XSEP 0 /* default separation between buddy and ctrl */ -#define DEFAULT_ADDTOP 0 /* amount to extend above the buddy window */ -#define DEFAULT_ADDBOT 0 /* amount to extend below the buddy window */ -#define DEFAULT_BUDDYBORDER 2 /* Width/height of the buddy border */ -#define DEFAULT_BUDDYSPACER 2 /* Spacer between the buddy and the ctrl */ - - -/* Work constants */ - -#define FLAG_INCR 0x01 -#define FLAG_DECR 0x02 -#define FLAG_MOUSEIN 0x04 -#define FLAG_PRESSED 0x08 -#define FLAG_ARROW (FLAG_INCR | FLAG_DECR) - -#define BUDDY_TYPE_UNKNOWN 0 -#define BUDDY_TYPE_LISTBOX 1 -#define BUDDY_TYPE_EDIT 2 - -#define TIMER_AUTOREPEAT 1 -#define TIMER_ACCEL 2 -#define TIMER_AUTOPRESS 3 - -#define UPDOWN_GetInfoPtr(hwnd) ((UPDOWN_INFO *)GetWindowLongPtrW (hwnd,0)) -#define COUNT_OF(a) (sizeof(a)/sizeof(a[0])) - -static const WCHAR BUDDY_UPDOWN_HWND[] = { 'b', 'u', 'd', 'd', 'y', 'U', 'p', 'D', 'o', 'w', 'n', 'H', 'W', 'N', 'D', 0 }; -static const WCHAR BUDDY_SUPERCLASS_WNDPROC[] = { 'b', 'u', 'd', 'd', 'y', 'S', 'u', 'p', 'p', 'e', 'r', - 'C', 'l', 'a', 's', 's', 'W', 'n', 'd', 'P', 'r', 'o', 'c', 0 }; -static void UPDOWN_DoAction (UPDOWN_INFO *infoPtr, int delta, int action); - -/*********************************************************************** - * UPDOWN_IsBuddyEdit - * Tests if our buddy is an edit control. - */ -static inline BOOL UPDOWN_IsBuddyEdit(UPDOWN_INFO *infoPtr) -{ - return infoPtr->BuddyType == BUDDY_TYPE_EDIT; -} - -/*********************************************************************** - * UPDOWN_IsBuddyListbox - * Tests if our buddy is a listbox control. - */ -static inline BOOL UPDOWN_IsBuddyListbox(UPDOWN_INFO *infoPtr) -{ - return infoPtr->BuddyType == BUDDY_TYPE_LISTBOX; -} - -/*********************************************************************** - * UPDOWN_InBounds - * Tests if a given value 'val' is between the Min&Max limits - */ -static BOOL UPDOWN_InBounds(UPDOWN_INFO *infoPtr, int val) -{ - if(infoPtr->MaxVal > infoPtr->MinVal) - return (infoPtr->MinVal <= val) && (val <= infoPtr->MaxVal); - else - return (infoPtr->MaxVal <= val) && (val <= infoPtr->MinVal); -} - -/*********************************************************************** - * UPDOWN_OffsetVal - * Change the current value by delta. - * It returns TRUE is the value was changed successfuly, or FALSE - * if the value was not changed, as it would go out of bounds. - */ -static BOOL UPDOWN_OffsetVal(UPDOWN_INFO *infoPtr, int delta) -{ - /* check if we can do the modification first */ - if(!UPDOWN_InBounds (infoPtr, infoPtr->CurVal+delta)) { - if (GetWindowLongW (infoPtr->Self, GWL_STYLE) & UDS_WRAP) { - delta += (delta < 0 ? -1 : 1) * - (infoPtr->MaxVal < infoPtr->MinVal ? -1 : 1) * - (infoPtr->MinVal - infoPtr->MaxVal) + - (delta < 0 ? 1 : -1); - } else return FALSE; - } - - infoPtr->CurVal += delta; - return TRUE; -} - -/*********************************************************************** - * UPDOWN_HasBuddyBorder - * - * When we have a buddy set and that we are aligned on our buddy, we - * want to draw a sunken edge to make like we are part of that control. - */ -static BOOL UPDOWN_HasBuddyBorder(UPDOWN_INFO* infoPtr) -{ - DWORD dwStyle = GetWindowLongW (infoPtr->Self, GWL_STYLE); - - return ( ((dwStyle & (UDS_ALIGNLEFT | UDS_ALIGNRIGHT)) != 0) && - UPDOWN_IsBuddyEdit(infoPtr) ); -} - -/*********************************************************************** - * UPDOWN_GetArrowRect - * wndPtr - pointer to the up-down wnd - * rect - will hold the rectangle - * arrow - FLAG_INCR to get the "increment" rect (up or right) - * FLAG_DECR to get the "decrement" rect (down or left) - * If both flags are pressent, the envelope is returned. - */ -static void UPDOWN_GetArrowRect (UPDOWN_INFO* infoPtr, RECT *rect, int arrow) -{ - DWORD dwStyle = GetWindowLongW (infoPtr->Self, GWL_STYLE); - - GetClientRect (infoPtr->Self, rect); - - /* - * Make sure we calculate the rectangle to fit even if we draw the - * border. - */ - if (UPDOWN_HasBuddyBorder(infoPtr)) { - if (dwStyle & UDS_ALIGNLEFT) - rect->left += DEFAULT_BUDDYBORDER; - else - rect->right -= DEFAULT_BUDDYBORDER; - - InflateRect(rect, 0, -DEFAULT_BUDDYBORDER); - } - - /* now figure out if we need a space away from the buddy */ - if ( IsWindow(infoPtr->Buddy) ) { - if (dwStyle & UDS_ALIGNLEFT) rect->right -= DEFAULT_BUDDYSPACER; - else rect->left += DEFAULT_BUDDYSPACER; - } - - /* - * We're calculating the midpoint to figure-out where the - * separation between the buttons will lay. We make sure that we - * round the uneven numbers by adding 1. - */ - if (dwStyle & UDS_HORZ) { - int len = rect->right - rect->left + 1; /* compute the width */ - if (arrow & FLAG_INCR) - rect->left = rect->left + len/2; - if (arrow & FLAG_DECR) - rect->right = rect->left + len/2 - 1; - } else { - int len = rect->bottom - rect->top + 1; /* compute the height */ - if (arrow & FLAG_INCR) - rect->bottom = rect->top + len/2 - 1; - if (arrow & FLAG_DECR) - rect->top = rect->top + len/2; - } -} - -/*********************************************************************** - * UPDOWN_GetArrowFromPoint - * Returns the rectagle (for the up or down arrow) that contains pt. - * If it returns the up rect, it returns TRUE. - * If it returns the down rect, it returns FALSE. - */ -static BOOL UPDOWN_GetArrowFromPoint (UPDOWN_INFO* infoPtr, RECT *rect, POINT pt) -{ - UPDOWN_GetArrowRect (infoPtr, rect, FLAG_INCR); - if(PtInRect(rect, pt)) return FLAG_INCR; - - UPDOWN_GetArrowRect (infoPtr, rect, FLAG_DECR); - if(PtInRect(rect, pt)) return FLAG_DECR; - - return 0; -} - - -/*********************************************************************** - * UPDOWN_GetThousandSep - * Returns the thousand sep. If an error occurs, it returns ','. - */ -static WCHAR UPDOWN_GetThousandSep() -{ - WCHAR sep[2]; - - if(GetLocaleInfoW(LOCALE_USER_DEFAULT, LOCALE_STHOUSAND, sep, 2) != 1) - sep[0] = ','; - - return sep[0]; -} - -/*********************************************************************** - * UPDOWN_GetBuddyInt - * Tries to read the pos from the buddy window and if it succeeds, - * it stores it in the control's CurVal - * returns: - * TRUE - if it read the integer from the buddy successfully - * FALSE - if an error occurred - */ -static BOOL UPDOWN_GetBuddyInt (UPDOWN_INFO *infoPtr) -{ - WCHAR txt[20], sep, *src, *dst; - int newVal; - - if (!IsWindow(infoPtr->Buddy)) - return FALSE; - - /*if the buddy is a list window, we must set curr index */ - if (UPDOWN_IsBuddyListbox(infoPtr)) { - newVal = SendMessageW(infoPtr->Buddy, LB_GETCARETINDEX, 0, 0); - if(newVal < 0) return FALSE; - } else { - /* we have a regular window, so will get the text */ - if (!GetWindowTextW(infoPtr->Buddy, txt, COUNT_OF(txt))) return FALSE; - - sep = UPDOWN_GetThousandSep(); - - /* now get rid of the separators */ - for(src = dst = txt; *src; src++) - if(*src != sep) *dst++ = *src; - *dst = 0; - - /* try to convert the number and validate it */ - newVal = strtolW(txt, &src, infoPtr->Base); - if(*src || !UPDOWN_InBounds (infoPtr, newVal)) return FALSE; - } - - TRACE("new value(%d) from buddy (old=%d)\n", newVal, infoPtr->CurVal); - infoPtr->CurVal = newVal; - return TRUE; -} - - -/*********************************************************************** - * UPDOWN_SetBuddyInt - * Tries to set the pos to the buddy window based on current pos - * returns: - * TRUE - if it set the caption of the buddy successfully - * FALSE - if an error occurred - */ -static BOOL UPDOWN_SetBuddyInt (UPDOWN_INFO *infoPtr) -{ - WCHAR fmt[3] = { '%', 'd', '\0' }; - WCHAR txt[20]; - int len; - - if (!IsWindow(infoPtr->Buddy)) return FALSE; - - TRACE("set new value(%d) to buddy.\n", infoPtr->CurVal); - - /*if the buddy is a list window, we must set curr index */ - if (UPDOWN_IsBuddyListbox(infoPtr)) { - return SendMessageW(infoPtr->Buddy, LB_SETCURSEL, infoPtr->CurVal, 0) != LB_ERR; - } - - /* Regular window, so set caption to the number */ - if (infoPtr->Base == 16) fmt[1] = 'X'; - len = wsprintfW(txt, fmt, infoPtr->CurVal); - - - /* Do thousands separation if necessary */ - if (!(GetWindowLongW (infoPtr->Self, GWL_STYLE) & UDS_NOTHOUSANDS) && (len > 3)) { - WCHAR tmp[COUNT_OF(txt)], *src = tmp, *dst = txt; - WCHAR sep = UPDOWN_GetThousandSep(); - int start = len % 3; - - memcpy(tmp, txt, sizeof(txt)); - if (start == 0) start = 3; - dst += start; - src += start; - for (len=0; *src; len++) { - if (len % 3 == 0) *dst++ = sep; - *dst++ = *src++; - } - *dst = 0; - } - - return SetWindowTextW(infoPtr->Buddy, txt); -} - -/*********************************************************************** - * UPDOWN_Draw - * - * Draw the arrows. The background need not be erased. - */ -static LRESULT UPDOWN_Draw (UPDOWN_INFO *infoPtr, HDC hdc) -{ - DWORD dwStyle = GetWindowLongW (infoPtr->Self, GWL_STYLE); - BOOL pressed, hot; - RECT rect; - - /* Draw the common border between ourselves and our buddy */ - if (UPDOWN_HasBuddyBorder(infoPtr)) { - GetClientRect(infoPtr->Self, &rect); - DrawEdge(hdc, &rect, EDGE_SUNKEN, - BF_BOTTOM | BF_TOP | - (dwStyle & UDS_ALIGNLEFT ? BF_LEFT : BF_RIGHT)); - } - - /* Draw the incr button */ - UPDOWN_GetArrowRect (infoPtr, &rect, FLAG_INCR); - pressed = (infoPtr->Flags & FLAG_PRESSED) && (infoPtr->Flags & FLAG_INCR); - hot = (infoPtr->Flags & FLAG_INCR) && (infoPtr->Flags & FLAG_MOUSEIN); - DrawFrameControl(hdc, &rect, DFC_SCROLL, - (dwStyle & UDS_HORZ ? DFCS_SCROLLRIGHT : DFCS_SCROLLUP) | - ((dwStyle & UDS_HOTTRACK) && hot ? DFCS_HOT : 0) | - (pressed ? DFCS_PUSHED : 0) | - (dwStyle & WS_DISABLED ? DFCS_INACTIVE : 0) ); - - /* Draw the decr button */ - UPDOWN_GetArrowRect(infoPtr, &rect, FLAG_DECR); - pressed = (infoPtr->Flags & FLAG_PRESSED) && (infoPtr->Flags & FLAG_DECR); - hot = (infoPtr->Flags & FLAG_DECR) && (infoPtr->Flags & FLAG_MOUSEIN); - DrawFrameControl(hdc, &rect, DFC_SCROLL, - (dwStyle & UDS_HORZ ? DFCS_SCROLLLEFT : DFCS_SCROLLDOWN) | - ((dwStyle & UDS_HOTTRACK) && hot ? DFCS_HOT : 0) | - (pressed ? DFCS_PUSHED : 0) | - (dwStyle & WS_DISABLED ? DFCS_INACTIVE : 0) ); - - return 0; -} - -/*********************************************************************** - * UPDOWN_Paint - * - * Asynchronous drawing (must ONLY be used in WM_PAINT). - * Calls UPDOWN_Draw. - */ -static LRESULT UPDOWN_Paint (UPDOWN_INFO *infoPtr, HDC hdc) -{ - PAINTSTRUCT ps; - if (hdc) return UPDOWN_Draw (infoPtr, hdc); - hdc = BeginPaint (infoPtr->Self, &ps); - UPDOWN_Draw (infoPtr, hdc); - EndPaint (infoPtr->Self, &ps); - return 0; -} - -/*********************************************************************** - * UPDOWN_KeyPressed - * - * Handle key presses (up & down) when we have to do so - */ -static LRESULT UPDOWN_KeyPressed(UPDOWN_INFO *infoPtr, int key) -{ - int arrow; - - if (key == VK_UP) arrow = FLAG_INCR; - else if (key == VK_DOWN) arrow = FLAG_DECR; - else return 1; - - UPDOWN_GetBuddyInt (infoPtr); - infoPtr->Flags &= ~FLAG_ARROW; - infoPtr->Flags |= FLAG_PRESSED | arrow; - InvalidateRect (infoPtr->Self, NULL, FALSE); - SetTimer(infoPtr->Self, TIMER_AUTOPRESS, AUTOPRESS_DELAY, 0); - UPDOWN_DoAction (infoPtr, 1, arrow); - return 0; -} - -/*********************************************************************** - * UPDOWN_Buddy_SubclassProc used to handle messages sent to the buddy - * control. - */ -static LRESULT CALLBACK -UPDOWN_Buddy_SubclassProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam) -{ - WNDPROC superClassWndProc = (WNDPROC)GetPropW(hwnd, BUDDY_SUPERCLASS_WNDPROC); - - TRACE("hwnd=%p, wndProc=%p, uMsg=%04x, wParam=%08x, lParam=%08lx\n", - hwnd, superClassWndProc, uMsg, wParam, lParam); - - if (uMsg == WM_KEYDOWN) { - HWND upDownHwnd = GetPropW(hwnd, BUDDY_UPDOWN_HWND); - - UPDOWN_KeyPressed(UPDOWN_GetInfoPtr(upDownHwnd), (int)wParam); - } - - return CallWindowProcW( superClassWndProc, hwnd, uMsg, wParam, lParam); -} - -/*********************************************************************** - * UPDOWN_SetBuddy - * - * Sets bud as a new Buddy. - * Then, it should subclass the buddy - * If window has the UDS_ARROWKEYS, it subcalsses the buddy window to - * process the UP/DOWN arrow keys. - * If window has the UDS_ALIGNLEFT or UDS_ALIGNRIGHT style - * the size/pos of the buddy and the control are adjusted accordingly. - */ -static HWND UPDOWN_SetBuddy (UPDOWN_INFO* infoPtr, HWND bud) -{ - static const WCHAR editW[] = { 'E', 'd', 'i', 't', 0 }; - static const WCHAR listboxW[] = { 'L', 'i', 's', 't', 'b', 'o', 'x', 0 }; - DWORD dwStyle = GetWindowLongW (infoPtr->Self, GWL_STYLE); - RECT budRect; /* new coord for the buddy */ - int x, width; /* new x position and width for the up-down */ - WNDPROC baseWndProc; - WCHAR buddyClass[40]; - HWND ret; - - TRACE("(hwnd=%p, bud=%p)\n", infoPtr->Self, bud); - - ret = infoPtr->Buddy; - - /* there is already a body assigned */ - if (infoPtr->Buddy) RemovePropW(infoPtr->Buddy, BUDDY_UPDOWN_HWND); - - if(!IsWindow(bud)) - bud = 0; - - /* Store buddy window handle */ - infoPtr->Buddy = bud; - - if(bud) { - - /* keep upDown ctrl hwnd in a buddy property */ - SetPropW( bud, BUDDY_UPDOWN_HWND, infoPtr->Self); - - /* Store buddy window class type */ - infoPtr->BuddyType = BUDDY_TYPE_UNKNOWN; - if (GetClassNameW(bud, buddyClass, COUNT_OF(buddyClass))) { - if (lstrcmpiW(buddyClass, editW) == 0) - infoPtr->BuddyType = BUDDY_TYPE_EDIT; - else if (lstrcmpiW(buddyClass, listboxW) == 0) - infoPtr->BuddyType = BUDDY_TYPE_LISTBOX; - } - - if(dwStyle & UDS_ARROWKEYS){ - /* Note that I don't clear the BUDDY_SUPERCLASS_WNDPROC property - when we reset the upDown ctrl buddy to another buddy because it is not - good to break the window proc chain. */ - if (!GetPropW(bud, BUDDY_SUPERCLASS_WNDPROC)) { - baseWndProc = (WNDPROC)SetWindowLongPtrW(bud, GWLP_WNDPROC, (LPARAM)UPDOWN_Buddy_SubclassProc); - SetPropW(bud, BUDDY_SUPERCLASS_WNDPROC, (HANDLE)baseWndProc); - } - } - - /* Get the rect of the buddy relative to its parent */ - GetWindowRect(infoPtr->Buddy, &budRect); - MapWindowPoints(HWND_DESKTOP, GetParent(infoPtr->Buddy), (POINT *)(&budRect.left), 2); - - /* now do the positioning */ - if (dwStyle & UDS_ALIGNLEFT) { - x = budRect.left; - budRect.left += DEFAULT_WIDTH + DEFAULT_XSEP; - } else if (dwStyle & UDS_ALIGNRIGHT) { - budRect.right -= DEFAULT_WIDTH + DEFAULT_XSEP; - x = budRect.right+DEFAULT_XSEP; - } else { - /* nothing to do */ - return ret; - } - - /* first adjust the buddy to accommodate the up/down */ - SetWindowPos(infoPtr->Buddy, 0, budRect.left, budRect.top, - budRect.right - budRect.left, budRect.bottom - budRect.top, - SWP_NOACTIVATE|SWP_NOZORDER); - - /* now position the up/down */ - /* Since the UDS_ALIGN* flags were used, */ - /* we will pick the position and size of the window. */ - width = DEFAULT_WIDTH; - - /* - * If the updown has a buddy border, it has to overlap with the buddy - * to look as if it is integrated with the buddy control. - * We nudge the control or change its size to overlap. - */ - if (UPDOWN_HasBuddyBorder(infoPtr)) { - if(dwStyle & UDS_ALIGNLEFT) - width += DEFAULT_BUDDYBORDER; - else - x -= DEFAULT_BUDDYBORDER; - } - - SetWindowPos(infoPtr->Self, 0, x, - budRect.top - DEFAULT_ADDTOP, width, - budRect.bottom - budRect.top + DEFAULT_ADDTOP + DEFAULT_ADDBOT, - SWP_NOACTIVATE|SWP_FRAMECHANGED|SWP_NOZORDER); - } else { - RECT rect; - GetWindowRect(infoPtr->Self, &rect); - MapWindowPoints(HWND_DESKTOP, GetParent(infoPtr->Self), (POINT *)&rect, 2); - SetWindowPos(infoPtr->Self, 0, rect.left, rect.top, DEFAULT_WIDTH, rect.bottom - rect.top, - SWP_NOACTIVATE|SWP_FRAMECHANGED|SWP_NOZORDER); - } - return ret; -} - -/*********************************************************************** - * UPDOWN_DoAction - * - * This function increments/decrements the CurVal by the - * 'delta' amount according to the 'action' flag which can be a - * combination of FLAG_INCR and FLAG_DECR - * It notifies the parent as required. - * It handles wraping and non-wraping correctly. - * It is assumed that delta>0 - */ -static void UPDOWN_DoAction (UPDOWN_INFO *infoPtr, int delta, int action) -{ - DWORD dwStyle = GetWindowLongW (infoPtr->Self, GWL_STYLE); - NM_UPDOWN ni; - - TRACE("%d by %d\n", action, delta); - - /* check if we can do the modification first */ - delta *= (action & FLAG_INCR ? 1 : -1) * (infoPtr->MaxVal < infoPtr->MinVal ? -1 : 1); - if ( (action & FLAG_INCR) && (action & FLAG_DECR) ) delta = 0; - - TRACE("current %d, delta: %d\n", infoPtr->CurVal, delta); - - /* We must notify parent now to obtain permission */ - ni.iPos = infoPtr->CurVal; - ni.iDelta = delta; - ni.hdr.hwndFrom = infoPtr->Self; - ni.hdr.idFrom = GetWindowLongPtrW (infoPtr->Self, GWLP_ID); - ni.hdr.code = UDN_DELTAPOS; - if (!SendMessageW(infoPtr->Notify, WM_NOTIFY, (WPARAM)ni.hdr.idFrom, (LPARAM)&ni)) { - /* Parent said: OK to adjust */ - - /* Now adjust value with (maybe new) delta */ - if (UPDOWN_OffsetVal (infoPtr, ni.iDelta)) { - TRACE("new %d, delta: %d\n", infoPtr->CurVal, ni.iDelta); - - /* Now take care about our buddy */ - if (dwStyle & UDS_SETBUDDYINT) UPDOWN_SetBuddyInt (infoPtr); - } - } - - /* Also, notify it. This message is sent in any case. */ - SendMessageW( infoPtr->Notify, dwStyle & UDS_HORZ ? WM_HSCROLL : WM_VSCROLL, - MAKELONG(SB_THUMBPOSITION, infoPtr->CurVal), (LPARAM)infoPtr->Self); -} - -/*********************************************************************** - * UPDOWN_IsEnabled - * - * Returns TRUE if it is enabled as well as its buddy (if any) - * FALSE otherwise - */ -static BOOL UPDOWN_IsEnabled (UPDOWN_INFO *infoPtr) -{ - if (!IsWindowEnabled(infoPtr->Self)) - return FALSE; - if(infoPtr->Buddy) - return IsWindowEnabled(infoPtr->Buddy); - return TRUE; -} - -/*********************************************************************** - * UPDOWN_CancelMode - * - * Deletes any timers, releases the mouse and does redraw if necessary. - * If the control is not in "capture" mode, it does nothing. - * If the control was not in cancel mode, it returns FALSE. - * If the control was in cancel mode, it returns TRUE. - */ -static BOOL UPDOWN_CancelMode (UPDOWN_INFO *infoPtr) -{ - if (!(infoPtr->Flags & FLAG_PRESSED)) return FALSE; - - KillTimer (infoPtr->Self, TIMER_AUTOREPEAT); - KillTimer (infoPtr->Self, TIMER_ACCEL); - KillTimer (infoPtr->Self, TIMER_AUTOPRESS); - - if (GetCapture() == infoPtr->Self) { - NMHDR hdr; - hdr.hwndFrom = infoPtr->Self; - hdr.idFrom = GetWindowLongPtrW (infoPtr->Self, GWLP_ID); - hdr.code = NM_RELEASEDCAPTURE; - SendMessageW(infoPtr->Notify, WM_NOTIFY, hdr.idFrom, (LPARAM)&hdr); - ReleaseCapture(); - } - - infoPtr->Flags &= ~FLAG_PRESSED; - InvalidateRect (infoPtr->Self, NULL, FALSE); - - return TRUE; -} - -/*********************************************************************** - * UPDOWN_HandleMouseEvent - * - * Handle a mouse event for the updown. - * 'pt' is the location of the mouse event in client or - * windows coordinates. - */ -static void UPDOWN_HandleMouseEvent (UPDOWN_INFO *infoPtr, UINT msg, INT x, INT y) -{ - DWORD dwStyle = GetWindowLongW (infoPtr->Self, GWL_STYLE); - POINT pt = { x, y }; - RECT rect; - int temp, arrow; - - TRACE("msg %04x point %s\n", msg, wine_dbgstr_point(&pt)); - - switch(msg) - { - case WM_LBUTTONDOWN: /* Initialise mouse tracking */ - - /* If the buddy is an edit, will set focus to it */ - if (UPDOWN_IsBuddyEdit(infoPtr)) SetFocus(infoPtr->Buddy); - - /* Now see which one is the 'active' arrow */ - arrow = UPDOWN_GetArrowFromPoint (infoPtr, &rect, pt); - - /* Update the flags if we are in/out */ - infoPtr->Flags &= ~(FLAG_MOUSEIN | FLAG_ARROW); - if (arrow) - infoPtr->Flags |= FLAG_MOUSEIN | arrow; - else - if (infoPtr->AccelIndex != -1) infoPtr->AccelIndex = 0; - - if (infoPtr->Flags & FLAG_ARROW) { - - /* Update the CurVal if necessary */ - if (dwStyle & UDS_SETBUDDYINT) UPDOWN_GetBuddyInt (infoPtr); - - /* Set up the correct flags */ - infoPtr->Flags |= FLAG_PRESSED; - - /* repaint the control */ - InvalidateRect (infoPtr->Self, NULL, FALSE); - - /* process the click */ - temp = (infoPtr->AccelCount && infoPtr->AccelVect) ? infoPtr->AccelVect[0].nInc : 1; - UPDOWN_DoAction (infoPtr, temp, infoPtr->Flags & FLAG_ARROW); - - /* now capture all mouse messages */ - SetCapture (infoPtr->Self); - - /* and startup the first timer */ - SetTimer(infoPtr->Self, TIMER_AUTOREPEAT, INITIAL_DELAY, 0); - } - break; - - case WM_MOUSEMOVE: - /* save the flags to see if any got modified */ - temp = infoPtr->Flags; - - /* Now see which one is the 'active' arrow */ - arrow = UPDOWN_GetArrowFromPoint (infoPtr, &rect, pt); - - /* Update the flags if we are in/out */ - infoPtr->Flags &= ~(FLAG_MOUSEIN | FLAG_ARROW); - if(arrow) { - infoPtr->Flags |= FLAG_MOUSEIN | arrow; - } else { - if(infoPtr->AccelIndex != -1) infoPtr->AccelIndex = 0; - } - - /* If state changed, redraw the control */ - if(temp != infoPtr->Flags) - InvalidateRect (infoPtr->Self, &rect, FALSE); - break; - - default: - ERR("Impossible case (msg=%x)!\n", msg); - } - -} - -/*********************************************************************** - * UpDownWndProc - */ -static LRESULT WINAPI UpDownWindowProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam) -{ - UPDOWN_INFO *infoPtr = UPDOWN_GetInfoPtr (hwnd); - DWORD dwStyle = GetWindowLongW (hwnd, GWL_STYLE); - int temp; - - TRACE("hwnd=%p msg=%04x wparam=%08x lparam=%08lx\n", hwnd, message, wParam, lParam); - - if (!infoPtr && (message != WM_CREATE)) - return DefWindowProcW (hwnd, message, wParam, lParam); - - switch(message) - { - case WM_CREATE: - SetWindowLongW (hwnd, GWL_STYLE, dwStyle & ~WS_BORDER); - infoPtr = (UPDOWN_INFO*)Alloc (sizeof(UPDOWN_INFO)); - SetWindowLongPtrW (hwnd, 0, (DWORD_PTR)infoPtr); - - /* initialize the info struct */ - infoPtr->Self = hwnd; - infoPtr->Notify = ((LPCREATESTRUCTA)lParam)->hwndParent; - infoPtr->AccelCount = 0; - infoPtr->AccelVect = 0; - infoPtr->AccelIndex = -1; - infoPtr->CurVal = 0; - infoPtr->MinVal = 100; - infoPtr->MaxVal = 0; - infoPtr->Base = 10; /* Default to base 10 */ - infoPtr->Buddy = 0; /* No buddy window yet */ - infoPtr->Flags = 0; /* And no flags */ - - /* Do we pick the buddy win ourselves? */ - if (dwStyle & UDS_AUTOBUDDY) - UPDOWN_SetBuddy (infoPtr, GetWindow (hwnd, GW_HWNDPREV)); - - TRACE("UpDown Ctrl creation, hwnd=%p\n", hwnd); - break; - - case WM_DESTROY: - if(infoPtr->AccelVect) Free (infoPtr->AccelVect); - - if(infoPtr->Buddy) RemovePropW(infoPtr->Buddy, BUDDY_UPDOWN_HWND); - - Free (infoPtr); - SetWindowLongPtrW (hwnd, 0, 0); - TRACE("UpDown Ctrl destruction, hwnd=%p\n", hwnd); - break; - - case WM_ENABLE: - if (dwStyle & WS_DISABLED) UPDOWN_CancelMode (infoPtr); - InvalidateRect (infoPtr->Self, NULL, FALSE); - break; - - case WM_TIMER: - /* is this the auto-press timer? */ - if(wParam == TIMER_AUTOPRESS) { - KillTimer(hwnd, TIMER_AUTOPRESS); - infoPtr->Flags &= ~(FLAG_PRESSED | FLAG_ARROW); - InvalidateRect(infoPtr->Self, NULL, FALSE); - } - - /* if initial timer, kill it and start the repeat timer */ - if(wParam == TIMER_AUTOREPEAT) { - KillTimer(hwnd, TIMER_AUTOREPEAT); - /* if no accel info given, used default timer */ - if(infoPtr->AccelCount==0 || infoPtr->AccelVect==0) { - infoPtr->AccelIndex = -1; - temp = REPEAT_DELAY; - } else { - infoPtr->AccelIndex = 0; /* otherwise, use it */ - temp = infoPtr->AccelVect[infoPtr->AccelIndex].nSec * 1000 + 1; - } - SetTimer(hwnd, TIMER_ACCEL, temp, 0); - } - - /* now, if the mouse is above us, do the thing...*/ - if(infoPtr->Flags & FLAG_MOUSEIN) { - temp = infoPtr->AccelIndex == -1 ? 1 : infoPtr->AccelVect[infoPtr->AccelIndex].nInc; - UPDOWN_DoAction(infoPtr, temp, infoPtr->Flags & FLAG_ARROW); - - if(infoPtr->AccelIndex != -1 && infoPtr->AccelIndex < infoPtr->AccelCount-1) { - KillTimer(hwnd, TIMER_ACCEL); - infoPtr->AccelIndex++; /* move to the next accel info */ - temp = infoPtr->AccelVect[infoPtr->AccelIndex].nSec * 1000 + 1; - /* make sure we have at least 1ms intervals */ - SetTimer(hwnd, TIMER_ACCEL, temp, 0); - } - } - break; - - case WM_CANCELMODE: - return UPDOWN_CancelMode (infoPtr); - - case WM_LBUTTONUP: - if (GetCapture() != infoPtr->Self) break; - - if ( (infoPtr->Flags & FLAG_MOUSEIN) && - (infoPtr->Flags & FLAG_ARROW) ) { - - SendMessageW( infoPtr->Notify, - dwStyle & UDS_HORZ ? WM_HSCROLL : WM_VSCROLL, - MAKELONG(SB_ENDSCROLL, infoPtr->CurVal), - (LPARAM)hwnd); - if (UPDOWN_IsBuddyEdit(infoPtr)) - SendMessageW(infoPtr->Buddy, EM_SETSEL, 0, MAKELONG(0, -1)); - } - UPDOWN_CancelMode(infoPtr); - break; - - case WM_LBUTTONDOWN: - case WM_MOUSEMOVE: - if(UPDOWN_IsEnabled(infoPtr)) - UPDOWN_HandleMouseEvent (infoPtr, message, (SHORT)LOWORD(lParam), (SHORT)HIWORD(lParam)); - break; - - case WM_KEYDOWN: - if((dwStyle & UDS_ARROWKEYS) && UPDOWN_IsEnabled(infoPtr)) - return UPDOWN_KeyPressed(infoPtr, (int)wParam); - break; - - case WM_PAINT: - return UPDOWN_Paint (infoPtr, (HDC)wParam); - - case UDM_GETACCEL: - if (wParam==0 && lParam==0) return infoPtr->AccelCount; - if (wParam && lParam) { - temp = min(infoPtr->AccelCount, wParam); - memcpy((void *)lParam, infoPtr->AccelVect, temp*sizeof(UDACCEL)); - return temp; - } - return 0; - - case UDM_SETACCEL: - TRACE("UDM_SETACCEL\n"); - - if(infoPtr->AccelVect) { - Free (infoPtr->AccelVect); - infoPtr->AccelCount = 0; - infoPtr->AccelVect = 0; - } - if(wParam==0) return TRUE; - infoPtr->AccelVect = Alloc (wParam*sizeof(UDACCEL)); - if(infoPtr->AccelVect == 0) return FALSE; - memcpy(infoPtr->AccelVect, (void*)lParam, wParam*sizeof(UDACCEL)); - infoPtr->AccelCount = wParam; - - for (temp = 0; temp < wParam; temp++) - TRACE("%d: nSec %u nInc %u\n", temp, infoPtr->AccelVect[temp].nSec, infoPtr->AccelVect[temp].nInc); - - return TRUE; - - case UDM_GETBASE: - return infoPtr->Base; - - case UDM_SETBASE: - TRACE("UpDown Ctrl new base(%d), hwnd=%p\n", wParam, hwnd); - if (wParam==10 || wParam==16) { - temp = infoPtr->Base; - infoPtr->Base = wParam; - return temp; - } - break; - - case UDM_GETBUDDY: - return (LRESULT)infoPtr->Buddy; - - case UDM_SETBUDDY: - return (LRESULT)UPDOWN_SetBuddy (infoPtr, (HWND)wParam); - - case UDM_GETPOS: - temp = UPDOWN_GetBuddyInt (infoPtr); - return MAKELONG(infoPtr->CurVal, temp ? 0 : 1); - - case UDM_SETPOS: - temp = (short)LOWORD(lParam); - TRACE("UpDown Ctrl new value(%d), hwnd=%p\n", temp, hwnd); - if(!UPDOWN_InBounds(infoPtr, temp)) { - if(temp < infoPtr->MinVal) temp = infoPtr->MinVal; - if(temp > infoPtr->MaxVal) temp = infoPtr->MaxVal; - } - wParam = infoPtr->CurVal; - infoPtr->CurVal = temp; - if(dwStyle & UDS_SETBUDDYINT) UPDOWN_SetBuddyInt (infoPtr); - return wParam; /* return prev value */ - - case UDM_GETRANGE: - return MAKELONG(infoPtr->MaxVal, infoPtr->MinVal); - - case UDM_SETRANGE: - /* we must have: */ - infoPtr->MaxVal = (short)(lParam); /* UD_MINVAL <= Max <= UD_MAXVAL */ - infoPtr->MinVal = (short)HIWORD(lParam); /* UD_MINVAL <= Min <= UD_MAXVAL */ - /* |Max-Min| <= UD_MAXVAL */ - TRACE("UpDown Ctrl new range(%d to %d), hwnd=%p\n", - infoPtr->MinVal, infoPtr->MaxVal, hwnd); - break; - - case UDM_GETRANGE32: - if (wParam) *(LPINT)wParam = infoPtr->MinVal; - if (lParam) *(LPINT)lParam = infoPtr->MaxVal; - break; - - case UDM_SETRANGE32: - infoPtr->MinVal = (INT)wParam; - infoPtr->MaxVal = (INT)lParam; - if (infoPtr->MaxVal <= infoPtr->MinVal) - infoPtr->MaxVal = infoPtr->MinVal + 1; - TRACE("UpDown Ctrl new range(%d to %d), hwnd=%p\n", - infoPtr->MinVal, infoPtr->MaxVal, hwnd); - break; - - case UDM_GETPOS32: - if ((LPBOOL)lParam != NULL) *((LPBOOL)lParam) = TRUE; - return infoPtr->CurVal; - - case UDM_SETPOS32: - if(!UPDOWN_InBounds(infoPtr, (int)lParam)) { - if((int)lParam < infoPtr->MinVal) lParam = infoPtr->MinVal; - if((int)lParam > infoPtr->MaxVal) lParam = infoPtr->MaxVal; - } - temp = infoPtr->CurVal; /* save prev value */ - infoPtr->CurVal = (int)lParam; /* set the new value */ - if(dwStyle & UDS_SETBUDDYINT) UPDOWN_SetBuddyInt (infoPtr); - return temp; /* return prev value */ - - case UDM_GETUNICODEFORMAT: - /* we lie a bit here, we're always using Unicode internally */ - return infoPtr->UnicodeFormat; - - case UDM_SETUNICODEFORMAT: - /* do we really need to honour this flag? */ - temp = infoPtr->UnicodeFormat; - infoPtr->UnicodeFormat = (BOOL)wParam; - return temp; - - default: - if ((message >= WM_USER) && (message < WM_APP)) - ERR("unknown msg %04x wp=%04x lp=%08lx\n", message, wParam, lParam); - return DefWindowProcW (hwnd, message, wParam, lParam); - } - - return 0; -} - -/*********************************************************************** - * UPDOWN_Register [Internal] - * - * Registers the updown window class. - */ -void UPDOWN_Register(void) -{ - WNDCLASSW wndClass; - - ZeroMemory( &wndClass, sizeof( WNDCLASSW ) ); - wndClass.style = CS_GLOBALCLASS | CS_VREDRAW | CS_HREDRAW; - wndClass.lpfnWndProc = UpDownWindowProc; - wndClass.cbClsExtra = 0; - wndClass.cbWndExtra = sizeof(UPDOWN_INFO*); - wndClass.hCursor = LoadCursorW( 0, (LPWSTR)IDC_ARROW ); - wndClass.hbrBackground = (HBRUSH)(COLOR_BTNFACE + 1); - wndClass.lpszClassName = UPDOWN_CLASSW; - - RegisterClassW( &wndClass ); -} - - -/*********************************************************************** - * UPDOWN_Unregister [Internal] - * - * Unregisters the updown window class. - */ -void UPDOWN_Unregister (void) -{ - UnregisterClassW (UPDOWN_CLASSW, NULL); -} diff --git a/reactos/lib/comctl32/winehq2ros.patch b/reactos/lib/comctl32/winehq2ros.patch deleted file mode 100644 index 8193180a57b..00000000000 --- a/reactos/lib/comctl32/winehq2ros.patch +++ /dev/null @@ -1,220 +0,0 @@ -Index: comctl32.spec -=================================================================== -RCS file: /home/wine/wine/dlls/comctl32/comctl32.spec,v -retrieving revision 1.46 -diff -u -r1.46 comctl32.spec ---- comctl32.spec 19 Oct 2004 22:59:59 -0000 1.46 -+++ comctl32.spec 5 Dec 2004 22:48:09 -0000 -@@ -106,13 +106,13 @@ - 412 stdcall RemoveWindowSubclass(long ptr long) - 413 stdcall DefSubclassProc(long long long long) - 414 stdcall -noname MirrorIcon(ptr ptr) --415 stdcall -noname DrawTextWrap(long wstr long ptr long) user32.DrawTextW --416 stdcall -noname DrawTextExPrivWrap(long wstr long ptr long ptr) user32.DrawTextExW --417 stdcall -noname ExtTextOutWrap(long long long long ptr wstr long ptr) gdi32.ExtTextOutW --418 stdcall -noname GetCharWidthWrap(long long long long) gdi32.GetCharWidthW --419 stdcall -noname GetTextExtentPointWrap(long wstr long ptr) gdi32.GetTextExtentPointW --420 stdcall -noname GetTextExtentPoint32Wrap(long wstr long ptr) gdi32.GetTextExtentPoint32W --421 stdcall -noname TextOutWrap(long long long wstr long) gdi32.TextOutW -+415 stdcall DrawTextWrap(long wstr long ptr long) user32.DrawTextW -+416 stdcall DrawTextExPrivWrap(long wstr long ptr long ptr) user32.DrawTextExW -+417 stdcall ExtTextOutWrap(long long long long ptr wstr long ptr) gdi32.ExtTextOutW -+418 stdcall GetCharWidthWrap(long long long long) gdi32.GetCharWidthW -+419 stdcall GetTextExtentPointWrap(long wstr long ptr) gdi32.GetTextExtentPointW -+420 stdcall GetTextExtentPoint32Wrap(long wstr long ptr) gdi32.GetTextExtentPoint32W -+421 stdcall TextOutWrap(long long long wstr long) gdi32.TextOutW - - # Functions imported by name - -Index: commctrl.c -=================================================================== -RCS file: /home/wine/wine/dlls/comctl32/commctrl.c,v -retrieving revision 1.88 -diff -u -r1.88 commctrl.c ---- commctrl.c 19 Oct 2004 22:59:59 -0000 1.88 -+++ commctrl.c 5 Dec 2004 22:48:09 -0000 -@@ -482,7 +482,7 @@ - r.left += 3; - if (style & SBT_RTLREADING) - FIXME("Unsupported RTL style!\n"); -- DrawTextW (hdc, text, -1, &r, align|DT_VCENTER|DT_SINGLELINE); -+ DrawTextW (hdc, text, -1, &r, align|DT_VCENTER|DT_SINGLELINE|DT_NOPREFIX); - SetBkMode(hdc, oldbkmode); - } - } -Index: datetime.c -=================================================================== -RCS file: /home/wine/wine/dlls/comctl32/datetime.c,v -retrieving revision 1.49 -diff -u -r1.49 datetime.c ---- datetime.c 24 Nov 2004 18:28:31 -0000 1.49 -+++ datetime.c 5 Dec 2004 22:48:10 -0000 -@@ -814,10 +814,10 @@ - - TRACE("Height=%ld, Width=%ld\n", infoPtr->rcClient.bottom, infoPtr->rcClient.right); - -- /* use DrawEdge to adjust the size of rcEdge to get rcDraw */ - memcpy((&infoPtr->rcDraw), (&infoPtr->rcClient), sizeof(infoPtr->rcDraw)); - -- DrawEdge(NULL, &(infoPtr->rcDraw), EDGE_SUNKEN, BF_RECT | BF_ADJUST); -+ /* subract the size of the edge drawn by DrawEdge */ -+ InflateRect(&infoPtr->rcDraw, -2, -2); - - /* set the size of the button that drops the calendar down */ - /* FIXME: account for style that allows button on left side */ -Index: listview.c -=================================================================== -RCS file: /home/wine/wine/dlls/comctl32/listview.c,v -retrieving revision 1.398 -diff -u -r1.398 listview.c ---- listview.c 24 Nov 2004 18:28:31 -0000 1.398 -+++ listview.c 5 Dec 2004 22:48:13 -0000 -@@ -146,6 +146,7 @@ - #include - #include - #include -+#include - #include - #include - #include -@@ -2033,7 +2034,8 @@ - infoPtr->iconSize.cy + ICON_BOTTOM_PADDING; - Label.right = Label.left + labelSize.cx; - Label.bottom = Label.top + infoPtr->nItemHeight; -- if (!oversizedBox && labelSize.cy > infoPtr->ntmHeight) -+ if (!oversizedBox && labelSize.cy > infoPtr->ntmHeight && -+ infoPtr->ntmHeight) - { - labelSize.cy = min(Box.bottom - Label.top, labelSize.cy); - labelSize.cy /= infoPtr->ntmHeight; -@@ -9522,7 +9524,8 @@ - hOldFont = SelectObject(hdc, infoPtr->hFont); - - /*Get String Length in pixels */ -- GetTextExtentPoint32W(hdc, text, lstrlenW(text), &sz); -+ if(!GetTextExtentPoint32W(hdc, text, lstrlenW(text), &sz)) -+ sz.cx = 0; - - /*Add Extra spacing for the next character */ - GetTextMetricsW(hdc, &textMetric); -Index: rebar.c -=================================================================== -RCS file: /home/wine/wine/dlls/comctl32/rebar.c,v -retrieving revision 1.100 -diff -u -r1.100 rebar.c ---- rebar.c 24 Nov 2004 18:28:31 -0000 1.100 -+++ rebar.c 5 Dec 2004 22:48:14 -0000 -@@ -3786,10 +3786,10 @@ - infoPtr->bands = NULL; - } - -- DeleteObject (infoPtr->hcurArrow); -- DeleteObject (infoPtr->hcurHorz); -- DeleteObject (infoPtr->hcurVert); -- DeleteObject (infoPtr->hcurDrag); -+ DestroyCursor (infoPtr->hcurArrow); -+ DestroyCursor (infoPtr->hcurHorz); -+ DestroyCursor (infoPtr->hcurVert); -+ DestroyCursor (infoPtr->hcurDrag); - if(infoPtr->hDefaultFont) DeleteObject (infoPtr->hDefaultFont); - SetWindowLongPtrW (infoPtr->hwndSelf, 0, 0); - -Index: string.c -=================================================================== -RCS file: /home/wine/wine/dlls/comctl32/string.c,v -retrieving revision 1.5 -diff -u -r1.5 string.c ---- string.c 22 Sep 2004 19:10:27 -0000 1.5 -+++ string.c 5 Dec 2004 22:48:15 -0000 -@@ -264,7 +264,7 @@ - { - TRACE("(%s,%s)\n", debugstr_w(lpszStr), debugstr_w(lpszSearch)); - -- return COMCTL32_StrStrHelperW(lpszStr, lpszSearch, strncmpiW); -+ return COMCTL32_StrStrHelperW(lpszStr, lpszSearch, (int (*)(LPCWSTR,LPCWSTR,int)) wcsnicmp); - } - - /************************************************************************** -@@ -513,7 +513,7 @@ - { - TRACE("(%s,%s)\n", debugstr_w(lpszStr), debugstr_w(lpszSearch)); - -- return COMCTL32_StrStrHelperW(lpszStr, lpszSearch, strncmpW); -+ return COMCTL32_StrStrHelperW(lpszStr, lpszSearch, (int (*)(LPCWSTR,LPCWSTR,int)) wcsncmp); - } - - /************************************************************************* -Index: tooltips.c -=================================================================== -RCS file: /home/wine/wine/dlls/comctl32/tooltips.c,v -retrieving revision 1.74 -diff -u -r1.74 tooltips.c ---- tooltips.c 25 Oct 2004 21:44:50 -0000 1.74 -+++ tooltips.c 5 Dec 2004 22:48:16 -0000 -@@ -2836,7 +2836,7 @@ - TOOLTIPS_Unregister (void) - { - int i; -- for (i = 0; i < TTI_ERROR+1; i++) -- DeleteObject(hTooltipIcons[i]); -+ for (i = TTI_INFO; i <= TTI_ERROR; i++) -+ DestroyIcon(hTooltipIcons[i]); - UnregisterClassW (TOOLTIPS_CLASSW, NULL); - } -Index: treeview.c -=================================================================== -RCS file: /home/wine/wine/dlls/comctl32/treeview.c,v -retrieving revision 1.158 -diff -u -r1.158 treeview.c ---- treeview.c 21 Nov 2004 15:41:08 -0000 1.158 -+++ treeview.c 5 Dec 2004 22:48:18 -0000 -@@ -2329,7 +2329,7 @@ - SelectObject(hdc, hOldPen); - DeleteObject(hNewPen); - -- if (height < 16 || width < 16) -+ if (height < 18 || width < 18) - { - MoveToEx(hdc, centerx - plussize + 1, centery, NULL); - LineTo(hdc, centerx + plussize, centery); -Index: status.c -=================================================================== -RCS file: /CVS/ReactOS/reactos/lib/comctl32/status.c,v -retrieving revision 1.7 -diff -u -r1.7 status.c ---- status.c 5 Dec 2004 23:09:27 -0000 1.7 -+++ status.c 14 Dec 2004 00:58:03 -0000 -@@ -650,6 +650,7 @@ - { - STATUSWINDOWPART *part=NULL; - BOOL changed = FALSE; -+ WORD oldStyle; - - if (style & SBT_OWNERDRAW) { - TRACE("part %d, text %p\n",nPart,text); -@@ -671,6 +672,7 @@ - if (part->style != style) - changed = TRUE; - -+ oldStyle = part->style; - part->style = style; - if (style & SBT_OWNERDRAW) { - if (part->text == text) -@@ -694,7 +696,7 @@ - /* check if text is unchanged -> no need to redraw */ - if (text) { - if (!changed && part->text && !lstrcmpW(ntext, part->text)) { -- if (!isW) Free(ntext); -+ Free(ntext); - return TRUE; - } - } else { -@@ -702,7 +704,7 @@ - return TRUE; - } - -- if (part->text) -+ if (part->text && !(oldStyle & SBT_OWNERDRAW)) - Free (part->text); - part->text = ntext; - }