//	Album List for Winamp
//	Copyright (C) 1999-2001 Safai Ma
//
//	This program is free software; you can redistribute it and/or modify
//	it under the terms of the GNU General Public License as published by
//	the Free Software Foundation; either version 2 of the License, or
//	(at your option) any later version.
//
//	This program is distributed in the hope that it will be useful,
//	but WITHOUT ANY WARRANTY; without even the implied warranty of
//	MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
//	GNU General Public License for more details.
//
//	You should have received a copy of the GNU General Public License
//	along with this program; if not, write to the Free Software
//	Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
#include "stdafx.h"
#include <shlobj.h>
#include <shlguid.h>
#include <stdlib.h>
#include <mbstring.h>
#include <shellapi.h>
#include "resource.h"

#include "winampalbumlist.h"
#include "gen.h"
#include "config.h"

extern CWinampAlbumList winampAL;

char szPluginINI[MAX_PATH]		= "";
char szLangDir[MAX_PATH]		= "";
char szLangINI[MAX_PATH]		= "";
char szAlbumListDir[MAX_PATH]	= "";
char szAlbumListPluginDir[MAX_PATH] = "";
char szAppName[64]		= "Album List";
int  al_instance		= 0;
int  al_wx				= 30000;
int  al_wy				= 30000;
int  al_open			= 1;
int	 al_ws				= 0;
int  al_width			= MIN_WIDTH;
int  al_height			= MIN_HEIGHT;
int  al_language		= IDC_LANGUAGE_ENU;
char al_lang[MAX_PATH]	= "";
BOOL al_add_cdroms		= TRUE;
char al_index[MAX_PATH] = "";
int  al_timeformat		= 1;	// 0 - off, 1 - 8:88:88, 2 - 888:88, 3 - (888)
int  al_sortalbum		= 0;	// 0 - off, 1 - path, 2 - name, 3 - artist, 4 - year, 5 - num. of songs, 6 - total time
int  al_alphablend		= 255;
int  al_shownum			= 0;
int  al_showyear		= 0;
int  al_newverchk		= 1;
int  al_lastverchk		= 0;
int  al_ignore_pl		= 0;
int  al_ignore_m3u		= 0;
int  al_useid3			= 1;
int  al_dirstyle		= 0;
int  al_useplskin		= 1;
int  al_rmpltitle		= 1;
int  al_usecompression	= 1;
int  al_startup_scan	= 1;
int	 al_enqueue			= 0;
int  al_keepsp			= 0;
int  al_curver			= 0;
int  al_loop			= 0;
int  al_showcover       = 0;
int  al_sortname        = 0;
int	 al_fontsize		= 0;
int  al_searchsubdir	= 1;
int  al_fixtitles		= 1;
int  al_multidiscfix	= 0;
int  al_logfile			= 0;
int  al_autoadvance		= 0;
BOOL al_resume_play		= 1;
int  al_resume_time		= -1;
int  al_resume_pos		= 0;
char al_extlist[MAX_PATH] = "MP3, MPC, MP+, MPP, WMA, WAV, APE, MAC, SPC";
char al_multidiscnames[MAX_PATH] = "cd, disc";
int  pe_fontsize		= 10;
int  aot				= 0;
int  easymove			= 0;
int	 snap				= 1;
int	 snaplen			= 10;
int  shownumsinpl		= 1;
int  usecursors         = 1;
int  hilite				= 1;
int  fixtitles			= 3;
int  keeponscreen		= 1;
int  addtolist          = 0;
int  randskin			= 0;
int  bifont				= 1;
int  color_normal		= RGB(0x00,0xff,0x00);
int  color_current		= RGB(0xff,0xff,0xff);
int  color_normalbg		= RGB(0x00,0x00,0x00);
int  color_selectedbg	= RGB(0x00,0x00,0xc6);
int  color_cdrom		= RGB(0x00,0xff,0xff);
char color_font[MAX_PATH] = "Arial";
DWORD wa_version		= 0x2000;

// non-setting variables
HWND hWndConfigPage		= NULL;
BOOL bInternetReady		= FALSE;

BOOL bRefresh = FALSE;
BOOL bRefresh2 = FALSE;
BOOL bRefresh3 = FALSE;

void AutoLanguageDetection();

