//this file is part of eMule
//Copyright (C)2002 Merkur ( merkur-@users.sourceforge.net / http://www.emule-project.net )
//
//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 "preferences.h"
#include <time.h>
#include "opcodes.h"
#include "otherfunctions.h"
#include "ini2.h"
#include "stdlib.h"
#include "stdio.h"
#include <locale.h>
#include "resource.h"

#define ELEMENT_COUNT(X) (sizeof(X) / sizeof(X[0]))

CPreferences::CPreferences(){
	srand((uint32)time(0)); // we need random numbers sometimes

	prefs = new Preferences_Struct;
	memset(prefs,0,sizeof(Preferences_Struct));
	prefsExt=new Preferences_Ext_Struct;
	memset(prefsExt,0,sizeof(Preferences_Ext_Struct));

	//get application start directory
	char buffer[490];
	::GetModuleFileName(0, buffer, 490);
	LPTSTR pszFileName = _tcsrchr(buffer, '\\') + 1;
	*pszFileName = '\0';
	appdir = nstrdup(buffer);
	CreateUserHash();
	memcpy(&prefs->userhash,&userhash,16);

	// load preferences.dat or set standart values
	char* fullpath = new char[strlen(appdir)+16];
	sprintf(fullpath,"%spreferences.dat",appdir);
	FILE* preffile = fopen(fullpath,"rb");
	delete[] fullpath;

	LoadPreferences();
	
	if (!preffile){
		SetStandartValues();
		//if (Ask4RegFix(true)) Ask4RegFix(false);
	}
	else{
		fread(prefsExt,sizeof(Preferences_Ext_Struct),1,preffile);
		if (ferror(preffile))
			SetStandartValues();

		// import old pref-files
		if (prefsExt->version<20) {


			if (prefsExt->version>17) {// v0.20b+
				prefsImport20b=new Preferences_Import20b_Struct;
				memset(prefsImport20b,0,sizeof(Preferences_Import20b_Struct));
				fseek(preffile,0,0);
				fread(prefsImport20b,sizeof(Preferences_Import20b_Struct),1,preffile);

				memcpy(&prefs->userhash,&prefsImport20b->userhash,16);
				memcpy(&prefs->incomingdir,&prefsImport20b->incomingdir,510);
				memcpy(&prefs->tempdir,&prefsImport20b->tempdir,510);
				sprintf(prefs->nick,prefsImport20b->nick);

				prefs->totalDownloadedBytes=prefsImport20b->totalDownloadedBytes;
				prefs->totalUploadedBytes=prefsImport20b->totalUploadedBytes;

			} else if (prefsExt->version>7) { // v0.20a
				prefsImport20a=new Preferences_Import20a_Struct;
				memset(prefsImport20a,0,sizeof(Preferences_Import20a_Struct));
				fseek(preffile,0,0);
				fread(prefsImport20a,sizeof(Preferences_Import20a_Struct),1,preffile);

				memcpy(&prefs->userhash,&prefsImport20a->userhash,16);
				memcpy(&prefs->incomingdir,&prefsImport20a->incomingdir,510);
				memcpy(&prefs->tempdir,&prefsImport20a->tempdir,510);
				sprintf(prefs->nick,prefsImport20a->nick);

				prefs->totalDownloadedBytes=prefsImport20a->totalDownloaded;
				prefs->totalUploadedBytes=prefsImport20a->totalUploaded;

			} else {	//v0.19c-
				prefsImport19c=new Preferences_Import19c_Struct;
				memset(prefsImport19c,0,sizeof(Preferences_Import19c_Struct));

				fseek(preffile,0,0);
				fread(prefsImport19c,sizeof(Preferences_Import19c_Struct),1,preffile);

				if (prefsExt->version<3) {
					CreateUserHash();
					memcpy(&prefs->userhash,&userhash,16);
				} else {memcpy(&prefs->userhash,&prefsImport19c->userhash,16);}
				memcpy(&prefs->incomingdir,&prefsImport19c->incomingdir,510);memcpy(&prefs->tempdir,&prefsImport19c->tempdir,510);
				sprintf(prefs->nick,prefsImport19c->nick);
			}
 		} else {
			memcpy(&prefs->userhash,&prefsExt->userhash,16);
			prefs->EmuleWindowPlacement=prefsExt->EmuleWindowPlacement;
		}
		fclose(preffile);
	memcpy(&userhash,&prefs->userhash,16);
	prefs->smartidstate=0;
	}

	// shared directories
	fullpath = new char[strlen(appdir)+MAX_PATH]; // i_a
	sprintf(fullpath,"%sshareddir.dat",appdir);
	CStdioFile* sdirfile = new CStdioFile();
	if (sdirfile->Open(fullpath,CFile::modeRead)){
		CString toadd;
		while (sdirfile->ReadString(toadd))
			shareddir_list.AddHead(toadd);
		sdirfile->Close();
	}
	delete sdirfile;
	delete[] fullpath;
	//serverlist adresses
	fullpath = new char[strlen(appdir)+20];
	sprintf(fullpath,"%sadresses.dat",appdir);
	sdirfile = new CStdioFile();
	if (sdirfile->Open(fullpath,CFile::modeRead)){
		CString toadd;
		while (sdirfile->ReadString(toadd))
			adresses_list.AddHead(toadd);
		sdirfile->Close();
	}
	delete sdirfile;
	delete[] fullpath;	

	userhash[5] = 14;
	userhash[14] = 111;

	::CreateDirectory(GetIncomingDir(),0);
	::CreateDirectory(GetTempDir(),0);
}

void CPreferences::SetStandartValues(){
	CreateUserHash();
	memcpy(&prefs->userhash,&userhash,16);

	WINDOWPLACEMENT defaultWPM;
	defaultWPM.length = sizeof(WINDOWPLACEMENT);
	defaultWPM.rcNormalPosition.left=10;defaultWPM.rcNormalPosition.top=10;
	defaultWPM.rcNormalPosition.right=700;defaultWPM.rcNormalPosition.bottom=500;
	defaultWPM.showCmd=0;
	prefs->EmuleWindowPlacement=defaultWPM;

	Save();
}

