/*

Miranda NG: the free IM client for Microsoft* Windows*

Copyright (�) 2012-17 Miranda NG project (https://miranda-ng.org)
Copyright (c) 2000-04 Miranda ICQ/IM project,
all portions of this codebase are copyrighted to the people
listed in contributors.txt.

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., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
*/

#include "stdafx.h"

#define DM_SETAVATARNAME (WM_USER + 10)
#define DM_REALODAVATAR (WM_USER + 11)
#define DM_AVATARCHANGED (WM_USER + 12)
#define DM_PROTOCOLCHANGED (WM_USER + 13)

extern int _DebugPopup(MCONTACT hContact, const char *fmt, ...);
extern OBJLIST<protoPicCacheEntry> g_ProtoPictures;
extern HANDLE hEventChanged;
extern HINSTANCE g_hInst;
extern HICON g_hIcon;

extern BOOL ScreenToClient(HWND hWnd, LPRECT lpRect);

static BOOL dialoginit = TRUE;

struct WindowData
{
	MCONTACT hContact;
	HANDLE hHook;
};

static void RemoveProtoPic(const char *szProto)
{
	if (szProto == NULL)
		return;

	db_unset(NULL, PPICT_MODULE, szProto);

	if (!mir_strcmp(AVS_DEFAULT, szProto)) {
		for (int i = 0; i < g_ProtoPictures.getCount(); i++) {
			protoPicCacheEntry &p = g_ProtoPictures[i];
			if (p.szProtoname == NULL)
				continue;

			p.clear();
			CreateAvatarInCache(0, &p, (char *)p.szProtoname);
			NotifyEventHooks(hEventChanged, 0, (LPARAM)&p);
		}
		return;
	}

	if (strstr(szProto, "Global avatar for")) {
		char szProtoname[MAX_PATH] = { 0 };
		mir_strncpy(szProtoname, szProto, mir_strlen(szProto) - mir_strlen("accounts"));
		mir_strcpy(szProtoname, strrchr(szProtoname, ' ') + 1);
		for (int i = 0; i < g_ProtoPictures.getCount(); i++) {
			protoPicCacheEntry &p = g_ProtoPictures[i];

			if (p.szProtoname == NULL)
				continue;
			PROTOACCOUNT *pdescr = Proto_GetAccount(p.szProtoname);
			if (pdescr == NULL && mir_strcmp(p.szProtoname, szProto))
				continue;

			if (!mir_strcmp(p.szProtoname, szProto) || !mir_strcmp(pdescr->szProtoName, szProtoname)) {
				p.clear();
				CreateAvatarInCache(0, &p, (char *)p.szProtoname);
				NotifyEventHooks(hEventChanged, 0, (LPARAM)&p);
			}
		}
		return;
	}

	for (int i = 0; i < g_ProtoPictures.getCount(); i++) {
		protoPicCacheEntry &p = g_ProtoPictures[i];
		if (!mir_strcmp(p.szProtoname, szProto)) {
			p.clear();
			NotifyEventHooks(hEventChanged, 0, (LPARAM)&p);
		}
	}
}

static void SetProtoPic(char *szProto)
{
	wchar_t FileName[MAX_PATH], filter[256];
	Bitmap_GetFilter(filter, _countof(filter));

	OPENFILENAME ofn = { 0 };
	ofn.lStructSize = OPENFILENAME_SIZE_VERSION_400;
	ofn.lpstrFilter = filter;
	ofn.hwndOwner = 0;
	ofn.lpstrFile = FileName;
	ofn.nMaxFile = MAX_PATH;
	ofn.nMaxFileTitle = MAX_PATH;
	ofn.Flags = OFN_HIDEREADONLY;
	ofn.lpstrInitialDir = L".";
	*FileName = '\0';
	ofn.lpstrDefExt = L"";
	if (!GetOpenFileName(&ofn))
		return;

	if (_waccess(FileName, 4) == -1)
		return;

	wchar_t szNewPath[MAX_PATH];
	PathToRelativeW(FileName, szNewPath, g_szDataPath);
	db_set_ws(NULL, PPICT_MODULE, szProto, szNewPath);

	if (!mir_strcmp(AVS_DEFAULT, szProto)) {
		for (int i = 0; i < g_ProtoPictures.getCount(); i++) {
			protoPicCacheEntry& p = g_ProtoPictures[i];
			if (mir_strlen(p.szProtoname) == 0)
				continue;

			if (p.hbmPic == 0 || !mir_strcmp(p.szProtoname, AVS_DEFAULT)) {
				CreateAvatarInCache(0, &p, szProto);
				NotifyEventHooks(hEventChanged, 0, (LPARAM)&p);
			}
		}
	}
	else if (strstr(szProto, "Global avatar for")) {
		char szProtoname[MAX_PATH] = { 0 };
		mir_strncpy(szProtoname, szProto, mir_strlen(szProto) - mir_strlen("accounts"));
		mir_strcpy(szProtoname, strrchr(szProtoname, ' ') + 1);
		for (int i = 0; i < g_ProtoPictures.getCount(); i++) {
			PROTOACCOUNT* pdescr = Proto_GetAccount(g_ProtoPictures[i].szProtoname);
			if (pdescr == NULL && mir_strcmp(g_ProtoPictures[i].szProtoname, szProto))
				continue;

			if (!mir_strcmp(g_ProtoPictures[i].szProtoname, szProto) || !mir_strcmp(pdescr->szProtoName, szProtoname)) {
				protoPicCacheEntry& p = g_ProtoPictures[i];
				if (mir_strlen(p.szProtoname) != 0) {
					if (p.hbmPic == 0) {
						CreateAvatarInCache(0, &p, szProto);
						NotifyEventHooks(hEventChanged, 0, (LPARAM)&p);
					}
				}
			}
		}
	}
	else {
		for (int i = 0; i < g_ProtoPictures.getCount(); i++) {
			protoPicCacheEntry& p = g_ProtoPictures[i];
			if (mir_strlen(p.szProtoname) == 0)
				break;

			if (!mir_strcmp(p.szProtoname, szProto) && mir_strlen(p.szProtoname) == mir_strlen(szProto)) {
				if (p.hbmPic != 0)
					DeleteObject(p.hbmPic);
				memset(&p, 0, sizeof(AVATARCACHEENTRY));
				CreateAvatarInCache(0, &p, szProto);
				NotifyEventHooks(hEventChanged, 0, (LPARAM)&p);
				break;
			}
		}
	}
}

static char* g_selectedProto;

