winamp/Src/Winamp/util.cpp

660 lines
16 KiB
C++
Raw Normal View History

2024-09-24 13:54:57 +01:00
/** (c) Nullsoft, Inc. C O N F I D E N T I A L
** Filename:
** Project:
** Description:
** Author:
** Created:
**/
#include "main.h"
#include <windows.h>
#include "strutil.h"
#include "../nu/ns_wc.h"
#include "plush/plush.h"
#include "../nu/AutoChar.h"
#include "../nu/AutoWide.h"
#include "WinampAttributes.h"
#undef GetSystemMetrics
int IsUrl(const char *url)
{
return !!strstr(url, "://");
}
void link_startsubclass(HWND hwndDlg, UINT id){
HWND ctrl = GetDlgItem(hwndDlg, id);
if(!GetPropW(ctrl, L"link_proc"))
{
SetPropW(ctrl, L"link_proc",
(HANDLE)SetWindowLongPtrW(ctrl, GWLP_WNDPROC, (LONG_PTR)link_handlecursor));
}
}
static HCURSOR link_hand_cursor;
LRESULT link_handlecursor(HWND hwndDlg, UINT uMsg, WPARAM wParam, LPARAM lParam)
{
LRESULT ret = CallWindowProcW((WNDPROC)GetPropW(hwndDlg, L"link_proc"), hwndDlg, uMsg, wParam, lParam);
// override the normal cursor behaviour so we have a hand to show it is a link
if(uMsg == WM_SETCURSOR)
{
if((HWND)wParam == hwndDlg)
{
if(!link_hand_cursor)
{
link_hand_cursor = LoadCursor(NULL, IDC_HAND);
}
SetCursor(link_hand_cursor);
return TRUE;
}
}
return ret;
}
void link_handledraw(HWND hwndDlg, UINT uMsg, WPARAM wParam, LPARAM lParam)
{
if (uMsg == WM_DRAWITEM)
{
DRAWITEMSTRUCT *di = (DRAWITEMSTRUCT *)lParam;
if (di->CtlType == ODT_BUTTON)
{
wchar_t wt[123] = {0};
int y;
RECT r;
HPEN hPen, hOldPen;
GetDlgItemTextW(hwndDlg, wParam, wt, sizeof(wt)/sizeof(wt[0]));
// draw text
SetTextColor(di->hDC, (di->itemState & ODS_SELECTED) ? RGB(220, 0, 0) : RGB(0, 0, 220));
r = di->rcItem;
// is used by the file types page to have a slimmer button so it doesn't override other
// characters which are otherwise drawn over by the size of the button needed for a link
if(GetPropW(di->hwndItem, L"slim"))
{
r.top -= 2;
}
r.left += 2;
DrawTextW(di->hDC, wt, -1, &r, DT_VCENTER | DT_SINGLELINE);
memset(&r, 0, sizeof(r));
DrawTextW(di->hDC, wt, -1, &r, DT_SINGLELINE | DT_CALCRECT);
// draw underline
y = di->rcItem.bottom - ((di->rcItem.bottom - di->rcItem.top) - (r.bottom - r.top)) / 2 - 1;
hPen = CreatePen(PS_SOLID, 0, (di->itemState & ODS_SELECTED) ? RGB(220, 0, 0) : RGB(0, 0, 220));
hOldPen = (HPEN) SelectObject(di->hDC, hPen);
MoveToEx(di->hDC, di->rcItem.left + 2, y, NULL);
LineTo(di->hDC, di->rcItem.right + 2 - ((di->rcItem.right - di->rcItem.left) - (r.right - r.left)), y);
SelectObject(di->hDC, hOldPen);
DeleteObject(hPen);
}
}
}
///////// if you update this, be sure to update the copy of it in $/winampa/winampicon.c
// thx.
int geticonid(int x)
{
switch (x) {
case 1: return IDI_FILEICON;
case 2: return IDI_FILEICON2;
case 3: return IDI_FILEICON3;
case 4: return IDI_FILEICON10;
case 5: return IDI_FILEICON5;
case 6: return IDI_FILEICON6;
case 7: return IDI_FILEICON7;
case 8: return IDI_FILEICON8;
case 9: return IDI_FILEICON9;
case 10: return IDI_FILEICON4;
case 11: return IDI_FILEICON11;
case 12: return ICON_TB1;
case 13: return -666;
default: return ICON_XP;
}
}
/*
void plSplineGetPoint(pl_Spline *s, float frame, float *out)
{
int i, i_1, i0, i1, i2;
float time1, time2, time3;
float t1, t2, t3, t4, u1, u2, u3, u4, v1, v2, v3;
float a, b, c, d;
float *keys = s->keys;
a = (1 - s->tens) * (1 + s->cont) * (1 + s->bias);
b = (1 - s->tens) * (1 - s->cont) * (1 - s->bias);
c = (1 - s->tens) * (1 - s->cont) * (1 + s->bias);
d = (1 - s->tens) * (1 + s->cont) * (1 - s->bias);
v1 = t1 = -a / 2.0f; u1 = a;
u2 = ( -6 - 2 * a + 2 * b + c) / 2.0f; v2 = (a - b) / 2.0f; t2 = (4 + a - b - c) / 2.0f;
t3 = ( -4 + b + c - d) / 2.0f;
u3 = (6 - 2 * b - c + d) / 2.0f;
v3 = b / 2.0f;
t4 = d / 2.0f; u4 = -t4;
i0 = (int) frame;
i_1 = i0 - 1;
while (i_1 < 0) i_1 += s->numKeys;
i1 = i0 + 1;
while (i1 >= s->numKeys) i1 -= s->numKeys;
i2 = i0 + 2;
while (i2 >= s->numKeys) i2 -= s->numKeys;
time1 = frame - (float) ((int) frame);
time2 = time1 * time1;
time3 = time2 * time1;
i0 *= s->keyWidth;
i1 *= s->keyWidth;
i2 *= s->keyWidth;
i_1 *= s->keyWidth;
for (i = 0; i < s->keyWidth; i ++)
{
a = t1 * keys[i + i_1] + t2 * keys[i + i0] + t3 * keys[i + i1] + t4 * keys[i + i2];
b = u1 * keys[i + i_1] + u2 * keys[i + i0] + u3 * keys[i + i1] + u4 * keys[i + i2];
c = v1 * keys[i + i_1] + v2 * keys[i + i0] + v3 * keys[i + i1];
*out++ = a * time3 + b * time2 + c * time1 + keys[i + i0];
}
}
*/
//int transAccel(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
//{
// HACCEL h;
// MSG msg;
// if (hwnd == hMainWindow) h = hAccel[0];
// else if (hwnd == hEQWindow) h = hAccel[1];
// else if (hwnd == hPLWindow) h = hAccel[2];
// // else if (hwnd==hMBWindow) h=hAccel[3];
// else if (hwnd == hVideoWindow || GetParent(hwnd) == hVideoWindow)
// {
// h = hAccel[0];
// }
// else
// {
// return 0;
// }
// msg.hwnd = hwnd;
// msg.lParam = lParam;
// msg.message = uMsg;
// msg.wParam = wParam;
// return TranslateAccelerator(hwnd, h, &msg);
//
//}
#include <pshpack4.h>
typedef struct
{
DWORD dwSize;
HANDLE hrasconn;
char szEntryName[256 + 1];
char szDeviceType[ 16 + 1 ];
char szDeviceName[ 128 + 1 ];
}
RASCONN ;
#include <poppack.h>
typedef DWORD (WINAPI *RASENUMCONNECTIONS)(RASCONN *lprasconn,
LPDWORD lpcb,
LPDWORD lpcConnections);
static int isRASActive()
{
int r = 0;
HINSTANCE h = LoadLibraryA("rasapi32.dll");
RASENUMCONNECTIONS RasEnumConnections;
RASCONN v = {sizeof(RASCONN), };
DWORD i = sizeof(v), o = 0;
if (!h) return 0;
RasEnumConnections = (RASENUMCONNECTIONS)GetProcAddress(h, "RasEnumConnectionsA");
if (RasEnumConnections && !RasEnumConnections(&v, &i, &o) && o) r = 1;
FreeModule(h);
return r;
}
int isInetAvailable(void)
{
if (config_inet_mode == 3)
{
if (isRASActive()) config_inet_mode = 1;
else config_inet_mode = 0;
return (1 == config_inet_mode);
}
if (config_inet_mode == 0) return 1;
if (config_inet_mode == 2) return 0;
return isRASActive();
}
unsigned int getDay(void)
{
unsigned int day = 0;
SYSTEMTIME tm, st = {0, };
FILETIME ft1, ft2;
ULARGE_INTEGER l1, l2;
GetSystemTime(&tm);
st.wYear = 1978;
st.wMonth = 10;
st.wDay = 14;
SystemTimeToFileTime(&tm, &ft1);
SystemTimeToFileTime(&st, &ft2);
memcpy(&l1, &ft1, sizeof(l1));
memcpy(&l2, &ft2, sizeof(l2));
day = (int) ((l1.QuadPart - l2.QuadPart) / (10 * 1000 * 1000) / (60 * 60 * 24));
return day;
}
void recent_add(const wchar_t *loc)
{
wchar_t ls[MAX_PATH] = {0};
_r_sW("RecentURL1", ls, MAX_PATH);
_w_sW("RecentURL1", loc);
if (wcscmp(ls, loc))
{
int x = 2;
while(1)
{
char s[123] = {0};
wchar_t temp[MAX_PATH] = {0};
StringCchPrintfA(s, 123, "RecentURL%d", x);
_r_sW(s, temp, MAX_PATH);
if (ls[0]) _w_sW(s, ls);
if (!_wcsicmp(temp, loc) || !temp[0])
break;
lstrcpynW(ls, temp, MAX_PATH);
x++;
}
}
}
#include <assert.h>
void getViewport(RECT *r, HWND wnd, int full, RECT *sr)
{
POINT *p = NULL;
if (p || sr || wnd)
{
HMONITOR hm = NULL;
if (sr)
hm = MonitorFromRect(sr, MONITOR_DEFAULTTONEAREST);
else if (wnd)
hm = MonitorFromWindow(wnd, MONITOR_DEFAULTTONEAREST);
else if (p)
hm = MonitorFromPoint(*p, MONITOR_DEFAULTTONEAREST);
if (hm)
{
MONITORINFOEXW mi;
memset(&mi, 0, sizeof(mi));
mi.cbSize = sizeof(mi);
if (GetMonitorInfoW(hm, &mi))
{
if (!full)
*r = mi.rcWork;
else
*r = mi.rcMonitor;
return ;
}
}
}
if (full)
{ // this might be borked =)
r->top = r->left = 0;
r->right = GetSystemMetrics(SM_CXSCREEN);
r->bottom = GetSystemMetrics(SM_CYSCREEN);
}
else
{
SystemParametersInfoW(SPI_GETWORKAREA, 0, r, 0);
}
}
BOOL windowOffScreen(HWND hwnd, POINT pt)
{
RECT r = {0}, wnd = {0}, sr = {0};
GetWindowRect(hwnd, &wnd);
sr.left = pt.x;
sr.top = pt.y;
sr.right = sr.left + (wnd.right - wnd.left);
sr.bottom = sr.top + (wnd.bottom - wnd.top);
getViewport(&r, hwnd, 0, &sr);
return !PtInRect(&r, pt);
}
void readwrite_client_uid(int isWrite, wchar_t uid_str[64])
{
HKEY hkey;
wchar_t path[MAX_PATH] = {0};
GetModuleFileNameW(0, path, MAX_PATH);
if (isWrite)
{
IFileTypeRegistrar *registrar=0;
if (GetRegistrar(&registrar, true) == 0 && registrar)
{
registrar->WriteClientUIDKey(path, uid_str);
registrar->Release();
}
return;
}
if (!isWrite) *uid_str = 0;
if (RegCreateKeyExW(HKEY_LOCAL_MACHINE, L"SOFTWARE\\Nullsoft\\Winamp", 0, 0, 0, KEY_READ, NULL, &hkey, NULL) == ERROR_SUCCESS)
{
DWORD s = 512, t = REG_SZ;
if (RegQueryValueExW(hkey, path, 0, &t, (LPBYTE)uid_str, &s) != ERROR_SUCCESS || t != REG_SZ) uid_str[0] = 0;
RegCloseKey(hkey);
}
}
BOOL read_compatmode()
{
HKEY hkey = NULL;
wchar_t path[MAX_PATH] = {0};
GetModuleFileNameW(0, path, MAX_PATH);
if (RegCreateKeyExW(HKEY_CURRENT_USER, L"Software\\Microsoft\\Windows NT\\CurrentVersion\\AppCompatFlags\\Layers", 0, 0, 0, KEY_READ, NULL, &hkey, NULL) == ERROR_SUCCESS)
{
DWORD s = 512, t = REG_SZ;
wchar_t buf[128] = {0};
if (RegQueryValueExW(hkey, path, 0, &t, (LPBYTE)buf, &s) != ERROR_SUCCESS || t != REG_SZ) buf[0] = 0;
RegCloseKey(hkey);
wchar_t *p = buf, *fields[] = {L"256COLOR", L"640X480", L"DISABLETHEMES", L"$",
L"DISABLEDWM", L"DISABLEUSERCALLBACKEXCEPTION",
L"HIGHDPIAWARE", L"RUNASADMIN", L"IGNOREFREELIBRARY",
L"ELEVATECREATEPROCESS", L"#", L"~", L"PLACEHOLDERFILES"};
int fields_len[] = {8, 7, 13, 1, 10, 28, 12, 10, 17, 20, 1, 1, 16};
while (p && *p)
{
wchar_t *pp = p;
while (pp && *pp && *pp != L' ')
{
pp = CharNextW(pp);
}
wchar_t pp_old = (pp ? *pp : 0);
if (pp && *pp) *pp = 0;
bool found = false;
for (int i = 0; i < sizeof(fields)/sizeof(fields[0]); i++)
{
if (!wcsncmp(fields[i], p, fields_len[i]))
found = true;
}
if (!found)
return TRUE;
if (pp) *pp = pp_old;
if (!pp_old) break;
p = CharNextW(pp);
}
}
return FALSE;
}
BOOL IsVista(void)
{
static INT fVista = -1;
if (-1 == fVista)
{
OSVERSIONINFO osver = {0};
osver.dwOSVersionInfoSize = sizeof( OSVERSIONINFO );
fVista = (::GetVersionEx(&osver) && osver.dwPlatformId == VER_PLATFORM_WIN32_NT && (osver.dwMajorVersion >= 6)) ? 1 : 0;
}
return (1 == fVista);
}
BOOL IsVistaOrLower(void)
{
static INT fVistaOrLower = -1;
if (-1 == fVistaOrLower)
{
OSVERSIONINFO osver = {0};
osver.dwOSVersionInfoSize = sizeof( OSVERSIONINFO );
fVistaOrLower = (::GetVersionEx(&osver) && osver.dwPlatformId == VER_PLATFORM_WIN32_NT &&
(osver.dwMajorVersion <= 5 || (osver.dwMajorVersion == 6 && osver.dwMinorVersion == 0))) ? 1 : 0;
}
return (1 == fVistaOrLower);
}
BOOL IsWin8(void)
{
static INT fWin8 = -1;
if (-1 == fWin8)
{
OSVERSIONINFO osver = {0};
osver.dwOSVersionInfoSize = sizeof( OSVERSIONINFO );
fWin8 = ( ::GetVersionEx(&osver) && osver.dwPlatformId == VER_PLATFORM_WIN32_NT && (osver.dwMajorVersion > 6 || (osver.dwMajorVersion == 6 && osver.dwMinorVersion >= 2))) ? 1 : 0;
}
return (1 == fWin8);
}
//XP Theme crap
typedef HRESULT (WINAPI * ENABLETHEMEDIALOGTEXTURE)(HWND, DWORD);
int IsWinXPTheme(void)
{
static int previousRet = -1;
if (previousRet == -1)
{
BOOL bEnabled(FALSE);
OSVERSIONINFO vi;
vi.dwOSVersionInfoSize = sizeof(OSVERSIONINFO);
if (GetVersionEx(&vi) && (vi.dwMajorVersion > 5 || (vi.dwMajorVersion == 5 && vi.dwMinorVersion > 0)))
{
HINSTANCE dll = LoadLibraryW(TEXT("uxtheme.dll"));
if (dll)
{
BOOL (WINAPI *waIsAppThemed)(void);
BOOL (WINAPI *waIsThemeActive)(void);
waIsAppThemed = (BOOL (WINAPI *)())GetProcAddress(dll, "IsAppThemed");
waIsThemeActive = (BOOL (WINAPI *)())GetProcAddress(dll, "IsThemeActive");
if (waIsAppThemed && waIsThemeActive && waIsAppThemed() && waIsThemeActive())
{
HMODULE hComCtl = LoadLibraryW(TEXT("comctl32.dll"));
if (hComCtl)
{
HRESULT (CALLBACK *waDllGetVersion)(DLLVERSIONINFO*) = (HRESULT (CALLBACK *)(DLLVERSIONINFO*))GetProcAddress(hComCtl, "DllGetVersion");
if (waDllGetVersion)
{
DLLVERSIONINFO dllVer;
dllVer.cbSize = sizeof(DLLVERSIONINFO);
if (S_OK == waDllGetVersion(&dllVer) && dllVer.dwMajorVersion >= 6) bEnabled = TRUE;
}
FreeLibrary(hComCtl);
}
}
FreeLibrary(dll);
}
}
previousRet = bEnabled;
}
return previousRet;
}
void DoWinXPStyle(HWND tab)
{
WAEnableThemeDialogTexture(tab, ETDT_ENABLETAB);
}
HRESULT WAEnableThemeDialogTexture(HWND hwnd, DWORD dwFlags)
{
static int uxThemeTried = 0;
static ENABLETHEMEDIALOGTEXTURE pfnETDT = NULL;
if(!uxThemeTried)
{
HINSTANCE ux_hDll;
if ((ux_hDll = LoadLibraryA("uxtheme.dll")) != NULL)
pfnETDT = (ENABLETHEMEDIALOGTEXTURE)GetProcAddress(ux_hDll, "EnableThemeDialogTexture");
uxThemeTried = 1;
}
return (pfnETDT) ? pfnETDT(hwnd, dwFlags) : E_NOTIMPL;
}
typedef BOOL(WINAPI*ISCOMPOSITIONACTIVE)(VOID);
int IsAero(void)
{
static int uxTried = 0;
static ISCOMPOSITIONACTIVE IsAeroActive = 0;
if (!uxTried)
{
static HMODULE UXTHEME = 0;
if ((UXTHEME = LoadLibraryA("uxtheme.dll")) != NULL)
IsAeroActive = (ISCOMPOSITIONACTIVE)GetProcAddress(UXTHEME, "IsCompositionActive");
uxTried = 1;
}
if (IsAeroActive)
return !!IsAeroActive();
else
return 0;
}
/*
int IsCharSpace(char digit)
{
WORD type=0;
GetStringTypeEx(LOCALE_USER_DEFAULT, CT_CTYPE1, &digit, 1, &type);
return type&C1_SPACE;
}
int IsCharSpaceW(wchar_t digit)
{
WORD type=0;
GetStringTypeExW(LOCALE_USER_DEFAULT, CT_CTYPE1, &digit, 1, &type);
return type&C1_SPACE;
}
*/
LPCWSTR BuildFullPath(LPCWSTR pszPathRoot, LPCWSTR pszPath, LPWSTR pszDest, INT cchDest)
{
LPCWSTR pszFile;
if (!pszPath || !*pszPath)
{
pszDest[0] = 0x00;
return pszDest;
}
pszFile = PathFindFileNameW(pszPath);
if (pszFile != pszPath)
{
if (PathIsRelativeW(pszPath))
{
wchar_t szTemp[MAX_PATH] = {0};
PathCombineW(szTemp, pszPathRoot, pszPath);
PathCanonicalizeW(pszDest, szTemp);
}
else StringCchCopyW(pszDest, cchDest, pszPath);
}
else {
if (pszPathRoot && *pszPathRoot) PathCombineW(pszDest, pszPathRoot, pszPath);
else StringCchCopyW(pszDest, cchDest, pszPath);
}
return pszDest;
}
INT ComparePath(LPCWSTR pszPath1, LPCWSTR pszPath2, LPCWSTR pszPathRoot) // compares two pathes
{
INT cr;
DWORD lcid;
LPCWSTR pszFile1, pszFile2;
if (!pszPath1 || !pszPath2) return 0;
lcid = MAKELCID(MAKELANGID(LANG_ENGLISH, SUBLANG_ENGLISH_US), SORT_DEFAULT);
pszFile1 = PathFindFileNameW(pszPath1);
pszFile2 = PathFindFileNameW(pszPath2);
cr = CompareStringW(lcid, NORM_IGNORECASE, pszFile1, -1, pszFile2, -1);
if (CSTR_EQUAL == cr && (pszFile1 != pszPath1 || pszFile2 != pszPath2))
{
wchar_t path1[MAX_PATH*2] = {0}, path2[MAX_PATH*2] = {0};
pszPath1 = BuildFullPath(pszPathRoot, pszPath1, path1, sizeof(path1)/sizeof(wchar_t));
pszPath2 = BuildFullPath(pszPathRoot, pszPath2, path2, sizeof(path2)/sizeof(wchar_t));
if (!pszPath1 || !pszPath2) return 0;
cr = CompareStringW(lcid, NORM_IGNORECASE, pszPath1, -1, path2, -1);
}
return cr;
}
BOOL DisabledWindow_OnMouseClick(HWND hwnd)
{
DWORD windowStyle = GetWindowLongPtrW(hwnd, GWL_STYLE);
if (WS_DISABLED != ((WS_CHILD | WS_DISABLED) & windowStyle))
return FALSE;
HWND hActive = GetActiveWindow();
HWND hPopup = GetWindow(hwnd, GW_ENABLEDPOPUP);
BOOL beepOk = (hPopup == hActive || hwnd == GetWindow(hActive, GW_OWNER));
if (!beepOk && NULL == hPopup)
{
for (HWND hWalker = hwnd; ;)
{
hWalker = GetWindow(hWalker, GW_OWNER);
if (NULL == hWalker || (0 != (WS_CHILD & GetWindowLongPtrW(hWalker, GWL_STYLE))))
break;
if (hActive == GetWindow(hWalker, GW_ENABLEDPOPUP))
{
beepOk = TRUE;
break;
}
}
}
if (beepOk)
{
if (config_accessibility_modalflash.GetBool())
{
FLASHWINFO flashInfo;
flashInfo.cbSize = sizeof(FLASHWINFO);
flashInfo.hwnd = hActive;
flashInfo.dwFlags = FLASHW_CAPTION;
flashInfo.uCount = 2;
flashInfo.dwTimeout = 100;
FlashWindowEx(&flashInfo);
}
if (config_accessibility_modalbeep.GetBool())
MessageBeep(MB_OK);
}
else
{
for (HWND hWalker = hwnd; NULL == hPopup;)
{
hWalker = GetWindow(hWalker, GW_OWNER);
if (NULL == hWalker || (0 != (WS_CHILD & GetWindowLongPtrW(hWalker, GWL_STYLE))))
break;
hPopup = GetWindow(hWalker, GW_ENABLEDPOPUP);
}
SetWindowPos(hwnd, HWND_TOP, 0, 0, 0, 0, SWP_NOACTIVATE | SWP_NOSIZE | SWP_NOMOVE);
if (NULL != hPopup && hPopup != hwnd)
{
BringWindowToTop(hPopup);
SetActiveWindow(hPopup);
}
}
return TRUE;
}