uint16 CPreferences::GetMaxDownload(){
	//return prefs->maxdownload; // I am a Lam3r ;)
	
	//dont be a Lam3r :)
	if( GetMaxUpload() < 4 )
		return (( (GetMaxUpload() < 10) && (GetMaxUpload()*3 < prefs->maxdownload) )? GetMaxUpload()*3 : prefs->maxdownload);
	return (( (GetMaxUpload() < 10) && (GetMaxUpload()*4 < prefs->maxdownload) )? GetMaxUpload()*4 : prefs->maxdownload);
}

bool CPreferences::Save(){

	bool error = false;
	char* fullpath = new char[strlen(appdir)+MAX_PATH]; // i_a
	sprintf(fullpath,"%spreferences.dat",appdir);

	FILE* preffile = fopen(fullpath,"wb");
	prefsExt->version = PREFFILE_VERSION;

	delete[] fullpath;
	if (preffile){
		prefsExt->version=PREFFILE_VERSION;
		prefsExt->EmuleWindowPlacement=prefs->EmuleWindowPlacement;
		memcpy(&prefsExt->userhash,&prefs->userhash,16);

		error = fwrite(prefsExt,sizeof(Preferences_Ext_Struct),1,preffile);
		fclose(preffile);
	}
	else
		error = true;

	SavePreferences();

	fullpath = new char[strlen(appdir)+14];
	sprintf(fullpath,"%sshareddir.dat",appdir);
	CStdioFile sdirfile;
	if (sdirfile.Open(fullpath,CFile::modeCreate|CFile::modeWrite)){

		for (POSITION pos = shareddir_list.GetHeadPosition();pos != 0;shareddir_list.GetNext(pos)){
			sdirfile.WriteString(shareddir_list.GetAt(pos).GetBuffer());
			sdirfile.Write("\n",1);
		}
		sdirfile.Close();
	}
	else
		error = true;
	delete[] fullpath;
	::CreateDirectory(GetIncomingDir(),0);
	::CreateDirectory(GetTempDir(),0);
	return error;
}

void CPreferences::CreateUserHash(){
	for (int i = 0;i != 8; i++){ 
		uint16	random = rand();
		memcpy(&userhash[i*2],&random,2);
	}
	// mark as emule client. that will be need in later version
	userhash[5] = 14;
	userhash[14] = 111;
}

int CPreferences::GetColumnWidth(Table t, int index) const {
	switch(t) {
	case tableDownload:
		return prefs->downloadColumnWidths[index];
	case tableUpload:
		return prefs->uploadColumnWidths[index];
	case tableQueue:
		return prefs->queueColumnWidths[index];
	case tableSearch:
		return prefs->searchColumnWidths[index];
	case tableShared:
		return prefs->sharedColumnWidths[index];
	case tableServer:
		return prefs->serverColumnWidths[index];
	}
	return 0;
}

void CPreferences::SetColumnWidth(Table t, int index, int width) {
	switch(t) {
	case tableDownload:
		prefs->downloadColumnWidths[index] = width;
		break;
	case tableUpload:
		prefs->uploadColumnWidths[index] = width;
		break;
	case tableQueue:
		prefs->queueColumnWidths[index] = width;
		break;
	case tableSearch:
		prefs->searchColumnWidths[index] = width;
		break;
	case tableShared:
		prefs->sharedColumnWidths[index] = width;
		break;
	case tableServer:
		prefs->serverColumnWidths[index] = width;
		break;
	}
}

BOOL CPreferences::GetColumnHidden(Table t, int index) const {
	switch(t) {
	case tableDownload:
		return prefs->downloadColumnHidden[index];
	case tableUpload:
		return prefs->uploadColumnHidden[index];
	case tableQueue:
		return prefs->queueColumnHidden[index];
	case tableSearch:
		return prefs->searchColumnHidden[index];
	case tableShared:
		return prefs->sharedColumnHidden[index];
	case tableServer:
		return prefs->serverColumnHidden[index];
	}
	return FALSE;
}

void CPreferences::SetColumnHidden(Table t, int index, BOOL bHidden) {
	switch(t) {
	case tableDownload:
		prefs->downloadColumnHidden[index] = bHidden;
		break;
	case tableUpload:
		prefs->uploadColumnHidden[index] = bHidden;
		break;
	case tableQueue:
		prefs->queueColumnHidden[index] = bHidden;
		break;
	case tableSearch:
		prefs->searchColumnHidden[index] = bHidden;
		break;
	case tableShared:
		prefs->sharedColumnHidden[index] = bHidden;
		break;
	case tableServer:
		prefs->serverColumnHidden[index] = bHidden;
		break;
	}
}

int CPreferences::GetColumnOrder(Table t, int index) const {
	switch(t) {
	case tableDownload:
		return prefs->downloadColumnOrder[index];
	case tableUpload:
		return prefs->uploadColumnOrder[index];
	case tableQueue:
		return prefs->queueColumnOrder[index];
	case tableSearch:
		return prefs->searchColumnOrder[index];
	case tableShared:
		return prefs->sharedColumnOrder[index];
	case tableServer:
		return prefs->serverColumnOrder[index];
	}
	return 0;
}

void CPreferences::SetColumnOrder(Table t, INT *piOrder) {
	switch(t) {
	case tableDownload:
		memcpy(prefs->downloadColumnOrder, piOrder, sizeof(prefs->downloadColumnOrder));
		break;
	case tableUpload:
		memcpy(prefs->uploadColumnOrder, piOrder, sizeof(prefs->uploadColumnOrder));
		break;
	case tableQueue:
		memcpy(prefs->queueColumnOrder, piOrder, sizeof(prefs->queueColumnOrder));
		break;
	case tableSearch:
		memcpy(prefs->searchColumnOrder, piOrder, sizeof(prefs->searchColumnOrder));
		break;
	case tableShared:
		memcpy(prefs->sharedColumnOrder, piOrder, sizeof(prefs->sharedColumnOrder));
		break;
	case tableServer:
		memcpy(prefs->serverColumnOrder, piOrder, sizeof(prefs->serverColumnOrder));
		break;
	}
}

CPreferences::~CPreferences(){
	delete[] appdir;
	delete prefs;
	delete prefsExt;
}

int CPreferences::GetRecommendedMaxConnections() {
	int iRealMax = ::GetMaxConnections();
	if(iRealMax == -1 || iRealMax > 520)
		return 500;

	if(iRealMax < 20)
		return iRealMax;

	if(iRealMax <= 256)
		return iRealMax - 10;

	return iRealMax - 20;
}