static INT_PTR CALLBACK DlgProcOptionsAvatars(HWND hwndDlg, UINT msg, WPARAM wParam, LPARAM lParam)
{
	switch (msg) {
	case WM_INITDIALOG:
		TranslateDialogDefault(hwndDlg);

		CheckDlgButton(hwndDlg, IDC_SHOWWARNINGS, db_get_b(0, AVS_MODULE, "warnings", 0) ? BST_CHECKED : BST_UNCHECKED);
		CheckDlgButton(hwndDlg, IDC_MAKE_GRAYSCALE, db_get_b(0, AVS_MODULE, "MakeGrayscale", 0) ? BST_CHECKED : BST_UNCHECKED);
		CheckDlgButton(hwndDlg, IDC_MAKE_TRANSPARENT_BKG, db_get_b(0, AVS_MODULE, "MakeTransparentBkg", 0) ? BST_CHECKED : BST_UNCHECKED);
		CheckDlgButton(hwndDlg, IDC_MAKE_TRANSP_PROPORTIONAL, db_get_b(0, AVS_MODULE, "MakeTransparencyProportionalToColorDiff", 0) ? BST_CHECKED : BST_UNCHECKED);

		SendDlgItemMessage(hwndDlg, IDC_BKG_NUM_POINTS_SPIN, UDM_SETRANGE, 0, MAKELONG(8, 2));
		SendDlgItemMessage(hwndDlg, IDC_BKG_NUM_POINTS_SPIN, UDM_SETPOS, 0, (LPARAM)db_get_w(0, AVS_MODULE, "TranspBkgNumPoints", 5));

		SendDlgItemMessage(hwndDlg, IDC_BKG_COLOR_DIFFERENCE_SPIN, UDM_SETRANGE, 0, MAKELONG(100, 0));
		SendDlgItemMessage(hwndDlg, IDC_BKG_COLOR_DIFFERENCE_SPIN, UDM_SETPOS, 0, (LPARAM)db_get_w(0, AVS_MODULE, "TranspBkgColorDiff", 10));
		{
			BOOL enabled = IsDlgButtonChecked(hwndDlg, IDC_MAKE_TRANSPARENT_BKG);
			EnableWindow(GetDlgItem(hwndDlg, IDC_BKG_NUM_POINTS_L), enabled);
			EnableWindow(GetDlgItem(hwndDlg, IDC_BKG_NUM_POINTS_SPIN), enabled);
			EnableWindow(GetDlgItem(hwndDlg, IDC_BKG_NUM_POINTS), enabled);
			EnableWindow(GetDlgItem(hwndDlg, IDC_BKG_COLOR_DIFFERENCE_L), enabled);
			EnableWindow(GetDlgItem(hwndDlg, IDC_BKG_COLOR_DIFFERENCE_SPIN), enabled);
			EnableWindow(GetDlgItem(hwndDlg, IDC_BKG_COLOR_DIFFERENCE), enabled);
			EnableWindow(GetDlgItem(hwndDlg, IDC_MAKE_TRANSP_PROPORTIONAL), enabled);
		}

		return TRUE;

	case WM_COMMAND:
		if ((LOWORD(wParam) == IDC_BKG_NUM_POINTS || LOWORD(wParam) == IDC_BKG_COLOR_DIFFERENCE)
			&& (HIWORD(wParam) != EN_CHANGE || (HWND)lParam != GetFocus()))
			return FALSE;
		SendMessage(GetParent(hwndDlg), PSM_CHANGED, 0, 0);
		break;

	case WM_NOTIFY:
		switch (((LPNMHDR)lParam)->idFrom) {
		case IDC_MAKE_TRANSPARENT_BKG:
		{
			BOOL transp_enabled = IsDlgButtonChecked(hwndDlg, IDC_MAKE_TRANSPARENT_BKG);
			EnableWindow(GetDlgItem(hwndDlg, IDC_BKG_NUM_POINTS_L), transp_enabled);
			EnableWindow(GetDlgItem(hwndDlg, IDC_BKG_NUM_POINTS_SPIN), transp_enabled);
			EnableWindow(GetDlgItem(hwndDlg, IDC_BKG_NUM_POINTS), transp_enabled);
			EnableWindow(GetDlgItem(hwndDlg, IDC_BKG_COLOR_DIFFERENCE_L), transp_enabled);
			EnableWindow(GetDlgItem(hwndDlg, IDC_BKG_COLOR_DIFFERENCE_SPIN), transp_enabled);
			EnableWindow(GetDlgItem(hwndDlg, IDC_BKG_COLOR_DIFFERENCE), transp_enabled);
			EnableWindow(GetDlgItem(hwndDlg, IDC_MAKE_TRANSP_PROPORTIONAL), transp_enabled);
			break;
		}
		case 0:
			switch (((LPNMHDR)lParam)->code) {
			case PSN_APPLY:
				db_set_b(NULL, AVS_MODULE, "warnings", IsDlgButtonChecked(hwndDlg, IDC_SHOWWARNINGS) ? 1 : 0);
				db_set_b(NULL, AVS_MODULE, "MakeGrayscale", IsDlgButtonChecked(hwndDlg, IDC_MAKE_GRAYSCALE) ? 1 : 0);
				db_set_b(NULL, AVS_MODULE, "MakeTransparentBkg", IsDlgButtonChecked(hwndDlg, IDC_MAKE_TRANSPARENT_BKG) ? 1 : 0);
				db_set_b(NULL, AVS_MODULE, "MakeTransparencyProportionalToColorDiff", IsDlgButtonChecked(hwndDlg, IDC_MAKE_TRANSP_PROPORTIONAL) ? 1 : 0);
				db_set_w(NULL, AVS_MODULE, "TranspBkgNumPoints", (WORD)SendDlgItemMessage(hwndDlg, IDC_BKG_NUM_POINTS_SPIN, UDM_GETPOS, 0, 0));
				db_set_w(NULL, AVS_MODULE, "TranspBkgColorDiff", (WORD)SendDlgItemMessage(hwndDlg, IDC_BKG_COLOR_DIFFERENCE_SPIN, UDM_GETPOS, 0, 0));
			}
		}
		break;
	}
	return FALSE;
}

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

static INT_PTR CALLBACK DlgProcOptionsOwn(HWND hwndDlg, UINT msg, WPARAM, LPARAM lParam)
{
	switch (msg) {
	case WM_INITDIALOG:
		TranslateDialogDefault(hwndDlg);

		CheckDlgButton(hwndDlg, IDC_MAKE_MY_AVATARS_TRANSP, db_get_b(0, AVS_MODULE, "MakeMyAvatarsTransparent", 0) ? BST_CHECKED : BST_UNCHECKED);
		CheckDlgButton(hwndDlg, IDC_SET_MAKE_SQUARE, db_get_b(0, AVS_MODULE, "SetAllwaysMakeSquare", 0) ? BST_CHECKED : BST_UNCHECKED);

		return TRUE;

	case WM_COMMAND:
		SendMessage(GetParent(hwndDlg), PSM_CHANGED, 0, 0);
		break;

	case WM_NOTIFY:
		switch (((LPNMHDR)lParam)->idFrom) {
		case 0:
			switch (((LPNMHDR)lParam)->code) {
			case PSN_APPLY:
				db_set_b(NULL, AVS_MODULE, "MakeMyAvatarsTransparent", IsDlgButtonChecked(hwndDlg, IDC_MAKE_MY_AVATARS_TRANSP) ? 1 : 0);
				db_set_b(NULL, AVS_MODULE, "SetAllwaysMakeSquare", IsDlgButtonChecked(hwndDlg, IDC_SET_MAKE_SQUARE) ? 1 : 0);
			}
		}
		break;
	}
	return FALSE;
}

