diff options
Diffstat (limited to 'Src/Winamp/setup')
43 files changed, 6436 insertions, 0 deletions
diff --git a/Src/Winamp/setup/checkbox.bmp b/Src/Winamp/setup/checkbox.bmp Binary files differnew file mode 100644 index 00000000..4730c42b --- /dev/null +++ b/Src/Winamp/setup/checkbox.bmp diff --git a/Src/Winamp/setup/headerstrip.bmp b/Src/Winamp/setup/headerstrip.bmp Binary files differnew file mode 100644 index 00000000..a40b51dd --- /dev/null +++ b/Src/Winamp/setup/headerstrip.bmp diff --git a/Src/Winamp/setup/httpgrab.cpp b/Src/Winamp/setup/httpgrab.cpp new file mode 100644 index 00000000..6f45914a --- /dev/null +++ b/Src/Winamp/setup/httpgrab.cpp @@ -0,0 +1,183 @@ +#include "main.h" +#include "./httpgrab.h" + + +static HHOOK g_hook = NULL; +static HWND g_hook_host = NULL; +static HWND g_hook_fwd = NULL; +static DWORD g_hook_flags = 0; +static HWND *g_hook_phwnd =NULL; + +static LRESULT CALLBACK TargetWndProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam); +static LRESULT CALLBACK LabelWndProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam); + +static BOOL IsDialog(HWND hwnd) +{ + wchar_t szName[256] = {0}; + return (GetClassNameW(hwnd, szName, sizeof(szName)/sizeof(wchar_t)) && + CSTR_EQUAL == CompareStringW(MAKELCID(MAKELANGID(LANG_ENGLISH, SUBLANG_ENGLISH_US), SORT_DEFAULT), + NORM_IGNORECASE, szName, -1, L"#32770", -1)); +} + +static LRESULT CALLBACK HookProc(int code, WPARAM wParam, LPARAM lParam) +{ + if (HCBT_CREATEWND == code && IsDialog((HWND)wParam) && ((CBT_CREATEWND*)lParam)->lpcs->hwndParent == g_hook_host) + { + LRESULT result; + + result = CallNextHookEx(g_hook, code, wParam, lParam); + UnhookWindowsHookEx(g_hook); + g_hook = NULL; + + if (0 == result) + { + ((CBT_CREATEWND*)lParam)->lpcs->style &= ~WS_VISIBLE; + WNDPROC oldProc = (WNDPROC)SetWindowLongPtrW((HWND)wParam, GWLP_WNDPROC, (LONG_PTR)TargetWndProc); + if (oldProc) + { + SetPropW((HWND)wParam, L"WNDPROC", oldProc); + if (g_hook_fwd) SetPropW((HWND)wParam, L"FWDHWND", g_hook_fwd); + if (g_hook_flags) SetPropW((HWND)wParam, L"FLAGS", (HANDLE)(INT_PTR)g_hook_flags); + if (g_hook_phwnd) *g_hook_phwnd = (HWND)wParam; + } + } + else if (g_hook_host && IsWindow(g_hook_host)) DestroyWindow(g_hook_host); + + g_hook_fwd = NULL; + g_hook_flags = 0; + g_hook_host = NULL; + return result; + } + return CallNextHookEx(g_hook, code, wParam, lParam); +} + +HWND BeginGrabHTTPText(HWND hwndFwd, UINT flags, HWND *phwndTarget) +{ + + g_hook_host = CreateWindowExW(0x08000000/*WS_EX_NOACTIVATE*/ | WS_EX_NOPARENTNOTIFY, L"STATIC", L"", WS_DISABLED | WS_POPUP, -10000, -10000, 0, 0, NULL, NULL, NULL, NULL); + if (!g_hook_host) return NULL; + + g_hook = SetWindowsHookEx(WH_CBT, HookProc, NULL, GetCurrentThreadId()); + if (!g_hook) + { + if (g_hook_host) DestroyWindow(g_hook_host); + g_hook_host = NULL; + g_hook_fwd = NULL; + g_hook_flags = 0; + g_hook_phwnd = NULL; + } + else + { + g_hook_fwd = hwndFwd; + g_hook_flags = flags; + g_hook_phwnd = phwndTarget; + } + return g_hook_host; +} + +void EndGrabHTTPText(HWND hwndHost) +{ + if (g_hook_host == hwndHost) + { + if (g_hook) UnhookWindowsHookEx(g_hook); + g_hook = NULL; + g_hook_host = NULL; + g_hook_fwd = NULL; + g_hook_flags = 0; + } + if (IsWindow(hwndHost)) DestroyWindow(hwndHost); +} + +static LRESULT CALLBACK TargetWndProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam) +{ + WNDPROC fnOldProc = (WNDPROC)GetPropW(hwnd, L"WNDPROC"); + + switch(uMsg) + { + case WM_INITDIALOG: + { + HWND hwndFwd; + + hwndFwd = (HWND)GetPropW(hwnd, L"FWDHWND"); + DWORD flags = (DWORD)(INT_PTR)GetPropW(hwnd, L"FLAGS"); + RemovePropW(hwnd, L"FLAGS"); + RemovePropW(hwnd, L"FWDHWND"); + + if (hwndFwd) + { + HWND hwndText; + if (HTTPGRAB_USESTATUSTEXT & flags) + { + hwndText = GetDlgItem(hwnd, 1180/*IDC_STATUS*/); + WNDPROC oldProc = (WNDPROC)SetWindowLongPtrW(hwndText, GWLP_WNDPROC, (LONG_PTR)LabelWndProc); + if (oldProc) SetPropW(hwndText, L"WNDPROC", oldProc); + else hwndText = hwnd; + } + else hwndText = hwnd; + SetPropW(hwndText, L"FWDTEXT", hwndFwd); + + WCHAR szText[256] = {0}; + GetWindowTextW(hwndText, szText, sizeof(szText)/sizeof(wchar_t)); + SetWindowTextW(hwndFwd, szText); + } + } + break; + case WM_DESTROY: + { + RemovePropW(hwnd, L"WNDPROC"); + RemovePropW(hwnd, L"FWDTEXT"); + if (fnOldProc) SetWindowLongPtrW(hwnd, GWLP_WNDPROC, (LONG_PTR)fnOldProc); + HWND hwndOwner; + hwndOwner = GetWindow(hwnd, GW_OWNER); + if (hwndOwner) DestroyWindow(hwndOwner); + } + break; + case WM_STYLECHANGING: + if (GWL_STYLE & wParam) ((STYLESTRUCT*)lParam)->styleNew &= ~WS_VISIBLE; + return 0; + case WM_STYLECHANGED: + if ((GWL_STYLE & wParam) && (WS_VISIBLE & ((STYLESTRUCT*)lParam)->styleNew)) + SetWindowLongPtrW(hwnd, GWL_STYLE, (((STYLESTRUCT*)lParam)->styleNew & ~WS_VISIBLE)); + return 0; + case WM_WINDOWPOSCHANGING: + ((WINDOWPOS*)lParam)->flags = (((WINDOWPOS*)lParam)->flags & ~(SWP_SHOWWINDOW | SWP_FRAMECHANGED)) | SWP_NOACTIVATE | SWP_NOZORDER; + return 0; + case WM_SETTEXT: + { + HWND hwndFwd = (HWND)GetPropW(hwnd, L"FWDTEXT"); + if (hwndFwd) + { + (IsWindowUnicode(hwndFwd)) ? SendMessageW(hwndFwd, WM_SETTEXT, wParam, lParam) : + SendMessageA(hwndFwd, WM_SETTEXT, wParam, lParam); + } + } + break; + } + if (!fnOldProc) return DefWindowProc(hwnd, uMsg, wParam, lParam); + return (IsWindowUnicode(hwnd)) ? CallWindowProcW(fnOldProc, hwnd, uMsg, wParam, lParam) : CallWindowProcA(fnOldProc, hwnd, uMsg, wParam, lParam); +} + +static LRESULT CALLBACK LabelWndProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam) +{ + WNDPROC fnOldProc = (WNDPROC)GetPropW(hwnd, L"WNDPROC"); + + switch(uMsg) + { + case WM_SETTEXT: + { + HWND hwndFwd = (HWND)GetPropW(hwnd, L"FWDTEXT"); + if (hwndFwd) + { + (IsWindowUnicode(hwndFwd)) ? SendMessageW(hwndFwd, WM_SETTEXT, wParam, lParam) : + SendMessageA(hwndFwd, WM_SETTEXT, wParam, lParam); + } + } + case WM_DESTROY: + RemovePropW(hwnd, L"WNDPROC"); + RemovePropW(hwnd, L"FWDTEXT"); + if (fnOldProc) SetWindowLongPtrW(hwnd, GWLP_WNDPROC, (LONG_PTR)fnOldProc); + break; + } + if (!fnOldProc) return DefWindowProc(hwnd, uMsg, wParam, lParam); + return (IsWindowUnicode(hwnd)) ? CallWindowProcW(fnOldProc, hwnd, uMsg, wParam, lParam) : CallWindowProcA(fnOldProc, hwnd, uMsg, wParam, lParam); +} diff --git a/Src/Winamp/setup/httpgrab.h b/Src/Winamp/setup/httpgrab.h new file mode 100644 index 00000000..94845df8 --- /dev/null +++ b/Src/Winamp/setup/httpgrab.h @@ -0,0 +1,13 @@ +#ifndef WINAMP_HTTP_GRAB_TEXT_HEADER +#define WINAMP_HTTP_GRAB_TEXT_HEADER + +#include <windows.h> + +#define HTTPGRAB_USEWINDOWTEXT 0x0000 +#define HTTPGRAB_USESTATUSTEXT 0x0001 + +HWND BeginGrabHTTPText(HWND hwndFwd, UINT flags, HWND *phwndTarget); // returns hwnd that you need to supply as parent of http funciton +void EndGrabHTTPText(HWND hwndHost); + + +#endif //WINAMP_HTTP_GRAB_TEXT_HEADER
\ No newline at end of file diff --git a/Src/Winamp/setup/ifc_setupjob.h b/Src/Winamp/setup/ifc_setupjob.h new file mode 100644 index 00000000..ae239810 --- /dev/null +++ b/Src/Winamp/setup/ifc_setupjob.h @@ -0,0 +1,42 @@ +#ifndef WINAMP_IFC_SETUP_JOB_HEADER +#define WINAMP_IFC_SETUP_JOB_HEADER + +#include <bfc/dispatch.h> +#include <windows.h> + +class NOVTABLE ifc_setupjob : public Dispatchable +{ +protected: + ifc_setupjob(void) {} + virtual ~ifc_setupjob(void) {} + +public: + HRESULT Execute(HWND hwndText); + HRESULT Cancel(HWND hwndText); + HRESULT IsCancelSupported(void); + +public: + DISPATCH_CODES + { + API_SETUPJOB_EXECUTE = 10, + API_SETUPJOB_CANCEL = 20, + API_SETUPJOB_ISCANCELSUPPORTED = 30, + }; +}; + +inline HRESULT ifc_setupjob::Execute(HWND hwndText) +{ + return _call(API_SETUPJOB_EXECUTE, E_NOTIMPL, hwndText); +} + +inline HRESULT ifc_setupjob::Cancel(HWND hwndText) +{ + return _call(API_SETUPJOB_CANCEL, E_NOTIMPL, hwndText); +} + +inline HRESULT ifc_setupjob::IsCancelSupported(void) +{ + return _call(API_SETUPJOB_ISCANCELSUPPORTED, E_NOTIMPL); +} + +#endif //WINAMP_IFC_SETUP_JOB_HEADER
\ No newline at end of file diff --git a/Src/Winamp/setup/ifc_setuppage.h b/Src/Winamp/setup/ifc_setuppage.h new file mode 100644 index 00000000..3ea57de8 --- /dev/null +++ b/Src/Winamp/setup/ifc_setuppage.h @@ -0,0 +1,62 @@ +#ifndef WINAMP_IFC_SETUP_PAGE_HEADER +#define WINAMP_IFC_SETUP_PAGE_HEADER + +#include <bfc/dispatch.h> +#include <windows.h> + +class NOVTABLE ifc_setuppage : public Dispatchable +{ +protected: + ifc_setuppage(void) {} + virtual ~ifc_setuppage(void) {} + +public: + HRESULT GetName(bool bShort, const wchar_t **pszName); + HRESULT Save(HWND hwndText); // setup will allways call this no matter of IsDirty result. (you can check dirty state inside save()); + HRESULT CreateView(HWND hwndParent, HWND *phwnd); + HRESULT Revert(void); + HRESULT IsDirty(void); // S_OK - valid, S_FALSE - page is not dirty ( no save required), E_NOTIMPL - not impl. all errors counts as dirty + HRESULT Validate(void); // S_OK - valid, S_FALSE - invalid, E_NOTIMPL - not impl. all errors counts as page is valid + +public: + DISPATCH_CODES + { + API_SETUPPAGE_GET_NAME = 10, + API_SETUPPAGE_CREATEVIEW = 20, + API_SETUPPAGE_SAVE = 30, + API_SETUPPAGE_ISDIRTY = 40, + API_SETUPPAGE_REVERT = 50, + API_SETUPPAGE_VALIDATE = 60, + }; +}; + +inline HRESULT ifc_setuppage::GetName(bool bShort, const wchar_t **pszName) +{ + return _call(API_SETUPPAGE_GET_NAME, E_NOTIMPL, bShort, pszName); +} + +inline HRESULT ifc_setuppage::CreateView(HWND hwndParent, HWND *phwnd) +{ + return _call(API_SETUPPAGE_CREATEVIEW, E_NOTIMPL, hwndParent, phwnd); +} + +inline HRESULT ifc_setuppage::Save(HWND hwndText) +{ + return _call(API_SETUPPAGE_SAVE, E_NOTIMPL, hwndText); +} + +inline HRESULT ifc_setuppage::IsDirty(void) +{ + return _call(API_SETUPPAGE_ISDIRTY, E_NOTIMPL); +} + +inline HRESULT ifc_setuppage::Revert(void) +{ + return _call(API_SETUPPAGE_REVERT, E_NOTIMPL); +} + +inline HRESULT ifc_setuppage::Validate(void) +{ + return _call(API_SETUPPAGE_VALIDATE, E_NOTIMPL); +} +#endif //WINAMP_IFC_SETUP_PAGE_HEADER
\ No newline at end of file diff --git a/Src/Winamp/setup/langutil.cpp b/Src/Winamp/setup/langutil.cpp new file mode 100644 index 00000000..a461fc3b --- /dev/null +++ b/Src/Winamp/setup/langutil.cpp @@ -0,0 +1,43 @@ +#include "main.h" +#include "./langutil.h" + + + +INT_PTR WADialogBoxParam(LPCWSTR lpTemplateName, HWND hWndParent, DLGPROC lpDialogFunc, LPARAM dwInitParam) +{ + INT_PTR ret(0); + HINSTANCE hInst = (language_pack_instance) ? language_pack_instance : hMainInstance; + while(hInst) + { + ret = DialogBoxParamW(hInst, lpTemplateName, hWndParent, lpDialogFunc, dwInitParam); + if (-1 == ret && hInst != hMainInstance) hInst = hMainInstance; + else break; + } + return ret; +} + +HWND WACreateDialogParam(LPCWSTR lpTemplateName, HWND hWndParent, DLGPROC lpDialogFunc, LPARAM dwInitParam) +{ + HWND ret(NULL); + HINSTANCE hInst = (language_pack_instance) ? language_pack_instance : hMainInstance; + while(hInst) + { + ret = CreateDialogParamW(hInst, lpTemplateName, hWndParent, lpDialogFunc, dwInitParam); + if (NULL == ret && hInst != hMainInstance) hInst = hMainInstance; + else break; + } + return ret; +} + +HBITMAP WALoadImage2(LPCWSTR pszSectionName, LPCWSTR lpImageName, BOOL bPremult) +{ + HBITMAP ret(NULL); + HINSTANCE hInst = (language_pack_instance) ? language_pack_instance : hMainInstance; + while(hInst) + { + ret = WALoadImage(hInst, pszSectionName, lpImageName, bPremult); + if (NULL == ret && hInst != hMainInstance) hInst = hMainInstance; + else break; + } + return ret; +}
\ No newline at end of file diff --git a/Src/Winamp/setup/langutil.h b/Src/Winamp/setup/langutil.h new file mode 100644 index 00000000..dc4168de --- /dev/null +++ b/Src/Winamp/setup/langutil.h @@ -0,0 +1,18 @@ +#ifndef WINAMP_SETUP_LANGUTIL_HEADER +#define WINAMP_SETUP_LANGUTIL_HEADER + +#include <windows.h> +#include "./loadimage.h" + +INT_PTR WADialogBoxParam(LPCWSTR lpTemplateName, HWND hWndParent, DLGPROC lpDialogFunc, LPARAM dwInitParam); +HWND WACreateDialogParam(LPCWSTR lpTemplateName, HWND hWndParent, DLGPROC lpDialogFunc, LPARAM dwInitParam); +HBITMAP WALoadImage2(LPCWSTR pszSectionName, LPCWSTR lpImageName, BOOL bPremult); + + +#define WADialogBox(lpTemplate, hWndParent, lpDialogFunc) \ +WADialogBoxParam(lpTemplate, hWndParent, lpDialogFunc, 0L) + +#define WACreateDialog(lpName, hWndParent, lpDialogFunc) \ +WACreateDialogParam(lpName, hWndParent, lpDialogFunc, 0L) + +#endif //WINAMP_SETUP_LANGUTIL_HEADER
\ No newline at end of file diff --git a/Src/Winamp/setup/loadimage.cpp b/Src/Winamp/setup/loadimage.cpp new file mode 100644 index 00000000..54bbe566 --- /dev/null +++ b/Src/Winamp/setup/loadimage.cpp @@ -0,0 +1,235 @@ +#include "main.h" +#include "./loadimage.h" +#include "./api.h" +#include <api/service/waServiceFactory.h> +#include <api/service/svcs/svc_imgload.h> + +#define ABS(x) (((x) > 0) ? (x) : (-x)) + +static HANDLE ReadFromFile(LPCWSTR pszImage, DWORD *size, HANDLE *hres) +{ + HANDLE hFile = CreateFileW(pszImage, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, FILE_FLAG_SEQUENTIAL_SCAN, NULL), hmem(NULL); + *size = 0; + if (INVALID_HANDLE_VALUE != hFile) + { + *size = GetFileSize(hFile, NULL); + if (INVALID_FILE_SIZE != *size) + { + hmem = HeapAlloc(GetProcessHeap(), 0, *size); + if (hmem) + { + DWORD readed = 0; + if (!ReadFile(hFile, hmem, *size, &readed, NULL) || *size != readed) + { + HeapFree(GetProcessHeap(), 0, hmem); + hmem = NULL; + } + } + } + CloseHandle(hFile); + } + + *hres = hmem; + return hmem; +} + +static HANDLE ReadFromRes(HMODULE hMod, LPCWSTR pszSection, LPCWSTR pszImage, DWORD *size, HANDLE *hres) +{ + *size = 0; + HRSRC res = FindResourceW(hMod, pszImage, pszSection); + if (res) + { + *hres = LoadResource(hMod, res); + *size = SizeofResource(hMod, res); + return LockResource(*hres); + } + return NULL; +} + +static HANDLE LoadImg(HANDLE data, DWORD size, INT *cx, INT *cy, BOOL premult) +{ + FOURCC imgload = svc_imageLoader::getServiceType(); + int n = (int) WASABI_API_SVC->service_getNumServices(imgload); + for (int i=0; i<n; i++) + { + waServiceFactory *sf = WASABI_API_SVC->service_enumService(imgload,i); + if (sf) + { + svc_imageLoader * l = (svc_imageLoader*)sf->getInterface(); + if (l) + { + if (l->testData(data,size)) + { + HANDLE ret; + ret = (premult) ? l->loadImage(data, size, cx, cy) : l->loadImageData(data, size, cx, cy); + sf->releaseInterface(l); + return ret; + } + sf->releaseInterface(l); + } + } + } + return NULL; +} + +HBITMAP WALoadImage(HMODULE hMod, LPCWSTR pszSection, LPCWSTR pszImage, BOOL bPremult) +{ + BITMAPINFOHEADER header = {0}; + HBITMAP hbmp = NULL; + HANDLE hres = NULL; + LPVOID dib = NULL; + DWORD size = 0; + + header.biBitCount = 32; + header.biPlanes = 1; + header.biSize = sizeof(BITMAPINFOHEADER); + + LPVOID data = (!hMod) ? ReadFromFile(pszImage, &size, &hres) : ReadFromRes(hMod, pszSection, pszImage, &size, &hres); + + if (data) data = LoadImg(data, size, (int*)&header.biWidth, (int*)&header.biHeight, bPremult); + + if (hres) + { + (hMod) ? FreeResource(hres) : HeapFree(GetProcessHeap(), 0, hres); + } + + if (data) + { + header.biHeight = 0 - header.biHeight; + hbmp = CreateDIBSection(NULL, (LPBITMAPINFO)&header, DIB_RGB_COLORS, &dib, NULL, 0); + if (hbmp) CopyMemory(dib, data, header.biWidth * ABS(header.biHeight) * sizeof(DWORD)); + WASABI_API_MEMMGR->sysFree(data); + } + else hbmp = NULL; + return hbmp; +} + +HBITMAP WAResizeImage(HBITMAP hbmp, INT cx, INT cy, HBRUSH hbBk) +{ + BITMAP bi = {0}; + + if (!hbmp || !GetObject(hbmp, sizeof(BITMAP), &bi)) return hbmp; + + if (bi.bmWidth != cx || bi.bmHeight != cy) + { + INT ix = cx, iy = cy; + + HDC hdc = GetDC(NULL), + hdcSrc = CreateCompatibleDC(hdc), + hdcDst = CreateCompatibleDC(hdc); + HBITMAP hbmpOld1 = (HBITMAP)SelectObject(hdcSrc, hbmp); + hbmp = CreateCompatibleBitmap(hdc, cx, cy); + HBITMAP hbmpOld2 = (HBITMAP)SelectObject(hdcDst, hbmp); + if (ix != cx || iy != cy) + { + RECT r; + SetRect(&r, 0, 0, cx, cy); + FillRect(hdcDst, &r, hbBk); + } + SetStretchBltMode(hdcDst, HALFTONE); + StretchBlt(hdcDst, (cx - ix)/2, (cy - iy)/2, ix, iy, hdcSrc, 0, 0, bi.bmWidth, bi.bmHeight, SRCCOPY); + + SelectObject(hdcDst, hbmpOld2); + hbmpOld2 = (HBITMAP)SelectObject(hdcSrc, hbmpOld1); + if (hbmpOld2) DeleteObject(hbmpOld2); + + DeleteDC(hdcSrc); + DeleteDC(hdcDst); + ReleaseDC(NULL, hdc); + } + return hbmp; +} + +HBITMAP WABlendOnColor(HBITMAP hbmp, COLORREF rgbBk) +{ + DIBSECTION dibsec = {0}; + LONG pitch, x; + INT cx, cy; + LPBYTE cursor = NULL, line = NULL, pData = NULL; + + if (!hbmp || sizeof(DIBSECTION) != GetObjectW(hbmp, sizeof(DIBSECTION), &dibsec) || + BI_RGB != dibsec.dsBmih.biCompression || 1 != dibsec.dsBmih.biPlanes || 32 != dibsec.dsBm.bmBitsPixel) return hbmp; + + cx = dibsec.dsBm.bmWidth; + cy = dibsec.dsBm.bmHeight; + pitch = dibsec.dsBm.bmWidth*4; + pData = (LPBYTE)dibsec.dsBm.bmBits; + + for (line = pData; cy-- != 0; line += pitch ) + { + for (x = cx, cursor = line; x-- != 0; cursor += 4) + { + if (0x00 == cursor[3]) + { + cursor[0] = GetBValue(rgbBk); + cursor[1] = GetGValue(rgbBk); + cursor[2] = GetRValue(rgbBk); + cursor[3] = 0xFF; + } + else if (cursor[3] != 0xFF) + { + cursor[0] = (cursor[0]*cursor[3] + (((255 - cursor[3])*255 + 127)/255)*GetBValue(rgbBk) + 127)/255; + cursor[1] = (cursor[1]*cursor[3] + (((255 - cursor[3])*255 + 127)/255)*GetGValue(rgbBk) + 127)/255; + cursor[2] = (cursor[2]*cursor[3] + (((255 - cursor[3])*255 + 127)/255)*GetRValue(rgbBk) + 127)/255; + cursor[3] = 0xFF; + } + } + } + return hbmp; +} + +HBITMAP WACreatePatternBitmap(INT cx, INT cy, INT bpp, HBRUSH hbPattern, LPBYTE *ppData) +{ + BITMAPINFOHEADER bi = {0}; + RECT r; + HDC hdcTmp = CreateCompatibleDC(NULL); + + bi.biSize = sizeof (bi); + bi.biWidth= cx; + bi.biHeight = -cy; + bi.biPlanes = 1; + bi.biBitCount= (WORD)bpp; + + HBITMAP hbmpPattern = CreateDIBSection(hdcTmp, (BITMAPINFO *)&bi, DIB_RGB_COLORS, (LPVOID*)ppData, NULL, NULL); + if (!hbmpPattern) return NULL; + + HBITMAP hbmpOld = (HBITMAP)SelectObject(hdcTmp, hbmpPattern); + SetRect(&r, 0, 0, cx, cy); + FillRect(hdcTmp, &r, hbPattern); + SelectObject(hdcTmp, hbmpOld); + DeleteDC(hdcTmp); + return hbmpPattern; +} + +HBITMAP WABlendOnARGB32(HBITMAP hbmp, LPBYTE pRGB) +{ + DIBSECTION dibsec = {0}; + LONG pitch, x; + INT cx, cy; + LPBYTE cursor = NULL, cursor2 = NULL, line = NULL, line2 = NULL, pData = NULL; + + if (!hbmp || sizeof(DIBSECTION) != GetObjectW(hbmp, sizeof(DIBSECTION), &dibsec) || + BI_RGB != dibsec.dsBmih.biCompression || 1 != dibsec.dsBmih.biPlanes || 32 != dibsec.dsBm.bmBitsPixel) return hbmp; + + cx = dibsec.dsBm.bmWidth; + cy = dibsec.dsBm.bmHeight; + pitch = dibsec.dsBm.bmWidth*4; + pData = (LPBYTE)dibsec.dsBm.bmBits; + + for (line = pData, line2 = pRGB; cy-- != 0; line += pitch, line2 += pitch ) + { + for (x = cx, cursor = line, cursor2 = line2; x-- != 0; cursor += 4, cursor2 += 4) + { + if (0x00 == cursor[3]) *((DWORD*)cursor) = *((DWORD*)cursor2); + else if (cursor[3] != 0xFF) + { + cursor[0] = (cursor[0]*cursor[3] + (((255 - cursor[3])*255 + 127)/255)*cursor2[0] + 127)/255; + cursor[1] = (cursor[1]*cursor[3] + (((255 - cursor[3])*255 + 127)/255)*cursor2[1] + 127)/255; + cursor[2] = (cursor[2]*cursor[3] + (((255 - cursor[3])*255 + 127)/255)*cursor2[2] + 127)/255; + } + cursor[3] = 0xFF; + } + } + + return hbmp; +}
\ No newline at end of file diff --git a/Src/Winamp/setup/loadimage.h b/Src/Winamp/setup/loadimage.h new file mode 100644 index 00000000..eb873753 --- /dev/null +++ b/Src/Winamp/setup/loadimage.h @@ -0,0 +1,12 @@ +#ifndef WINAMP_LOADIMAGE_HEADER +#define WINAMP_LOADIMAGE_HEADER + +#include <windows.h> + +HBITMAP WALoadImage(HMODULE hMod, LPCWSTR pszSection, LPCWSTR pszImage, BOOL bPremult); +HBITMAP WAResizeImage(HBITMAP hbmp, INT cx, INT cy, HBRUSH hbBk); +HBITMAP WABlendOnColor(HBITMAP hbmp, COLORREF rgbBk); +HBITMAP WABlendOnARGB32(HBITMAP hbmp, LPBYTE pRGB); +HBITMAP WACreatePatternBitmap(INT cx, INT cy, INT bpp, HBRUSH hbPattern, LPBYTE *ppData); + +#endif //WINAMP_LOADIMAGE_HEADER
\ No newline at end of file diff --git a/Src/Winamp/setup/navitemstrip.bmp b/Src/Winamp/setup/navitemstrip.bmp Binary files differnew file mode 100644 index 00000000..0eb654ce --- /dev/null +++ b/Src/Winamp/setup/navitemstrip.bmp diff --git a/Src/Winamp/setup/navstrip.bmp b/Src/Winamp/setup/navstrip.bmp Binary files differnew file mode 100644 index 00000000..6105816d --- /dev/null +++ b/Src/Winamp/setup/navstrip.bmp diff --git a/Src/Winamp/setup/png.rc b/Src/Winamp/setup/png.rc new file mode 100644 index 00000000..e66ee65c --- /dev/null +++ b/Src/Winamp/setup/png.rc @@ -0,0 +1,72 @@ +// Microsoft Visual C++ generated resource script. +// +#include "resource.h" + +#define APSTUDIO_READONLY_SYMBOLS +///////////////////////////////////////////////////////////////////////////// +// +// Generated from the TEXTINCLUDE 2 resource. +// +#include "setup_resource.h" + +///////////////////////////////////////////////////////////////////////////// +#undef APSTUDIO_READONLY_SYMBOLS + +///////////////////////////////////////////////////////////////////////////// +// English (U.S.) resources + +#if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_ENU) +#ifdef _WIN32 +LANGUAGE LANG_ENGLISH, SUBLANG_ENGLISH_US +#pragma code_page(1252) +#endif //_WIN32 + +///////////////////////////////////////////////////////////////////////////// +// +// Data +// + +IDB_ABOUT ".\\smokingllama.png" +IDB_PREVIEW_CLASSIC ".\\preview_classicskin.png" +IDB_PREVIEW_NO_1 ".\\preview_no.png" + +#ifdef APSTUDIO_INVOKED +///////////////////////////////////////////////////////////////////////////// +// +// TEXTINCLUDE +// + +1 TEXTINCLUDE +BEGIN + "resource.h\0" +END + +2 TEXTINCLUDE +BEGIN + "#include ""setup_resource.h""\r\n" + "\0" +END + +3 TEXTINCLUDE +BEGIN + "\r\n" + "\0" +END + +#endif // APSTUDIO_INVOKED + +#endif // English (U.S.) resources +///////////////////////////////////////////////////////////////////////////// + + + +#ifndef APSTUDIO_INVOKED +///////////////////////////////////////////////////////////////////////////// +// +// Generated from the TEXTINCLUDE 3 resource. +// + + +///////////////////////////////////////////////////////////////////////////// +#endif // not APSTUDIO_INVOKED + diff --git a/Src/Winamp/setup/postsetup.cpp b/Src/Winamp/setup/postsetup.cpp new file mode 100644 index 00000000..55eafa94 --- /dev/null +++ b/Src/Winamp/setup/postsetup.cpp @@ -0,0 +1,68 @@ +#define APSTUDIO_READONLY_SYMBOLS +#include "main.h" +#include ".\postsetup.h" +#include "./setup_resource.h" +#include "./langutil.h" +#include "api.h" + + +static BOOL SleepMsg(DWORD dwTimeout) +{ + DWORD dwStart = GetTickCount(); + DWORD dwElapsed; + while ((dwElapsed = GetTickCount() - dwStart) < dwTimeout) + { + DWORD dwStatus = MsgWaitForMultipleObjectsEx(0, NULL, dwTimeout - dwElapsed, QS_ALLINPUT, MWMO_WAITALL | MWMO_INPUTAVAILABLE); + if (dwStatus == WAIT_OBJECT_0) while (application->app_messageLoopStep()); + } + return TRUE; // timed out +} + +BOOL StartWinamp(BOOL bWaitShow, HWND *phwndWA, LPCSTR pszParam) +{ + HWND hwndWA; + DWORD pid; + wchar_t buf[MAX_PATH] = L"\""; + STARTUPINFOW si = {sizeof(si), }; + PROCESS_INFORMATION pi; + + if (phwndWA) *phwndWA = NULL; + + GetModuleFileNameW(NULL, buf + 1, sizeof(buf)/sizeof(wchar_t) - 1); + StringCchCatW(buf, MAX_PATH, L"\" /NEW "); + if (*pszParam && lstrlenA(pszParam)) + { + int count, len; + len = sizeof(buf)/sizeof(wchar_t) - lstrlenW(buf)- 1; + count = MultiByteToWideChar(CP_ACP, 0, pszParam, -1, NULL, 0); + if (count < len) MultiByteToWideChar(CP_ACP, 0, pszParam, -1, buf + lstrlenW(buf), len); + } + si.dwFlags = STARTF_FORCEONFEEDBACK | STARTF_USESHOWWINDOW; + si.wShowWindow = SW_SHOWNOACTIVATE; + if ( 0 ==CreateProcessW(NULL, buf, NULL, NULL, FALSE, 0, NULL, NULL, &si, &pi)) + { + return FALSE; + } + + hwndWA = NULL; + if (bWaitShow) + { + for (int a = 0; a < 20; a++) + { + if (!hwndWA) + { + while (NULL != (hwndWA = FindWindowExW(NULL, hwndWA, szAppName, NULL))) + { + GetWindowThreadProcessId(hwndWA, &pid); + if (pid == pi.dwProcessId) break; + } + } + SleepMsg(250); + if (hwndWA && IsWindowVisible(hwndWA)) + break; + } + } + + if (phwndWA) *phwndWA = hwndWA; + return TRUE; +}
\ No newline at end of file diff --git a/Src/Winamp/setup/postsetup.h b/Src/Winamp/setup/postsetup.h new file mode 100644 index 00000000..001ed6ae --- /dev/null +++ b/Src/Winamp/setup/postsetup.h @@ -0,0 +1,10 @@ +#ifndef WINAMP_POSTSETUP_HEADER +#define WINAMP_POSTSETUP_HEADER + +#include <windows.h> + +HWND CreateStatusWnd(HWND hwndParent, INT x, INT y, INT cx, INT cy); +void SetStatusText(); +BOOL StartWinamp(BOOL bWaitShow, HWND *phwndWA, LPCSTR pszParam); + +#endif //WINAMP_POSTSETUP_HEADER
\ No newline at end of file diff --git a/Src/Winamp/setup/preview_classic.png b/Src/Winamp/setup/preview_classic.png Binary files differnew file mode 100644 index 00000000..7a02a1da --- /dev/null +++ b/Src/Winamp/setup/preview_classic.png diff --git a/Src/Winamp/setup/preview_no.png b/Src/Winamp/setup/preview_no.png Binary files differnew file mode 100644 index 00000000..317bc0ab --- /dev/null +++ b/Src/Winamp/setup/preview_no.png diff --git a/Src/Winamp/setup/resource.h b/Src/Winamp/setup/resource.h new file mode 100644 index 00000000..7a1e3e2c --- /dev/null +++ b/Src/Winamp/setup/resource.h @@ -0,0 +1,16 @@ +//{{NO_DEPENDENCIES}} +// Microsoft Visual C++ generated include file. +// Used by png.rc +// +#define IDB_PREVIEW_NO_1 115 + +// Next default values for new objects +// +#ifdef APSTUDIO_INVOKED +#ifndef APSTUDIO_READONLY_SYMBOLS +#define _APS_NEXT_RESOURCE_VALUE 117 +#define _APS_NEXT_COMMAND_VALUE 40017 +#define _APS_NEXT_CONTROL_VALUE 1033 +#define _APS_NEXT_SYMED_VALUE 101 +#endif +#endif diff --git a/Src/Winamp/setup/setup.cpp b/Src/Winamp/setup/setup.cpp new file mode 100644 index 00000000..4ec461ae --- /dev/null +++ b/Src/Winamp/setup/setup.cpp @@ -0,0 +1,1131 @@ +#define APSTUDIO_READONLY_SYMBOLS +#include "main.h" +#include "./setup.h" +#include "./setup_resource.h" +#include "./loadimage.h" +#include "./langutil.h" +#include "../nu/AutoWide.h" +#include "api.h" + +#define HEADER_FONT_NAME "Arial"//"Lucida Sans Unicode"//"Verdana"//"Trebuchet MS"//"Arial Unicode MS" +#define HEADER_FONT_SIZE 13 //11 +#define HEADER_FONT_ITALIC FALSE +#define HEADER_FONT_WEIGHT FW_MEDIUM +#define HEADER_TEXT_COLOR RGB(255,255,255)//RGB(16, 72, 148)//RGB(7, 30, 140) +#define HEADER_BORDER_COLOR RGB(236, 233, 216) + +#define HEADER_PAGENUM_FONT_NAME "Lucida Sans Unicode"//"Lucida Sans Unicode"//"Verdana"//"Trebuchet MS"//"Arial Unicode MS" +#define HEADER_PAGENUM_FONT_SIZE 10 +#define HEADER_PAGENUM_FONT_ITALIC FALSE +#define HEADER_PAGENUM_FONT_WEIGHT FW_SEMIBOLD//FW_MEDIUM +#define HEADER_PAGENUM_TEXT_COLOR RGB(210,120,42) + +#define NAVIGATION_FONT_NAME "Arial" +#define NAVIGATION_FONT_SIZE 9 +#define NAVIGATION_FONT_ITALIC FALSE +#define NAVIGATION_FONT_WEIGHT FW_MEDIUM + +#define NAVIGATION_SEL_FONT_NAME "Arial" +#define NAVIGATION_SEL_FONT_SIZE 10 +#define NAVIGATION_SEL_FONT_ITALIC FALSE +#define NAVIGATION_SEL_FONT_WEIGHT FW_MEDIUM//FW_SEMIBOLD + +#define NAVIGATION_SEL_TEXT_COLOR RGB(252, 252, 255) +#define NAVIGATION_TEXT_COLOR RGB(222, 225, 234) +#define NAVIGATION_BACK_COLOR RGB(137,145,156)//RGB(150,156,163) +#define NAVIGATION_PADDING_LEFT 0 +#define NAVIGATION_PADDING_RIGHT 0 + +#define PAGE_BACK_COLOR RGB(236, 234, 232) + + +typedef struct _UI +{ + ULONG ref; + HBRUSH hbPage; + HBRUSH hbHeader; + HBRUSH hbNavItemSel; + HBRUSH hbNavBack; + HFONT hfHeader; + HFONT hfNavItem; + HFONT hfNavItemSel; + HFONT hfHeaderPageNum; + INT nHdrTxtHeight; + INT nHdrPageTxtHeight; + INT nNavTxtHeight; + INT nNavTxtSelHeight; + INT nHdrHeight; + INT nNavItemHeight; + COLORREF rgbPageBk; +} UI; + +typedef struct _SPTHEME +{ + WNDPROC fnOldProc; + UI *pui; + BOOL bUnicode; +} SPTHEME; + +static WASetup *g_pAttachInstance = NULL; +static BOOL bUseMarquee = -1; + +static INT_PTR WINAPI AboutDialogProc(HWND hwndDlg, UINT uMsg, WPARAM wParam, LPARAM lParam); +static INT_PTR WINAPI JobStatusDialog(HWND hwndDlg, UINT uMsg, WPARAM wParam, LPARAM lParam); +static INT_PTR WINAPI ErrorPageDialog(HWND hwndDlg, UINT uMsg, WPARAM wParam, LPARAM lParam); +static LRESULT WINAPI PageWndProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam); +static INT ConvertFontHeight(HWND hwnd, INT ptHeight); +static DWORD GetHighestFontQuality(void); +static BOOL InitializeUI(UI *pui, HWND hwndCtrl); +static BOOL ReleaseUI(UI *pui); +static const wchar_t *GetUnknownStr(void); +static LRESULT WINAPI FrameWndProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam); +static BOOL JobStatus_Advance(HWND hwndStatus); + +WASetup::WASetup(void) + : ref((size_t)1), hwnd(NULL), hwndActive(NULL), nPageActive((size_t)-1), pui(NULL), hWinamp(NULL) +{ +} + +WASetup::~WASetup(void) +{ + if (hwnd && IsWindow(hwnd)) DestroyWindow(hwnd); + size_t index; + index = pageList.size(); + while(index--) + { + pageList[index]->Release(); + } + + index = jobList.size(); + while(index--) + { + jobList[index]->Release(); + } +} +svc_setup *WASetup::CreateInstance() +{ + WASetup *instance = new WASetup(); + return (svc_setup*)instance; +} + +int WASetup::AddRef(void) +{ + return ++ref; +} + +int WASetup::Release(void) +{ + if (1 == ref) + { + delete(this); + return 0; + } + return --ref; +} + + +HRESULT WASetup::InsertPage(ifc_setuppage *pPage, int* pIndex) +{ + size_t index; + if (!pIndex || !pPage) return E_INVALIDARG; + + index = *pIndex; + if (index >= pageList.size()) + { + index = pageList.size(); + pageList.push_back(pPage); + } + else + { + //pageList.insertBefore(*pIndex, pPage); + pageList.insert(pageList.begin() + index, pPage); + } + + *pIndex = (int)index; + pPage->AddRef(); + return S_OK; +} + +HRESULT WASetup::RemovePage(size_t index) +{ + if (index >= pageList.size()) + return HRESULT_FROM_WIN32(ERROR_INVALID_INDEX); + pageList[index]->Release(); + pageList.erase(pageList.begin() + index); + return S_OK; +} + +HRESULT WASetup::GetPageCount(int *pCount) +{ + if (!pCount) return E_INVALIDARG; + *pCount = (int)pageList.size(); + return S_OK; +} + +HRESULT WASetup::GetPage(size_t index, ifc_setuppage **pPage) +{ + if (index >= pageList.size()) return HRESULT_FROM_WIN32(ERROR_INVALID_INDEX); + *pPage = pageList[index]; + return S_OK; +} + +HRESULT WASetup::AddJob(ifc_setupjob *pJob) +{ + for (size_t i = 0; i < jobList.size(); i++) + { + if (jobList[i] == pJob) return S_OK; + } + jobList.push_back(pJob); + pJob->AddRef(); + return S_OK; +} + +HRESULT WASetup::RemoveJob(ifc_setupjob *pJob) +{ + for (size_t i = 0; i < jobList.size(); i++) + { + if (jobList[i] == pJob) + { + jobList[i]->Release(); + jobList.erase(jobList.begin() + i); + return S_OK; + } + } + return E_INVALIDARG; +} + +HRESULT WASetup::GetActiveIndex(int* pIndex) +{ + if (!pIndex) return E_INVALIDARG; + *pIndex = (int)nPageActive; + return S_OK; +} + +HRESULT WASetup::CreateStatusWnd(HWND *phwndStatus) +{ + HWND hwndStatus; + + if (!phwndStatus) return S_FALSE; + *phwndStatus = NULL; + + if (-1 == bUseMarquee) + { + OSVERSIONINFO vi; + vi.dwOSVersionInfoSize = sizeof(OSVERSIONINFO); + bUseMarquee = (GetVersionEx(&vi) && (vi.dwMajorVersion > 5 || (vi.dwMajorVersion == 5 && vi.dwMinorVersion > 0))); + } + + hwndStatus = WACreateDialog(MAKEINTRESOURCEW(IDD_SETUPSTATUS), NULL, JobStatusDialog); + if (!hwndStatus) return S_FALSE; + + if (rcUI.right != rcUI.left) + { + RECT rw; + GetWindowRect(hwndStatus, &rw); + SetWindowPos(hwndStatus, NULL, rcUI.left + ((rcUI.right - rcUI.left) - (rw.right - rw.left))/2, + rcUI.top + ((rcUI.bottom - rcUI.top) - (rw.bottom - rw.top))/2, 0, 0, SWP_NOSIZE | SWP_NOACTIVATE | SWP_NOZORDER); + } + + HWND hwndCtrl = GetDlgItem(hwndStatus, IDC_PROGRESS); + if (hwndCtrl) + { + if (bUseMarquee) + { + SetWindowLongPtrW(hwndCtrl, GWL_STYLE, GetWindowLongPtrW(hwndCtrl, GWL_STYLE) | 0x08/*PBS_MARQUEE*/); + SendMessageW(hwndCtrl, (WM_USER + 10)/*PBM_SETMARQUEE*/, TRUE, (LPARAM)200); + } + else + { + SendMessageW(hwndCtrl, PBM_SETRANGE, 0, MAKELPARAM(0, 1 + (INT)(pageList.size() + jobList.size()))); + SendMessageW(hwndCtrl, PBM_SETPOS, 0, 0L); + SendMessageW(hwndCtrl, PBM_SETSTEP, 1, 0L); + } + } + + *phwndStatus = hwndStatus; + return S_OK; +} + +static BOOL WaSetup_MessageLoop(HWND hMainWnd, HACCEL hAccel) +{ + MSG msg; + + for (;;) + { + DWORD status = MsgWaitForMultipleObjectsEx(0, NULL, INFINITE, QS_ALLINPUT, MWMO_ALERTABLE | MWMO_INPUTAVAILABLE); + if (WAIT_OBJECT_0 == status) + { + while (PeekMessageW(&msg, NULL, 0, 0, PM_REMOVE)) + { + //if (!CallMsgFilter(&msg, MSGF_DIALOGBOX)) + { + if (msg.message == WM_QUIT) + return (BOOL)msg.wParam; + + if (!TranslateAcceleratorW(hMainWnd, hAccel, &msg) && + !IsDialogMessageW(hMainWnd, &msg)) + { + TranslateMessage(&msg); + DispatchMessageW(&msg); + } + } + } + } + } +} + +HRESULT WASetup::Start(HWND hwndWinamp) +{ + INT_PTR r(IDOK); + + SetRectEmpty(&rcUI); + + hWinamp = hwndWinamp; + + if (pageList.size()) + { + HACCEL hAccel; + static UI ui = {0, }; + + for (size_t i = 0; i < pageList.size(); i++) pageList[i]->Revert(); + g_pAttachInstance = this; + + InitializeUI(&ui, hwnd); + pui = &ui; + + hwnd = WACreateDialog(MAKEINTRESOURCEW(IDD_SETUP), NULL, ::DialogProc); + if (!hwnd) return E_UNEXPECTED; + HINSTANCE hInst = (language_pack_instance) ? language_pack_instance : hMainInstance; + hAccel = LoadAcceleratorsW(hInst, MAKEINTRESOURCEW(IDR_ACCEL_SETUP)); + + r = WaSetup_MessageLoop(hwnd, hAccel); + + g_pAttachInstance = NULL; + ReleaseUI(&ui); + } + + return (IDOK == r) ? S_OK : S_FALSE; +} + +HRESULT WASetup::Save(HWND hwndStatus) +{ + HRESULT hr(S_OK); + HWND hwndText = GetDlgItem(hwndStatus, IDC_LBL_STATUS); + for (size_t i = 0; i < pageList.size(); i++) + { + if (hwndText) SetWindowTextW(hwndText, getStringW(IDS_STATUS_SAVING, NULL, 0)); + if (S_OK != pageList[i]->Save(hwndText)) hr = S_FALSE; + JobStatus_Advance(hwndStatus); + } + WritePrivateProfileStringW(L"WinampReg", L"WAVer", AutoWide(APP_VERSION), INI_FILE); + return hr; +} +HRESULT WASetup::ExecJobs(HWND hwndStatus) +{ + HRESULT hr(S_OK); + HWND hwndText = GetDlgItem(hwndStatus, IDC_LBL_STATUS); + HWND hwndBtn = GetDlgItem(hwndStatus, IDC_BTN_SKIP); + for (size_t i = 0; i < jobList.size(); i++) + { + if (hwndText) SetWindowTextW(hwndText, getStringW(IDS_STATUS_JOBS, NULL, 0)); + if (hwndBtn && S_OK == jobList[i]->IsCancelSupported() && + SetPropW(hwndStatus, L"JOB", (HANDLE)jobList[i])) + { + EnableWindow(hwndBtn, TRUE); + } + + if (S_OK != jobList[i]->Execute(hwndText)) hr = S_FALSE; + if (hwndBtn) EnableWindow(hwndBtn, FALSE); + JobStatus_Advance(hwndStatus); + } + + return hr; +} + +HRESULT WASetup::GetWinampWnd(HWND *phwndWinamp) +{ + if (NULL == phwndWinamp) + return E_INVALIDARG; + *phwndWinamp = hWinamp; + return (NULL == hWinamp) ? E_UNEXPECTED : S_OK; +} + +static INT_PTR CALLBACK tmpProc(HWND hwndDlg, UINT uMsg, WPARAM wParam, LPARAM lParam) +{ + return 0; +} + +INT_PTR WASetup::OnInitDialog(HWND hwndFocused, LPARAM lParam) +{ + HWND hwndLB, hwndFrame, hwndHeader; + RECT rw, rc; + HICON hIcon = LoadIconW(hMainInstance, MAKEINTRESOURCE(ICON_XP)); + + // make other people's dialogs show the winamp icon + HWND h = CreateDialogW(hMainInstance, MAKEINTRESOURCE(IDD_OPENLOC), NULL, tmpProc); + SetClassLongPtrW(h, GCLP_HICON, (LONG_PTR)hIcon); + DestroyWindow(h); + + SendMessageW(hwnd, WM_NEXTDLGCTL, (WPARAM)GetDlgItem(hwnd, IDC_BTN_NEXT), TRUE); + + wchar_t buf[256] = {0}; + StringCchPrintfW(buf,256, getStringW(IDS_SETUP_WND_TITLE,NULL,0), AutoWideDup(app_version_string)); + SetWindowTextW(hwnd, buf); + + // adjust dialog + rw.left = GetPrivateProfileIntW(L"SETUP", L"left", 0, INI_FILE); + rw.top = GetPrivateProfileIntW(L"SETUP", L"top", 0, INI_FILE); + rw.right = GetPrivateProfileIntW(L"SETUP", L"right", 0, INI_FILE); + rw.bottom = GetPrivateProfileIntW(L"SETUP", L"bottom", 0, INI_FILE); + + if (rw.left != rw.right && rw.top != rw.bottom) + { + INT x, y; + GetWindowRect(hwnd, &rc); + x = (rw.right) ? (rw.left + ((rw.right - rw.left) - (rc.right - rc.left))/2) : rw.left; + y = (rw.bottom) ? (rw.top + ((rw.bottom - rw.top) - (rc.bottom - rc.top))/2) : rw.top; + SetWindowPos(hwnd, NULL, x, y, rc.right - rc.left, rc.bottom - rc.top, SWP_NOSIZE | SWP_NOACTIVATE | SWP_NOZORDER); + } + + hwndFrame = GetDlgItem(hwnd, IDC_FRAME); + + // TODO if this is needed again then remove + // deletes the 'Tools' menu as it's not used + DeleteMenu(GetMenu(hwnd), 2, MF_BYPOSITION); + DrawMenuBar(hwnd); + + WNDPROC fnOldProc = (WNDPROC)(LONG_PTR)SetWindowLongPtrW(hwndFrame, GWLP_WNDPROC, (LONG_PTR)FrameWndProc); + if (fnOldProc) SetPropW(hwndFrame, L"SKINFRAME", fnOldProc); + + SetWindowLongPtrW(hwndFrame, GWL_STYLE, GetWindowLongPtrW(hwndFrame, GWL_STYLE) | WS_CLIPSIBLINGS | WS_CLIPCHILDREN); + if (!IsWinXPTheme()) SetWindowLongPtrW(hwndFrame, GWL_EXSTYLE, (GetWindowLongPtrW(hwndFrame, GWL_EXSTYLE) & ~WS_EX_CLIENTEDGE) | WS_EX_STATICEDGE); + SetWindowPos(hwndFrame, HWND_BOTTOM, 0,0,0,0, SWP_NOACTIVATE | SWP_NOMOVE | SWP_NOSIZE | SWP_FRAMECHANGED | SWP_NOOWNERZORDER); + + GetClientRect(hwndFrame, &rc); + MapWindowPoints(hwndFrame, hwnd, (POINT*)&rc, 2); + + hwndLB = GetDlgItem(hwnd, IDC_LB_NAVIGATION); + if (hwndLB) + { + GetWindowRect(hwndLB, &rw); + SetWindowPos(hwndLB, GetDlgItem(hwnd, IDC_BTN_BACK), rc.left, rc.top, rw.right - rw.left, rc.bottom - rc.top, SWP_NOACTIVATE | SWP_NOOWNERZORDER); + SendMessageW(hwndLB, WM_SETFONT, (WPARAM)pui->hfNavItem, FALSE); + } + + hwndHeader = GetDlgItem(hwnd, IDC_HEADER); + if (hwndHeader) + { + SendMessageW(hwndHeader, WM_SETFONT, (WPARAM)pui->hfHeader, FALSE); + GetWindowRect(hwndLB, &rw); + MapWindowPoints(HWND_DESKTOP, hwnd, (POINT*)&rw, 2); + SetWindowPos(hwndHeader, NULL, rw.right, rc.top, rc.right - rw.right, pui->nHdrHeight, SWP_NOACTIVATE | SWP_NOOWNERZORDER | SWP_NOZORDER); + } + + if (hwndLB) + { + for (size_t i = 0; i < pageList.size(); i++) SendMessageW(hwndLB, LB_ADDSTRING, 0, (LPARAM)i); + SendMessageW(hwndLB, LB_SETCURSEL, 0, 0L); + PostMessageW(hwnd, WM_COMMAND, MAKEWPARAM(IDC_LB_NAVIGATION, LBN_SELCHANGE), (LPARAM)hwndLB); + } + + ShowWindow(hwnd, SW_SHOWNORMAL); + DWORD ourThreadID, foregroundThreadID; + foregroundThreadID = GetWindowThreadProcessId(GetForegroundWindow(), NULL); + ourThreadID = GetCurrentThreadId(); + + if (foregroundThreadID != ourThreadID) AttachThreadInput(foregroundThreadID, ourThreadID, TRUE); + SetWindowPos(hwnd, HWND_TOP, 0, 0, 0, 0, SWP_NOSIZE | SWP_NOMOVE); + SetForegroundWindow(hwnd); + SetFocus(hwnd); + if (foregroundThreadID != ourThreadID) AttachThreadInput(foregroundThreadID, ourThreadID, FALSE); + + return 0; +} + +void WASetup::OnDestroy(void) +{ + GetWindowRect(hwnd, &rcUI); +} + +void WASetup::OnCancel(void) +{ + BOOL bNeedSave = FALSE; + WCHAR szTitle[128] = {0}; + + for (size_t i = 0; i < pageList.size() && !bNeedSave; i++) + { + bNeedSave = (S_FALSE != pageList[i]->IsDirty()); + } + + GetWindowTextW(hwnd, szTitle, sizeof(szTitle)/sizeof(WCHAR)); + if (bNeedSave) + { + INT nr = MessageBoxW(hwnd, getStringW(IDS_SAVE_CHANGES_BEFORE_EXIT, NULL, 0), szTitle, MB_YESNOCANCEL | MB_ICONWARNING); + switch(nr) + { + case IDYES: SendMessageW(hwnd, WM_COMMAND, MAKEWPARAM(IDM_FILE_SAVECHANGES, 0), 0L); break; + case IDCANCEL: return; + } + } + else if (IDNO == MessageBoxW(hwnd, getStringW(IDS_QUIT_OK, NULL, 0), szTitle, MB_YESNO | MB_ICONWARNING)) return; + + DestroyWindow(hwnd); + PostQuitMessage(IDCANCEL); +} + +void WASetup::OnNext_Clicked(HWND hwndCtrl) +{ + HWND hwndLB = GetDlgItem(hwnd, IDC_LB_NAVIGATION); + INT index = (INT)SendMessageW(hwndLB, LB_GETCURSEL, 0, 0L) + 1; + if (index > -1) SendMessageW(hwndLB, LB_SETCURSEL, (WPARAM)index, 0L); + PostMessageW(hwnd, WM_COMMAND, MAKEWPARAM(IDC_LB_NAVIGATION, LBN_SELCHANGE), (LPARAM)hwndLB); +} + +void WASetup::OnBack_Clicked(HWND hwndCtrl) +{ + HWND hwndLB = GetDlgItem(hwnd, IDC_LB_NAVIGATION); + INT index = (INT)SendMessageW(hwndLB, LB_GETCURSEL, 0, 0L) -1; + if (index > -1) SendMessageW(hwndLB, LB_SETCURSEL, (WPARAM)index, 0L); + PostMessageW(hwnd, WM_COMMAND, MAKEWPARAM(IDC_LB_NAVIGATION, LBN_SELCHANGE), (LPARAM)hwndLB); +} + +void WASetup::OnNavigation_SelChange(HWND hwndCtrl) +{ + HWND hwndFrame; + HMENU hMenu; + MENUITEMINFO mii; + + INT idList[] = { IDC_BTN_BACK, IDC_BTN_NEXT}; + INT count = (INT)SendMessageW(hwndCtrl, LB_GETCOUNT, 0, 0L); + INT index = (INT)SendMessageW(hwndCtrl, LB_GETCURSEL, 0, 0L); + + if (nPageActive == (size_t)index) return; + + if (-1 != nPageActive && S_FALSE == pageList[nPageActive]->Validate()) + { + SendMessageW(hwndCtrl, LB_SETCURSEL, nPageActive, 0L); + return; + } + + hwndFrame = GetDlgItem(hwnd, IDC_FRAME); + hMenu = GetMenu(hwnd); + + mii.cbSize = sizeof(MENUITEMINFO); + mii.fMask = MIIM_STATE; + + for(int i = sizeof(idList)/sizeof(int) - 1; i >= 0 ; i--) + { + HWND hwndBtn = GetDlgItem(hwnd, idList[i]); + BOOL bEnable = (IDC_BTN_NEXT == idList[i]) ? ((count - index) > 1) : (0 != index); + if (hwndBtn) + { + if (bEnable != IsWindowEnabled(hwndBtn)) + { + if (IDC_BTN_NEXT == idList[i]) SendMessageW(hwnd, DM_SETDEFID, (WPARAM)((bEnable) ? IDC_BTN_NEXT : IDOK), 0L); + EnableWindow(hwndBtn, bEnable); + } + + if (hMenu) + { + mii.fState = (bEnable) ? MFS_ENABLED : MFS_DISABLED; + SetMenuItemInfoW(hMenu, (IDC_BTN_NEXT == idList[i]) ? IDM_NAVIGATE_NEXT : IDM_NAVIGATE_BACK, FALSE, &mii); + } + } + } + + if (hwndActive) + { + DestroyWindow(hwndActive); + hwndActive = NULL; + nPageActive = (size_t)-1; + } + + if (S_OK != pageList[index]->CreateView(hwnd, &hwndActive)) + hwndActive = WACreateDialog(MAKEINTRESOURCEW(IDD_SETUP_PAGE_ERROR), hwnd, ErrorPageDialog); + + HWND hwndHeader; + RECT rc; + GetClientRect(hwndFrame, &rc); + MapWindowPoints(hwndFrame, hwnd, (POINT*)&rc, 2); + + hwndHeader = GetDlgItem(hwnd, IDC_HEADER); + if (hwndHeader && (WS_VISIBLE & GetWindowLongPtrW(hwndHeader, GWL_STYLE))) + { + RECT rw; + GetWindowRect(hwndHeader, &rw); + MapWindowPoints(HWND_DESKTOP, hwnd, (POINT*)&rw, 2); + rc.top = rw.bottom; + rc.left = rw.left; + } + + SetWindowPos(hwndActive, GetDlgItem(hwnd, IDC_LB_NAVIGATION), rc.left, rc.top, rc.right - rc.left, rc.bottom - rc.top, SWP_NOACTIVATE); + + if(IsWinXPTheme()) WAEnableThemeDialogTexture(hwndActive, ETDT_ENABLETAB); + else + { + SPTHEME *pTheme = (SPTHEME*)malloc(sizeof(SPTHEME)); + pTheme->bUnicode = IsWindowUnicode(hwndActive); + pTheme->pui = pui; + pTheme->fnOldProc = (WNDPROC)SetWindowLongPtrW(hwndActive, GWLP_WNDPROC, (LONG_PTR)PageWndProc); + if (!pTheme->fnOldProc || !SetPropW(hwndActive, L"SPTHEME", pTheme)) + { + if (pTheme->fnOldProc) SetWindowLongPtrW(hwndActive, GWLP_WNDPROC, (LONG_PTR)pTheme->fnOldProc); + free(pTheme); + } + } + ShowWindow(hwndActive, SW_SHOW); + nPageActive = index; + + if (hwndHeader) InvalidateRect(hwndHeader, NULL, FALSE); + + HWND hwndTest = GetNextDlgTabItem(hwnd, GetWindow(hwndActive, GW_HWNDPREV), FALSE); + if (hwndTest) SendMessageW(hwnd, WM_NEXTDLGCTL, (WPARAM)hwndTest, TRUE); +} + +void WASetup::OnCommand(INT nCtrlID, INT nEvntID, HWND hwndCtrl) +{ + switch(nCtrlID) + { + case IDOK: + if (BN_CLICKED == nEvntID) + { + if (-1 != nPageActive && S_FALSE != pageList[nPageActive]->Validate()) + { + DestroyWindow(hwnd); + PostQuitMessage(IDOK); + } + } + break; + case IDCANCEL: if (BN_CLICKED == nEvntID) OnCancel(); break; + case IDC_BTN_NEXT: if (BN_CLICKED == nEvntID) OnNext_Clicked(hwndCtrl); break; + case IDC_BTN_BACK: if (BN_CLICKED == nEvntID) OnBack_Clicked(hwndCtrl); break; + + case IDC_LB_NAVIGATION: + switch(nEvntID) + { + case LBN_SELCHANGE: OnNavigation_SelChange(hwndCtrl); break; + } + break; + + case IDM_HELP_ABOUT: WADialogBox(MAKEINTRESOURCEW(IDD_ABOUT), hwnd, AboutDialogProc); break; + case IDM_NAVIGATE_BACK: SendMessageW(GetDlgItem(hwnd, IDC_BTN_BACK), BM_CLICK, 0, 0L); break; + case IDM_NAVIGATE_NEXT: SendMessageW(GetDlgItem(hwnd, IDC_BTN_NEXT), BM_CLICK, 0, 0L); break; + case IDM_FILE_EXIT: OnCancel(); break; + case IDM_FILE_SAVECHANGES: + if (S_OK != Save(NULL)) + { + WCHAR szTitle[128] = {0}, szText[256] = {0}; + GetWindowTextW(hwnd, szTitle, sizeof(szTitle)/sizeof(WCHAR)); + MessageBoxW(hwnd, getStringW(IDS_CHANGES_NOT_SAVED, szText, sizeof(szText)/sizeof(wchar_t)), szTitle, MB_OK | MB_ICONERROR); + } + break; + } +} + +void WASetup::OnDrawHeader(DRAWITEMSTRUCT *pdis) +{ + const wchar_t *pszName; + RECT ri, re; + INT top; + + CopyRect(&ri, &pdis->rcItem); + CopyRect(&re, &ri); + re.right = ri.left + 1; + + FillRect(pdis->hDC, &re, (HBRUSH)GetStockObject(WHITE_BRUSH)); + + ri.left = re.right; + SetBrushOrgEx(pdis->hDC, ri.left, ri.top, NULL); + FillRect(pdis->hDC, &ri, pui->hbHeader); + + if (nPageActive >= pageList.size() || S_OK != pageList[nPageActive]->GetName(FALSE, &pszName) || !*pszName) pszName = GetUnknownStr(); + + SetBkMode(pdis->hDC, TRANSPARENT); + + InflateRect(&ri, -4, -2); + + top = ri.top + (ri.bottom - ri.top - pui->nHdrTxtHeight)/2 - 1; + if (top > ri.top) ri.top = top; + + if (ri.left < ri.right) + { + RECT rn; + wchar_t szPageInfo[64] = {0}; + CopyRect(&rn, &ri); + SetTextColor(pdis->hDC, HEADER_PAGENUM_TEXT_COLOR); + UINT oldMode = SetTextAlign(pdis->hDC, TA_RIGHT); + HFONT hfOld = (pui->hfHeaderPageNum) ? (HFONT)SelectObject(pdis->hDC, pui->hfHeaderPageNum) : NULL; + top = ri.top + pui->nHdrTxtHeight - pui->nHdrPageTxtHeight; + if (top > rn.top) rn.top = top; + rn.right -= 8; + rn.left = rn.right - 42; + StringCchPrintfW(szPageInfo, sizeof(szPageInfo)/sizeof(wchar_t), L"%d/%d", nPageActive + 1, pageList.size()); + ExtTextOutW(pdis->hDC, rn.right, rn.top, ETO_CLIPPED, &rn, szPageInfo, lstrlenW(szPageInfo), NULL); + + SetTextAlign(pdis->hDC, oldMode); + if (hfOld) SelectObject(pdis->hDC, hfOld); + ri.right = rn.left -= 4; + } + + if (ri.left < ri.right) + { + SetTextColor(pdis->hDC, HEADER_TEXT_COLOR); + SetTextAlign(pdis->hDC, TA_LEFT); + ExtTextOutW(pdis->hDC, ri.left, ri.top, ETO_CLIPPED, &ri, pszName, lstrlenW(pszName), NULL); + } +} + +void WASetup::OnDrawNavigationItem(DRAWITEMSTRUCT *pdis) +{ + const wchar_t *pszName; + RECT ri; + HFONT hfOld; + wchar_t szTitle[128] = {0}; + COLORREF rgbText; + + if (pdis->itemID == -1) return; + + CopyRect(&ri, &pdis->rcItem); + ri.left += NAVIGATION_PADDING_LEFT; + ri.right -= NAVIGATION_PADDING_RIGHT; + + if (ODA_FOCUS == pdis->itemAction) + { + if (0 == (0x0200/*ODS_NOFOCUSRECT*/ & pdis->itemState)) + { + InflateRect(&ri, -1, -1); + DrawFocusRect(pdis->hDC, &ri); + } + return; + } + + if (ODS_SELECTED & pdis->itemState) + { + HBRUSH hbActive; + if (pui->hbNavItemSel) + { + SetBrushOrgEx(pdis->hDC, ri.left, ri.top, NULL); + hbActive = pui->hbNavItemSel; + } + else + { + SetBrushOrgEx(pdis->hDC, 0, 0, NULL); + hbActive = pui->hbNavBack; + } + FillRect(pdis->hDC, &ri, hbActive); + rgbText = SetTextColor(pdis->hDC, NAVIGATION_SEL_TEXT_COLOR); + hfOld = (HFONT)SelectObject(pdis->hDC, pui->hfNavItemSel); + } + else + { + if (ODA_SELECT == pdis->itemAction) + { + SetBrushOrgEx(pdis->hDC, 0, 0, NULL); + FillRect(pdis->hDC, &ri, pui->hbNavBack); + } + rgbText = 0; + hfOld = NULL; + } + + if (pdis->itemData >= pageList.size() || S_OK != pageList[pdis->itemData]->GetName(TRUE, &pszName) || !*pszName) + pszName = GetUnknownStr(); + + SetBkMode(pdis->hDC, TRANSPARENT); + + InflateRect(&ri, -4, -2); + INT top = ri.top + (ri.bottom - ri.top - pui->nNavTxtHeight)/2 - 1; + if (top > ri.top) ri.top = top; + + StringCchPrintfW(szTitle, sizeof(szTitle)/sizeof(wchar_t), L"%d. %s", pdis->itemData + 1, pszName); + ExtTextOutW(pdis->hDC, ri.left, ri.top, ETO_CLIPPED, &ri, szTitle, lstrlenW(szTitle), NULL); + + if (ODS_SELECTED & pdis->itemState) + { + SetTextColor(pdis->hDC, rgbText); + if (hfOld) SelectObject(pdis->hDC, hfOld); + } +} + +INT_PTR WASetup::OnDrawItem(INT nCtrlID, DRAWITEMSTRUCT *pdis) +{ + switch(nCtrlID) + { + case IDC_HEADER: OnDrawHeader(pdis); return TRUE; + case IDC_LB_NAVIGATION: OnDrawNavigationItem(pdis); return TRUE; + } + return 0; +} + +INT_PTR WASetup::OnMeasureItem(INT nCtrlID, MEASUREITEMSTRUCT *pmis) +{ + switch(nCtrlID) + { + case IDC_LB_NAVIGATION: + pmis->itemHeight = (pui) ? pui->nNavItemHeight : 0; + return TRUE; + } + return FALSE; +} + +INT_PTR WASetup::OnColorListBox(HDC hdc, HWND hwndCtrl) +{ + if (hwndCtrl == GetDlgItem(hwnd, IDC_LB_NAVIGATION)) + { + + SetTextColor(hdc, NAVIGATION_TEXT_COLOR); + SetBkColor(hdc, NAVIGATION_BACK_COLOR); + return (INT_PTR)pui->hbNavBack; + } + return NULL; +} + +INT_PTR WASetup::DialogProc(UINT uMsg, WPARAM wParam, LPARAM lParam) +{ + INT_PTR result = 0; + switch(uMsg) + { + case WM_INITDIALOG: return OnInitDialog((HWND)wParam, lParam); + case WM_DESTROY: OnDestroy(); break; + case WM_COMMAND: OnCommand(LOWORD(wParam), HIWORD(wParam), (HWND)lParam); break; + case WM_DRAWITEM: result = OnDrawItem((INT)wParam, (DRAWITEMSTRUCT*)lParam); break; + case WM_MEASUREITEM: result = OnMeasureItem((INT)wParam, (MEASUREITEMSTRUCT*)lParam); break; + case WM_CTLCOLORLISTBOX: return OnColorListBox((HDC)wParam, (HWND)lParam); + case WM_CHAR: + if (0x30 == wParam) + { + OutputDebugStringA("test\n"); + return 0; + } + } + + if (result) + { + SetWindowLongPtrW(hwnd, DWLP_MSGRESULT, (LONG_PTR)result); + return TRUE; + } + + return 0; +} + +static INT_PTR WINAPI DialogProc(HWND hwndDlg, UINT uMsg, WPARAM wParam, LPARAM lParam) +{ + WASetup *pInst = (WASetup*)GetPropW(hwndDlg, L"SETUPDLG"); + if (!pInst && g_pAttachInstance) + { + pInst = g_pAttachInstance; + pInst->hwnd = hwndDlg; + SetPropW(hwndDlg, L"SETUPDLG", pInst); + g_pAttachInstance = NULL; + } + + switch(uMsg) + { + case WM_DESTROY: + if (pInst) + { + pInst->DialogProc(uMsg, wParam, lParam); + RemovePropW(hwndDlg, L"SETUPDLG"); + pInst = NULL; + } + break; + } + + return (pInst) ? pInst->DialogProc(uMsg, wParam, lParam) : 0; +} + +static INT_PTR WINAPI AboutDialogProc(HWND hwndDlg, UINT uMsg, WPARAM wParam, LPARAM lParam) +{ + switch(uMsg) + { + case WM_INITDIALOG: + { + SendDlgItemMessageW(hwndDlg, IDC_PIC_ABOUT, STM_SETIMAGE, IMAGE_BITMAP, + (LPARAM)WALoadImage2(L"PNG", MAKEINTRESOURCEW(IDB_ABOUT), FALSE)); + + wchar_t buf[2048] = {0}, buf2[2048] = {0}; + GetWindowTextW(GetDlgItem(hwndDlg,IDC_VER_TEXT),buf,ARRAYSIZE(buf)); + StringCchPrintfW(buf2,2048,(buf[0] ? buf : L"v%s %s - %s"),AutoWideDup(app_version_string),AutoWideDup(APP_VERSION_PLATFORM),AutoWideDup(app_date)); + SetWindowTextW(GetDlgItem(hwndDlg,IDC_VER_TEXT),buf2); + } + break; + case WM_DESTROY: + { + DeleteObject((HBITMAP)SendDlgItemMessageW(hwndDlg, IDC_PIC_ABOUT, STM_GETIMAGE, IMAGE_BITMAP, 0L)); + } + break; + case WM_COMMAND: + switch(LOWORD(wParam)) + { + case IDOK: + case IDCANCEL: + EndDialog(hwndDlg, 0); + break; + } + } + + return 0; +} + +static INT_PTR WINAPI JobStatusDialog(HWND hwndDlg, UINT uMsg, WPARAM wParam, LPARAM lParam) +{ + switch(uMsg) + { + case WM_COMMAND: + switch(LOWORD(wParam)) + { + case IDC_BTN_SKIP: + if (BN_CLICKED == HIWORD(wParam)) + { + ifc_setupjob *pj = (ifc_setupjob*)GetPropW(hwndDlg, L"JOB"); + if (pj) + { + HWND hwndStatus = GetDlgItem(hwndDlg, IDC_LBL_STATUS); + EnableWindow((HWND)lParam, FALSE); + if (hwndStatus) SetWindowTextW(hwndStatus, getStringW(IDS_HTTP_ABORT, NULL, 0)); + pj->Cancel(hwndStatus); + } + } + break; + } + case WM_DESTROY: + RemovePropW(hwndDlg, L"JOB"); + } + + return 0; +} + +static INT_PTR WINAPI ErrorPageDialog(HWND hwndDlg, UINT uMsg, WPARAM wParam, LPARAM lParam) +{ + switch(uMsg) + { + case WM_WINDOWPOSCHANGED: + if (SWP_NOSIZE != ((SWP_NOSIZE | SWP_FRAMECHANGED) & ((WINDOWPOS*)lParam)->flags)) + { + HWND messageWindow; + messageWindow = GetDlgItem(hwndDlg, IDC_LBL_MESSAGE); + if (NULL != messageWindow) + { + RECT rect; + long top; + + GetWindowRect(messageWindow, &rect); + MapWindowPoints(HWND_DESKTOP, hwndDlg, (POINT*)&rect, 1); + + top = rect.top; + + GetClientRect(hwndDlg, &rect); + rect.top = top; + + SetWindowPos(messageWindow, NULL, rect.left, rect.top, rect.right - rect.left, rect.bottom - rect.top, + SWP_NOACTIVATE | SWP_NOZORDER); + } + } + break; + } + return 0; +} + +static LRESULT WINAPI PageWndProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam) +{ + SPTHEME *pTheme = (SPTHEME*)GetPropW(hwnd, L"SPTHEME"); + if (!pTheme || !pTheme->fnOldProc) return DefWindowProcW(hwnd, uMsg, wParam, lParam); + + switch(uMsg) + { + case WM_CTLCOLORDLG: + case WM_CTLCOLORSTATIC: + SetBkColor((HDC)wParam, PAGE_BACK_COLOR); + SetTextColor((HDC)wParam, GetSysColor(COLOR_WINDOWTEXT)); + return (LRESULT)pTheme->pui->hbPage; + case WM_DESTROY: + { + WNDPROC fnOldProc = pTheme->fnOldProc; + RemovePropA(hwnd, "SPTHEME"); + free(pTheme); + SetWindowLongPtrW(hwnd, GWLP_WNDPROC, (LONG_PTR)fnOldProc); + return CallWindowProcW(fnOldProc, hwnd, uMsg, wParam, lParam); + } + } + + return (pTheme->bUnicode) ? CallWindowProcW(pTheme->fnOldProc, hwnd, uMsg, wParam, lParam) : + CallWindowProcA(pTheme->fnOldProc, hwnd, uMsg, wParam, lParam); +} + +static DWORD GetHighestFontQuality(void) +{ + DWORD fdwQuality; + BOOL bSmoothing; + + if (SystemParametersInfo(SPI_GETFONTSMOOTHING, 0, &bSmoothing, 0) && bSmoothing) + { + OSVERSIONINFO vi = { sizeof(OSVERSIONINFO), }; + fdwQuality = (GetVersionEx(&vi) && (vi.dwMajorVersion > 5 || (vi.dwMajorVersion == 5 && vi.dwMinorVersion > 0))) ? + 5/*CLEARTYPE_QUALITY*/ : ANTIALIASED_QUALITY; + } + else fdwQuality = DEFAULT_QUALITY; + + return fdwQuality; +} + +static BOOL InitializeUI(UI *pui, HWND hwndCtrl) +{ + if (!pui) return FALSE; + if (!pui->ref) + { + HBITMAP hbmp; + BITMAP bi; + HDC hdc; + INT logPx; + TEXTMETRIC tm; + + hdc = GetWindowDC(hwndCtrl); + logPx = GetDeviceCaps(hdc, LOGPIXELSY); + + pui->hbPage = CreateSolidBrush(PAGE_BACK_COLOR); + + hbmp = (HBITMAP)LoadImageW(hMainInstance, MAKEINTRESOURCEW(IDB_NAVIGATION_STRIP), IMAGE_BITMAP, 0, 0, LR_DEFAULTCOLOR); + if (hbmp) + { + pui->hbNavBack = CreatePatternBrush(hbmp); + DeleteObject(hbmp); + } + else pui->hbNavBack = CreateSolidBrush(NAVIGATION_BACK_COLOR); + + pui->hfNavItem = CreateFontA(-MulDiv(NAVIGATION_FONT_SIZE, logPx, 72), 0, 0, 0, NAVIGATION_FONT_WEIGHT, + NAVIGATION_FONT_ITALIC, FALSE, FALSE, DEFAULT_CHARSET, OUT_DEFAULT_PRECIS, CLIP_DEFAULT_PRECIS, + GetHighestFontQuality(), FF_DONTCARE, NAVIGATION_FONT_NAME); + + pui->hfNavItemSel = CreateFontA(-MulDiv(NAVIGATION_SEL_FONT_SIZE, logPx, 72), 0, 0, 0, NAVIGATION_SEL_FONT_WEIGHT, + NAVIGATION_SEL_FONT_ITALIC, FALSE, FALSE, DEFAULT_CHARSET, OUT_DEFAULT_PRECIS, CLIP_DEFAULT_PRECIS, + GetHighestFontQuality(), FF_DONTCARE, NAVIGATION_SEL_FONT_NAME); + + pui->hfHeader = CreateFontA(-MulDiv(HEADER_FONT_SIZE, logPx, 72), 0, 0, 0, HEADER_FONT_WEIGHT, + HEADER_FONT_ITALIC, FALSE, FALSE, DEFAULT_CHARSET, OUT_DEFAULT_PRECIS, CLIP_DEFAULT_PRECIS, + GetHighestFontQuality(), FF_DONTCARE, HEADER_FONT_NAME); + + pui->hfHeaderPageNum = CreateFontA(-MulDiv(HEADER_PAGENUM_FONT_SIZE, logPx, 72), 0, 0, 0, HEADER_PAGENUM_FONT_WEIGHT, + HEADER_PAGENUM_FONT_ITALIC, FALSE, FALSE, DEFAULT_CHARSET, OUT_DEFAULT_PRECIS, CLIP_DEFAULT_PRECIS, + GetHighestFontQuality(), FF_DONTCARE, HEADER_PAGENUM_FONT_NAME); + + pui->nHdrHeight = 36; + + hbmp = (HBITMAP)LoadImageW(hMainInstance, MAKEINTRESOURCEW(IDB_HEADER_STRIP), IMAGE_BITMAP, 0, 0, LR_DEFAULTCOLOR); + if (hbmp) + { + if (GetObject(hbmp, sizeof(BITMAP), &bi)) pui->nHdrHeight = bi.bmHeight; + pui->hbHeader = CreatePatternBrush(hbmp); + DeleteObject(hbmp); + } + + pui->nNavItemHeight = 32; +// hbmp = (HBITMAP)LoadImageW(hMainInstance, MAKEINTRESOURCEW(IDB_NAVITEM_STRIP), IMAGE_BITMAP, 0, 0, LR_DEFAULTCOLOR); +// if (hbmp) +// { +// if (GetObject(hbmp, sizeof(BITMAP), &bi)) pui->nNavItemHeight = bi.bmHeight; +// pui->hbNavItemSel = CreatePatternBrush(hbmp); +// DeleteObject(hbmp); +// } + + HFONT hfOld = (HFONT)SelectObject(hdc, pui->hfHeader); + GetTextMetrics(hdc, &tm); + pui->nHdrTxtHeight = tm.tmAscent; + + SelectObject(hdc, pui->hfHeaderPageNum); + GetTextMetrics(hdc, &tm); + pui->nHdrPageTxtHeight = tm.tmAscent; + + SelectObject(hdc, pui->hfNavItem); + GetTextMetrics(hdc, &tm); + pui->nNavTxtHeight = tm.tmAscent; + + SelectObject(hdc, pui->hfNavItemSel); + GetTextMetrics(hdc, &tm); + pui->nNavTxtSelHeight = tm.tmAscent; + + SelectObject(hdc, hfOld); + ReleaseDC(hwndCtrl, hdc); + } + pui->ref++; + return TRUE; +} + +static BOOL ReleaseUI(UI *pui) +{ + if (!pui) return FALSE; + if (0 == pui->ref) + { + return TRUE; + } + if (1 == pui->ref) + { + if (pui->hbPage) DeleteObject(pui->hbPage); + if (pui->hbNavBack) DeleteObject(pui->hbNavBack); + if (pui->hbHeader) DeleteObject(pui->hbHeader); + if (pui->hbNavItemSel) DeleteObject(pui->hbNavItemSel); + if (pui->hfNavItem) DeleteObject(pui->hfNavItem); + if (pui->hfNavItemSel) DeleteObject(pui->hfNavItemSel); + if (pui->hfHeader) DeleteObject(pui->hfHeader); + if (pui->hfHeaderPageNum) DeleteObject(pui->hfHeaderPageNum); + ZeroMemory(pui, sizeof(UI)); + return TRUE; + } + pui->ref--; + return TRUE; +} + +static const wchar_t *GetUnknownStr(void) +{ + static wchar_t unknown[64] = {0,}; + return (unknown) ? unknown : getStringW(IDS_UNKNOWN, unknown, sizeof(unknown)/sizeof(wchar_t)); +} + +static LRESULT WINAPI FrameWndProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam) +{ + WNDPROC fnOldProc = (WNDPROC)GetPropW(hwnd, L"SKINFRAME"); + if (!fnOldProc) return DefWindowProcW(hwnd, uMsg, wParam, lParam); + switch(uMsg) + { + case WM_DESTROY: + RemovePropW(hwnd, L"SKINFRAME"); + SetWindowLongPtrW(hwnd, GWLP_WNDPROC, (LONG_PTR)fnOldProc); + break; + case WM_PAINT: + ValidateRect(hwnd, NULL); + return 0; + case WM_ERASEBKGND: return 1; + } + return CallWindowProcW(fnOldProc, hwnd, uMsg, wParam, lParam); +} + +static BOOL JobStatus_Advance(HWND hwndStatus) +{ + if (bUseMarquee > 0 ) return TRUE; + if (!hwndStatus) return FALSE; + HWND hwndCtrl = GetDlgItem(hwndStatus, IDC_PROGRESS); + if (!hwndCtrl) return FALSE; + SendMessageW(hwndCtrl, PBM_STEPIT, 0, 0L); + return TRUE; +} + +#ifdef CBCLASS +#undef CBCLASS +#endif + +#define CBCLASS WASetup +START_DISPATCH +CB(ADDREF, AddRef) +CB(RELEASE, Release) +CB(API_SETUP_INSERT_PAGE, InsertPage) +CB(API_SETUP_REMOVE_PAGE, RemovePage) +CB(API_SETUP_GET_PAGE_COUNT, GetPageCount) +CB(API_SETUP_GET_PAGE, GetPage) +CB(API_SETUP_GET_ACTIVE_INDEX, GetActiveIndex) +CB(API_SETUP_START, Start) +CB(API_SETUP_ADD_JOB, AddJob) +CB(API_SETUP_REMOVE_JOB, RemoveJob) +CB(API_SETUP_CREATE_STATUSWND, CreateStatusWnd) +CB(API_SETUP_SAVE, Save) +CB(API_SETUP_EXECJOBS, ExecJobs) +CB(API_SETUP_GETWINAMPWND, GetWinampWnd) +END_DISPATCH +#undef CBCLASS
\ No newline at end of file diff --git a/Src/Winamp/setup/setup.h b/Src/Winamp/setup/setup.h new file mode 100644 index 00000000..8344bad7 --- /dev/null +++ b/Src/Winamp/setup/setup.h @@ -0,0 +1,66 @@ +#ifndef NULLSOFT_WINAMP_SETUP_HEADER +#define NULLSOFT_WINAMP_SETUP_HEADER + +#include "./svc_setup.h" +#include <vector> + +typedef struct _UI UI; + +class WASetup : svc_setup +{ +protected: + WASetup(void); + ~WASetup(void); +public: + static svc_setup *CreateInstance(); +public: + int AddRef(void); + int Release(void); + HRESULT InsertPage(ifc_setuppage *pPage, int*pIndex); + HRESULT RemovePage(size_t index); + HRESULT GetPageCount(int*pCount); + HRESULT GetPage(size_t index, ifc_setuppage **pPage); + HRESULT AddJob(ifc_setupjob *pJob); + HRESULT RemoveJob(ifc_setupjob *pJob); + HRESULT GetActiveIndex(int*pIndex); + HRESULT Start(HWND hwndWinamp); + HRESULT CreateStatusWnd(HWND *phwndStatus); + HRESULT Save(HWND hwndStatus); + HRESULT ExecJobs(HWND hwndStatus); + HRESULT GetWinampWnd(HWND *phwndWinamp); + +protected: + INT_PTR DialogProc(UINT uMsg, WPARAM wParam, LPARAM lParam); + INT_PTR OnInitDialog(HWND hwndFocused, LPARAM lParam); + void OnDestroy(void); + void OnCommand(INT nCtrlID, INT nEvntID, HWND hwndCtrl); + void OnCancel(void); // use it if you want prompt user first + void OnCancel_Clicked(void); + void OnNext_Clicked(HWND hwndCtrl); + void OnBack_Clicked(HWND hwndCtrl); + void OnNavigation_SelChange(HWND hwndCtrl); + INT_PTR OnDrawItem(INT nCtrlID, DRAWITEMSTRUCT *pdis); + INT_PTR OnMeasureItem(INT nCtrlID, MEASUREITEMSTRUCT *pmis); + void OnDrawHeader(DRAWITEMSTRUCT *pdis); + void OnDrawNavigationItem(DRAWITEMSTRUCT *pdis); + INT_PTR OnColorListBox(HDC hdc, HWND hwndCtrl); + +private: + int ref; + HWND hwnd; + std::vector<ifc_setuppage*> pageList; + std::vector<ifc_setupjob*> jobList; + HWND hwndActive; + size_t nPageActive; + UI *pui; + RECT rcUI; + HWND hWinamp; + +protected: + friend static INT_PTR WINAPI DialogProc(HWND hwndDlg, UINT uMsg, WPARAM wParam, LPARAM lParam); + RECVS_DISPATCH; + +}; + + +#endif //WINAMP_SETUP_WIZARD_HEADER
\ No newline at end of file diff --git a/Src/Winamp/setup/setup.rc b/Src/Winamp/setup/setup.rc new file mode 100644 index 00000000..503c2811 --- /dev/null +++ b/Src/Winamp/setup/setup.rc @@ -0,0 +1,446 @@ +// Microsoft Visual C++ generated resource script. +// +#include "setup_resource.h" + +#define APSTUDIO_READONLY_SYMBOLS +///////////////////////////////////////////////////////////////////////////// +// +// Generated from the TEXTINCLUDE 2 resource. +// +#include "afxres.h" + +///////////////////////////////////////////////////////////////////////////// +#undef APSTUDIO_READONLY_SYMBOLS + +///////////////////////////////////////////////////////////////////////////// +// English (U.S.) resources + +#if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_ENU) +#ifdef _WIN32 +LANGUAGE LANG_ENGLISH, SUBLANG_ENGLISH_US +#pragma code_page(1252) +#endif //_WIN32 + +#ifdef APSTUDIO_INVOKED +///////////////////////////////////////////////////////////////////////////// +// +// TEXTINCLUDE +// + +1 TEXTINCLUDE +BEGIN + "setup_resource.h\0" +END + +2 TEXTINCLUDE +BEGIN + "#include ""afxres.h""\r\n" + "\0" +END + +3 TEXTINCLUDE +BEGIN + "\r\n" + "\0" +END + +#endif // APSTUDIO_INVOKED + + +///////////////////////////////////////////////////////////////////////////// +// +// Dialog +// + +IDD_SETUP DIALOGEX 0, 0, 369, 214 +STYLE DS_SETFONT | DS_NOIDLEMSG | DS_SETFOREGROUND | DS_FIXEDSYS | DS_NOFAILCREATE | DS_CENTER | WS_CLIPSIBLINGS | WS_CLIPCHILDREN | WS_CAPTION | WS_SYSMENU +EXSTYLE WS_EX_NOPARENTNOTIFY | WS_EX_CONTROLPARENT | WS_EX_APPWINDOW +CAPTION "Winamp Setup" +MENU IDR_SETUPMENU +FONT 8, "MS Shell Dlg", 400, 0, 0x1 +BEGIN + LISTBOX IDC_FRAME,7,6,355,180,NOT LBS_NOTIFY | LBS_NOREDRAW | LBS_OWNERDRAWFIXED | LBS_NOINTEGRALHEIGHT | LBS_NODATA | LBS_NOSEL | WS_DISABLED + LISTBOX IDC_LB_NAVIGATION,7,6,96,180,LBS_OWNERDRAWFIXED | LBS_NOINTEGRALHEIGHT | WS_DISABLED | NOT WS_BORDER | WS_TABSTOP + PUSHBUTTON "&Cancel",IDCANCEL,7,194,50,14 + PUSHBUTTON "&Back",IDC_BTN_BACK,197,194,50,14 + DEFPUSHBUTTON "&Next",IDC_BTN_NEXT,255,194,50,14 + PUSHBUTTON "Fini&sh",IDOK,312,194,50,14 + CONTROL "",IDC_HEADER,"Static",SS_OWNERDRAW,129,8,233,28 +END + +IDD_SETUP_PAGE_ASSOC DIALOGEX 0, 0, 241, 152 +STYLE DS_SETFONT | DS_FIXEDSYS | DS_CONTROL | WS_CHILD | WS_CLIPSIBLINGS | WS_CLIPCHILDREN | WS_SYSMENU +EXSTYLE WS_EX_CONTROLPARENT +FONT 8, "MS Shell Dlg", 400, 0, 0x1 +BEGIN + LTEXT "Select the file types you want to be associated with Winamp.",IDC_LBL_HEADER,6,6,229,18 + CONTROL "",IDC_TREE_TYPES,"SysTreeView32",TVS_HASBUTTONS | TVS_LINESATROOT | TVS_DISABLEDRAGDROP | TVS_SHOWSELALWAYS | WS_BORDER | WS_HSCROLL | WS_TABSTOP,6,24,229,87 + CONTROL "Show Winamp in the folder context menus in Windows Explorer",IDC_CHK_EXPLORER_MENU, + "Button",BS_AUTOCHECKBOX | WS_TABSTOP,6,115,229,10 + CONTROL "Enable Winamp Agent",IDC_CHK_AGENT,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,6,126,229,9 + LTEXT "Places a Winamp icon in the notification area.",IDC_LBL_AGENT_DESC,17,136,218,9 +END + +#if defined(APSTUDIO_INVOKED) || defined(NOT_USED) +#if defined(APSTUDIO_INVOKED) +IDD_SETUP_PAGE_CONNECT$(NOT_USED) DIALOGEX 0, 0, 225, 137 +#else +IDD_SETUP_PAGE_CONNECT DIALOGEX 0, 0, 225, 137 +#endif +STYLE DS_SETFONT | DS_FIXEDSYS | DS_CONTROL | WS_CHILD | WS_CLIPSIBLINGS | WS_SYSMENU +EXSTYLE WS_EX_CONTROLPARENT +FONT 8, "MS Shell Dlg", 400, 0, 0x1 +BEGIN + LTEXT "Select your internet connection type:",IDC_LBL_HEADER,6,6,213,18 + COMBOBOX IDC_CB_CONNECT,6,24,213,58,CBS_DROPDOWNLIST | WS_VSCROLL | WS_TABSTOP + GROUPBOX "HTTP Proxy (Optional)",IDC_GRP_PROXY,6,49,213,82 + EDITTEXT IDC_EDT_SERVER,16,82,193,14,ES_AUTOHSCROLL | WS_DISABLED + LTEXT "Server address (Server:Port):",IDC_LBL_SERVER,16,71,193,8 + CONTROL "Use proxy only for port 80 URLs",IDC_CHK_PORT80,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,16,101,193,10 +END +#endif + +IDD_SETUP_PAGE_SKIN DIALOGEX 0, 0, 257, 158 +STYLE DS_SETFONT | DS_FIXEDSYS | DS_CONTROL | WS_CHILD | WS_CLIPSIBLINGS | WS_SYSMENU +EXSTYLE WS_EX_NOPARENTNOTIFY | WS_EX_CONTROLPARENT +FONT 8, "MS Shell Dlg", 400, 0, 0x1 +BEGIN + LTEXT "Choose the look and feel for your Winamp.",IDC_LBL_HEADER,5,6,246,8 + LISTBOX IDC_LB_SKIN,5,24,101,126,LBS_SORT | LBS_OWNERDRAWFIXED | LBS_NOINTEGRALHEIGHT | LBS_WANTKEYBOARDINPUT | WS_VSCROLL | WS_TABSTOP + GROUPBOX "Preview",IDC_GRP_PREVIEW,114,22,137,128 + CONTROL "",IDC_PIC_PREVIEW,"Static",SS_BITMAP,122,35,124,43 + LTEXT "Name:",IDC_LBL_NAME,122,87,28,8 + EDITTEXT IDC_EDT_NAME,150,87,96,12,ES_AUTOHSCROLL | ES_READONLY | NOT WS_BORDER | NOT WS_TABSTOP,WS_EX_TRANSPARENT + LTEXT "Type:",IDC_LBL_TYPE,122,98,20,8 + EDITTEXT IDC_EDT_TYPE,150,98,96,12,ES_AUTOHSCROLL | ES_READONLY | NOT WS_BORDER | NOT WS_TABSTOP + LTEXT "Author:",IDC_LBL_AUTHOR,122,109,26,8 + EDITTEXT IDC_EDT_AUTHOR,150,109,96,12,ES_AUTOHSCROLL | ES_READONLY | NOT WS_BORDER | NOT WS_TABSTOP + LTEXT "Version:",IDC_LBL_VERSION,122,120,27,8 + EDITTEXT IDC_EDT_VERSION,150,120,96,12,ES_AUTOHSCROLL | ES_READONLY | NOT WS_BORDER | NOT WS_TABSTOP + PUSHBUTTON "More Info...",IDC_BTN_MOREINFO,194,133,52,13,NOT WS_VISIBLE +END + +IDD_ABOUT DIALOGEX 0, 0, 206, 54 +STYLE DS_SETFONT | DS_MODALFRAME | DS_FIXEDSYS | DS_CENTER | WS_POPUP | WS_CAPTION | WS_SYSMENU +CAPTION "Winamp Setup - About" +FONT 8, "MS Shell Dlg", 400, 0, 0x0 +BEGIN + CONTROL 108,IDC_PIC_ABOUT,"Static",SS_BITMAP | SS_REALSIZEIMAGE,4,4,35,32,WS_EX_TRANSPARENT + LTEXT "Winamp Setup Wizard",IDC_STATIC,50,4,152,8 + LTEXT "Copyright © 1997-2023 Winamp SA",IDC_STATIC,50,15,152,9,NOT WS_GROUP + LTEXT "v%s %s - %s",IDC_VER_TEXT,4,42,144,8 + DEFPUSHBUTTON "Close",IDOK,152,36,50,14 +END + +#if defined(APSTUDIO_INVOKED) || defined(NOT_USED) +#if defined(APSTUDIO_INVOKED) +IDD_SETUP_PAGE_LANG$(NOT_USED) DIALOGEX 0, 0, 160, 152 +#else +IDD_SETUP_PAGE_LANG DIALOGEX 0, 0, 160, 152 +#endif +STYLE DS_SETFONT | DS_FIXEDSYS | DS_CONTROL | WS_CHILD | WS_CLIPSIBLINGS | WS_CLIPCHILDREN | WS_SYSMENU +EXSTYLE WS_EX_CONTROLPARENT +FONT 8, "MS Shell Dlg", 400, 0, 0x1 +BEGIN + LTEXT "Choose one of the available languages:",IDC_LBL_HEADER,6,6,148,18 + LISTBOX IDC_LB_LANG,6,24,148,122,LBS_SORT | LBS_NOINTEGRALHEIGHT | WS_VSCROLL | WS_HSCROLL | WS_TABSTOP +END +#endif + +#if defined(APSTUDIO_INVOKED) || defined(DISABLED) +#if defined(APSTUDIO_INVOKED) +IDD_SETUP_PAGE_FEEDBACK$(DISABLED) DIALOGEX 0, 0, 256, 158 +#else +IDD_SETUP_PAGE_FEEDBACK DIALOGEX 0, 0, 256, 158 +#endif +STYLE DS_SETFONT | DS_FIXEDSYS | DS_CONTROL | WS_CHILD | WS_CLIPSIBLINGS | WS_SYSMENU +EXSTYLE WS_EX_CONTROLPARENT +FONT 8, "MS Shell Dlg", 400, 0, 0x1 +BEGIN + LTEXT "Let us know more about you so we can continue to improve Winamp.",IDC_LBL_HEADER,5,6,245,18 + LTEXT "Email:",IDC_LBL_EMAIL,12,36,102,12 + EDITTEXT IDC_EDT_EMAIL,114,36,130,12,ES_AUTOHSCROLL + LTEXT "Zip code (US) or Country:",IDC_LBL_COUNTRY,12,51,98,12 + EDITTEXT IDC_EDT_COUNTRY,114,51,130,12,ES_AUTOHSCROLL + LTEXT "Gender:",IDC_LBL_GENDER,12,67,98,12 + COMBOBOX IDC_CB_GENDER,114,66,130,46,CBS_DROPDOWNLIST | CBS_SORT | WS_VSCROLL | WS_TABSTOP + CONTROL "Yes, send me information about Winamp",IDC_CHK_ANNOUNCEMENTS, + "Button",BS_AUTOCHECKBOX | WS_TABSTOP,12,129,232,10 + CONTROL "Yes, allow anonymous usage statistics (recommended)",IDC_CHK_STATISTICS, + "Button",BS_AUTOCHECKBOX | WS_TABSTOP,12,140,232,10 +END +#endif + +IDD_SETUPSTATUS DIALOGEX 0, 0, 249, 71 +STYLE DS_SETFONT | DS_MODALFRAME | DS_SETFOREGROUND | DS_FIXEDSYS | DS_CENTER | WS_POPUP | WS_CAPTION +CAPTION "Winamp Setup" +FONT 8, "MS Shell Dlg", 400, 0, 0x1 +BEGIN + CONTROL "",IDC_LBL_STATUS,"Static",SS_LEFTNOWORDWRAP | SS_ENDELLIPSIS | WS_GROUP,11,12,226,9 + CONTROL "",IDC_PROGRESS,"msctls_progress32",WS_BORDER,11,25,226,12 + PUSHBUTTON "Skip",IDC_BTN_SKIP,181,47,56,14,WS_DISABLED +END + +IDD_SETUP_PAGE_ERROR DIALOGEX 0, 0, 316, 183 +STYLE DS_SETFONT | DS_FIXEDSYS | DS_CONTROL | WS_CHILD | WS_CLIPSIBLINGS | WS_CLIPCHILDREN +EXSTYLE WS_EX_CONTROLPARENT +FONT 8, "MS Shell Dlg", 400, 0, 0x1 +BEGIN + CTEXT "Unable to load setup page",IDC_LBL_MESSAGE,5,37,304,8 +END + +IDD_SETUP_PAGE_ASSOC_WIN8 DIALOGEX 0, 0, 257, 152 +STYLE DS_SETFONT | DS_FIXEDSYS | DS_CONTROL | WS_CHILD | WS_CLIPSIBLINGS | WS_CLIPCHILDREN | WS_SYSMENU +EXSTYLE WS_EX_CONTROLPARENT +FONT 8, "MS Shell Dlg", 400, 0, 0x1 +BEGIN + LTEXT "Select the file types you want to be associated with Winamp.",IDC_LBL_HEADER,5,6,248,18 + LTEXT "To associate files with Winamp on this version of Windows, you need to go to 'Set Default Programs' in the Control Panel once Winamp's setup is complete.\n\nNote: This can also be accessed via Winamp's 'File Types' preferences page.",IDC_STATIC,5,24,248,32 + CONTROL "Launch Winamp for Audio CDs",IDC_CHK_CD,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,11,66,242,9 + CONTROL "Show Winamp in the folder context menus in Windows Explorer",IDC_CHK_EXPLORER_MENU, + "Button",BS_AUTOCHECKBOX | WS_TABSTOP,11,78,242,10 + CONTROL "Enable Winamp Agent",IDC_CHK_AGENT,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,11,90,242,9 + LTEXT "Places a Winamp icon in the notification area.",IDC_LBL_AGENT_DESC,22,101,231,9 + CONTROL "",IDC_TREE_TYPES,"SysTreeView32",TVS_HASBUTTONS | TVS_LINESATROOT | TVS_DISABLEDRAGDROP | TVS_SHOWSELALWAYS | NOT WS_VISIBLE | WS_BORDER | WS_HSCROLL | WS_TABSTOP,5,144,248,0 +END + + +///////////////////////////////////////////////////////////////////////////// +// +// DESIGNINFO +// + +#ifdef APSTUDIO_INVOKED +GUIDELINES DESIGNINFO +BEGIN + IDD_SETUP, DIALOG + BEGIN + LEFTMARGIN, 7 + RIGHTMARGIN, 362 + TOPMARGIN, 6 + BOTTOMMARGIN, 208 + HORZGUIDE, 186 + END + + IDD_SETUP_PAGE_ASSOC, DIALOG + BEGIN + LEFTMARGIN, 6 + RIGHTMARGIN, 235 + VERTGUIDE, 17 + TOPMARGIN, 6 + BOTTOMMARGIN, 144 + HORZGUIDE, 24 + END + + "IDD_SETUP_PAGE_CONNECT$(NOT_USED)", DIALOG + BEGIN + LEFTMARGIN, 6 + RIGHTMARGIN, 219 + VERTGUIDE, 16 + VERTGUIDE, 209 + TOPMARGIN, 6 + BOTTOMMARGIN, 131 + HORZGUIDE, 24 + HORZGUIDE, 49 + HORZGUIDE, 111 + END + + IDD_SETUP_PAGE_SKIN, DIALOG + BEGIN + LEFTMARGIN, 5 + RIGHTMARGIN, 251 + VERTGUIDE, 106 + VERTGUIDE, 114 + VERTGUIDE, 122 + VERTGUIDE, 150 + VERTGUIDE, 246 + TOPMARGIN, 6 + BOTTOMMARGIN, 150 + HORZGUIDE, 24 + HORZGUIDE, 35 + END + + IDD_ABOUT, DIALOG + BEGIN + LEFTMARGIN, 4 + RIGHTMARGIN, 202 + VERTGUIDE, 50 + TOPMARGIN, 4 + BOTTOMMARGIN, 50 + END + + "IDD_SETUP_PAGE_LANG$(NOT_USED)", DIALOG + BEGIN + LEFTMARGIN, 6 + RIGHTMARGIN, 154 + TOPMARGIN, 6 + BOTTOMMARGIN, 146 + HORZGUIDE, 24 + END + + IDD_SETUPSTATUS, DIALOG + BEGIN + LEFTMARGIN, 11 + RIGHTMARGIN, 237 + TOPMARGIN, 7 + BOTTOMMARGIN, 61 + END + + IDD_SETUP_PAGE_ERROR, DIALOG + BEGIN + LEFTMARGIN, 5 + RIGHTMARGIN, 309 + TOPMARGIN, 7 + BOTTOMMARGIN, 176 + END + + IDD_SETUP_PAGE_ASSOC_WIN8, DIALOG + BEGIN + LEFTMARGIN, 5 + RIGHTMARGIN, 253 + VERTGUIDE, 11 + TOPMARGIN, 6 + BOTTOMMARGIN, 144 + HORZGUIDE, 24 + END +END +#endif // APSTUDIO_INVOKED + + +///////////////////////////////////////////////////////////////////////////// +// +// Menu +// + +IDR_SETUPMENU MENU +BEGIN + POPUP "&File" + BEGIN + MENUITEM "&Save Changes\tCtrl+S", 40013 + MENUITEM SEPARATOR + MENUITEM "E&xit\tAlt+F4", 40016 + END + POPUP "Na&vigation" + BEGIN + MENUITEM "&Back\tAlt+B", 40011 + MENUITEM "&Next\tAlt+N", 40012 + END + POPUP "&Tools", GRAYED + BEGIN + MENUITEM "Migrate/Import...", 40009 + MENUITEM "Register Winamp...", 40010 + END + POPUP "&Help" + BEGIN + MENUITEM "&About\tF1", 40008 + END +END + + +///////////////////////////////////////////////////////////////////////////// +// +// Bitmap +// + +IDB_HEADER_STRIP BITMAP "headerstrip.bmp" +IDB_NAVITEM_STRIP BITMAP "navitemstrip.bmp" +IDB_CHECKBOX BITMAP "checkbox.bmp" +IDB_NAVIGATION_STRIP BITMAP "navstrip.bmp" + +///////////////////////////////////////////////////////////////////////////// +// +// PNG +// + +IDB_PREVIEW_NO PNG "preview_no.png" +IDB_PREVIEW_CLASSIC PNG "preview_classic.png" +IDB_ABOUT PNG "smokingllama.png" + +///////////////////////////////////////////////////////////////////////////// +// +// Accelerator +// + +IDR_ACCEL_SETUP ACCELERATORS +BEGIN + VK_F1, IDM_HELP_ABOUT, VIRTKEY, NOINVERT + "S", IDM_FILE_SAVECHANGES, VIRTKEY, CONTROL, NOINVERT +END + + +///////////////////////////////////////////////////////////////////////////// +// +// String Table +// + +STRINGTABLE +BEGIN + IDS_SKIN_CURRENT "Current" + IDS_SKIN_PROMO1 "Bento Skin" + IDS_SKIN_PROMO2 "Bento Skin (Large)" + IDS_PAGE_SKIN "Skin" + IDS_PAGE_LANGUAGE "Language" + IDS_PAGE_CONNECTIVITY "Connectivity" + IDS_SAVE_CHANGES_BEFORE_EXIT "Do you want to save changes before exit?" + IDS_UNKNOWN "Unknown" + IDS_CHANGES_NOT_SAVED "Some settings were not saved." + IDS_MODERN "Modern" + IDS_CLASSIC "Classic" + IDS_QUIT_OK "Are you sure you want to quit Winamp Setup?" + IDS_PAGE_ASSOCIATIONS "Associations" + IDS_FILETYPE_VIDEO "Video Files" + IDS_FILETYPE_AUDIO "Audio Files" + IDS_FILETYPE_UNKNOWN "Other Files" +END + +STRINGTABLE +BEGIN + IDS_FILETYPE_PLAYLIST "Playlist Files" + IDS_PAGE_FEEDBACK "Feedback" + IDS_GENDER_MALE "Male" + IDS_GENDER_FEMALE "Female" + IDS_GENDER_UNKNOWN "Select gender" + IDS_REGISTER_CDPLAYER "Launch Winamp for Audio CDs" + IDS_STATUS_SAVING "Saving settings" + IDS_STATUS_JOBS "Executing scripts" + IDS_STATUS_RUNWA "Starting Winamp" + IDS_PAGE_SKIN_LONG "Choose Skin" + IDS_REGISTER_AGENT "Enable Winamp Agent" + IDS_PAGE_ASSOCIATIONS_LONG "File Associations" + IDS_PAGE_FEEDBACK_LONG "User Feedback" + IDS_PAGE_INCORRECT_EMAIL_ADDRESS "Incorrect email address." + IDS_FILETYPE_AUXILIARY "Winamp Specific Files" + IDS_WINAMP_SKIN_MODERN "Winamp Skin (Modern)" +END + +STRINGTABLE +BEGIN + IDS_WINAMP_SKIN_CLASSIC "Winamp Skin (Classic)" + IDS_WINAMP_LANG_PACK "Winamp Language Pack" + IDS_DOWNLOADSTATUS_INITIALIZING "Initializing..." + IDS_DOWNLOADSTATUS_CONNECTING "Connecting..." + IDS_DOWNLOADSTATUS_CONNECTED "Connected" + IDS_DOWNLOADSTATUS_RECEIVING "Downloading..." + IDS_DOWNLOADSTATUS_RECEIVINGPERCENT "Downloading... (%d%% completed)" + IDS_DOWNLOADSTATUS_SUCCESS "Success." + IDS_DOWNLOADSTATUS_FAILED "Failed." + IDS_DOWNLOADSTATUS_ABORTING "Aborting..." + IDS_DOWNLOADSTATUS_ABORTED "Aborted." + IDS_SETUP_WND_TITLE "Winamp v%s Setup" +END + +#endif // English (U.S.) resources +///////////////////////////////////////////////////////////////////////////// + + + +#ifndef APSTUDIO_INVOKED +///////////////////////////////////////////////////////////////////////////// +// +// Generated from the TEXTINCLUDE 3 resource. +// + + +///////////////////////////////////////////////////////////////////////////// +#endif // not APSTUDIO_INVOKED + diff --git a/Src/Winamp/setup/setup_api.h b/Src/Winamp/setup/setup_api.h new file mode 100644 index 00000000..8ed8c1b6 --- /dev/null +++ b/Src/Winamp/setup/setup_api.h @@ -0,0 +1,24 @@ +#ifndef WINAMP_SETUP_API_HEADER +#define WINAMP_SETUP_API_HEADER + +#include <windows.h> + + +class __declspec(novtable) WASetupAPI +{ +protected: + WASetupAPI(void){}; + virtual ~WASetupAPI(void) = 0; +public: + virtual INT GetInterfaceVersion(void) = 0; + virtual LPCWSTR GetName(BOOL bShort) = 0; + virtual HICON GetIcon(BOOL bSmall) = 0; + virtual BOOL Initialize(void) = 0; + virtual BOOL Finish(BOOL bCancelled) = 0; + virtual HWND CreateView(HWND hwndParent) = 0; + virtual HWND GetHWND(void) = 0; +}; + + + +#endif //WINAMP_SETUP_API_HEADER
\ No newline at end of file diff --git a/Src/Winamp/setup/setup_resource.h b/Src/Winamp/setup/setup_resource.h new file mode 100644 index 00000000..6e44de7a --- /dev/null +++ b/Src/Winamp/setup/setup_resource.h @@ -0,0 +1,139 @@ +//{{NO_DEPENDENCIES}} +// Microsoft Visual C++ generated include file. +// Used by setup.rc +// +#define IDD_SETUP 101 +#define IDB_CHECKBOX 101 +#define IDD_SETUP_PAGE_LANG1 102 +#define IDD_SETUP_PAGE_ASSOC 102 +#define IDD_SETUP_PAGE_CONNECT 103 +#define IDD_SETUP_PAGE_SKIN 104 +#define IDD_ABOUT 105 +#define IDB_HEADERSTRIP 106 +#define IDB_HEADER_STRIP 106 +#define IDD_SETUP_PAGE_LANG 106 +#define IDD_SETUP_PAGE_FEEDBACK 107 +#define IDB_ABOUT 108 +#define IDD_SETUP_PAGE_ERROR 108 +#define IDD_SETUPSTATUS 109 +#define IDB_NAVIGATION_STRIP 110 +#define IDB_NAVITEM_STRIP 111 +#define IDB_PREVIEW_CLASSIC 112 +#define IDR_ACCEL_SETUP 112 +#define IDB_PREVIEW_NO 113 +#define IDD_SETUP_PAGE_ASSOC_WIN8 114 +#define IDR_SETUPMENU 191 +#define IDC_CB_CONNECT 1000 +#define IDC_LBL_MESSAGE 1000 +#define IDC_BTN_NEXT 1001 +#define IDC_EDT_SERVER 1001 +#define IDC_VER_TEXT 1001 +#define IDC_BTN_BACK 1002 +#define IDC_CHK_PORT80 1002 +#define IDC_LB_NAVIGATION 1003 +#define IDC_EDT_EMAIL 1003 +#define IDC_FRAME 1004 +#define IDC_GRP_PROXY 1004 +#define IDC_CHK_ANNOUNCEMENTS 1004 +#define IDC_EDT_TEST 1005 +#define IDC_LBL_SERVER 1005 +#define IDC_BTN_TEST_ME 1006 +#define IDC_TREE_TYPES 1006 +#define IDC_LBL_COUNTRY 1006 +#define IDC_HEADER 1007 +#define IDC_LBL_HEADER 1007 +#define IDC_LBL_GENDER 1008 +#define IDC_LBL_EMAIL 1011 +#define IDC_EDT_COUNTRY 1012 +#define IDC_CHK_STATISTICS 1013 +#define IDC_CHK_FEEDBACK 1014 +#define IDC_GRP_FEEDBACK 1015 +#define IDC_LB_LANG 1016 +#define IDC_CB_GENDER 1016 +#define IDC_LB_SKIN 1017 +#define IDC_LBL_STATUS 1017 +#define IDC_EDT_INFO 1018 +#define IDC_PROGRESS 1018 +#define IDC_PIC_PREVIEW 1020 +#define IDC_LBL_CAPTION 1021 +#define IDC_CHK_AGENT 1021 +#define IDC_EDT_NAME 1022 +#define IDC_LBL_AGENT_DESC 1022 +#define IDC_EDT_TYPE 1023 +#define IDC_CHK_EXPLORER_MENU 1023 +#define IDC_LBL_NAME 1024 +#define IDC_BTN_SKIP 1024 +#define IDC_LBL_TYPE 1025 +#define IDC_GRP_PREVIEW 1026 +#define IDC_LBL_VERSION 1027 +#define IDC_EDT_VERSION 1028 +#define IDC_LBL_TYPE3 1029 +#define IDC_LBL_AUTHOR 1029 +#define IDC_EDT_AUTHOR 1030 +#define IDC_PIC_ABOUT 1032 +#define IDC_BTN_MOREINFO 1033 +#define IDC_CHK_CD 1034 +#define IDS_SKIN_CURRENT 2000 +#define IDS_SKIN_PROMO1 2001 +#define IDS_SKIN_PROMO2 2002 +#define IDS_PAGE_SKIN 2003 +#define IDS_PAGE_LANGUAGE 2004 +#define IDS_PAGE_CONNECTIVITY 2005 +#define IDS_SAVE_CHANGES_BEFORE_EXIT 2006 +#define IDS_UNKNOWN 2007 +#define IDS_CHANGES_NOT_SAVED 2008 +#define IDS_MODERN 2009 +#define IDS_CLASSIC 2010 +#define IDS_QUIT_OK 2011 +#define IDS_PAGE_ASSOCIATIONS 2012 +#define IDS_FILETYPE_VIDEO 2013 +#define IDS_FILETYPE_AUDIO 2014 +#define IDS_FILETYPE_UNKNOWN 2015 +#define IDS_FILETYPE_PLAYLIST 2016 +#define IDS_PAGE_FEEDBACK 2017 +#define IDS_GENDER_MALE 2018 +#define IDS_GENDER_FEMALE 2019 +#define IDS_GENDER_UNKNOWN 2020 +#define IDS_REGISTER_CDPLAYER 2021 +#define IDS_STATUS_SAVING 2022 +#define IDS_STATUS_JOBS 2023 +#define IDS_STATUS_RUNWA 2024 +#define IDS_PAGE_SKIN_LONG 2025 +#define IDS_REGISTER_AGENT 2026 +#define IDS_PAGE_ASSOCIATIONS_LONG 2027 +#define IDS_PAGE_FEEDBACK_LONG 2028 +#define IDS_INCORRECT_EMAIL_ADDRESS 2029 +#define IDS_PAGE_INCORRECT_EMAIL_ADDRESS 2029 +#define IDS_FILETYPE_AUXILIARY 2030 +#define IDS_WINAMP_SKIN_MODERN 2031 +#define IDS_WINAMP_SKIN_CLASSIC 2032 +#define IDS_WINAMP_LANG_PACK 2033 +#define IDS_DOWNLOADSTATUS_INITIALIZING 2034 +#define IDS_DOWNLOADSTATUS_CONNECTING 2035 +#define IDS_DOWNLOADSTATUS_CONNECTED 2036 +#define IDS_DOWNLOADSTATUS_RECEIVING 2037 +#define IDS_DOWNLOADSTATUS_RECEIVINGPERCENT 2038 +#define IDS_DOWNLOADSTATUS_SUCCESS 2039 +#define IDS_DOWNLOADSTATUS_FAILED 2040 +#define IDS_DOWNLOADSTATUS_ABORTING 2041 +#define IDS_DOWNLOADSTATUS_ABORTED 2042 +#define IDS_SETUP_WND_TITLE 2043 +#define ID_CMD_SAVE 40003 +#define IDM_HELP_ABOUT 40008 +#define IDM_TOOLS_MIGRATE 40009 +#define IDM_TOOLS_REGISTERWINAMP 40010 +#define IDM_NAVIGATE_BACK 40011 +#define IDM_NAVIGATE_NEXT 40012 +#define IDM_FILE_SAVECHANGES 40013 +#define IDM_FILE_EXIT 40016 + +// Next default values for new objects +// +#ifdef APSTUDIO_INVOKED +#ifndef APSTUDIO_READONLY_SYMBOLS +#define _APS_NEXT_RESOURCE_VALUE 121 +#define _APS_NEXT_COMMAND_VALUE 40001 +#define _APS_NEXT_CONTROL_VALUE 1001 +#define _APS_NEXT_SYMED_VALUE 101 +#endif +#endif diff --git a/Src/Winamp/setup/setupcommon.h b/Src/Winamp/setup/setupcommon.h new file mode 100644 index 00000000..3073bd4e --- /dev/null +++ b/Src/Winamp/setup/setupcommon.h @@ -0,0 +1,31 @@ +#ifndef NULLOSFT_WINAMP_SETUPCOMMON_HEADER +#define NULLOSFT_WINAMP_SETUPCOMMON_HEADER + +#if defined(_MSC_VER) && (_MSC_VER >= 1020) +#pragma once +#endif + +#include <wtypes.h> + + +#ifndef LONGX86 +#ifdef _WIN64 + #define LONGX86 LONG_PTR +#else /*_WIN64*/ + #define LONGX86 LONG +#endif /*_WIN64*/ +#endif // LONGX86 + +#ifdef __cplusplus + #define SENDMSG(__hwnd, __msgId, __wParam, __lParam) ::SendMessageW((__hwnd), (__msgId), (__wParam), (__lParam)) +#else + #define SENDMSG(__hwnd, __msgId, __wParam, __lParam) SendMessageW((__hwnd), (__msgId), (__wParam), (__lParam)) +#endif // __cplusplus + +#define SENDWAIPC(__ipcMsgId, __param) SENDMSG(hMainWindow, WM_WA_IPC, (WPARAM)(__param), (LPARAM)(__ipcMsgId)) + +#define MSGRESULT(__hwnd, __result) { SetWindowLongPtrW((__hwnd), DWLP_MSGRESULT, ((LONGX86)(LONG_PTR)(__result))); return TRUE; } +#define CSTR_INVARIANT MAKELCID(MAKELANGID(LANG_ENGLISH, SUBLANG_ENGLISH_US), SORT_DEFAULT) + + +#endif // NULLOSFT_WINAMP_SETUPCOMMON_HEADER
\ No newline at end of file diff --git a/Src/Winamp/setup/setupfactory.cpp b/Src/Winamp/setup/setupfactory.cpp new file mode 100644 index 00000000..fdb417ef --- /dev/null +++ b/Src/Winamp/setup/setupfactory.cpp @@ -0,0 +1,249 @@ +#include "./setupfactory.h" +#include <api/service/waservicefactorybase.h> +#include <api/service/services.h> +#include "api.h" +#include "gen.h" +#include "main.h" + +#define GUID_DEFINE +#include "./setup.h" +#undef GUID_DEFINE + +//#include "./spage_lang.h" +//#include "./spage_connect.h" +#include "./spage_skin.h" +#include "./spage_assoc.h" +//#include "./spage_feedback.h" + +#include "./sjob_register.h" +#include <shlwapi.h> + +class setup_factory : public waServiceFactory +{ +public: + setup_factory(); + virtual ~setup_factory(); +public: + int AddRef(); + int Release(); + FOURCC GetServiceType(); + const char *GetServiceName(); + GUID GetGUID(); + void *GetInterface(int global_lock); + int SupportNonLockingInterface(); + int ReleaseInterface(void *ifc); + const char *GetTestString(); + int ServiceNotify(int msg, int param1, int param2); + +private: + int ref; + svc_setup *psvcSetup; +protected: + RECVS_DISPATCH; +}; + + +#ifdef __cplusplus +extern "C" { +#endif // __cplusplus + +BOOL Setup_RegisterService(void) +{ + setup_factory *psf = new setup_factory(); + WASABI_API_SVC->service_register(psf); + return (0 != psf->Release()); +} + +int Setup_RegisterDefault(void) +{ + waServiceFactory *psf = WASABI_API_SVC->service_getServiceByGuid(UID_SVC_SETUP); + if (!psf) return 0; + + svc_setup *pSvc = (svc_setup*)psf->getInterface(); + if (pSvc) + { + int index = 0; + ifc_setuppage *pp; + ifc_setupjob *pj; + // pp = new setup_page_lang(); + // if (pp) { pSvc->InsertPage(pp, &index); pp->Release(); } + + pp = new setup_page_skin(); + if (pp) { pSvc->InsertPage(pp, &++index); pp->Release(); } + +// pp = new setup_page_connect(); +// if (pp) { pSvc->InsertPage(pp, &++index); pp->Release(); } + + pp = new setup_page_assoc(); + if (pp) { pSvc->InsertPage(pp, &++index); pp->Release(); } + + // disabled for 5.66 +// pp = new setup_page_feedback(); +// if (pp) { pSvc->InsertPage(pp, &++index); pp->Release(); } + + pj = new setup_job_register(); + if (pj) { pSvc->AddJob(pj); pj->Release(); } + + pSvc->Release(); + return 1; + } + + return 0; +} + +int Setup_RegisterPlugins(void) +{ + wchar_t dirstr[MAX_PATH] = {0}; + WIN32_FIND_DATAW d = {0}; + PathCombineW(dirstr, PLUGINDIR, L"GEN_*.DLL"); + + HANDLE h = FindFirstFileW(dirstr,&d); + if (h != INVALID_HANDLE_VALUE) + { + do + { + wchar_t temp[MAX_PATH] = {0}; + PathCombineW(temp, PLUGINDIR, d.cFileName); + HINSTANCE hLib = LoadLibraryW(temp); + if (hLib) + { + winampGeneralPurposePluginGetter pr = (winampGeneralPurposePluginGetter) GetProcAddress(hLib,"winampGetGeneralPurposePlugin"); + if (pr) + { + Plugin_RegisterSetup fn = (Plugin_RegisterSetup)GetProcAddress(hLib, "RegisterSetup"); + if (NULL == fn || FALSE == fn(hLib, WASABI_API_SVC)) + { + winampGeneralPurposePlugin *plugin = pr(); + if (plugin && (plugin->version == GPPHDR_VER || plugin->version == GPPHDR_VER_U)) + { + char desc[128] = {0}; + lstrcpynA(desc, plugin->description, sizeof(desc)); + if (desc[0] && !memcmp(desc, "nullsoft(", 9)) + { + // we'll let this leak for all 3rd party plug-ins as some crash during + // setup when we try to unload the plug-in e.g gen_Wake_up_call.dll + FreeModule(hLib); + } + } + } + } + } + } while (FindNextFileW(h,&d)); + FindClose(h); + } + return 1; +} + +#ifdef __cplusplus +} +#endif // __cplusplus + + + +setup_factory::setup_factory() : ref(1), psvcSetup(NULL) +{ +} + +setup_factory::~setup_factory() +{ + if (NULL != psvcSetup) + { + psvcSetup->Release(); + } +} + +int setup_factory::AddRef(void) +{ + return ++ref; +} + +int setup_factory::Release(void) +{ + if (1 == ref) + { + delete(this); + return 0; + } + return --ref; +} + +FOURCC setup_factory::GetServiceType() +{ + return WaSvc::UNIQUE; +} + +const char *setup_factory::GetServiceName() +{ + return "Setup Service"; +} + +GUID setup_factory::GetGUID() +{ + return UID_SVC_SETUP; +} + +int setup_factory::SupportNonLockingInterface() +{ + return 1; +} + +const char *setup_factory::GetTestString() +{ + return NULL; +} + +int setup_factory::ServiceNotify(int msg, int param1, int param2) +{ + switch(msg) + { + case SvcNotify::ONREGISTERED: + AddRef(); + break; + case SvcNotify::ONDEREGISTERED: + Release(); + break; + } + return 1; +} + +void *setup_factory::GetInterface(int global_lock) +{ + if (NULL == psvcSetup) + { + psvcSetup = WASetup::CreateInstance(); + if (NULL == psvcSetup) + return NULL; + } + + psvcSetup->AddRef(); + return psvcSetup; +} + +int setup_factory::ReleaseInterface(void *ifc) +{ + if (ifc == psvcSetup && NULL != psvcSetup) + { + if (0 == psvcSetup->Release()) + psvcSetup = NULL; + } + return 1; +} + +#ifdef CBCLASS +#undef CBCLASS +#endif + +#define CBCLASS setup_factory +START_DISPATCH +CB(ADDREF, AddRef) +CB(RELEASE, Release) +CB(WASERVICEFACTORY_GETSERVICETYPE, GetServiceType) +CB(WASERVICEFACTORY_GETSERVICENAME, GetServiceName) +CB(WASERVICEFACTORY_GETGUID, GetGUID) +CB(WASERVICEFACTORY_GETINTERFACE, GetInterface) +CB(WASERVICEFACTORY_SUPPORTNONLOCKINGGETINTERFACE, SupportNonLockingInterface) +CB(WASERVICEFACTORY_RELEASEINTERFACE, ReleaseInterface) +CB(WASERVICEFACTORY_GETTESTSTRING, GetTestString) +CB(WASERVICEFACTORY_SERVICENOTIFY, ServiceNotify) +END_DISPATCH + diff --git a/Src/Winamp/setup/setupfactory.h b/Src/Winamp/setup/setupfactory.h new file mode 100644 index 00000000..c3ccba1c --- /dev/null +++ b/Src/Winamp/setup/setupfactory.h @@ -0,0 +1,19 @@ +#ifndef NULLSOFT_WINAMP_SETUP_FACTORY_HEADER +#define NULLSOFT_WINAMP_SETUP_FACTORY_HEADER + +#ifdef __cplusplus +extern "C" { +#endif // __cplusplus + +int Setup_RegisterService(void); +int Setup_RegisterDefault(void); +int Setup_RegisterPlugins(void); + +#ifdef __cplusplus +} +#endif // __cplusplus + + + + +#endif // NULLSOFT_WINAMP_SETUP_FACTORY_HEADER
\ No newline at end of file diff --git a/Src/Winamp/setup/sjob_register.cpp b/Src/Winamp/setup/sjob_register.cpp new file mode 100644 index 00000000..9754b2d4 --- /dev/null +++ b/Src/Winamp/setup/sjob_register.cpp @@ -0,0 +1,84 @@ +#include "main.h" +#include "../nu/AutoChar.h" +#include "./sjob_register.h" +#include "./httpgrab.h" + +setup_job_register::setup_job_register() : ref(1), hwndHttp(NULL) +{ +} + +setup_job_register::~setup_job_register() +{ +} + +size_t setup_job_register::AddRef() +{ + return ++ref; +} + +size_t setup_job_register::Release() +{ + if (1 == ref) + { + delete(this); + return 0; + } + return --ref; +} + +HRESULT setup_job_register::Execute(HWND hwndText) +{ + if (!isInetAvailable()) return S_OK; + if (!config_newverchk2) return S_OK; + + // TODO re-enable at some point as needed +#if 0 + char data[8192] = {0}; + SecureZeroMemory(data, sizeof(data)); + + INT s = GetPrivateProfileInt("WinampReg", "RegDataLen", 0, INI_FILEA); + if (s> 0) + { + if (GetPrivateProfileStruct("WinampReg", "RegData2", data, s, INI_FILEA)) + { + wchar_t szEmail[256] = {0}; + GetMetricsValueW(data, MAKEINTRESOURCEA(METRICS_EMAIL), szEmail, sizeof(szEmail)); + } + // if (!*szEmail) return S_OK; + } + + HWND hwndHost = BeginGrabHTTPText(hwndText, HTTPGRAB_USEWINDOWTEXT, &hwndHttp); + HRESULT hr = (SendMetrics(data, hwndHost)) ? S_OK : S_FALSE; + hwndHttp = NULL; + EndGrabHTTPText(hwndHost); + return hr; +#else + return S_OK; +#endif +} + +HRESULT setup_job_register::Cancel(HWND hwndText) +{ + if (hwndHttp) SendMessageW(hwndHttp, WM_COMMAND, MAKEWPARAM(IDCANCEL, BN_CLICKED), + (LPARAM)GetDlgItem(hwndHttp, IDCANCEL)); + return S_OK; +} + +HRESULT setup_job_register::IsCancelSupported() +{ + return S_OK; +} + +#ifdef CBCLASS +#undef CBCLASS +#endif + +#define CBCLASS setup_job_register +START_DISPATCH +CB(ADDREF, AddRef) +CB(RELEASE, Release) +CB(API_SETUPJOB_EXECUTE, Execute) +CB(API_SETUPJOB_CANCEL, Cancel) +CB(API_SETUPJOB_ISCANCELSUPPORTED, IsCancelSupported) +END_DISPATCH +#undef CBCLASS
\ No newline at end of file diff --git a/Src/Winamp/setup/sjob_register.h b/Src/Winamp/setup/sjob_register.h new file mode 100644 index 00000000..b87eb2e9 --- /dev/null +++ b/Src/Winamp/setup/sjob_register.h @@ -0,0 +1,28 @@ +#ifndef WINAMP_REGISTER_SETUP_JOB_HEADER +#define WINAMP_REGISTER_SETUP_JOB_HEADER + +#include "./ifc_setupjob.h" + +class setup_job_register: public ifc_setupjob +{ + +public: + setup_job_register(); + virtual ~setup_job_register(); + +public: + size_t AddRef(); + size_t Release(); + HRESULT Execute(HWND hwndText); + HRESULT Cancel(HWND hwndText); + HRESULT IsCancelSupported(); +private: + size_t ref; + HWND hwndHttp; + +protected: + RECVS_DISPATCH; +}; + + +#endif //WINAMP_REGISTER_SETUP_JOB_HEADER
\ No newline at end of file diff --git a/Src/Winamp/setup/skininfo.cpp b/Src/Winamp/setup/skininfo.cpp new file mode 100644 index 00000000..906d6e2b --- /dev/null +++ b/Src/Winamp/setup/skininfo.cpp @@ -0,0 +1,330 @@ +#define APSTUDIO_READONLY_SYMBOLS +#include "main.h" +#include "./skininfo.h" +#include "./loadimage.h" +#include "./langutil.h" +#include "./setup_resource.h" +#include "./api.h" +#include <../xml/obj_xml.h> +#include <api/service/waServiceFactory.h> +#include "../xml/ifc_xmlreadercallbacki.h" +#include "minizip/unzip.h" +#include "../nu/AutoChar.h" + +#define ZIP_BUFFER_SIZE 2048 + +static wchar_t szClassic[64] = {0, }; +#define CLASSIC_NAME() ((!*szClassic) ? getStringW(IDS_CLASSIC_SKIN_NAME, szClassic, sizeof(szClassic)/sizeof(wchar_t)) : szClassic) + +static BOOL ExtractCurrentFile(unzFile f, LPCWSTR pszPath); +static INT ZipProcessSkinInfo(unzFile f, LPCWSTR pszTemp, SKININFO *psi, LPSTR szSearch, INT cchSearch); // returns length of search + +class SkinXMLCallback : public ifc_xmlreadercallbackI +{ +public: + SkinXMLCallback(SKININFO *psi, LPCWSTR pszSkinXML, LPWSTR pszImage, INT cchImage) // if pszIamge != NULL iamge path will be returned instead of loading image + { + this->psi = psi; + this->pszImage = pszImage; + this->cchImage = cchImage; + if (this->pszImage) *this->pszImage = 0x00; + StringCchCopyW(szPath, sizeof(szPath)/sizeof(wchar_t), pszSkinXML); + PathRemoveFileSpecW(szPath); + }; + void xmlReaderOnCharacterDataCallback(const wchar_t *xmlpath, const wchar_t *xmltag, const wchar_t *s); + void xmlReaderOnStartElementCallback(const wchar_t *xmlpath, const wchar_t *xmltag, ifc_xmlreaderparams *params); + +protected: + SKININFO *psi; + wchar_t szPath[MAX_PATH*2]; + LPWSTR pszImage; + INT cchImage; +}; + +static BOOL LoadXMLFile(obj_xml *parser, LPCWSTR pszFileName) +{ + HANDLE hFile = CreateFileW(pszFileName, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, NULL, NULL); + if (INVALID_HANDLE_VALUE == hFile) return FALSE; + + BOOL br (TRUE); + DWORD bytesRead=0; + do + { + BYTE buffer[1024] = {0}; + bytesRead=0; + if (ReadFile(hFile, buffer, 1024, &bytesRead, NULL) && bytesRead) + { + if (parser->xmlreader_feed(buffer, bytesRead)!=API_XML_SUCCESS) { br = FALSE; break; } + } + else + { + if (parser->xmlreader_feed(0, 0) != API_XML_SUCCESS) { br = FALSE; break; } + bytesRead=0; + } + } while (bytesRead); + + CloseHandle(hFile); + return br; +} + +static BOOL ReadSkinInfo(LPCWSTR pszSkinXML, SKININFO *psi, LPWSTR pszImage, INT cchImage) +{ + waServiceFactory *parserFactory = WASABI_API_SVC->service_getServiceByGuid(obj_xmlGUID); + if (parserFactory) + { + obj_xml *parser = (obj_xml *)parserFactory->getInterface(); + if (parser) + { + SkinXMLCallback cb(psi, pszSkinXML, pszImage, cchImage); + parser->xmlreader_registerCallback(L"WinampAbstractionLayer", &cb); + parser->xmlreader_registerCallback(L"WinampAbstractionLayer\fSkinInfo\f*", &cb); + parser->xmlreader_registerCallback(L"WasabiXML", &cb); + parser->xmlreader_registerCallback(L"WasabiXML\fSkinInfo\f*", &cb); + parser->xmlreader_registerCallback(L"SkinInfo*", &cb); + + parser->xmlreader_open(); + LoadXMLFile(parser, pszSkinXML); + parser->xmlreader_unregisterCallback(&cb); + parser->xmlreader_close(); + parserFactory->releaseInterface(parser); + } + } + + return TRUE; +} + +void SkinXMLCallback::xmlReaderOnStartElementCallback(const wchar_t *xmlpath, const wchar_t *xmltag, ifc_xmlreaderparams *params) +{ + DWORD lcid = MAKELCID(MAKELANGID(LANG_ENGLISH, SUBLANG_ENGLISH_US), SORT_DEFAULT); + if (CSTR_EQUAL == CompareStringW(lcid, NORM_IGNORECASE, L"WinampAbstractionLayer", -1, xmltag, -1) || + CSTR_EQUAL == CompareStringW(lcid, NORM_IGNORECASE, L"WasabiXML", -1, xmltag, -1)) + { + const wchar_t *version = params->getItemValue(L"version"); + if (version) StringCchCopyW(psi->szWasabiVer, SI_VERMAX, version); + else psi->szWasabiVer[0] = 0x00; + } +} + +void SkinXMLCallback::xmlReaderOnCharacterDataCallback(const wchar_t *xmlpath, const wchar_t *xmltag, const wchar_t *s) +{ + static const wchar_t *tags[] = { L"name", L"version", L"comment", L"author", L"email", L"homepage", L"screenshot" }; + int cch, i, count = sizeof(tags)/sizeof(wchar_t*); + DWORD lcid = MAKELCID(MAKELANGID(LANG_ENGLISH, SUBLANG_ENGLISH_US), SORT_DEFAULT); + LPWSTR p; + + for (i = 0; i < count; i++) + { + if (CSTR_EQUAL == CompareStringW(lcid, NORM_IGNORECASE, tags[i], -1, xmltag, -1)) break; + } + + switch(i) + { + case 0: p = psi->szName; cch = SI_NAMEMAX; break; + case 1: p = psi->szVersion; cch = SI_VERMAX; break; + case 2: p = (SIF_COMMENT & psi->fMask) ? psi->pszComment : NULL; cch = psi->cchComment; break; + case 3: p = psi->szAuthor; cch = SI_AUTHORMAX; break; + case 4: p = psi->szEmail; cch = SI_EMAILMAX; break; + case 5: p = psi->szHomePage; cch = SI_HOMEPAGEMAX; break; + case 6: + if ((SIF_PREVIEW & psi->fMask) && *s) + { + if (pszImage) StringCchCopyW(pszImage, cchImage, s); + else + { + wchar_t szPic[MAX_PATH*2] = {0}; + psi->hPreview = WALoadImage(NULL, NULL, (PathIsRootW(s)) ? s : PathCombineW(szPic, szPath, s), FALSE); + } + } + return; + default: return; + } + + if (p) StringCchCopyW(p, cch, s); +} + +BOOL GetSkinInfo(LPCWSTR pszSkinPath, SKININFO *psi) +{ + wchar_t szBuffer[MAX_PATH*2] = {0}; + if (!psi || sizeof(SKININFO) != psi->cbSize) return FALSE; + psi->type = SKIN_TYPE_UNKNOWN; + + if (SIF_COMMENT & psi->fMask) + { + if (!psi->pszComment || !psi->cchComment) return FALSE; + psi->pszComment[0] = 0x00; + } + if (SIF_PREVIEW & psi->fMask) psi->hPreview = NULL; + + if (!pszSkinPath || !*pszSkinPath || CSTR_EQUAL == CompareStringW(LOCALE_SYSTEM_DEFAULT, NORM_IGNORECASE, + pszSkinPath, -1, CLASSIC_NAME(), -1)) + { + // default classic + psi->type = SKIN_TYPE_CLASSIC; + StringCchCopyW(psi->szName, SI_NAMEMAX, CLASSIC_NAME()); + + if (SIF_COMMENT & psi->fMask) StringCchCopyW(psi->pszComment, psi->cchComment, L"Winamp base skin v5.5"); + if (SIF_PREVIEW & psi->fMask) + psi->hPreview = WALoadImage2(L"PNG", MAKEINTRESOURCEW(IDB_PREVIEW_CLASSIC), FALSE); + StringCchCopyW(psi->szAuthor, SI_AUTHORMAX, L"Steve Gedikian"); + StringCchCopyW(psi->szVersion, SI_VERMAX, L"2.0"); + return TRUE; + } + if (PathIsDirectoryW(pszSkinPath)) + { + if (PathFileExistsW(PathCombineW(szBuffer, pszSkinPath, L"skin.xml"))) + { + psi->type = SKIN_TYPE_MODERN; + ReadSkinInfo(szBuffer, psi, NULL, 0); + } + else if (PathFileExistsW(PathCombineW(szBuffer, pszSkinPath, L"main.bmp"))) + { + psi->type = SKIN_TYPE_CLASSIC; + ReadSkinInfo(PathCombineW(szBuffer, pszSkinPath, L"skininfo.xml"), psi, NULL, 0); + } + } + else + { + int len, start, lenSearch; + DWORD lcid; + wchar_t szTemp[MAX_PATH] = {0}; + char filename[MAX_PATH] = {0}, search[MAX_PATH] = {0}; + unzFile f; + + if (!GetTempPathW(MAX_PATH, szBuffer) || !GetTempFileNameW(szBuffer, L"WAS", 0, szTemp)) return FALSE; + + f = unzOpen(AutoChar(pszSkinPath)); + if (!f) return FALSE; + + lcid = MAKELCID(MAKELANGID(LANG_ENGLISH, SUBLANG_ENGLISH_US), SORT_DEFAULT); + search[0] = 1; + lenSearch = 0; + start = 0; + do + { + int pos = -1, nr = unzGoToFirstFile(f); + while (UNZ_OK == nr && *search) + { + pos++; + if (start && pos == start) { start = 0; break; } + if (UNZ_OK == unzGetCurrentFileInfo(f, NULL, filename, sizeof(filename), NULL, 0, NULL, 0) && *filename) + { + len = lstrlenA(filename); + if (!len || filename[len - 1] == '/') // empty or folder + { + nr = unzGoToNextFile(f); + continue; + } + if (SKIN_TYPE_UNKNOWN == psi->type) + { + if ((len == 8 || (len > 8 && '/' == filename[len - 8 - 1])) && + CSTR_EQUAL == CompareStringA(lcid, NORM_IGNORECASE, "main.bmp", -1, (filename + (len - 8)), -1)) + { + psi->type = SKIN_TYPE_CLASSIC; + StringCchCopyA(search, MAX_PATH, "skininfo.xml"); + lenSearch = lstrlenA(search); + start = pos; + } + else if ((len == 8 || (len > 8 && '/' == filename[len - 8 - 1])) && + CSTR_EQUAL == CompareStringA(lcid, NORM_IGNORECASE, "skin.xml", -1, (filename + (len - 8)), -1)) + { + psi->type = SKIN_TYPE_MODERN; + lenSearch = ZipProcessSkinInfo(f, szTemp, psi, search, MAX_PATH); + if (lenSearch) start = pos; + } + } + else if ((len == lenSearch || (len > lenSearch && '/' == filename[len - lenSearch - 1])) && + CSTR_EQUAL == CompareStringA(lcid, NORM_IGNORECASE, search, -1, (filename + (len - lenSearch)), -1)) + { + if (CSTR_EQUAL == CompareStringA(lcid, NORM_IGNORECASE, search, -1, "skininfo.xml", -1)) + { + lenSearch = ZipProcessSkinInfo(f, szTemp, psi, search, MAX_PATH); + if (lenSearch) start = pos; + } + else // image + { + if (ExtractCurrentFile(f, szTemp)) psi->hPreview = WALoadImage(NULL, NULL, szTemp, FALSE); + else psi->hPreview = NULL; + *search = 0x00; + } + } + } + nr = unzGoToNextFile(f); + } + } while(search && *search && start); + unzClose(f); + + // delete tmp file + DeleteFileW(szTemp); + } + + return TRUE; +} + +static BOOL ExtractCurrentFile(unzFile f, LPCWSTR pszPath) +{ + HANDLE hFile; + OVERLAPPED asyncIO; + static BOOL isNT = -1; + BOOL bSuccess(TRUE); + + int l(1), pos(0), bufNum(0); + char buf[ZIP_BUFFER_SIZE*2] = {0}; + + if (UNZ_OK != unzOpenCurrentFile(f)) return FALSE; + + if (-1 == isNT) isNT = (GetVersion() < 0x80000000); + ZeroMemory(&asyncIO, sizeof(OVERLAPPED)); + if (isNT) asyncIO.hEvent = CreateEvent(NULL, FALSE, TRUE, NULL); + + hFile = CreateFileW(pszPath, GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, + FILE_ATTRIBUTE_NORMAL | ((isNT) ? FILE_FLAG_OVERLAPPED : 0), NULL); + if (INVALID_HANDLE_VALUE == hFile) { bSuccess = FALSE; hFile = NULL; } + + while (bSuccess && l > 0) + { + DWORD written = 0; + bufNum = !bufNum; + l = unzReadCurrentFile(f, buf+ZIP_BUFFER_SIZE*bufNum, ZIP_BUFFER_SIZE); + if (l < 0) bSuccess = FALSE; + if (isNT) + { + WaitForSingleObject(asyncIO.hEvent, INFINITE); + if (l > 0) + { + asyncIO.Offset = pos; + if (!WriteFile(hFile, buf+ZIP_BUFFER_SIZE*bufNum, l, NULL, &asyncIO) && ERROR_IO_PENDING != GetLastError()) + { + bSuccess = FALSE; + } + pos += l; + } + } + else + { + if (l > 0) + { + if (!WriteFile(hFile, buf+ZIP_BUFFER_SIZE*bufNum, l, &written, NULL)) bSuccess = FALSE; + } + } + } + + if (hFile) CloseHandle(hFile); + if (asyncIO.hEvent) CloseHandle(asyncIO.hEvent); + unzCloseCurrentFile(f); + return bSuccess; +} + +static INT ZipProcessSkinInfo(unzFile f, LPCWSTR pszTemp, SKININFO *psi, LPSTR szSearch, INT cchSearch) // returns length of search +{ + *szSearch = 0x00; + if (ExtractCurrentFile(f, pszTemp)) + { + wchar_t szImage[MAX_PATH] = {0}; + if (ReadSkinInfo(pszTemp, psi, szImage, MAX_PATH) && *szImage) + { + if(!PathIsRelativeW(szImage)) psi->hPreview = WALoadImage(NULL, NULL, szImage, FALSE); + else StringCchCopyA(szSearch, cchSearch, AutoChar(szImage)); + } + } + return lstrlenA(szSearch); +}
\ No newline at end of file diff --git a/Src/Winamp/setup/skininfo.h b/Src/Winamp/setup/skininfo.h new file mode 100644 index 00000000..b96494db --- /dev/null +++ b/Src/Winamp/setup/skininfo.h @@ -0,0 +1,38 @@ +#ifndef WINAMP_SKININFO_HEADER +#define WINAMP_SKININFO_HEADER + +#include <windows.h> + +#define SIF_COMMENT 0x01 +#define SIF_PREVIEW 0x02 + +#define SKIN_TYPE_UNKNOWN 0 +#define SKIN_TYPE_CLASSIC 1 +#define SKIN_TYPE_MODERN 2 + +#define SI_NAMEMAX 32 +#define SI_VERMAX 16 +#define SI_AUTHORMAX 32 +#define SI_EMAILMAX 32 +#define SI_HOMEPAGEMAX 64 + +typedef struct _SKININFO +{ + INT cbSize; // sizeof(SKININFO) + UINT fMask; // SIF_DESCRIPTION | SIF_PREVIEW + int type; // classic/modern + wchar_t szName[SI_NAMEMAX]; + wchar_t szVersion[SI_VERMAX]; + wchar_t szAuthor[SI_AUTHORMAX]; + wchar_t szEmail[SI_EMAILMAX]; + wchar_t szHomePage[SI_HOMEPAGEMAX]; + wchar_t szWasabiVer[SI_VERMAX]; + wchar_t *pszComment; + int cchComment; + HBITMAP hPreview; // preiew bitmap; +}SKININFO; + + +BOOL GetSkinInfo(LPCWSTR pszSkinPath, SKININFO *psi); + +#endif //WINAMP_SKININFO_HEADER
\ No newline at end of file diff --git a/Src/Winamp/setup/smokingllama.png b/Src/Winamp/setup/smokingllama.png Binary files differnew file mode 100644 index 00000000..e63b4c28 --- /dev/null +++ b/Src/Winamp/setup/smokingllama.png diff --git a/Src/Winamp/setup/spage_assoc.cpp b/Src/Winamp/setup/spage_assoc.cpp new file mode 100644 index 00000000..937284d6 --- /dev/null +++ b/Src/Winamp/setup/spage_assoc.cpp @@ -0,0 +1,1069 @@ +#define APSTUDIO_READONLY_SYMBOLS +#include "main.h" +#include "api.h" +#include "./spage_assoc.h" +#include "./setup_resource.h" +#include "../nu/ns_wc.h" +#include "../nu/AutoWide.h" +#include "./langutil.h" +#include "./setupcommon.h" +#include "../playlist/svc_playlisthandler.h" +#include <api/service/waservicefactorybase.h> +#include "../Agave/URIHandler/svc_urihandler.h" +#include <api/service/waservicefactory.h> +#include <commctrl.h> + +#define MF_SELECTED 0x0001 +#define MF_TYPE_MASK 0xFF00 +#define MF_TYPE_REREAD 0xFF +#define MF_TYPE_UNKNOWN 0x00 +#define MF_TYPE_AUDIO 0x01 +#define MF_TYPE_VIDEO 0x02 +#define MF_TYPE_PLAYLIST 0x03 +#define MF_TYPE_AUXILIARY 0x04 + +#define ID_REGISTERCD ((TYPE_CATEGORIES_NUM) + 1) +#define ID_REGISTERAGENT ((TYPE_CATEGORIES_NUM) + 2) + +#define SET_TYPE(_val, _type) ((_val) = ((_val) & ~MF_TYPE_MASK) | ((_type) << 8)) +#define GET_TYPE(_val) ((_val) >> 8) +#define IS_NEEDREREAD(_val) GET_TYPE((_val), MF_TYPE_REREAD) +#define IS_SELECTED(_val) (MF_SELECTED & (_val)) +#define INITMETA( _type, _selected) ((WORD)(((_type) << 8) | ((_selected) ? MF_SELECTED : 0x0000))) + +static wchar_t szAuxExt[] = L"wsz\0wal\0wlz\0"; + +static LRESULT WINAPI TreeViewProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam); + +static BOOL IsAgentScheduled(void) +{ + HKEY hKey = NULL; + BOOL bActive(FALSE); + WCHAR szAgent[MAX_PATH*2] = {0}; + DWORD cb = sizeof(szAgent); + + if (ERROR_SUCCESS != RegOpenKeyW(HKEY_LOCAL_MACHINE, L"SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Run", &hKey)) + return FALSE; + if (ERROR_SUCCESS != RegQueryValueExW(hKey, L"WinampAgent", NULL, NULL, (BYTE*)szAgent, &cb)) + szAgent[0] = 0x00; + RegCloseKey(hKey); + + if (*szAgent) + { + WCHAR szPath[MAX_PATH*2] = {0}; + GetModuleFileNameW(NULL, szPath, sizeof(szPath)/sizeof(wchar_t)); + PathUnquoteSpacesW(szAgent); + PathRemoveFileSpecW(szAgent); + PathRemoveFileSpecW(szPath); + DWORD lcid = MAKELCID(MAKELANGID(LANG_ENGLISH, SUBLANG_ENGLISH_US), SORT_DEFAULT); + bActive = (CSTR_EQUAL == CompareStringW(lcid, NORM_IGNORECASE, szPath, -1, szAgent, -1)); + } + + return bActive; +} + +static BOOL IsAgentExist(void) +{ + wchar_t szAgent[MAX_PATH] = {0}; + if (0 == GetModuleFileNameW(hMainInstance, szAgent, sizeof(szAgent)/sizeof(wchar_t))) + return FALSE; + + PathRemoveFileSpecW(szAgent); + if (NULL == PathCombineW(szAgent, szAgent, L"winampa.exe")) + return FALSE; + + return (FALSE != PathFileExistsW(szAgent)); +} + +static BOOL RefreshIcons(void) +{ + SHChangeNotify(SHCNE_ASSOCCHANGED, SHCNF_IDLIST | SHCNF_FLUSHNOWAIT, NULL, NULL); + return TRUE; +} + +static void RegisterProtocols() +{ + if (config_no_registry) + return; + + wchar_t winampexe[MAX_PATH] = {0}; + GetModuleFileNameW(hMainInstance, winampexe, MAX_PATH); + + WCHAR szApplication[256] = {0}; + INT r = MultiByteToWideCharSZ(CP_ACP, 0, app_name, -1, NULL, 0); + if (r > ARRAYSIZE(szApplication) || 0 == r) + return; + if (0 == MultiByteToWideCharSZ(CP_ACP, 0, app_name, -1, szApplication, ARRAYSIZE(szApplication))) + return; + + if (NULL != WASABI_API_SVC) + { + for(size_t i =0;;i++) + { + waServiceFactory *sf = WASABI_API_SVC->service_enumService(svc_urihandler::getServiceType(), i); + if (NULL == sf) break; + + svc_urihandler *handler = (svc_urihandler *)sf->getInterface(); + if (NULL != handler) + { + WCHAR szName[128] = {0}, szDesc[256] = {0}; + for (size_t k = 0; ;k++) + { + INT ret = handler->EnumProtocols(k, szName, ARRAYSIZE(szName), szDesc, ARRAYSIZE(szDesc)); + if (0 != ret) + break; + + if (0 == handler->RegisterProtocol(szName, winampexe)) + { + IFileTypeRegistrar *registrar = 0; + if (GetRegistrar(®istrar, true) == 0 && registrar) + { + registrar->RegisterMediaPlayerProtocol(szName, szApplication); + registrar->Release(); + } + } + } + sf->releaseInterface(handler); + } + } + } +} + +setup_page_assoc::setup_page_assoc() : ref(1), hwnd(NULL), pszTypes(NULL), pMeta(NULL), bRegCD(FALSE), bAgent(FALSE), bExplorerMenu(TRUE) +{ + ZeroMemory(expanded, sizeof(expanded)); + ZeroMemory(szTopExt, sizeof(szTopExt)); + ZeroMemory(szCaretExt, sizeof(szCaretExt)); +} + +setup_page_assoc::~setup_page_assoc() +{ + if (pszTypes) + { + free(pszTypes); + pszTypes = NULL; + } + if (pMeta) + { + free(pMeta); + pMeta = NULL; + } +} + +size_t setup_page_assoc::AddRef() +{ + return ++ref; +} + +size_t setup_page_assoc::Release() +{ + if (1 == ref) + { + delete(this); + return 0; + } + return --ref; +} + +HRESULT setup_page_assoc::GetName(bool bShort, const wchar_t **pszName) +{ + if (bShort) + { + static wchar_t szShortName[32] = {0}; + *pszName = (*szShortName) ? szShortName : getStringW(IDS_PAGE_ASSOCIATIONS, szShortName, sizeof(szShortName)/sizeof(wchar_t)); + } + else + { + static wchar_t szLongName[64] = {0}; + *pszName = (*szLongName) ? szLongName : getStringW(IDS_PAGE_ASSOCIATIONS_LONG, szLongName, sizeof(szLongName)/sizeof(wchar_t)); + } + return S_OK; +} + +HRESULT setup_page_assoc::Save(HWND hwndText) +{ + HRESULT hr(S_OK); + WORD *pm; + wchar_t ext_list[16384] = {0}, *p = 0, *pe = ext_list; + BOOL bFirst(TRUE); + size_t len = ARRAYSIZE(ext_list); + + // make sure that we honour the agent setting even if no settings changed + // this allows the agent to be restarted correctly after a normal upgrade + if (bAgent && IsAgentExist()) + config_agent_add(); + else + config_agent_remove(); + + // temporary: always enumerate and register protocols + RegisterProtocols(); + + if (S_FALSE == IsDirty()) return S_OK; + + if (!pszTypes) return S_FALSE; + + config_setup_filetypes(0); + + for(pm = pMeta, p = pszTypes; *p != 0; p += lstrlenW(p) + 1, pm++) + { + config_register_capability(p, 0); + config_register(p, IS_SELECTED(*pm)); + if (IS_SELECTED(*pm) && (S_OK == hr) && GET_TYPE(*pm) != MF_TYPE_AUXILIARY) + { + if (!len) { hr = S_FALSE; continue; } + if (!bFirst) + { + pe[0] = L':'; + pe++; + len--; + } + else bFirst = FALSE; + if (S_OK != StringCchCopyExW(pe, len, p, &pe, &len, STRSAFE_IGNORE_NULLS)) hr = S_FALSE; + } + } + if (S_OK == hr) _w_sW("config_extlist", ext_list); + + config_regcdplayer(bRegCD, 0); + (bExplorerMenu) ? config_adddircontext(0) : config_removedircontext(0); + + config_registermediaplayer(1); + + WritePrivateProfileStringW(L"Jump To File Extra", L"newIconLib", L"refresh", INI_FILE); + RefreshIcons(); + + return hr; +} + +static BOOL IsFirstSetup() +{ + wchar_t szVer[512] = {0}; + if (0 == GetPrivateProfileIntW(L"WinampReg", L"IsFirstInst", 1, INI_FILE)) return FALSE; + + GetPrivateProfileStringW(L"Winamp", L"config_extlist", L"", szVer, 512, INI_FILE); + if (*szVer) return FALSE; + + GetPrivateProfileStringW(L"WinampReg", L"WAVer", L"", szVer, 512, INI_FILE); + return (!*szVer || CSTR_EQUAL != CompareStringW(MAKELCID(MAKELANGID(LANG_ENGLISH, SUBLANG_ENGLISH_US), SORT_DEFAULT), + NORM_IGNORECASE, szVer, -1, AutoWide(APP_VERSION), -1)); +} + +static wchar_t *BuildExtensionString(WORD **ppMeta, BOOL bFirstSetup) +{ + INT cWA(0), cPL(0), cAux(0), lWA(0), lPL(0), lAux(0); + wchar_t *pszType, *pWAExt = in_getextlistW(), *pPLExt, *p; + + if (pWAExt) + { + for(p = pWAExt; *p != 0; cWA++, p += lstrlenW(p) + 1); + lWA = (INT)(p - pWAExt); + } + + if (playlistManager) + { + size_t playlistEnum = 0; + const wchar_t *playlistExt=0; + while (NULL != (playlistExt = playlistManager->EnumExtension(playlistEnum++))) { lPL += (lstrlenW(playlistExt) + 1); cPL++; } + lPL += 2; + } + + for(p = szAuxExt; *p != 0; cAux++, p += lstrlenW(p) + 1); + lAux = (INT)(p - szAuxExt); + + pszType = (wchar_t*)calloc((lWA + lPL + lAux + 1), sizeof(wchar_t)); + if (ppMeta) + { + *ppMeta = (WORD*)calloc((cWA + cPL + cAux), sizeof(WORD)); + } + + if (pszType) + { + if (pWAExt) CopyMemory(pszType, pWAExt, lWA*sizeof(wchar_t)); + pPLExt = pszType + lWA; + p = pPLExt; + if (playlistManager) + { + size_t playlistEnum=0; + const wchar_t *playlistExt=0; + while (lPL > 0 && NULL != (playlistExt = playlistManager->EnumExtension(playlistEnum++))) + { + int c = lstrlenW(playlistExt) + 1; + lstrcpynW(p, playlistExt, c); + if (c) + { + p += c; + lPL -= c; + } + } + if (lPL > 1) *p = 0x00; + } + CopyMemory(p, szAuxExt, lAux*sizeof(wchar_t)); + *(p+lAux)=0; + } + + if(ppMeta && *ppMeta) + { + int i; + WORD *pm = *ppMeta; + p = pszType; + for (i = 0; i < cWA; i++, pm++, p += lstrlenW(p) + 1) *pm = INITMETA(MF_TYPE_REREAD, ((!bFirstSetup) ? config_isregistered(p) : 1)); + for (i = 0; i < cPL; i++, pm++, p += lstrlenW(p) + 1) *pm = INITMETA(MF_TYPE_PLAYLIST, ((!bFirstSetup) ? config_isregistered(p) : 1)); + for (i = 0; i < cAux; i++, pm++, p += lstrlenW(p) + 1) *pm = INITMETA(MF_TYPE_AUXILIARY, ((!bFirstSetup) ? config_isregistered(p) : 1)); + } + + if (pWAExt) GlobalFree(pWAExt); + + return pszType; +} + +static BOOL GetPLExtensionName(LPCWSTR pszExt, LPWSTR pszDest, INT cchDest) +{ + BOOL result(FALSE); + int n(0); + waServiceFactory *sf = 0; + LPCWSTR ext; + DWORD lcid = MAKELCID(MAKELANGID(LANG_ENGLISH, SUBLANG_ENGLISH_US), SORT_DEFAULT); + + while (NULL != (sf = WASABI_API_SVC->service_enumService(WaSvc::PLAYLISTHANDLER, n++))) + { + svc_playlisthandler * handler = static_cast<svc_playlisthandler *>(sf->getInterface()); + if (handler) + { + int k(0); + while (NULL != (ext = handler->EnumerateExtensions(k++))) + { + if (CSTR_EQUAL == CompareStringW(lcid, NORM_IGNORECASE, pszExt, -1, ext, -1)) + { + result = (S_OK == StringCchCopyW(pszDest, cchDest, handler->GetName())); + if (result && CSTR_EQUAL == CompareStringW(lcid, NORM_IGNORECASE, pszExt, -1, L"M3U8", -1)) // ugly... + result = (S_OK == StringCchCatW(pszDest, cchDest, L" (Unicode)")); + break; + } + } + sf->releaseInterface(handler); + } + } + return result; +} + +static BOOL GetAuxExtensionName(LPCWSTR pszExt, LPWSTR pszDest, INT cchDest) +{ + BOOL result(FALSE); + DWORD lcid = MAKELCID(MAKELANGID(LANG_ENGLISH, SUBLANG_ENGLISH_US), SORT_DEFAULT); + if (CSTR_EQUAL == CompareStringW(lcid, NORM_IGNORECASE, pszExt, -1, L"wal", -1)) + result = (S_OK == StringCchCopyW(pszDest, cchDest, getStringW(IDS_WINAMP_SKIN_MODERN, NULL, 0))); + else if (CSTR_EQUAL == CompareStringW(lcid, NORM_IGNORECASE, pszExt, -1, L"wsz", -1)) + result = (S_OK == StringCchCopyW(pszDest, cchDest, getStringW(IDS_WINAMP_SKIN_CLASSIC, NULL, 0))); + else if (CSTR_EQUAL == CompareStringW(lcid, NORM_IGNORECASE, pszExt, -1, L"wlz", -1)) + result = (S_OK == StringCchCopyW(pszDest, cchDest, getStringW(IDS_WINAMP_LANG_PACK, NULL, 0))); + return result; +} + +static BOOL GetExtensionName(LPCWSTR pszFile, INT type, LPWSTR pszDest, INT cchDest) +{ + switch(type) + { + case MF_TYPE_AUDIO: + case MF_TYPE_VIDEO: + return in_get_extended_fileinfoW(pszFile, L"family", pszDest, cchDest); + case MF_TYPE_PLAYLIST: + { + const wchar_t *pszExt = PathFindExtensionW(pszFile); + return (L'.' == *pszExt && 0x00 != *(++pszExt)) ? GetPLExtensionName(pszExt, pszDest, cchDest) : FALSE; + } + case MF_TYPE_AUXILIARY: + { + const wchar_t *pszExt = PathFindExtensionW(pszFile); + return (L'.' == *pszExt && 0x00 != *(++pszExt)) ? GetAuxExtensionName(pszExt, pszDest, cchDest) : FALSE; + } + } + return FALSE; +} + +HRESULT setup_page_assoc::Revert(void) +{ + HRESULT hr(S_OK); + + if (pszTypes) + { + free(pszTypes); + pszTypes = NULL; + } + + if (pMeta) + { + free(pMeta); + pMeta = NULL; + } + + BOOL firstSetup = IsFirstSetup(); + pszTypes = BuildExtensionString(&pMeta, firstSetup); + + ZeroMemory(expanded, sizeof(expanded)); + ZeroMemory(szTopExt, sizeof(szTopExt)); + ZeroMemory(szCaretExt, sizeof(szCaretExt)); + + bRegCD = (firstSetup) ? TRUE : config_iscdplayer(); + bAgent = (FALSE != IsAgentExist()) ? ((firstSetup) ? FALSE : IsAgentScheduled()) : FALSE; + bExplorerMenu = (firstSetup) ? TRUE : config_isdircontext(); + + if (hwnd) UpdateUI(); + return hr; +} + +HRESULT setup_page_assoc::IsDirty(void) +{ + if (IsFirstSetup()) return S_OK; + + HRESULT hr(S_FALSE); + DWORD lcid = MAKELCID(MAKELANGID(LANG_ENGLISH, SUBLANG_ENGLISH_US), SORT_DEFAULT); + wchar_t *pszOrigTypes = BuildExtensionString(NULL, TRUE), *p; + if ((!pszOrigTypes && pszTypes) || (pszOrigTypes && !pszTypes)) + { + if (pszOrigTypes) free(pszOrigTypes); + return S_OK; + } + else if (!pszOrigTypes && !pszTypes) return S_FALSE; + + INT cr = CompareStringW(lcid, NORM_IGNORECASE, pszTypes, -1, pszOrigTypes, -1); + if (0 == cr) hr = E_UNEXPECTED; + else if (CSTR_EQUAL == cr) + { + WORD *pm; + for(pm = pMeta, p = pszTypes; *p != 0; p += lstrlenW(p) + 1, pm++) + { + if ((MF_SELECTED & *pm) != (BYTE)config_isregistered(p)) { hr = S_OK; break; } + } + } + else hr = S_OK; + + if (pszOrigTypes) free(pszOrigTypes); + + if (S_FALSE == hr && bRegCD != config_iscdplayer()) hr = S_OK; + if (S_FALSE == hr && bAgent != (IsAgentExist() && IsAgentScheduled())) hr = S_OK; + if (S_FALSE == hr && bExplorerMenu != config_isdircontext()) hr = S_OK; + + return hr; +} + +HRESULT setup_page_assoc::Validate(void) +{ + return S_OK; +} + +HRESULT setup_page_assoc::CreateView(HWND hwndParent, HWND *phwnd) +{ + *phwnd = WACreateDialogParam(MAKEINTRESOURCEW((!IsWin8() ? IDD_SETUP_PAGE_ASSOC : IDD_SETUP_PAGE_ASSOC_WIN8)), hwndParent, ::DialogProc, (LPARAM)this); + return S_OK; +} + +void setup_page_assoc::UpdateUI(void) +{ + TVINSERTSTRUCTW is = {0}; + WORD *pm; + HTREEITEM hBranch[TYPE_CATEGORIES_NUM], hFirst(NULL), hCaret(NULL), hItem; + INT sBranch[TYPE_CATEGORIES_NUM] = {0}; + INT ids[TYPE_CATEGORIES_NUM] = {IDS_FILETYPE_UNKNOWN, IDS_FILETYPE_AUDIO, IDS_FILETYPE_VIDEO, IDS_FILETYPE_PLAYLIST, IDS_FILETYPE_AUXILIARY}; + INT i; + + wchar_t szText[MAX_PATH] = {0}, buf[MAX_PATH] = {0}, buf2[MAX_PATH] = {0}, *p, *test; + if (!hwnd || !IsWindow(hwnd)) return; + + DWORD lcid = MAKELCID(MAKELANGID(LANG_ENGLISH, SUBLANG_ENGLISH_US), SORT_DEFAULT); + + HWND hwndTree = GetDlgItem(hwnd,IDC_TREE_TYPES); + SendMessageW(hwndTree, TVM_DELETEITEM, 0, (LPARAM)TVI_ROOT); + if (!pszTypes) return; + + for (i = 0; i < ARRAYSIZE(hBranch); i++) + { + hBranch[i] = NULL; + sBranch[i] = -1; + } + + INT len = ARRAYSIZE(buf); + StringCchCopyW(buf, len, L"test."); + test = buf + lstrlenW(buf); + len -= (INT)(test - buf); + + SendMessageW(hwndTree, WM_SETREDRAW, FALSE, 0L); + + is.hInsertAfter = TVI_LAST; + is.item.mask = TVIF_STATE | TVIF_CHILDREN | TVIF_TEXT | TVIF_PARAM; + is.item.stateMask = TVIS_STATEIMAGEMASK | TVIS_EXPANDED; + for(i = 0, pm = pMeta, p = pszTypes; *p != 0 && *(p+1) != 0; pm++, p += lstrlenW(p) + 1, i++) + { + StringCchCopyW(test, len, p); + OutputDebugStringW(test); + OutputDebugStringW(L"\r\n"); + if (MF_TYPE_REREAD == GET_TYPE(*pm)) + { + if (!in_get_extended_fileinfoW(buf, L"type", buf2, MAX_PATH)) + ZeroMemory(buf2, sizeof(buf2)); + + *pm = *pm & 0x00FF; + switch(buf2[0]) + { + case L'0': SET_TYPE(*pm, MF_TYPE_AUDIO); break; + case L'1': SET_TYPE(*pm, MF_TYPE_VIDEO); break; + } + } + + INT index = GET_TYPE(*pm); + if (!hBranch[index]) + { + is.hInsertAfter = TVI_SORT; + is.hParent = TVI_ROOT; + is.item.cChildren = 1; + is.item.state = INDEXTOSTATEIMAGEMASK(1) | ((expanded[index]) ? TVIS_EXPANDED : 0); + is.item.pszText = getStringW(ids[index], NULL, 0); + is.item.lParam = -(index + 1); + hBranch[index] = (HTREEITEM)SendMessageW(hwndTree, TVM_INSERTITEMW, 0, (LPARAM)&is); + is.item.cChildren = 0; + is.hInsertAfter = TVI_LAST; + + wchar_t t[32] = {0}; + StringCchPrintfW(t, ARRAYSIZE(t), L"#%d", index + 1); + if (!hFirst && CSTR_EQUAL == CompareStringW(lcid, 0, t, -1, szTopExt, -1)) hFirst = hBranch[index]; + if (!hCaret && CSTR_EQUAL == CompareStringW(lcid, 0, t, -1, szCaretExt, -1)) hCaret = hBranch[index]; + } + + is.hParent = hBranch[index]; + + if (MF_SELECTED & *pm) + { + if (-1 == sBranch[index]) sBranch[index] = 1; + else if (0 == sBranch[index]) sBranch[index] = 2; + } + else + { + if (-1 == sBranch[index]) sBranch[index] = 0; + else if (1 == sBranch[index]) sBranch[index] = 2; + } + + lstrcpynW(szText, p, MAX_PATH); + INT count = lstrlenW(szText); + CharUpperW(szText); + wchar_t szName[MAX_PATH] = {0}; + if (GetExtensionName(buf, GET_TYPE(*pm), szName, MAX_PATH)) + { + if (count) StringCchCatW(szText, MAX_PATH, L"\t"); + StringCchCatW(szText, MAX_PATH, szName); + } + + is.item.pszText = szText; + is.item.lParam = (LPARAM)i; + is.item.state = INDEXTOSTATEIMAGEMASK((MF_SELECTED & *pm)?2:1); + + hItem = (HTREEITEM)SendMessageW(hwndTree, TVM_INSERTITEMW, 0, (LPARAM)&is); + + if (hItem) + { + if (!hFirst && CSTR_EQUAL == CompareStringW(lcid, NORM_IGNORECASE, p, -1, szTopExt, -1)) hFirst = hItem; + if (!hCaret && CSTR_EQUAL == CompareStringW(lcid, NORM_IGNORECASE, p, -1, szCaretExt, -1)) hCaret = hItem; + } + } + + // insert cd + is.hParent = TVI_ROOT; + is.item.state = INDEXTOSTATEIMAGEMASK(bRegCD + 1); + is.item.pszText = getStringW(IDS_REGISTER_CDPLAYER, NULL, 0); + is.item.lParam = -ID_REGISTERCD; + hItem = (HTREEITEM)SendMessageW(hwndTree, TVM_INSERTITEMW, 0, (LPARAM)&is); + if (!hFirst || !hCaret) + { + wchar_t t[32] = {0}; + StringCchPrintfW(t, ARRAYSIZE(t), L"#%d", ID_REGISTERCD); + if (!hFirst && CSTR_EQUAL == CompareStringW(lcid, 0, t, -1, szTopExt, -1)) hFirst = hItem; + if (!hCaret && CSTR_EQUAL == CompareStringW(lcid, 0, t, -1, szCaretExt, -1)) hCaret = hItem; + } + + // agent + BOOL bAgentExist = IsAgentExist(); + HWND hwndCtrl = GetDlgItem(hwnd, IDC_CHK_AGENT); + if (hwndCtrl) EnableWindow(hwndCtrl, bAgentExist); + hwndCtrl = GetDlgItem(hwnd, IDC_LBL_AGENT_DESC); + if (hwndCtrl) EnableWindow(hwndCtrl, bAgentExist); + + CheckDlgButton(hwnd, IDC_CHK_AGENT, (bAgent && bAgentExist) ? BST_CHECKED : BST_UNCHECKED); + CheckDlgButton(hwnd, IDC_CHK_CD, (bRegCD) ? BST_CHECKED : BST_UNCHECKED); + CheckDlgButton(hwnd, IDC_CHK_EXPLORER_MENU, (bExplorerMenu) ? BST_CHECKED : BST_UNCHECKED); + + is.item.mask = TVIF_STATE; + is.item.stateMask = TVIS_STATEIMAGEMASK; + + for (int i = 0; i < sizeof(hBranch)/sizeof(HTREEITEM); i++) + { + if (!hBranch[i]) continue; + is.item.hItem = hBranch[i]; + is.item.state = INDEXTOSTATEIMAGEMASK(sBranch[i] + 1); + SendMessageW(hwndTree, TVM_SETITEM, 0, (LPARAM)&is.item); + SendMessageW(hwndTree, TVM_SORTCHILDREN, FALSE, (LPARAM)hBranch[i]); + } + + if (hCaret) PostMessageW(hwndTree, TVM_SELECTITEM, TVGN_CARET, (LPARAM)hCaret); + if (hFirst) PostMessageW(hwndTree, TVM_SELECTITEM, TVGN_FIRSTVISIBLE, (LPARAM)hFirst); + + SendMessageW(hwndTree, WM_SETREDRAW, TRUE, 0L); +} + +INT setup_page_assoc::TreeView_OnCustomDraw(NMTVCUSTOMDRAW *ptvcd) +{ + switch(ptvcd->nmcd.dwDrawStage) + { + case CDDS_PREPAINT: + return CDRF_DODEFAULT | CDRF_NOTIFYITEMDRAW; + case CDDS_ITEMPREPAINT: + return CDRF_DODEFAULT | CDRF_NOTIFYPOSTPAINT; + case CDDS_ITEMPOSTPAINT: + { + RECT rt; + WCHAR szText[256] = {0}; + TVITEMW item = {0}; + + item.hItem = (HTREEITEM)ptvcd->nmcd.dwItemSpec; + item.mask = TVIF_TEXT | TVIF_STATE; + item.stateMask = TVIS_SELECTED; + item.pszText = szText; + item.cchTextMax = 256; + SendMessageW(ptvcd->nmcd.hdr.hwndFrom, TVM_GETITEMW, 0, (LPARAM)&item); + *(DWORD_PTR*)&rt = ptvcd->nmcd.dwItemSpec; + SendMessageW(ptvcd->nmcd.hdr.hwndFrom, TVM_GETITEMRECT, TRUE, (LPARAM)&rt); + SetTextColor(ptvcd->nmcd.hdc, ptvcd->clrText); + SetBkColor(ptvcd->nmcd.hdc, ptvcd->clrTextBk); + + DrawTextW(ptvcd->nmcd.hdc, item.pszText, -1, &rt, DT_EXPANDTABS | DT_NOPREFIX | DT_SINGLELINE | DT_CALCRECT); + rt.right += 8; + rt.top = ptvcd->nmcd.rc.top; + rt.bottom = ptvcd->nmcd.rc.bottom; + + ExtTextOutW(ptvcd->nmcd.hdc, 0, 0, ETO_OPAQUE, &rt, L"", 0, NULL); + rt.left += 4; + DrawTextW(ptvcd->nmcd.hdc, item.pszText, -1, &rt, DT_EXPANDTABS | DT_NOPREFIX | DT_SINGLELINE | DT_VCENTER); + + if ((TVIS_SELECTED & item.state) && ptvcd->nmcd.hdr.hwndFrom == GetFocus()) + { + if (0 == (0x01/*UISF_HIDEFOCUS*/ & SendMessageW(ptvcd->nmcd.hdr.hwndFrom, 0x0129/*WM_QUERYUISTATE*/, 0, 0L))) + { + rt.left -= 4; + SetTextColor(ptvcd->nmcd.hdc, GetSysColor(COLOR_WINDOWTEXT)); + SetBkColor(ptvcd->nmcd.hdc, GetSysColor(COLOR_WINDOW)); + DrawFocusRect(ptvcd->nmcd.hdc, &rt); + } + } + } + break; + } + return CDRF_DODEFAULT; +} + +BOOL setup_page_assoc::TreeView_OnClick(NMHDR *pnmh) +{ + TVHITTESTINFO ht; + GetCursorPos(&ht.pt); + MapWindowPoints(HWND_DESKTOP, pnmh->hwndFrom, &ht.pt, 1); + if(NULL != SendMessageW(pnmh->hwndFrom, TVM_HITTEST, 0, (LPARAM)&ht)) + { + if ((TVHT_ONITEM | TVHT_ONITEMRIGHT) & ht.flags) + { + TreeView_OnItemStateClick(pnmh->hwndFrom, ht.hItem); + if (TVHT_ONITEMSTATEICON & ht.flags) return TRUE; + } + } + return FALSE; +} + +BOOL setup_page_assoc::TreeView_OnKeyDown(NMTVKEYDOWN *ptvkd) +{ + switch(ptvkd->wVKey) + { + case VK_SPACE: + { + HTREEITEM hItem = (HTREEITEM)(HTREEITEM)SendMessageW(ptvkd->hdr.hwndFrom, TVM_GETNEXTITEM, (WPARAM)TVGN_CARET, 0L); + if (hItem) TreeView_OnItemStateClick(ptvkd->hdr.hwndFrom, hItem); + return TRUE; + } + } + return FALSE; +} + +void setup_page_assoc::TreeView_OnItemStateClick(HWND hwndTree, HTREEITEM hItem) +{ + HTREEITEM hParent = (HTREEITEM)SendMessageW(hwndTree, TVM_GETNEXTITEM, (WPARAM)TVGN_PARENT, (LPARAM)hItem); + HTREEITEM hChild = (HTREEITEM)SendMessageW(hwndTree, TVM_GETNEXTITEM, (WPARAM)TVGN_CHILD, (LPARAM)hItem); + TVITEMW item = {0}; + item.hItem = hItem; + item.mask = TVIF_STATE | TVIF_PARAM; + item.stateMask = TVIS_STATEIMAGEMASK; + + if (!SendMessageW(hwndTree, TVM_GETITEMW, 0, (LPARAM)&item)) return; + INT state = ((item.state>>12) - 1); + INT param = (INT)item.lParam; + + SendMessageW(hwndTree, WM_SETREDRAW, FALSE, 0L); + + state = (2 == state) ? 1 : !state; + + item.mask = TVIF_STATE; + item.state = INDEXTOSTATEIMAGEMASK(state + 1); + SendMessageW(hwndTree, TVM_SETITEMW, 0, (LPARAM)&item); + + if (!hChild) + { + INT count = 1, selcount = state; + + item.hItem = hItem; + while(NULL != (item.hItem = (HTREEITEM)SendMessageW(hwndTree, TVM_GETNEXTITEM, (WPARAM)TVGN_PREVIOUS, (LPARAM)item.hItem))) + { + count++; + if (!SendMessageW(hwndTree, TVM_GETITEMW, 0, (LPARAM)&item)) continue; + if (2 == (item.state>>12)) selcount++; + } + item.hItem = hItem; + while(NULL != (item.hItem = (HTREEITEM)SendMessageW(hwndTree, TVM_GETNEXTITEM, (WPARAM)TVGN_NEXT, (LPARAM)item.hItem))) + { + count++; + if (!SendMessageW(hwndTree, TVM_GETITEMW, 0, (LPARAM)&item)) continue; + if (2 == (item.state>>12)) selcount++; + } + + item.hItem = hParent; + item.state = INDEXTOSTATEIMAGEMASK(((!selcount) ? 1 : ((selcount == count) ? 2 :3))); + SendMessageW(hwndTree, TVM_SETITEMW, 0, (LPARAM)&item); + if (param >= 0) pMeta[param] = (pMeta[param] & ~MF_SELECTED) | ((state) ? MF_SELECTED : 0); + else + { + switch(-param) + { + case ID_REGISTERCD: bRegCD = state; break; + } + } + } + else + { + item.hItem = hChild; + while(item.hItem) + { + item.mask = TVIF_PARAM; + if (SendMessageW(hwndTree, TVM_GETITEMW, 0, (LPARAM)&item) && item.lParam >= 0) pMeta[item.lParam] = (pMeta[item.lParam] & ~MF_SELECTED) | ((state) ? MF_SELECTED : 0); + + item.mask = TVIF_STATE; + item.state = INDEXTOSTATEIMAGEMASK(state + 1); + SendMessageW(hwndTree, TVM_SETITEMW, 0, (LPARAM)&item); + item.hItem = (HTREEITEM)SendMessageW(hwndTree, TVM_GETNEXTITEM, (WPARAM)TVGN_NEXT, (LPARAM)item.hItem); + } + } + UpdateWindow(hwnd); + SendMessageW(hwnd, WM_SETREDRAW, FALSE, 0L); + SendMessageW(hwndTree, WM_SETREDRAW, TRUE, 0L); + SendMessageW(hwnd, WM_SETREDRAW, TRUE, 0L); + InvalidateRect(hwndTree, NULL, FALSE); +} + +INT_PTR setup_page_assoc::OnInitDialog(HWND hwndFocus, LPARAM lParam) +{ + HWND hwndTree = GetDlgItem(hwnd, IDC_TREE_TYPES); + if (hwndTree) + { + HIMAGELIST himl = ImageList_LoadImage(hMainInstance, MAKEINTRESOURCE(IDB_CHECKBOX), 16, 1, CLR_NONE, IMAGE_BITMAP, LR_CREATEDIBSECTION | LR_LOADTRANSPARENT); + if (himl) himl = (HIMAGELIST) SendMessageW(hwndTree, TVM_SETIMAGELIST, TVSIL_STATE, (LPARAM)himl); + if (himl) ImageList_Destroy(himl); + + WNDPROC fnOldProc = (WNDPROC)(LONG_PTR)SetWindowLongPtrW(hwndTree, GWLP_WNDPROC, (LONGX86)(LONG_PTR)TreeViewProc); + if (fnOldProc) SetPropW(hwndTree, L"TVPROC", fnOldProc); + } + UpdateUI(); + return 0; +} + +void setup_page_assoc::OnDestroy(void) +{ + HWND hwndTree = GetDlgItem(hwnd, IDC_TREE_TYPES); + if (hwndTree) + { + TVITEMW item = {0}; + HIMAGELIST himl; + INT index1(-1), index2(-1); + wchar_t *p; + + ZeroMemory(expanded, sizeof(expanded)); + ZeroMemory(szTopExt, sizeof(szTopExt)); + ZeroMemory(szCaretExt, sizeof(szCaretExt)); + + item.mask = TVIF_PARAM | TVIF_STATE; + item.stateMask = TVIS_EXPANDED; + item.hItem = (HTREEITEM)SendMessageW(hwndTree, TVM_GETNEXTITEM, (WPARAM)TVGN_ROOT, 0L); + while(item.hItem) + { + if (SendMessageW(hwndTree, TVM_GETITEMW, 0, (LPARAM)&item)) + { + INT param = (INT)-item.lParam; + if (param < TYPE_CATEGORIES_NUM) expanded[param] = (BYTE)(TVIS_EXPANDED & item.state); + } + item.hItem = (HTREEITEM)SendMessageW(hwndTree, TVM_GETNEXTITEM, (WPARAM)TVGN_NEXT, (LPARAM)item.hItem); + } + item.mask = TVIF_PARAM; + item.hItem = (HTREEITEM)SendMessageW(hwndTree, TVM_GETNEXTITEM, (WPARAM)TVGN_FIRSTVISIBLE, 0L); + if (item.hItem && SendMessageW(hwndTree, TVM_GETITEMW, 0, (LPARAM)&item)) index1 = (INT)item.lParam; + item.hItem = (HTREEITEM)SendMessageW(hwndTree, TVM_GETNEXTITEM, (WPARAM)TVGN_CARET, 0L); + if (item.hItem && SendMessageW(hwndTree, TVM_GETITEMW, 0, (LPARAM)&item)) index2 = (INT)item.lParam; + + if (index1 < 0) StringCchPrintfW(szTopExt, ARRAYSIZE(szTopExt), L"#%d", -index1); + if (index2 < 0) StringCchPrintfW(szCaretExt, ARRAYSIZE(szCaretExt), L"#%d", -index2); + + if (index1 >= 0 || index2 >= 0) + { + INT i; + for(i = 0, p = pszTypes; *p != 0; p += lstrlenW(p) + 1, i++) + { + if (index1 == i) + { + StringCchCopyW(szTopExt, ARRAYSIZE(szTopExt), p); + if (index2 < 0) break; + index1 = -1; + } + if (index2 == i) + { + StringCchCopyW(szCaretExt, ARRAYSIZE(szCaretExt), p); + if (index1 < 0) break; + index2 = -1; + } + } + } + himl = (HIMAGELIST) SendMessageW(hwndTree, TVM_SETIMAGELIST, TVSIL_STATE, (LPARAM)NULL); + if (himl) ImageList_Destroy(himl); + } +} + +void setup_page_assoc::OnSize(UINT nType, INT cx, INT cy) +{ + RECT rw; + INT h, r; + h = cy; + r = cx; + + HWND hwndCtrl = GetDlgItem(hwnd, IDC_LBL_HEADER); + if (hwndCtrl) + { + GetWindowRect(hwndCtrl, &rw); + MapWindowPoints(HWND_DESKTOP, hwnd, (POINT*)&rw, 2); + SetWindowPos(hwndCtrl, NULL, 0, 0, cx - rw.left*2, rw.bottom - rw.top, SWP_NOACTIVATE | SWP_NOZORDER | SWP_NOMOVE); + } + + if (IsWin8()) + { + // hide the treeview (as needed to process things nicely but needs to be hidden on Windows 8 and higher as they work differently) + hwndCtrl = GetDlgItem(hwnd, IDC_TREE_TYPES); + if (hwndCtrl) + { + SetWindowPos(hwndCtrl, NULL, 0, 0, 0, 0, SWP_NOACTIVATE | SWP_NOZORDER | SWP_HIDEWINDOW); + } + return; + } + + hwndCtrl = GetDlgItem(hwnd, IDC_CHK_EXPLORER_MENU); + if (hwndCtrl) + { + GetWindowRect(hwndCtrl, &rw); + MapWindowPoints(HWND_DESKTOP, hwnd, (POINT*)&rw, 2); + h = cy - (((rw.bottom - rw.top)*3) + 6); + r = max(0, (cx - (rw.right - rw.left))/2) + (rw.right - rw.left); + SetWindowPos(hwndCtrl, NULL, r - (rw.right - rw.left) - 12, + h, rw.right - rw.left + 26, + rw.bottom - rw.top, SWP_NOACTIVATE | SWP_NOZORDER); + + } + hwndCtrl = GetDlgItem(hwnd, IDC_CHK_AGENT); + if (hwndCtrl) + { + GetWindowRect(hwndCtrl, &rw); + MapWindowPoints(HWND_DESKTOP, hwnd, (POINT*)&rw, 2); + SetWindowPos(hwndCtrl, NULL, r - (rw.right - rw.left) - 12, + h + (rw.bottom - rw.top) + 2, + rw.right - rw.left + 26, + rw.bottom - rw.top, SWP_NOACTIVATE | SWP_NOZORDER); + } + hwndCtrl = GetDlgItem(hwnd, IDC_LBL_AGENT_DESC); + if (hwndCtrl) + { + GetWindowRect(hwndCtrl, &rw); + MapWindowPoints(HWND_DESKTOP, hwnd, (POINT*)&rw, 2); + SetWindowPos(hwndCtrl, NULL, r - (rw.right - rw.left) - 12, + h + (rw.bottom - rw.top)*2 + 2, + rw.right - rw.left + 26, + rw.bottom - rw.top, SWP_NOACTIVATE | SWP_NOZORDER); + } + hwndCtrl = GetDlgItem(hwnd, IDC_TREE_TYPES); + if (hwndCtrl) + { + GetWindowRect(hwndCtrl, &rw); + MapWindowPoints(HWND_DESKTOP, hwnd, (POINT*)&rw, 2); + SetWindowPos(hwndCtrl, NULL, r - (rw.right - rw.left) - 12, + rw.top, rw.right - rw.left + 26, + h - rw.top - 4, SWP_NOACTIVATE | SWP_NOZORDER); + } +} + +void setup_page_assoc::OnCommand(INT nCtrlID, INT nEvntID, HWND hwndCtrl) +{ + switch(nCtrlID) + { + case IDC_CHK_EXPLORER_MENU: + { + switch (nEvntID) + { + case BN_CLICKED: + bExplorerMenu = (BST_CHECKED == (BST_CHECKED & (INT)SendMessageW(hwndCtrl, BM_GETSTATE, 0, 0L))); + break; + } + break; + } + case IDC_CHK_AGENT: + { + switch (nEvntID) + { + case BN_CLICKED: + bAgent = (BST_CHECKED == (BST_CHECKED & (INT)SendMessageW(hwndCtrl, BM_GETSTATE, 0, 0L))); + break; + } + break; + } + case IDC_CHK_CD: + { + switch (nEvntID) + { + case BN_CLICKED: + bRegCD = (BST_CHECKED == (BST_CHECKED & (INT)SendMessageW(hwndCtrl, BM_GETSTATE, 0, 0L))); + break; + } + break; + } + } +} + +BOOL setup_page_assoc::OnNotify(INT nCtrlID, NMHDR *pnmh, LRESULT *pResult) +{ + switch(nCtrlID) + { + case IDC_TREE_TYPES: + switch(pnmh->code) + { + case NM_CUSTOMDRAW: *pResult = TreeView_OnCustomDraw((NMTVCUSTOMDRAW*)pnmh); return TRUE; + case NM_CLICK: *pResult = TreeView_OnClick(pnmh); return TRUE; + case TVN_KEYDOWN: *pResult = TreeView_OnKeyDown((NMTVKEYDOWN*)pnmh); return TRUE; + } + } + return FALSE; +} + +INT_PTR setup_page_assoc::PageDlgProc(UINT uMsg, WPARAM wParam, LPARAM lParam) +{ + switch(uMsg) + { + case WM_INITDIALOG: return OnInitDialog((HWND)wParam, lParam); + case WM_DESTROY: OnDestroy(); break; + case WM_SIZE: OnSize((UINT)wParam, LOWORD(lParam), HIWORD(lParam)); break; + case WM_COMMAND: OnCommand(LOWORD(wParam), HIWORD(wParam), (HWND)lParam); break; + case WM_NOTIFY: + { + LRESULT result = 0; + if (OnNotify((INT)wParam, (NMHDR*)lParam, &result)) + { + SetWindowLongPtrW(hwnd, DWLP_MSGRESULT, (LONGX86)(LONG_PTR)result); + return TRUE; + } + } + break; + } + return 0; +} + +static INT_PTR WINAPI DialogProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam) +{ + setup_page_assoc *pInst = (setup_page_assoc*)GetPropW(hwnd, L"SETUPPAGE"); + + switch(uMsg) + { + case WM_INITDIALOG: + pInst = (setup_page_assoc*)lParam; + if (pInst) + { + pInst->hwnd = hwnd; + SetPropW(hwnd, L"SETUPPAGE", pInst); + } + break; + + case WM_DESTROY: + if (pInst) + { + pInst->PageDlgProc(uMsg, wParam, lParam); + RemovePropW(hwnd, L"SETUPPAGE"); + pInst = NULL; + } + break; + } + + return (pInst) ? pInst->PageDlgProc(uMsg, wParam, lParam) : 0; +} + +static void TreeViewCheckItems(HWND hwnd, TVITEMW *pItem) +{ + while (pItem->hItem) + { + SendMessageW(hwnd, TVM_SETITEMW, 0, (LPARAM)pItem); + HTREEITEM hChild = (HTREEITEM)SendMessageW(hwnd, TVM_GETNEXTITEM, (WPARAM)TVGN_CHILD, (LPARAM)pItem->hItem); + if (hChild) + { + HTREEITEM hTemp = pItem->hItem; + pItem->hItem = hChild; + TreeViewCheckItems(hwnd, pItem); + pItem->hItem = hTemp; + } + pItem->hItem = (HTREEITEM)SendMessageW(hwnd, TVM_GETNEXTITEM , TVGN_NEXT, (LPARAM)pItem->hItem); + } +} + +static LRESULT WINAPI TreeViewProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam) +{ + WNDPROC fnOldProc = (WNDPROC)GetPropW(hwnd, L"TVPROC"); + if (!fnOldProc) return DefWindowProcW(hwnd, uMsg, wParam, lParam); + switch(uMsg) + { + case WM_DESTROY: + RemovePropW(hwnd, L"TVPROC"); + SetWindowLongPtrW(hwnd, GWLP_WNDPROC, (LONGX86)(LONG_PTR)fnOldProc); + break; + + case WM_CHAR: + if (0x01/*(CTRL_A)*/ == wParam) + { + TVITEMW item = {0}; + item.mask = TVIF_HANDLE | TVIF_STATE; + item.stateMask = TVIS_STATEIMAGEMASK; + item.state = INDEXTOSTATEIMAGEMASK(2); + item.hItem = (HTREEITEM)SendMessageW(hwnd, TVM_GETNEXTITEM , TVGN_ROOT, 0L); + SendMessageW(hwnd, WM_SETREDRAW, FALSE, 0L); + TreeViewCheckItems(hwnd, &item); + SendMessageW(hwnd, WM_SETREDRAW, TRUE, 0L); + return 0; + } + break; + } + return CallWindowProcW(fnOldProc, hwnd, uMsg, wParam, lParam); +} + +#ifdef CBCLASS +#undef CBCLASS +#endif + +#define CBCLASS setup_page_assoc +START_DISPATCH +CB(ADDREF, AddRef) +CB(RELEASE, Release) +CB(API_SETUPPAGE_GET_NAME, GetName) +CB(API_SETUPPAGE_CREATEVIEW, CreateView) +CB(API_SETUPPAGE_SAVE, Save) +CB(API_SETUPPAGE_REVERT, Revert) +CB(API_SETUPPAGE_ISDIRTY, IsDirty) +CB(API_SETUPPAGE_VALIDATE, Validate) +END_DISPATCH +#undef CBCLASS
\ No newline at end of file diff --git a/Src/Winamp/setup/spage_assoc.h b/Src/Winamp/setup/spage_assoc.h new file mode 100644 index 00000000..f18270b8 --- /dev/null +++ b/Src/Winamp/setup/spage_assoc.h @@ -0,0 +1,57 @@ +#ifndef WINAMP_ASSOCIATIONS_SETUP_PAGE_HEADER +#define WINAMP_ASSOCIATIONS_SETUP_PAGE_HEADER + +#include "./ifc_setuppage.h" +#include <commctrl.h> + +#define TYPE_CATEGORIES_NUM 5 + +class setup_page_assoc : public ifc_setuppage +{ +public: + setup_page_assoc(); + virtual ~setup_page_assoc(); + +public: + size_t AddRef(); + size_t Release(); + HRESULT GetName(bool bShort, const wchar_t **pszName); + HRESULT Save(HWND hwndText); + HRESULT CreateView(HWND hwndParent, HWND *phwnd); + HRESULT Revert(void); + HRESULT IsDirty(void); + HRESULT Validate(void); + +protected: + INT_PTR PageDlgProc(UINT uMsg, WPARAM wParam, LPARAM lParam); + INT_PTR OnInitDialog(HWND hwndFocus, LPARAM lParam); + void OnDestroy(void); + void OnSize(UINT nType, INT cx, INT cy); + void OnCommand(INT nCtrlID, INT nEvntID, HWND hwndCtrl); + BOOL OnNotify(INT nCtrlID, NMHDR *pnmh, LRESULT *pResult); + + BOOL TreeView_OnClick(NMHDR *pnmh); + void TreeView_OnItemStateClick(HWND hwndTree, HTREEITEM hItem); + BOOL TreeView_OnKeyDown(NMTVKEYDOWN *ptvkd); + INT TreeView_OnCustomDraw(NMTVCUSTOMDRAW *ptvcd); + + void UpdateUI(void); + +private: + size_t ref; + HWND hwnd; + wchar_t *pszTypes; + WORD *pMeta; + BYTE expanded[TYPE_CATEGORIES_NUM]; + wchar_t szTopExt[32]; + wchar_t szCaretExt[32]; + BOOL bRegCD; + BOOL bAgent; + BOOL bExplorerMenu; + +protected: + friend static INT_PTR WINAPI DialogProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam); + RECVS_DISPATCH; +}; + +#endif //WINAMP_ASSOCIATIONS_SETUP_PAGE_HEADER
\ No newline at end of file diff --git a/Src/Winamp/setup/spage_connect.cpp b/Src/Winamp/setup/spage_connect.cpp new file mode 100644 index 00000000..af0e84cc --- /dev/null +++ b/Src/Winamp/setup/spage_connect.cpp @@ -0,0 +1,313 @@ +#define APSTUDIO_READONLY_SYMBOLS +#include "main.h" +#include "./spage_connect.h" +#include "./setup_resource.h" +#include "../nu/ns_wc.h" +#include "./langutil.h" + +setup_page_connect::setup_page_connect() : ref(1), hwnd(NULL) +{ + inetMode = 0; + bPort80 = FALSE; + szProxy[MAX_PATH] = 0x00; +} +setup_page_connect::~setup_page_connect() +{ +} + +size_t setup_page_connect::AddRef() +{ + return ++ref; +} + +size_t setup_page_connect::Release() +{ + if (1 == ref) + { + delete(this); + return 0; + } + return --ref; +} + +HRESULT setup_page_connect::GetName(bool bShort, const wchar_t **pszName) +{ + static wchar_t szName[64] = {0,}; + *pszName = (*szName) ? szName : getStringW(IDS_PAGE_CONNECTIVITY, szName, sizeof(szName)/sizeof(wchar_t)); + return S_OK; +} + +HRESULT setup_page_connect::Save(HWND hwndText) +{ + HRESULT hr(S_OK); + INT count; + wchar_t app[MAX_PATH] = {0}, *p; + + if (S_FALSE == IsDirty()) return S_OK; + + count = MultiByteToWideCharSZ(CP_ACP, 0, app_name, -1, app, sizeof(app)/sizeof(wchar_t)); + if (!count) hr = S_FALSE; + if (S_FALSE == hr) return hr; + + if (config_inet_mode != inetMode) + { + wchar_t szText[MAX_PATH] = {0}; + config_inet_mode = (char)inetMode; + WritePrivateProfileStringW(app, L"inet_mode", _itow(inetMode, szText, 10), INI_FILE); + } + + if (2 == inetMode) szProxy[0] = 0x00; + if (0 == *szProxy) config_proxy[0] = 0x00; + else + { + count = WideCharToMultiByteSZ(CP_ACP, 0, szProxy, -1, config_proxy, sizeof(config_proxy)/sizeof(char), NULL, NULL); + if (!count) hr = S_FALSE; + } + if (!WritePrivateProfileStringW(app, L"Proxy", szProxy, INI_FILE)) hr = S_FALSE; + if (bPort80 && 0x00 == *szProxy) bPort80 = FALSE; + p = (bPort80) ? L"1" : L""; + if (!WritePrivateProfileStringW(app, L"proxyonly80", p, INI_FILE)) hr = S_FALSE; + WritePrivateProfileStringW(app, L"proxy80", p, INI_FILE); // old + + if (hwnd) UpdateUI(); + return hr; +} + +HRESULT setup_page_connect::Revert(void) +{ + HRESULT hr(S_OK); + INT count; + wchar_t app[MAX_PATH] = {0}; + + count = MultiByteToWideCharSZ(CP_ACP, 0, app_name, -1, app, sizeof(app)/sizeof(wchar_t)); + if (!count) hr = S_FALSE; + + if (config_inet_mode==3) isInetAvailable(); // autodetect + inetMode = config_inet_mode; + + if (*config_proxy && 2 != inetMode) + { + count = MultiByteToWideCharSZ(CP_ACP, 0, config_proxy, -1, szProxy, sizeof(szProxy)/sizeof(wchar_t)); + if (!count) hr = S_FALSE; + } + else szProxy[0] = 0x00; + + bPort80 = (0x00 != *szProxy && 0 != GetPrivateProfileIntW(app, L"proxyonly80", 0, INI_FILE)); + + if (hwnd) UpdateUI(); + + return hr; +} + +HRESULT setup_page_connect::IsDirty(void) +{ + INT res; + wchar_t app[MAX_PATH] = {0}; + char szTest[MAX_PATH] = {0}; + + if (inetMode != config_inet_mode) return S_OK; + + if (2 == inetMode || 0 == *szProxy) szTest[0] = 0x00; + else + { + res = WideCharToMultiByteSZ(CP_ACP, 0, szProxy, -1, szTest, sizeof(szTest)/sizeof(char), NULL, NULL); + if (!res) return E_OUTOFMEMORY; + } + + res = CompareStringA(MAKELCID(MAKELANGID(LANG_ENGLISH, SUBLANG_ENGLISH_US), SORT_DEFAULT), + NORM_IGNORECASE, szTest, -1, config_proxy, -1); + if (0 == res) return E_UNEXPECTED; + if (CSTR_EQUAL != res) return S_OK; + + res = MultiByteToWideCharSZ(CP_ACP, 0, app_name, -1, app, sizeof(app)/sizeof(wchar_t)); + if (!res) return E_OUTOFMEMORY; + + return ((bPort80 && 0x00 != *szProxy) != ( 0 != GetPrivateProfileIntW(app, L"proxyonly80", 0, INI_FILE))) ? S_OK : S_FALSE; +} + +HRESULT setup_page_connect::Validate(void) +{ + return S_OK; +} + +HRESULT setup_page_connect::CreateView(HWND hwndParent, HWND *phwnd) +{ + *phwnd = WACreateDialogParam(MAKEINTRESOURCEW(IDD_SETUP_PAGE_CONNECT), hwndParent, ::DialogProc, (LPARAM)this); + return S_OK; +} + +void setup_page_connect::UpdateUI(void) +{ + int count; + + if (!hwnd || !IsWindow(hwnd)) return; + + CheckDlgButton(hwnd, IDC_CHK_PORT80, (bPort80) ? BST_CHECKED : BST_UNCHECKED); + SetDlgItemTextW(hwnd, IDC_EDT_SERVER, szProxy); + + HWND hwndCB = GetDlgItem(hwnd, IDC_CB_CONNECT); + if (!hwndCB || !IsWindow(hwndCB)) return; + + count = (INT)SendMessageW(hwndCB, CB_GETCOUNT, 0, 0L); + if (count > 0) + { + int index; + for (index = 0; index < count && inetMode != (INT)SendMessageW(hwndCB, CB_GETITEMDATA, index, 0L); index++); + if (index == count) + { + inetMode = (INT)SendMessageW(hwndCB, CB_GETITEMDATA, 0, 0L); + index = 0; + } + SendMessageW(hwndCB, CB_SETCURSEL, index, 0L); + PostMessageW(hwnd, WM_COMMAND, MAKEWPARAM(IDC_CB_CONNECT, CBN_SELCHANGE), (LPARAM)hwndCB); + } +} + +void setup_page_connect::ComboBox_OnSelChange(HWND hwndCtrl) +{ + INT proxyList[] = { IDC_GRP_PROXY, IDC_LBL_SERVER, IDC_EDT_SERVER, IDC_CHK_PORT80, }; + INT index; + + index = (INT)SendMessageW(hwndCtrl, CB_GETCURSEL, 0, 0L); + if (CB_ERR == index) return; + + inetMode = (INT)SendMessageW(hwndCtrl, CB_GETITEMDATA, index, 0L); + + for (int i = 0; i < sizeof(proxyList)/sizeof(INT); i++) + { + HWND hwndItem = GetDlgItem(hwnd, proxyList[i]); + if (IsWindow(hwndItem)) ShowWindow(hwndItem, (2 != inetMode) ? SW_SHOWNA : SW_HIDE); + } +} + +INT_PTR setup_page_connect::OnInitDialog(HWND hwndFocus, LPARAM lParam) +{ + UINT connID[] = { IDS_INST_INET1, IDS_INST_INET2, IDS_INST_INET3, }; + HWND hwndCB = GetDlgItem(hwnd, IDC_CB_CONNECT); + + CheckDlgButton(hwnd, IDC_CHK_PORT80, (bPort80) ? BST_CHECKED : BST_UNCHECKED); + //SendDlgItemMessageW(hwnd, IDC_EDT_SERVER, EM_LIMITTEXT, sizeof(szProxy)/sizeof(wchar_t), 0); + SetDlgItemTextW(hwnd, IDC_EDT_SERVER, szProxy); + + if (inetMode < 0) inetMode = 0; + else if (inetMode >= sizeof(connID)/sizeof(INT)) inetMode = sizeof(connID)/sizeof(INT) - 1; + + for(int i = 0; i < sizeof(connID)/sizeof(INT); i++) + { + INT index = (INT)SendMessageW(hwndCB, CB_ADDSTRING,0, (LPARAM)getStringW(connID[i], NULL, 0)); + if (CB_ERR != index) SendMessageW(hwndCB, CB_SETITEMDATA, index, (LPARAM)i); + if (inetMode == i) SendMessageW(hwndCB, CB_SETCURSEL, index, 0L); + } + + PostMessageW(hwnd, WM_COMMAND, MAKEWPARAM(IDC_CB_CONNECT, CBN_SELCHANGE), (LPARAM)hwndCB); + + return 0; +} + +void setup_page_connect::OnSize(UINT nType, INT cx, INT cy) +{ + INT ctrlList[] = { IDC_CB_CONNECT, IDC_GRP_PROXY, IDC_LBL_SERVER, IDC_EDT_SERVER, IDC_CHK_PORT80, }; + RECT rw; + HDWP hdwp = BeginDeferWindowPos(sizeof(ctrlList)/sizeof(INT)); + if (!hdwp) return; + + for (int i = 0; i < sizeof(ctrlList)/sizeof(INT); i++) + { + HWND hwndCtrl = GetDlgItem(hwnd, ctrlList[i]); + if (hwndCtrl) + { + GetWindowRect(hwndCtrl, &rw); + MapWindowPoints(HWND_DESKTOP, hwnd, (POINT*)&rw, 2); + hdwp = DeferWindowPos(hdwp, hwndCtrl, NULL, max(0, (cx - (rw.right - rw.left))/2), rw.top, 0, 0, SWP_NOACTIVATE | SWP_NOZORDER | SWP_NOSIZE); + } + } + if (hdwp) EndDeferWindowPos(hdwp); +} + +void setup_page_connect::OnCommand(INT nCtrlID, INT nEvntID, HWND hwndCtrl) +{ + switch(nCtrlID) + { + case IDC_CB_CONNECT: + switch(nEvntID) + { + case CBN_SELCHANGE: ComboBox_OnSelChange(hwndCtrl); break; + } + break; + case IDC_EDT_SERVER: + switch(nEvntID) + { + case EN_CHANGE: + GetWindowTextW(hwndCtrl, szProxy, sizeof(szProxy)/sizeof(wchar_t)); + EnableWindow(GetDlgItem(hwnd, IDC_CHK_PORT80), 0x00 != *szProxy); + if(0x00 == *szProxy) + { + CheckDlgButton(hwnd, IDC_CHK_PORT80, BST_UNCHECKED); + PostMessageW(hwnd, WM_COMMAND, MAKEWPARAM(IDC_CHK_PORT80, BN_CLICKED), (LPARAM)GetDlgItem(hwnd, IDC_CHK_PORT80)); + } + break; + } + break; + case IDC_CHK_PORT80: + switch(nEvntID) + { + case BN_CLICKED: bPort80 = (BST_CHECKED & (INT)SendMessageW(hwndCtrl, BM_GETSTATE, 0, 0L)); break; + } + break; + } +} + +INT_PTR setup_page_connect::PageDlgProc(UINT uMsg, WPARAM wParam, LPARAM lParam) +{ + switch(uMsg) + { + case WM_INITDIALOG: return OnInitDialog((HWND)wParam, lParam); + case WM_DESTROY: break; + case WM_SIZE: OnSize((UINT)wParam, LOWORD(lParam), HIWORD(lParam)); break; + case WM_COMMAND: OnCommand(LOWORD(wParam), HIWORD(wParam), (HWND)lParam); break; + } + return 0; +} + +static INT_PTR WINAPI DialogProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam) +{ + setup_page_connect *pInst = (setup_page_connect*)GetPropW(hwnd, L"SETUPPAGE"); + + switch(uMsg) + { + case WM_INITDIALOG: + pInst = (setup_page_connect*)lParam; + if (pInst) + { + pInst->hwnd = hwnd; + SetPropW(hwnd, L"SETUPPAGE", pInst); + } + break; + case WM_DESTROY: + if (pInst) + { + pInst->PageDlgProc(uMsg, wParam, lParam); + RemovePropW(hwnd, L"SETUPPAGE"); + pInst = NULL; + } + break; + } + return (pInst) ? pInst->PageDlgProc(uMsg, wParam, lParam) : 0; +} + +#ifdef CBCLASS +#undef CBCLASS +#endif + +#define CBCLASS setup_page_connect +START_DISPATCH +CB(ADDREF, AddRef) +CB(RELEASE, Release) +CB(API_SETUPPAGE_GET_NAME, GetName) +CB(API_SETUPPAGE_CREATEVIEW, CreateView) +CB(API_SETUPPAGE_SAVE, Save) +CB(API_SETUPPAGE_REVERT, Revert) +CB(API_SETUPPAGE_ISDIRTY, IsDirty) +CB(API_SETUPPAGE_VALIDATE, Validate) +END_DISPATCH +#undef CBCLASS
\ No newline at end of file diff --git a/Src/Winamp/setup/spage_connect.h b/Src/Winamp/setup/spage_connect.h new file mode 100644 index 00000000..c4af10d7 --- /dev/null +++ b/Src/Winamp/setup/spage_connect.h @@ -0,0 +1,45 @@ +#ifndef WINAMP_CONNECTIOVITY_SETUP_PAGE_HEADER +#define WINAMP_CONNECTIOVITY_SETUP_PAGE_HEADER + +#include "./ifc_setuppage.h" + +class setup_page_connect : public ifc_setuppage +{ + +public: + setup_page_connect(); + virtual ~setup_page_connect(); + +public: + size_t AddRef(); + size_t Release(); + HRESULT GetName(bool bShort, const wchar_t **pszName); + HRESULT Save(HWND hwndText); + HRESULT CreateView(HWND hwndParent, HWND *phwnd); + HRESULT Revert(void); + HRESULT IsDirty(void); + HRESULT Validate(void); +protected: + INT_PTR PageDlgProc(UINT uMsg, WPARAM wParam, LPARAM lParam); + INT_PTR OnInitDialog(HWND hwndFocus, LPARAM lParam); + void OnSize(UINT nType, INT cx, INT cy); + void OnCommand(INT nCtrlID, INT nEvntID, HWND hwndCtrl); + + void ComboBox_OnSelChange(HWND hwndCtrl); + + void UpdateUI(void); + +private: + size_t ref; + HWND hwnd; + INT inetMode; + BOOL bPort80; + WCHAR szProxy[MAX_PATH]; + +protected: + friend static INT_PTR WINAPI DialogProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam); + RECVS_DISPATCH; +}; + + +#endif //WINAMP_CONNECTIOVITY_SETUP_PAGE_HEADER
\ No newline at end of file diff --git a/Src/Winamp/setup/spage_feedback.cpp b/Src/Winamp/setup/spage_feedback.cpp new file mode 100644 index 00000000..4a2515e4 --- /dev/null +++ b/Src/Winamp/setup/spage_feedback.cpp @@ -0,0 +1,392 @@ +#define APSTUDIO_READONLY_SYMBOLS +#include "main.h" +#include "./spage_feedback.h" +#include "./setup_resource.h" +#include "../nu/ns_wc.h" +#include "../nu/AutoChar.h" +#include "../nu/AutoWide.h" +#include "./langutil.h" + + +#define FF_ALLOWFEEDBACK 0x0001 +#define FF_ANNOUNCEMENTS 0x0010 +#define FF_STATISTICS 0x0020 + +#define GENDER_UNKNOWN 0 +#define GENDER_MALE 1 +#define GENDER_FEMALE 2 + +setup_page_feedback::setup_page_feedback() : ref(1), hwnd(NULL) +{ + szEmail[0] = 0x00; + szCountry[0] = 0x00; + gender = GENDER_UNKNOWN; + flags = FF_ALLOWFEEDBACK | FF_ANNOUNCEMENTS | FF_STATISTICS; +} + +setup_page_feedback::~setup_page_feedback() +{ +} + +size_t setup_page_feedback::AddRef() +{ + return ++ref; +} + +size_t setup_page_feedback::Release() +{ + if (1 == ref) + { + delete(this); + return 0; + } + return --ref; +} + +HRESULT setup_page_feedback::GetName(bool bShort, const wchar_t **pszName) +{ + if (bShort) + { + static wchar_t szShortName[32] = {0}; + *pszName = (*szShortName) ? szShortName : getStringW(IDS_PAGE_FEEDBACK, szShortName, sizeof(szShortName)/sizeof(wchar_t)); + } + else + { + static wchar_t szLongName[64] = {0}; + *pszName = (*szLongName) ? szLongName : getStringW(IDS_PAGE_FEEDBACK_LONG, szLongName, sizeof(szLongName)/sizeof(wchar_t)); + } + return S_OK; +} + +HRESULT setup_page_feedback::Save(HWND hwndText) +{ + HRESULT hr(S_OK); + + int r, s; + char data[8192] = {0}; + char str[32] = {0}; + + if (FF_ALLOWFEEDBACK & flags) + { + s = GetPrivateProfileIntW(L"WinampReg", L"RegDataLen", 0, INI_FILE); + if (s > 0) GetPrivateProfileStructA("WinampReg", "RegData2", data, s, INI_FILEA); + if (!SetMetricsValueW(data, MAKEINTRESOURCEA(METRICS_EMAIL), szEmail, -1)) hr = E_UNEXPECTED; + if (!SetMetricsValueW(data, MAKEINTRESOURCEA(METRICS_COUNTRY), szCountry, lstrlenW(szCountry)*sizeof(wchar_t))) hr = E_UNEXPECTED; + if (!SetMetricsValueW(data, MAKEINTRESOURCEA(METRICS_GENDER), &gender, sizeof(gender))) hr = E_UNEXPECTED; + r = (FF_ANNOUNCEMENTS == (FF_ANNOUNCEMENTS & flags)); + if (!SetMetricsValueW(data, MAKEINTRESOURCEA(METRICS_ANNOUNCEMENTS), &r, sizeof(r))) hr = E_UNEXPECTED; + config_newverchk2 = (FF_STATISTICS == (FF_STATISTICS & flags)); + } + else config_newverchk2 = 0; + + WritePrivateProfileStringW(AutoWide(app_name), L"newverchk2", (config_newverchk2) ? L"1" : L"0", INI_FILE); + + s = GetMetricsSize(data); + + StringCchPrintfA(str, 32, "%d", s); + WritePrivateProfileStringA("WinampReg", "RegDataLen", (s) ? str : NULL, INI_FILEA); + WritePrivateProfileStructA("WinampReg", "RegData2", (s) ? data : NULL, s, INI_FILEA); + + if (hwnd) UpdateUI(); + return hr; +} + +HRESULT setup_page_feedback::Revert(void) +{ + HRESULT hr(S_OK); + char data[8192] = {0, }; + DWORD sendinfo; + + flags = FF_ALLOWFEEDBACK; + + if (config_newverchk2) flags |= FF_STATISTICS; + + int s = GetPrivateProfileIntW(L"WinampReg", L"RegDataLen", 0, INI_FILE); + if (s > 0) GetPrivateProfileStructA("WinampReg", "RegData2", data, s, INI_FILEA); + + GetMetricsValueW(data, MAKEINTRESOURCEA(METRICS_EMAIL), szEmail, sizeof(szEmail)); + GetMetricsValueW(data, MAKEINTRESOURCEA(METRICS_COUNTRY), szCountry, sizeof(szCountry)); + GetMetricsValueW(data, MAKEINTRESOURCEA(METRICS_GENDER), &gender, sizeof(gender)); + GetMetricsValueW(data, MAKEINTRESOURCEA(METRICS_ANNOUNCEMENTS), &sendinfo, sizeof(sendinfo)); + if (sendinfo) flags |= FF_ANNOUNCEMENTS; + if (hwnd) UpdateUI(); + return hr; +} + +HRESULT setup_page_feedback::IsDirty(void) +{ + char data[8192] = {0}; + wchar_t szTest[256] = {0}; + int r; + DWORD lcid; + + lcid = MAKELCID(MAKELANGID(LANG_ENGLISH, SUBLANG_ENGLISH_US), SORT_DEFAULT); + if (0 != (FF_STATISTICS & flags) != !!config_newverchk2) return S_OK; + + int s = GetPrivateProfileIntW(L"WinampReg", L"RegDataLen", 0, INI_FILE); + if (s > 0) GetPrivateProfileStructA("WinampReg", "RegData2", data, s, INI_FILEA); + + if (!GetMetricsValueW(data, MAKEINTRESOURCEA(METRICS_EMAIL), szTest, sizeof(szTest))) return E_UNEXPECTED; + r = CompareStringW(lcid, NORM_IGNORECASE, szTest, -1, szEmail, -1); + if (0 == r) return E_UNEXPECTED; + if (CSTR_EQUAL != r) return S_OK; + + if (!GetMetricsValueW(data, MAKEINTRESOURCEA(METRICS_COUNTRY), szTest, sizeof(szTest))) return E_UNEXPECTED; + r = CompareStringW(lcid, NORM_IGNORECASE, szTest, -1, szCountry, -1); + if (0 == r) return E_UNEXPECTED; + if (CSTR_EQUAL != r) return S_OK; + r = 0; + if (!GetMetricsValueW(data, MAKEINTRESOURCEA(METRICS_GENDER), &r, sizeof(r))) return E_UNEXPECTED; + if (r != gender) return S_OK; + r = 0; + if (!GetMetricsValueW(data, MAKEINTRESOURCEA(METRICS_ANNOUNCEMENTS), &r, sizeof(r))) return E_UNEXPECTED; + if (r != (FF_ANNOUNCEMENTS == (FF_ANNOUNCEMENTS & flags))) return S_OK; + + return S_FALSE; +} + +HRESULT setup_page_feedback::Validate(void) +{ + wchar_t *p; + + if (0 == (FF_ALLOWFEEDBACK & flags) || !*szEmail) return S_OK; + for (p = szEmail; *p != 0x00 && *p != L'@'; p = CharNextW(p)); + + if (L'@' != *p || 0x00 == *CharNextW(p)) + { + WCHAR szTitle[128] = {0}; + HWND hwndTop, hwndTest; + hwndTop = hwnd; + while(NULL != (hwndTest = GetParent(hwndTop))) hwndTop = hwndTest; + GetWindowTextW(hwndTop, szTitle, sizeof(szTitle)/sizeof(WCHAR)); + if (hwndTop) + { + MessageBoxW(hwndTop, getStringW(IDS_PAGE_INCORRECT_EMAIL_ADDRESS, NULL, 0), + szTitle, MB_OK | MB_ICONERROR); + return S_FALSE; + } + } + return S_OK; +} + +HRESULT setup_page_feedback::CreateView(HWND hwndParent, HWND *phwnd) +{ + *phwnd = WACreateDialogParam(MAKEINTRESOURCEW(IDD_SETUP_PAGE_FEEDBACK), hwndParent, ::DialogProc, (LPARAM)this); + return S_OK; +} + +void setup_page_feedback::UpdateUI(void) +{ + + HWND hwndCB; + if (!hwnd || !IsWindow(hwnd)) return; + + CheckDlgButton(hwnd, IDC_CHK_ANNOUNCEMENTS, (FF_ANNOUNCEMENTS & flags) ? BST_CHECKED : BST_UNCHECKED); + CheckDlgButton(hwnd, IDC_CHK_STATISTICS, (FF_STATISTICS & flags) ? BST_CHECKED : BST_UNCHECKED); + + SetDlgItemTextW(hwnd, IDC_EDT_EMAIL, szEmail); + SetDlgItemTextW(hwnd, IDC_EDT_COUNTRY, szCountry); + + hwndCB = GetDlgItem(hwnd, IDC_CB_GENDER); + if (hwndCB) + { + INT count = (INT)SendMessageW(hwndCB, CB_GETCOUNT, 0, 0L); + if (count > 0) + { + INT i; + for (i = 0; i < count && gender != (INT)SendMessageW(hwndCB, CB_GETITEMDATA, i, 0L); i++); + if (i != count) SendMessageW(hwndCB, CB_SETCURSEL, i, 0L); + } + } +} + + +void setup_page_feedback::ComboBox_OnSelChange(HWND hwndCtrl) +{ + INT index; + index = (INT)SendMessageW(hwndCtrl, CB_GETCURSEL, 0, 0L); + if (CB_ERR == index) return; + gender = (INT)SendMessageW(hwndCtrl, CB_GETITEMDATA, index, 0L); +} + +INT_PTR setup_page_feedback::OnInitDialog(HWND hwndFocus, LPARAM lParam) +{ + HWND hwndCB; + + SendDlgItemMessageW(hwnd, IDC_EDT_EMAIL, EM_LIMITTEXT, sizeof(szEmail)/sizeof(wchar_t), 0); + SendDlgItemMessageW(hwnd, IDC_EDT_COUNTRY, EM_LIMITTEXT, sizeof(szCountry)/sizeof(wchar_t), 0); + + hwndCB = GetDlgItem(hwnd, IDC_CB_GENDER); + if (hwndCB) + { + UINT genderStrID[] = {IDS_GENDER_UNKNOWN, IDS_GENDER_FEMALE, IDS_GENDER_MALE, }; + INT genderVal[] = {GENDER_UNKNOWN, GENDER_FEMALE, GENDER_MALE, }; + for(int i = 0; i < sizeof(genderStrID)/sizeof(UINT); i++) + { + INT index = (INT)SendMessageW(hwndCB, CB_ADDSTRING,0, (LPARAM)getStringW(genderStrID[i], NULL, 0)); + if (CB_ERR != index) SendMessageW(hwndCB, CB_SETITEMDATA, index, (LPARAM)genderVal[i]); + } + } + + UpdateUI(); + return 0; +} + +void setup_page_feedback::OnSize(UINT nType, INT cx, INT cy) +{ + INT ctrlList[] = { IDC_LBL_HEADER, IDC_CHK_ANNOUNCEMENTS, IDC_CHK_STATISTICS, + IDC_EDT_EMAIL, IDC_EDT_COUNTRY, IDC_CB_GENDER, }; + HWND hwndCtrl; + HDWP hdwp; + RECT rw; + INT width, ox; + + hwndCtrl = GetDlgItem(hwnd, IDC_LBL_EMAIL); + GetWindowRect(hwndCtrl, &rw); + MapWindowPoints(HWND_DESKTOP, hwnd, (POINT*)&rw, 2); + ox = rw.left; + + hdwp = BeginDeferWindowPos(sizeof(ctrlList)/sizeof(INT)); + if (!hdwp) return; + + for (int i = 0; i < sizeof(ctrlList)/sizeof(INT); i++) + { + hwndCtrl = GetDlgItem(hwnd, ctrlList[i]); + if (hwndCtrl) + { + GetWindowRect(hwndCtrl, &rw); + MapWindowPoints(HWND_DESKTOP, hwnd, (POINT*)&rw, 2); + switch(ctrlList[i]) + { + case IDC_EDT_EMAIL: + case IDC_EDT_COUNTRY: + case IDC_CB_GENDER: + width = cx - rw.left - ox; + break; + default: + width = cx - rw.left*2; + break; + } + hdwp = DeferWindowPos(hdwp, hwndCtrl, NULL, 0, 0, width, rw.bottom - rw.top, + SWP_NOACTIVATE | SWP_NOZORDER | SWP_NOMOVE); + } + } + if (hdwp) EndDeferWindowPos(hdwp); +} + + +void setup_page_feedback::OnCommand(INT nCtrlID, INT nEvntID, HWND hwndCtrl) +{ + switch(nCtrlID) + { + case IDC_EDT_EMAIL: + switch(nEvntID) + { + case EN_CHANGE: + { + GetWindowTextW(hwndCtrl, szEmail, sizeof(szEmail)/sizeof(wchar_t)); + HWND hwndChk = GetDlgItem(hwnd, IDC_CHK_ANNOUNCEMENTS); + if (IsWindow(hwndChk)) + { + BOOL bEnabled = IsWindowEnabled(hwndChk); + if (bEnabled != (0x00 != *szEmail)) + { + CheckDlgButton(hwnd, IDC_CHK_ANNOUNCEMENTS, (0x00 != *szEmail) ? BST_CHECKED : BST_UNCHECKED); + EnableWindow(GetDlgItem(hwnd, IDC_CHK_ANNOUNCEMENTS), 0x00 != *szEmail); + PostMessageW(hwnd, WM_COMMAND, MAKEWPARAM(IDC_CHK_ANNOUNCEMENTS, BN_CLICKED), (LPARAM)GetDlgItem(hwnd, IDC_CHK_ANNOUNCEMENTS)); + } + } + } + break; + } + break; + case IDC_EDT_COUNTRY: + switch(nEvntID) + { + case EN_CHANGE: + GetWindowTextW(hwndCtrl, szCountry, sizeof(szCountry)/sizeof(wchar_t)); + break; + } + break; + case IDC_CHK_ANNOUNCEMENTS: + switch(nEvntID) + { + case BN_CLICKED: + if (BST_CHECKED & (INT)SendMessageW(hwndCtrl, BM_GETSTATE, 0, 0L)) flags |= FF_ANNOUNCEMENTS; + else flags &= ~FF_ANNOUNCEMENTS; + break; + } + break; + case IDC_CHK_STATISTICS: + switch(nEvntID) + { + case BN_CLICKED: + if (BST_CHECKED & (INT)SendMessageW(hwndCtrl, BM_GETSTATE, 0, 0L)) flags |= FF_STATISTICS; + else flags &= ~FF_STATISTICS; + break; + } + break; + case IDC_CB_GENDER: + switch(nEvntID) + { + case CBN_SELCHANGE: ComboBox_OnSelChange(hwndCtrl); break; + } + break; + } +} + +INT_PTR setup_page_feedback::PageDlgProc(UINT uMsg, WPARAM wParam, LPARAM lParam) +{ + switch(uMsg) + { + case WM_INITDIALOG: return OnInitDialog((HWND)wParam, lParam); + case WM_DESTROY: break; + case WM_SIZE: OnSize((UINT)wParam, LOWORD(lParam), HIWORD(lParam)); break; + case WM_COMMAND: OnCommand(LOWORD(wParam), HIWORD(wParam), (HWND)lParam); break; + } + return 0; +} + +static INT_PTR WINAPI DialogProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam) +{ + setup_page_feedback *pInst = (setup_page_feedback*)GetPropW(hwnd, L"SETUPPAGE"); + + switch(uMsg) + { + case WM_INITDIALOG: + pInst = (setup_page_feedback*)lParam; + if (pInst) + { + pInst->hwnd = hwnd; + SetPropW(hwnd, L"SETUPPAGE", pInst); + } + break; + case WM_DESTROY: + if (pInst) + { + pInst->PageDlgProc(uMsg, wParam, lParam); + RemovePropW(hwnd, L"SETUPPAGE"); + pInst = NULL; + } + break; + } + + return (pInst) ? pInst->PageDlgProc(uMsg, wParam, lParam) : 0; +} + +#ifdef CBCLASS +#undef CBCLASS +#endif + +#define CBCLASS setup_page_feedback +START_DISPATCH +CB(ADDREF, AddRef) +CB(RELEASE, Release) +CB(API_SETUPPAGE_GET_NAME, GetName) +CB(API_SETUPPAGE_CREATEVIEW, CreateView) +CB(API_SETUPPAGE_SAVE, Save) +CB(API_SETUPPAGE_REVERT, Revert) +CB(API_SETUPPAGE_ISDIRTY, IsDirty) +CB(API_SETUPPAGE_VALIDATE, Validate) +END_DISPATCH +#undef CBCLASS
\ No newline at end of file diff --git a/Src/Winamp/setup/spage_feedback.h b/Src/Winamp/setup/spage_feedback.h new file mode 100644 index 00000000..1ce53c13 --- /dev/null +++ b/Src/Winamp/setup/spage_feedback.h @@ -0,0 +1,45 @@ +#ifndef WINAMP_FEEDBACK_SETUP_PAGE_HEADER +#define WINAMP_FEEDBACK_SETUP_PAGE_HEADER + +#include "./ifc_setuppage.h" + +class setup_page_feedback : public ifc_setuppage +{ + +public: + setup_page_feedback(); + virtual ~setup_page_feedback(); + +public: + size_t AddRef(); + size_t Release(); + HRESULT GetName(bool bShort, const wchar_t **pszName); + HRESULT Save(HWND hwndText); + HRESULT CreateView(HWND hwndParent, HWND *phwnd); + HRESULT Revert(void); + HRESULT IsDirty(void); + HRESULT Validate(void); +protected: + INT_PTR PageDlgProc(UINT uMsg, WPARAM wParam, LPARAM lParam); + INT_PTR OnInitDialog(HWND hwndFocus, LPARAM lParam); + void OnSize(UINT nType, INT cx, INT cy); + void OnCommand(INT nCtrlID, INT nEvntID, HWND hwndCtrl); + + void ComboBox_OnSelChange(HWND hwndCtrl); + void UpdateUI(void); + +private: + size_t ref; + HWND hwnd; + WCHAR szEmail[MAX_PATH]; + WCHAR szCountry[MAX_PATH]; + INT gender; + DWORD flags; + +protected: + friend static INT_PTR WINAPI DialogProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam); + RECVS_DISPATCH; +}; + + +#endif //WINAMP_FEEDBACK_SETUP_PAGE_HEADER
\ No newline at end of file diff --git a/Src/Winamp/setup/spage_lang.cpp b/Src/Winamp/setup/spage_lang.cpp new file mode 100644 index 00000000..83282311 --- /dev/null +++ b/Src/Winamp/setup/spage_lang.cpp @@ -0,0 +1,293 @@ +#define APSTUDIO_READONLY_SYMBOLS +#include "main.h" +#include "./spage_lang.h" +#include "./setup_resource.h" +#include "../nu/ns_wc.h" +#include "./langutil.h" + +typedef struct _LANGREC +{ + LPWSTR pszFileName; + INT nType; +} LANGREC; + + +static BOOL CALLBACK AddLangToListBox(ENUMLANG *pel, LPVOID pUser); +static INT ListBox_FindLangFileIndex(HWND hwndLB, LPCWSTR pszLangPath); +static LPCWSTR ListBox_GetSelectedLang(HWND hwndLB, LPWSTR pszLangPath, INT cchLen); + + +setup_page_lang::setup_page_lang() : ref(1), hwnd(NULL) +{ + *szSelectionPath = 0x00; +} +setup_page_lang::~setup_page_lang() +{ +} + +size_t setup_page_lang::AddRef() +{ + return ++ref; +} + +size_t setup_page_lang::Release() +{ + if (1 == ref) + { + delete(this); + return 0; + } + return --ref; +} + +HRESULT setup_page_lang::GetName(bool bShort, const wchar_t **pszName) +{ + static wchar_t szName[64] = {0}; + *pszName = (*szName) ? szName : getStringW(IDS_PAGE_LANGUAGE, szName, sizeof(szName)/sizeof(wchar_t)); + return S_OK; +} + +HRESULT setup_page_lang::Save(HWND hwndText) +{ + if (S_FALSE == IsDirty()) return S_OK; + + if (!*szSelectionPath) *config_langpack = 0x00; + else + { + StringCbCopyW(config_langpack, sizeof(config_langpack), szSelectionPath); + } + config_save_langpack_var(); + return S_OK; +} + +HRESULT setup_page_lang::Revert(void) +{ + HRESULT hr(S_OK); + + if (*config_langpack) + { + StringCbCopyW(config_langpack, sizeof(szSelectionPath), config_langpack); + } + else szSelectionPath[0] = 0x00; + + if (hwnd) + { + HWND hwndLB = GetDlgItem(hwnd, IDC_LB_LANG); + INT index = ListBox_FindLangFileIndex(hwndLB, szSelectionPath); + if (LB_ERR == index && *szSelectionPath) index = ListBox_FindLangFileIndex(hwndLB, NULL); // find default embeded lang + SendMessageW(hwndLB, LB_SETCURSEL, (LB_ERR != index) ? index : 0, 0L); + } + return hr; +} + +HRESULT setup_page_lang::IsDirty(void) +{ + INT cr; + + cr = ComparePath(config_langpack, szSelectionPath, LANGDIR); + if (!cr) return E_UNEXPECTED; + + return (CSTR_EQUAL != cr) ? S_OK : S_FALSE; +} + +HRESULT setup_page_lang::Validate(void) +{ + return S_OK; +} + +HRESULT setup_page_lang::CreateView(HWND hwndParent, HWND *phwnd) +{ + *phwnd = WACreateDialogParam(MAKEINTRESOURCEW(IDD_SETUP_PAGE_LANG), hwndParent, ::DialogProc, (LPARAM)this); + return S_OK; +} + +void setup_page_lang::ListBox_OnSelChange(HWND hwndCtrl) +{ + ListBox_GetSelectedLang(hwndCtrl, szSelectionPath, sizeof(szSelectionPath)/sizeof(wchar_t)); +} + +void setup_page_lang::ListBox_OnItemDelete(DELETEITEMSTRUCT *pdis) +{ + LANGREC *pr = (LANGREC*)pdis->itemData; + if (pr) + { + if (pr->pszFileName) free(pr->pszFileName); + free(pr); + } +} + +INT_PTR setup_page_lang::OnInitDialog(HWND hwndFocus, LPARAM lParam) +{ + INT index; + HWND hwndLB; + hwndLB = GetDlgItem(hwnd, IDC_LB_LANG); + EnumerateLanguages(AddLangToListBox, hwndLB); + index = ListBox_FindLangFileIndex(hwndLB, szSelectionPath); + if (LB_ERR == index && *szSelectionPath) index = ListBox_FindLangFileIndex(hwndLB, NULL); // find default embeded lang + SendMessageW(hwndLB, LB_SETCURSEL, (LB_ERR != index) ? index : 0, 0L); + + PostMessageW(hwnd, WM_COMMAND, MAKEWPARAM(IDC_LB_LANG, LBN_SELCHANGE), (LPARAM)hwndLB); + return 0; +} + +void setup_page_lang::OnSize(UINT nType, INT cx, INT cy) +{ + HWND hwndCtrl; + RECT rw; + + hwndCtrl = GetDlgItem(hwnd, IDC_LBL_HEADER); + if (hwndCtrl) + { + GetWindowRect(hwndCtrl, &rw); + MapWindowPoints(HWND_DESKTOP, hwnd, (POINT*)&rw, 2); + SetWindowPos(hwndCtrl, NULL, 0, 0, cx - rw.left*2, rw.bottom - rw.top, SWP_NOACTIVATE | SWP_NOZORDER | SWP_NOMOVE); + } + hwndCtrl = GetDlgItem(hwnd, IDC_LB_LANG); + if (hwndCtrl) + { + + GetWindowRect(hwndCtrl, &rw); + MapWindowPoints(HWND_DESKTOP, hwnd, (POINT*)&rw, 2); + SetWindowPos(hwndCtrl, NULL, max(0, (cx - (rw.right - rw.left))/2), rw.top, rw.right - rw.left, cy - rw.top - 16, SWP_NOACTIVATE | SWP_NOZORDER); + } +} + +void setup_page_lang::OnCommand(INT nCtrlID, INT nEvntID, HWND hwndCtrl) +{ + switch(nCtrlID) + { + case IDC_LB_LANG: + switch(nEvntID) + { + case LBN_SELCHANGE: ListBox_OnSelChange(hwndCtrl); break; + } + break; + } +} + +INT_PTR setup_page_lang::OnDeleteItem(INT nCtrlID, DELETEITEMSTRUCT *pdis) +{ + switch(nCtrlID) + { + case IDC_LB_LANG: ListBox_OnItemDelete(pdis); return TRUE; + } + return 0; +} + +INT_PTR setup_page_lang::PageDlgProc(UINT uMsg, WPARAM wParam, LPARAM lParam) +{ + switch(uMsg) + { + case WM_INITDIALOG: return OnInitDialog((HWND)wParam, lParam); + case WM_DESTROY: break; + case WM_SIZE: OnSize((UINT)wParam, LOWORD(lParam), HIWORD(lParam)); break; + case WM_COMMAND: OnCommand(LOWORD(wParam), HIWORD(wParam), (HWND)lParam); break; + } + return 0; +} + +static INT_PTR WINAPI DialogProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam) +{ + setup_page_lang *pInst = (setup_page_lang*)GetPropW(hwnd, L"SETUPPAGE"); + + switch(uMsg) + { + case WM_INITDIALOG: + pInst = (setup_page_lang*)lParam; + if (pInst) + { + pInst->hwnd = hwnd; + SetPropW(hwnd, L"SETUPPAGE", pInst); + } + break; + case WM_DESTROY: + if (pInst) + { + pInst->PageDlgProc(uMsg, wParam, lParam); + RemovePropW(hwnd, L"SETUPPAGE"); + pInst = NULL; + } + break; + } + + return (pInst) ? pInst->PageDlgProc(uMsg, wParam, lParam) : 0; +} + +static BOOL CALLBACK AddLangToListBox(ENUMLANG *pel, LPVOID pUser) +{ + INT index; + LANGREC *pr; + HWND hwndLB = (HWND)pUser; + if (!hwndLB) return FALSE; + + pr = (LANGREC*)calloc(1, sizeof(LANGREC)); + if (!pr) return FALSE; + pr->nType = pel->nType; + if (pel->pszFileName) pr->pszFileName = _wcsdup(pel->pszFileName); + + index = (INT)SendMessageW(hwndLB, LB_ADDSTRING, 0, (LPARAM)pel->pszName); + if (LB_ERR != index) SendMessageW(hwndLB, LB_SETITEMDATA, index, (LPARAM)pr); + else + { + if (pr->pszFileName) free(pr->pszFileName); + free(pr); + } + return TRUE; +} + +static INT ListBox_FindLangFileIndex(HWND hwndLB, LPCWSTR pszLangPath) +{ + int index, count; + + if (!hwndLB) return LB_ERR; + + index = LB_ERR; + + count = (INT)SendMessageW(hwndLB, LB_GETCOUNT, 0, 0L); + for (index = 0; index < count; index++) + { + LANGREC *pr = (LANGREC*) SendMessageW(hwndLB, LB_GETITEMDATA, index, 0L); + if (!pr || LB_ERR == (INT)(INT_PTR)pr) continue; + if (!pszLangPath || !*pszLangPath) + { + if (LANG_FILETYPE_EMBED == pr->nType && (!pr->pszFileName || !*pr->pszFileName)) break; + } + else + { + if (CSTR_EQUAL == ComparePath(pszLangPath, pr->pszFileName, LANGDIR)) break; + } + } + return (count == index) ? LB_ERR : index; +} + +static LPCWSTR ListBox_GetSelectedLang(HWND hwndLB, LPWSTR pszLangPath, INT cchLen) +{ + INT index; + LANGREC *pr; + if (!hwndLB || !pszLangPath) return NULL; + index = (INT)SendMessageW(hwndLB, LB_GETCURSEL, 0, 0L); + if (LB_ERR == index) return NULL; + pr = (LANGREC*)SendMessageW(hwndLB, LB_GETITEMDATA, index, 0L); + if (!pr || LB_ERR == (INT)(INT_PTR)pr) return NULL; + + if (!pr->pszFileName || !*pr->pszFileName) pszLangPath[0] = 0x00; + else if (S_OK != StringCchCopyW(pszLangPath, cchLen, pr->pszFileName)) return NULL; + return pszLangPath; +} + +#ifdef CBCLASS +#undef CBCLASS +#endif + +#define CBCLASS setup_page_lang +START_DISPATCH +CB(ADDREF, AddRef) +CB(RELEASE, Release) +CB(API_SETUPPAGE_GET_NAME, GetName) +CB(API_SETUPPAGE_CREATEVIEW, CreateView) +CB(API_SETUPPAGE_SAVE, Save) +CB(API_SETUPPAGE_REVERT, Revert) +CB(API_SETUPPAGE_ISDIRTY, IsDirty) +CB(API_SETUPPAGE_VALIDATE, Validate) +END_DISPATCH +#undef CBCLASS
\ No newline at end of file diff --git a/Src/Winamp/setup/spage_lang.h b/Src/Winamp/setup/spage_lang.h new file mode 100644 index 00000000..f3848ab7 --- /dev/null +++ b/Src/Winamp/setup/spage_lang.h @@ -0,0 +1,42 @@ +#ifndef WINAMP_LANGUAGE_SETUP_PAGE_HEADER +#define WINAMP_LANGUAGE_SETUP_PAGE_HEADER + +#include "./ifc_setuppage.h" + +class setup_page_lang : public ifc_setuppage +{ + +public: + setup_page_lang(); + virtual ~setup_page_lang(); + +public: + size_t AddRef(); + size_t Release(); + HRESULT GetName(bool bShort, const wchar_t **pszName); + HRESULT Save(HWND hwndText); + HRESULT CreateView(HWND hwndParent, HWND *phwnd); + HRESULT Revert(void); + HRESULT IsDirty(void); + HRESULT Validate(void); +protected: + INT_PTR PageDlgProc(UINT uMsg, WPARAM wParam, LPARAM lParam); + INT_PTR OnInitDialog(HWND hwndFocus, LPARAM lParam); + void OnSize(UINT nType, INT cx, INT cy); + void OnCommand(INT nCtrlID, INT nEvntID, HWND hwndCtrl); + INT_PTR OnDeleteItem(INT nCtrlID, DELETEITEMSTRUCT *pdis); + void ListBox_OnItemDelete(DELETEITEMSTRUCT *pdis); + void ListBox_OnSelChange(HWND hwndCtrl); + +private: + size_t ref; + HWND hwnd; + wchar_t szSelectionPath[MAX_PATH]; + +protected: + friend static INT_PTR WINAPI DialogProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam); + RECVS_DISPATCH; +}; + + +#endif //WINAMP_LANGUAGE_SETUP_PAGE_HEADER
\ No newline at end of file diff --git a/Src/Winamp/setup/spage_skin.cpp b/Src/Winamp/setup/spage_skin.cpp new file mode 100644 index 00000000..d50f3998 --- /dev/null +++ b/Src/Winamp/setup/spage_skin.cpp @@ -0,0 +1,646 @@ +#define APSTUDIO_READONLY_SYMBOLS +#include "main.h" +#include "./spage_skin.h" +#include "./setup_resource.h" +#include "./skininfo.h" +#include "../nu/ns_wc.h" +#include "../nu/AutoWide.h" +#include "./loadimage.h" +#include "./langutil.h" +#include "./setupcommon.h" + +typedef struct _SKINLINK +{ + LPCWSTR pszName; + LPCWSTR pszTarget; +} SKINLINK; + +typedef struct _SKINREC +{ + LPWSTR pszName; + LPWSTR pszFileName; + INT nType; + BOOL bLink; // if bLink == TRUE than nType index in links +} SKINREC; + +#define CURRENT_SKIN_ID 1 +#define SEPARATOR_DATA 0xEFFF + +#define LINK_FONT_ITALIC FALSE +#define LINK_FONT_WEIGHT FW_MEDIUM +//#define LINK_TEXT_COLOR RGB(0, 50, 193) +//#define LINK_TEXT_HIGHLITECOLOR RGB(16, 64, 212) + +#define PREVIEW_WIDTH 178 +#define PREVIEW_HEIGHT 75 + +static SKINLINK links[] = +{ + { MAKEINTRESOURCEW(IDS_SKIN_PROMO1), BENTO_SKIN_NAME }, + { MAKEINTRESOURCEW(IDS_SKIN_PROMO2), BIG_BENTO_SKIN_NAME }, + { MAKEINTRESOURCEW(IDS_SKIN_CURRENT), MAKEINTRESOURCEW(CURRENT_SKIN_ID) }, +}; + +static wchar_t szClassic[64] = {0, }; + +#define CLASSIC_NAME() ((!*szClassic) ? getStringW(IDS_CLASSIC_SKIN_NAME, szClassic, sizeof(szClassic)/sizeof(wchar_t)) : szClassic) + +static BOOL CALLBACK AddSkinToListBox(ENUMSKIN *pes, LPVOID pUser); +static LRESULT WINAPI ListBoxProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam); +static LPCWSTR ResolveLink(SKINREC *pr); +static INT ListBox_FindSkinFileIndex(HWND hwndLB, LPCWSTR pszSkinPath, BOOL bSearchLinks); + +setup_page_skin::setup_page_skin() : ref(1), hwnd(NULL), hfLink(NULL), idxSelected(-1) +{ + *szSelectionPath = 0x00; +} + +setup_page_skin::~setup_page_skin() +{ +} + +size_t setup_page_skin::AddRef() +{ + return ++ref; +} + +size_t setup_page_skin::Release() +{ + if (1 == ref) + { + delete(this); + return 0; + } + return --ref; +} + +HRESULT setup_page_skin::GetName(bool bShort, const wchar_t **pszName) +{ + if (bShort) + { + static wchar_t szShortName[32] = {0}; + *pszName = (*szShortName) ? szShortName : getStringW(IDS_PAGE_SKIN, szShortName, sizeof(szShortName)/sizeof(wchar_t)); + } + else + { + static wchar_t szLongName[64] = {0}; + *pszName = (*szLongName) ? szLongName : getStringW(IDS_PAGE_SKIN_LONG, szLongName, sizeof(szLongName)/sizeof(wchar_t)); + } + return S_OK; +} + +HRESULT setup_page_skin::Save(HWND hwndText) +{ + if (S_FALSE == IsDirty()) return S_OK; + + if (!*szSelectionPath) *config_skin = 0x00; + else if (S_OK != StringCchCopyW(config_skin, sizeof(config_skin)/sizeof(wchar_t), szSelectionPath)) return S_FALSE; + + _w_sW("skin", config_skin); + if (hwnd) + { + HWND hwndLB = GetDlgItem(hwnd, IDC_LB_SKIN); + INT index = ListBox_FindSkinFileIndex(hwndLB, szSelectionPath, TRUE); + if (LB_ERR == index && *szSelectionPath) index = ListBox_FindSkinFileIndex(hwndLB, NULL, TRUE); // find default embeded skin + SendMessageW(hwndLB, LB_SETCURSEL, (LB_ERR != index) ? index : 0, 0L); + } + return S_OK;//(count) ? S_OK : S_FALSE; +} + +static BOOL IsForceBento() +{ + wchar_t szVer[128] = {0}; + if (GetPrivateProfileIntW(L"WinampReg", L"IsFirstInst", 0, INI_FILE)) return TRUE; + GetPrivateProfileStringW(L"WinampReg", L"WAVer", L"", szVer, 128, INI_FILE); + return (!*szVer || CSTR_LESS_THAN == CompareStringW(MAKELCID(MAKELANGID(LANG_ENGLISH, SUBLANG_ENGLISH_US), SORT_DEFAULT), + NORM_IGNORECASE, szVer, -1, AutoWide(APP_VERSION), -1)); +} + +HRESULT setup_page_skin::Revert(void) +{ + HRESULT hr(S_OK); + + if (NULL != config_skin && !IsForceBento()) StringCchCopyW(szSelectionPath, sizeof(szSelectionPath)/sizeof(wchar_t), config_skin); + else StringCchCopyW(szSelectionPath, sizeof(szSelectionPath)/sizeof(wchar_t), L"Bento"); + + if (hwnd) + { + HWND hwndLB = GetDlgItem(hwnd, IDC_LB_SKIN); + INT index = ListBox_FindSkinFileIndex(hwndLB, szSelectionPath, TRUE); + if (LB_ERR == index && *szSelectionPath) index = ListBox_FindSkinFileIndex(hwndLB, NULL, TRUE); // find default embeded skin + SendMessageW(hwndLB, LB_SETCURSEL, (LB_ERR != index) ? index : 0, 0L); + } + return hr; +} + +HRESULT setup_page_skin::IsDirty(void) +{ + INT cr; + + if (IsForceBento()) return S_OK; + + cr = ComparePath(config_skin, szSelectionPath, SKINDIR); + if (!cr) return E_UNEXPECTED; + return (CSTR_EQUAL != cr) ? S_OK : S_FALSE; +} + +HRESULT setup_page_skin::Validate(void) +{ + return S_OK; +} + +HRESULT setup_page_skin::CreateView(HWND hwndParent, HWND *phwnd) +{ + *phwnd = WACreateDialogParam(MAKEINTRESOURCEW(IDD_SETUP_PAGE_SKIN), hwndParent, ::DialogProc, (LPARAM)this); + return S_OK; +} + +void setup_page_skin::ListBox_OnSelChange(HWND hwndCtrl) +{ + SKININFO si = {0}; + SKINREC *pr; + WCHAR szText[MAX_PATH*2] = {0}; + INT typeID, index; + + index = (INT)SendMessageW(hwndCtrl, LB_GETCURSEL, 0, 0L); + if (idxSelected == index) return; + + pr = (SKINREC*)SendMessageW(hwndCtrl, LB_GETITEMDATA, index, 0L); + if (pr && LB_ERR != (INT)(INT_PTR)pr && pr->bLink) // resolve link + { + index = ListBox_FindSkinFileIndex(hwndCtrl, ResolveLink(pr), FALSE); + pr = (LB_ERR != index) ? (SKINREC*)SendMessageW(hwndCtrl, LB_GETITEMDATA, index, 0L) : NULL; + } + if (!pr || LB_ERR == (INT)(INT_PTR)pr) { SendMessageW(hwndCtrl, LB_SETCURSEL, idxSelected, 0L); return; } + idxSelected = index; + + if (!pr->pszFileName || !*pr->pszFileName) szSelectionPath[0] = 0x00; + else StringCchCopyW(szSelectionPath, sizeof(szSelectionPath)/sizeof(wchar_t), pr->pszFileName); + + ZeroMemory(&si, sizeof(SKININFO)); + si.cbSize = sizeof(SKININFO); + si.fMask = SIF_PREVIEW; + StringCchCopyW(si.szName, SI_NAMEMAX, pr->pszName); + + GetSkinInfo(BuildFullPath(SKINDIR, szSelectionPath, szText, sizeof(szText)/sizeof(wchar_t)), &si); + + switch(si.type) + { + case SKIN_TYPE_MODERN: typeID = IDS_MODERN; break; + case SKIN_TYPE_CLASSIC: typeID = IDS_CLASSIC; break; + default: typeID = IDS_UNKNOWN; break; + } + + SetDlgItemTextW(hwnd, IDC_EDT_NAME, si.szName); + SetDlgItemTextW(hwnd, IDC_EDT_TYPE, getStringW(typeID, NULL, 0)); + SetDlgItemTextW(hwnd, IDC_EDT_AUTHOR, si.szAuthor); + SetDlgItemTextW(hwnd, IDC_EDT_VERSION, si.szVersion); + if (!si.hPreview) si.hPreview = WALoadImage2(L"PNG", MAKEINTRESOURCEW(IDB_PREVIEW_NO), FALSE); + if (si.hPreview) + { + HBRUSH hb = (HBRUSH)SendMessageW(hwnd, WM_CTLCOLORSTATIC, NULL, (LPARAM)GetDlgItem(hwnd, IDC_PIC_PREVIEW)); + WABlendOnColor(si.hPreview, RGB(137,145,156)); + si.hPreview = WAResizeImage(si.hPreview, PREVIEW_WIDTH, PREVIEW_HEIGHT, hb); + if (!si.hPreview) si.hPreview = WALoadImage2(L"PNG", MAKEINTRESOURCEW(IDB_PREVIEW_NO), FALSE); + } + + HBITMAP hPrev = (HBITMAP)SendDlgItemMessageW(hwnd, IDC_PIC_PREVIEW, STM_SETIMAGE, IMAGE_BITMAP, (LPARAM)si.hPreview); + if (hPrev) DeleteObject(hPrev); +} + +void setup_page_skin::ListBox_OnItemDelete(DELETEITEMSTRUCT *pdis) +{ + SKINREC *pr = (SKINREC*)pdis->itemData; + if (pr) + { + if (pr->pszName) free(pr->pszName); + if (pr->pszFileName) free(pr->pszFileName); + free(pr); + } +} + +void setup_page_skin::ListBox_OnDrawItem(DRAWITEMSTRUCT *pdis) +{ + RECT ri; + SKINREC *pr = (SKINREC*)pdis->itemData; + static UINT trackFocus = 0x0000FFFF; + + if (pdis->itemID == -1) return; + + CopyRect(&ri, &pdis->rcItem); + switch(pdis->itemAction) + { + case ODA_FOCUS: + if (0 == (0x0200/*ODS_NOFOCUSRECT*/ & pdis->itemState) && pr) + { + if (LOWORD(trackFocus) != pdis->itemID || HIWORD(trackFocus) != (ODS_FOCUS & pdis->itemState) ? 0x0001: 0x0000) + DrawFocusRect(pdis->hDC, &ri); + trackFocus = pdis->itemID | ((ODS_FOCUS & pdis->itemState) ? 0x00010000 : 0x00000000); + } + else trackFocus = pdis->itemID; + return; + + case ODA_SELECT: + if (0 == (ODS_SELECTED & pdis->itemState) && pr) + ExtTextOutW(pdis->hDC, 0, 0, ETO_OPAQUE, &ri, L"", 0, NULL); + break; + } + + if ((ODS_SELECTED & pdis->itemState) && pr) + { + COLORREF rgb = SetBkColor(pdis->hDC, GetSysColor(COLOR_HIGHLIGHT)); + ExtTextOutW(pdis->hDC, 0, 0, ETO_OPAQUE, &ri, L"", 0, NULL); + SetBkColor(pdis->hDC, rgb); + } + + if (pr) + { + if (pr->pszName) + { + HFONT hfOld; + COLORREF rgb(0); + + if (pr->bLink) + { + if (!hfLink) + { + LOGFONTW lf = {0}; + if (GetObject(GetCurrentObject(pdis->hDC, OBJ_FONT), sizeof(LOGFONTW), &lf)) + { + lf.lfItalic = LINK_FONT_ITALIC; + lf.lfWeight = LINK_FONT_WEIGHT; + hfLink = CreateFontIndirectW(&lf); + } + } + hfOld = (HFONT)SelectObject(pdis->hDC, hfLink); + rgb = SetTextColor(pdis->hDC, GetSysColor((ODS_SELECTED & pdis->itemState) ? COLOR_HIGHLIGHTTEXT : COLOR_WINDOWTEXT)); + } + else + { + hfOld = NULL; + rgb = SetTextColor(pdis->hDC, GetSysColor((ODS_SELECTED & pdis->itemState) ? COLOR_HIGHLIGHTTEXT : COLOR_WINDOWTEXT)); + } + + ri.left += 2; + COLORREF oldrgb = SetBkColor(pdis->hDC, GetSysColor((ODS_SELECTED & pdis->itemState) ? COLOR_HIGHLIGHT : COLOR_WINDOW)); + DrawTextW(pdis->hDC, pr->pszName, -1, &ri, DT_VCENTER | DT_SINGLELINE | DT_NOPREFIX | DT_WORD_ELLIPSIS); + SetBkColor(pdis->hDC, oldrgb); + if (pr->bLink && hfOld) SelectObject(pdis->hDC, hfOld); + SetTextColor(pdis->hDC, rgb); + } + } + else + { + HPEN hPen, hPenOld; + hPen = CreatePen(PS_DOT, 0, GetSysColor(COLOR_WINDOWTEXT)); + hPenOld = (HPEN)SelectObject(pdis->hDC, hPen); + MoveToEx(pdis->hDC, ri.left + 1, ri.top + (ri.bottom - ri.top)/2, NULL); + LineTo(pdis->hDC, ri.right - 1, ri.top + (ri.bottom - ri.top)/2); + SelectObject(pdis->hDC, hPenOld); + } +} + +INT_PTR setup_page_skin::ListBox_OnItemCompare(COMPAREITEMSTRUCT *pcis) +{ SKINREC *pr1, *pr2; + INT cr; + + pr1 = (SKINREC*)pcis->itemData1; + pr2 = (SKINREC*)pcis->itemData2; + if (pr1 == pr2) return 0; + if (!pr1) return (pr2->bLink) ? 1 : -1; + if (!pr2) return (pr1->bLink) ? -1 : 1; + if (pr1->bLink) return (pr2->bLink) ? (pcis->itemID1 - pcis->itemID2) : -1; + if (pr2->bLink) return (pr1->bLink) ? (pcis->itemID1 - pcis->itemID2) : 1; + cr = CompareStringW(pcis->dwLocaleId, NORM_IGNORECASE, pr1->pszName, -1, pr2->pszName, -1); + if (CSTR_EQUAL == cr) + { + INT t1, t2; + t1 = (SKIN_FILETYPE_WAL == pr1->nType) ? SKIN_FILETYPE_ZIP : ((SKIN_FILETYPE_ZIP == pr1->nType) ? SKIN_FILETYPE_WAL : pr1->nType); + t2 = (SKIN_FILETYPE_WAL == pr2->nType) ? SKIN_FILETYPE_ZIP : ((SKIN_FILETYPE_ZIP == pr2->nType) ? SKIN_FILETYPE_WAL : pr2->nType); + return t1 - t2; + } + return cr - 2; +} + +INT_PTR setup_page_skin::ListBox_OnVKeyToItem(HWND hwndLB, WORD vKey, INT index) +{ + switch(vKey) + { + case VK_UP: + case VK_LEFT: + if (NULL == SendMessageW(hwndLB, LB_GETITEMDATA, index - 1, 0L)) return index - 2; + break; + case VK_DOWN: + case VK_RIGHT: + if (NULL == SendMessageW(hwndLB, LB_GETITEMDATA, index + 1, 0L)) return index + 2; + break; + case VK_NEXT: + case VK_PRIOR: + { + RECT rc; + INT page, count; + GetClientRect(hwndLB, &rc); + page = (rc.bottom - rc.top)/(INT)SendMessageW(hwndLB, LB_GETITEMHEIGHT, 0, 0L) - 1; + count = (INT)SendMessageW(hwndLB, LB_GETCOUNT, 0, 0L); + index = (VK_NEXT == vKey) ? min(index + page, count) : max(0, index - page); + if (NULL == SendMessageW(hwndLB, LB_GETITEMDATA, index, 0L)) return index + ((VK_NEXT == vKey) ? 1 : -1); + break; + } + } + return -1; +} + +INT_PTR setup_page_skin::ListBox_OnCharToItem(HWND hwndLB, WORD vKey, INT index) +{ + return -2; +} + +INT_PTR setup_page_skin::OnInitDialog(HWND hwndFocus, LPARAM lParam) +{ + HWND hwndLB, hwndGrp; + int count, linksCount(0), index; + wchar_t szBuffer[MAX_PATH] = {0}; + + idxSelected = -1; + + hwndGrp = GetDlgItem(hwnd, IDC_GRP_PREVIEW); + SetWindowLongPtrW(hwndGrp, GWL_STYLE, GetWindowLongPtrW(hwndGrp, GWL_STYLE) | WS_CLIPSIBLINGS); + + hwndLB = GetDlgItem(hwnd, IDC_LB_SKIN); + EnumerateSkins(AddSkinToListBox, hwndLB); + + count = sizeof(links)/sizeof(SKINLINK); + + for (int i = count - 1; i >= 0; i--) + { + SKINREC *pr = (SKINREC*)calloc(1, sizeof(SKINREC)); + if (pr) + { + LPCWSTR pszName = links[i].pszName; + if (IS_INTRESOURCE(pszName)) pszName = getStringW((INT)(INT_PTR)pszName, szBuffer, sizeof(szBuffer)/sizeof(wchar_t)); + pr->pszName = _wcsdup(pszName); + pr->bLink = TRUE; + pr->nType = i; + + if(LB_ERR != ListBox_FindSkinFileIndex(hwndLB, ResolveLink(pr), FALSE) && + LB_ERR != SendMessageW(hwndLB, LB_INSERTSTRING, 0, (LPARAM)pr)) + { + linksCount++; + } + else + { + if (pr) + { + if (pr->pszName) free(pr->pszName); + free(pr); + } + } + } + } + + if (linksCount) SendMessageW(hwndLB, LB_INSERTSTRING, linksCount, (LPARAM)NULL); + + WNDPROC fnOldProc = (WNDPROC)(LONG_PTR)SetWindowLongPtrW(hwndLB, GWLP_WNDPROC, (LONGX86)(LONG_PTR)ListBoxProc); + if (fnOldProc) SetPropW(hwndLB, L"SKINLB", fnOldProc); + + index = ListBox_FindSkinFileIndex(hwndLB, szSelectionPath, TRUE); + if (LB_ERR == index && *szSelectionPath) index = ListBox_FindSkinFileIndex(hwndLB, NULL, TRUE); // find default embeded lang + SendMessageW(hwndLB, LB_SETCURSEL, (LB_ERR != index) ? index : 0, 0L); + + PostMessageW(hwnd, WM_COMMAND, MAKEWPARAM(IDC_LB_SKIN, LBN_SELCHANGE), (LPARAM)hwndLB); + return 0; +} + +void setup_page_skin::OnDestroy(void) +{ + if (hfLink) { DeleteObject(hfLink); hfLink = NULL; } +} + +void setup_page_skin::OnCommand(INT nCtrlID, INT nEvntID, HWND hwndCtrl) +{ + switch(nCtrlID) + { + case IDC_LB_SKIN: + switch(nEvntID) + { + case LBN_SELCHANGE: ListBox_OnSelChange(hwndCtrl); break; + } + break; + } +} + +INT_PTR setup_page_skin::OnColorStatic(HDC hdc, HWND hwndCtrl) +{ + INT ctrlID = GetDlgCtrlID(hwndCtrl); + switch(ctrlID) + { + case IDC_LBL_NAME: + case IDC_LBL_TYPE: + case IDC_LBL_AUTHOR: + case IDC_LBL_VERSION: + SetTextColor(hdc, RGB(0, 70, 213)); + break; + } + return NULL; +} + +INT_PTR setup_page_skin::OnDrawItem(INT nCtrlID, DRAWITEMSTRUCT *pdis) +{ + switch(nCtrlID) + { + case IDC_LB_SKIN: ListBox_OnDrawItem(pdis); return TRUE; + } + return 0; +} + +INT_PTR setup_page_skin::OnMeasureItem(INT nCtrlID, MEASUREITEMSTRUCT *pmis) +{ + switch(nCtrlID) + { + case IDC_LB_SKIN: + return TRUE; + } + return FALSE; +} + +INT_PTR setup_page_skin::OnDeleteItem(INT nCtrlID, DELETEITEMSTRUCT *pdis) +{ + switch(nCtrlID) + { + case IDC_LB_SKIN: ListBox_OnItemDelete(pdis); return TRUE; + } + return 0; +} + +INT_PTR setup_page_skin::OnCompareItem(INT nCtrlID, COMPAREITEMSTRUCT *pcis) +{ + switch(nCtrlID) + { + case IDC_LB_SKIN: return ListBox_OnItemCompare(pcis); + } + return 0; +} + +INT_PTR setup_page_skin::OnVKeyToItem(WORD vKey, INT index, HWND hwndCtrl) +{ + switch(GetDlgCtrlID(hwndCtrl)) + { + case IDC_LB_SKIN: return ListBox_OnVKeyToItem(hwndCtrl, vKey, index); + } + return -1; +} + +INT_PTR setup_page_skin::OnCharToItem(WORD vKey, INT index, HWND hwndCtrl) +{ + switch(GetDlgCtrlID(hwndCtrl)) + { + case IDC_LB_SKIN: return ListBox_OnCharToItem(hwndCtrl, vKey, index); + } + return -1; +} + +INT_PTR setup_page_skin::PageDlgProc(UINT uMsg, WPARAM wParam, LPARAM lParam) +{ + switch(uMsg) + { + case WM_INITDIALOG: return OnInitDialog((HWND)wParam, lParam); + case WM_DESTROY: OnDestroy(); break; + case WM_CTLCOLORSTATIC: return OnColorStatic((HDC)wParam, (HWND)lParam); + case WM_DRAWITEM: MSGRESULT(hwnd, OnDrawItem((INT)wParam, (DRAWITEMSTRUCT*)lParam)); + case WM_MEASUREITEM: MSGRESULT(hwnd, OnMeasureItem((INT)wParam, (MEASUREITEMSTRUCT*)lParam)); + case WM_COMMAND: OnCommand(LOWORD(wParam), HIWORD(wParam), (HWND)lParam); break; + case WM_DELETEITEM: MSGRESULT(hwnd, OnDeleteItem((INT)wParam, (DELETEITEMSTRUCT*)lParam)); + case WM_COMPAREITEM: return OnCompareItem((INT)wParam, (COMPAREITEMSTRUCT*)lParam); + case WM_VKEYTOITEM: return OnVKeyToItem(LOWORD(wParam), HIWORD(wParam), (HWND)lParam); + case WM_CHARTOITEM: return OnCharToItem(LOWORD(wParam), HIWORD(wParam), (HWND)lParam); + } + return 0; +} + +static BOOL CALLBACK AddSkinToListBox(ENUMSKIN *pes, LPVOID pUser) +{ + HWND hwndLB = (HWND)pUser; + if (!hwndLB) return FALSE; + + SKINREC *pr = (SKINREC*)calloc(1, sizeof(SKINREC)); + if (!pr) return FALSE; + pr->nType = pes->nType; + if (pes->pszName) pr->pszName = _wcsdup(pes->pszName); + if (pes->pszFileName) pr->pszFileName = _wcsdup(pes->pszFileName); + + if (LB_ERR == SendMessageW(hwndLB, LB_ADDSTRING, 0, (LPARAM)pr)) + { + if (pr->pszName) free(pr->pszName); + if (pr->pszFileName) free(pr->pszFileName); + free(pr); + } + return TRUE; +} + +static LPCWSTR ResolveLink(SKINREC *pr) +{ + if (!pr) return NULL; + if (!pr->bLink) return pr->pszFileName; + if (pr->nType < 0 || pr->nType >= sizeof(links)/sizeof(SKINLINK)) return NULL; + if(CURRENT_SKIN_ID == (INT)(INT_PTR)links[pr->nType].pszTarget) return config_skin; + if (IS_INTRESOURCE(links[pr->nType].pszTarget)) return getStringW((INT)(INT_PTR)links[pr->nType].pszTarget, NULL, 0); + return links[pr->nType].pszTarget; +} + +static INT ListBox_FindSkinFileIndex(HWND hwndLB, LPCWSTR pszSkinPath, BOOL bSearchLinks) +{ + int index, count; + SKINREC *pr; + LPCWSTR pszFileName; + + if (!hwndLB) return LB_ERR; + + index = LB_ERR; + + count = (INT)SendMessageW(hwndLB, LB_GETCOUNT, 0, 0L); + for (index = 0; index < count; index++) + { + pr = (SKINREC*) SendMessageW(hwndLB, LB_GETITEMDATA, index, 0L); + if (!pr || LB_ERR == (INT)(INT_PTR)pr) continue; + + if (pr->bLink) + { + if(bSearchLinks) pszFileName = ResolveLink(pr); + else continue; + } + else pszFileName = pr->pszFileName; + + if (!pszSkinPath || !*pszSkinPath) + { + if (!pszFileName || !*pszFileName) break; + } + else + { + if (pszFileName && CSTR_EQUAL == ComparePath(pszSkinPath, pszFileName, SKINDIR)) break; + } + } + return (count == index) ? LB_ERR : index; +} + +static INT_PTR WINAPI DialogProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam) +{ + setup_page_skin *pInst = (setup_page_skin*)GetPropW(hwnd, L"SETUPPAGE"); + switch(uMsg) + { + case WM_INITDIALOG: + pInst = (setup_page_skin*)lParam; + if (pInst) + { + pInst->hwnd = hwnd; + SetPropW(hwnd, L"SETUPPAGE", pInst); + } + break; + case WM_DESTROY: + if (pInst) + { + pInst->PageDlgProc(uMsg, wParam, lParam); + RemovePropW(hwnd, L"SETUPPAGE"); + pInst = NULL; + } + break; + } + return (pInst) ? pInst->PageDlgProc(uMsg, wParam, lParam) : 0; +} + +static LRESULT WINAPI ListBoxProc( HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam ) +{ + WNDPROC fnOldProc = (WNDPROC) GetPropW( hwnd, L"SKINLB" ); + if ( !fnOldProc ) return DefWindowProcW( hwnd, uMsg, wParam, lParam ); + switch ( uMsg ) + { + case WM_DESTROY: + RemovePropW( hwnd, L"SKINLB" ); + SetWindowLongPtrW( hwnd, GWLP_WNDPROC, (LONG_PTR) fnOldProc ); + break; + case WM_LBUTTONDOWN: + case WM_RBUTTONDOWN: + case WM_LBUTTONDBLCLK: + if ( SendMessageW( hwnd, LB_GETITEMDATA, LOWORD( SendMessageW( hwnd, LB_ITEMFROMPOINT, 0, lParam ) ), 0L ) == NULL ) + return 0; + break; + } + + return CallWindowProcW( fnOldProc, hwnd, uMsg, wParam, lParam ); +} + +#ifdef CBCLASS +#undef CBCLASS +#endif + +#define CBCLASS setup_page_skin +START_DISPATCH +CB(ADDREF, AddRef) +CB(RELEASE, Release) +CB(API_SETUPPAGE_GET_NAME, GetName) +CB(API_SETUPPAGE_CREATEVIEW, CreateView) +CB(API_SETUPPAGE_SAVE, Save) +CB(API_SETUPPAGE_REVERT, Revert) +CB(API_SETUPPAGE_ISDIRTY, IsDirty) +CB(API_SETUPPAGE_VALIDATE, Validate) +END_DISPATCH +#undef CBCLASS
\ No newline at end of file diff --git a/Src/Winamp/setup/spage_skin.h b/Src/Winamp/setup/spage_skin.h new file mode 100644 index 00000000..3a380731 --- /dev/null +++ b/Src/Winamp/setup/spage_skin.h @@ -0,0 +1,52 @@ +#ifndef WINAMP_SKIN_SETUP_PAGE_HEADER +#define WINAMP_SKIN_SETUP_PAGE_HEADER + +#include "./ifc_setuppage.h" + +class setup_page_skin : public ifc_setuppage +{ +public: + setup_page_skin(); + virtual ~setup_page_skin(); + +public: + size_t AddRef(); + size_t Release(); + HRESULT GetName(bool bShort, const wchar_t **pszName); + HRESULT Save(HWND hwndText); + HRESULT CreateView(HWND hwndParent, HWND *phwnd); + HRESULT Revert(void); + HRESULT IsDirty(void); + HRESULT Validate(void); +protected: + INT_PTR PageDlgProc(UINT uMsg, WPARAM wParam, LPARAM lParam); + INT_PTR OnInitDialog(HWND hwndFocus, LPARAM lParam); + void OnDestroy(void); + INT_PTR OnColorStatic(HDC hdc, HWND hwndCtrl); + INT_PTR OnDrawItem(INT nCtrlID, DRAWITEMSTRUCT *pdis); + INT_PTR OnMeasureItem(INT nCtrlID, MEASUREITEMSTRUCT *pmis); + void OnCommand(INT nCtrlID, INT nEvntID, HWND hwndCtrl); + INT_PTR OnDeleteItem(INT nCtrlID, DELETEITEMSTRUCT *pdis); + INT_PTR OnCompareItem(INT nCtrlID, COMPAREITEMSTRUCT *pcis); + INT_PTR OnVKeyToItem(WORD vKey, INT index, HWND hwndCtrl); + INT_PTR OnCharToItem(WORD vKey, INT index, HWND hwndCtrl); + + void ListBox_OnDrawItem(DRAWITEMSTRUCT *pdis); + void ListBox_OnSelChange(HWND hwndCtrl); + void ListBox_OnItemDelete(DELETEITEMSTRUCT *pdis); + INT_PTR ListBox_OnItemCompare(COMPAREITEMSTRUCT *pcis); + INT_PTR ListBox_OnVKeyToItem(HWND hwndLB, WORD vKey, INT index); + INT_PTR ListBox_OnCharToItem(HWND hwndLB, WORD vKey, INT index); + +private: + size_t ref; + HWND hwnd; + HFONT hfLink; + int idxSelected; // internal crap + wchar_t szSelectionPath[MAX_PATH]; +protected: + friend static INT_PTR WINAPI DialogProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam); + RECVS_DISPATCH; +}; + +#endif //WINAMP_SKIN_SETUP_PAGE_HEADER
\ No newline at end of file diff --git a/Src/Winamp/setup/svc_setup.h b/Src/Winamp/setup/svc_setup.h new file mode 100644 index 00000000..d4cd8106 --- /dev/null +++ b/Src/Winamp/setup/svc_setup.h @@ -0,0 +1,123 @@ +#ifndef NULLSOFT_WINAMP_SETUP_SERVICE_HEADER +#define NULLSOFT_WINAMP_SETUP_SERVICE_HEADER + +#include <bfc/dispatch.h> +#include "./ifc_setuppage.h" +#include "./ifc_setupjob.h" + +#include <windows.h> + +#ifdef __cplusplus +extern "C" { +#endif // __cplusplus + +#ifdef __cplusplus +} +#endif // __cplusplus + +class api_service; +typedef BOOL (__cdecl *Plugin_RegisterSetup)(HINSTANCE /*hInstance*/, api_service* /*serviceApi*/); + +class __declspec(novtable) svc_setup : public Dispatchable +{ +protected: + svc_setup(void) {}; + ~svc_setup(void) {}; +public: + HRESULT InsertPage(ifc_setuppage *pPage, int* pIndex); + HRESULT RemovePage(int index); + HRESULT GetPageCount(int* pCount); + HRESULT GetPage(int index, ifc_setuppage **pPage); + HRESULT GetActiveIndex(int*pIndex); + HRESULT Start(HWND hwndWinamp); + HRESULT AddJob(ifc_setupjob *pJob); + HRESULT RemoveJob(ifc_setupjob *pJob); + HRESULT CreateStatusWnd(HWND *phwndStatus); + HRESULT Save(HWND hwndStatus); + HRESULT ExecJobs(HWND hwndStatus); + HRESULT GetWinampWnd(HWND *phwndWinamp); // this call will return S_OK only after setup->Start() + +public: + DISPATCH_CODES + { + API_SETUP_INSERT_PAGE = 10, + API_SETUP_REMOVE_PAGE = 20, + API_SETUP_GET_PAGE_COUNT= 30, + API_SETUP_GET_PAGE= 40, + API_SETUP_GET_ACTIVE_INDEX = 50, + API_SETUP_START = 60, + API_SETUP_ADD_JOB = 70, + API_SETUP_REMOVE_JOB = 80, + API_SETUP_CREATE_STATUSWND = 90, + API_SETUP_SAVE = 100, + API_SETUP_EXECJOBS = 110, + API_SETUP_GETWINAMPWND = 120, + + }; +}; + +inline HRESULT svc_setup::InsertPage(ifc_setuppage *pPage, int* pIndex) +{ + return _call(API_SETUP_INSERT_PAGE, E_NOTIMPL, pPage, pIndex); +} + +inline HRESULT svc_setup::RemovePage(int index) +{ + return _call(API_SETUP_REMOVE_PAGE, E_NOTIMPL, index); +} + +inline HRESULT svc_setup::GetPageCount(int* pCount) +{ + return _call(API_SETUP_GET_PAGE_COUNT, E_NOTIMPL, pCount); +} + +inline HRESULT svc_setup::GetPage(int index, ifc_setuppage **pPage) +{ + return _call(API_SETUP_GET_PAGE, E_NOTIMPL, index, pPage); +} +inline HRESULT svc_setup::GetActiveIndex(int*pIndex) +{ + return _call(API_SETUP_GET_ACTIVE_INDEX, E_NOTIMPL, pIndex); +} +inline HRESULT svc_setup::Start(HWND hwndWinamp) +{ + return _call(API_SETUP_START, E_NOTIMPL, hwndWinamp); +} + +inline HRESULT svc_setup::AddJob(ifc_setupjob *pJob) +{ + return _call(API_SETUP_ADD_JOB, E_NOTIMPL, pJob); +} + +inline HRESULT svc_setup::RemoveJob(ifc_setupjob *pJob) +{ + return _call(API_SETUP_REMOVE_JOB, E_NOTIMPL, pJob); +} + +inline HRESULT svc_setup::CreateStatusWnd(HWND *phwndStatus) +{ + return _call(API_SETUP_CREATE_STATUSWND, E_NOTIMPL, phwndStatus); +} + +inline HRESULT svc_setup::Save(HWND hwndStatus) +{ + return _call(API_SETUP_SAVE, E_NOTIMPL, hwndStatus); +} + +inline HRESULT svc_setup::ExecJobs(HWND hwndStatus) +{ + return _call(API_SETUP_EXECJOBS, E_NOTIMPL, hwndStatus); +} + +inline HRESULT svc_setup::GetWinampWnd(HWND *phwndWinamp) +{ + return _call(API_SETUP_GETWINAMPWND, E_NOTIMPL, phwndWinamp); +} + + + +// {A7281DEB-9DA8-4ee9-93A8-2E0B8F5F1805} +static const GUID UID_SVC_SETUP = { 0xa7281deb, 0x9da8, 0x4ee9, { 0x93, 0xa8, 0x2e, 0xb, 0x8f, 0x5f, 0x18, 0x5 } }; + + +#endif //NULLSOFT_WINAMP_SETUP_SERVICE_HEADER diff --git a/Src/Winamp/setup/wa_classic_preview.png b/Src/Winamp/setup/wa_classic_preview.png Binary files differnew file mode 100644 index 00000000..7a02a1da --- /dev/null +++ b/Src/Winamp/setup/wa_classic_preview.png |