void CPreferences::SavePreferences(){
	CString buffer;
	char* fullpath = new char[strlen(appdir)+MAX_PATH]; // i_a
	sprintf(fullpath,"%spreferences.ini",appdir);
	
	CIni ini( fullpath, "eMule" );

	delete[] fullpath;

	//---
	ini.WriteString("AppVersion", CURRENT_VERSION_LONG);
	//---

	buffer.Format("%s",prefs->nick);
	ini.WriteString("Nick",buffer);

	buffer.Format("%s",prefs->incomingdir);
	ini.WriteString("IncomingDir",buffer );

	buffer.Format("%s",prefs->tempdir);
	ini.WriteString("TempDir",buffer );

	ini.WriteInt("MaxUpload",prefs->maxupload);
	ini.WriteInt("MaxDownload",prefs->maxdownload);
	ini.WriteInt("MaxConnections",prefs->maxconnections);
	ini.WriteInt("DeadServerAction",prefs->deadserver);
	ini.WriteInt("Port",prefs->port);
	ini.WriteInt("UDPPort",prefs->udpport);
	ini.WriteInt("MaxSourcesPerFile",prefs->maxsourceperfile );
	ini.WriteWORD("Language",prefs->languageID);
	ini.WriteInt("SeeShare",prefs->m_iSeeShares);
	ini.WriteInt("ToolTipDelay",prefs->m_iToolDelayTime);
	ini.WriteInt("StatGraphsInterval",prefs->trafficOMeterInterval);
	ini.WriteInt("StatsInterval",prefs->statsInterval);
	ini.WriteInt("DownloadCapacity",prefs->maxGraphDownloadRate);
	ini.WriteInt("UploadCapacity",prefs->maxGraphUploadRate);
	ini.WriteInt("DeadServerRetries",prefs->deadserverretries);
	ini.WriteInt("SplitterbarPosition",prefs->splitterbarPosition);
	ini.WriteInt("VariousStatisticsMaxValue",prefs->statsMax);
	ini.WriteInt("StatsAverageMinutes",prefs->statsAverageMinutes);
	ini.WriteInt("MaxConnectionsPerFiveSeconds",prefs->MaxConperFive);

	ini.WriteBool("Reconnect",prefs->reconnect);
	ini.WriteBool("Scoresystem",prefs->scorsystem);
	ini.WriteBool("ICH",prefs->ICH);
	ini.WriteBool("Serverlist",prefs->autoserverlist);
	ini.WriteBool("UpdateNotify",prefs->updatenotify);
	ini.WriteBool("MinToTray",prefs->mintotray);
	ini.WriteBool("AddServersFromServer",prefs->addserversfromserver);
	ini.WriteBool("AddServersFromClient",prefs->addserversfromclient);
	ini.WriteBool("Splashscreen",prefs->splashscreen);
	ini.WriteBool("BringToFront",prefs->bringtoforeground);
	ini.WriteBool("TransferDoubleClick",prefs->transferDoubleclick);
	ini.WriteBool("BeepOnError",prefs->beepOnError);
	ini.WriteBool("ConfirmExit",prefs->confirmExit);
	ini.WriteBool("FilterBadIPs",prefs->filerBadIP);
    ini.WriteBool("Autoconnect",prefs->autoconnect);
	ini.WriteBool("OnlineSignature",prefs->onlineSig);
	ini.WriteBool("StartupMinimized",prefs->startMinimized);
	ini.WriteBool("SafeServerConnect",prefs->safeServerConnect);

	// Barry - New properties...
    ini.WriteBool("AutoConnectStaticOnly", prefs->autoconnectstaticonly);  
	ini.WriteBool("AutoTakeED2KLinks", prefs->autotakeed2klinks);  
    ini.WriteBool("AddNewFilesPaused", prefs->addnewfilespaused);  
    ini.WriteBool("GlobalSearch", prefs->globalsearch);  
    ini.WriteInt ("3DDepth", prefs->depth3D);  

	ini.WriteBool("UAP", prefs->UAP) ;
	ini.WriteBool("NotifyOnDownload",prefs->useDownloadNotifier); // Added by enkeyDEV
	ini.WriteBool("NotifyOnChat",prefs->useChatNotifier);		  
	ini.WriteBool("NotifyOnLog",prefs->useLogNotifier);
	ini.WriteBool("NotifierUseSound",prefs->useSoundInNotifier);
	ini.WriteBool("NotifierPopEveryChatMessage",prefs->notifierPopsEveryChatMsg);


	buffer.Format("%s",prefs->notifierSoundFilePath);
	ini.WriteString("NotifierSoundPath",buffer);

	ini.WriteString("TxtEditor",prefs->TxtEditor);
	ini.WriteString("IRCServer",prefs->m_sircserver);
	ini.WriteString("IRCNick",prefs->m_sircnick);
	ini.WriteBool("IRCAddTimestamp", prefs->m_bircaddtimestamp);
	ini.WriteString("IRCFilterName", prefs->m_sircchannamefilter);
	ini.WriteInt("IRCFilterUser", prefs->m_iircchanneluserfilter);
	ini.WriteBool("IRCUseFilter", prefs->m_bircusechanfilter);
	ini.WriteString("IRCPerformString", prefs->m_sircperformstring);
	ini.WriteBool("IRCUsePerform", prefs->m_bircuseperform);
	ini.WriteBool("IRCListOnConnect", prefs->m_birclistonconnect);
	ini.WriteBool("IRCAcceptLinks", prefs->m_bircacceptlinks);
	ini.WriteBool("IRCIgnoreInfoMessage", prefs->m_bircignoreinfomessage);
	ini.WriteBool("IRCIgnoreEmuleProtoInfoMessage", prefs->m_bircignoreemuleprotoinfomessage);
	ini.WriteBool("NotifyOnImportantError", prefs->notifierImportantError);
	ini.WriteBool("SmartIdCheck", prefs->smartidcheck);
	ini.WriteBool("Verbose", prefs->m_bVerbose);
	ini.WriteBool("PreviewPrio", prefs->m_bpreviewprio);
	ini.WriteBool("UpdateQueueList", prefs->m_bupdatequeuelist);
	ini.WriteBool("ManualHighPrio", prefs->m_bmanualhighprio);
	ini.WriteBool("FullChunkTransfers", prefs->m_btransferfullchunks);
	ini.WriteBool("StartNextFile", prefs->m_bstartnextfile);
	ini.WriteBool("ShowOverhead", prefs->m_bshowoverhead);

	// Added by Tarod -new properties
	ini.WriteInt("QueueSize", prefs->queuesize);
	ini.WriteInt("RemoteQueueLimit", prefs->remotequeuelimit);
	ini.WriteBool("DisableXS", prefs->disablexs);
	ini.WriteBool("ThrottleUpload", prefs->throttleupload);
	ini.WriteBool("DynamicUpload", prefs->dynamicupload);
	ini.WriteString("URLToPing", CString(prefs->url_ping));
	ini.WriteInt("BasePing", prefs->base_ping);
	ini.WriteInt("MaxXSAtOnce", prefs->max_xs_at_once);
	ini.WriteString("A4AFAutoFileHash", EncodeBase16(prefs->A4AF_file_hash, sizeof(prefs->A4AF_file_hash)));
	// End by Tarod

	ini.SerGet(false, prefs->downloadColumnWidths,
		ELEMENT_COUNT(prefs->downloadColumnWidths), "DownloadColumnWidths");
	ini.SerGet(false, prefs->downloadColumnHidden,
		ELEMENT_COUNT(prefs->downloadColumnHidden), "DownloadColumnHidden");
	ini.SerGet(false, prefs->downloadColumnOrder,
		ELEMENT_COUNT(prefs->downloadColumnOrder), "DownloadColumnOrder");
	ini.SerGet(false, prefs->uploadColumnWidths,
		ELEMENT_COUNT(prefs->uploadColumnWidths), "UploadColumnWidths");
	ini.SerGet(false, prefs->uploadColumnHidden,
		ELEMENT_COUNT(prefs->uploadColumnHidden), "UploadColumnHidden");
	ini.SerGet(false, prefs->uploadColumnOrder,
		ELEMENT_COUNT(prefs->uploadColumnOrder), "UploadColumnOrder");
	ini.SerGet(false, prefs->queueColumnWidths,
		ELEMENT_COUNT(prefs->queueColumnWidths), "QueueColumnWidths");
	ini.SerGet(false, prefs->queueColumnHidden,
		ELEMENT_COUNT(prefs->queueColumnHidden), "QueueColumnHidden");
	ini.SerGet(false, prefs->queueColumnOrder,
		ELEMENT_COUNT(prefs->queueColumnOrder), "QueueColumnOrder");
	ini.SerGet(false, prefs->searchColumnWidths,
		ELEMENT_COUNT(prefs->searchColumnWidths), "SearchColumnWidths");
	ini.SerGet(false, prefs->searchColumnHidden,
		ELEMENT_COUNT(prefs->searchColumnHidden), "SearchColumnHidden");
	ini.SerGet(false, prefs->searchColumnOrder,
		ELEMENT_COUNT(prefs->searchColumnOrder), "SearchColumnOrder");
	ini.SerGet(false, prefs->sharedColumnWidths,
		ELEMENT_COUNT(prefs->sharedColumnWidths), "SharedColumnWidths");
	ini.SerGet(false, prefs->sharedColumnHidden,
		ELEMENT_COUNT(prefs->sharedColumnHidden), "SharedColumnHidden");
	ini.SerGet(false, prefs->sharedColumnOrder,
		ELEMENT_COUNT(prefs->sharedColumnOrder), "SharedColumnOrder");
	ini.SerGet(false, prefs->serverColumnWidths,
		ELEMENT_COUNT(prefs->serverColumnWidths), "ServerColumnWidths");
	ini.SerGet(false, prefs->serverColumnHidden,
		ELEMENT_COUNT(prefs->serverColumnHidden), "ServerColumnHidden");
	ini.SerGet(false, prefs->serverColumnOrder,
		ELEMENT_COUNT(prefs->serverColumnOrder), "ServerColumnOrder");

	// Barry - Provide a mechanism for all tables to store/retrieve sort order
	ini.WriteInt("TableSortItemDownload", prefs->tableSortItemDownload);
	ini.WriteInt("TableSortItemUpload", prefs->tableSortItemUpload);
	ini.WriteInt("TableSortItemQueue", prefs->tableSortItemQueue);
	ini.WriteInt("TableSortItemSearch", prefs->tableSortItemSearch);
	ini.WriteInt("TableSortItemShared", prefs->tableSortItemShared);
	ini.WriteInt("TableSortItemServer", prefs->tableSortItemServer);
	ini.WriteBool("TableSortAscendingDownload", prefs->tableSortAscendingDownload);
	ini.WriteBool("TableSortAscendingUpload", prefs->tableSortAscendingUpload);
	ini.WriteBool("TableSortAscendingQueue", prefs->tableSortAscendingQueue);
	ini.WriteBool("TableSortAscendingSearch", prefs->tableSortAscendingSearch);
	ini.WriteBool("TableSortAscendingShared", prefs->tableSortAscendingShared);
	ini.WriteBool("TableSortAscendingServer", prefs->tableSortAscendingServer);

	CString buffer2;
	for (int i=0;i<15;i++) {
		buffer.Format("%I64Lu",GetStatsColor(i));
		buffer2.Format("StatColor%i",i);
		ini.WriteString(buffer2,buffer);
	}

	buffer.Format("%I64Lu",prefs->totalDownloadedBytes);
	ini.WriteString("TotalDownloadedBytes",buffer ,"Statistics");

	buffer.Format("%I64Lu",prefs->totalUploadedBytes);
	ini.WriteString("TotalUploadedBytes",buffer ,"Statistics");

}

