From 10e856dedeb8bc7adf01213ff393b82772c90e92 Mon Sep 17 00:00:00 2001 From: Vadim Dashevskiy Date: Wed, 3 Oct 2012 15:03:01 +0000 Subject: QuickContacts - welcome on board git-svn-id: http://svn.miranda-ng.org/main/trunk@1770 1316c22d-e87f-b044-9b9b-93d7a3e3ba9c --- plugins/QuickContacts/src/commons.h | 107 +++ plugins/QuickContacts/src/options.cpp | 164 ++++ plugins/QuickContacts/src/options.h | 65 ++ plugins/QuickContacts/src/quickcontacts.cpp | 1285 +++++++++++++++++++++++++++ plugins/QuickContacts/src/resource.h | 47 + 5 files changed, 1668 insertions(+) create mode 100644 plugins/QuickContacts/src/commons.h create mode 100644 plugins/QuickContacts/src/options.cpp create mode 100644 plugins/QuickContacts/src/options.h create mode 100644 plugins/QuickContacts/src/quickcontacts.cpp create mode 100644 plugins/QuickContacts/src/resource.h (limited to 'plugins/QuickContacts/src') 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 +#include +#include +#include + + +// Miranda headers +#define MIRANDA_VER 0x0A00 +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#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 + + +#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;looptype==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 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;loopszname,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;loopszname)==0 || lstreq(sztext, GetListName(contacts[loop]))==0) + { + EnableButtons(hwndMain, contacts[loop]->hcontact); + return 0; + } + } + } + else + { + for(int loop=0;loophcontact); + 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;loophcontact) + 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 -- cgit v1.2.3