void config_read()
{
	char ini_file[MAX_PATH], *p;
	GetModuleFileName(plugin.hDllInstance, ini_file, sizeof(ini_file));
	p = (char *)_mbsrchr((unsigned char *)ini_file,'\\');
	if (p == NULL)
	{
		p = ini_file;
	}
	if (++p >= ini_file) *p = 0;
	lstrcpy (szAlbumListDir, ini_file);
	lstrcpy (szAlbumListPluginDir, szAlbumListDir);
	lstrcat (szAlbumListPluginDir, "Album List\\Plugins\\");
	wsprintf(szPluginINI, "%s%s", ini_file, "plugin.ini");

	al_wx			= GetPrivateProfileInt(szAppName, "al_wx",			al_wx,			szPluginINI);
	al_wy			= GetPrivateProfileInt(szAppName, "al_wy",			al_wy,			szPluginINI);
	al_ws			= GetPrivateProfileInt(szAppName, "al_ws",			al_ws,			szPluginINI);
	al_open			= GetPrivateProfileInt(szAppName, "al_open",		al_open,		szPluginINI);
	al_width		= GetPrivateProfileInt(szAppName, "al_width",		al_width,		szPluginINI);
	al_height		= GetPrivateProfileInt(szAppName, "al_height",		al_height,		szPluginINI);
	al_language		= GetPrivateProfileInt(szAppName, "al_language",	al_language,	szPluginINI);
	al_add_cdroms	= GetPrivateProfileInt(szAppName, "al_add_cdroms",	al_add_cdroms,	szPluginINI);
	al_timeformat	= GetPrivateProfileInt(szAppName, "al_timeformat",	al_timeformat,	szPluginINI);
	al_sortalbum	= GetPrivateProfileInt(szAppName, "al_sortalbum",	al_sortalbum,	szPluginINI);
	al_sortname		= GetPrivateProfileInt(szAppName, "al_sortname",	al_sortname,	szPluginINI);
	al_shownum		= GetPrivateProfileInt(szAppName, "al_shownum",		al_shownum,		szPluginINI);
	al_showyear		= GetPrivateProfileInt(szAppName, "al_showyear",	al_showyear,	szPluginINI);
	al_newverchk	= GetPrivateProfileInt(szAppName, "al_newverchk",	al_newverchk,	szPluginINI);
	al_ignore_pl	= GetPrivateProfileInt(szAppName, "al_ignore_pl",	al_ignore_pl,	szPluginINI);
	al_ignore_m3u	= GetPrivateProfileInt(szAppName, "al_ignore_m3u",	al_ignore_m3u,	szPluginINI);
	al_useid3		= GetPrivateProfileInt(szAppName, "al_useid3",		al_useid3,		szPluginINI);
	al_dirstyle		= GetPrivateProfileInt(szAppName, "al_dirstyle",	al_dirstyle,	szPluginINI);
	al_lastverchk	= GetPrivateProfileInt(szAppName, "al_lastverchk",	al_lastverchk,	szPluginINI);
	al_useplskin	= GetPrivateProfileInt(szAppName, "al_useplskin",	al_useplskin,	szPluginINI);
	al_rmpltitle	= GetPrivateProfileInt(szAppName, "al_rmpltitle",	al_rmpltitle,	szPluginINI);
	al_startup_scan	= GetPrivateProfileInt(szAppName, "al_startup_scan",al_startup_scan,szPluginINI);
	al_enqueue		= GetPrivateProfileInt(szAppName, "al_enqueue",		al_enqueue,		szPluginINI);
	al_keepsp		= GetPrivateProfileInt(szAppName, "al_keepsp",		al_keepsp,		szPluginINI);
	al_loop			= GetPrivateProfileInt(szAppName, "al_loop",		al_loop,		szPluginINI);
	al_showcover	= GetPrivateProfileInt(szAppName, "al_showcover",	al_showcover,	szPluginINI);
	al_searchsubdir	= GetPrivateProfileInt(szAppName, "al_searchsubdir",al_searchsubdir,szPluginINI);
	al_fixtitles	= GetPrivateProfileInt(szAppName, "al_fixtitles",	al_fixtitles,	szPluginINI);
	al_multidiscfix	= GetPrivateProfileInt(szAppName, "al_multidiscfix",al_multidiscfix,szPluginINI);
	al_autoadvance	= GetPrivateProfileInt(szAppName, "al_autoadvance", al_autoadvance, szPluginINI);
	al_resume_play	= GetPrivateProfileInt(szAppName, "al_resume_play",	al_resume_play,	szPluginINI);
	al_resume_time	= GetPrivateProfileInt(szAppName, "al_resume_time",	al_resume_time,	szPluginINI);
	al_resume_pos	= GetPrivateProfileInt(szAppName, "al_resume_pos",	al_resume_pos,	szPluginINI);

	// get last selected path
	GetPrivateProfileString(szAppName, "al_index", "", al_index, MAX_PATH, szPluginINI);
	GetPrivateProfileString(szAppName, "al_extlist", al_extlist, al_extlist, MAX_PATH, szPluginINI);
	GetPrivateProfileString(szAppName, "al_multidiscnames", al_multidiscnames, al_multidiscnames, MAX_PATH, szPluginINI);

	GetPrivateProfileString(szAppName, "al_lang", "", al_lang, MAX_PATH, szPluginINI);
	AutoLanguageDetection();
	wsprintf(szLangDir, "%s%s", ini_file, "Album List\\Language");
	wsprintf(szLangINI, "%s\\%s", szLangDir, al_lang);

	// read only variable
	al_alphablend	  = GetPrivateProfileInt(szAppName, "al_alphablend",	al_alphablend,	  szPluginINI);
	al_usecompression = GetPrivateProfileInt(szAppName, "al_usecompression",al_usecompression,szPluginINI);
	al_fontsize		  = GetPrivateProfileInt(szAppName, "al_fontsize",		al_fontsize,	  szPluginINI);
	al_logfile		  = GetPrivateProfileInt(szAppName, "al_logfile",		al_logfile,		  szPluginINI);

	// range check
	if ((al_alphablend < 0) || (255 < al_alphablend)) al_alphablend = 255;
	if (al_timeformat == 3) al_timeformat = 0, al_shownum = 1;
}