static char* GetProtoFromList(HWND hwndDlg, int iItem)
{
	LVITEM item;
	item.mask = LVIF_PARAM;
	item.iItem = iItem;
	if (!ListView_GetItem(GetDlgItem(hwndDlg, IDC_PROTOCOLS), &item))
		return NULL;

	protoPicCacheEntry *pce = (protoPicCacheEntry *)item.lParam;
	return (pce == NULL) ? NULL : pce->szProtoname;
}

static INT_PTR CALLBACK DlgProcOptionsProtos(HWND hwndDlg, UINT msg, WPARAM wParam, LPARAM lParam)
{
	HWND hwndList = GetDlgItem(hwndDlg, IDC_PROTOCOLS);
	HWND hwndChoosePic = GetDlgItem(hwndDlg, IDC_SETPROTOPIC);
	HWND hwndRemovePic = GetDlgItem(hwndDlg, IDC_REMOVEPROTOPIC);

	switch (msg) {
	case WM_INITDIALOG:
		dialoginit = TRUE;
		TranslateDialogDefault(hwndDlg);

		ListView_SetExtendedListViewStyle(hwndList, LVS_EX_CHECKBOXES);
		{
			LVCOLUMN lvc = { 0 };
			lvc.mask = LVCF_FMT;
			lvc.fmt = LVCFMT_IMAGE | LVCFMT_LEFT;
			ListView_InsertColumn(hwndList, 0, &lvc);

			LVITEM item = { 0 };
			item.mask = LVIF_TEXT | LVIF_PARAM;
			item.iItem = 1000;
			for (int i = 0; i < g_ProtoPictures.getCount(); i++) {
				item.lParam = (LPARAM)&g_ProtoPictures[i];
				item.pszText = g_ProtoPictures[i].tszAccName;
				int newItem = ListView_InsertItem(hwndList, &item);
				if (newItem >= 0)
					ListView_SetCheckState(hwndList, newItem,
						db_get_b(NULL, AVS_MODULE, g_ProtoPictures[i].szProtoname, 1) ? TRUE : FALSE);
			}
			ListView_SetColumnWidth(hwndList, 0, LVSCW_AUTOSIZE);
			ListView_Arrange(hwndList, LVA_ALIGNLEFT | LVA_ALIGNTOP);
			EnableWindow(hwndChoosePic, FALSE);
			EnableWindow(hwndRemovePic, FALSE);
		}
		dialoginit = FALSE;
		return TRUE;

	case WM_COMMAND:
		switch (LOWORD(wParam)) {
		case IDC_SETPROTOPIC:
		case IDC_REMOVEPROTOPIC:
			int iItem = ListView_GetSelectionMark(hwndList);
			char *szProto = GetProtoFromList(hwndDlg, iItem);
			if (szProto) {
				if (LOWORD(wParam) == IDC_SETPROTOPIC)
					SetProtoPic(szProto);
				else
					RemoveProtoPic(szProto);

				NMHDR nm = { hwndList, IDC_PROTOCOLS, NM_CLICK };
				SendMessage(hwndDlg, WM_NOTIFY, 0, (LPARAM)&nm);
			}
		}
		break;

	case WM_DRAWITEM:
	{
		LPDRAWITEMSTRUCT dis = (LPDRAWITEMSTRUCT)lParam;
		if (dis->CtlType == ODT_BUTTON && dis->CtlID == IDC_PROTOPIC) {
			AVATARDRAWREQUEST avdrq = { 0 };
			avdrq.cbSize = sizeof(avdrq);
			avdrq.hTargetDC = dis->hDC;
			avdrq.dwFlags |= AVDRQ_PROTOPICT;
			avdrq.szProto = g_selectedProto;
			GetClientRect(GetDlgItem(hwndDlg, IDC_PROTOPIC), &avdrq.rcDraw);
			CallService(MS_AV_DRAWAVATAR, 0, (LPARAM)&avdrq);
		}
	}
	return TRUE;

	case WM_NOTIFY:
		if (dialoginit)
			break;

		switch (((LPNMHDR)lParam)->idFrom) {
		case IDC_PROTOCOLS:
			switch (((LPNMHDR)lParam)->code) {
			case LVN_KEYDOWN:
			{
				NMLVKEYDOWN* ptkd = (NMLVKEYDOWN*)lParam;
				if (ptkd&&ptkd->wVKey == VK_SPACE&&ListView_GetSelectedCount(ptkd->hdr.hwndFrom) == 1)
					SendMessage(GetParent(hwndDlg), PSM_CHANGED, 0, 0);
			}
			break;

			case LVN_ITEMCHANGED:
			{
				NMLISTVIEW *nmlv = (NMLISTVIEW *)lParam;
				if (IsWindowVisible(GetDlgItem(hwndDlg, IDC_PROTOCOLS)) && ((nmlv->uNewState ^ nmlv->uOldState) & LVIS_STATEIMAGEMASK))
					SendMessage(GetParent(hwndDlg), PSM_CHANGED, 0, 0);
			}
			break;

			case NM_CLICK:
				EnableWindow(hwndChoosePic, TRUE);
				EnableWindow(hwndRemovePic, TRUE);

				int iItem = ListView_GetSelectionMark(hwndList);
				g_selectedProto = GetProtoFromList(hwndDlg, iItem);
				if (g_selectedProto) {
					DBVARIANT dbv;
					if (!db_get_ws(NULL, PPICT_MODULE, g_selectedProto, &dbv)) {
						if (!PathIsAbsoluteW(VARSW(dbv.ptszVal))) {
							wchar_t szFinalPath[MAX_PATH];
							mir_snwprintf(szFinalPath, L"%%miranda_path%%\\%s", dbv.ptszVal);
							SetDlgItemText(hwndDlg, IDC_PROTOAVATARNAME, szFinalPath);
						}
						else SetDlgItemText(hwndDlg, IDC_PROTOAVATARNAME, dbv.ptszVal);

						InvalidateRect(GetDlgItem(hwndDlg, IDC_PROTOPIC), NULL, TRUE);
						db_free(&dbv);
					}
					else {
						SetDlgItemText(hwndDlg, IDC_PROTOAVATARNAME, L"");
						InvalidateRect(GetDlgItem(hwndDlg, IDC_PROTOPIC), NULL, TRUE);
					}
				}
			}
			break;

		case 0:
			if (((LPNMHDR)lParam)->code == PSN_APPLY) {
				for (int i = 0; i < ListView_GetItemCount(hwndList); i++) {
					char *szProto = GetProtoFromList(hwndDlg, i);

					BOOL oldVal = db_get_b(NULL, AVS_MODULE, szProto, 1);
					BOOL newVal = ListView_GetCheckState(hwndList, i);

					if (oldVal && !newVal)
						for (MCONTACT hContact = db_find_first(szProto); hContact; hContact = db_find_next(hContact, szProto))
							DeleteAvatarFromCache(hContact, TRUE);

					if (newVal)
						db_set_b(NULL, AVS_MODULE, szProto, 1);
					else
						db_set_b(NULL, AVS_MODULE, szProto, 0);
				}
			}
		}
		break;
	}
	return FALSE;
}

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