void CPreferences::ResetStatsColor(int index){
	switch(index) {
		case 0 : prefs->statcolors[0]=RGB(0,0,64);break;
		case 1 : prefs->statcolors[1]=RGB(192,192,255);break;
		case 2 : prefs->statcolors[2]=RGB(128, 255, 128);break;
		case 3 : prefs->statcolors[3]=RGB(0, 210, 0);break;
		case 4 : prefs->statcolors[4]=RGB(0, 128, 0);break;
		case 5 : prefs->statcolors[5]=RGB(255, 128, 128);break;
		case 6 : prefs->statcolors[6]=RGB(200, 0, 0);break;
		case 7 : prefs->statcolors[7]=RGB(140, 0, 0);break;
		case 8 : prefs->statcolors[8]=RGB(150, 150, 255);break;
		case 9 : prefs->statcolors[9]=RGB(192,   0, 192);break;
		case 10 : prefs->statcolors[10]=RGB(255, 192, 255);break;
		case 11 : prefs->statcolors[11]=RGB(255, 255, 128);break;
		case 12 : prefs->statcolors[12]=RGB(255, 255, 255);break;


		default:break;
	}
}

void CPreferences::LoadPreferences(){
	char buffer[200];
	//char* fullpath = new char[strlen(appdir)+MAX_PATH]; // i_a
	//sprintf(fullpath,"%spreferences.ini",appdir);

	//--- Quick hack to add version tag to preferences.ini-file and solve the issue with the FlatStatusBar tag...
	CString strFileName;
	strFileName.Format("%spreferences.ini", appdir);
	CIni* pIni = new CIni(strFileName, "eMule");

	CString strCurrVersion, strPrefsVersion;

	strCurrVersion = CURRENT_VERSION_LONG;
	strPrefsVersion = pIni->GetString("AppVersion");
	delete pIni;

	CFileFind findFileName;

	if ((strCurrVersion != strPrefsVersion) && findFileName.FindFile(strFileName)){
		CFile file;
		CFileFind findNewName;
		CString strNewName;
		strNewName.Format("%spreferences.ini.old", appdir);

		if (findNewName.FindFile(strNewName))
			file.Remove(strNewName);

		file.Rename(strFileName, strNewName);
		strFileName = strNewName;
	}

	CIni ini(strFileName, "eMule");
	//--- end Ozon :)


	//CIni ini( fullpath, "eMule" );

	//delete[] fullpath;

	sprintf(prefs->nick,"%s",ini.GetString("Nick","http://emule-project.net"));
	
	sprintf(buffer,"%sIncoming",appdir);
	sprintf(prefs->incomingdir,"%s",ini.GetString("IncomingDir",buffer ));

	sprintf(buffer,"%sTemp",appdir);
	sprintf(prefs->tempdir,"%s",ini.GetString("TempDir",buffer));

	prefs->maxupload=ini.GetInt("MaxUpload",UNLIMITED);
	prefs->maxdownload=ini.GetInt("MaxDownload",UNLIMITED);
	prefs->maxconnections=ini.GetInt("MaxConnections",GetRecommendedMaxConnections());
	prefs->deadserver=ini.GetInt("DeadServerAction",2);
	prefs->port=ini.GetInt("Port",4662);
	prefs->udpport=ini.GetInt("UDPPort",prefs->port+10);
	prefs->maxsourceperfile=ini.GetInt("MaxSourcesPerFile",400 );
	prefs->languageID=ini.GetWORD("Language",0);
	prefs->m_iSeeShares=ini.GetInt("SeeShare",2);
	prefs->m_iToolDelayTime=ini.GetInt("ToolTipDelay",1);
	prefs->trafficOMeterInterval=ini.GetInt("StatGraphsInterval",3);
	prefs->statsInterval=ini.GetInt("statsInterval",5);
	prefs->maxGraphDownloadRate=ini.GetInt("DownloadCapacity",96);
	prefs->maxGraphUploadRate=ini.GetInt("UploadCapacity",16);
	prefs->deadserverretries=ini.GetInt("DeadServerRetries",1);
	prefs->splitterbarPosition=ini.GetInt("SplitterbarPosition",75);
	prefs->statsMax=ini.GetInt("VariousStatisticsMaxValue",100);
	prefs->statsAverageMinutes=ini.GetInt("StatsAverageMinutes",5);
	prefs->MaxConperFive=ini.GetInt("MaxConnectionsPerFiveSeconds",GetDefaultMaxConperFive());

	prefs->reconnect=ini.GetBool("Reconnect",true);
	prefs->scorsystem=ini.GetBool("Scoresystem",true);
	prefs->ICH=ini.GetBool("ICH",true);
	prefs->autoserverlist=ini.GetBool("Serverlist",false);
	prefs->updatenotify=ini.GetBool("UpdateNotify",true);
	prefs->mintotray=ini.GetBool("MinToTray",false);
	prefs->addserversfromserver=ini.GetBool("AddServersFromServer",true);
	prefs->addserversfromclient=ini.GetBool("AddServersFromClient",true);
	prefs->splashscreen=ini.GetBool("Splashscreen",true);
	prefs->bringtoforeground=ini.GetBool("BringToFront",true);
	prefs->transferDoubleclick=ini.GetBool("TransferDoubleClick",true);
	prefs->beepOnError=ini.GetBool("BeepOnError",true);
	prefs->confirmExit=ini.GetBool("ConfirmExit",false);
	prefs->filerBadIP=ini.GetBool("FilterBadIPs",true);
	prefs->autoconnect=ini.GetBool("Autoconnect",false);

	prefs->onlineSig=ini.GetBool("OnlineSignature",false);
	prefs->startMinimized=ini.GetBool("StartupMinimized",false);
	prefs->safeServerConnect =ini.GetBool("SafeServerConnect",false);

	// Barry - New properties...
	prefs->autoconnectstaticonly = ini.GetBool("AutoConnectStaticOnly",false); 
	prefs->autotakeed2klinks = ini.GetBool("AutoTakeED2KLinks",true); 
	prefs->addnewfilespaused = ini.GetBool("AddNewFilesPaused",false); 
	prefs->globalsearch = ini.GetBool("GlobalSearch",true); 
	prefs->depth3D = ini.GetInt("3DDepth", 0);

	// Added by Tarod -new properties
	prefs->queuesize = ini.GetInt("QueueSize", 1000);
	prefs->remotequeuelimit = ini.GetInt("RemoteQueueLimit", 5000);
	prefs->disablexs = ini.GetBool("DisableXS", false);
	prefs->throttleupload = ini.GetBool("ThrottleUpload", false);
	prefs->dynamicupload = ini.GetBool("DynamicUpload", false);
	sprintf(prefs->url_ping, "%s", ini.GetString("URLToPing", "t-online.de"));
	prefs->base_ping = ini.GetInt("BasePing", 300);
	prefs->max_xs_at_once = ini.GetInt("MaxXSAtOnce", MAX_SOURCES_AT_ONCE);

	CString A4AF_hash = ini.GetString("A4AFAutoFileHash", "");
	if (A4AF_hash == "" || A4AF_hash.Trim().GetLength() != 32) {
		memset(prefs->A4AF_file_hash, '\0', sizeof(prefs->A4AF_file_hash));
	} else {
		A4AF_hash.Trim();
		DecodeBase16(A4AF_hash, A4AF_hash.GetLength(), prefs->A4AF_file_hash);
	}
	// End by Tarod

	// as temporarial converter for previous versions
	if (strPrefsVersion < "0.25a") // before 0.25a
		if (ini.GetBool("FlatStatusBar",false))
			prefs->depth3D = 0;
		else 
			prefs->depth3D = 5;

	prefs->UAP = ini.GetBool("UAP", true) ;
    prefs->useDownloadNotifier=ini.GetBool("NotifyOnDownload",false);	// Added by enkeyDEV
    prefs->useChatNotifier=ini.GetBool("NotifyOnChat",false);
    prefs->useLogNotifier=ini.GetBool("NotifyOnLog",false);
    prefs->useSoundInNotifier=ini.GetBool("NotifierUseSound",false);
	prefs->notifierPopsEveryChatMsg=ini.GetBool("NotifierPopEveryChatMessage",false);
	prefs->notifierImportantError=ini.GetBool("NotifyOnImportantError",false);
	sprintf(prefs->notifierSoundFilePath,"%s",ini.GetString("NotifierSoundPath",""));

	sprintf(prefs->m_sircserver,"%s",ini.GetString("IRCServer","irc.liquidirc.com"));
	sprintf(prefs->m_sircnick,"%s",ini.GetString("IRCNick","eMule"));
	prefs->m_bircaddtimestamp=ini.GetBool("IRCAddTimestamp",true);
	sprintf(prefs->m_sircchannamefilter,"%s",ini.GetString("IRCFilterName", "" ));
	prefs->m_bircusechanfilter=ini.GetBool("IRCUseFilter", false);
	prefs->m_iircchanneluserfilter=ini.GetInt("IRCFilterUser", 0);
	sprintf(prefs->m_sircperformstring,"%s",ini.GetString("IRCPerformString", "/join #emule" ));
	prefs->m_bircuseperform=ini.GetBool("IRCUsePerform", false);
	prefs->m_birclistonconnect=ini.GetBool("IRCListOnConnect", true);
	prefs->m_bircacceptlinks=ini.GetBool("IRCAcceptLinks", false);
	prefs->m_bircignoreinfomessage=ini.GetBool("IRCIgnoreInfoMessage", false);
	prefs->m_bircignoreemuleprotoinfomessage=ini.GetBool("IRCIgnoreEmuleProtoInfoMessage", true);
	prefs->smartidcheck=ini.GetBool("SmartIdCheck",true);
	prefs->m_bVerbose=ini.GetBool("Verbose",false);
	prefs->m_bpreviewprio=ini.GetBool("PreviewPrio",false);
	prefs->m_bupdatequeuelist=ini.GetBool("UpdateQueueList",false);
	prefs->m_bmanualhighprio=ini.GetBool("ManualHighPrio",false);
	prefs->m_btransferfullchunks=ini.GetBool("FullChunkTransfers",true);
	prefs->m_bstartnextfile=ini.GetBool("StartNextFile",false);
	prefs->m_bshowoverhead=ini.GetBool("ShowOverhead",false);

	sprintf(prefs->TxtEditor,"%s",ini.GetString("TxtEditor","notepad.exe"));

	//if (prefs->maxGraphDownloadRate<prefs->maxdownload) prefs->maxdownload=UNLIMITED;
	//if (prefs->maxGraphUploadRate<prefs->maxupload) prefs->maxupload=UNLIMITED;

	ini.SerGet(true, prefs->downloadColumnWidths,
		ELEMENT_COUNT(prefs->downloadColumnWidths), "DownloadColumnWidths");
	ini.SerGet(true, prefs->downloadColumnHidden,
		ELEMENT_COUNT(prefs->downloadColumnHidden), "DownloadColumnHidden");
	ini.SerGet(true, prefs->downloadColumnOrder,
		ELEMENT_COUNT(prefs->downloadColumnOrder), "DownloadColumnOrder");
	ini.SerGet(true, prefs->uploadColumnWidths,
		ELEMENT_COUNT(prefs->uploadColumnWidths), "UploadColumnWidths");
	ini.SerGet(true, prefs->uploadColumnHidden,
		ELEMENT_COUNT(prefs->uploadColumnHidden), "UploadColumnHidden");
	ini.SerGet(true, prefs->uploadColumnOrder,
		ELEMENT_COUNT(prefs->uploadColumnOrder), "UploadColumnOrder");
	ini.SerGet(true, prefs->queueColumnWidths,
		ELEMENT_COUNT(prefs->queueColumnWidths), "QueueColumnWidths");
	ini.SerGet(true, prefs->queueColumnHidden,
		ELEMENT_COUNT(prefs->queueColumnHidden), "QueueColumnHidden");
	ini.SerGet(true, prefs->queueColumnOrder,
		ELEMENT_COUNT(prefs->queueColumnOrder), "QueueColumnOrder");
	ini.SerGet(true, prefs->searchColumnWidths,
		ELEMENT_COUNT(prefs->searchColumnWidths), "SearchColumnWidths");
	ini.SerGet(true, prefs->searchColumnHidden,
		ELEMENT_COUNT(prefs->searchColumnHidden), "SearchColumnHidden");
	ini.SerGet(true, prefs->searchColumnOrder,
		ELEMENT_COUNT(prefs->searchColumnOrder), "SearchColumnOrder");
	ini.SerGet(true, prefs->sharedColumnWidths,
		ELEMENT_COUNT(prefs->sharedColumnWidths), "SharedColumnWidths");
	ini.SerGet(true, prefs->sharedColumnHidden,
		ELEMENT_COUNT(prefs->sharedColumnHidden), "SharedColumnHidden");
	ini.SerGet(true, prefs->sharedColumnOrder,
		ELEMENT_COUNT(prefs->sharedColumnOrder), "SharedColumnOrder");
	ini.SerGet(true, prefs->serverColumnWidths,
		ELEMENT_COUNT(prefs->serverColumnWidths), "ServerColumnWidths");
	ini.SerGet(true, prefs->serverColumnHidden,
		ELEMENT_COUNT(prefs->serverColumnHidden), "ServerColumnHidden");
	ini.SerGet(true, prefs->serverColumnOrder,
		ELEMENT_COUNT(prefs->serverColumnOrder), "ServerColumnOrder");

	// Barry - Provide a mechanism for all tables to store/retrieve sort order
	prefs->tableSortItemDownload = ini.GetInt("TableSortItemDownload", 0);
	prefs->tableSortItemUpload = ini.GetInt("TableSortItemUpload", 0);
	prefs->tableSortItemQueue = ini.GetInt("TableSortItemQueue", 0);
	prefs->tableSortItemSearch = ini.GetInt("TableSortItemSearch", 0);
	prefs->tableSortItemShared = ini.GetInt("TableSortItemShared", 0);
	prefs->tableSortItemServer = ini.GetInt("TableSortItemServer", 0);
	prefs->tableSortAscendingDownload = ini.GetBool("TableSortAscendingDownload", true);
	prefs->tableSortAscendingUpload = ini.GetBool("TableSortAscendingUpload", true);
	prefs->tableSortAscendingQueue = ini.GetBool("TableSortAscendingQueue", true);
	prefs->tableSortAscendingSearch = ini.GetBool("TableSortAscendingSearch", true);
	prefs->tableSortAscendingShared = ini.GetBool("TableSortAscendingShared", true);
	prefs->tableSortAscendingServer = ini.GetBool("TableSortAscendingServer", true);

	if (prefs->statsAverageMinutes<1) prefs->statsAverageMinutes=5;

	CString buffer2;
	for (int i=0;i<15;i++) {
		buffer2.Format("StatColor%i",i);
		sprintf(buffer,ini.GetString(buffer2,"0"));
		prefs->statcolors[i]=_atoi64(buffer);
		if (prefs->statcolors[i]==0) {ResetStatsColor(i);}
	}

	sprintf(buffer,ini.GetString("TotalDownloadedBytes",0,"Statistics"));
	prefs->totalDownloadedBytes=_atoi64(buffer);

	sprintf(buffer,ini.GetString("TotalUploadedBytes",0,"Statistics"));
	prefs->totalUploadedBytes=_atoi64(buffer);

	SetLanguage();
}