void config_write()
{
	char string[32];

	wsprintf(string, "%ld", al_wx);			WritePrivateProfileString(szAppName, "al_wx",		 string, szPluginINI);
	wsprintf(string, "%ld", al_wy);			WritePrivateProfileString(szAppName, "al_wy",		 string, szPluginINI);
	wsprintf(string, "%ld", al_ws);			WritePrivateProfileString(szAppName, "al_ws",		 string, szPluginINI);
	wsprintf(string, "%ld", al_open);		WritePrivateProfileString(szAppName, "al_open",		 string, szPluginINI);
	wsprintf(string, "%ld", al_width);		WritePrivateProfileString(szAppName, "al_width",	 string, szPluginINI);
	wsprintf(string, "%ld", al_height);		WritePrivateProfileString(szAppName, "al_height",	 string, szPluginINI);
	wsprintf(string, "%ld", al_language);	WritePrivateProfileString(szAppName, "al_language",	 string, szPluginINI);
	wsprintf(string, "%ld", al_add_cdroms);	WritePrivateProfileString(szAppName, "al_add_cdroms",string, szPluginINI);
	wsprintf(string, "%ld", al_timeformat);	WritePrivateProfileString(szAppName, "al_timeformat",string, szPluginINI);
	wsprintf(string, "%ld", al_sortalbum);	WritePrivateProfileString(szAppName, "al_sortalbum", string, szPluginINI);
	wsprintf(string, "%ld", al_sortname);	WritePrivateProfileString(szAppName, "al_sortname",	 string, szPluginINI);
	wsprintf(string, "%ld", al_shownum);	WritePrivateProfileString(szAppName, "al_shownum",	 string, szPluginINI);
	wsprintf(string, "%ld", al_showyear);	WritePrivateProfileString(szAppName, "al_showyear",	 string, szPluginINI);
	wsprintf(string, "%ld", al_newverchk);	WritePrivateProfileString(szAppName, "al_newverchk", string, szPluginINI);
	wsprintf(string, "%ld", al_ignore_pl);	WritePrivateProfileString(szAppName, "al_ignore_pl", string, szPluginINI);
	wsprintf(string, "%ld", al_ignore_m3u);	WritePrivateProfileString(szAppName, "al_ignore_m3u",string, szPluginINI);
	wsprintf(string, "%ld", al_useid3);		WritePrivateProfileString(szAppName, "al_useid3",	 string, szPluginINI);
	wsprintf(string, "%ld", al_dirstyle);	WritePrivateProfileString(szAppName, "al_dirstyle",	 string, szPluginINI);
	wsprintf(string, "%ld", al_lastverchk);	WritePrivateProfileString(szAppName, "al_lastverchk",string, szPluginINI);
	wsprintf(string, "%ld", al_useplskin);	WritePrivateProfileString(szAppName, "al_useplskin", string, szPluginINI);
	wsprintf(string, "%ld", al_rmpltitle);	WritePrivateProfileString(szAppName, "al_rmpltitle", string, szPluginINI);
	wsprintf(string, "%ld", al_startup_scan);	WritePrivateProfileString(szAppName, "al_startup_scan", string, szPluginINI);
	wsprintf(string, "%ld", al_enqueue);	WritePrivateProfileString(szAppName, "al_enqueue",	 string, szPluginINI);
	wsprintf(string, "%ld", al_keepsp);		WritePrivateProfileString(szAppName, "al_keepsp",	 string, szPluginINI);
	wsprintf(string, "%ld", al_loop);		WritePrivateProfileString(szAppName, "al_loop",		 string, szPluginINI);
	wsprintf(string, "%ld", al_showcover);	WritePrivateProfileString(szAppName, "al_showcover", string, szPluginINI);
	wsprintf(string, "%ld", al_fontsize);	WritePrivateProfileString(szAppName, "al_fontsize",	 string, szPluginINI);
	wsprintf(string, "%ld", al_searchsubdir);	WritePrivateProfileString(szAppName, "al_searchsubdir", string, szPluginINI);
	wsprintf(string, "%ld", al_fixtitles);	WritePrivateProfileString(szAppName, "al_fixtitles", string, szPluginINI);
	wsprintf(string, "%ld", al_multidiscfix);	WritePrivateProfileString(szAppName, "al_multidiscfix", string, szPluginINI);
	wsprintf(string, "%ld", al_autoadvance);	WritePrivateProfileString(szAppName, "al_autoadvance", string, szPluginINI);
	wsprintf(string, "%ld", al_resume_play);	WritePrivateProfileString(szAppName, "al_resume_play", string, szPluginINI);
	wsprintf(string, "%ld", al_resume_time);	WritePrivateProfileString(szAppName, "al_resume_time", string, szPluginINI);
	wsprintf(string, "%ld", al_resume_pos);	WritePrivateProfileString(szAppName, "al_resume_pos", string, szPluginINI);

	WritePrivateProfileString(szAppName, "al_index", al_index, szPluginINI);
	WritePrivateProfileString(szAppName, "al_extlist", al_extlist, szPluginINI);
	WritePrivateProfileString(szAppName, "al_lang", al_lang, szPluginINI);
	WritePrivateProfileString(szAppName, "al_multidiscnames", al_multidiscnames, szPluginINI);
}

void config_winamp_read()
{
	char szWinampINI[MAX_PATH] = "";
	char ini_file[MAX_PATH], *p;
	GetModuleFileName(NULL, ini_file, sizeof(ini_file));
	p = (char *)_mbsrchr((unsigned char *)ini_file,'\\');
	if (p == NULL) p = ini_file;
	if (++p >= ini_file) *p = 0;
	wsprintf(szWinampINI, "%s%s", ini_file, "winamp.ini");

	snap		= GetPrivateProfileInt("Winamp", "snap",		snap,		 szWinampINI);
	snaplen		= GetPrivateProfileInt("Winamp", "snaplen",		snaplen,	 szWinampINI);
	pe_fontsize	= GetPrivateProfileInt("Winamp", "pe_fontsize",	pe_fontsize, szWinampINI);
	easymove	= GetPrivateProfileInt("Winamp", "easymove",	easymove,	 szWinampINI);
	shownumsinpl= GetPrivateProfileInt("Winamp", "shownumsinpl",shownumsinpl,szWinampINI);
	usecursors  = GetPrivateProfileInt("Winamp", "usecursors",	usecursors,  szWinampINI);
	hilite		= GetPrivateProfileInt("Winamp", "hilite",		hilite,		 szWinampINI);
	fixtitles	= GetPrivateProfileInt("Winamp", "fixtitles",	fixtitles,	 szWinampINI);
	keeponscreen= GetPrivateProfileInt("Winamp", "keeponscreen",keeponscreen,szWinampINI);
	addtolist	= GetPrivateProfileInt("Winamp", "addtolist",	addtolist,	 szWinampINI);
	aot			= GetPrivateProfileInt("Winamp", "aot",			aot,		 szWinampINI);
	randskin	= GetPrivateProfileInt("Winamp", "randskin",	randskin,	 szWinampINI);
	bifont		= GetPrivateProfileInt("Winamp", "bifont",		bifont,		 szWinampINI);
}