static void LoadTransparentData(HWND hwndDlg, MCONTACT hContact)
{
	CheckDlgButton(hwndDlg, IDC_MAKETRANSPBKG, db_get_b(hContact, "ContactPhoto", "MakeTransparentBkg", db_get_b(0, AVS_MODULE, "MakeTransparentBkg", 0)) ? BST_CHECKED : BST_UNCHECKED);
	SendDlgItemMessage(hwndDlg, IDC_BKG_NUM_POINTS_SPIN, UDM_SETPOS, 0, (LPARAM)db_get_w(hContact, "ContactPhoto", "TranspBkgNumPoints", db_get_w(0, AVS_MODULE, "TranspBkgNumPoints", 5)));
	SendDlgItemMessage(hwndDlg, IDC_BKG_COLOR_DIFFERENCE_SPIN, UDM_SETPOS, 0, (LPARAM)db_get_w(hContact, "ContactPhoto", "TranspBkgColorDiff", db_get_w(0, AVS_MODULE, "TranspBkgColorDiff", 10)));

	BOOL transp_enabled = IsDlgButtonChecked(hwndDlg, IDC_MAKETRANSPBKG);
	EnableWindow(GetDlgItem(hwndDlg, IDC_BKG_NUM_POINTS_L), transp_enabled);
	EnableWindow(GetDlgItem(hwndDlg, IDC_BKG_NUM_POINTS_SPIN), transp_enabled);
	EnableWindow(GetDlgItem(hwndDlg, IDC_BKG_NUM_POINTS), transp_enabled);
	EnableWindow(GetDlgItem(hwndDlg, IDC_BKG_COLOR_DIFFERENCE_L), transp_enabled);
	EnableWindow(GetDlgItem(hwndDlg, IDC_BKG_COLOR_DIFFERENCE_SPIN), transp_enabled);
	EnableWindow(GetDlgItem(hwndDlg, IDC_BKG_COLOR_DIFFERENCE), transp_enabled);
}

static void SaveTransparentData(HWND hwndDlg, MCONTACT hContact)
{
	BOOL transp = IsDlgButtonChecked(hwndDlg, IDC_MAKETRANSPBKG);
	if (db_get_b(0, AVS_MODULE, "MakeTransparentBkg", 0) == transp)
		db_unset(hContact, "ContactPhoto", "MakeTransparentBkg");
	else
		db_set_b(hContact, "ContactPhoto", "MakeTransparentBkg", transp);

	WORD tmp = (WORD)SendDlgItemMessage(hwndDlg, IDC_BKG_NUM_POINTS_SPIN, UDM_GETPOS, 0, 0);
	if (db_get_w(0, AVS_MODULE, "TranspBkgNumPoints", 5) == tmp)
		db_unset(hContact, "ContactPhoto", "TranspBkgNumPoints");
	else
		db_set_w(hContact, "ContactPhoto", "TranspBkgNumPoints", tmp);

	tmp = (WORD)SendDlgItemMessage(hwndDlg, IDC_BKG_COLOR_DIFFERENCE_SPIN, UDM_GETPOS, 0, 0);
	if (db_get_w(0, AVS_MODULE, "TranspBkgColorDiff", 10) == tmp)
		db_unset(hContact, "ContactPhoto", "TranspBkgColorDiff");
	else
		db_set_w(hContact, "ContactPhoto", "TranspBkgColorDiff", tmp);
}

static void SaveTransparentData(HWND hwndDlg, MCONTACT hContact, BOOL locked)
{
	SaveTransparentData(hwndDlg, hContact);

	MCONTACT tmp = GetContactThatHaveTheAvatar(hContact, locked);
	if (tmp != hContact)
		SaveTransparentData(hwndDlg, tmp);
}

