summaryrefslogtreecommitdiff
path: root/plugins/QuickContacts/quickcontacts.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'plugins/QuickContacts/quickcontacts.cpp')
-rw-r--r--plugins/QuickContacts/quickcontacts.cpp1302
1 files changed, 1302 insertions, 0 deletions
diff --git a/plugins/QuickContacts/quickcontacts.cpp b/plugins/QuickContacts/quickcontacts.cpp
new file mode 100644
index 0000000000..31fb3b835d
--- /dev/null
+++ b/plugins/QuickContacts/quickcontacts.cpp
@@ -0,0 +1,1302 @@
+/*
+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)
+{
+#ifdef UNICODE
+ 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;
+#else
+ if (len > 0)
+ return _tcsnicmp(a, b, len);
+ else
+ return _tcsicmp(a, b);
+#endif
+}
+
+
+// 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 hasAccounts = ServiceExists(MS_PROTO_GETACCOUNT);
+ 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 = (hasAccounts ? ProtoGetAccount(pszProto) : NULL);
+ if (acc != NULL)
+ {
+ lstrcpyn(contact->proto, acc->tszAccountName, MAX_REGS(contact->proto));
+ }
+ else
+ {
+ char szName[128];
+ CallProtoService(pszProto, PS_GETNAME, sizeof(szName), (LPARAM) szName);
+ lstrcpyn(contact->proto, CharToTchar(szName), 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 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)
+{
+ MSG *msg;
+ HWND htemp;
+
+ if (code!=MSGF_DIALOGBOX)
+ return 0;
+
+ 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
+ {
+ 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, char *name, char *key, HICON icon)
+{
+ char tmp[256];
+ char *full;
+ if (key == NULL)
+ full = Translate(name);
+ else
+ mir_snprintf(full = tmp, MAX_REGS(tmp), "%s (%s)", Translate(name), key);
+
+ SendMessage(GetDlgItem(hwndDlg, dlgItem), BUTTONSETASFLATBTN, 0, 0);
+ SendMessageA(GetDlgItem(hwndDlg, dlgItem), BUTTONADDTOOLTIP, (LPARAM) full, 0);
+ SendDlgItemMessage(hwndDlg, dlgItem, BM_SETIMAGE, IMAGE_ICON, (LPARAM) icon);
+}
+
+
+static void FillCheckbox(HWND hwndDlg, int dlgItem, char *name, char *key)
+{
+ char tmp[256];
+ char *full;
+ if (key == NULL)
+ full = Translate(name);
+ else
+ mir_snprintf(full = tmp, MAX_REGS(tmp), "%s (%s)", Translate(name), key);
+
+ SendMessageA(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, "Show all contacts", hasNewHotkeyModule ? NULL : "Ctrl+A");
+ FillButton(hwndDlg, IDC_MESSAGE, "Send message", NULL, LoadSkinnedIcon(SKINICON_EVENT_MESSAGE));
+
+ if (ServiceExists(MS_VOICESERVICE_CAN_CALL))
+ {
+ FillButton(hwndDlg, IDC_VOICE, "Make a voice call", hasNewHotkeyModule ? NULL : "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, "Send file", hasNewHotkeyModule ? NULL : "Ctrl+F", LoadSkinnedIcon(SKINICON_EVENT_FILE));
+ FillButton(hwndDlg, IDC_URL, "Send URL", hasNewHotkeyModule ? NULL : "Ctrl+U", LoadSkinnedIcon(SKINICON_EVENT_URL));
+ FillButton(hwndDlg, IDC_USERINFO, "Open userinfo", hasNewHotkeyModule ? NULL : "Ctrl+I", (HICON) LoadImage(GetModuleHandle(NULL),MAKEINTRESOURCE(160),IMAGE_ICON,16,16,LR_DEFAULTCOLOR));
+ FillButton(hwndDlg, IDC_HISTORY, "Open history", hasNewHotkeyModule ? NULL : "Ctrl+H", (HICON) LoadImage(GetModuleHandle(NULL),MAKEINTRESOURCE(174),IMAGE_ICON,16,16,LR_DEFAULTCOLOR));
+ FillButton(hwndDlg, IDC_MENU, "Open contact menu", hasNewHotkeyModule ? NULL : "Ctrl+M", (HICON) LoadImage(GetModuleHandle(NULL),MAKEINTRESOURCE(264),IMAGE_ICON,16,16,LR_DEFAULTCOLOR));
+
+ 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;
+}