/////////////////////////////////////////////////////////////////////////
// UTIL FUNCTIONS
//

void GetVersionInformation(int &major, int &minor, int &build)
{
	// Get version information
	char				szFullPath[256];
	DWORD				dwVerHnd=0;			// An 'ignored' parameter, always '0'
	VS_FIXEDFILEINFO*	lpVersion;			// Pointer to 'Fixed' file info
	UINT				uVersionLen;

	GetModuleFileName(plugin.hDllInstance, szFullPath, sizeof(szFullPath));
	DWORD dwVerInfoSize = GetFileVersionInfoSize(szFullPath, &dwVerHnd);
	if (dwVerInfoSize)
	{
		LPSTR   lpstrVffInfo;
		HANDLE  hMem;

		// allocate memory for version block
		hMem = GlobalAlloc(GMEM_MOVEABLE, dwVerInfoSize);
		lpstrVffInfo  = (LPSTR)GlobalLock(hMem);
		GetFileVersionInfo(szFullPath, dwVerHnd, dwVerInfoSize, lpstrVffInfo);
		BOOL bRetCode = VerQueryValue(	lpstrVffInfo, "\\", (LPVOID *)&lpVersion, &uVersionLen);
		if (bRetCode)
		{
			// access version information
			major = HIWORD(lpVersion->dwProductVersionMS);
			minor = LOWORD(lpVersion->dwProductVersionMS);
			build = LOWORD(lpVersion->dwFileVersionLS);
		}

		GlobalUnlock(hMem);
		GlobalFree(hMem);
	}
}

void CenterWindow(HWND hwnd)
{
	RECT rc;
	GetClientRect(hwnd, &rc);

	RECT rc2;
	GetWindowRect(GetParent(hwnd), &rc2);

	int x = rc2.left + (rc2.right - rc2.left  - rc.right) / 2;
	int y = rc2.top + (rc2.bottom - rc2.top - rc.bottom) / 2;

	SetWindowPos(hwnd, NULL, x, y, 0, 0, SWP_NOZORDER|SWP_NOSIZE|SWP_NOACTIVATE);
}

LONG GetRegKey(HKEY key, LPCTSTR subkey, LPTSTR retdata)
{
    HKEY hkey;
    LONG retval = RegOpenKeyEx(key, subkey, 0, KEY_QUERY_VALUE, &hkey);

    if (retval == ERROR_SUCCESS) {
        long datasize = MAX_PATH;
		TCHAR data[MAX_PATH];
		RegQueryValue(hkey, NULL, data, &datasize);
		lstrcpy(retdata,data);
		RegCloseKey(hkey);
    }

    return retval;
}

HINSTANCE GotoURL(LPCTSTR url, int showcmd)
{
    TCHAR key[MAX_PATH + MAX_PATH];	

    // First try ShellExecute()
    HINSTANCE result = ShellExecute(NULL, "open", url, NULL,NULL, showcmd);

    // If it failed, get the .htm regkey and lookup the program
    if ((UINT)result <= HINSTANCE_ERROR) {		
		
        if (GetRegKey(HKEY_CLASSES_ROOT, ".htm", key) == ERROR_SUCCESS) {
            lstrcat(key, "\\shell\\open\\command");

            if (GetRegKey(HKEY_CLASSES_ROOT,key,key) == ERROR_SUCCESS) {
                TCHAR *pos;
                pos = strstr(key, "\"%1\"");
                if (pos == NULL) {                     // No quotes found
                    pos = strstr(key, "%1");       // Check for %1, without quotes
                    if (pos == NULL)                   // No parameter at all...
                        pos = key+lstrlen(key)-1;
                    else
                        *pos = '\0';                   // Remove the parameter
                }
                else
                    *pos = '\0';                       // Remove the parameter

                lstrcat(pos, " ");
                lstrcat(pos, url);
                result = (HINSTANCE) WinExec(key,showcmd);
            }
        }
	}
	  
    return result;
}

typedef struct _tagALEnumThreadWnd
{
	LPCTSTR lpClassName;
	LPCTSTR lpWindowName;
	union
	{
		HWND	hWnd;
		DWORD	nCount;
	};
}	ALEnumThreadWnd, *LPALEnumThreadWnd;

char szWindowName[MAX_PATH];
char szClassName[MAX_PATH];

BOOL CALLBACK EnumThreadWndProc(HWND hwnd, LPARAM lParam)
{
	LPALEnumThreadWnd lpEnumData = (LPALEnumThreadWnd)lParam;

	if (lpEnumData->lpWindowName)
	{
		GetWindowText(hwnd, szWindowName, MAX_PATH);
		if (lstrcmp(lpEnumData->lpWindowName, szWindowName) == 0)
		{
			lpEnumData->hWnd = hwnd;
			return FALSE;
		}
	}
	else if (lpEnumData->lpClassName)
	{
		GetClassName(hwnd, szClassName, MAX_PATH);
		if (lstrcmp(lpEnumData->lpClassName, szClassName) == 0)
		{
			lpEnumData->hWnd = hwnd;
			return FALSE;
		}
	}
	return TRUE;
}

HWND ALFindWindow(LPCTSTR lpClassName, LPCTSTR lpWindowName)
{
	DWORD dwThreadId = GetCurrentThreadId();
 
	ALEnumThreadWnd EnumData;
	EnumData.lpClassName = lpClassName;
	EnumData.lpWindowName = lpWindowName;
	EnumData.hWnd = NULL;

	if (EnumThreadWindows(dwThreadId, EnumThreadWndProc, (LPARAM)&EnumData))
	{
		return EnumData.hWnd;
	}
	return EnumData.hWnd;
}