INT_PTR CALLBACK DlgProcAvatarOptions(HWND hwndDlg, UINT msg, WPARAM wParam, LPARAM lParam)
{
	WindowData *dat = (WindowData*)GetWindowLongPtr(hwndDlg, GWLP_USERDATA);
	MCONTACT hContact = (dat) ? dat->hContact : INVALID_CONTACT_ID;

	switch (msg) {
	case WM_INITDIALOG:
		dat = (WindowData*)malloc(sizeof(WindowData));
		dat->hContact = hContact = lParam;
		SetWindowLongPtr(hwndDlg, GWLP_USERDATA, (LONG_PTR)dat);

		TranslateDialogDefault(hwndDlg);
		if (hContact) {
			wchar_t szTitle[512];
			mir_snwprintf(szTitle, TranslateT("Set avatar options for %s"), pcli->pfnGetContactDisplayName(hContact, 0));
			SetWindowText(hwndDlg, szTitle);
		}
		SendMessage(hwndDlg, DM_SETAVATARNAME, 0, 0);
		ShowWindow(hwndDlg, SW_SHOWNORMAL);
		InvalidateRect(GetDlgItem(hwndDlg, IDC_PROTOPIC), NULL, FALSE);
		CheckDlgButton(hwndDlg, IDC_PROTECTAVATAR, db_get_b(hContact, "ContactPhoto", "Locked", 0) ? BST_CHECKED : BST_UNCHECKED);
		CheckDlgButton(hwndDlg, IDC_HIDEAVATAR, db_get_b(hContact, "ContactPhoto", "Hidden", 0) ? BST_CHECKED : BST_UNCHECKED);

		SendDlgItemMessage(hwndDlg, IDC_BKG_NUM_POINTS_SPIN, UDM_SETBUDDY, (WPARAM)GetDlgItem(hwndDlg, IDC_BKG_NUM_POINTS), 0);
		SendDlgItemMessage(hwndDlg, IDC_BKG_NUM_POINTS_SPIN, UDM_SETRANGE, 0, MAKELONG(8, 2));

		SendDlgItemMessage(hwndDlg, IDC_BKG_COLOR_DIFFERENCE_SPIN, UDM_SETBUDDY, (WPARAM)GetDlgItem(hwndDlg, IDC_BKG_COLOR_DIFFERENCE), 0);
		SendDlgItemMessage(hwndDlg, IDC_BKG_COLOR_DIFFERENCE_SPIN, UDM_SETRANGE, 0, MAKELONG(100, 0));

		LoadTransparentData(hwndDlg, GetContactThatHaveTheAvatar(hContact));
		dat->hHook = HookEventMessage(ME_AV_AVATARCHANGED, hwndDlg, DM_AVATARCHANGED);
		SendMessage(hwndDlg, WM_SETICON, IMAGE_ICON, (LPARAM)g_hIcon);
		return TRUE;

	case WM_COMMAND:
		switch (LOWORD(wParam)) {
		case ID_USE_DEFAULTS:
			hContact = GetContactThatHaveTheAvatar(hContact);

			db_unset(hContact, "ContactPhoto", "MakeTransparentBkg");
			db_unset(hContact, "ContactPhoto", "TranspBkgNumPoints");
			db_unset(hContact, "ContactPhoto", "TranspBkgColorDiff");

			LoadTransparentData(hwndDlg, hContact);

			SendMessage(hwndDlg, DM_REALODAVATAR, 0, 0);
			break;

		case IDOK:
		{
			BOOL locked = IsDlgButtonChecked(hwndDlg, IDC_PROTECTAVATAR);
			int hidden = IsDlgButtonChecked(hwndDlg, IDC_HIDEAVATAR) ? 1 : 0;
			SetAvatarAttribute(hContact, AVS_HIDEONCLIST, hidden);
			if (hidden != db_get_b(hContact, "ContactPhoto", "Hidden", 0))
				db_set_b(hContact, "ContactPhoto", "Hidden", hidden);

			if (!locked && db_get_b(hContact, "ContactPhoto", "NeedUpdate", 0))
				QueueAdd(hContact);
		}
		// Continue to the cancel handle

		case IDCANCEL:
			DestroyWindow(hwndDlg);
			break;

		case IDC_PROTECTAVATAR:
		{
			BOOL locked = IsDlgButtonChecked(hwndDlg, IDC_PROTECTAVATAR);
			ProtectAvatar(hContact, locked ? 1 : 0);
		}
		break;

		case IDC_CHANGE:
			SetAvatar(hContact, 0);
			SendMessage(hwndDlg, DM_SETAVATARNAME, 0, 0);
			CheckDlgButton(hwndDlg, IDC_PROTECTAVATAR, db_get_b(hContact, "ContactPhoto", "Locked", 0) ? BST_CHECKED : BST_UNCHECKED);
			break;

		case IDC_BKG_NUM_POINTS:
		case IDC_BKG_COLOR_DIFFERENCE:
			if (HIWORD(wParam) != EN_CHANGE || (HWND)lParam != GetFocus())
				break;

		case IDC_MAKETRANSPBKG:
		{
			BOOL enable = IsDlgButtonChecked(hwndDlg, IDC_MAKETRANSPBKG);
			EnableWindow(GetDlgItem(hwndDlg, IDC_BKG_NUM_POINTS_L), enable);
			EnableWindow(GetDlgItem(hwndDlg, IDC_BKG_NUM_POINTS_SPIN), enable);
			EnableWindow(GetDlgItem(hwndDlg, IDC_BKG_NUM_POINTS), enable);
			EnableWindow(GetDlgItem(hwndDlg, IDC_BKG_COLOR_DIFFERENCE_L), enable);
			EnableWindow(GetDlgItem(hwndDlg, IDC_BKG_COLOR_DIFFERENCE_SPIN), enable);
			EnableWindow(GetDlgItem(hwndDlg, IDC_BKG_COLOR_DIFFERENCE), enable);

			SendMessage(hwndDlg, DM_REALODAVATAR, 0, 0);
		}
		break;

		case IDC_RESET:
			ProtectAvatar(hContact, 0);
			if (MessageBox(0, TranslateT("Delete picture file from disk (may be necessary to force a reload, but will delete local pictures)?"), TranslateT("Reset contact picture"), MB_YESNO) == IDYES) {
				DBVARIANT dbv = { 0 };
				if (!db_get_ws(hContact, "ContactPhoto", "File", &dbv)) {
					DeleteFile(dbv.ptszVal);
					db_free(&dbv);
				}
			}
			db_unset(hContact, "ContactPhoto", "Locked");
			db_unset(hContact, "ContactPhoto", "Backup");
			db_unset(hContact, "ContactPhoto", "RFile");
			db_unset(hContact, "ContactPhoto", "File");
			db_unset(hContact, "ContactPhoto", "Format");
			{
				char *szProto = GetContactProto(hContact);
				db_unset(hContact, szProto, "AvatarHash");
				db_unset(hContact, szProto, "AvatarSaved");
				DeleteAvatarFromCache(hContact, FALSE);

				QueueAdd(hContact);
				DestroyWindow(hwndDlg);
			}
			break;

		case IDC_DELETE:
			if (MessageBox(0, TranslateT("Delete picture file from disk (may be necessary to force a reload, but will delete local pictures)?"), TranslateT("Reset contact picture"), MB_YESNO) == IDYES) {
				DBVARIANT dbv = { 0 };
				ProtectAvatar(hContact, 0);
				if (!db_get_ws(hContact, "ContactPhoto", "File", &dbv)) {
					DeleteFile(dbv.ptszVal);
					db_free(&dbv);
				}
			}
			db_unset(hContact, "ContactPhoto", "Locked");
			db_unset(hContact, "ContactPhoto", "Backup");
			db_unset(hContact, "ContactPhoto", "RFile");
			db_unset(hContact, "ContactPhoto", "File");
			db_unset(hContact, "ContactPhoto", "Format");
			DeleteAvatarFromCache(hContact, FALSE);
			SendMessage(hwndDlg, DM_SETAVATARNAME, 0, 0);
			InvalidateRect(GetDlgItem(hwndDlg, IDC_PROTOPIC), NULL, TRUE);
			break;
		}
		break;

	case WM_DRAWITEM:
	{
		LPDRAWITEMSTRUCT dis = (LPDRAWITEMSTRUCT)lParam;
		if (dis->CtlType == ODT_BUTTON && dis->CtlID == IDC_PROTOPIC) {
			AVATARDRAWREQUEST avdrq = { 0 };
			GetClientRect(GetDlgItem(hwndDlg, IDC_PROTOPIC), &avdrq.rcDraw);

			FillRect(dis->hDC, &avdrq.rcDraw, GetSysColorBrush(COLOR_BTNFACE));

			avdrq.hContact = hContact;
			avdrq.cbSize = sizeof(avdrq);
			avdrq.hTargetDC = dis->hDC;
			avdrq.dwFlags |= AVDRQ_DRAWBORDER;
			avdrq.clrBorder = GetSysColor(COLOR_BTNTEXT);
			avdrq.radius = 6;
			if (!CallService(MS_AV_DRAWAVATAR, 0, (LPARAM)&avdrq)) {
				// Get text rectangle
				RECT rc = avdrq.rcDraw;
				rc.top += 10;
				rc.bottom -= 10;
				rc.left += 10;
				rc.right -= 10;

				// Calc text size
				RECT rc_ret = rc;
				DrawText(dis->hDC, TranslateT("Contact has no avatar"), -1, &rc_ret,
					DT_WORDBREAK | DT_NOPREFIX | DT_CENTER | DT_CALCRECT);

				// Calc needed size
				rc.top += ((rc.bottom - rc.top) - (rc_ret.bottom - rc_ret.top)) / 2;
				rc.bottom = rc.top + (rc_ret.bottom - rc_ret.top);
				DrawText(dis->hDC, TranslateT("Contact has no avatar"), -1, &rc,
					DT_WORDBREAK | DT_NOPREFIX | DT_CENTER);
			}

			FrameRect(dis->hDC, &avdrq.rcDraw, GetSysColorBrush(COLOR_BTNSHADOW));
		}
	}
	return TRUE;

	case DM_SETAVATARNAME:
	{
		wchar_t szFinalName[MAX_PATH];
		DBVARIANT dbv = { 0 };
		BYTE is_locked = db_get_b(hContact, "ContactPhoto", "Locked", 0);

		szFinalName[0] = 0;

		if (is_locked && !db_get_ws(hContact, "ContactPhoto", "Backup", &dbv)) {
			MyPathToAbsolute(dbv.ptszVal, szFinalName);
			db_free(&dbv);
		}
		else if (!db_get_ws(hContact, "ContactPhoto", "RFile", &dbv)) {
			MyPathToAbsolute(dbv.ptszVal, szFinalName);
			db_free(&dbv);
		}
		else if (!db_get_ws(hContact, "ContactPhoto", "File", &dbv)) {
			MyPathToAbsolute(dbv.ptszVal, szFinalName);
			db_free(&dbv);
		}
		szFinalName[MAX_PATH - 1] = 0;
		SetDlgItemText(hwndDlg, IDC_AVATARNAME, szFinalName);
	}
	break;

	case DM_REALODAVATAR:
		SaveTransparentData(hwndDlg, hContact, IsDlgButtonChecked(hwndDlg, IDC_PROTECTAVATAR));
		ChangeAvatar(hContact, true);
		InvalidateRect(GetDlgItem(hwndDlg, IDC_PROTOPIC), NULL, TRUE);
		break;

	case DM_AVATARCHANGED:
		InvalidateRect(GetDlgItem(hwndDlg, IDC_PROTOPIC), NULL, TRUE);
		break;

	case WM_NCDESTROY:
		if (dat) {
			UnhookEvent(dat->hHook);
			free(dat);
		}
		SetWindowLongPtr(hwndDlg, GWLP_USERDATA, 0);
		break;
	}
	return FALSE;
}