WORD CPreferences::GetWindowsVersion(){
	static bWinVerAlreadyDetected = false;
	if(!bWinVerAlreadyDetected)
	{	
		bWinVerAlreadyDetected = true;
		m_wWinVer = DetectWinVersion();	
	}	
	return m_wWinVer;
}

uint16 CPreferences::GetMaxConperFive(){
	return prefs->MaxConperFive;
}

uint16 CPreferences::GetDefaultMaxConperFive(){
	switch (GetWindowsVersion()){
		case _WINVER_98_:
			return 5;
		case _WINVER_95_:	
		case _WINVER_ME_:
			return MAXCON5WIN9X;
		case _WINVER_2K_:
		case _WINVER_XP_:
			return MAXCONPER5SEC;
		default:
			return MAXCONPER5SEC;
	}
}

// Barry - Provide a mechanism for all tables to store/retrieve sort order
int CPreferences::GetColumnSortItem(Table t) const
{
	switch(t) 
	{
		case tableDownload:
			return prefs->tableSortItemDownload;
		case tableUpload:
			return prefs->tableSortItemUpload;
		case tableQueue:
			return prefs->tableSortItemQueue;
		case tableSearch:
			return prefs->tableSortItemSearch;
		case tableShared:
			return prefs->tableSortItemShared;
		case tableServer:
			return prefs->tableSortItemServer;
	}
	return 0;
}