/////////////////////////////////////////////////////////////////////////

BOOL CALLBACK EnumThreadWndProcCount(HWND hwnd, LPARAM lParam)
{
	LPALEnumThreadWnd lpEnumData = (LPALEnumThreadWnd)lParam;

	if (lpEnumData->lpWindowName)
	{
		GetWindowText(hwnd, szWindowName, MAX_PATH);
		if (lstrcmp(lpEnumData->lpWindowName, szWindowName) == 0)
		{
			lpEnumData->nCount ++;
			return TRUE;
		}
	}
	else if (lpEnumData->lpClassName)
	{
		GetClassName(hwnd, szClassName, MAX_PATH);
		if (lstrcmp(lpEnumData->lpClassName, szClassName) == 0)
		{
			lpEnumData->nCount ++;
			return TRUE;
		}
	}
	return TRUE;
}

int ALCountWindow(LPCTSTR lpClassName, LPCTSTR lpWindowName)
{
	DWORD dwThreadId = GetCurrentThreadId();
 
	ALEnumThreadWnd EnumData;
	EnumData.lpClassName = lpClassName;
	EnumData.lpWindowName = lpWindowName;
	EnumData.nCount = 0;

	if (EnumThreadWindows(dwThreadId, EnumThreadWndProcCount, (LPARAM)&EnumData))
	{
		return EnumData.nCount;
	}
	return EnumData.nCount;
}

/////////////////////////////////////////////////////////////////////////
// JUMP TO ALBUM
//