int OptInit(WPARAM wParam, LPARAM)
{
	OPTIONSDIALOGPAGE odp = { 0 };
	odp.hInstance = g_hInst;
	odp.flags = ODPF_BOLDGROUPS;
	odp.szGroup.a = LPGEN("Contacts");
	odp.szTitle.a = LPGEN("Avatars");

	odp.szTab.a = LPGEN("Protocols");
	odp.pszTemplate = MAKEINTRESOURCEA(IDD_OPTIONS_PICTS);
	odp.pfnDlgProc = DlgProcOptionsProtos;
	Options_AddPage(wParam, &odp);

	odp.szTab.a = LPGEN("Contact avatars");
	odp.pszTemplate = MAKEINTRESOURCEA(IDD_OPTIONS_AVATARS);
	odp.pfnDlgProc = DlgProcOptionsAvatars;
	Options_AddPage(wParam, &odp);

	odp.szTab.a = LPGEN("Own avatars");
	odp.pszTemplate = MAKEINTRESOURCEA(IDD_OPTIONS_OWN);
	odp.pfnDlgProc = DlgProcOptionsOwn;
	Options_AddPage(wParam, &odp);
	return 0;
}

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

static INT_PTR CALLBACK DlgProcAvatarUserInfo(HWND hwndDlg, UINT msg, WPARAM wParam, LPARAM lParam)
{
	WindowData *dat = (WindowData*)GetWindowLongPtr(hwndDlg, GWLP_USERDATA);
	MCONTACT hContact = (dat) ? dat->hContact : INVALID_CONTACT_ID;

	switch (msg) {
	case WM_INITDIALOG:
		dat = (WindowData*)malloc(sizeof(WindowData));
		dat->hContact = hContact = lParam;
		{
			HWND protopic = GetDlgItem(hwndDlg, IDC_PROTOPIC);
			SendMessage(protopic, AVATAR_SETCONTACT, 0, (LPARAM)hContact);
			SendMessage(protopic, AVATAR_SETAVATARBORDERCOLOR, 0, (LPARAM)GetSysColor(COLOR_BTNSHADOW));
			SendMessage(protopic, AVATAR_SETNOAVATARTEXT, 0, (LPARAM)LPGENW("Contact has no avatar"));
			SendMessage(protopic, AVATAR_RESPECTHIDDEN, 0, (LPARAM)FALSE);
			SendMessage(protopic, AVATAR_SETRESIZEIFSMALLER, 0, (LPARAM)FALSE);
		}

		SetWindowLongPtr(hwndDlg, GWLP_USERDATA, (LONG_PTR)dat);
		TranslateDialogDefault(hwndDlg);
		SendMessage(hwndDlg, DM_SETAVATARNAME, 0, 0);
		CheckDlgButton(hwndDlg, IDC_PROTECTAVATAR, db_get_b(hContact, "ContactPhoto", "Locked", 0) ? BST_CHECKED : BST_UNCHECKED);
		CheckDlgButton(hwndDlg, IDC_HIDEAVATAR, db_get_b(hContact, "ContactPhoto", "Hidden", 0) ? BST_CHECKED : BST_UNCHECKED);

		SendDlgItemMessage(hwndDlg, IDC_BKG_NUM_POINTS_SPIN, UDM_SETBUDDY, (WPARAM)GetDlgItem(hwndDlg, IDC_BKG_NUM_POINTS), 0);
		SendDlgItemMessage(hwndDlg, IDC_BKG_NUM_POINTS_SPIN, UDM_SETRANGE, 0, MAKELONG(8, 2));

		SendDlgItemMessage(hwndDlg, IDC_BKG_COLOR_DIFFERENCE_SPIN, UDM_SETBUDDY, (WPARAM)GetDlgItem(hwndDlg, IDC_BKG_COLOR_DIFFERENCE), 0);
		SendDlgItemMessage(hwndDlg, IDC_BKG_COLOR_DIFFERENCE_SPIN, UDM_SETRANGE, 0, MAKELONG(100, 0));

		LoadTransparentData(hwndDlg, GetContactThatHaveTheAvatar(hContact));
		break;

	case WM_COMMAND:
		switch (LOWORD(wParam)) {
		case ID_USE_DEFAULTS:
			hContact = GetContactThatHaveTheAvatar(hContact);

			db_unset(hContact, "ContactPhoto", "MakeTransparentBkg");
			db_unset(hContact, "ContactPhoto", "TranspBkgNumPoints");
			db_unset(hContact, "ContactPhoto", "TranspBkgColorDiff");

			LoadTransparentData(hwndDlg, hContact);

			SendMessage(hwndDlg, DM_REALODAVATAR, 0, 0);
			break;

		case IDC_CHANGE:
			SetAvatar(hContact, 0);
			SendMessage(hwndDlg, DM_SETAVATARNAME, 0, 0);
			CheckDlgButton(hwndDlg, IDC_PROTECTAVATAR, db_get_b(hContact, "ContactPhoto", "Locked", 0) ? BST_CHECKED : BST_UNCHECKED);
			break;

		case IDC_HIDEAVATAR:
			{
				int hidden = IsDlgButtonChecked(hwndDlg, IDC_HIDEAVATAR) ? 1 : 0;
				SetAvatarAttribute(hContact, AVS_HIDEONCLIST, hidden);
				if (hidden != db_get_b(hContact, "ContactPhoto", "Hidden", 0))
					db_set_b(hContact, "ContactPhoto", "Hidden", hidden);
			}
			break;

		case IDC_PROTECTAVATAR:
			{
				BOOL locked = IsDlgButtonChecked(hwndDlg, IDC_PROTECTAVATAR);
				SaveTransparentData(hwndDlg, hContact, locked);
				ProtectAvatar(hContact, locked ? 1 : 0);
			}
			break;

		case IDC_BKG_NUM_POINTS:
		case IDC_BKG_COLOR_DIFFERENCE:
			if (HIWORD(wParam) != EN_CHANGE || (HWND)lParam != GetFocus())
				break;

		case IDC_MAKETRANSPBKG:
			{
				BOOL enable = IsDlgButtonChecked(hwndDlg, IDC_MAKETRANSPBKG);
				EnableWindow(GetDlgItem(hwndDlg, IDC_BKG_NUM_POINTS_L), enable);
				EnableWindow(GetDlgItem(hwndDlg, IDC_BKG_NUM_POINTS_SPIN), enable);
				EnableWindow(GetDlgItem(hwndDlg, IDC_BKG_NUM_POINTS), enable);
				EnableWindow(GetDlgItem(hwndDlg, IDC_BKG_COLOR_DIFFERENCE_L), enable);
				EnableWindow(GetDlgItem(hwndDlg, IDC_BKG_COLOR_DIFFERENCE_SPIN), enable);
				EnableWindow(GetDlgItem(hwndDlg, IDC_BKG_COLOR_DIFFERENCE), enable);
			}
			SendMessage(hwndDlg, DM_REALODAVATAR, 0, 0);
			break;
		case IDC_RESET:
			ProtectAvatar(hContact, 0);
			if (MessageBox(0, TranslateT("Delete picture file from disk (may be necessary to force a reload, but will delete local pictures)?"), TranslateT("Reset contact picture"), MB_YESNO) == IDYES) {
				DBVARIANT dbv = { 0 };
				if (!db_get_ws(hContact, "ContactPhoto", "File", &dbv)) {
					DeleteFile(dbv.ptszVal);
					db_free(&dbv);
				}
			}
			db_unset(hContact, "ContactPhoto", "Locked");
			db_unset(hContact, "ContactPhoto", "Backup");
			db_unset(hContact, "ContactPhoto", "RFile");
			db_unset(hContact, "ContactPhoto", "File");
			db_unset(hContact, "ContactPhoto", "Format");
			{
				char *szProto = GetContactProto(hContact);
				db_unset(hContact, szProto, "AvatarHash");
				db_unset(hContact, szProto, "AvatarSaved");
				DeleteAvatarFromCache(hContact, FALSE);

				QueueAdd(hContact);
			}
			break;

		case IDC_DELETE:
			ProtectAvatar(hContact, 0);
			if (MessageBox(0, TranslateT("Delete picture file from disk (may be necessary to force a reload, but will delete local pictures)?"), TranslateT("Reset contact picture"), MB_YESNO) == IDYES) {
				DBVARIANT dbv = { 0 };
				if (!db_get_ws(hContact, "ContactPhoto", "File", &dbv)) {
					DeleteFile(dbv.ptszVal);
					db_free(&dbv);
				}
			}
			db_unset(hContact, "ContactPhoto", "Locked");
			db_unset(hContact, "ContactPhoto", "Backup");
			db_unset(hContact, "ContactPhoto", "RFile");
			db_unset(hContact, "ContactPhoto", "File");
			db_unset(hContact, "ContactPhoto", "Format");
			DeleteAvatarFromCache(hContact, FALSE);
			SendMessage(hwndDlg, DM_SETAVATARNAME, 0, 0);
			break;
		}
		break;

	case DM_REALODAVATAR:
		SaveTransparentData(hwndDlg, hContact, IsDlgButtonChecked(hwndDlg, IDC_PROTECTAVATAR));
		ChangeAvatar(hContact, true);
		break;

	case WM_NCDESTROY:
		free(dat);
		SetWindowLongPtr(hwndDlg, GWLP_USERDATA, 0);
		break;
	}
	return FALSE;
}

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