// Barry - Provide a mechanism for all tables to store/retrieve sort order
bool CPreferences::GetColumnSortAscending(Table t) const
{
	switch(t) 
	{
		case tableDownload:
			return prefs->tableSortAscendingDownload;
		case tableUpload:
			return prefs->tableSortAscendingUpload;
		case tableQueue:
			return prefs->tableSortAscendingQueue;
		case tableSearch:
			return prefs->tableSortAscendingSearch;
		case tableShared:
			return prefs->tableSortAscendingShared;
		case tableServer:
			return prefs->tableSortAscendingServer;
	}
	return true;
}

// Barry - Provide a mechanism for all tables to store/retrieve sort order
void CPreferences::SetColumnSortItem(Table t, int sortItem)
{
	switch(t) 
	{
		case tableDownload:
			prefs->tableSortItemDownload = sortItem;
			break;
		case tableUpload:
			prefs->tableSortItemUpload = sortItem;
			break;
		case tableQueue:
			prefs->tableSortItemQueue = sortItem;
			break;
		case tableSearch:
			prefs->tableSortItemSearch = sortItem;
			break;
		case tableShared:
			prefs->tableSortItemShared = sortItem;
			break;
		case tableServer:
			prefs->tableSortItemServer = sortItem;
			break;
	}
}