LRESULT CALLBACK WndProcSearchText(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
{
	LRESULT (CALLBACK *pOldWndProc)(HWND, UINT, WPARAM, LPARAM) = (LRESULT(CALLBACK *)(HWND, UINT, WPARAM, LPARAM))GetProp(hwnd, "OldWndProc");

	POINT point = { (short)LOWORD(lParam), (short)HIWORD(lParam) };

	switch (message)
	{
	case WM_KEYDOWN:
	case WM_KEYUP:
		if ((wParam == VK_DOWN) || (wParam == VK_UP))
		{
			HWND hListBox = GetDlgItem(GetParent(hwnd), IDC_ALBUMLIST);
			SendMessage(hListBox, message, wParam, lParam);
			return TRUE;
		}
	}

	return CallWindowProc(pOldWndProc, hwnd, message, wParam, lParam);
}

void OnInitDialogJumpToAlbum(HWND hwndDlg)
{
	HWND hwndList = GetDlgItem(hwndDlg, IDC_ALBUMLIST);

	int nSel = 0;
	int size = winampAL.m_AlbumList.GetSize();
	for (int i=0; i<size; i++)
	{
		LPALBUMINFO pAlbumInfo = winampAL.m_AlbumList.GetAlbum(i);
		int nIndex = SendMessage(hwndList, LB_ADDSTRING, 0, (LPARAM)pAlbumInfo->name);
		if ((nIndex != LB_ERR) && (nIndex != LB_ERRSPACE))
		{
			SendMessage(hwndList, LB_SETITEMDATA, nIndex, i);
			if (lstrcmp(pAlbumInfo->path, al_index) == 0)
			{
				nSel = nIndex;
			}
		}
	}

	SendMessage(hwndList, LB_SETCURSEL, nSel, 0);

	// version static
	HWND hWnd = GetDlgItem(hwndDlg, IDC_SEARCHTEXT);

	SetProp(hWnd, "OldWndProc", (HANDLE)GetWindowLong(hWnd, GWL_WNDPROC));
	SetWindowLong(hWnd, GWL_WNDPROC, (LONG)WndProcSearchText);
}

void OnChangeSearchText(HWND hwndDlg)
{
	char szSearchText[MAX_PATH];
	GetWindowText(GetDlgItem(hwndDlg, IDC_SEARCHTEXT), szSearchText, MAX_PATH);
	_mbslwr((unsigned char *)szSearchText);

	HWND hwndList = GetDlgItem(hwndDlg, IDC_ALBUMLIST);

	// remove all the contents
	SendMessage(hwndList, LB_RESETCONTENT, 0, 0);

	char name[MAX_PATH] = "";

	int len = lstrlen(szSearchText);

	// no search string entered, list everything
	if (len == 0)
	{
		int size = winampAL.m_AlbumList.GetSize();
		for (int i=0; i<size; i++)
		{
			wsprintf(name, "%ld. %s", i+1, winampAL.m_AlbumList.GetAlbum(i)->name);
			int nIndex = SendMessage(hwndList, LB_ADDSTRING, 0, (LPARAM)name);//winampAL.m_AlbumList.GetAlbum(i)->name);
			if ((nIndex != LB_ERR) && (nIndex != LB_ERRSPACE))
			{
				SendMessage(hwndList, LB_SETITEMDATA, nIndex, i);
			}
		}

		SendMessage(hwndList, LB_SETCURSEL, 0, 0);

		return;
	}

	char string[MAX_PATH] = "";
	char *token = NULL;
	char seps[] = " ?,\"'~!.-:;\t\n";

	int size = winampAL.m_AlbumList.GetSize();
	for (int i=0; i<size; i++)
	{
		LPALBUMINFO pAlbumInfo = winampAL.m_AlbumList.GetAlbum(i);

		// do year search as well when the search string
		// is at least 4 characters
		if (len >= 4)	wsprintf(name, "%ld %s %ld", i+1, pAlbumInfo->name, pAlbumInfo->nYear);
		else			wsprintf(name, "%ld %s", i+1, pAlbumInfo->name);

		_mbslwr((unsigned char *)name);
		lstrcpyn(string, szSearchText, MAX_PATH);

		BOOL bFound = TRUE;

		token = strtok(string, seps);
		while( token != NULL )
		{
			// While there are tokens in "szSearchText"
			if (strstr(name, token) == NULL)
			{
				bFound = FALSE;
				break;
			}

			// Get next token:
			token = strtok(NULL, seps);
		}

		if (bFound)
		{
			wsprintf(name, "%ld. %s", i+1, pAlbumInfo->name);

			int nIndex = SendMessage(hwndList, LB_ADDSTRING, 0, (LPARAM)name);//pAlbumInfo->name);
			if ((nIndex != LB_ERR) && (nIndex != LB_ERRSPACE))
			{
				SendMessage(hwndList, LB_SETITEMDATA, nIndex, i);
			}
		}
	}

	SendMessage(hwndList, LB_SETCURSEL, 0, 0);
}

void OnDblClkAlbumList(HWND hwndDlg)
{
	HWND hwndList = GetDlgItem(hwndDlg, IDC_ALBUMLIST);

	int nCurSel = SendMessage(hwndList, LB_GETCURSEL, 0, 0);
	if (nCurSel == LB_ERR) return;

	int nIndex = SendMessage(hwndList, LB_GETITEMDATA, nCurSel, 0);
	if (nIndex == LB_ERR) return;

	if (GetKeyState(VK_SHIFT) & 0x80000000)
	{
		winampAL.EnqueueAlbum(nIndex);
	}
	else
	{
		winampAL.SelectAlbum(nIndex);
	}
}

BOOL CALLBACK JumpToAlbumProc(HWND hwndDlg, UINT uMsg, WPARAM wParam, LPARAM lParam)
{
	switch (uMsg)
	{
	case WM_INITDIALOG:
		OnInitDialogJumpToAlbum(hwndDlg);
		UpdateDialogStrings(hwndDlg);
		return TRUE;

	case WM_COMMAND:
		switch (LOWORD(wParam))
		{
		case IDOK:
			OnDblClkAlbumList(hwndDlg);
			EndDialog(hwndDlg, 0);
			return TRUE;

		case IDCANCEL:
			EndDialog(hwndDlg, 0);
			return TRUE;

		case IDC_SEARCHTEXT:
			switch (HIWORD(wParam))
			{
			case EN_CHANGE:
				OnChangeSearchText(hwndDlg);
				return TRUE;
			}
			break;

		case IDC_ALBUMLIST:
			switch (HIWORD(wParam))
			{
			case LBN_DBLCLK:
				OnDblClkAlbumList(hwndDlg);
				EndDialog(hwndDlg, 0);
				return TRUE;
			}
			break;
		}
		break;
	}

	return FALSE;
}

/////////////////////////////////////////////////////////////////////////
// RENAME ALBUM
//

void OnInitDialogRenameAlbum(HWND hwndDlg)
{
	RECT rcWnd, rcParent;
	GetWindowRect(winampAL.GetSafeHwnd(), &rcParent);
	GetWindowRect(hwndDlg, &rcWnd);

	int nHeight = rcWnd.bottom - rcWnd.top;

	if (GetSystemMetrics(SM_CYSCREEN) >= (rcParent.bottom + nHeight))
	{
		SetWindowPos(hwndDlg, NULL, rcWnd.left, rcParent.bottom, 0, 0, SWP_NOSIZE|SWP_NOZORDER|SWP_NOACTIVATE);
	}
	else if (0 <= (rcParent.top - nHeight))
	{
		SetWindowPos(hwndDlg, NULL, rcWnd.left, rcParent.top - nHeight, 0, 0, SWP_NOSIZE|SWP_NOZORDER|SWP_NOACTIVATE);
	}

	HWND hWnd = GetDlgItem(hwndDlg, IDC_NEWNAME);
	LPALBUMINFO pAlbumInfo = winampAL.GetCurrentAlbum();
	if (pAlbumInfo)
	{
		SetWindowText(hWnd, pAlbumInfo->name);
	}
}

void OnRenameAlbum(HWND hwndDlg)
{
	HWND hWnd = GetDlgItem(hwndDlg, IDC_NEWNAME);
	LPALBUMINFO pAlbumInfo = winampAL.GetCurrentAlbum();
	if (pAlbumInfo)
	{
		GetWindowText(hWnd, pAlbumInfo->name, MAX_PATH);
	}
}

BOOL CALLBACK RenameAlbumProc(HWND hwndDlg, UINT uMsg, WPARAM wParam, LPARAM lParam)
{
	switch (uMsg)
	{
	case WM_INITDIALOG:
		OnInitDialogRenameAlbum(hwndDlg);
		UpdateDialogStrings(hwndDlg);
		return TRUE;

	case WM_COMMAND:
		switch (LOWORD(wParam))
		{
		case IDOK:
			OnRenameAlbum(hwndDlg);
			EndDialog(hwndDlg, IDOK);
			return TRUE;

		case IDCANCEL:
			EndDialog(hwndDlg, IDCANCEL);
			return TRUE;
		}
		break;
	}

	return FALSE;
}


/////////////////////////////////////////////////////////////////////////
// ALBUM INFO
//

void OnInitDialogAlbumInfo(HWND hwndDlg)
{
	RECT rcWnd, rcParent;
	GetWindowRect(winampAL.GetSafeHwnd(), &rcParent);
	GetWindowRect(hwndDlg, &rcWnd);

	int nHeight = rcWnd.bottom - rcWnd.top;

	if (GetSystemMetrics(SM_CYSCREEN) >= (rcParent.bottom + nHeight))
	{
		SetWindowPos(hwndDlg, NULL, rcWnd.left, rcParent.bottom, 0, 0, SWP_NOSIZE|SWP_NOZORDER|SWP_NOACTIVATE);
	}
	else if (0 <= (rcParent.top - nHeight))
	{
		SetWindowPos(hwndDlg, NULL, rcWnd.left, rcParent.top - nHeight, 0, 0, SWP_NOSIZE|SWP_NOZORDER|SWP_NOACTIVATE);
	}

	//ANDREAS: Added some functionality to the rename dialog
	LPALBUMINFO pAlbumInfo = winampAL.GetCurrentAlbum();
	if (pAlbumInfo)
	{
		//From CMP3Info...
		int s  = pAlbumInfo->nTotalTime;
		int ss = s%60;
		int m  = (s-ss)/60;
		int mm = m%60;
		int h = (m-mm)/60;

		char szLength[16]; // temporary string

		// make a "hh:mm:ss" if there is any hours, otherwise
		// make it   "mm:ss"
		if (h>0) {
			wsprintf(szLength,"%02d:%02d:%02d", h,mm,ss);
		}
		else {
			wsprintf(szLength,     "%02d:%02d",   mm,ss);
		}

		SetDlgItemText(hwndDlg, IDC_LENGTH, szLength); 
		
		SetDlgItemText(hwndDlg, IDC_PATH, pAlbumInfo->path);
		SetDlgItemText(hwndDlg, IDC_ARTIST, pAlbumInfo->artist);
		SetDlgItemText(hwndDlg, IDC_ALBUM, pAlbumInfo->album);
		SetDlgItemText(hwndDlg, IDC_LISTNAME, pAlbumInfo->name);

		SetDlgItemInt(hwndDlg, IDC_FILECOUNT, pAlbumInfo->nCount, TRUE);
		SetDlgItemInt(hwndDlg, IDC_YEAR, pAlbumInfo->nYear, TRUE);
	}
}

void OnAlbumInfo(HWND hwndDlg)
{
	LPALBUMINFO pAlbumInfo = winampAL.GetCurrentAlbum();
	if (pAlbumInfo)
	{
		GetDlgItemText(hwndDlg, IDC_ARTIST, pAlbumInfo->artist, sizeof(pAlbumInfo->artist));
		GetDlgItemText(hwndDlg, IDC_ALBUM, pAlbumInfo->album, sizeof(pAlbumInfo->album));
		GetDlgItemText(hwndDlg, IDC_LISTNAME, pAlbumInfo->name, sizeof(pAlbumInfo->name));

		pAlbumInfo->nYear = GetDlgItemInt(hwndDlg, IDC_YEAR, NULL, TRUE);
	}
}

BOOL CALLBACK AlbumInfoProc(HWND hwndDlg, UINT uMsg, WPARAM wParam, LPARAM lParam)
{
	switch (uMsg)
	{
	case WM_INITDIALOG:
		OnInitDialogAlbumInfo(hwndDlg);
		UpdateDialogStrings(hwndDlg);
		return TRUE;

	case WM_COMMAND:
		switch (LOWORD(wParam))
		{
		case IDOK:
			OnAlbumInfo(hwndDlg);
			EndDialog(hwndDlg, IDOK);
			return TRUE;

		case IDCANCEL:
			EndDialog(hwndDlg, IDCANCEL);
			return TRUE;
		}
		break;
	}

	return FALSE;
}

/////////////////////////////////////////////////////////////////////////
// CONFIG TABS
//

CSearchPathPage	g_SearchPathPage;

void OnInitDialogConfigTabs(HWND hwndDlg)
{
	HWND hTabs = GetDlgItem(hwndDlg, IDC_TABS);

	TCITEM item;
	item.mask = TCIF_TEXT;
	item.pszText = "test";

	TabCtrl_InsertItem(hTabs, 0, &item);

	g_SearchPathPage.Create(hTabs);

	// position the page in the right place
	HWND hHolder = GetDlgItem(hwndDlg, IDC_PPAGE_HOLDER);
	if (hHolder)
	{
		RECT rc;
		GetWindowRect(hHolder, &rc);
		POINT pt = { rc.left, rc.top };
		ScreenToClient(hwndDlg, &pt);
//		RECT rc;
//		GetClientRect(hTabs, &rc);
		SetWindowPos(g_SearchPathPage.m_hWnd, NULL, pt.x, pt.y, rc.right-rc.left, rc.bottom-rc.top, SWP_NOZORDER|SWP_NOACTIVATE);
	}
}

BOOL CALLBACK ConfigTabsProc(HWND hwndDlg, UINT uMsg, WPARAM wParam, LPARAM lParam)
{
	switch (uMsg)
	{
	case WM_INITDIALOG:
		OnInitDialogConfigTabs(hwndDlg);
		UpdateDialogStrings(hwndDlg);
		return TRUE;

	case WM_COMMAND:
		switch (LOWORD(wParam))
		{
		case IDOK:
			EndDialog(hwndDlg, IDOK);
			return TRUE;

		case IDCANCEL:
			EndDialog(hwndDlg, IDCANCEL);
			return TRUE;
		}
		break;
	}

	return FALSE;
}

/////////////////////////////////////////////////////////////////////////

LPCTSTR ALSTRING(LPCTSTR str1, LPCTSTR str2 /*=NULL*/)
{
	static char szResult[MAX_PATH*2] = "";

	// no language or english (default) is selected?
	if ((al_lang[0] == 0) || (stricmp(al_lang, "%default%") == 0))
	{
		if (str2 == NULL) return str1;
		
		lstrcpy(szResult, str1);
		if (str2) lstrcat(szResult, str2);
		return szResult;
	}

	// get the string from the language file (*.al)
	if (GetPrivateProfileString("Strings", str1, str1, szResult, MAX_PATH, szLangINI))
	{
		if (szResult[0] == 0)
		{
			if (str2 == NULL) return str1;
			lstrcpy(szResult, str1);
		}
		if (str2) lstrcat(szResult, str2);
		return szResult;
	}

	// *it shouldn't get here, but just in case*
	// string no present in language file?
	// just give back the english strings
	if (str2 == NULL) return str1;
	
	lstrcpy(szResult, str1);
	if (str2) lstrcat(szResult, str2);
	return szResult;
}

void UpdateDialogStrings(HWND hWnd)
{
	char str[MAX_PATH+1] = "";

	HFONT hFont = (HFONT)GetStockObject(DEFAULT_GUI_FONT);

	PostMessage(hWnd, WM_SETFONT, (WPARAM)hFont, MAKELPARAM(TRUE, 0));
	GetWindowText(hWnd, str, MAX_PATH);
	SetWindowText(hWnd, ALSTRING(str));

	HWND hChild = NULL;
	while (hChild = FindWindowEx(hWnd, hChild, NULL, NULL))
	{
		int nID = GetDlgCtrlID(hChild);
		if ((nID != IDC_VERSION_STATIC) &&
			(nID != IDC_VERSION2_STATIC) &&
			(nID != IDC_ADDITIONAL_STATIC) &&
			(nID != IDC_README_TEXT))
		{
			UpdateDialogStrings(hChild);
		}
		else
		{
			PostMessage(hChild, WM_SETFONT, (WPARAM)hFont, MAKELPARAM(TRUE, 0));
		}
	}
}

BOOL WriteString(HANDLE hFile, LPCTSTR lpszBuffer)
{
	DWORD nBytesWritten;
	return WriteFile(hFile, lpszBuffer, lstrlen(lpszBuffer), &nBytesWritten, NULL);
}

void AutoLanguageDetection()
{
	if (lstrlen(al_lang) == 0)
	{
		char szLangID[4] = "";
		LCID lcid = GetUserDefaultLCID();
		GetLocaleInfo (lcid, LOCALE_SABBREVLANGNAME, szLangID, 4);
		_strlwr(szLangID);

		if ((szLangID[0] == 'e') && (szLangID[1] == 'n'))
		{
			lstrcpy(al_lang, "%default%");
		}
		else if (lstrcmpi(szLangID, "cat") == 0)
		{
			lstrcpy(al_lang, "catalan.al");
		}
		else if (lstrcmpi(szLangID, "csy") == 0)
		{
			lstrcpy(al_lang, "czech.al");
		}
		else if ((szLangID[0] == 'n') && (szLangID[1] == 'l'))
		{
			lstrcpy(al_lang, "dutch.al");
		}
		else if (lstrcmpi(szLangID, "fin") == 0)
		{
			lstrcpy(al_lang, "finnish.al");
		}
		else if ((szLangID[0] == 'f') && (szLangID[1] == 'r'))
		{
			lstrcpy(al_lang, "french.al");
		}
		else if ((szLangID[0] == 'd') && (szLangID[1] == 'e'))
		{
			lstrcpy(al_lang, "german.al");
		}
		else if (lstrcmpi(szLangID, "hun") == 0)
		{
			lstrcpy(al_lang, "hungarian.al");
		}
		else if ((szLangID[0] == 'i') && (szLangID[1] == 't'))
		{
			lstrcpy(al_lang, "italian.al");
		}
		else if (lstrcmpi(szLangID, "jpn") == 0)
		{
			lstrcpy(al_lang, "japanese.al");
		}
		else if (lstrcmpi(szLangID, "plk") == 0)
		{
			lstrcpy(al_lang, "polish.al");
		}
		else if ((szLangID[0] == 'p') && (szLangID[1] == 't'))
		{
			lstrcpy(al_lang, "portuguese.al");
		}
		else if (lstrcmpi(szLangID, "rom") == 0)
		{
			lstrcpy(al_lang, "romanian.al");
		}
		else if (lstrcmpi(szLangID, "rus") == 0)
		{
			lstrcpy(al_lang, "russian.al");
		}
		else if ((szLangID[0] == 'e') && (szLangID[1] == 's'))
		{
			lstrcpy(al_lang, "spanish.al");
		}
		else if (lstrcmpi(szLangID, "sve") == 0)
		{
			lstrcpy(al_lang, "swedish.al");
		}
	}
}

BOOL ResolveIt(HWND hwnd, LPCSTR lpszLinkFile, LPSTR lpszPath) 
{ 
    HRESULT hres = E_FAIL;
 
	CoInitialize(NULL);
	
	// Get a pointer to the IShellLink interface. 
    IShellLink* psl = NULL;
	hres = CoCreateInstance(CLSID_ShellLink, NULL, CLSCTX_INPROC_SERVER, IID_IShellLink, (LPVOID*)&psl);
	if (SUCCEEDED(hres))
	{ 
		IPersistFile* ppf; 

		// Get a pointer to the IPersistFile interface. 
		hres = psl->QueryInterface(IID_IPersistFile, (LPVOID *)&ppf); 
		if (SUCCEEDED(hres))
		{ 
			WORD wsz[MAX_PATH]; 

			// Ensure that the string is Unicode. 
			MultiByteToWideChar(CP_ACP, 0, lpszLinkFile, -1, wsz, MAX_PATH); 

			// Load the shortcut. 
			hres = ppf->Load(wsz, STGM_READ); 
			if (SUCCEEDED(hres))
			{ 
				// Resolve the link. 
				hres = psl->Resolve(hwnd, SLR_ANY_MATCH | SLR_NO_UI); 
				if (SUCCEEDED(hres))
				{ 
					// Get the path to the link target. 
				    WIN32_FIND_DATA wfd; 
				    char szGotPath[MAX_PATH] = "";
					hres = psl->GetPath(szGotPath, MAX_PATH, (WIN32_FIND_DATA *)&wfd, SLGP_SHORTPATH);
					if (SUCCEEDED(hres))
					{
						lstrcpy(lpszPath, szGotPath); 
					}
				} 
			} 
			// Release the pointer to the IPersistFile interface. 
			ppf->Release(); 
		}
		// Release the pointer to the IShellLink interface. 
		psl->Release();
	}

	CoUninitialize();

    return SUCCEEDED(hres); 
}