static char* GetSelectedProtocol(HWND hwndDlg)
{
	HWND hwndList = GetDlgItem(hwndDlg, IDC_PROTOCOLS);

	// Get selection
	int iItem = ListView_GetSelectionMark(hwndList);
	if (iItem < 0)
		return NULL;

	// Get protocol name
	LVITEM item = { 0 };
	item.mask = LVIF_PARAM;
	item.iItem = iItem;
	SendMessage(hwndList, LVM_GETITEMA, 0, (LPARAM)&item);
	return (char*)item.lParam;
}

static void EnableDisableControls(HWND hwndDlg, char *proto)
{
	if (IsDlgButtonChecked(hwndDlg, IDC_PER_PROTO)) {
		if (proto == NULL) {
			EnableWindow(GetDlgItem(hwndDlg, IDC_CHANGE), FALSE);
			EnableWindow(GetDlgItem(hwndDlg, IDC_DELETE), FALSE);
		}
		else {
			if (!ProtoServiceExists(proto, PS_SETMYAVATAR)) {
				EnableWindow(GetDlgItem(hwndDlg, IDC_CHANGE), FALSE);
				EnableWindow(GetDlgItem(hwndDlg, IDC_DELETE), FALSE);
			}
			else {
				EnableWindow(GetDlgItem(hwndDlg, IDC_CHANGE), TRUE);

				int width, height;
				SendDlgItemMessage(hwndDlg, IDC_PROTOPIC, AVATAR_GETUSEDSPACE, (WPARAM)&width, (LPARAM)&height);
				EnableWindow(GetDlgItem(hwndDlg, IDC_DELETE), (LPARAM)width != 0 || height != 0);
			}
		}
	}
	else {
		EnableWindow(GetDlgItem(hwndDlg, IDC_CHANGE), TRUE);

		if (db_get_b(NULL, AVS_MODULE, "GlobalUserAvatarNotConsistent", 1))
			EnableWindow(GetDlgItem(hwndDlg, IDC_DELETE), TRUE);
		else {
			int width, height;
			SendDlgItemMessage(hwndDlg, IDC_PROTOPIC, AVATAR_GETUSEDSPACE, (WPARAM)&width, (LPARAM)&height);
			EnableWindow(GetDlgItem(hwndDlg, IDC_DELETE), (LPARAM)width != 0 || height != 0);
		}
	}
}

static void OffsetWindow(HWND parent, HWND hwnd, int dx, int dy)
{
	RECT rc;
	GetWindowRect(hwnd, &rc);
	ScreenToClient(parent, &rc);
	OffsetRect(&rc, dx, dy);
	MoveWindow(hwnd, rc.left, rc.top, rc.right - rc.left, rc.bottom - rc.top, TRUE);
}

static void EnableDisableProtocols(HWND hwndDlg, BOOL init)
{
	int diff = 147; // Pre-calc
	BOOL perProto = IsDlgButtonChecked(hwndDlg, IDC_PER_PROTO);
	HWND hwndList = GetDlgItem(hwndDlg, IDC_PROTOCOLS);

	if (perProto) {
		if (!init && !IsWindowVisible(hwndList)) {
			// Show list of protocols
			ShowWindow(hwndList, SW_SHOW);

			// Move controls
			OffsetWindow(hwndDlg, GetDlgItem(hwndDlg, IDC_PROTOPIC), diff, 0);
			OffsetWindow(hwndDlg, GetDlgItem(hwndDlg, IDC_CHANGE), diff, 0);
			OffsetWindow(hwndDlg, GetDlgItem(hwndDlg, IDC_DELETE), diff, 0);
		}

		char * proto = GetSelectedProtocol(hwndDlg);
		if (proto == NULL) {
			ListView_SetItemState(hwndList, 0, LVIS_FOCUSED | LVIS_SELECTED, 0x0F);
		}
		else {
			SendDlgItemMessage(hwndDlg, IDC_PROTOPIC, AVATAR_SETPROTOCOL, 0, (LPARAM)proto);
			EnableDisableControls(hwndDlg, proto);
		}
	}
	else {
		if (init || IsWindowVisible(hwndList)) {
			// Show list of protocols
			ShowWindow(hwndList, SW_HIDE);

			// Move controls
			OffsetWindow(hwndDlg, GetDlgItem(hwndDlg, IDC_PROTOPIC), -diff, 0);
			OffsetWindow(hwndDlg, GetDlgItem(hwndDlg, IDC_CHANGE), -diff, 0);
			OffsetWindow(hwndDlg, GetDlgItem(hwndDlg, IDC_DELETE), -diff, 0);
		}

		SendDlgItemMessage(hwndDlg, IDC_PROTOPIC, AVATAR_SETPROTOCOL, 0, NULL);
	}
}