// Barry - Provide a mechanism for all tables to store/retrieve sort order
void CPreferences::SetColumnSortAscending(Table t, bool sortAscending)
{
	switch(t) 
	{
		case tableDownload:
			prefs->tableSortAscendingDownload = sortAscending;
			break;
		case tableUpload:
			prefs->tableSortAscendingUpload = sortAscending;
			break;
		case tableQueue:
			prefs->tableSortAscendingQueue = sortAscending;
			break;
		case tableSearch:
			prefs->tableSortAscendingSearch = sortAscending;
			break;
		case tableShared:
			prefs->tableSortAscendingShared = sortAscending;
			break;
		case tableServer:
			prefs->tableSortAscendingServer = sortAscending;
			break;
	}
}

void CPreferences::SetLanguage() {
	switch(prefs->languageID) {
		// read from ini and supported by the program?
		case MAKELANGID(LANG_ENGLISH,SUBLANG_DEFAULT):setlocale( LC_ALL, "english");break;
		case MAKELANGID(LANG_GERMAN,SUBLANG_DEFAULT):setlocale( LC_ALL, "german");break;
		case MAKELANGID(LANG_FRENCH,SUBLANG_DEFAULT):setlocale( LC_ALL, "french");break;
		case MAKELANGID(LANG_DANISH,SUBLANG_DEFAULT):setlocale( LC_ALL, "danish");break;
		case MAKELANGID(LANG_SPANISH,SUBLANG_SPANISH):setlocale( LC_ALL, "spanish");break;
		case MAKELANGID(LANG_DUTCH,SUBLANG_DEFAULT):setlocale( LC_ALL, "dutch");break;
		case MAKELANGID(LANG_RUSSIAN,SUBLANG_DEFAULT):setlocale( LC_ALL, "russian");break;
		case MAKELANGID(LANG_SLOVENIAN,SUBLANG_DEFAULT):setlocale( LC_ALL, "slovak");break;
		case MAKELANGID(LANG_CHINESE,SUBLANG_CHINESE_SIMPLIFIED):setlocale( LC_ALL, "chs");break;
		case MAKELANGID(LANG_CHINESE,SUBLANG_CHINESE_TRADITIONAL):setlocale( LC_ALL, "cht");break;
		case MAKELANGID(LANG_LITHUANIAN,SUBLANG_DEFAULT):setlocale( LC_ALL, "");break;
		case MAKELANGID(LANG_POLISH,SUBLANG_DEFAULT):setlocale( LC_ALL, "polish");break;
		case MAKELANGID(LANG_KOREAN,SUBLANG_DEFAULT):setlocale( LC_ALL, "korean");break;
		case MAKELANGID(LANG_PORTUGUESE,SUBLANG_PORTUGUESE_BRAZILIAN):setlocale( LC_ALL, "ptb");break;
		case MAKELANGID(LANG_PORTUGUESE,SUBLANG_PORTUGUESE):setlocale( LC_ALL, "ptg");break;
		case MAKELANGID(LANG_SWEDISH,SUBLANG_DEFAULT):setlocale( LC_ALL, "swedish");break;
		case MAKELANGID(LANG_NORWEGIAN,SUBLANG_NORWEGIAN_BOKMAL):setlocale( LC_ALL, "norwegian");break;
		case MAKELANGID(LANG_FINNISH,SUBLANG_DEFAULT):setlocale( LC_ALL, "finnish");break;
		case MAKELANGID(LANG_ITALIAN,SUBLANG_DEFAULT):setlocale( LC_ALL, "italian");break;
		case MAKELANGID(LANG_BULGARIAN,SUBLANG_DEFAULT):setlocale( LC_ALL, "hun");break;
		case MAKELANGID(LANG_CATALAN,SUBLANG_DEFAULT):setlocale( LC_ALL, "");break;
		case MAKELANGID(LANG_GREEK,SUBLANG_DEFAULT):setlocale( LC_ALL, "greek");break;
		case MAKELANGID(LANG_LATVIAN ,SUBLANG_DEFAULT):setlocale( LC_ALL, "");break;
		case MAKELANGID(LANG_TURKISH ,SUBLANG_DEFAULT):setlocale( LC_ALL, "turkish");break;
		case MAKELANGID(LANG_HUNGARIAN ,SUBLANG_DEFAULT):setlocale( LC_ALL, "hungarian");break;
		case MAKELANGID(LANG_GERMAN ,SUBLANG_GERMAN_SWISS):setlocale( LC_ALL, "german");break;
		default:{
			uint8 nLocalLang = ::GetThreadLocale();
			
            CString strLng1 = GetResString(IDS_MB_LANGUAGEINFO,MAKELANGID(LANG_ENGLISH,SUBLANG_DEFAULT));
			CString strLng2 = "";
			switch(nLocalLang) {
				case	LANG_GREEK:
				case 	LANG_GERMAN:
				case 	LANG_FRENCH:
				case 	LANG_DANISH:
				case 	LANG_SPANISH:
				case 	LANG_DUTCH:
				case 	LANG_RUSSIAN:
				case 	LANG_SLOVENIAN:
				case 	LANG_CHINESE:
				case 	LANG_LITHUANIAN:
				case 	LANG_NORWEGIAN:
				case 	LANG_POLISH:
				case 	LANG_KOREAN:
				case 	LANG_PORTUGUESE:
				case 	LANG_SWEDISH:
				case	LANG_FINNISH:
				case	LANG_ITALIAN:
				case	LANG_BULGARIAN:
				case	LANG_CATALAN:
				case	LANG_LATVIAN:
				case	LANG_TURKISH:
				case	LANG_HUNGARIAN:
				{
					prefs->languageID =  MAKELANGID(nLocalLang,SUBLANG_DEFAULT);
					SetThreadLocale(prefs->languageID);
					strLng2 = GetResString(IDS_MB_LANGUAGEINFO,prefs->languageID);
					break;
				}
				default:
					prefs->languageID = MAKELANGID(LANG_ENGLISH,SUBLANG_DEFAULT);
					SetThreadLocale(prefs->languageID);
			}

			CString strMessage = strLng1 + CString("\n\n") + strLng2;;
			MessageBox(0, strMessage.GetBuffer(),"Language",64);
		}
	}
	SetThreadLocale(prefs->languageID);

	// if loading a string fails, set language to English
	if (GetResString(IDS_MB_LANGUAGEINFO,prefs->languageID).GetLength()==0) {
		prefs->languageID = MAKELANGID(LANG_ENGLISH,SUBLANG_DEFAULT);
		SetThreadLocale(prefs->languageID);
	}
}

// Added by Tarod -imports serverlist from adresses.dat
void CPreferences::LoadServerlistAddresses()
{
	// First we must free list
	adresses_list.RemoveAll() ;

	CString toadd ;
	CString fullpath = CString(appdir) + "adresses.dat" ;
	CStdioFile* sdirfile = new CStdioFile() ;
	if (sdirfile->Open(fullpath, CFile::modeRead)) {
		adresses_list.RemoveAll() ;
		while (sdirfile->ReadString(toadd)) {
        	// [i_a] allow commented-out entries in the addresses.dat file.
            toadd.TrimLeft();
            if (toadd.GetLength() > 0 && toadd[0] != '#')
			adresses_list.AddHead(toadd) ;
        	// [/i_a]
		}
		sdirfile->Close() ;
	}
	delete sdirfile ;
}
