diff options
Diffstat (limited to 'plugins/QuickContacts/src')
| -rw-r--r-- | plugins/QuickContacts/src/commons.h | 107 | ||||
| -rw-r--r-- | plugins/QuickContacts/src/options.cpp | 164 | ||||
| -rw-r--r-- | plugins/QuickContacts/src/options.h | 65 | ||||
| -rw-r--r-- | plugins/QuickContacts/src/quickcontacts.cpp | 1285 | ||||
| -rw-r--r-- | plugins/QuickContacts/src/resource.h | 47 | 
5 files changed, 1668 insertions, 0 deletions
diff --git a/plugins/QuickContacts/src/commons.h b/plugins/QuickContacts/src/commons.h new file mode 100644 index 0000000000..c53689f1cd --- /dev/null +++ b/plugins/QuickContacts/src/commons.h @@ -0,0 +1,107 @@ +/* 
 +Copyright (C) 2006 Ricardo Pescuma Domenecci
 +Based on work (C) Heiko Schillinger
 +
 +This is free software; you can redistribute it and/or
 +modify it under the terms of the GNU Library General Public
 +License as published by the Free Software Foundation; either
 +version 2 of the License, or (at your option) any later version.
 +
 +This 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
 +Library General Public License for more details.
 +
 +You should have received a copy of the GNU Library General Public
 +License along with this file; see the file license.txt.  If
 +not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
 +Boston, MA 02111-1307, USA.  
 +*/
 +
 +
 +#ifndef __COMMONS_H__
 +# define __COMMONS_H__
 +
 +
 +#define WINVER 0x0500
 +#include <windows.h>
 +#include <commctrl.h>
 +#include <stdio.h>
 +#include <tchar.h>
 +
 +
 +// Miranda headers
 +#define MIRANDA_VER 0x0A00
 +#include <newpluginapi.h>
 +#include <m_system.h>
 +#include <m_system_cpp.h>
 +#include <m_protocols.h>
 +#include <m_protosvc.h>
 +#include <m_clist.h>
 +#include <m_ignore.h>
 +#include <m_contacts.h>
 +#include <m_message.h>
 +#include <m_userinfo.h>
 +#include <m_skin.h>
 +#include <m_langpack.h>
 +#include <m_database.h>
 +#include <m_options.h>
 +#include <m_utils.h>
 +#include <m_button.h>
 +#include <m_file.h>
 +#include <m_url.h>
 +#include <m_history.h>
 +#include <m_metacontacts.h>
 +#include <m_MagneticWindows.h>
 +#include <m_popup.h>
 +#include <m_voice.h>
 +#include <m_voiceservice.h>
 +#include <m_icolib.h>
 +#include <m_hotkeys.h>
 +
 +#include "../utils/mir_memory.h"
 +#include "../utils/mir_options.h"
 +#include "../utils/utf8_helpers.h"
 +
 +#include "resource.h"
 +#include "m_quickcontacts.h"
 +#include "options.h"
 +
 +
 +#define MODULE_NAME		"QuickContacts"
 +
 +
 +// Global Variables
 +extern HINSTANCE hInst;
 +extern char *metacontacts_proto;
 +
 +
 +#define MAX_REGS(_A_) ( sizeof(_A_) / sizeof(_A_[0]) )
 +
 +
 +
 +
 +
 +// Copied from "../modernb/clc.h" ///////////////////////////////////////////////////////////////////
 +
 +//add a new hotkey so it has a default and can be changed in the options dialog
 +//wParam=0
 +//lParam=(LPARAM)(SKINHOTKEYDESC*)ssd;
 +//returns 0 on success, nonzero otherwise
 +
 +typedef struct {
 +	int cbSize;
 +	const char *pszName;		   //name to refer to sound when playing and in db
 +	const char *pszDescription;	   //description for options dialog
 +    const char *pszSection;        //section name used to group sounds (NULL is acceptable)
 +	const char *pszService;        //Service to call when HotKey Pressed
 +
 +	int DefHotKey; //default hot key for action
 +} SKINHOTKEYDESCEX;
 +
 +#define MS_SKIN_ADDHOTKEY      "Skin/HotKeys/AddNew"
 +#define MS_SKIN_PLAYHOTKEY		"Skin/HotKeys/Run"
 +
 +
 +
 +#endif // __COMMONS_H__
 diff --git a/plugins/QuickContacts/src/options.cpp b/plugins/QuickContacts/src/options.cpp new file mode 100644 index 0000000000..6154a03ba5 --- /dev/null +++ b/plugins/QuickContacts/src/options.cpp @@ -0,0 +1,164 @@ +/* 
 +Copyright (C) 2006 Ricardo Pescuma Domenecci
 +Based on work (C) Heiko Schillinger
 +
 +This is free software; you can redistribute it and/or
 +modify it under the terms of the GNU Library General Public
 +License as published by the Free Software Foundation; either
 +version 2 of the License, or (at your option) any later version.
 +
 +This 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
 +Library General Public License for more details.
 +
 +You should have received a copy of the GNU Library General Public
 +License along with this file; see the file license.txt.  If
 +not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
 +Boston, MA 02111-1307, USA.  
 +*/
 +
 +
 +#include "options.h"
 +
 +
 +
 +// Prototypes /////////////////////////////////////////////////////////////////////////////////////
 +
 +HANDLE hOptHook = NULL;
 +
 +
 +Options opts;
 +
 +static INT_PTR CALLBACK OptionsDlgProc(HWND hwndDlg, UINT msg, WPARAM wParam, LPARAM lParam);
 +
 +
 +
 +// Functions //////////////////////////////////////////////////////////////////////////////////////
 +
 +
 +// Initializations needed by options
 +void LoadOptions()
 +{
 +	opts.last_sent_enable = DBGetContactSettingByte(NULL, MODULE_NAME, "EnableLastSentTo", TRUE);
 +	opts.last_sent_msg_type = DBGetContactSettingWord(NULL, MODULE_NAME, "MsgTypeRec", TYPE_GLOBAL);
 +	opts.hide_from_offline_proto = DBGetContactSettingByte(NULL, MODULE_NAME, "HideOfflineFromOfflineProto", TRUE);
 +	opts.group_append = DBGetContactSettingByte(NULL, MODULE_NAME, "AppendGroupName", FALSE);
 +	opts.group_column = DBGetContactSettingByte(NULL, MODULE_NAME, "GroupColumn", FALSE);
 +	opts.group_column_left = DBGetContactSettingByte(NULL, MODULE_NAME, "GroupColumnLeft", FALSE);
 +	opts.hide_subcontacts = DBGetContactSettingByte(NULL, MODULE_NAME, "HideSubcontacts", TRUE);
 +	opts.keep_subcontacts_from_offline = DBGetContactSettingByte(NULL, MODULE_NAME, "KeepSubcontactsFromOffline", TRUE);
 +}
 +
 +int InitOptionsCallback(WPARAM wParam,LPARAM lParam)
 +{
 +	OPTIONSDIALOGPAGE odp;
 +
 +	ZeroMemory(&odp,sizeof(odp));
 +    odp.cbSize=sizeof(odp);
 +    odp.position=0;
 +	odp.hInstance=hInst;
 +	odp.ptszGroup = LPGENT("Plugins");
 +	odp.ptszTitle = LPGENT("Quick Contacts");
 +	odp.pfnDlgProc = OptionsDlgProc;
 +	odp.pszTemplate = MAKEINTRESOURCEA(IDD_OPT);
 +    odp.flags = ODPF_BOLDGROUPS | ODPF_EXPERTONLY | ODPF_TCHAR;
 +	Options_AddPage(wParam,&odp);
 +
 +	return 0;
 +}
 +
 +
 +void InitOptions()
 +{
 +	LoadOptions();
 +
 +	hOptHook = HookEvent(ME_OPT_INITIALISE, InitOptionsCallback);
 +}
 +
 +// Deinitializations needed by options
 +void DeInitOptions()
 +{
 +	UnhookEvent(hOptHook);
 +}
 +
 +// Options page
 +
 +static OptPageControl controls[] = { 
 +	{ NULL, CONTROL_CHECKBOX,		IDC_LASTSENTTO,		"EnableLastSentTo",				(BYTE) TRUE },
 +	{ NULL, CONTROL_RADIO,			IDC_GLOBAL,			"MsgTypeRec",					(WORD) TYPE_GLOBAL, TYPE_GLOBAL },
 +	{ NULL, CONTROL_RADIO,			IDC_LOCAL,			"MsgTypeRec",					(WORD) TYPE_GLOBAL, TYPE_LOCAL },
 +	{ NULL, CONTROL_PROTOCOL_LIST,	IDC_PROTOCOLS,		"ShowOffline%s",				(BYTE) FALSE },
 +	{ NULL, CONTROL_CHECKBOX,		IDC_HIDE_OFFLINE,	"HideOfflineFromOfflineProto",	(BYTE) TRUE },
 +	{ NULL, CONTROL_CHECKBOX,		IDC_APPEND_GROUP,	"AppendGroupName",				(BYTE) FALSE },
 +	{ NULL, CONTROL_CHECKBOX,		IDC_GROUP_COLUMN,	"GroupColumn",					(BYTE) FALSE },
 +	{ NULL, CONTROL_CHECKBOX,		IDC_GROUP_LEFT,		"GroupColumnLeft",				(BYTE) FALSE },
 +	{ NULL, CONTROL_CHECKBOX,		IDC_SUBCONTACTS,	"HideSubcontacts",				(BYTE) TRUE },
 +	{ NULL, CONTROL_CHECKBOX,		IDC_KEEP_OFFLINE,	"KeepSubcontactsFromOffline",	(BYTE) TRUE }
 +};
 +
 +static INT_PTR CALLBACK OptionsDlgProc(HWND hwndDlg, UINT msg, WPARAM wParam, LPARAM lParam) 
 +{
 +	int ret = SaveOptsDlgProc(controls, MAX_REGS(controls), MODULE_NAME, hwndDlg, msg, wParam, lParam);
 +
 +	switch (msg) 
 +	{
 +		case WM_INITDIALOG:
 +		{
 +			BOOL enabled = IsDlgButtonChecked(hwndDlg, IDC_LASTSENTTO);
 +			EnableWindow(GetDlgItem(hwndDlg, IDC_GLOBAL), enabled);
 +			EnableWindow(GetDlgItem(hwndDlg, IDC_LOCAL), enabled);
 +			
 +			enabled = IsDlgButtonChecked(hwndDlg, IDC_SUBCONTACTS);
 +			EnableWindow(GetDlgItem(hwndDlg, IDC_KEEP_OFFLINE), enabled);
 +
 +			if (metacontacts_proto == NULL)
 +			{
 +				ShowWindow(GetDlgItem(hwndDlg, IDC_SUBCONTACTS), SW_HIDE);
 +				ShowWindow(GetDlgItem(hwndDlg, IDC_KEEP_OFFLINE), SW_HIDE);
 +			}
 +
 +			return TRUE;
 +		}
 +		case WM_COMMAND:
 +		{
 +			if(LOWORD(wParam) == IDC_LASTSENTTO)
 +			{
 +				BOOL enabled = IsDlgButtonChecked(hwndDlg, IDC_LASTSENTTO);
 +				EnableWindow(GetDlgItem(hwndDlg, IDC_GLOBAL), enabled);
 +				EnableWindow(GetDlgItem(hwndDlg, IDC_LOCAL), enabled);
 +			}
 +
 +			if(LOWORD(wParam) == IDC_SUBCONTACTS)
 +			{
 +				BOOL enabled = IsDlgButtonChecked(hwndDlg, IDC_SUBCONTACTS);
 +				EnableWindow(GetDlgItem(hwndDlg, IDC_KEEP_OFFLINE), enabled);
 +			}
 +
 +			break;
 +		}
 +		case WM_NOTIFY:
 +		{
 +			switch (((LPNMHDR)lParam)->idFrom) 
 +			{
 +				case 0:
 +				{
 +					switch (((LPNMHDR)lParam)->code)
 +					{
 +						case PSN_APPLY:
 +						{
 +							LoadOptions();
 +
 +							return TRUE;
 +						}
 +					}
 +					break;
 +				}
 +			}
 +			break;
 +		}
 +	}
 +
 +	return ret;
 +}
 +
 diff --git a/plugins/QuickContacts/src/options.h b/plugins/QuickContacts/src/options.h new file mode 100644 index 0000000000..1036261bbb --- /dev/null +++ b/plugins/QuickContacts/src/options.h @@ -0,0 +1,65 @@ +/* 
 +Copyright (C) 2006 Ricardo Pescuma Domenecci
 +Based on work (C) Heiko Schillinger
 +
 +This is free software; you can redistribute it and/or
 +modify it under the terms of the GNU Library General Public
 +License as published by the Free Software Foundation; either
 +version 2 of the License, or (at your option) any later version.
 +
 +This 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
 +Library General Public License for more details.
 +
 +You should have received a copy of the GNU Library General Public
 +License along with this file; see the file license.txt.  If
 +not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
 +Boston, MA 02111-1307, USA.  
 +*/
 +
 +
 +#ifndef __OPTIONS_H__
 +# define __OPTIONS_H__
 +
 +
 +#include "commons.h"
 +
 +#include <windows.h>
 +
 +
 +#define TYPE_GLOBAL 0
 +#define TYPE_LOCAL 1
 +
 +typedef struct 
 +{
 +	BOOL last_sent_enable;
 +	int last_sent_msg_type;
 +	BOOL hide_from_offline_proto;
 +	BOOL hide_subcontacts;
 +	BOOL keep_subcontacts_from_offline;
 +	BOOL group_append;
 +	BOOL group_column;
 +	BOOL group_column_left;
 +
 +	int num_protos;
 +} Options;
 +
 +extern Options opts;
 +
 +
 +// Initializations needed by options
 +void InitOptions();
 +
 +// Deinitializations needed by options
 +void DeInitOptions();
 +
 +
 +// Loads the options from DB
 +// It don't need to be called, except in some rare cases
 +void LoadOptions();
 +
 +
 +
 +
 +#endif // __OPTIONS_H__
 diff --git a/plugins/QuickContacts/src/quickcontacts.cpp b/plugins/QuickContacts/src/quickcontacts.cpp new file mode 100644 index 0000000000..cb120351b0 --- /dev/null +++ b/plugins/QuickContacts/src/quickcontacts.cpp @@ -0,0 +1,1285 @@ +/* 
 +Copyright (C) 2006 Ricardo Pescuma Domenecci
 +Based on work (C) Heiko Schillinger
 +
 +This is free software; you can redistribute it and/or
 +modify it under the terms of the GNU Library General Public
 +License as published by the Free Software Foundation; either
 +version 2 of the License, or (at your option) any later version.
 +
 +This 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
 +Library General Public License for more details.
 +
 +You should have received a copy of the GNU Library General Public
 +License along with this file; see the file license.txt.  If
 +not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
 +Boston, MA 02111-1307, USA.  
 +*/
 +
 +
 +#include "commons.h"
 +
 +
 +// Prototypes ///////////////////////////////////////////////////////////////////////////
 +
 +
 +PLUGININFOEX pluginInfo={
 +	sizeof(PLUGININFOEX),
 +	"Quick Contacts",
 +	PLUGIN_MAKE_VERSION(1,0,0,0),
 +	"Open contact-specific windows by hotkey",
 +	"Ricardo Pescuma Domenecci, Heiko Schillinger",
 +	"pescuma@miranda-im.org",
 +	"© 2007-2009 Ricardo Pescuma Domenecci",
 +	"http://pescuma.org/miranda/quickcontacts",
 +	UNICODE_AWARE,
 +	{ 0xf93ba59c, 0x4f48, 0x4f2e, { 0x8a, 0x91, 0x77, 0xa2, 0x80, 0x15, 0x27, 0xa3 } } // {F93BA59C-4F48-4F2E-8A91-77A2801527A3}
 +};
 +
 +
 +HINSTANCE hInst;
 +HIMAGELIST hIml;
 +int hLangpack = 0;
 +
 +HANDLE hModulesLoaded = NULL;
 +HANDLE hEventAdded = NULL;
 +HANDLE hHotkeyPressed = NULL;
 +HANDLE hQSShowDialog = NULL;
 +
 +long main_dialog_open = 0;
 +HWND hwndMain = NULL;
 +
 +int ModulesLoaded(WPARAM wParam, LPARAM lParam);
 +int EventAdded(WPARAM wparam, LPARAM lparam);
 +int HotkeyPressed(WPARAM wParam, LPARAM lParam);
 +INT_PTR ShowDialog(WPARAM wParam,LPARAM lParam);
 +void FreeContacts();
 +
 +int hksModule = 0;
 +int hksAction = 0;
 +
 +BOOL hasNewHotkeyModule = FALSE;
 +
 +char *metacontacts_proto = NULL;
 +
 +#define IDC_ICO 12344
 +
 +
 +// Functions ////////////////////////////////////////////////////////////////////////////
 +
 +
 +extern "C" BOOL WINAPI DllMain(HINSTANCE hinstDLL, DWORD fdwReason, LPVOID lpvReserved) 
 +{
 +	hInst = hinstDLL;
 +	return TRUE;
 +}
 +
 +
 +extern "C" __declspec(dllexport) PLUGININFOEX* MirandaPluginInfoEx(DWORD mirandaVersion)
 +{
 +	return &pluginInfo;
 +}
 +
 +
 +static const MUUID interfaces[] = { MIID_QUICKCONTACTS, MIID_LAST };
 +extern "C" __declspec(dllexport) const MUUID* MirandaPluginInterfaces(void)
 +{
 +	return interfaces;
 +}
 +
 +
 +extern "C" __declspec(dllexport) int Load() 
 +{
 +	mir_getLP(&pluginInfo);
 +
 +	hQSShowDialog = CreateServiceFunction(MS_QC_SHOW_DIALOG, ShowDialog);
 +
 +	// hooks
 +	hModulesLoaded = HookEvent(ME_SYSTEM_MODULESLOADED, ModulesLoaded);
 +	hEventAdded = HookEvent(ME_DB_EVENT_ADDED, EventAdded);
 +
 +	return 0;
 +}
 +
 +extern "C" __declspec(dllexport) int Unload(void) 
 +{
 +	FreeContacts();
 +
 +	DeInitOptions();
 +
 +	DestroyServiceFunction(hQSShowDialog);
 +
 +	UnhookEvent(hModulesLoaded);
 +	UnhookEvent(hEventAdded);
 +
 +	return 0;
 +}
 +
 +
 +// Called when all the modules are loaded
 +int ModulesLoaded(WPARAM wParam, LPARAM lParam) 
 +{
 +	InitOptions();
 +
 +	// add our modules to the KnownModules list
 +	CallService("DBEditorpp/RegisterSingleModule", (WPARAM) MODULE_NAME, 0);
 +
 +	// Get number of protocols
 +	int pcount = 0;
 +	PROTOACCOUNT** pdesc;
 +
 +	ProtoEnumAccounts(&pcount,&pdesc);
 +
 +	opts.num_protos = 0;
 +	for (int loop=0;loop<pcount;loop++)
 +	{
 +		if (pdesc[loop]->type==PROTOTYPE_PROTOCOL)
 +			opts.num_protos++;
 +	}
 +
 +	// Add hotkey to multiple services
 +
 +	hasNewHotkeyModule = TRUE;
 +
 +	HOTKEYDESC hkd = {0};
 +	hkd.cbSize = sizeof(hkd);
 +	hkd.dwFlags = HKD_TCHAR;
 +	hkd.pszName = "Quick Contacts/Open dialog";
 +	hkd.ptszDescription = LPGENT("Open dialog");
 +	hkd.ptszSection = LPGENT("Quick Contacts");
 +	hkd.pszService = MS_QC_SHOW_DIALOG;
 +	hkd.DefHotKey = HOTKEYCODE(HOTKEYF_CONTROL|HOTKEYF_ALT, 'Q');
 +	Hotkey_Register(&hkd);
 +
 +	hkd.pszService = NULL;
 +
 +	hkd.lParam = HOTKEY_VOICE;
 +	hkd.DefHotKey = HOTKEYCODE(HOTKEYF_CONTROL, 'V');
 +	hkd.pszName = "Quick Contacts/Voice";
 +	hkd.ptszDescription = LPGENT("Make a voice call");
 +	Hotkey_Register(&hkd);
 +
 +	hkd.lParam = HOTKEY_FILE;
 +	hkd.DefHotKey = HOTKEYCODE(HOTKEYF_CONTROL, 'F');
 +	hkd.pszName = "Quick Contacts/File";
 +	hkd.ptszDescription = LPGENT("Send file");
 +	Hotkey_Register(&hkd);
 +
 +	hkd.lParam = HOTKEY_URL;
 +	hkd.DefHotKey = HOTKEYCODE(HOTKEYF_CONTROL, 'U');
 +	hkd.pszName = "Quick Contacts/URL";
 +	hkd.ptszDescription = LPGENT("Send URL");
 +	Hotkey_Register(&hkd);
 +
 +	hkd.lParam = HOTKEY_INFO;
 +	hkd.DefHotKey = HOTKEYCODE(HOTKEYF_CONTROL, 'I');
 +	hkd.pszName = "Quick Contacts/Info";
 +	hkd.ptszDescription = LPGENT("Open userinfo");
 +	Hotkey_Register(&hkd);
 +		
 +	hkd.lParam = HOTKEY_HISTORY;
 +	hkd.DefHotKey = HOTKEYCODE(HOTKEYF_CONTROL, 'H');
 +	hkd.pszName = "Quick Contacts/History";
 +	hkd.ptszDescription = LPGENT("Open history");
 +	Hotkey_Register(&hkd);
 +		
 +	hkd.lParam = HOTKEY_MENU;
 +	hkd.DefHotKey = HOTKEYCODE(HOTKEYF_CONTROL, 'M');
 +	hkd.pszName = "Quick Contacts/Menu";
 +	hkd.ptszDescription = LPGENT("Open contact menu");
 +	Hotkey_Register(&hkd);
 +		
 +	hkd.lParam = HOTKEY_ALL_CONTACTS;
 +	hkd.DefHotKey = HOTKEYCODE(HOTKEYF_CONTROL, 'A');
 +	hkd.pszName = "Quick Contacts/All Contacts";
 +	hkd.ptszDescription = LPGENT("Show all contacts");
 +	Hotkey_Register(&hkd);
 +
 +	if (ServiceExists(MS_SKIN_ADDHOTKEY))
 +	{
 +		SKINHOTKEYDESCEX hk = {0};
 +		hk.cbSize = sizeof(hk);
 +		hk.pszSection = Translate("Quick Contacts");
 +		hk.pszName = Translate("Open dialog");
 +		hk.pszDescription = Translate("Open dialog");
 +		hk.pszService = MS_QC_SHOW_DIALOG;
 +		hk.DefHotKey = 0;
 +		CallService(MS_SKIN_ADDHOTKEY, 0, (LPARAM)&hk);
 +	}
 +
 +	// Get the icons for the listbox
 +	hIml = (HIMAGELIST)CallService(MS_CLIST_GETICONSIMAGELIST,0,0);
 +
 +	// Add menu item
 +	CLISTMENUITEM mi;
 +	ZeroMemory(&mi,sizeof(mi));
 +	mi.cbSize = sizeof(mi);
 +	mi.position = 500100001;
 +	mi.flags = CMIF_TCHAR;
 +	mi.ptszName = LPGENT("Quick Contacts...");
 +	mi.pszService = MS_QC_SHOW_DIALOG;
 +	Menu_AddMainMenuItem(&mi);
 +
 +	if (ServiceExists(MS_MC_GETPROTOCOLNAME) && ServiceExists(MS_MC_GETMETACONTACT))
 +		metacontacts_proto = (char *) CallService(MS_MC_GETPROTOCOLNAME, 0, 0);
 +
 +	return 0;
 +}
 +
 +
 +// called when a message/file/url was sent
 +// handle of contact is set as window-userdata
 +int EventAdded(WPARAM wparam, LPARAM lparam)
 +{
 +	DBEVENTINFO dbei;
 +
 +    ZeroMemory(&dbei,sizeof(dbei));
 +    dbei.cbSize=sizeof(dbei);
 +    dbei.cbBlob=0;
 +    
 +    CallService(MS_DB_EVENT_GET,lparam,(LPARAM)&dbei);
 +    
 +	if(		!(dbei.flags & DBEF_SENT) 
 +			|| dbei.flags & DBEF_READ 
 +			|| !DBGetContactSettingByte(NULL, MODULE_NAME, "EnableLastSentTo", 0) 
 +			|| DBGetContactSettingWord(NULL, MODULE_NAME, "MsgTypeRec", TYPE_GLOBAL) != TYPE_GLOBAL) 
 +		return 0;
 +
 +	DBWriteContactSettingDword(NULL, MODULE_NAME, "LastSentTo", (DWORD)(HANDLE)wparam);
 +	return 0;
 +}
 +
 +
 +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////
 +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////
 +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////
 +
 +
 +#define IDC_ENTER 2000	// Pseudo control to handle enter in the main window
 +
 +
 +// array where the contacts are put into
 +struct c_struct {
 +	TCHAR szname[120];
 +	TCHAR szgroup[50];
 +	HANDLE hcontact;
 +	TCHAR proto[20];
 +
 +	c_struct()
 +	{
 +		szname[0] = 0;
 +		szgroup[0] = 0;
 +		hcontact = 0;
 +		proto[0] = 0;
 +	}
 +};
 +
 +LIST<c_struct> contacts(200);
 +long max_proto_width;
 +
 +
 +// Get the name the contact has in list
 +// This was not made to be called by more than one thread!
 +TCHAR tmp_list_name[120];
 +
 +TCHAR *GetListName(c_struct *cs)
 +{
 +	if (opts.group_append && cs->szgroup[0] != _T('\0'))
 +	{
 +		mir_sntprintf(tmp_list_name, MAX_REGS(tmp_list_name), _T("%s (%s)"), cs->szname, cs->szgroup);
 +		return tmp_list_name;
 +	}
 +	else
 +	{
 +		return cs->szname;
 +	}
 +}
 +
 +
 +int lstreq(TCHAR *a, TCHAR *b, size_t len = -1)
 +{
 +	a = CharLower(_tcsdup(a));
 +	b = CharLower(_tcsdup(b));
 +	int ret;
 +	if (len > 0)
 +		ret = _tcsncmp(a, b, len);
 +	else
 +		ret = _tcscmp(a, b);
 +	free(a);
 +	free(b);
 +	return ret;
 +}
 +
 +
 +// simple sorting function to have
 +// the contact array in alphabetical order
 +void SortArray(void)
 +{
 +	int loop,doop;
 +	c_struct *cs_temp;
 +
 +	SortedList *sl = (SortedList *) &contacts;
 +	for(loop=0;loop<contacts.getCount();loop++)
 +	{
 +		for(doop=loop+1;doop<contacts.getCount();doop++)
 +		{
 +			int cmp = lstreq(contacts[loop]->szname,contacts[doop]->szname);
 +			if (cmp > 0)
 +			{
 +				cs_temp=contacts[loop];
 +				sl->items[loop]=contacts[doop];
 +				sl->items[doop]=cs_temp;
 +			}
 +			else if (cmp == 0)
 +			{
 +				if(lstreq(contacts[loop]->proto, contacts[doop]->proto) > 0)
 +				{
 +					cs_temp=contacts[loop];
 +					sl->items[loop]=contacts[doop];
 +					sl->items[doop]=cs_temp;
 +				}
 +			}
 +
 +		}
 +	}
 +}
 +
 +
 +int GetStatus(HANDLE hContact, char *proto = NULL)
 +{
 +	if (proto == NULL)
 +		proto = (char *) CallService(MS_PROTO_GETCONTACTBASEPROTO, (WPARAM) hContact, 0);
 +
 +	if (proto == NULL)
 +		return ID_STATUS_OFFLINE;
 +
 +	return DBGetContactSettingWord(hContact, proto, "Status", ID_STATUS_OFFLINE);
 +}
 +
 +
 +void FreeContacts()
 +{
 +	for (int i = contacts.getCount() - 1; i >= 0; i--)
 +	{
 +		delete contacts[i];
 +		contacts.remove(i);
 +	}
 +}
 +
 +
 +void LoadContacts(HWND hwndDlg, BOOL show_all)
 +{
 +	BOOL metacontactsEnabled = (metacontacts_proto != NULL
 +				 && DBGetContactSettingByte(0, metacontacts_proto, "Enabled", 1));
 +
 +	// Read last-sent-to contact from db and set handle as window-userdata
 +	HANDLE hlastsent = (HANDLE)DBGetContactSettingDword(NULL, MODULE_NAME, "LastSentTo", -1);
 +	SetWindowLongPtr(hwndMain, GWLP_USERDATA, (LONG)hlastsent);
 +
 +	// enumerate all contacts and write them to the array
 +	// item data of listbox-strings is the array position
 +	FreeContacts();
 +	for(HANDLE hContact = (HANDLE)CallService(MS_DB_CONTACT_FINDFIRST,0,0); 
 +		hContact != NULL; 
 +		hContact = (HANDLE)CallService(MS_DB_CONTACT_FINDNEXT,(WPARAM)hContact,0))
 +	{
 +		char *pszProto = (char *) CallService(MS_PROTO_GETCONTACTBASEPROTO, (WPARAM)hContact, 0);
 +		if(pszProto != NULL)
 +		{
 +			// Get meta
 +			HANDLE hMeta = NULL;
 +			if (metacontactsEnabled)
 +			{
 +				if ((!show_all && opts.hide_subcontacts) || opts.group_append)
 +					hMeta = (HANDLE) CallService(MS_MC_GETMETACONTACT, (WPARAM)hContact, 0);
 +			}
 +			else
 +			{
 +				if (metacontacts_proto != NULL && strcmp(metacontacts_proto, pszProto) == 0)
 +					continue;
 +			}
 +
 +
 +			if (!show_all)
 +			{
 +				// Check if is offline and have to show
 +				if (GetStatus(hContact, pszProto) <= ID_STATUS_OFFLINE)
 +				{
 +					// See if has to show
 +					char setting[128];
 +					mir_snprintf(setting, sizeof(setting), "ShowOffline%s", pszProto);
 +
 +					if (!DBGetContactSettingByte(NULL, MODULE_NAME, setting, FALSE))
 +						continue;
 +
 +					// Check if proto offline
 +					else if (opts.hide_from_offline_proto 
 +							&& CallProtoService(pszProto, PS_GETSTATUS, 0, 0) <= ID_STATUS_OFFLINE)
 +						continue;
 +
 +				}
 +
 +				// Check if is subcontact
 +				if (opts.hide_subcontacts && hMeta != NULL) 
 +				{
 +					if (!opts.keep_subcontacts_from_offline)
 +						continue;
 +
 +					if (GetStatus(hMeta, metacontacts_proto) > ID_STATUS_OFFLINE)
 +					{
 +						continue;
 +					}
 +					else 
 +					{
 +						char setting[128];
 +						mir_snprintf(setting, sizeof(setting), "ShowOffline%s", metacontacts_proto);
 +						if (DBGetContactSettingByte(NULL, MODULE_NAME, setting, FALSE))
 +							continue;
 +					}
 +				}
 +			}
 +
 +			// Add to list
 +
 +			// Get group
 +			c_struct *contact = new c_struct();
 +			
 +			if (opts.group_append)
 +			{
 +				DBVARIANT dbv;
 +				if (DBGetContactSettingTString(hMeta == NULL ? hContact : hMeta, "CList", "Group", &dbv) == 0)
 +				{
 +					if (dbv.ptszVal != NULL)
 +						lstrcpyn(contact->szgroup, dbv.ptszVal, MAX_REGS(contact->szgroup));
 +
 +					DBFreeVariant(&dbv);
 +				}
 +			}
 +
 +			// Make contact name
 +			TCHAR *tmp = (TCHAR *) CallService(MS_CLIST_GETCONTACTDISPLAYNAME, (WPARAM) hContact, GCDNF_TCHAR);
 +			lstrcpyn(contact->szname, tmp, MAX_REGS(contact->szname));
 +
 +			PROTOACCOUNT *acc = ProtoGetAccount(pszProto);
 +			if (acc != NULL)
 +			{
 +				lstrcpyn(contact->proto, acc->tszAccountName, MAX_REGS(contact->proto));
 +			}
 +
 +			contact->hcontact = hContact;
 +
 +			contacts.insert(contact);
 +		}
 +	}
 +
 +	SortArray();
 +			
 +	SendDlgItemMessage(hwndDlg, IDC_USERNAME, CB_RESETCONTENT, 0, 0);
 +	for(int loop = 0; loop < contacts.getCount(); loop++)
 +	{
 +		SendDlgItemMessage(hwndDlg, IDC_USERNAME, CB_SETITEMDATA, 
 +							(WPARAM)SendDlgItemMessage(hwndDlg, IDC_USERNAME, 
 +											CB_ADDSTRING, 0, (LPARAM) GetListName(contacts[loop])), 
 +							(LPARAM)loop);
 +	}
 +}
 +
 +
 +// Enable buttons for the selected contact
 +void EnableButtons(HWND hwndDlg, HANDLE hContact)
 +{
 +	if (hContact == NULL)
 +	{
 +		EnableWindow(GetDlgItem(hwndDlg, IDC_MESSAGE), FALSE);
 +		EnableWindow(GetDlgItem(hwndDlg, IDC_VOICE), FALSE);
 +		EnableWindow(GetDlgItem(hwndDlg, IDC_FILE), FALSE);
 +		EnableWindow(GetDlgItem(hwndDlg, IDC_URL), FALSE);
 +		EnableWindow(GetDlgItem(hwndDlg, IDC_USERINFO), FALSE);
 +		EnableWindow(GetDlgItem(hwndDlg, IDC_HISTORY), FALSE);
 +		EnableWindow(GetDlgItem(hwndDlg, IDC_MENU), FALSE);
 +
 +		SendMessage(GetDlgItem(hwndDlg, IDC_ICO), STM_SETICON, 0, 0);
 +	}
 +	else
 +	{
 +		// Is a meta?
 +		if (ServiceExists(MS_MC_GETMOSTONLINECONTACT)) 
 +		{
 +			HANDLE hSub = (HANDLE) CallService(MS_MC_GETMOSTONLINECONTACT, (WPARAM) hContact, 0);
 +			if (hSub != NULL)
 +				hContact = hSub;
 +		}
 +
 +		// Get caps
 +		INT_PTR caps = 0;
 +
 +		char *pszProto = (char *) CallService(MS_PROTO_GETCONTACTBASEPROTO, (WPARAM)hContact, 0);
 +		if (pszProto != NULL)
 +			caps = CallProtoService(pszProto, PS_GETCAPS, PFLAGNUM_1, 0);
 +
 +		BOOL voice = (ServiceExists(MS_VOICESERVICE_CAN_CALL) 
 +			&& CallService(MS_VOICESERVICE_CAN_CALL, (WPARAM)hContact, 0) > 0);
 +
 +		EnableWindow(GetDlgItem(hwndDlg, IDC_MESSAGE), caps & PF1_IMSEND ? TRUE : FALSE);
 +		EnableWindow(GetDlgItem(hwndDlg, IDC_VOICE), voice);
 +		EnableWindow(GetDlgItem(hwndDlg, IDC_FILE), caps & PF1_FILESEND ? TRUE : FALSE);
 +		EnableWindow(GetDlgItem(hwndDlg, IDC_URL), caps & PF1_URLSEND ? TRUE : FALSE);
 +		EnableWindow(GetDlgItem(hwndDlg, IDC_USERINFO), TRUE);
 +		EnableWindow(GetDlgItem(hwndDlg, IDC_HISTORY), TRUE);
 +		EnableWindow(GetDlgItem(hwndDlg, IDC_MENU), TRUE);
 +
 +		HICON ico = ImageList_GetIcon(hIml, CallService(MS_CLIST_GETCONTACTICON, (WPARAM) hContact, 0), ILD_IMAGE);
 +		SendMessage(GetDlgItem(hwndDlg, IDC_ICO), STM_SETICON, (WPARAM) ico, 0);
 +	}
 +}
 +
 +
 +// check if the char(s) entered appears in a contacts name
 +int CheckText(HWND hdlg, TCHAR *sztext, BOOL only_enable = FALSE)
 +{
 +	EnableButtons(hwndMain, NULL);
 +
 +	if(sztext == NULL || sztext[0] == _T('\0'))
 +		return 0;
 +
 +	int len = lstrlen(sztext);
 +
 +	if (only_enable)
 +	{
 +		for(int loop=0;loop<contacts.getCount();loop++)
 +		{
 +			if(lstreq(sztext, contacts[loop]->szname)==0 || lstreq(sztext, GetListName(contacts[loop]))==0)
 +			{
 +				EnableButtons(hwndMain, contacts[loop]->hcontact);
 +				return 0;
 +			}
 +		}
 +	}
 +	else
 +	{
 +		for(int loop=0;loop<contacts.getCount();loop++)
 +		{
 +			if (lstreq(sztext, GetListName(contacts[loop]), len) == 0)
 +			{
 +				SendMessage(hdlg, WM_SETTEXT, 0, (LPARAM) GetListName(contacts[loop]));
 +				SendMessage(hdlg, EM_SETSEL, (WPARAM) len, (LPARAM) -1);
 +				EnableButtons(hwndMain, contacts[loop]->hcontact);
 +				return 0;
 +			}
 +		}
 +	}
 +
 +	EnableButtons(hwndMain, NULL);
 +	return 0;
 +}
 +
 +HANDLE GetSelectedContact(HWND hwndDlg)
 +{
 +	// First try selection
 +	int sel = SendDlgItemMessage(hwndDlg, IDC_USERNAME, CB_GETCURSEL, 0, 0);
 +
 +	if (sel != CB_ERR)
 +	{
 +		int pos = SendDlgItemMessage(hwndDlg, IDC_USERNAME, CB_GETITEMDATA, sel, 0);
 +		if (pos != CB_ERR)
 +			return contacts[pos]->hcontact;
 +	}
 +
 +	// Now try the name
 +	TCHAR cname[120] = _T("");
 +
 +	GetDlgItemText(hwndDlg, IDC_USERNAME, cname, MAX_REGS(cname));
 +			
 +	for(int loop = 0; loop < contacts.getCount(); loop++)
 +	{
 +		if(!lstrcmpi(cname, GetListName(contacts[loop])))
 +			return contacts[loop]->hcontact;
 +	}
 +
 +	return NULL;
 +}
 +
 +// get array position from handle
 +int GetItemPos(HANDLE hcontact)
 +{
 +	int loop;
 +
 +	for(loop=0;loop<contacts.getCount();loop++)
 +	{
 +		if(hcontact==contacts[loop]->hcontact)
 +			return loop;
 +	}
 +	return -1;
 +}
 +
 +
 +WNDPROC wpEditMainProc;
 +
 +// callback function for edit-box of the listbox
 +// without this the autofill function isn't possible
 +// this was done like ie does it..as far as spy++ could tell ;)
 +LRESULT CALLBACK EditProc(HWND hdlg,UINT msg,WPARAM wparam,LPARAM lparam)
 +{
 +	switch(msg)
 +	{
 +		case WM_CHAR:
 +		{
 +			if (wparam<32 && wparam != VK_BACK) 
 +				break;
 +
 +			TCHAR sztext[120] = _T("");
 +			DWORD start;
 +			DWORD end;
 +
 +			int ret = SendMessage(hdlg,EM_GETSEL,(WPARAM)&start,(LPARAM)&end);
 +
 +			SendMessage(hdlg,WM_GETTEXT,(WPARAM)MAX_REGS(sztext),(LPARAM)sztext);
 +
 +			BOOL at_end = (lstrlen(sztext) == (int)end);
 +
 +			if (ret != -1)
 +			{
 +				if (wparam == VK_BACK)
 +				{
 +					if (start > 0)
 +						SendMessage(hdlg,EM_SETSEL,(WPARAM)start-1,(LPARAM)end);
 +
 +					sztext[0]=0;
 +				}
 +				else
 +				{
 +					sztext[0]=wparam;
 +					sztext[1]=0;
 +				}
 +
 +				SendMessage(hdlg,EM_REPLACESEL,(WPARAM)0,(LPARAM)sztext);
 +				SendMessage(hdlg,WM_GETTEXT,(WPARAM)MAX_REGS(sztext),(LPARAM)sztext);
 +			}
 +
 +			CheckText(hdlg, sztext, !at_end);
 +
 +			return 1;
 +		}
 +		case WM_KEYUP:
 +		{
 +			TCHAR sztext[120] = _T("");
 +
 +			if (wparam == VK_RETURN)
 +			{
 +				switch(SendMessage(GetParent(hdlg),CB_GETDROPPEDSTATE,0,0))
 +				{
 +					case FALSE:
 +						SendMessage(GetParent(GetParent(hdlg)),WM_COMMAND,MAKEWPARAM(IDC_ENTER,STN_CLICKED),0);
 +						break;
 +
 +					case TRUE:
 +						SendMessage(GetParent(hdlg),CB_SHOWDROPDOWN,(WPARAM)FALSE,0);
 +						break;
 +				}
 +			}
 +			else if (wparam == VK_DELETE)
 +			{
 +				SendMessage(hdlg,WM_GETTEXT,(WPARAM)MAX_REGS(sztext),(LPARAM)sztext);
 +				CheckText(hdlg, sztext, TRUE);
 +			}
 +
 +			return 0;
 +		}
 +		case WM_GETDLGCODE:
 +			return DLGC_WANTCHARS|DLGC_WANTARROWS;
 +
 +	}
 +
 +	return CallWindowProc(wpEditMainProc,hdlg,msg,wparam,lparam);
 +}
 +
 +
 +HACCEL hAcct;
 +HHOOK hHook;
 +
 +// This function filters the message queue and translates
 +// the keyboard accelerators
 +LRESULT CALLBACK HookProc(int code, WPARAM wparam, LPARAM lparam)
 +{
 +	if (code!=MSGF_DIALOGBOX) 
 +		return 0;
 +
 +	MSG *msg = (MSG*)lparam;
 +
 +
 +	if (hasNewHotkeyModule)
 +	{
 +		int action = CallService(MS_HOTKEY_CHECK, (WPARAM) msg, (LPARAM) "Quick Contacts");
 +		if (action != 0)
 +		{
 +			SendMessage(hwndMain, WM_COMMAND, action, 0);
 +			return 1;
 +		}
 +	}
 +	else
 +	{
 +		HWND htemp = msg->hwnd;
 +		msg->hwnd = hwndMain;
 +
 +		if (TranslateAccelerator(msg->hwnd, hAcct, msg))
 +			return 1;
 +		
 +		msg->hwnd=htemp;
 +	}
 +
 +	if (msg->message == WM_KEYDOWN && msg->wParam == VK_ESCAPE)
 +	{
 +		switch(SendMessage(GetDlgItem(hwndMain, IDC_USERNAME), CB_GETDROPPEDSTATE, 0, 0))
 +		{
 +			case FALSE:
 +				SendMessage(hwndMain, WM_CLOSE, 0, 0);
 +				break;
 +
 +			case TRUE:
 +				SendMessage(GetDlgItem(hwndMain, IDC_USERNAME), CB_SHOWDROPDOWN, (WPARAM)FALSE, 0);
 +				break;
 +		}
 +	}
 +	
 +	return 0;
 +}
 +
 +BOOL ScreenToClient(HWND hWnd, LPRECT lpRect)
 +{
 +	BOOL ret;
 +
 +	POINT pt;
 +
 +	pt.x = lpRect->left;
 +	pt.y = lpRect->top;
 +
 +	ret = ScreenToClient(hWnd, &pt);
 +
 +	if (!ret) return ret;
 +
 +	lpRect->left = pt.x;
 +	lpRect->top = pt.y;
 +
 +
 +	pt.x = lpRect->right;
 +	pt.y = lpRect->bottom;
 +
 +	ret = ScreenToClient(hWnd, &pt);
 +
 +	lpRect->right = pt.x;
 +	lpRect->bottom = pt.y;
 +
 +	return ret;
 +}
 +
 +
 +BOOL MoveWindow(HWND hWnd, const RECT &rect, BOOL bRepaint)
 +{
 +	return MoveWindow(hWnd, rect.left, rect.top, rect.right - rect.left, rect.bottom - rect.top, bRepaint);
 +}
 +
 +
 +static void FillButton(HWND hwndDlg, int dlgItem, TCHAR *name, TCHAR *key, HICON icon)
 +{
 +	TCHAR tmp[256];
 +	TCHAR *full;
 +	if (key == NULL)
 +		full = TranslateTS(name);
 +	else
 +		mir_sntprintf(full = tmp, MAX_REGS(tmp), _T("%s (%s)"), TranslateTS(name), key);
 +
 +	SendMessage(GetDlgItem(hwndDlg, dlgItem), BUTTONSETASFLATBTN, 0, 0);
 +	SendMessage(GetDlgItem(hwndDlg, dlgItem), BUTTONADDTOOLTIP, (LPARAM) full, BATF_TCHAR);
 +	SendDlgItemMessage(hwndDlg, dlgItem, BM_SETIMAGE, IMAGE_ICON, (LPARAM) icon);
 +}
 +
 +
 +static void FillCheckbox(HWND hwndDlg, int dlgItem, TCHAR *name, TCHAR *key)
 +{
 +	TCHAR tmp[256];
 +	TCHAR *full;
 +	if (key == NULL)
 +		full = TranslateTS(name);
 +	else
 +		mir_sntprintf(full = tmp, MAX_REGS(tmp), _T("%s (%s)"), TranslateTS(name), key);
 +
 +	SendMessage(GetDlgItem(hwndDlg, dlgItem), WM_SETTEXT, 0, (LPARAM) full);
 +}
 +
 +
 +static INT_PTR CALLBACK MainDlgProc(HWND hwndDlg, UINT msg, WPARAM wParam, LPARAM lParam)
 +{
 +	switch (msg)
 +	{
 +		case WM_INITDIALOG:
 +		{
 +			TranslateDialogDefault(hwndDlg);
 +
 +			RECT rc;
 +			GetWindowRect(GetDlgItem(hwndDlg, IDC_USERNAME), &rc);
 +			ScreenToClient(hwndDlg, &rc);
 +
 +			HWND icon = CreateWindow(_T("STATIC"), _T(""), WS_CHILD | WS_VISIBLE | SS_ICON | SS_CENTERIMAGE, 
 +                    rc.left - 20, rc.top + (rc.bottom - rc.top - 16) / 2, 16, 16, hwndDlg, (HMENU) IDC_ICO, 
 +					hInst, NULL);
 +
 +			if (!hasNewHotkeyModule)
 +				hAcct = LoadAccelerators(hInst, MAKEINTRESOURCE(ACCEL_TABLE));
 +
 +			hHook = SetWindowsHookEx(WH_MSGFILTER, HookProc, hInst, GetCurrentThreadId());
 +
 +			// Combo
 +			SendMessage(GetDlgItem(hwndDlg, IDC_USERNAME), EM_LIMITTEXT, (WPARAM)119,0);
 +			wpEditMainProc = (WNDPROC) SetWindowLongPtr(GetWindow(GetDlgItem(hwndDlg, IDC_USERNAME),GW_CHILD), GWLP_WNDPROC, (LONG)EditProc);
 +
 +			// Buttons
 +			FillCheckbox(hwndDlg, IDC_SHOW_ALL_CONTACTS, LPGENT("Show all contacts"), hasNewHotkeyModule ? NULL : LPGENT("Ctrl+A"));
 +			FillButton(hwndDlg, IDC_MESSAGE, LPGENT("Send message"), NULL, LoadSkinnedIcon(SKINICON_EVENT_MESSAGE));
 +
 +			if (ServiceExists(MS_VOICESERVICE_CAN_CALL))
 +			{
 +				FillButton(hwndDlg, IDC_VOICE, LPGENT("Make a voice call"), hasNewHotkeyModule ? NULL : LPGENT("Ctrl+V"), (HICON) CallService(MS_SKIN2_GETICON, 0, (LPARAM) "vca_call"));
 +			}
 +			else
 +			{
 +				GetWindowRect(GetDlgItem(hwndDlg, IDC_VOICE), &rc);
 +				ScreenToClient(hwndDlg, &rc);
 +				MoveWindow(GetDlgItem(hwndDlg, IDC_MESSAGE), rc, FALSE);
 +				ShowWindow(GetDlgItem(hwndDlg, IDC_VOICE), SW_HIDE);
 +			}
 +
 +			FillButton(hwndDlg, IDC_FILE, LPGENT("Send file"), hasNewHotkeyModule ? NULL : LPGENT("Ctrl+F"), LoadSkinnedIcon(SKINICON_EVENT_FILE));
 +			FillButton(hwndDlg, IDC_URL, LPGENT("Send URL"), hasNewHotkeyModule ? NULL : LPGENT("Ctrl+U"), LoadSkinnedIcon(SKINICON_EVENT_URL));
 +			FillButton(hwndDlg, IDC_USERINFO, LPGENT("Open userinfo"), hasNewHotkeyModule ? NULL : LPGENT("Ctrl+I"), LoadSkinnedIcon(SKINICON_OTHER_USERDETAILS));
 +			FillButton(hwndDlg, IDC_HISTORY, LPGENT("Open history"), hasNewHotkeyModule ? NULL : LPGENT("Ctrl+H"), LoadSkinnedIcon(SKINICON_OTHER_HISTORY));
 +			FillButton(hwndDlg, IDC_MENU, LPGENT("Open contact menu"), hasNewHotkeyModule ? NULL : LPGENT("Ctrl+M"), LoadSkinnedIcon(SKINICON_OTHER_DOWNARROW));
 +
 +			SendDlgItemMessage(hwndDlg, IDC_USERNAME, CB_SETEXTENDEDUI, (WPARAM)TRUE, 0);
 +
 +			MagneticWindows_AddWindow(hwndDlg);
 +
 +			Utils_RestoreWindowPositionNoSize(hwndDlg, NULL, MODULE_NAME, "window");
 +
 +			LoadContacts(hwndDlg, FALSE);
 +
 +			EnableButtons(hwndDlg, NULL);
 +			if (DBGetContactSettingByte(NULL, MODULE_NAME, "EnableLastSentTo", 0))
 +			{
 +				int pos = GetItemPos((HANDLE) DBGetContactSettingDword(NULL, MODULE_NAME, "LastSentTo", -1));
 +
 +				if (pos != -1)
 +				{
 +					SendDlgItemMessage(hwndDlg, IDC_USERNAME, CB_SETCURSEL, (WPARAM) pos, 0);
 +					EnableButtons(hwndDlg, contacts[pos]->hcontact);
 +				}
 +			}
 +
 +			SetFocus(GetDlgItem(hwndDlg, IDC_USERNAME));
 +
 +			return TRUE;
 +		}
 +
 +		case WM_COMMAND:
 +		{
 +			switch(LOWORD(wParam))
 +			{
 +				case IDC_USERNAME:
 +				{
 +					if (HIWORD(wParam) == CBN_SELCHANGE)
 +					{
 +						int pos = SendDlgItemMessage(hwndDlg, IDC_USERNAME, CB_GETCURSEL, 0, 0);
 +						EnableButtons(hwndDlg, pos < contacts.getCount() ? contacts[pos]->hcontact : NULL);
 +					}
 +					break;
 +				}
 +				case IDC_ENTER:
 +				{
 +					HANDLE hContact = GetSelectedContact(hwndDlg);
 +					if (hContact == NULL)
 +						break;
 +
 +					CallService(MS_CLIST_CONTACTDOUBLECLICKED, (WPARAM) hContact, 0);
 +
 +					DBWriteContactSettingDword(NULL, MODULE_NAME, "LastSentTo", (DWORD) hContact);
 +					SendMessage(hwndDlg, WM_CLOSE, 0, 0);
 +					break;
 +				}
 +				case IDC_MESSAGE:
 +				{
 +					HANDLE hContact = GetSelectedContact(hwndDlg);
 +					if (hContact == NULL)
 +					{
 +						SetDlgItemText(hwndDlg, IDC_USERNAME, _T(""));
 +						SetFocus(GetDlgItem(hwndDlg, IDC_USERNAME));
 +						break;
 +					}
 +
 +					// Is button enabled?
 +					if (!IsWindowEnabled(GetDlgItem(hwndDlg, IDC_MESSAGE)))
 +						break;
 +
 +					CallService(MS_MSG_SENDMESSAGET, (WPARAM) hContact, 0);
 +
 +					DBWriteContactSettingDword(NULL, MODULE_NAME, "LastSentTo", (DWORD) hContact);
 +					SendMessage(hwndDlg, WM_CLOSE, 0, 0);
 +					break;
 +				}
 +				case HOTKEY_VOICE:
 +				case IDC_VOICE:
 +				{
 +					HANDLE hContact = GetSelectedContact(hwndDlg);
 +					if (hContact == NULL)
 +					{
 +						SetDlgItemText(hwndDlg, IDC_USERNAME, _T(""));
 +						SetFocus(GetDlgItem(hwndDlg, IDC_USERNAME));
 +						break;
 +					}
 +
 +					// Is button enabled?
 +					if (!IsWindowEnabled(GetDlgItem(hwndDlg, IDC_VOICE)))
 +						break;
 +
 +					if (!ServiceExists(MS_VOICESERVICE_CALL))
 +						break;
 +
 +					CallService(MS_VOICESERVICE_CALL, (WPARAM) hContact, 0);
 +
 +					DBWriteContactSettingDword(NULL, MODULE_NAME, "LastSentTo", (DWORD) hContact);
 +					SendMessage(hwndDlg, WM_CLOSE, 0, 0);
 +					break;
 +				}
 +				case HOTKEY_FILE:
 +				case IDC_FILE:
 +				{
 +					HANDLE hContact = GetSelectedContact(hwndDlg);
 +					if (hContact == NULL)
 +					{
 +						SetDlgItemText(hwndDlg, IDC_USERNAME, _T(""));
 +						SetFocus(GetDlgItem(hwndDlg, IDC_USERNAME));
 +						break;
 +					}
 +
 +					// Is button enabled?
 +					if (!IsWindowEnabled(GetDlgItem(hwndDlg, IDC_FILE)))
 +						break;
 +
 +					CallService(MS_FILE_SENDFILE, (WPARAM) hContact, 0);
 +
 +					DBWriteContactSettingDword(NULL, MODULE_NAME, "LastSentTo", (DWORD) hContact);
 +					SendMessage(hwndDlg, WM_CLOSE, 0, 0);
 +					break;
 +				}
 +				case HOTKEY_URL:
 +				case IDC_URL:
 +				{
 +					HANDLE hContact = GetSelectedContact(hwndDlg);
 +					if (hContact == NULL)
 +					{
 +						SetDlgItemText(hwndDlg, IDC_USERNAME, _T(""));
 +						SetFocus(GetDlgItem(hwndDlg, IDC_USERNAME));
 +						break;
 +					}
 +
 +					// Is button enabled?
 +					if (!IsWindowEnabled(GetDlgItem(hwndDlg, IDC_URL)))
 +						break;
 +
 +					CallService(MS_URL_SENDURL, (WPARAM) hContact, 0);
 +
 +					DBWriteContactSettingDword(NULL, MODULE_NAME, "LastSentTo", (DWORD) hContact);
 +					SendMessage(hwndDlg, WM_CLOSE, 0, 0);
 +					break;
 +				}
 +				case HOTKEY_INFO:
 +				case IDC_USERINFO:
 +				{
 +					HANDLE hContact = GetSelectedContact(hwndDlg);
 +					if (hContact == NULL)
 +					{
 +						SetDlgItemText(hwndDlg, IDC_USERNAME, _T(""));
 +						SetFocus(GetDlgItem(hwndDlg, IDC_USERNAME));
 +						break;
 +					}
 +
 +					// Is button enabled?
 +					if (!IsWindowEnabled(GetDlgItem(hwndDlg, IDC_USERINFO)))
 +						break;
 +
 +					CallService(MS_USERINFO_SHOWDIALOG, (WPARAM) hContact, 0);
 +
 +					DBWriteContactSettingDword(NULL, MODULE_NAME, "LastSentTo", (DWORD) hContact);
 +					SendMessage(hwndDlg, WM_CLOSE, 0, 0);
 +					break;
 +				}
 +				case HOTKEY_HISTORY:
 +				case IDC_HISTORY:
 +				{
 +					HANDLE hContact = GetSelectedContact(hwndDlg);
 +					if (hContact == NULL)
 +					{
 +						SetDlgItemText(hwndDlg, IDC_USERNAME, _T(""));
 +						SetFocus(GetDlgItem(hwndDlg, IDC_USERNAME));
 +						break;
 +					}
 +
 +					// Is button enabled?
 +					if (!IsWindowEnabled(GetDlgItem(hwndDlg, IDC_HISTORY)))
 +						break;
 +
 +					CallService(MS_HISTORY_SHOWCONTACTHISTORY, (WPARAM) hContact, 0);
 +
 +					DBWriteContactSettingDword(NULL, MODULE_NAME, "LastSentTo", (DWORD) hContact);
 +					SendMessage(hwndDlg, WM_CLOSE, 0, 0);
 +					break;
 +				}
 +				case HOTKEY_MENU:
 +				case IDC_MENU:
 +				{
 +					HANDLE hContact = GetSelectedContact(hwndDlg);
 +					if (hContact == NULL)
 +					{
 +						SetDlgItemText(hwndDlg, IDC_USERNAME, _T(""));
 +						SetFocus(GetDlgItem(hwndDlg, IDC_USERNAME));
 +						break;
 +					}
 +
 +					// Is button enabled?
 +					if (!IsWindowEnabled(GetDlgItem(hwndDlg, IDC_MENU)))
 +						break;
 +
 +                    RECT rc;
 +                    GetWindowRect(GetDlgItem(hwndDlg, IDC_MENU), &rc);
 +                    HMENU hMenu = (HMENU) CallService(MS_CLIST_MENUBUILDCONTACT, (WPARAM) hContact, 0);
 +                    int ret = TrackPopupMenu(hMenu, TPM_TOPALIGN|TPM_RIGHTBUTTON|TPM_RETURNCMD, rc.left, rc.bottom, 0, hwndDlg, NULL);
 +                    DestroyMenu(hMenu);
 +
 +					if(ret)
 +					{
 +						SendMessage(hwndDlg, WM_CLOSE, 0, 0);
 +						CallService(MS_CLIST_MENUPROCESSCOMMAND, MAKEWPARAM(LOWORD(ret),MPCF_CONTACTMENU),(LPARAM) hContact);
 +					}
 +
 +					DBWriteContactSettingDword(NULL, MODULE_NAME, "LastSentTo", (DWORD) hContact);
 +					break;
 +				}
 +				case HOTKEY_ALL_CONTACTS:
 +				case IDC_SHOW_ALL_CONTACTS:
 +				{
 +					// Get old text
 +					HWND hEdit = GetWindow(GetWindow(hwndDlg,GW_CHILD),GW_CHILD);
 +					TCHAR sztext[120] = _T("");
 +
 +					if (SendMessage(hEdit, EM_GETSEL, (WPARAM)NULL, (LPARAM)NULL) != -1)
 +						SendMessage(hEdit, EM_REPLACESEL, (WPARAM)0, (LPARAM)_T(""));
 +
 +					SendMessage(hEdit, WM_GETTEXT, (WPARAM)MAX_REGS(sztext), (LPARAM)sztext);
 +
 +					// Fill combo			
 +					BOOL all = IsDlgButtonChecked(hwndDlg, IDC_SHOW_ALL_CONTACTS);
 +
 +					if (LOWORD(wParam) == HOTKEY_ALL_CONTACTS)
 +					{
 +						// Toggle checkbox
 +						all = !all;
 +						CheckDlgButton(hwndDlg, IDC_SHOW_ALL_CONTACTS, all ? BST_CHECKED : BST_UNCHECKED);
 +					}
 +
 +					LoadContacts(hwndDlg, all);
 +
 +					// Return selection
 +					CheckText(hEdit, sztext);
 +
 +					break;
 +				}
 +			}
 +
 +			break;
 +		}
 +
 +		case WM_CLOSE:
 +		{
 +			Utils_SaveWindowPosition(hwndDlg, NULL, MODULE_NAME, "window");
 +			MagneticWindows_RemoveWindow(hwndDlg);
 +			DestroyWindow(hwndDlg);
 +			break;
 +		}
 +
 +		case WM_DESTROY:
 +		{
 +			UnhookWindowsHookEx(hHook);
 +			hwndMain = NULL;
 +			FreeContacts();
 +			InterlockedExchange(&main_dialog_open, 0);
 +			break;
 +		}
 +
 +		case WM_NCLBUTTONDBLCLK:
 +		{
 +			MagneticWindows_SnapWindowToList(hwndDlg, MS_MW_STL_List_Left | MS_MW_STL_List_Top
 +													| MS_MW_STL_Wnd_Right | MS_MW_STL_Wnd_Top);
 +			break;
 +		}
 +		
 +		case WM_DRAWITEM:
 +		{
 +			// add icons and protocol to listbox
 +			LPDRAWITEMSTRUCT lpdis = (LPDRAWITEMSTRUCT)lParam;
 +
 +			// Handle contact menu
 +			if(lpdis->CtlID != IDC_USERNAME) 
 +			{
 +				if (lpdis->CtlType == ODT_MENU)
 +					return CallService(MS_CLIST_MENUDRAWITEM,wParam,lParam);
 +				else
 +					break;
 +			}
 +
 +			// Handle combo
 +			if(lpdis->itemID == -1) 
 +				break;
 +
 +			TEXTMETRIC tm;
 +			int icon_width=0, icon_height=0;
 +			RECT rc;
 +
 +			GetTextMetrics(lpdis->hDC, &tm);
 +			ImageList_GetIconSize(hIml, &icon_width, &icon_height);
 +
 +			COLORREF clrfore = SetTextColor(lpdis->hDC,GetSysColor(lpdis->itemState & ODS_SELECTED?COLOR_HIGHLIGHTTEXT:COLOR_WINDOWTEXT));
 +			COLORREF clrback = SetBkColor(lpdis->hDC,GetSysColor(lpdis->itemState & ODS_SELECTED?COLOR_HIGHLIGHT:COLOR_WINDOW));
 +
 +			FillRect(lpdis->hDC, &lpdis->rcItem, GetSysColorBrush(lpdis->itemState & ODS_SELECTED ? COLOR_HIGHLIGHT : COLOR_WINDOW));
 +
 +			// Draw icon
 +			rc.left = lpdis->rcItem.left + 5;
 +			rc.top = (lpdis->rcItem.bottom + lpdis->rcItem.top - icon_height) / 2;
 +			ImageList_Draw(hIml, CallService(MS_CLIST_GETCONTACTICON, (WPARAM)contacts[lpdis->itemData]->hcontact, 0), 
 +							lpdis->hDC, rc.left, rc.top, ILD_NORMAL);
 +
 +			// Make rect for text
 +			rc.left += icon_width + 5;
 +			rc.right = lpdis->rcItem.right - 1;
 +			rc.top = (lpdis->rcItem.bottom + lpdis->rcItem.top - tm.tmHeight) / 2;
 +			rc.bottom = rc.top + tm.tmHeight;
 +
 +			// Draw Protocol
 +			if (opts.num_protos > 1)
 +			{
 +				if (max_proto_width == 0)
 +				{
 +					// Has to be done, else the DC isnt the right one
 +					// Dont ask me why
 +					for(int loop = 0; loop < contacts.getCount(); loop++)
 +					{
 +						RECT rcc = { 0, 0, 0x7FFF, 0x7FFF };
 +
 +						DrawText(lpdis->hDC, contacts[loop]->proto, lstrlen(contacts[loop]->proto), 
 +								 &rcc, DT_END_ELLIPSIS | DT_NOPREFIX | DT_SINGLELINE | DT_CALCRECT);
 +						max_proto_width = max(max_proto_width, rcc.right - rcc.left);
 +					}
 +
 +					// Fix max_proto_width
 +					if (opts.group_append && opts.group_column)
 +						max_proto_width = min(max_proto_width, (rc.right - rc.left) / 5);
 +					else if (opts.group_append)
 +						max_proto_width = min(max_proto_width, (rc.right - rc.left) / 4);
 +					else
 +						max_proto_width = min(max_proto_width, (rc.right - rc.left) / 3);
 +				}
 +
 +				RECT rc_tmp = rc;
 +
 +				rc_tmp.left = rc_tmp.right - max_proto_width;
 +
 +				DrawText(lpdis->hDC, contacts[lpdis->itemData]->proto, lstrlen(contacts[lpdis->itemData]->proto), 
 +						 &rc_tmp, DT_END_ELLIPSIS | DT_NOPREFIX | DT_SINGLELINE);
 +
 +				rc.right = rc_tmp.left - 5;
 +			}
 +
 +			// Draw group
 +			if (opts.group_append && opts.group_column)
 +			{
 +				RECT rc_tmp = rc;
 +
 +				if (opts.group_column_left)
 +				{
 +					rc_tmp.right = rc_tmp.left + (rc.right - rc.left) / 3;
 +					rc.left = rc_tmp.right + 5;
 +				}
 +				else
 +				{
 +					rc_tmp.left = rc_tmp.right - (rc.right - rc.left) / 3;
 +					rc.right = rc_tmp.left - 5;
 +				}
 +
 +				DrawText(lpdis->hDC, contacts[lpdis->itemData]->szgroup, lstrlen(contacts[lpdis->itemData]->szgroup),
 +						 &rc_tmp, DT_END_ELLIPSIS | DT_NOPREFIX | DT_SINGLELINE);
 +			}
 +
 +			// Draw text
 +			TCHAR *name;
 +			if (opts.group_append && !opts.group_column)
 +				name = GetListName(contacts[lpdis->itemData]);
 +			else
 +				name = contacts[lpdis->itemData]->szname;
 +
 +			DrawText(lpdis->hDC, name, lstrlen(name), &rc, DT_END_ELLIPSIS | DT_NOPREFIX | DT_SINGLELINE);
 +
 +			// Restore old colors
 +			SetTextColor(lpdis->hDC, clrfore);
 +			SetBkColor(lpdis->hDC, clrback);
 +
 +			return TRUE;
 +		}
 +
 +		case WM_MEASUREITEM:
 +		{
 +			LPMEASUREITEMSTRUCT lpmis = (LPMEASUREITEMSTRUCT)lParam;
 +
 +			// Handle contact menu
 +			if(lpmis->CtlID != IDC_USERNAME) 
 +			{
 +				if (lpmis->CtlType == ODT_MENU)
 +					return CallService(MS_CLIST_MENUMEASUREITEM,wParam,lParam);
 +				else
 +					break;
 +			}
 +
 +			// Handle combo
 +
 +			TEXTMETRIC tm;
 +			int icon_width = 0, icon_height=0;
 +
 +			GetTextMetrics(GetDC(hwndDlg), &tm);
 +			ImageList_GetIconSize(hIml, &icon_width, &icon_height);
 +
 +			lpmis->itemHeight = max(icon_height, tm.tmHeight);
 +				
 +			return TRUE;
 +		}
 +	}
 +	
 +	return FALSE;
 +}
 +
 +
 +// Show the main dialog
 +INT_PTR ShowDialog(WPARAM wParam, LPARAM lParam) 
 +{
 +	if (!main_dialog_open) 
 +	{
 +		InterlockedExchange(&main_dialog_open, 1);
 +
 +		hwndMain = CreateDialog(hInst, MAKEINTRESOURCE(IDD_MAIN), NULL, MainDlgProc);
 +	}
 +
 +	// Show it
 +	SetForegroundWindow(hwndMain);
 +	SetFocus(hwndMain);
 + 	ShowWindow(hwndMain, SW_SHOW);
 +
 +	return 0;
 +}
 diff --git a/plugins/QuickContacts/src/resource.h b/plugins/QuickContacts/src/resource.h new file mode 100644 index 0000000000..f7f6a0142f --- /dev/null +++ b/plugins/QuickContacts/src/resource.h @@ -0,0 +1,47 @@ +//{{NO_DEPENDENCIES}}
 +// Microsoft Developer Studio generated include file.
 +// Used by resource.rc
 +//
 +#define ACCEL_TABLE                     103
 +#define IDD_OPT                         110
 +#define IDD_MAIN                        1000
 +#define IDC_USERNAME                    1001
 +#define IDC_LASTSENTTO                  1004
 +#define IDC_GLOBAL                      1009
 +#define IDC_LOCAL                       1010
 +#define IDC_PROTOCOLS                   1041
 +#define IDC_SUBCONTACTS                 1058
 +#define IDC_KEEP_OFFLINE                1059
 +#define IDC_HIDE_OFFLINE                1060
 +#define IDC_SHOW_ALL_CONTACTS           1061
 +#define IDC_APPEND_GROUP                1061
 +#define IDC_MESSAGE                     1062
 +#define IDC_GROUP_COLUMN                1062
 +#define IDC_FILE                        1063
 +#define IDC_GROUP_LEFT                  1063
 +#define IDC_URL                         1064
 +#define IDC_USERINFO                    1065
 +#define IDC_HISTORY                     1066
 +#define IDC_MENU                        1067
 +#define IDC_VOICE                       1068
 +#define HOTKEY_FILE                     40001
 +#define HOTKEY_URL                      40002
 +#define HOTKEY_INFO                     40003
 +#define HOTKEY_HISTORY                  40004
 +#define HOTKEY_ALL_CONTACTS             40005
 +#define HOTKEY_MENU                     40006
 +#define HOTKEY_VOICE                    40007
 +#define IDC_STATIC                      -1
 +
 +// Next default values for new objects
 +// 
 +#ifdef APSTUDIO_INVOKED
 +#ifndef APSTUDIO_READONLY_SYMBOLS
 +#define _APS_NO_MFC                     1
 +#define _APS_3D_CONTROLS                     1
 +#define _APS_NEXT_RESOURCE_VALUE        119
 +#define _APS_NEXT_COMMAND_VALUE         40008
 +#define _APS_NEXT_CONTROL_VALUE         1063
 +#define _APS_NEXT_SYMED_VALUE           101
 +#endif
 +#endif
  | 