static INT_PTR CALLBACK DlgProcAvatarProtoInfo(HWND hwndDlg, UINT msg, WPARAM wParam, LPARAM lParam)
{
	switch (msg) {
	case WM_INITDIALOG:
		TranslateDialogDefault(hwndDlg);
		{
			HWND protopic = GetDlgItem(hwndDlg, IDC_PROTOPIC);
			SendMessage(protopic, AVATAR_SETAVATARBORDERCOLOR, 0, (LPARAM)GetSysColor(COLOR_BTNSHADOW));
			SendMessage(protopic, AVATAR_SETNOAVATARTEXT, 0, (LPARAM)LPGENW("No avatar"));
			SendMessage(protopic, AVATAR_SETRESIZEIFSMALLER, 0, (LPARAM)FALSE);

			HWND hwndList = GetDlgItem(hwndDlg, IDC_PROTOCOLS);
			ListView_SetExtendedListViewStyleEx(hwndList, 0, LVS_EX_SUBITEMIMAGES);

			HIMAGELIST hIml = ImageList_Create(16, 16, ILC_MASK | ILC_COLOR32, 4, 0);
			ListView_SetImageList(hwndList, hIml, LVSIL_SMALL);

			LVCOLUMN lvc = { 0 };
			lvc.mask = LVCF_FMT;
			lvc.fmt = LVCFMT_IMAGE | LVCFMT_LEFT;
			ListView_InsertColumn(hwndList, 0, &lvc);

			LVITEM item = { 0 };
			item.mask = LVIF_TEXT | LVIF_PARAM | LVIF_IMAGE;
			item.iItem = 1000;

			// List protocols
			PROTOACCOUNT **accs;
			int count, num = 0;

			Proto_EnumAccounts(&count, &accs);
			for (int i = 0; i < count; i++) {
				if (!ProtoServiceExists(accs[i]->szModuleName, PS_GETMYAVATAR))
					continue;

				if (!Proto_IsAvatarsEnabled(accs[i]->szModuleName))
					continue;

				ImageList_AddIcon(hIml, Skin_LoadProtoIcon(accs[i]->szModuleName, ID_STATUS_ONLINE));
				item.pszText = accs[i]->tszAccountName;
				item.iImage = num;
				item.lParam = (LPARAM)accs[i]->szModuleName;

				ListView_InsertItem(hwndList, &item);
				num++;
			}

			ListView_SetColumnWidth(hwndList, 0, LVSCW_AUTOSIZE);
			ListView_Arrange(hwndList, LVA_ALIGNLEFT | LVA_ALIGNTOP);

			// Check if should show per protocol avatars
			CheckDlgButton(hwndDlg, IDC_PER_PROTO, db_get_b(NULL, AVS_MODULE, "PerProtocolUserAvatars", 1) ? BST_CHECKED : BST_UNCHECKED);
			EnableDisableProtocols(hwndDlg, TRUE);
		}
		break;

	case WM_NOTIFY:
	{
		LPNMHDR nm = (LPNMHDR)lParam;
		switch (nm->idFrom) {
		case IDC_PROTOCOLS:
			switch (nm->code) {
			case LVN_ITEMCHANGED:
				LPNMLISTVIEW li = (LPNMLISTVIEW)nm;
				if (li->uNewState & LVIS_SELECTED) {
					SendDlgItemMessage(hwndDlg, IDC_PROTOPIC, AVATAR_SETPROTOCOL, 0, li->lParam);
					EnableDisableControls(hwndDlg, (char*)li->lParam);
				}
			}
			break;

		case IDC_PROTOPIC:
			if (nm->code == NM_AVATAR_CHANGED) {
				EnableDisableControls(hwndDlg, GetSelectedProtocol(hwndDlg));
				break;
			}
		}
	}
	break;

	case WM_COMMAND:
		switch (LOWORD(wParam)) {
		case IDC_CHANGE:
			if (BST_UNCHECKED == IsDlgButtonChecked(hwndDlg, IDC_PER_PROTO))
				SetMyAvatar(NULL, NULL);
			else {
				char *proto = GetSelectedProtocol(hwndDlg);
				if (proto != NULL)
					SetMyAvatar((WPARAM)proto, NULL);
			}
			break;

		case IDC_DELETE:
			if (BST_UNCHECKED == IsDlgButtonChecked(hwndDlg, IDC_PER_PROTO)) {
				if (MessageBox(hwndDlg, TranslateT("Are you sure you want to remove your avatar?"), TranslateT("Global avatar"), MB_YESNO) == IDYES)
					SetMyAvatar(NULL, (LPARAM)L"");
			}
			else {
				char *proto = GetSelectedProtocol(hwndDlg);
				if (proto == NULL)
					break;

				char description[256];
				CallProtoService(proto, PS_GETNAME, _countof(description), (LPARAM)description);
				wchar_t *descr = mir_a2u(description);
				if (MessageBox(hwndDlg, TranslateT("Are you sure you want to remove your avatar?"), descr, MB_YESNO) == IDYES)
					SetMyAvatar((WPARAM)proto, (LPARAM)L"");
				mir_free(descr);
			}
			break;

		case IDC_PER_PROTO:
			db_set_b(NULL, AVS_MODULE, "PerProtocolUserAvatars", IsDlgButtonChecked(hwndDlg, IDC_PER_PROTO) ? 1 : 0);
			EnableDisableProtocols(hwndDlg, FALSE);
			break;
		}
		break;
	}
	return FALSE;
}

int OnDetailsInit(WPARAM wParam, LPARAM lParam)
{
	OPTIONSDIALOGPAGE odp = { 0 };
	odp.hInstance = g_hInst;
	odp.szTitle.a = LPGEN("Avatar");

	MCONTACT hContact = lParam;
	if (hContact == NULL) {
		// User dialog
		odp.pfnDlgProc = DlgProcAvatarProtoInfo;
		odp.pszTemplate = MAKEINTRESOURCEA(IDD_PROTO_AVATARS);
		UserInfo_AddPage(wParam, &odp);
	}
	else {
		char *szProto = GetContactProto(hContact);
		if (szProto == NULL || db_get_b(NULL, AVS_MODULE, szProto, 1)) {
			// Contact dialog
			odp.pfnDlgProc = DlgProcAvatarUserInfo;
			odp.position = -2000000000;
			odp.pszTemplate = MAKEINTRESOURCEA(IDD_USER_AVATAR);
			UserInfo_AddPage(wParam, &odp);
		}
	}
	return 0;
}