From 0db94803bd3ca4599e6c54be7db72633806fad49 Mon Sep 17 00:00:00 2001
From: Rozhuk Ivan <rozhuk.im@gmail.com>
Date: Tue, 25 Nov 2014 13:50:58 +0000
Subject: add nullptr ckeck after alloca()

git-svn-id: http://svn.miranda-ng.org/main/trunk@11056 1316c22d-e87f-b044-9b9b-93d7a3e3ba9c
---
 src/modules/findadd/findadd.cpp | 2120 ++++++++++++++++++++-------------------
 1 file changed, 1061 insertions(+), 1059 deletions(-)

(limited to 'src/modules')

diff --git a/src/modules/findadd/findadd.cpp b/src/modules/findadd/findadd.cpp
index 99fda257b2..033ae492c0 100644
--- a/src/modules/findadd/findadd.cpp
+++ b/src/modules/findadd/findadd.cpp
@@ -1,1059 +1,1061 @@
-/*
-
-Miranda NG: the free IM client for Microsoft* Windows*
-
-Copyright (c) 2012-14 Miranda NG project (http://miranda-ng.org),
-Copyright (c) 2000-12 Miranda 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 "..\..\core\commonheaders.h"
-#include "findadd.h"
-
-#define TIMERID_THROBBER 111
-
-#define HM_SEARCHACK  (WM_USER+10)
-#define M_SETGROUPVISIBILITIES  (WM_USER+11)
-
-static HWND hwndFindAdd = NULL;
-static HANDLE hHookModulesLoaded = 0;
-static HGENMENU hMainMenuItem = NULL;
-static int OnSystemModulesLoaded(WPARAM wParam, LPARAM lParam);
-
-static int FindAddDlgResizer(HWND, LPARAM lParam, UTILRESIZECONTROL *urc)
-{
-	static int y, nextY, oldTop;
-	FindAddDlgData *dat = (FindAddDlgData*)lParam;
-
-	switch (urc->wId) {
-	case IDC_RESULTS:
-		return RD_ANCHORX_WIDTH | RD_ANCHORY_HEIGHT;
-
-	case IDOK:
-		dat->minDlgHeight = nextY + urc->rcItem.bottom - urc->rcItem.top;
-		return RD_ANCHORX_LEFT | RD_ANCHORY_BOTTOM;
-
-	case IDC_ADD:
-	case IDC_MOREOPTIONS:
-		return RD_ANCHORX_RIGHT | RD_ANCHORY_BOTTOM;
-
-	case IDC_STATUSBAR:
-		return RD_ANCHORX_WIDTH | RD_ANCHORY_BOTTOM;
-
-	case IDC_PROTOIDGROUP:	//the resize is always processed in template order
-		nextY = y = urc->rcItem.top;
-		if (dat->showProtoId) nextY = y + urc->rcItem.bottom - urc->rcItem.top + 7;
-		break;
-
-	case IDC_EMAILGROUP:
-		oldTop = urc->rcItem.top;
-		y = nextY;
-		if (dat->showEmail) nextY = y + urc->rcItem.bottom - urc->rcItem.top + 7;
-		OffsetRect(&urc->rcItem, 0, y - oldTop);
-		return RD_ANCHORX_LEFT | RD_ANCHORY_CUSTOM;
-
-	case IDC_NAMEGROUP:
-		oldTop = urc->rcItem.top;
-		y = nextY;
-		if (dat->showName) nextY = y + urc->rcItem.bottom - urc->rcItem.top + 7;
-		OffsetRect(&urc->rcItem, 0, y - oldTop);
-		return RD_ANCHORX_LEFT | RD_ANCHORY_CUSTOM;
-
-	case IDC_ADVANCEDGROUP:
-		oldTop = urc->rcItem.top;
-		y = nextY;
-		if (dat->showAdvanced) nextY = y + urc->rcItem.bottom - urc->rcItem.top + 7;
-		OffsetRect(&urc->rcItem, 0, y - oldTop);
-		return RD_ANCHORX_LEFT | RD_ANCHORY_CUSTOM;
-
-	case IDC_TINYEXTENDEDGROUP:
-		oldTop = urc->rcItem.top;
-		y = nextY;
-		if (dat->showTiny) {
-			int height = urc->dlgNewSize.cy - y - (urc->dlgOriginalSize.cy - urc->rcItem.bottom);
-			nextY = y + 200;  //min height for custom dialog
-			urc->rcItem.top = urc->rcItem.bottom - height;
-		}
-		return RD_ANCHORX_LEFT | RD_ANCHORY_BOTTOM;
-
-	case IDC_BYEMAIL:
-	case IDC_EMAIL:
-	case IDC_BYNAME:
-	case IDC_STNAMENICK:
-	case IDC_STNAMEFIRST:
-	case IDC_STNAMELAST:
-	case IDC_NAMENICK:
-	case IDC_NAMEFIRST:
-	case IDC_NAMELAST:
-	case IDC_BYADVANCED:
-	case IDC_BYCUSTOM:
-	case IDC_ADVANCED:
-		OffsetRect(&urc->rcItem, 0, y - oldTop);
-		return RD_ANCHORX_LEFT | RD_ANCHORY_CUSTOM;
-
-	case IDC_HEADERBAR:
-		return RD_ANCHORX_LEFT | RD_ANCHORY_TOP | RD_ANCHORX_WIDTH;
-	}
-	return RD_ANCHORX_LEFT | RD_ANCHORY_TOP;
-}
-
-static void RenderThrobber(HDC hdc, RECT *rcItem, int *throbbing, int *pivot)
-{
-	InflateRect(rcItem, -1, 0);
-	int width = rcItem->right - rcItem->left;
-	int height = rcItem->bottom - rcItem->top;
-	int height2 = height / 2;
-
-	if (*throbbing) {
-		/* create memdc */
-		HDC hMemDC = CreateCompatibleDC(0);
-		HBITMAP hBitmap = (HBITMAP)SelectObject(hMemDC, CreateCompatibleBitmap(hdc, width, height));
-		/* flush it */
-		RECT rc;
-		rc.left = rc.top = 0;
-		rc.right = width;
-		rc.bottom = height;
-		HBRUSH hBr = GetSysColorBrush(COLOR_BTNFACE);
-		FillRect(hMemDC, &rc, hBr);
-		DeleteObject(hBr);
-		/* set up the pen */
-		HPEN hPen = (HPEN)SelectObject(hMemDC, CreatePen(PS_SOLID, 4, GetSysColor(COLOR_BTNSHADOW)));
-		/* draw everything before the pivot */
-		int x = *pivot;
-		while (x > (-height)) {
-			MoveToEx(hMemDC, x + height2, 0, NULL);
-			LineTo(hMemDC, x - height2, height);
-			x -= 12;
-		}
-
-		/* draw everything after the pivot */
-		x = *pivot;
-		while (x < width + height) {
-			MoveToEx(hMemDC, x + height2, 0, NULL);
-			LineTo(hMemDC, x - height2, height);
-			x += 12;
-		}
-
-		/* move the pivot */
-		*pivot += 2;
-		/* reset the pivot point if it gets past the rect */
-		if (*pivot > width) *pivot = 0;
-		/* put back the old pen and delete the new one */
-		DeleteObject(SelectObject(hMemDC, hPen));
-		/* cap the top and bottom */
-		hPen = (HPEN)SelectObject(hMemDC, CreatePen(PS_SOLID, 1, GetSysColor(COLOR_BTNFACE)));
-		MoveToEx(hMemDC, 0, 0, NULL);
-		LineTo(hMemDC, width, 0);
-		MoveToEx(hMemDC, 0, height - 1, NULL);
-		LineTo(hMemDC, width, height - 1);
-		/* select in the old pen and delete the new pen */
-		DeleteObject(SelectObject(hMemDC, hPen));
-		/* paint to screen */
-		BitBlt(hdc, rcItem->left, rcItem->top, width, height, hMemDC, 0, 0, SRCCOPY);
-		/* select back in the old bitmap and delete the created one, as well as freeing the mem dc. */
-		hBitmap = (HBITMAP)SelectObject(hMemDC, hBitmap);
-		DeleteObject(hBitmap);
-		DeleteDC(hMemDC);
-	}
-	else {
-		/* just flush the DC */
-		HBRUSH hBr = GetSysColorBrush(COLOR_BTNFACE);
-		FillRect(hdc, rcItem, hBr);
-		DeleteObject(hBr);
-	}
-}
-
-static void StartThrobber(HWND hwndDlg, FindAddDlgData *dat)
-{
-	dat->throbbing = 1;
-	SetTimer(hwndDlg, TIMERID_THROBBER, 25, NULL);
-}
-
-static void StopThrobber(HWND hwndDlg, FindAddDlgData *dat)
-{
-	KillTimer(hwndDlg, TIMERID_THROBBER);
-	dat->throbbing = 0;
-	dat->pivot = 0;
-	InvalidateRect(GetDlgItem(hwndDlg, IDC_STATUSBAR), NULL, FALSE);
-}
-
-static LRESULT CALLBACK AdvancedSearchDlgSubclassProc(HWND hwndDlg, UINT msg, WPARAM wParam, LPARAM lParam)
-{
-	if (msg == WM_COMMAND) {
-		HWND parentHwnd = GetParent(hwndDlg);
-		switch (LOWORD(wParam)) {
-		case IDOK:
-			SendMessage(parentHwnd, WM_COMMAND, MAKEWPARAM(IDOK, BN_CLICKED), (LPARAM)GetDlgItem(parentHwnd, IDOK));
-			SetFocus(GetDlgItem(parentHwnd, IDC_ADVANCED));
-			break;
-
-		case IDCANCEL:
-			CheckDlgButton(parentHwnd, IDC_ADVANCED, BST_UNCHECKED);
-			SendMessage(parentHwnd, WM_COMMAND, MAKEWPARAM(IDC_ADVANCED, BN_CLICKED), (LPARAM)GetDlgItem(parentHwnd, IDC_ADVANCED));
-			SetFocus(GetDlgItem(parentHwnd, IDC_ADVANCED));
-			break;
-		}
-	}
-	return mir_callNextSubclass(hwndDlg, AdvancedSearchDlgSubclassProc, msg, wParam, lParam);
-}
-
-static void ShowAdvancedSearchDlg(HWND hwndDlg, FindAddDlgData *dat)
-{
-	char *szProto = (char*)SendDlgItemMessage(hwndDlg, IDC_PROTOLIST, CB_GETITEMDATA, SendDlgItemMessage(hwndDlg, IDC_PROTOLIST, CB_GETCURSEL, 0, 0), 0);
-	if (szProto == NULL)
-		return;
-
-	if (dat->hwndAdvSearch == NULL) {
-		RECT rc;
-		dat->hwndAdvSearch = (HWND)CallProtoServiceInt(NULL, szProto, PS_CREATEADVSEARCHUI, 0, (LPARAM)hwndDlg);
-		if (dat->hwndAdvSearch != NULL)
-			mir_subclassWindow(dat->hwndAdvSearch, AdvancedSearchDlgSubclassProc);
-		GetWindowRect(GetDlgItem(hwndDlg, IDC_RESULTS), &rc);
-		SetWindowPos(dat->hwndAdvSearch, 0, rc.left, rc.top, 0, 0, SWP_NOZORDER | SWP_NOSIZE);
-	}
-
-	AnimateWindow(dat->hwndAdvSearch, 150, AW_ACTIVATE | AW_SLIDE | AW_HOR_POSITIVE);
-	RedrawWindow(dat->hwndAdvSearch, NULL, NULL, RDW_INVALIDATE | RDW_UPDATENOW | RDW_ALLCHILDREN);
-
-	CheckDlgButton(hwndDlg, IDC_ADVANCED, BST_CHECKED);
-}
-
-static void ReposTinySearchDlg(HWND hwndDlg, FindAddDlgData *dat)
-{
-	if (dat->hwndTinySearch == NULL)
-		return;
-
-	RECT rc;
-	RECT clientRect;
-	POINT pt = { 0, 0 };
-	GetWindowRect(GetDlgItem(hwndDlg, IDC_TINYEXTENDEDGROUP), &rc);
-	GetWindowRect(dat->hwndTinySearch, &clientRect);
-	pt.x = rc.left;
-	pt.y = rc.top;
-	ScreenToClient(hwndDlg, &pt);
-	SetWindowPos(dat->hwndTinySearch, 0, pt.x + 5, pt.y + 15, rc.right - rc.left - 10, rc.bottom - rc.top - 30, SWP_NOZORDER);
-}
-
-static void ShowTinySearchDlg(HWND hwndDlg, FindAddDlgData *dat)
-{
-	char *szProto = (char*)SendDlgItemMessage(hwndDlg, IDC_PROTOLIST, CB_GETITEMDATA, SendDlgItemMessage(hwndDlg, IDC_PROTOLIST, CB_GETCURSEL, 0, 0), 0);
-	if (szProto == NULL)
-		return;
-
-	if (dat->hwndTinySearch == NULL) {
-		dat->hwndTinySearch = (HWND)CallProtoServiceInt(NULL, szProto, PS_CREATEADVSEARCHUI, 0, (LPARAM)/*GetDlgItem(*/hwndDlg/*, IDC_TINYEXTENDEDGROUP)*/);
-		if (dat->hwndTinySearch)
-			ReposTinySearchDlg(hwndDlg, dat);
-		else
-			dat->showTiny = false;
-	}
-	ShowWindow(dat->hwndTinySearch, SW_SHOW);
-}
-
-static void HideAdvancedSearchDlg(HWND hwndDlg, FindAddDlgData *dat)
-{
-	if (dat->hwndAdvSearch == NULL)
-		return;
-
-	AnimateWindow(dat->hwndAdvSearch, 150, AW_HIDE | AW_BLEND);
-	CheckDlgButton(hwndDlg, IDC_ADVANCED, BST_UNCHECKED);
-}
-
-void EnableResultButtons(HWND hwndDlg, int enable)
-{
-	EnableWindow(GetDlgItem(hwndDlg, IDC_ADD), enable);
-	EnableWindow(GetDlgItem(hwndDlg, IDC_MOREOPTIONS), enable);
-}
-
-static const int controls[] = { IDC_BYPROTOID, IDC_BYEMAIL, IDC_BYNAME, IDC_BYADVANCED, IDC_BYCUSTOM };
-
-static void CheckSearchTypeRadioButton(HWND hwndDlg, int idControl)
-{
-	for (int i = 0; i < SIZEOF(controls); i++)
-		CheckDlgButton(hwndDlg, controls[i], idControl == controls[i] ? BST_CHECKED : BST_UNCHECKED);
-}
-
-#define sttErrMsg TranslateT("You haven't filled in the search field. Please enter a search term and try again.")
-#define sttErrTitle TranslateT("Search")
-
-static void SetListItemText(HWND hwndList, int idx, int col, TCHAR* szText)
-{
-	if (szText && szText[0]) {
-		ListView_SetItemText(hwndList, idx, col, szText);
-	}
-	else {
-		ListView_SetItemText(hwndList, idx, col, TranslateT("<not specified>"));
-	}
-}
-
-static INT_PTR CALLBACK DlgProcFindAdd(HWND hwndDlg, UINT msg, WPARAM wParam, LPARAM lParam)
-{
-	FindAddDlgData* dat = (FindAddDlgData*)GetWindowLongPtr(hwndDlg, GWLP_USERDATA);
-	HWND hwndList = GetDlgItem(hwndDlg, IDC_RESULTS);
-
-	switch (msg) {
-	case WM_INITDIALOG:
-		TranslateDialogDefault(hwndDlg);
-		Window_SetIcon_IcoLib(hwndDlg, SKINICON_OTHER_FINDUSER);
-		dat = (FindAddDlgData*)mir_calloc(sizeof(FindAddDlgData));
-		SetWindowLongPtr(hwndDlg, GWLP_USERDATA, (LONG_PTR)dat);
-		dat->notSearchedYet = 1;
-		dat->iLastColumnSortIndex = 1;
-		dat->bSortAscending = 1;
-		SendDlgItemMessage(hwndDlg, IDC_MOREOPTIONS, BUTTONSETARROW, 1, 0);
-		SendDlgItemMessage(hwndDlg, IDOK, BUTTONADDTOOLTIP, (WPARAM)LPGENT("Ctrl+Search add contact"), BATF_TCHAR);
-
-		ListView_SetExtendedListViewStyle(hwndList, LVS_EX_FULLROWSELECT | LVS_EX_HEADERDRAGDROP);
-		{
-			RECT rc;
-			GetClientRect(hwndList, &rc);
-
-			LVCOLUMN lvc;
-			lvc.mask = LVCF_TEXT | LVCF_WIDTH;
-			lvc.pszText = TranslateT("Results");
-			lvc.cx = rc.right - 1;
-			ListView_InsertColumn(hwndList, 0, &lvc);
-
-			LVITEM lvi;
-			lvi.mask = LVIF_TEXT;
-			lvi.iItem = 0;
-			lvi.iSubItem = 0;
-			lvi.pszText = TranslateT("There are no results to display.");
-			ListView_InsertItem(hwndList, &lvi);
-
-			// Allocate a reasonable amount of space in the status bar
-			HDC hdc = GetDC(GetDlgItem(hwndDlg, IDC_STATUSBAR));
-			SelectObject(hdc, (HFONT)SendDlgItemMessage(hwndDlg, IDC_STATUSBAR, WM_GETFONT, 0, 0));
-
-			SIZE textSize;
-			GetTextExtentPoint32(hdc, TranslateT("Searching"), lstrlen(TranslateT("Searching")), &textSize);
-
-			int partWidth[3];
-			partWidth[0] = textSize.cx;
-			GetTextExtentPoint32(hdc, _T("01234567890123456789"), 20, &textSize);
-			partWidth[0] += textSize.cx;
-			ReleaseDC(GetDlgItem(hwndDlg, IDC_STATUSBAR), hdc);
-			partWidth[1] = partWidth[0] + 150;
-			partWidth[2] = -1;
-			SendDlgItemMessage(hwndDlg, IDC_STATUSBAR, SB_SETPARTS, SIZEOF(partWidth), (LPARAM)partWidth);
-			SendDlgItemMessage(hwndDlg, IDC_STATUSBAR, SB_SETTEXT, 1 | SBT_OWNERDRAW, 0);
-			SetStatusBarSearchInfo(GetDlgItem(hwndDlg, IDC_STATUSBAR), dat);
-
-			TCHAR *szProto = NULL;
-			DBVARIANT dbv;
-			if (!db_get_ts(NULL, "FindAdd", "LastSearched", &dbv)) {
-				szProto = NEWTSTR_ALLOCA(dbv.ptszVal);
-				db_free(&dbv); /* free string szProto was fetched with */
-			}
-
-			int i, index = 0, cbwidth = 0, netProtoCount = 0;
-			for (i = 0; i < accounts.getCount(); i++) {
-				if (!Proto_IsAccountEnabled(accounts[i]))
-					continue;
-
-				DWORD caps = (DWORD)CallProtoServiceInt(NULL, accounts[i]->szModuleName, PS_GETCAPS, PFLAGNUM_1, 0);
-				if (caps & PF1_ANYSEARCH)
-					netProtoCount++;
-			}
-			dat->himlComboIcons = ImageList_Create(GetSystemMetrics(SM_CXSMICON), GetSystemMetrics(SM_CYSMICON), ILC_COLOR32 | ILC_MASK, netProtoCount + 1, netProtoCount + 1);
-			SendDlgItemMessage(hwndDlg, IDC_PROTOLIST, CBEM_SETIMAGELIST, 0, (LPARAM)dat->himlComboIcons);
-
-			COMBOBOXEXITEM cbei;
-			cbei.mask = CBEIF_IMAGE | CBEIF_SELECTEDIMAGE | CBEIF_TEXT | CBEIF_LPARAM;
-			cbei.iItem = 0;
-			hdc = GetDC(hwndDlg);
-			SelectObject(hdc, (HFONT)SendDlgItemMessage(hwndDlg, IDC_PROTOLIST, WM_GETFONT, 0, 0));
-			if (netProtoCount > 1) {
-				cbei.pszText = TranslateT("All networks");
-				GetTextExtentPoint32(hdc, cbei.pszText, lstrlen(cbei.pszText), &textSize);
-				if (textSize.cx > cbwidth)
-					cbwidth = textSize.cx;
-				cbei.iImage = cbei.iSelectedImage = ImageList_AddIcon_IconLibLoaded(dat->himlComboIcons, SKINICON_OTHER_SEARCHALL);
-				cbei.lParam = 0;
-				SendDlgItemMessage(hwndDlg, IDC_PROTOLIST, CBEM_INSERTITEM, 0, (LPARAM)&cbei);
-				cbei.iItem++;
-			}
-
-			for (i = 0; i < accounts.getCount(); i++) {
-				PROTOACCOUNT *pa = accounts[i];
-				if (!Proto_IsAccountEnabled(pa))
-					continue;
-
-				DWORD caps = (DWORD)CallProtoServiceInt(NULL, pa->szModuleName, PS_GETCAPS, PFLAGNUM_1, 0);
-				if (!(caps & PF1_ANYSEARCH))
-					continue;
-
-				cbei.pszText = pa->tszAccountName;
-				GetTextExtentPoint32(hdc, cbei.pszText, lstrlen(cbei.pszText), &textSize);
-				if (textSize.cx > cbwidth)
-					cbwidth = textSize.cx;
-
-				HICON hIcon = (HICON)CallProtoServiceInt(NULL, pa->szModuleName, PS_LOADICON, PLI_PROTOCOL | PLIF_SMALL, 0);
-				cbei.iImage = cbei.iSelectedImage = ImageList_AddIcon(dat->himlComboIcons, hIcon);
-				DestroyIcon(hIcon);
-				cbei.lParam = (LPARAM)pa->szModuleName;
-				SendDlgItemMessageA(hwndDlg, IDC_PROTOLIST, CBEM_INSERTITEM, 0, (LPARAM)&cbei);
-				if (szProto && cbei.pszText && !lstrcmp(szProto, pa->tszAccountName))
-					index = cbei.iItem;
-				cbei.iItem++;
-			}
-			cbwidth += 32;
-
-			RECT rect;
-			SendDlgItemMessage(hwndDlg, IDC_PROTOLIST, CB_GETDROPPEDCONTROLRECT, 0, (LPARAM)&rect);
-			if ((rect.right - rect.left) < cbwidth)
-				SendDlgItemMessage(hwndDlg, IDC_PROTOLIST, CB_SETDROPPEDWIDTH, cbwidth, 0);
-			SendDlgItemMessage(hwndDlg, IDC_PROTOLIST, CB_SETCURSEL, index, 0);
-
-			SendMessage(hwndDlg, M_SETGROUPVISIBILITIES, 0, 0);
-			Utils_RestoreWindowPosition(hwndDlg, NULL, "FindAdd", "");
-		}
-		return TRUE;
-
-	case WM_SIZE:
-		{
-			UTILRESIZEDIALOG urd = { 0 };
-			urd.cbSize = sizeof(urd);
-			urd.hwndDlg = hwndDlg;
-			urd.hInstance = hInst;
-			urd.lpTemplate = MAKEINTRESOURCEA(IDD_FINDADD);
-			urd.lParam = (LPARAM)dat;
-			urd.pfnResizer = FindAddDlgResizer;
-			CallService(MS_UTILS_RESIZEDIALOG, 0, (LPARAM)&urd);
-			ReposTinySearchDlg(hwndDlg, dat);
-			SendDlgItemMessage(hwndDlg, IDC_STATUSBAR, WM_SIZE, 0, 0);
-			if (dat->notSearchedYet) {
-				RECT rc;
-				GetClientRect(hwndList, &rc);
-				ListView_SetColumnWidth(hwndList, 0, rc.right);
-			}
-		}
-		//fall through
-	case WM_MOVE:
-		if (dat && dat->hwndAdvSearch) {
-			RECT rc;
-			GetWindowRect(hwndList, &rc);
-			SetWindowPos(dat->hwndAdvSearch, 0, rc.left, rc.top, 0, 0, SWP_NOZORDER | SWP_NOSIZE);
-		}
-		break;
-
-	case WM_GETMINMAXINFO:
-		RECT rc, rc2;
-		GetWindowRect(hwndList, &rc);
-		GetWindowRect(hwndDlg, &rc2);
-		{
-			MINMAXINFO *mmi = (MINMAXINFO*)lParam;
-			mmi->ptMinTrackSize.x = rc.left - rc2.left + 10 + GetSystemMetrics(SM_CXFRAME);
-			GetClientRect(GetDlgItem(hwndDlg, IDC_MOREOPTIONS), &rc);
-			mmi->ptMinTrackSize.x += rc.right + 5;
-			GetClientRect(GetDlgItem(hwndDlg, IDC_ADD), &rc);
-			mmi->ptMinTrackSize.x += rc.right + 5;
-			GetClientRect(GetDlgItem(hwndDlg, IDC_STATUSBAR), &rc);
-			mmi->ptMinTrackSize.y = dat->minDlgHeight + 20 + GetSystemMetrics(SM_CYCAPTION) + 2 * GetSystemMetrics(SM_CYFRAME);
-			GetClientRect(GetDlgItem(hwndDlg, IDC_STATUSBAR), &rc);
-			mmi->ptMinTrackSize.y += rc.bottom;
-		}
-		return 0;
-
-	case M_SETGROUPVISIBILITIES:
-		dat->showAdvanced = dat->showEmail = dat->showName = dat->showProtoId = dat->showTiny = 0;
-		{
-			char *szProto = (char*)SendDlgItemMessage(hwndDlg, IDC_PROTOLIST, CB_GETITEMDATA, SendDlgItemMessage(hwndDlg, IDC_PROTOLIST, CB_GETCURSEL, 0, 0), 0);
-			if (szProto == (char *)CB_ERR)
-				break;
-			if (szProto == NULL) {
-				for (int i = 0; i < accounts.getCount(); i++) {
-					PROTOACCOUNT *pa = accounts[i];
-					if (Proto_IsAccountEnabled(pa)) {
-						DWORD protoCaps = (DWORD)CallProtoServiceInt(NULL, pa->szModuleName, PS_GETCAPS, PFLAGNUM_1, 0);
-						if (protoCaps & PF1_SEARCHBYEMAIL) dat->showEmail = 1;
-						if (protoCaps & PF1_SEARCHBYNAME) dat->showName = 1;
-					}
-				}
-			}
-			else {
-				DWORD protoCaps = (DWORD)CallProtoServiceInt(NULL, szProto, PS_GETCAPS, PFLAGNUM_1, 0);
-				if (protoCaps & PF1_BASICSEARCH) dat->showProtoId = 1;
-				if (protoCaps & PF1_SEARCHBYEMAIL) dat->showEmail = 1;
-				if (protoCaps & PF1_SEARCHBYNAME) dat->showName = 1;
-
-				if (protoCaps & PF1_EXTSEARCHUI) dat->showAdvanced = 1;
-				else if (protoCaps & PF1_EXTSEARCH) dat->showTiny = 1;
-
-				if (protoCaps & PF1_USERIDISEMAIL && dat->showProtoId) { dat->showProtoId = 0; dat->showEmail = 1; }
-				if (dat->showProtoId) {
-					char *szUniqueId = (char*)CallProtoServiceInt(NULL, szProto, PS_GETCAPS, PFLAG_UNIQUEIDTEXT, 0);
-					if (szUniqueId)
-						SetDlgItemTextA(hwndDlg, IDC_BYPROTOID, szUniqueId);
-					else
-						SetDlgItemText(hwndDlg, IDC_BYPROTOID, TranslateT("Handle"));
-
-					if (protoCaps & PF1_NUMERICUSERID)
-						SetWindowLongPtr(GetDlgItem(hwndDlg, IDC_PROTOID), GWL_STYLE, GetWindowLongPtr(GetDlgItem(hwndDlg, IDC_PROTOID), GWL_STYLE) | ES_NUMBER);
-					else
-						SetWindowLongPtr(GetDlgItem(hwndDlg, IDC_PROTOID), GWL_STYLE, GetWindowLongPtr(GetDlgItem(hwndDlg, IDC_PROTOID), GWL_STYLE)&~ES_NUMBER);
-				}
-			}
-
-			if (dat->showTiny)
-				ShowTinySearchDlg(hwndDlg, dat);
-			else if (dat->hwndTinySearch) {
-				DestroyWindow(dat->hwndTinySearch);
-				dat->hwndTinySearch = NULL;
-			}
-
-#define en(id, t) ShowWindow( GetDlgItem(hwndDlg, IDC_##id), dat->show##t?SW_SHOW:SW_HIDE)
-			en(PROTOIDGROUP, ProtoId); en(BYPROTOID, ProtoId); en(PROTOID, ProtoId);
-			en(EMAILGROUP, Email); en(BYEMAIL, Email); en(EMAIL, Email);
-			en(NAMEGROUP, Name);  en(BYNAME, Name);
-			en(STNAMENICK, Name); en(NAMENICK, Name);
-			en(STNAMEFIRST, Name); en(NAMEFIRST, Name);
-			en(STNAMELAST, Name); en(NAMELAST, Name);
-			en(ADVANCEDGROUP, Advanced); en(BYADVANCED, Advanced); en(ADVANCED, Advanced);
-			en(BYCUSTOM, Tiny); en(TINYEXTENDEDGROUP, Tiny);
-#undef en
-			int checkmarkVisible = (dat->showAdvanced && IsDlgButtonChecked(hwndDlg, IDC_BYADVANCED)) ||
-				(dat->showEmail && IsDlgButtonChecked(hwndDlg, IDC_BYEMAIL)) ||
-				(dat->showTiny && IsDlgButtonChecked(hwndDlg, IDC_BYCUSTOM)) ||
-				(dat->showName && IsDlgButtonChecked(hwndDlg, IDC_BYNAME)) ||
-				(dat->showProtoId && IsDlgButtonChecked(hwndDlg, IDC_BYPROTOID));
-			if (!checkmarkVisible) {
-				if (dat->showProtoId) CheckSearchTypeRadioButton(hwndDlg, IDC_BYPROTOID);
-				else if (dat->showEmail) CheckSearchTypeRadioButton(hwndDlg, IDC_BYEMAIL);
-				else if (dat->showName) CheckSearchTypeRadioButton(hwndDlg, IDC_BYNAME);
-				else if (dat->showAdvanced) CheckSearchTypeRadioButton(hwndDlg, IDC_BYADVANCED);
-				else if (dat->showTiny) CheckSearchTypeRadioButton(hwndDlg, IDC_BYCUSTOM);
-			}
-
-			SendMessage(hwndDlg, WM_SIZE, 0, 0);
-
-			MINMAXINFO mmi;
-			SendMessage(hwndDlg, WM_GETMINMAXINFO, 0, (LPARAM)&mmi);
-
-			RECT rc;
-			GetWindowRect(hwndDlg, &rc);
-			if (rc.bottom - rc.top < mmi.ptMinTrackSize.y)
-				SetWindowPos(hwndDlg, 0, 0, 0, rc.right - rc.left, mmi.ptMinTrackSize.y, SWP_NOZORDER | SWP_NOMOVE);
-		}
-		break;
-
-	case WM_TIMER:
-		if (wParam == TIMERID_THROBBER) {
-			int borders[3];
-			SendDlgItemMessage(hwndDlg, IDC_STATUSBAR, SB_GETBORDERS, 0, (LPARAM)borders);
-
-			RECT rc;
-			SendDlgItemMessage(hwndDlg, IDC_STATUSBAR, SB_GETRECT, 1, (LPARAM)&rc);
-			InflateRect(&rc, -borders[2] / 2, -borders[1] / 2);
-			HDC hdc = GetDC(GetDlgItem(hwndDlg, IDC_STATUSBAR));
-			RenderThrobber(hdc, &rc, &dat->throbbing, &dat->pivot);
-			ReleaseDC(GetDlgItem(hwndDlg, IDC_STATUSBAR), hdc);
-		}
-		break;
-
-	case WM_DRAWITEM:
-		{
-			DRAWITEMSTRUCT *dis = (DRAWITEMSTRUCT*)lParam;
-			if (dis->CtlID == IDC_STATUSBAR && dis->itemID == 1) {
-				RenderThrobber(dis->hDC, &dis->rcItem, &dat->throbbing, &dat->pivot);
-				return TRUE;
-			}
-		}
-		break;
-
-	case WM_NOTIFY:
-		if (wParam == IDC_RESULTS) {
-			switch (((LPNMHDR)lParam)->code) {
-			case LVN_ITEMCHANGED:
-				{
-					int count = ListView_GetSelectedCount(hwndList);
-					if (dat->notSearchedYet)
-						count = 0;
-					EnableResultButtons(hwndDlg, count);
-				}
-				break;
-
-			case LVN_COLUMNCLICK:
-				HDITEM hdi;
-				hdi.mask = HDI_FORMAT;
-				hdi.fmt = HDF_LEFT | HDF_STRING;
-				Header_SetItem(ListView_GetHeader(hwndList), dat->iLastColumnSortIndex, &hdi);
-
-				LPNMLISTVIEW nmlv = (LPNMLISTVIEW)lParam;
-				if (nmlv->iSubItem != dat->iLastColumnSortIndex) {
-					dat->bSortAscending = TRUE;
-					dat->iLastColumnSortIndex = nmlv->iSubItem;
-				}
-				else dat->bSortAscending = !dat->bSortAscending;
-
-				hdi.fmt = HDF_LEFT | HDF_STRING | (dat->bSortAscending ? HDF_SORTDOWN : HDF_SORTUP);
-				Header_SetItem(ListView_GetHeader(hwndList), dat->iLastColumnSortIndex, &hdi);
-
-				ListView_SortItemsEx(hwndList, SearchResultsCompareFunc, (LPARAM)hwndDlg);
-			}
-		}
-		break;
-
-	case WM_COMMAND:
-		switch(LOWORD(wParam)) {
-		case IDC_PROTOLIST:
-			if (HIWORD(wParam) == CBN_SELCHANGE) {
-				HideAdvancedSearchDlg(hwndDlg, dat);
-				if (dat->hwndAdvSearch) {
-					DestroyWindow(dat->hwndAdvSearch);
-					dat->hwndAdvSearch = NULL;
-				}
-				if (dat->hwndTinySearch) {
-					DestroyWindow(dat->hwndTinySearch);
-					dat->hwndTinySearch = NULL;
-				}
-				SendMessage(hwndDlg, M_SETGROUPVISIBILITIES, 0, 0);
-			}
-			break;
-
-		case IDC_BYPROTOID:
-		case IDC_BYEMAIL:
-		case IDC_BYNAME:
-			{
-				int count = ListView_GetSelectedCount(hwndList);
-				if (dat->notSearchedYet)
-					count = 0;
-				EnableWindow(GetDlgItem(hwndDlg, IDC_ADD), count);
-				HideAdvancedSearchDlg(hwndDlg, dat);
-			}
-			break;
-
-		case IDC_PROTOID:
-			if (HIWORD(wParam) == EN_CHANGE) {
-				HideAdvancedSearchDlg(hwndDlg, dat);
-				CheckSearchTypeRadioButton(hwndDlg, IDC_BYPROTOID);
-			}
-			break;
-
-		case IDC_EMAIL:
-			if (HIWORD(wParam) == EN_CHANGE) {
-				HideAdvancedSearchDlg(hwndDlg, dat);
-				CheckSearchTypeRadioButton(hwndDlg, IDC_BYEMAIL);
-			}
-			break;
-
-		case IDC_NAMENICK:
-		case IDC_NAMEFIRST:
-		case IDC_NAMELAST:
-			if (HIWORD(wParam) == EN_CHANGE) {
-				HideAdvancedSearchDlg(hwndDlg, dat);
-				CheckSearchTypeRadioButton(hwndDlg, IDC_BYNAME);
-			}
-			break;
-
-		case IDC_ADVANCED:
-			EnableWindow(GetDlgItem(hwndDlg, IDC_ADD), ListView_GetSelectedCount(hwndList) > 0);
-			if (IsDlgButtonChecked(hwndDlg, IDC_ADVANCED))
-				ShowAdvancedSearchDlg(hwndDlg, dat);
-			else
-				HideAdvancedSearchDlg(hwndDlg, dat);
-			CheckSearchTypeRadioButton(hwndDlg, IDC_BYADVANCED);
-			break;
-
-		case IDCANCEL:
-			DestroyWindow(hwndDlg);
-			break;
-
-		case IDOK:
-			HideAdvancedSearchDlg(hwndDlg, dat);
-			if (dat->searchCount) {	 //cancel search
-				SetDlgItemText(hwndDlg, IDOK, TranslateT("&Search"));
-				if (dat->hResultHook) { UnhookEvent(dat->hResultHook); dat->hResultHook = NULL; }
-				if (dat->search) { mir_free(dat->search); dat->search = NULL; }
-				dat->searchCount = 0;
-				StopThrobber(hwndDlg, dat);
-				SetStatusBarSearchInfo(GetDlgItem(hwndDlg, IDC_STATUSBAR), dat);
-			}
-			else {
-				char *szProto = (char*)SendDlgItemMessage(hwndDlg, IDC_PROTOLIST, CB_GETITEMDATA, SendDlgItemMessage(hwndDlg, IDC_PROTOLIST, CB_GETCURSEL, 0, 0), 0);
-				if (dat->search)
-					mir_free(dat->search), dat->search = NULL;
-				dat->searchCount = 0;
-				dat->hResultHook = HookEventMessage(ME_PROTO_ACK, hwndDlg, HM_SEARCHACK);
-				if (IsDlgButtonChecked(hwndDlg, IDC_BYCUSTOM))
-					BeginSearch(hwndDlg, dat, szProto, PS_SEARCHBYADVANCED, PF1_EXTSEARCHUI, dat->hwndTinySearch);
-				else if (IsDlgButtonChecked(hwndDlg, IDC_BYPROTOID)) {
-					TCHAR str[256];
-					GetDlgItemText(hwndDlg, IDC_PROTOID, str, SIZEOF(str));
-					rtrimt(str);
-					if (str[0] == 0)
-						MessageBox(hwndDlg, sttErrMsg, sttErrTitle, MB_ICONERROR | MB_OK);
-					else
-						BeginSearch(hwndDlg, dat, szProto, PS_BASICSEARCHT, PF1_BASICSEARCH, str);
-				}
-				else if (IsDlgButtonChecked(hwndDlg, IDC_BYEMAIL)) {
-					TCHAR str[256];
-					GetDlgItemText(hwndDlg, IDC_EMAIL, str, SIZEOF(str));
-					rtrimt(str);
-					if (str[0] == 0)
-						MessageBox(hwndDlg, sttErrMsg, sttErrTitle, MB_ICONERROR | MB_OK);
-					else
-						BeginSearch(hwndDlg, dat, szProto, PS_SEARCHBYEMAILT, PF1_SEARCHBYEMAIL, str);
-				}
-				else if (IsDlgButtonChecked(hwndDlg, IDC_BYNAME)) {
-					TCHAR nick[256], first[256], last[256];
-					PROTOSEARCHBYNAME psbn;
-					GetDlgItemText(hwndDlg, IDC_NAMENICK, nick, SIZEOF(nick));
-					GetDlgItemText(hwndDlg, IDC_NAMEFIRST, first, SIZEOF(first));
-					GetDlgItemText(hwndDlg, IDC_NAMELAST, last, SIZEOF(last));
-					psbn.pszFirstName = first;
-					psbn.pszLastName = last;
-					psbn.pszNick = nick;
-					if (nick[0] == 0 && first[0] == 0 && last[0] == 0)
-						MessageBox(hwndDlg, sttErrMsg, sttErrTitle, MB_ICONERROR | MB_OK);
-					else
-						BeginSearch(hwndDlg, dat, szProto, PS_SEARCHBYNAMET, PF1_SEARCHBYNAME, &psbn);
-				}
-				else if (IsDlgButtonChecked(hwndDlg, IDC_BYADVANCED)) {
-					if (dat->hwndAdvSearch == NULL)
-						MessageBox(hwndDlg, sttErrMsg, sttErrTitle, MB_ICONERROR | MB_OK);
-					else
-						BeginSearch(hwndDlg, dat, szProto, PS_SEARCHBYADVANCED, PF1_EXTSEARCHUI, dat->hwndAdvSearch);
-				}
-
-				if (dat->searchCount == 0) {
-					if (dat->hResultHook) {
-						UnhookEvent(dat->hResultHook);
-						dat->hResultHook = NULL;
-					}
-					break;
-				}
-
-				dat->notSearchedYet = 0;
-				FreeSearchResults(hwndList);
-
-				CreateResultsColumns(hwndList, dat, szProto);
-				SetStatusBarSearchInfo(GetDlgItem(hwndDlg, IDC_STATUSBAR), dat);
-				SetStatusBarResultInfo(hwndDlg);
-				StartThrobber(hwndDlg, dat);
-				SetDlgItemText(hwndDlg, IDOK, TranslateT("Cancel"));
-			}
-			break;
-
-		case IDC_ADD:
-			{
-				ADDCONTACTSTRUCT acs = {0};
-
-				if (ListView_GetSelectedCount(hwndList) == 1) {
-					LVITEM lvi;
-					lvi.mask = LVIF_PARAM;
-					lvi.iItem = ListView_GetNextItem(hwndList, -1, LVNI_ALL | LVNI_SELECTED);
-					ListView_GetItem(hwndList, &lvi);
-					ListSearchResult *lsr = (ListSearchResult*)lvi.lParam;
-					acs.szProto = lsr->szProto;
-					acs.psr = &lsr->psr;
-				}
-				else {
-					TCHAR str[256];
-					GetDlgItemText(hwndDlg, IDC_PROTOID, str, SIZEOF(str));
-					if (*rtrimt(str) == 0)
-						break;
-
-					PROTOSEARCHRESULT psr = { 0 };
-					psr.cbSize = sizeof(psr);
-					psr.flags = PSR_TCHAR;
-					psr.id = str;
-
-					acs.psr = &psr;
-					acs.szProto = (char*)SendDlgItemMessage(hwndDlg, IDC_PROTOLIST, CB_GETITEMDATA,
-						SendDlgItemMessage(hwndDlg, IDC_PROTOLIST, CB_GETCURSEL, 0, 0), 0);
-				}
-
-				acs.handleType = HANDLE_SEARCHRESULT;
-				CallService(MS_ADDCONTACT_SHOW, (WPARAM)hwndDlg, (LPARAM)&acs);
-			}
-			break;
-
-		case IDC_MOREOPTIONS:
-			RECT rc;
-			GetWindowRect(GetDlgItem(hwndDlg, IDC_MOREOPTIONS), &rc);
-			ShowMoreOptionsMenu(hwndDlg, rc.left, rc.bottom);
-			break;
-		}
-
-		if (lParam && dat->hwndTinySearch == (HWND)lParam &&
-			HIWORD(wParam) == EN_SETFOCUS && LOWORD(wParam) == 0 &&
-			!IsDlgButtonChecked(hwndDlg, IDC_BYCUSTOM))
-		{
-			CheckSearchTypeRadioButton(hwndDlg, IDC_BYCUSTOM);
-		}
-		break;
-
-	case WM_CONTEXTMENU:
-		{
-			POINT pt = { LOWORD(lParam), HIWORD(lParam) };
-
-			LVHITTESTINFO lvhti;
-			lvhti.pt = pt;
-			ScreenToClient(hwndDlg, &pt);
-			switch (GetDlgCtrlID(ChildWindowFromPoint(hwndDlg, pt))) {
-			case IDC_RESULTS:
-				if (dat->notSearchedYet)
-					return TRUE;
-				ScreenToClient(hwndList, &lvhti.pt);
-				if (ListView_HitTest(hwndList, &lvhti) == -1)
-					break;
-				ShowMoreOptionsMenu(hwndDlg, (short)LOWORD(lParam), (short)HIWORD(lParam));
-				return TRUE;
-			}
-		}
-		break;
-
-	case HM_SEARCHACK:
-		{
-			ACKDATA *ack = (ACKDATA*)lParam;
-			if (ack->type != ACKTYPE_SEARCH)
-				break;
-
-			int i;
-			for (i = 0; i < dat->searchCount; i++)
-				if (dat->search[i].hProcess == ack->hProcess && dat->search[i].hProcess != NULL && !lstrcmpA(dat->search[i].szProto, ack->szModule)) break;
-			if (i == dat->searchCount)
-				break;
-
-			if (ack->result == ACKRESULT_SUCCESS || ack->result == ACKRESULT_FAILED) {
-				dat->searchCount--;
-				memmove(dat->search + i, dat->search + i + 1, sizeof(struct ProtoSearchInfo)*(dat->searchCount - i));
-				if (dat->searchCount == 0) {
-					mir_free(dat->search);
-					dat->search = NULL;
-					UnhookEvent(dat->hResultHook);
-					dat->hResultHook = NULL;
-					SetDlgItemText(hwndDlg, IDOK, TranslateT("&Search"));
-					StopThrobber(hwndDlg, dat);
-				}
-				ListView_SortItemsEx(hwndList, SearchResultsCompareFunc, (LPARAM)hwndDlg);
-				SetStatusBarSearchInfo(GetDlgItem(hwndDlg, IDC_STATUSBAR), dat);
-			}
-			else if (ack->result == ACKRESULT_SEARCHRESULT && ack->lParam) {
-				CUSTOMSEARCHRESULTS *csr = (CUSTOMSEARCHRESULTS*)ack->lParam;
-				dat->bFlexSearchResult = TRUE;
-				PROTOSEARCHRESULT *psr = &csr->psr;
-				// check if this is column names data (psr->cbSize == 0)
-				if (psr->cbSize == 0) { // blob contain info about columns
-					//firstly remove all exist items
-					FreeSearchResults(hwndList);
-					ListView_DeleteAllItems(hwndList); //not sure if previous delete list items too
-					//secondly remove all columns
-					while (ListView_DeleteColumn(hwndList, 1)); //will delete fist column till it possible
-					//now will add columns and captions;
-					LVCOLUMN lvc = { 0 };
-					lvc.mask = LVCF_TEXT;
-					for (int iColumn = 0; iColumn < csr->nFieldCount; iColumn++) {
-						lvc.pszText = TranslateTS(csr->pszFields[iColumn]);
-						ListView_InsertColumn(hwndList, iColumn + 1, &lvc);
-					}
-					// Column inserting Done
-				}
-				else {	//  blob contain info about found contacts
-					ListSearchResult *lsr = (ListSearchResult*)mir_alloc(offsetof(struct ListSearchResult, psr) + psr->cbSize);
-					lsr->szProto = ack->szModule;
-					memcpy(&lsr->psr, psr, psr->cbSize);
-
-					/* Next block is not needed but behavior will be kept */
-					bool isUnicode = (psr->flags & PSR_UNICODE) != 0;
-					if (psr->id) {
-						BOOL validPtr = isUnicode ? IsBadStringPtrW((wchar_t*)psr->id, 25) : IsBadStringPtrA((char*)psr->id, 25);
-						if (!validPtr) {
-							isUnicode = false;
-							lsr->psr.id = NULL;
-						}
-						else lsr->psr.id = isUnicode ? mir_u2t((wchar_t*)psr->id) : mir_a2t((char*)psr->id);
-					}
-
-					lsr->psr.nick = isUnicode ? mir_u2t((wchar_t*)psr->nick) : mir_a2t((char*)psr->nick);
-					lsr->psr.firstName = isUnicode ? mir_u2t((wchar_t*)psr->firstName) : mir_a2t((char*)psr->firstName);
-					lsr->psr.lastName = isUnicode ? mir_u2t((wchar_t*)psr->lastName) : mir_a2t((char*)psr->lastName);
-					lsr->psr.email = isUnicode ? mir_u2t((wchar_t*)psr->email) : mir_a2t((char*)psr->email);
-					lsr->psr.flags = psr->flags & ~PSR_UNICODE | PSR_TCHAR;
-
-					LVITEM lvi = { 0 };
-					lvi.mask = LVIF_PARAM | LVIF_IMAGE;
-					lvi.lParam = (LPARAM)lsr;
-					for (int i = SendDlgItemMessage(hwndDlg, IDC_PROTOLIST, CB_GETCOUNT, 0, 0); i--;) {
-						char *szComboProto = (char*)SendDlgItemMessage(hwndDlg, IDC_PROTOLIST, CB_GETITEMDATA, i, 0);
-						if (szComboProto == NULL) continue;
-						if (!lstrcmpA(szComboProto, ack->szModule)) {
-							COMBOBOXEXITEM cbei = { 0 };
-							cbei.mask = CBEIF_IMAGE;
-							cbei.iItem = i;
-							SendDlgItemMessage(hwndDlg, IDC_PROTOLIST, CBEM_GETITEM, 0, (LPARAM)&cbei);
-							lvi.iImage = cbei.iImage;
-						}
-					}
-					int iItem = ListView_InsertItem(hwndList, &lvi);
-					for (int col = 0; col < csr->nFieldCount; col++)
-						SetListItemText(hwndList, iItem, col + 1, csr->pszFields[col]);
-
-					ListView_SortItemsEx(hwndList, SearchResultsCompareFunc, (LPARAM)hwndDlg);
-					iItem = 0;
-					while (ListView_SetColumnWidth(hwndList, iItem++, LVSCW_AUTOSIZE_USEHEADER));
-					SetStatusBarResultInfo(hwndDlg);
-				}
-				break;
-			}
-			else if (ack->result == ACKRESULT_DATA) {
-				PROTOSEARCHRESULT *psr = (PROTOSEARCHRESULT*)ack->lParam;
-				ListSearchResult *lsr = (ListSearchResult*)mir_alloc(offsetof(struct ListSearchResult, psr) + psr->cbSize);
-				lsr->szProto = ack->szModule;
-
-				dat->bFlexSearchResult = FALSE;
-
-				CopyMemory(&lsr->psr, psr, psr->cbSize);
-				lsr->psr.nick = psr->flags & PSR_UNICODE ? mir_u2t((wchar_t*)psr->nick) : mir_a2t((char*)psr->nick);
-				lsr->psr.firstName = psr->flags & PSR_UNICODE ? mir_u2t((wchar_t*)psr->firstName) : mir_a2t((char*)psr->firstName);
-				lsr->psr.lastName = psr->flags & PSR_UNICODE ? mir_u2t((wchar_t*)psr->lastName) : mir_a2t((char*)psr->lastName);
-				lsr->psr.email = psr->flags & PSR_UNICODE ? mir_u2t((wchar_t*)psr->email) : mir_a2t((char*)psr->email);
-				lsr->psr.id = psr->flags & PSR_UNICODE ? mir_u2t((wchar_t*)psr->id) : mir_a2t((char*)psr->id);
-				lsr->psr.flags = psr->flags & ~PSR_UNICODE | PSR_TCHAR;
-
-				LVITEM lvi = { 0 };
-				lvi.mask = LVIF_PARAM | LVIF_IMAGE;
-				lvi.lParam = (LPARAM)lsr;
-				for (int i = SendDlgItemMessage(hwndDlg, IDC_PROTOLIST, CB_GETCOUNT, 0, 0); i--;) {
-					char *szComboProto = (char*)SendDlgItemMessage(hwndDlg, IDC_PROTOLIST, CB_GETITEMDATA, i, 0);
-					if (szComboProto == NULL) continue;
-					if (!lstrcmpA(szComboProto, ack->szModule)) {
-						COMBOBOXEXITEM cbei = { 0 };
-						cbei.mask = CBEIF_IMAGE;
-						cbei.iItem = i;
-						SendDlgItemMessage(hwndDlg, IDC_PROTOLIST, CBEM_GETITEM, 0, (LPARAM)&cbei);
-						lvi.iImage = cbei.iImage;
-						break;
-					}
-				}
-				int iItem = ListView_InsertItem(hwndList, &lvi);
-				int col = 1;
-				SetListItemText(hwndList, iItem, col++, lsr->psr.id);
-				SetListItemText(hwndList, iItem, col++, lsr->psr.nick);
-				SetListItemText(hwndList, iItem, col++, lsr->psr.firstName);
-				SetListItemText(hwndList, iItem, col++, lsr->psr.lastName);
-				SetListItemText(hwndList, iItem, col++, lsr->psr.email);
-				SetStatusBarResultInfo(hwndDlg);
-			}
-		}
-		break;
-
-	case WM_CLOSE:
-		DestroyWindow(hwndDlg);
-		break;
-
-	case WM_DESTROY:
-		int len = SendDlgItemMessage(hwndDlg, IDC_PROTOLIST, CB_GETLBTEXTLEN, SendDlgItemMessage(hwndDlg, IDC_PROTOLIST, CB_GETCURSEL, 0, 0), 0);
-		TCHAR *szProto = (TCHAR*)alloca(sizeof(TCHAR)*(len + 1));
-		*szProto = '\0';
-		SendDlgItemMessage(hwndDlg, IDC_PROTOLIST, CB_GETLBTEXT, SendDlgItemMessage(hwndDlg, IDC_PROTOLIST, CB_GETCURSEL, 0, 0), (LPARAM)szProto);
-		db_set_ts(NULL, "FindAdd", "LastSearched", szProto ? szProto : _T(""));
-
-		SaveColumnSizes(hwndList);
-		if (dat->hResultHook != NULL)
-			UnhookEvent(dat->hResultHook);
-		FreeSearchResults(hwndList);
-		ImageList_Destroy(dat->himlComboIcons);
-		mir_free(dat->search);
-		if (dat->hwndAdvSearch) {
-			DestroyWindow(dat->hwndAdvSearch);
-			dat->hwndAdvSearch = NULL;
-		}
-		if (dat->hwndTinySearch) {
-			DestroyWindow(dat->hwndTinySearch);
-			dat->hwndTinySearch = NULL;
-		}
-		mir_free(dat);
-		Window_FreeIcon_IcoLib(hwndDlg);
-		Utils_SaveWindowPosition(hwndDlg, NULL, "FindAdd", "");
-		break;
-	}
-	return FALSE;
-}
-
-static INT_PTR FindAddCommand(WPARAM, LPARAM)
-{
-	if (IsWindow(hwndFindAdd)) {
-		ShowWindow(hwndFindAdd, SW_SHOWNORMAL);
-		SetForegroundWindow(hwndFindAdd);
-		SetFocus(hwndFindAdd);
-	}
-	else {
-		int netProtoCount = 0;
-
-		// Make sure we have some networks to search on. This is not ideal since
-		// this check will be repeated every time the dialog is requested, but it
-		// must be done since this service can be called from other places than the menu.
-		// One alternative would be to only create the service if we have network
-		// protocols loaded but that would delay the creation until MODULE_LOADED and
-		// that is not good either...
-		for (int i = 0; i < accounts.getCount(); i++) {
-			PROTOACCOUNT *pa = accounts[i];
-			if (!Proto_IsAccountEnabled(pa))
-				continue;
-
-			int protoCaps = CallProtoServiceInt(NULL, pa->szModuleName, PS_GETCAPS, PFLAGNUM_1, 0);
-			if (protoCaps & PF1_ANYSEARCH)
-				netProtoCount++;
-		}
-		if (netProtoCount > 0)
-			hwndFindAdd = CreateDialog(hInst, MAKEINTRESOURCE(IDD_FINDADD), NULL, DlgProcFindAdd);
-	}
-	return 0;
-}
-
-int FindAddPreShutdown(WPARAM, LPARAM)
-{
-	if (IsWindow(hwndFindAdd))
-		DestroyWindow(hwndFindAdd);
-	hwndFindAdd = NULL;
-	return 0;
-}
-
-int LoadFindAddModule(void)
-{
-	CreateServiceFunction(MS_FINDADD_FINDADD, FindAddCommand);
-	HookEvent(ME_SYSTEM_MODULESLOADED, OnSystemModulesLoaded);
-	HookEvent(ME_PROTO_ACCLISTCHANGED, OnSystemModulesLoaded);
-	HookEvent(ME_SYSTEM_PRESHUTDOWN, FindAddPreShutdown);
-
-	CLISTMENUITEM mi = { sizeof(mi) };
-	mi.position = 500020000;
-	mi.icolibItem = GetSkinIconHandle(SKINICON_OTHER_FINDUSER);
-	mi.pszName = LPGEN("&Find/add contacts...");
-	mi.pszService = MS_FINDADD_FINDADD;
-	hMainMenuItem = Menu_AddMainMenuItem(&mi);
-	return 0;
-}
-
-static int OnSystemModulesLoaded(WPARAM, LPARAM)
-{
-	int netProtoCount = 0;
-
-	// Make sure we have some networks to search on.
-	for (int i = 0; i < accounts.getCount(); i++) {
-		PROTOACCOUNT *pa = accounts[i];
-		int protoCaps = CallProtoServiceInt(NULL, pa->szModuleName, PS_GETCAPS, PFLAGNUM_1, 0);
-		if (protoCaps & PF1_ANYSEARCH)
-			netProtoCount++;
-	}
-
-	Menu_ShowItem(hMainMenuItem, netProtoCount != 0);
-	return 0;
-}
+/*
+
+Miranda NG: the free IM client for Microsoft* Windows*
+
+Copyright (c) 2012-14 Miranda NG project (http://miranda-ng.org),
+Copyright (c) 2000-12 Miranda 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 "..\..\core\commonheaders.h"
+#include "findadd.h"
+
+#define TIMERID_THROBBER 111
+
+#define HM_SEARCHACK  (WM_USER+10)
+#define M_SETGROUPVISIBILITIES  (WM_USER+11)
+
+static HWND hwndFindAdd = NULL;
+static HANDLE hHookModulesLoaded = 0;
+static HGENMENU hMainMenuItem = NULL;
+static int OnSystemModulesLoaded(WPARAM wParam, LPARAM lParam);
+
+static int FindAddDlgResizer(HWND, LPARAM lParam, UTILRESIZECONTROL *urc)
+{
+	static int y, nextY, oldTop;
+	FindAddDlgData *dat = (FindAddDlgData*)lParam;
+
+	switch (urc->wId) {
+	case IDC_RESULTS:
+		return RD_ANCHORX_WIDTH | RD_ANCHORY_HEIGHT;
+
+	case IDOK:
+		dat->minDlgHeight = nextY + urc->rcItem.bottom - urc->rcItem.top;
+		return RD_ANCHORX_LEFT | RD_ANCHORY_BOTTOM;
+
+	case IDC_ADD:
+	case IDC_MOREOPTIONS:
+		return RD_ANCHORX_RIGHT | RD_ANCHORY_BOTTOM;
+
+	case IDC_STATUSBAR:
+		return RD_ANCHORX_WIDTH | RD_ANCHORY_BOTTOM;
+
+	case IDC_PROTOIDGROUP:	//the resize is always processed in template order
+		nextY = y = urc->rcItem.top;
+		if (dat->showProtoId) nextY = y + urc->rcItem.bottom - urc->rcItem.top + 7;
+		break;
+
+	case IDC_EMAILGROUP:
+		oldTop = urc->rcItem.top;
+		y = nextY;
+		if (dat->showEmail) nextY = y + urc->rcItem.bottom - urc->rcItem.top + 7;
+		OffsetRect(&urc->rcItem, 0, y - oldTop);
+		return RD_ANCHORX_LEFT | RD_ANCHORY_CUSTOM;
+
+	case IDC_NAMEGROUP:
+		oldTop = urc->rcItem.top;
+		y = nextY;
+		if (dat->showName) nextY = y + urc->rcItem.bottom - urc->rcItem.top + 7;
+		OffsetRect(&urc->rcItem, 0, y - oldTop);
+		return RD_ANCHORX_LEFT | RD_ANCHORY_CUSTOM;
+
+	case IDC_ADVANCEDGROUP:
+		oldTop = urc->rcItem.top;
+		y = nextY;
+		if (dat->showAdvanced) nextY = y + urc->rcItem.bottom - urc->rcItem.top + 7;
+		OffsetRect(&urc->rcItem, 0, y - oldTop);
+		return RD_ANCHORX_LEFT | RD_ANCHORY_CUSTOM;
+
+	case IDC_TINYEXTENDEDGROUP:
+		oldTop = urc->rcItem.top;
+		y = nextY;
+		if (dat->showTiny) {
+			int height = urc->dlgNewSize.cy - y - (urc->dlgOriginalSize.cy - urc->rcItem.bottom);
+			nextY = y + 200;  //min height for custom dialog
+			urc->rcItem.top = urc->rcItem.bottom - height;
+		}
+		return RD_ANCHORX_LEFT | RD_ANCHORY_BOTTOM;
+
+	case IDC_BYEMAIL:
+	case IDC_EMAIL:
+	case IDC_BYNAME:
+	case IDC_STNAMENICK:
+	case IDC_STNAMEFIRST:
+	case IDC_STNAMELAST:
+	case IDC_NAMENICK:
+	case IDC_NAMEFIRST:
+	case IDC_NAMELAST:
+	case IDC_BYADVANCED:
+	case IDC_BYCUSTOM:
+	case IDC_ADVANCED:
+		OffsetRect(&urc->rcItem, 0, y - oldTop);
+		return RD_ANCHORX_LEFT | RD_ANCHORY_CUSTOM;
+
+	case IDC_HEADERBAR:
+		return RD_ANCHORX_LEFT | RD_ANCHORY_TOP | RD_ANCHORX_WIDTH;
+	}
+	return RD_ANCHORX_LEFT | RD_ANCHORY_TOP;
+}
+
+static void RenderThrobber(HDC hdc, RECT *rcItem, int *throbbing, int *pivot)
+{
+	InflateRect(rcItem, -1, 0);
+	int width = rcItem->right - rcItem->left;
+	int height = rcItem->bottom - rcItem->top;
+	int height2 = height / 2;
+
+	if (*throbbing) {
+		/* create memdc */
+		HDC hMemDC = CreateCompatibleDC(0);
+		HBITMAP hBitmap = (HBITMAP)SelectObject(hMemDC, CreateCompatibleBitmap(hdc, width, height));
+		/* flush it */
+		RECT rc;
+		rc.left = rc.top = 0;
+		rc.right = width;
+		rc.bottom = height;
+		HBRUSH hBr = GetSysColorBrush(COLOR_BTNFACE);
+		FillRect(hMemDC, &rc, hBr);
+		DeleteObject(hBr);
+		/* set up the pen */
+		HPEN hPen = (HPEN)SelectObject(hMemDC, CreatePen(PS_SOLID, 4, GetSysColor(COLOR_BTNSHADOW)));
+		/* draw everything before the pivot */
+		int x = *pivot;
+		while (x > (-height)) {
+			MoveToEx(hMemDC, x + height2, 0, NULL);
+			LineTo(hMemDC, x - height2, height);
+			x -= 12;
+		}
+
+		/* draw everything after the pivot */
+		x = *pivot;
+		while (x < width + height) {
+			MoveToEx(hMemDC, x + height2, 0, NULL);
+			LineTo(hMemDC, x - height2, height);
+			x += 12;
+		}
+
+		/* move the pivot */
+		*pivot += 2;
+		/* reset the pivot point if it gets past the rect */
+		if (*pivot > width) *pivot = 0;
+		/* put back the old pen and delete the new one */
+		DeleteObject(SelectObject(hMemDC, hPen));
+		/* cap the top and bottom */
+		hPen = (HPEN)SelectObject(hMemDC, CreatePen(PS_SOLID, 1, GetSysColor(COLOR_BTNFACE)));
+		MoveToEx(hMemDC, 0, 0, NULL);
+		LineTo(hMemDC, width, 0);
+		MoveToEx(hMemDC, 0, height - 1, NULL);
+		LineTo(hMemDC, width, height - 1);
+		/* select in the old pen and delete the new pen */
+		DeleteObject(SelectObject(hMemDC, hPen));
+		/* paint to screen */
+		BitBlt(hdc, rcItem->left, rcItem->top, width, height, hMemDC, 0, 0, SRCCOPY);
+		/* select back in the old bitmap and delete the created one, as well as freeing the mem dc. */
+		hBitmap = (HBITMAP)SelectObject(hMemDC, hBitmap);
+		DeleteObject(hBitmap);
+		DeleteDC(hMemDC);
+	}
+	else {
+		/* just flush the DC */
+		HBRUSH hBr = GetSysColorBrush(COLOR_BTNFACE);
+		FillRect(hdc, rcItem, hBr);
+		DeleteObject(hBr);
+	}
+}
+
+static void StartThrobber(HWND hwndDlg, FindAddDlgData *dat)
+{
+	dat->throbbing = 1;
+	SetTimer(hwndDlg, TIMERID_THROBBER, 25, NULL);
+}
+
+static void StopThrobber(HWND hwndDlg, FindAddDlgData *dat)
+{
+	KillTimer(hwndDlg, TIMERID_THROBBER);
+	dat->throbbing = 0;
+	dat->pivot = 0;
+	InvalidateRect(GetDlgItem(hwndDlg, IDC_STATUSBAR), NULL, FALSE);
+}
+
+static LRESULT CALLBACK AdvancedSearchDlgSubclassProc(HWND hwndDlg, UINT msg, WPARAM wParam, LPARAM lParam)
+{
+	if (msg == WM_COMMAND) {
+		HWND parentHwnd = GetParent(hwndDlg);
+		switch (LOWORD(wParam)) {
+		case IDOK:
+			SendMessage(parentHwnd, WM_COMMAND, MAKEWPARAM(IDOK, BN_CLICKED), (LPARAM)GetDlgItem(parentHwnd, IDOK));
+			SetFocus(GetDlgItem(parentHwnd, IDC_ADVANCED));
+			break;
+
+		case IDCANCEL:
+			CheckDlgButton(parentHwnd, IDC_ADVANCED, BST_UNCHECKED);
+			SendMessage(parentHwnd, WM_COMMAND, MAKEWPARAM(IDC_ADVANCED, BN_CLICKED), (LPARAM)GetDlgItem(parentHwnd, IDC_ADVANCED));
+			SetFocus(GetDlgItem(parentHwnd, IDC_ADVANCED));
+			break;
+		}
+	}
+	return mir_callNextSubclass(hwndDlg, AdvancedSearchDlgSubclassProc, msg, wParam, lParam);
+}
+
+static void ShowAdvancedSearchDlg(HWND hwndDlg, FindAddDlgData *dat)
+{
+	char *szProto = (char*)SendDlgItemMessage(hwndDlg, IDC_PROTOLIST, CB_GETITEMDATA, SendDlgItemMessage(hwndDlg, IDC_PROTOLIST, CB_GETCURSEL, 0, 0), 0);
+	if (szProto == NULL)
+		return;
+
+	if (dat->hwndAdvSearch == NULL) {
+		RECT rc;
+		dat->hwndAdvSearch = (HWND)CallProtoServiceInt(NULL, szProto, PS_CREATEADVSEARCHUI, 0, (LPARAM)hwndDlg);
+		if (dat->hwndAdvSearch != NULL)
+			mir_subclassWindow(dat->hwndAdvSearch, AdvancedSearchDlgSubclassProc);
+		GetWindowRect(GetDlgItem(hwndDlg, IDC_RESULTS), &rc);
+		SetWindowPos(dat->hwndAdvSearch, 0, rc.left, rc.top, 0, 0, SWP_NOZORDER | SWP_NOSIZE);
+	}
+
+	AnimateWindow(dat->hwndAdvSearch, 150, AW_ACTIVATE | AW_SLIDE | AW_HOR_POSITIVE);
+	RedrawWindow(dat->hwndAdvSearch, NULL, NULL, RDW_INVALIDATE | RDW_UPDATENOW | RDW_ALLCHILDREN);
+
+	CheckDlgButton(hwndDlg, IDC_ADVANCED, BST_CHECKED);
+}
+
+static void ReposTinySearchDlg(HWND hwndDlg, FindAddDlgData *dat)
+{
+	if (dat->hwndTinySearch == NULL)
+		return;
+
+	RECT rc;
+	RECT clientRect;
+	POINT pt = { 0, 0 };
+	GetWindowRect(GetDlgItem(hwndDlg, IDC_TINYEXTENDEDGROUP), &rc);
+	GetWindowRect(dat->hwndTinySearch, &clientRect);
+	pt.x = rc.left;
+	pt.y = rc.top;
+	ScreenToClient(hwndDlg, &pt);
+	SetWindowPos(dat->hwndTinySearch, 0, pt.x + 5, pt.y + 15, rc.right - rc.left - 10, rc.bottom - rc.top - 30, SWP_NOZORDER);
+}
+
+static void ShowTinySearchDlg(HWND hwndDlg, FindAddDlgData *dat)
+{
+	char *szProto = (char*)SendDlgItemMessage(hwndDlg, IDC_PROTOLIST, CB_GETITEMDATA, SendDlgItemMessage(hwndDlg, IDC_PROTOLIST, CB_GETCURSEL, 0, 0), 0);
+	if (szProto == NULL)
+		return;
+
+	if (dat->hwndTinySearch == NULL) {
+		dat->hwndTinySearch = (HWND)CallProtoServiceInt(NULL, szProto, PS_CREATEADVSEARCHUI, 0, (LPARAM)/*GetDlgItem(*/hwndDlg/*, IDC_TINYEXTENDEDGROUP)*/);
+		if (dat->hwndTinySearch)
+			ReposTinySearchDlg(hwndDlg, dat);
+		else
+			dat->showTiny = false;
+	}
+	ShowWindow(dat->hwndTinySearch, SW_SHOW);
+}
+
+static void HideAdvancedSearchDlg(HWND hwndDlg, FindAddDlgData *dat)
+{
+	if (dat->hwndAdvSearch == NULL)
+		return;
+
+	AnimateWindow(dat->hwndAdvSearch, 150, AW_HIDE | AW_BLEND);
+	CheckDlgButton(hwndDlg, IDC_ADVANCED, BST_UNCHECKED);
+}
+
+void EnableResultButtons(HWND hwndDlg, int enable)
+{
+	EnableWindow(GetDlgItem(hwndDlg, IDC_ADD), enable);
+	EnableWindow(GetDlgItem(hwndDlg, IDC_MOREOPTIONS), enable);
+}
+
+static const int controls[] = { IDC_BYPROTOID, IDC_BYEMAIL, IDC_BYNAME, IDC_BYADVANCED, IDC_BYCUSTOM };
+
+static void CheckSearchTypeRadioButton(HWND hwndDlg, int idControl)
+{
+	for (int i = 0; i < SIZEOF(controls); i++)
+		CheckDlgButton(hwndDlg, controls[i], idControl == controls[i] ? BST_CHECKED : BST_UNCHECKED);
+}
+
+#define sttErrMsg TranslateT("You haven't filled in the search field. Please enter a search term and try again.")
+#define sttErrTitle TranslateT("Search")
+
+static void SetListItemText(HWND hwndList, int idx, int col, TCHAR* szText)
+{
+	if (szText && szText[0]) {
+		ListView_SetItemText(hwndList, idx, col, szText);
+	}
+	else {
+		ListView_SetItemText(hwndList, idx, col, TranslateT("<not specified>"));
+	}
+}
+
+static INT_PTR CALLBACK DlgProcFindAdd(HWND hwndDlg, UINT msg, WPARAM wParam, LPARAM lParam)
+{
+	FindAddDlgData* dat = (FindAddDlgData*)GetWindowLongPtr(hwndDlg, GWLP_USERDATA);
+	HWND hwndList = GetDlgItem(hwndDlg, IDC_RESULTS);
+
+	switch (msg) {
+	case WM_INITDIALOG:
+		TranslateDialogDefault(hwndDlg);
+		Window_SetIcon_IcoLib(hwndDlg, SKINICON_OTHER_FINDUSER);
+		dat = (FindAddDlgData*)mir_calloc(sizeof(FindAddDlgData));
+		SetWindowLongPtr(hwndDlg, GWLP_USERDATA, (LONG_PTR)dat);
+		dat->notSearchedYet = 1;
+		dat->iLastColumnSortIndex = 1;
+		dat->bSortAscending = 1;
+		SendDlgItemMessage(hwndDlg, IDC_MOREOPTIONS, BUTTONSETARROW, 1, 0);
+		SendDlgItemMessage(hwndDlg, IDOK, BUTTONADDTOOLTIP, (WPARAM)LPGENT("Ctrl+Search add contact"), BATF_TCHAR);
+
+		ListView_SetExtendedListViewStyle(hwndList, LVS_EX_FULLROWSELECT | LVS_EX_HEADERDRAGDROP);
+		{
+			RECT rc;
+			GetClientRect(hwndList, &rc);
+
+			LVCOLUMN lvc;
+			lvc.mask = LVCF_TEXT | LVCF_WIDTH;
+			lvc.pszText = TranslateT("Results");
+			lvc.cx = rc.right - 1;
+			ListView_InsertColumn(hwndList, 0, &lvc);
+
+			LVITEM lvi;
+			lvi.mask = LVIF_TEXT;
+			lvi.iItem = 0;
+			lvi.iSubItem = 0;
+			lvi.pszText = TranslateT("There are no results to display.");
+			ListView_InsertItem(hwndList, &lvi);
+
+			// Allocate a reasonable amount of space in the status bar
+			HDC hdc = GetDC(GetDlgItem(hwndDlg, IDC_STATUSBAR));
+			SelectObject(hdc, (HFONT)SendDlgItemMessage(hwndDlg, IDC_STATUSBAR, WM_GETFONT, 0, 0));
+
+			SIZE textSize;
+			GetTextExtentPoint32(hdc, TranslateT("Searching"), lstrlen(TranslateT("Searching")), &textSize);
+
+			int partWidth[3];
+			partWidth[0] = textSize.cx;
+			GetTextExtentPoint32(hdc, _T("01234567890123456789"), 20, &textSize);
+			partWidth[0] += textSize.cx;
+			ReleaseDC(GetDlgItem(hwndDlg, IDC_STATUSBAR), hdc);
+			partWidth[1] = partWidth[0] + 150;
+			partWidth[2] = -1;
+			SendDlgItemMessage(hwndDlg, IDC_STATUSBAR, SB_SETPARTS, SIZEOF(partWidth), (LPARAM)partWidth);
+			SendDlgItemMessage(hwndDlg, IDC_STATUSBAR, SB_SETTEXT, 1 | SBT_OWNERDRAW, 0);
+			SetStatusBarSearchInfo(GetDlgItem(hwndDlg, IDC_STATUSBAR), dat);
+
+			TCHAR *szProto = NULL;
+			DBVARIANT dbv;
+			if (!db_get_ts(NULL, "FindAdd", "LastSearched", &dbv)) {
+				szProto = NEWTSTR_ALLOCA(dbv.ptszVal);
+				db_free(&dbv); /* free string szProto was fetched with */
+			}
+
+			int i, index = 0, cbwidth = 0, netProtoCount = 0;
+			for (i = 0; i < accounts.getCount(); i++) {
+				if (!Proto_IsAccountEnabled(accounts[i]))
+					continue;
+
+				DWORD caps = (DWORD)CallProtoServiceInt(NULL, accounts[i]->szModuleName, PS_GETCAPS, PFLAGNUM_1, 0);
+				if (caps & PF1_ANYSEARCH)
+					netProtoCount++;
+			}
+			dat->himlComboIcons = ImageList_Create(GetSystemMetrics(SM_CXSMICON), GetSystemMetrics(SM_CYSMICON), ILC_COLOR32 | ILC_MASK, netProtoCount + 1, netProtoCount + 1);
+			SendDlgItemMessage(hwndDlg, IDC_PROTOLIST, CBEM_SETIMAGELIST, 0, (LPARAM)dat->himlComboIcons);
+
+			COMBOBOXEXITEM cbei;
+			cbei.mask = CBEIF_IMAGE | CBEIF_SELECTEDIMAGE | CBEIF_TEXT | CBEIF_LPARAM;
+			cbei.iItem = 0;
+			hdc = GetDC(hwndDlg);
+			SelectObject(hdc, (HFONT)SendDlgItemMessage(hwndDlg, IDC_PROTOLIST, WM_GETFONT, 0, 0));
+			if (netProtoCount > 1) {
+				cbei.pszText = TranslateT("All networks");
+				GetTextExtentPoint32(hdc, cbei.pszText, lstrlen(cbei.pszText), &textSize);
+				if (textSize.cx > cbwidth)
+					cbwidth = textSize.cx;
+				cbei.iImage = cbei.iSelectedImage = ImageList_AddIcon_IconLibLoaded(dat->himlComboIcons, SKINICON_OTHER_SEARCHALL);
+				cbei.lParam = 0;
+				SendDlgItemMessage(hwndDlg, IDC_PROTOLIST, CBEM_INSERTITEM, 0, (LPARAM)&cbei);
+				cbei.iItem++;
+			}
+
+			for (i = 0; i < accounts.getCount(); i++) {
+				PROTOACCOUNT *pa = accounts[i];
+				if (!Proto_IsAccountEnabled(pa))
+					continue;
+
+				DWORD caps = (DWORD)CallProtoServiceInt(NULL, pa->szModuleName, PS_GETCAPS, PFLAGNUM_1, 0);
+				if (!(caps & PF1_ANYSEARCH))
+					continue;
+
+				cbei.pszText = pa->tszAccountName;
+				GetTextExtentPoint32(hdc, cbei.pszText, lstrlen(cbei.pszText), &textSize);
+				if (textSize.cx > cbwidth)
+					cbwidth = textSize.cx;
+
+				HICON hIcon = (HICON)CallProtoServiceInt(NULL, pa->szModuleName, PS_LOADICON, PLI_PROTOCOL | PLIF_SMALL, 0);
+				cbei.iImage = cbei.iSelectedImage = ImageList_AddIcon(dat->himlComboIcons, hIcon);
+				DestroyIcon(hIcon);
+				cbei.lParam = (LPARAM)pa->szModuleName;
+				SendDlgItemMessageA(hwndDlg, IDC_PROTOLIST, CBEM_INSERTITEM, 0, (LPARAM)&cbei);
+				if (szProto && cbei.pszText && !lstrcmp(szProto, pa->tszAccountName))
+					index = cbei.iItem;
+				cbei.iItem++;
+			}
+			cbwidth += 32;
+
+			RECT rect;
+			SendDlgItemMessage(hwndDlg, IDC_PROTOLIST, CB_GETDROPPEDCONTROLRECT, 0, (LPARAM)&rect);
+			if ((rect.right - rect.left) < cbwidth)
+				SendDlgItemMessage(hwndDlg, IDC_PROTOLIST, CB_SETDROPPEDWIDTH, cbwidth, 0);
+			SendDlgItemMessage(hwndDlg, IDC_PROTOLIST, CB_SETCURSEL, index, 0);
+
+			SendMessage(hwndDlg, M_SETGROUPVISIBILITIES, 0, 0);
+			Utils_RestoreWindowPosition(hwndDlg, NULL, "FindAdd", "");
+		}
+		return TRUE;
+
+	case WM_SIZE:
+		{
+			UTILRESIZEDIALOG urd = { 0 };
+			urd.cbSize = sizeof(urd);
+			urd.hwndDlg = hwndDlg;
+			urd.hInstance = hInst;
+			urd.lpTemplate = MAKEINTRESOURCEA(IDD_FINDADD);
+			urd.lParam = (LPARAM)dat;
+			urd.pfnResizer = FindAddDlgResizer;
+			CallService(MS_UTILS_RESIZEDIALOG, 0, (LPARAM)&urd);
+			ReposTinySearchDlg(hwndDlg, dat);
+			SendDlgItemMessage(hwndDlg, IDC_STATUSBAR, WM_SIZE, 0, 0);
+			if (dat->notSearchedYet) {
+				RECT rc;
+				GetClientRect(hwndList, &rc);
+				ListView_SetColumnWidth(hwndList, 0, rc.right);
+			}
+		}
+		//fall through
+	case WM_MOVE:
+		if (dat && dat->hwndAdvSearch) {
+			RECT rc;
+			GetWindowRect(hwndList, &rc);
+			SetWindowPos(dat->hwndAdvSearch, 0, rc.left, rc.top, 0, 0, SWP_NOZORDER | SWP_NOSIZE);
+		}
+		break;
+
+	case WM_GETMINMAXINFO:
+		RECT rc, rc2;
+		GetWindowRect(hwndList, &rc);
+		GetWindowRect(hwndDlg, &rc2);
+		{
+			MINMAXINFO *mmi = (MINMAXINFO*)lParam;
+			mmi->ptMinTrackSize.x = rc.left - rc2.left + 10 + GetSystemMetrics(SM_CXFRAME);
+			GetClientRect(GetDlgItem(hwndDlg, IDC_MOREOPTIONS), &rc);
+			mmi->ptMinTrackSize.x += rc.right + 5;
+			GetClientRect(GetDlgItem(hwndDlg, IDC_ADD), &rc);
+			mmi->ptMinTrackSize.x += rc.right + 5;
+			GetClientRect(GetDlgItem(hwndDlg, IDC_STATUSBAR), &rc);
+			mmi->ptMinTrackSize.y = dat->minDlgHeight + 20 + GetSystemMetrics(SM_CYCAPTION) + 2 * GetSystemMetrics(SM_CYFRAME);
+			GetClientRect(GetDlgItem(hwndDlg, IDC_STATUSBAR), &rc);
+			mmi->ptMinTrackSize.y += rc.bottom;
+		}
+		return 0;
+
+	case M_SETGROUPVISIBILITIES:
+		dat->showAdvanced = dat->showEmail = dat->showName = dat->showProtoId = dat->showTiny = 0;
+		{
+			char *szProto = (char*)SendDlgItemMessage(hwndDlg, IDC_PROTOLIST, CB_GETITEMDATA, SendDlgItemMessage(hwndDlg, IDC_PROTOLIST, CB_GETCURSEL, 0, 0), 0);
+			if (szProto == (char *)CB_ERR)
+				break;
+			if (szProto == NULL) {
+				for (int i = 0; i < accounts.getCount(); i++) {
+					PROTOACCOUNT *pa = accounts[i];
+					if (Proto_IsAccountEnabled(pa)) {
+						DWORD protoCaps = (DWORD)CallProtoServiceInt(NULL, pa->szModuleName, PS_GETCAPS, PFLAGNUM_1, 0);
+						if (protoCaps & PF1_SEARCHBYEMAIL) dat->showEmail = 1;
+						if (protoCaps & PF1_SEARCHBYNAME) dat->showName = 1;
+					}
+				}
+			}
+			else {
+				DWORD protoCaps = (DWORD)CallProtoServiceInt(NULL, szProto, PS_GETCAPS, PFLAGNUM_1, 0);
+				if (protoCaps & PF1_BASICSEARCH) dat->showProtoId = 1;
+				if (protoCaps & PF1_SEARCHBYEMAIL) dat->showEmail = 1;
+				if (protoCaps & PF1_SEARCHBYNAME) dat->showName = 1;
+
+				if (protoCaps & PF1_EXTSEARCHUI) dat->showAdvanced = 1;
+				else if (protoCaps & PF1_EXTSEARCH) dat->showTiny = 1;
+
+				if (protoCaps & PF1_USERIDISEMAIL && dat->showProtoId) { dat->showProtoId = 0; dat->showEmail = 1; }
+				if (dat->showProtoId) {
+					char *szUniqueId = (char*)CallProtoServiceInt(NULL, szProto, PS_GETCAPS, PFLAG_UNIQUEIDTEXT, 0);
+					if (szUniqueId)
+						SetDlgItemTextA(hwndDlg, IDC_BYPROTOID, szUniqueId);
+					else
+						SetDlgItemText(hwndDlg, IDC_BYPROTOID, TranslateT("Handle"));
+
+					if (protoCaps & PF1_NUMERICUSERID)
+						SetWindowLongPtr(GetDlgItem(hwndDlg, IDC_PROTOID), GWL_STYLE, GetWindowLongPtr(GetDlgItem(hwndDlg, IDC_PROTOID), GWL_STYLE) | ES_NUMBER);
+					else
+						SetWindowLongPtr(GetDlgItem(hwndDlg, IDC_PROTOID), GWL_STYLE, GetWindowLongPtr(GetDlgItem(hwndDlg, IDC_PROTOID), GWL_STYLE)&~ES_NUMBER);
+				}
+			}
+
+			if (dat->showTiny)
+				ShowTinySearchDlg(hwndDlg, dat);
+			else if (dat->hwndTinySearch) {
+				DestroyWindow(dat->hwndTinySearch);
+				dat->hwndTinySearch = NULL;
+			}
+
+#define en(id, t) ShowWindow( GetDlgItem(hwndDlg, IDC_##id), dat->show##t?SW_SHOW:SW_HIDE)
+			en(PROTOIDGROUP, ProtoId); en(BYPROTOID, ProtoId); en(PROTOID, ProtoId);
+			en(EMAILGROUP, Email); en(BYEMAIL, Email); en(EMAIL, Email);
+			en(NAMEGROUP, Name);  en(BYNAME, Name);
+			en(STNAMENICK, Name); en(NAMENICK, Name);
+			en(STNAMEFIRST, Name); en(NAMEFIRST, Name);
+			en(STNAMELAST, Name); en(NAMELAST, Name);
+			en(ADVANCEDGROUP, Advanced); en(BYADVANCED, Advanced); en(ADVANCED, Advanced);
+			en(BYCUSTOM, Tiny); en(TINYEXTENDEDGROUP, Tiny);
+#undef en
+			int checkmarkVisible = (dat->showAdvanced && IsDlgButtonChecked(hwndDlg, IDC_BYADVANCED)) ||
+				(dat->showEmail && IsDlgButtonChecked(hwndDlg, IDC_BYEMAIL)) ||
+				(dat->showTiny && IsDlgButtonChecked(hwndDlg, IDC_BYCUSTOM)) ||
+				(dat->showName && IsDlgButtonChecked(hwndDlg, IDC_BYNAME)) ||
+				(dat->showProtoId && IsDlgButtonChecked(hwndDlg, IDC_BYPROTOID));
+			if (!checkmarkVisible) {
+				if (dat->showProtoId) CheckSearchTypeRadioButton(hwndDlg, IDC_BYPROTOID);
+				else if (dat->showEmail) CheckSearchTypeRadioButton(hwndDlg, IDC_BYEMAIL);
+				else if (dat->showName) CheckSearchTypeRadioButton(hwndDlg, IDC_BYNAME);
+				else if (dat->showAdvanced) CheckSearchTypeRadioButton(hwndDlg, IDC_BYADVANCED);
+				else if (dat->showTiny) CheckSearchTypeRadioButton(hwndDlg, IDC_BYCUSTOM);
+			}
+
+			SendMessage(hwndDlg, WM_SIZE, 0, 0);
+
+			MINMAXINFO mmi;
+			SendMessage(hwndDlg, WM_GETMINMAXINFO, 0, (LPARAM)&mmi);
+
+			RECT rc;
+			GetWindowRect(hwndDlg, &rc);
+			if (rc.bottom - rc.top < mmi.ptMinTrackSize.y)
+				SetWindowPos(hwndDlg, 0, 0, 0, rc.right - rc.left, mmi.ptMinTrackSize.y, SWP_NOZORDER | SWP_NOMOVE);
+		}
+		break;
+
+	case WM_TIMER:
+		if (wParam == TIMERID_THROBBER) {
+			int borders[3];
+			SendDlgItemMessage(hwndDlg, IDC_STATUSBAR, SB_GETBORDERS, 0, (LPARAM)borders);
+
+			RECT rc;
+			SendDlgItemMessage(hwndDlg, IDC_STATUSBAR, SB_GETRECT, 1, (LPARAM)&rc);
+			InflateRect(&rc, -borders[2] / 2, -borders[1] / 2);
+			HDC hdc = GetDC(GetDlgItem(hwndDlg, IDC_STATUSBAR));
+			RenderThrobber(hdc, &rc, &dat->throbbing, &dat->pivot);
+			ReleaseDC(GetDlgItem(hwndDlg, IDC_STATUSBAR), hdc);
+		}
+		break;
+
+	case WM_DRAWITEM:
+		{
+			DRAWITEMSTRUCT *dis = (DRAWITEMSTRUCT*)lParam;
+			if (dis->CtlID == IDC_STATUSBAR && dis->itemID == 1) {
+				RenderThrobber(dis->hDC, &dis->rcItem, &dat->throbbing, &dat->pivot);
+				return TRUE;
+			}
+		}
+		break;
+
+	case WM_NOTIFY:
+		if (wParam == IDC_RESULTS) {
+			switch (((LPNMHDR)lParam)->code) {
+			case LVN_ITEMCHANGED:
+				{
+					int count = ListView_GetSelectedCount(hwndList);
+					if (dat->notSearchedYet)
+						count = 0;
+					EnableResultButtons(hwndDlg, count);
+				}
+				break;
+
+			case LVN_COLUMNCLICK:
+				HDITEM hdi;
+				hdi.mask = HDI_FORMAT;
+				hdi.fmt = HDF_LEFT | HDF_STRING;
+				Header_SetItem(ListView_GetHeader(hwndList), dat->iLastColumnSortIndex, &hdi);
+
+				LPNMLISTVIEW nmlv = (LPNMLISTVIEW)lParam;
+				if (nmlv->iSubItem != dat->iLastColumnSortIndex) {
+					dat->bSortAscending = TRUE;
+					dat->iLastColumnSortIndex = nmlv->iSubItem;
+				}
+				else dat->bSortAscending = !dat->bSortAscending;
+
+				hdi.fmt = HDF_LEFT | HDF_STRING | (dat->bSortAscending ? HDF_SORTDOWN : HDF_SORTUP);
+				Header_SetItem(ListView_GetHeader(hwndList), dat->iLastColumnSortIndex, &hdi);
+
+				ListView_SortItemsEx(hwndList, SearchResultsCompareFunc, (LPARAM)hwndDlg);
+			}
+		}
+		break;
+
+	case WM_COMMAND:
+		switch(LOWORD(wParam)) {
+		case IDC_PROTOLIST:
+			if (HIWORD(wParam) == CBN_SELCHANGE) {
+				HideAdvancedSearchDlg(hwndDlg, dat);
+				if (dat->hwndAdvSearch) {
+					DestroyWindow(dat->hwndAdvSearch);
+					dat->hwndAdvSearch = NULL;
+				}
+				if (dat->hwndTinySearch) {
+					DestroyWindow(dat->hwndTinySearch);
+					dat->hwndTinySearch = NULL;
+				}
+				SendMessage(hwndDlg, M_SETGROUPVISIBILITIES, 0, 0);
+			}
+			break;
+
+		case IDC_BYPROTOID:
+		case IDC_BYEMAIL:
+		case IDC_BYNAME:
+			{
+				int count = ListView_GetSelectedCount(hwndList);
+				if (dat->notSearchedYet)
+					count = 0;
+				EnableWindow(GetDlgItem(hwndDlg, IDC_ADD), count);
+				HideAdvancedSearchDlg(hwndDlg, dat);
+			}
+			break;
+
+		case IDC_PROTOID:
+			if (HIWORD(wParam) == EN_CHANGE) {
+				HideAdvancedSearchDlg(hwndDlg, dat);
+				CheckSearchTypeRadioButton(hwndDlg, IDC_BYPROTOID);
+			}
+			break;
+
+		case IDC_EMAIL:
+			if (HIWORD(wParam) == EN_CHANGE) {
+				HideAdvancedSearchDlg(hwndDlg, dat);
+				CheckSearchTypeRadioButton(hwndDlg, IDC_BYEMAIL);
+			}
+			break;
+
+		case IDC_NAMENICK:
+		case IDC_NAMEFIRST:
+		case IDC_NAMELAST:
+			if (HIWORD(wParam) == EN_CHANGE) {
+				HideAdvancedSearchDlg(hwndDlg, dat);
+				CheckSearchTypeRadioButton(hwndDlg, IDC_BYNAME);
+			}
+			break;
+
+		case IDC_ADVANCED:
+			EnableWindow(GetDlgItem(hwndDlg, IDC_ADD), ListView_GetSelectedCount(hwndList) > 0);
+			if (IsDlgButtonChecked(hwndDlg, IDC_ADVANCED))
+				ShowAdvancedSearchDlg(hwndDlg, dat);
+			else
+				HideAdvancedSearchDlg(hwndDlg, dat);
+			CheckSearchTypeRadioButton(hwndDlg, IDC_BYADVANCED);
+			break;
+
+		case IDCANCEL:
+			DestroyWindow(hwndDlg);
+			break;
+
+		case IDOK:
+			HideAdvancedSearchDlg(hwndDlg, dat);
+			if (dat->searchCount) {	 //cancel search
+				SetDlgItemText(hwndDlg, IDOK, TranslateT("&Search"));
+				if (dat->hResultHook) { UnhookEvent(dat->hResultHook); dat->hResultHook = NULL; }
+				if (dat->search) { mir_free(dat->search); dat->search = NULL; }
+				dat->searchCount = 0;
+				StopThrobber(hwndDlg, dat);
+				SetStatusBarSearchInfo(GetDlgItem(hwndDlg, IDC_STATUSBAR), dat);
+			}
+			else {
+				char *szProto = (char*)SendDlgItemMessage(hwndDlg, IDC_PROTOLIST, CB_GETITEMDATA, SendDlgItemMessage(hwndDlg, IDC_PROTOLIST, CB_GETCURSEL, 0, 0), 0);
+				if (dat->search)
+					mir_free(dat->search), dat->search = NULL;
+				dat->searchCount = 0;
+				dat->hResultHook = HookEventMessage(ME_PROTO_ACK, hwndDlg, HM_SEARCHACK);
+				if (IsDlgButtonChecked(hwndDlg, IDC_BYCUSTOM))
+					BeginSearch(hwndDlg, dat, szProto, PS_SEARCHBYADVANCED, PF1_EXTSEARCHUI, dat->hwndTinySearch);
+				else if (IsDlgButtonChecked(hwndDlg, IDC_BYPROTOID)) {
+					TCHAR str[256];
+					GetDlgItemText(hwndDlg, IDC_PROTOID, str, SIZEOF(str));
+					rtrimt(str);
+					if (str[0] == 0)
+						MessageBox(hwndDlg, sttErrMsg, sttErrTitle, MB_ICONERROR | MB_OK);
+					else
+						BeginSearch(hwndDlg, dat, szProto, PS_BASICSEARCHT, PF1_BASICSEARCH, str);
+				}
+				else if (IsDlgButtonChecked(hwndDlg, IDC_BYEMAIL)) {
+					TCHAR str[256];
+					GetDlgItemText(hwndDlg, IDC_EMAIL, str, SIZEOF(str));
+					rtrimt(str);
+					if (str[0] == 0)
+						MessageBox(hwndDlg, sttErrMsg, sttErrTitle, MB_ICONERROR | MB_OK);
+					else
+						BeginSearch(hwndDlg, dat, szProto, PS_SEARCHBYEMAILT, PF1_SEARCHBYEMAIL, str);
+				}
+				else if (IsDlgButtonChecked(hwndDlg, IDC_BYNAME)) {
+					TCHAR nick[256], first[256], last[256];
+					PROTOSEARCHBYNAME psbn;
+					GetDlgItemText(hwndDlg, IDC_NAMENICK, nick, SIZEOF(nick));
+					GetDlgItemText(hwndDlg, IDC_NAMEFIRST, first, SIZEOF(first));
+					GetDlgItemText(hwndDlg, IDC_NAMELAST, last, SIZEOF(last));
+					psbn.pszFirstName = first;
+					psbn.pszLastName = last;
+					psbn.pszNick = nick;
+					if (nick[0] == 0 && first[0] == 0 && last[0] == 0)
+						MessageBox(hwndDlg, sttErrMsg, sttErrTitle, MB_ICONERROR | MB_OK);
+					else
+						BeginSearch(hwndDlg, dat, szProto, PS_SEARCHBYNAMET, PF1_SEARCHBYNAME, &psbn);
+				}
+				else if (IsDlgButtonChecked(hwndDlg, IDC_BYADVANCED)) {
+					if (dat->hwndAdvSearch == NULL)
+						MessageBox(hwndDlg, sttErrMsg, sttErrTitle, MB_ICONERROR | MB_OK);
+					else
+						BeginSearch(hwndDlg, dat, szProto, PS_SEARCHBYADVANCED, PF1_EXTSEARCHUI, dat->hwndAdvSearch);
+				}
+
+				if (dat->searchCount == 0) {
+					if (dat->hResultHook) {
+						UnhookEvent(dat->hResultHook);
+						dat->hResultHook = NULL;
+					}
+					break;
+				}
+
+				dat->notSearchedYet = 0;
+				FreeSearchResults(hwndList);
+
+				CreateResultsColumns(hwndList, dat, szProto);
+				SetStatusBarSearchInfo(GetDlgItem(hwndDlg, IDC_STATUSBAR), dat);
+				SetStatusBarResultInfo(hwndDlg);
+				StartThrobber(hwndDlg, dat);
+				SetDlgItemText(hwndDlg, IDOK, TranslateT("Cancel"));
+			}
+			break;
+
+		case IDC_ADD:
+			{
+				ADDCONTACTSTRUCT acs = {0};
+
+				if (ListView_GetSelectedCount(hwndList) == 1) {
+					LVITEM lvi;
+					lvi.mask = LVIF_PARAM;
+					lvi.iItem = ListView_GetNextItem(hwndList, -1, LVNI_ALL | LVNI_SELECTED);
+					ListView_GetItem(hwndList, &lvi);
+					ListSearchResult *lsr = (ListSearchResult*)lvi.lParam;
+					acs.szProto = lsr->szProto;
+					acs.psr = &lsr->psr;
+				}
+				else {
+					TCHAR str[256];
+					GetDlgItemText(hwndDlg, IDC_PROTOID, str, SIZEOF(str));
+					if (*rtrimt(str) == 0)
+						break;
+
+					PROTOSEARCHRESULT psr = { 0 };
+					psr.cbSize = sizeof(psr);
+					psr.flags = PSR_TCHAR;
+					psr.id = str;
+
+					acs.psr = &psr;
+					acs.szProto = (char*)SendDlgItemMessage(hwndDlg, IDC_PROTOLIST, CB_GETITEMDATA,
+						SendDlgItemMessage(hwndDlg, IDC_PROTOLIST, CB_GETCURSEL, 0, 0), 0);
+				}
+
+				acs.handleType = HANDLE_SEARCHRESULT;
+				CallService(MS_ADDCONTACT_SHOW, (WPARAM)hwndDlg, (LPARAM)&acs);
+			}
+			break;
+
+		case IDC_MOREOPTIONS:
+			RECT rc;
+			GetWindowRect(GetDlgItem(hwndDlg, IDC_MOREOPTIONS), &rc);
+			ShowMoreOptionsMenu(hwndDlg, rc.left, rc.bottom);
+			break;
+		}
+
+		if (lParam && dat->hwndTinySearch == (HWND)lParam &&
+			HIWORD(wParam) == EN_SETFOCUS && LOWORD(wParam) == 0 &&
+			!IsDlgButtonChecked(hwndDlg, IDC_BYCUSTOM))
+		{
+			CheckSearchTypeRadioButton(hwndDlg, IDC_BYCUSTOM);
+		}
+		break;
+
+	case WM_CONTEXTMENU:
+		{
+			POINT pt = { LOWORD(lParam), HIWORD(lParam) };
+
+			LVHITTESTINFO lvhti;
+			lvhti.pt = pt;
+			ScreenToClient(hwndDlg, &pt);
+			switch (GetDlgCtrlID(ChildWindowFromPoint(hwndDlg, pt))) {
+			case IDC_RESULTS:
+				if (dat->notSearchedYet)
+					return TRUE;
+				ScreenToClient(hwndList, &lvhti.pt);
+				if (ListView_HitTest(hwndList, &lvhti) == -1)
+					break;
+				ShowMoreOptionsMenu(hwndDlg, (short)LOWORD(lParam), (short)HIWORD(lParam));
+				return TRUE;
+			}
+		}
+		break;
+
+	case HM_SEARCHACK:
+		{
+			ACKDATA *ack = (ACKDATA*)lParam;
+			if (ack->type != ACKTYPE_SEARCH)
+				break;
+
+			int i;
+			for (i = 0; i < dat->searchCount; i++)
+				if (dat->search[i].hProcess == ack->hProcess && dat->search[i].hProcess != NULL && !lstrcmpA(dat->search[i].szProto, ack->szModule)) break;
+			if (i == dat->searchCount)
+				break;
+
+			if (ack->result == ACKRESULT_SUCCESS || ack->result == ACKRESULT_FAILED) {
+				dat->searchCount--;
+				memmove(dat->search + i, dat->search + i + 1, sizeof(struct ProtoSearchInfo)*(dat->searchCount - i));
+				if (dat->searchCount == 0) {
+					mir_free(dat->search);
+					dat->search = NULL;
+					UnhookEvent(dat->hResultHook);
+					dat->hResultHook = NULL;
+					SetDlgItemText(hwndDlg, IDOK, TranslateT("&Search"));
+					StopThrobber(hwndDlg, dat);
+				}
+				ListView_SortItemsEx(hwndList, SearchResultsCompareFunc, (LPARAM)hwndDlg);
+				SetStatusBarSearchInfo(GetDlgItem(hwndDlg, IDC_STATUSBAR), dat);
+			}
+			else if (ack->result == ACKRESULT_SEARCHRESULT && ack->lParam) {
+				CUSTOMSEARCHRESULTS *csr = (CUSTOMSEARCHRESULTS*)ack->lParam;
+				dat->bFlexSearchResult = TRUE;
+				PROTOSEARCHRESULT *psr = &csr->psr;
+				// check if this is column names data (psr->cbSize == 0)
+				if (psr->cbSize == 0) { // blob contain info about columns
+					//firstly remove all exist items
+					FreeSearchResults(hwndList);
+					ListView_DeleteAllItems(hwndList); //not sure if previous delete list items too
+					//secondly remove all columns
+					while (ListView_DeleteColumn(hwndList, 1)); //will delete fist column till it possible
+					//now will add columns and captions;
+					LVCOLUMN lvc = { 0 };
+					lvc.mask = LVCF_TEXT;
+					for (int iColumn = 0; iColumn < csr->nFieldCount; iColumn++) {
+						lvc.pszText = TranslateTS(csr->pszFields[iColumn]);
+						ListView_InsertColumn(hwndList, iColumn + 1, &lvc);
+					}
+					// Column inserting Done
+				}
+				else {	//  blob contain info about found contacts
+					ListSearchResult *lsr = (ListSearchResult*)mir_alloc(offsetof(struct ListSearchResult, psr) + psr->cbSize);
+					lsr->szProto = ack->szModule;
+					memcpy(&lsr->psr, psr, psr->cbSize);
+
+					/* Next block is not needed but behavior will be kept */
+					bool isUnicode = (psr->flags & PSR_UNICODE) != 0;
+					if (psr->id) {
+						BOOL validPtr = isUnicode ? IsBadStringPtrW((wchar_t*)psr->id, 25) : IsBadStringPtrA((char*)psr->id, 25);
+						if (!validPtr) {
+							isUnicode = false;
+							lsr->psr.id = NULL;
+						}
+						else lsr->psr.id = isUnicode ? mir_u2t((wchar_t*)psr->id) : mir_a2t((char*)psr->id);
+					}
+
+					lsr->psr.nick = isUnicode ? mir_u2t((wchar_t*)psr->nick) : mir_a2t((char*)psr->nick);
+					lsr->psr.firstName = isUnicode ? mir_u2t((wchar_t*)psr->firstName) : mir_a2t((char*)psr->firstName);
+					lsr->psr.lastName = isUnicode ? mir_u2t((wchar_t*)psr->lastName) : mir_a2t((char*)psr->lastName);
+					lsr->psr.email = isUnicode ? mir_u2t((wchar_t*)psr->email) : mir_a2t((char*)psr->email);
+					lsr->psr.flags = psr->flags & ~PSR_UNICODE | PSR_TCHAR;
+
+					LVITEM lvi = { 0 };
+					lvi.mask = LVIF_PARAM | LVIF_IMAGE;
+					lvi.lParam = (LPARAM)lsr;
+					for (int i = SendDlgItemMessage(hwndDlg, IDC_PROTOLIST, CB_GETCOUNT, 0, 0); i--;) {
+						char *szComboProto = (char*)SendDlgItemMessage(hwndDlg, IDC_PROTOLIST, CB_GETITEMDATA, i, 0);
+						if (szComboProto == NULL) continue;
+						if (!lstrcmpA(szComboProto, ack->szModule)) {
+							COMBOBOXEXITEM cbei = { 0 };
+							cbei.mask = CBEIF_IMAGE;
+							cbei.iItem = i;
+							SendDlgItemMessage(hwndDlg, IDC_PROTOLIST, CBEM_GETITEM, 0, (LPARAM)&cbei);
+							lvi.iImage = cbei.iImage;
+						}
+					}
+					int iItem = ListView_InsertItem(hwndList, &lvi);
+					for (int col = 0; col < csr->nFieldCount; col++)
+						SetListItemText(hwndList, iItem, col + 1, csr->pszFields[col]);
+
+					ListView_SortItemsEx(hwndList, SearchResultsCompareFunc, (LPARAM)hwndDlg);
+					iItem = 0;
+					while (ListView_SetColumnWidth(hwndList, iItem++, LVSCW_AUTOSIZE_USEHEADER));
+					SetStatusBarResultInfo(hwndDlg);
+				}
+				break;
+			}
+			else if (ack->result == ACKRESULT_DATA) {
+				PROTOSEARCHRESULT *psr = (PROTOSEARCHRESULT*)ack->lParam;
+				ListSearchResult *lsr = (ListSearchResult*)mir_alloc(offsetof(struct ListSearchResult, psr) + psr->cbSize);
+				lsr->szProto = ack->szModule;
+
+				dat->bFlexSearchResult = FALSE;
+
+				CopyMemory(&lsr->psr, psr, psr->cbSize);
+				lsr->psr.nick = psr->flags & PSR_UNICODE ? mir_u2t((wchar_t*)psr->nick) : mir_a2t((char*)psr->nick);
+				lsr->psr.firstName = psr->flags & PSR_UNICODE ? mir_u2t((wchar_t*)psr->firstName) : mir_a2t((char*)psr->firstName);
+				lsr->psr.lastName = psr->flags & PSR_UNICODE ? mir_u2t((wchar_t*)psr->lastName) : mir_a2t((char*)psr->lastName);
+				lsr->psr.email = psr->flags & PSR_UNICODE ? mir_u2t((wchar_t*)psr->email) : mir_a2t((char*)psr->email);
+				lsr->psr.id = psr->flags & PSR_UNICODE ? mir_u2t((wchar_t*)psr->id) : mir_a2t((char*)psr->id);
+				lsr->psr.flags = psr->flags & ~PSR_UNICODE | PSR_TCHAR;
+
+				LVITEM lvi = { 0 };
+				lvi.mask = LVIF_PARAM | LVIF_IMAGE;
+				lvi.lParam = (LPARAM)lsr;
+				for (int i = SendDlgItemMessage(hwndDlg, IDC_PROTOLIST, CB_GETCOUNT, 0, 0); i--;) {
+					char *szComboProto = (char*)SendDlgItemMessage(hwndDlg, IDC_PROTOLIST, CB_GETITEMDATA, i, 0);
+					if (szComboProto == NULL) continue;
+					if (!lstrcmpA(szComboProto, ack->szModule)) {
+						COMBOBOXEXITEM cbei = { 0 };
+						cbei.mask = CBEIF_IMAGE;
+						cbei.iItem = i;
+						SendDlgItemMessage(hwndDlg, IDC_PROTOLIST, CBEM_GETITEM, 0, (LPARAM)&cbei);
+						lvi.iImage = cbei.iImage;
+						break;
+					}
+				}
+				int iItem = ListView_InsertItem(hwndList, &lvi);
+				int col = 1;
+				SetListItemText(hwndList, iItem, col++, lsr->psr.id);
+				SetListItemText(hwndList, iItem, col++, lsr->psr.nick);
+				SetListItemText(hwndList, iItem, col++, lsr->psr.firstName);
+				SetListItemText(hwndList, iItem, col++, lsr->psr.lastName);
+				SetListItemText(hwndList, iItem, col++, lsr->psr.email);
+				SetStatusBarResultInfo(hwndDlg);
+			}
+		}
+		break;
+
+	case WM_CLOSE:
+		DestroyWindow(hwndDlg);
+		break;
+
+	case WM_DESTROY:
+		int len = SendDlgItemMessage(hwndDlg, IDC_PROTOLIST, CB_GETLBTEXTLEN, SendDlgItemMessage(hwndDlg, IDC_PROTOLIST, CB_GETCURSEL, 0, 0), 0);
+		TCHAR *szProto = (TCHAR*)alloca(sizeof(TCHAR)*(len + 1));
+		if (szProto != NULL) {
+			*szProto = '\0';
+			SendDlgItemMessage(hwndDlg, IDC_PROTOLIST, CB_GETLBTEXT, SendDlgItemMessage(hwndDlg, IDC_PROTOLIST, CB_GETCURSEL, 0, 0), (LPARAM)szProto);
+			db_set_ts(NULL, "FindAdd", "LastSearched", szProto);
+		}
+
+		SaveColumnSizes(hwndList);
+		if (dat->hResultHook != NULL)
+			UnhookEvent(dat->hResultHook);
+		FreeSearchResults(hwndList);
+		ImageList_Destroy(dat->himlComboIcons);
+		mir_free(dat->search);
+		if (dat->hwndAdvSearch) {
+			DestroyWindow(dat->hwndAdvSearch);
+			dat->hwndAdvSearch = NULL;
+		}
+		if (dat->hwndTinySearch) {
+			DestroyWindow(dat->hwndTinySearch);
+			dat->hwndTinySearch = NULL;
+		}
+		mir_free(dat);
+		Window_FreeIcon_IcoLib(hwndDlg);
+		Utils_SaveWindowPosition(hwndDlg, NULL, "FindAdd", "");
+		break;
+	}
+	return FALSE;
+}
+
+static INT_PTR FindAddCommand(WPARAM, LPARAM)
+{
+	if (IsWindow(hwndFindAdd)) {
+		ShowWindow(hwndFindAdd, SW_SHOWNORMAL);
+		SetForegroundWindow(hwndFindAdd);
+		SetFocus(hwndFindAdd);
+	}
+	else {
+		int netProtoCount = 0;
+
+		// Make sure we have some networks to search on. This is not ideal since
+		// this check will be repeated every time the dialog is requested, but it
+		// must be done since this service can be called from other places than the menu.
+		// One alternative would be to only create the service if we have network
+		// protocols loaded but that would delay the creation until MODULE_LOADED and
+		// that is not good either...
+		for (int i = 0; i < accounts.getCount(); i++) {
+			PROTOACCOUNT *pa = accounts[i];
+			if (!Proto_IsAccountEnabled(pa))
+				continue;
+
+			int protoCaps = CallProtoServiceInt(NULL, pa->szModuleName, PS_GETCAPS, PFLAGNUM_1, 0);
+			if (protoCaps & PF1_ANYSEARCH)
+				netProtoCount++;
+		}
+		if (netProtoCount > 0)
+			hwndFindAdd = CreateDialog(hInst, MAKEINTRESOURCE(IDD_FINDADD), NULL, DlgProcFindAdd);
+	}
+	return 0;
+}
+
+int FindAddPreShutdown(WPARAM, LPARAM)
+{
+	if (IsWindow(hwndFindAdd))
+		DestroyWindow(hwndFindAdd);
+	hwndFindAdd = NULL;
+	return 0;
+}
+
+int LoadFindAddModule(void)
+{
+	CreateServiceFunction(MS_FINDADD_FINDADD, FindAddCommand);
+	HookEvent(ME_SYSTEM_MODULESLOADED, OnSystemModulesLoaded);
+	HookEvent(ME_PROTO_ACCLISTCHANGED, OnSystemModulesLoaded);
+	HookEvent(ME_SYSTEM_PRESHUTDOWN, FindAddPreShutdown);
+
+	CLISTMENUITEM mi = { sizeof(mi) };
+	mi.position = 500020000;
+	mi.icolibItem = GetSkinIconHandle(SKINICON_OTHER_FINDUSER);
+	mi.pszName = LPGEN("&Find/add contacts...");
+	mi.pszService = MS_FINDADD_FINDADD;
+	hMainMenuItem = Menu_AddMainMenuItem(&mi);
+	return 0;
+}
+
+static int OnSystemModulesLoaded(WPARAM, LPARAM)
+{
+	int netProtoCount = 0;
+
+	// Make sure we have some networks to search on.
+	for (int i = 0; i < accounts.getCount(); i++) {
+		PROTOACCOUNT *pa = accounts[i];
+		int protoCaps = CallProtoServiceInt(NULL, pa->szModuleName, PS_GETCAPS, PFLAGNUM_1, 0);
+		if (protoCaps & PF1_ANYSEARCH)
+			netProtoCount++;
+	}
+
+	Menu_ShowItem(hMainMenuItem, netProtoCount != 0);
+	return 0;
+}
-- 
cgit v1.2.3