From 11e70d8c4e224d80015fffe0378c53abee5fd824 Mon Sep 17 00:00:00 2001 From: George Hazan Date: Thu, 17 May 2018 19:41:35 +0300 Subject: Popup, PManagerEx, QuickContacts, RemovePersonalSettings, Restart, SeenPlugin, SendSS, ShlExt, SimpleAR, SimpleStatusMsg, SkypeStatusChange, SmileyAdd, SMS => CMPlugin --- plugins/QuickContacts/src/dialog.cpp | 881 +++++++++++++++++++++++++ plugins/QuickContacts/src/options.cpp | 2 +- plugins/QuickContacts/src/quickcontacts.cpp | 955 +--------------------------- plugins/QuickContacts/src/stdafx.h | 16 +- 4 files changed, 917 insertions(+), 937 deletions(-) create mode 100644 plugins/QuickContacts/src/dialog.cpp (limited to 'plugins/QuickContacts/src') diff --git a/plugins/QuickContacts/src/dialog.cpp b/plugins/QuickContacts/src/dialog.cpp new file mode 100644 index 0000000000..e51d2734e2 --- /dev/null +++ b/plugins/QuickContacts/src/dialog.cpp @@ -0,0 +1,881 @@ +/* +Copyright (C) 2012-18 Miranda NG team (https://miranda-ng.org) + +This program is free software; you can redistribute it and/or +modify it under the terms of the GNU General Public License +as published by the Free Software Foundation version 2 +of the License. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program. If not, see . +*/ + +#include "stdafx.h" + +#define IDC_ICO 12344 + +#define IDC_ENTER 2000 // Pseudo control to handle enter in the main window + +HIMAGELIST hIml; + +long main_dialog_open = 0; +HWND hwndMain = nullptr; + +// array where the contacts are put into +struct c_struct +{ + wchar_t szname[120]; + wchar_t szgroup[50]; + MCONTACT hcontact; + wchar_t 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! +wchar_t tmp_list_name[120]; + +wchar_t *GetListName(c_struct *cs) +{ + if (opts.group_append && cs->szgroup[0] != '\0') { + mir_snwprintf(tmp_list_name, L"%s (%s)", cs->szname, cs->szgroup); + return tmp_list_name; + } + else { + return cs->szname; + } +} + + +int lstreq(wchar_t *a, wchar_t *b, size_t len = -1) +{ + a = CharLower(wcsdup(a)); + b = CharLower(wcsdup(b)); + int ret; + if (len > 0) + ret = wcsncmp(a, b, len); + else + ret = mir_wstrcmp(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(MCONTACT hContact, char *proto = nullptr) +{ + if (proto == nullptr) + proto = GetContactProto(hContact); + + if (proto == nullptr) + return ID_STATUS_OFFLINE; + + return db_get_w(hContact, proto, "Status", ID_STATUS_OFFLINE); +} + + +void FreeContacts() +{ + for (auto &it : contacts) + delete it; + contacts.destroy(); +} + + +void LoadContacts(HWND hwndDlg, BOOL show_all) +{ + BOOL metacontactsEnabled = db_mc_isEnabled(); + + // Read last-sent-to contact from db and set handle as window-userdata + HANDLE hlastsent = (HANDLE)db_get_dw(NULL, MODULE_NAME, "LastSentTo", -1); + SetWindowLongPtr(hwndMain, GWLP_USERDATA, (LONG_PTR)hlastsent); + + // enumerate all contacts and write them to the array + // item data of listbox-strings is the array position + FreeContacts(); + + for (auto &hContact : Contacts()) { + char *pszProto = GetContactProto(hContact); + if (pszProto == nullptr) + continue; + + // Get meta + MCONTACT hMeta = NULL; + if (metacontactsEnabled) { + if ((!show_all && opts.hide_subcontacts) || opts.group_append) + hMeta = db_mc_getMeta(hContact); + } + else if (!mir_strcmp(META_PROTO, pszProto)) + 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, "ShowOffline%s", pszProto); + + if (!db_get_b(NULL, MODULE_NAME, setting, FALSE)) + continue; + + // Check if proto offline + else if (opts.hide_from_offline_proto && Proto_GetStatus(pszProto) <= ID_STATUS_OFFLINE) + continue; + + } + + // Check if is subcontact + if (opts.hide_subcontacts && hMeta != NULL) { + if (!opts.keep_subcontacts_from_offline) + continue; + + if (GetStatus(hMeta, META_PROTO) > ID_STATUS_OFFLINE) + continue; + + char setting[128]; + mir_snprintf(setting, "ShowOffline%s", META_PROTO); + if (db_get_b(NULL, MODULE_NAME, setting, FALSE)) + continue; + } + } + + // Add to list + + // Get group + c_struct *contact = new c_struct(); + + if (opts.group_append) { + DBVARIANT dbv; + if (db_get_ws(hMeta == NULL ? hContact : hMeta, "CList", "Group", &dbv) == 0) { + if (dbv.ptszVal != nullptr) + mir_wstrncpy(contact->szgroup, dbv.ptszVal, _countof(contact->szgroup)); + + db_free(&dbv); + } + } + + // Make contact name + wchar_t *tmp = (wchar_t *)Clist_GetContactDisplayName(hContact); + mir_wstrncpy(contact->szname, tmp, _countof(contact->szname)); + + PROTOACCOUNT *acc = Proto_GetAccount(pszProto); + if (acc != nullptr) + mir_wstrncpy(contact->proto, acc->tszAccountName, _countof(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, SendDlgItemMessage(hwndDlg, IDC_USERNAME, CB_ADDSTRING, 0, (LPARAM)GetListName(contacts[loop])), loop); +} + + +// Enable buttons for the selected contact +void EnableButtons(HWND hwndDlg, MCONTACT hContact) +{ + if (hContact == NULL) { + EnableWindow(GetDlgItem(hwndDlg, IDC_MESSAGE), 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); + + SendDlgItemMessage(hwndDlg, IDC_ICO, STM_SETICON, 0, 0); + } + else { + // Is a meta? + MCONTACT hSub = db_mc_getMostOnline(hContact); + if (hSub != NULL) + hContact = hSub; + + // Get caps + INT_PTR caps = 0; + + char *pszProto = GetContactProto(hContact); + if (pszProto != nullptr) + caps = CallProtoService(pszProto, PS_GETCAPS, PFLAGNUM_1, 0); + + EnableWindow(GetDlgItem(hwndDlg, IDC_MESSAGE), caps & PF1_IMSEND ? TRUE : FALSE); + 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, Clist_GetContactIcon(hContact), ILD_IMAGE); + SendDlgItemMessage(hwndDlg, IDC_ICO, STM_SETICON, (WPARAM)ico, 0); + } +} + + +// check if the char(s) entered appears in a contacts name +int CheckText(HWND hdlg, wchar_t *sztext, BOOL only_enable = FALSE) +{ + EnableButtons(hwndMain, NULL); + + if (sztext == nullptr || sztext[0] == '\0') + return 0; + + size_t len = mir_wstrlen(sztext); + + if (only_enable) { + for (auto &it : contacts) { + if (lstreq(sztext, it->szname) == 0 || lstreq(sztext, GetListName(it)) == 0) { + EnableButtons(hwndMain, it->hcontact); + return 0; + } + } + } + else { + for (auto &it : contacts) { + if (lstreq(sztext, GetListName(it), len) == 0) { + SetWindowText(hdlg, GetListName(it)); + SendMessage(hdlg, EM_SETSEL, (WPARAM)len, (LPARAM)-1); + EnableButtons(hwndMain, it->hcontact); + return 0; + } + } + } + + EnableButtons(hwndMain, NULL); + return 0; +} + +MCONTACT 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 + wchar_t cname[120] = L""; + + GetDlgItemText(hwndDlg, IDC_USERNAME, cname, _countof(cname)); + + for (auto &it : contacts) + if (!mir_wstrcmpi(cname, GetListName(it))) + return it->hcontact; + + return NULL; +} + +// get array position from handle +int GetItemPos(MCONTACT hcontact) +{ + for (auto &it : contacts) + if (hcontact == it->hcontact) + return contacts.indexOf(&it); + + return -1; +} + + +// 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; + + wchar_t sztext[120] = L""; + DWORD start; + DWORD end; + + int ret = SendMessage(hdlg, EM_GETSEL, (WPARAM)&start, (LPARAM)&end); + + GetWindowText(hdlg, sztext, _countof(sztext)); + + BOOL at_end = (mir_wstrlen(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, 0, (LPARAM)sztext); + GetWindowText(hdlg, sztext, _countof(sztext)); + } + + CheckText(hdlg, sztext, !at_end); + + return 1; + } + case WM_KEYUP: + { + wchar_t sztext[120] = L""; + + 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, FALSE, 0); + break; + } + } + else if (wparam == VK_DELETE) { + GetWindowText(hdlg, sztext, _countof(sztext)); + CheckText(hdlg, sztext, TRUE); + } + + return 0; + } + + case WM_GETDLGCODE: + return DLGC_WANTCHARS | DLGC_WANTARROWS; + } + + return mir_callNextSubclass(hdlg, EditProc, msg, wparam, lparam); +} + +HACCEL hAcct; +HHOOK hHook; + +// This function filters the message queue and translates +// the keyboard accelerators +LRESULT CALLBACK HookProc(int code, WPARAM, LPARAM lparam) +{ + if (code != MSGF_DIALOGBOX) + return 0; + + MSG *msg = (MSG*)lparam; + + int action = Hotkey_Check(msg, "Quick Contacts"); + if (action != 0) { + SendMessage(hwndMain, WM_COMMAND, action, 0); + return 1; + } + + if (msg->message == WM_KEYDOWN && msg->wParam == VK_ESCAPE) { + switch (SendDlgItemMessage(hwndMain, IDC_USERNAME, CB_GETDROPPEDSTATE, 0, 0)) { + case FALSE: + SendMessage(hwndMain, WM_CLOSE, 0, 0); + break; + + case TRUE: + SendDlgItemMessage(hwndMain, IDC_USERNAME, CB_SHOWDROPDOWN, 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, wchar_t *name, wchar_t *key, HICON icon) +{ + wchar_t tmp[256]; + wchar_t *full = tmp; + + if (key == nullptr) + full = TranslateW(name); + else + mir_snwprintf(tmp, L"%s (%s)", TranslateW(name), key); + + SendDlgItemMessage(hwndDlg, dlgItem, BUTTONSETASFLATBTN, 0, 0); + SendDlgItemMessage(hwndDlg, dlgItem, BUTTONADDTOOLTIP, (LPARAM)full, BATF_UNICODE); + SendDlgItemMessage(hwndDlg, dlgItem, BM_SETIMAGE, IMAGE_ICON, (LPARAM)icon); +} + + +static void FillCheckbox(HWND hwndDlg, int dlgItem, wchar_t *name, wchar_t *key) +{ + wchar_t tmp[256]; + wchar_t *full = tmp; + + if (key == nullptr) + full = TranslateW(name); + else + mir_snwprintf(tmp, L"%s (%s)", TranslateW(name), key); + + SetDlgItemText(hwndDlg, dlgItem, 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); + + CreateWindow(L"STATIC", L"", 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, + g_plugin.getInst(), nullptr); + + hHook = SetWindowsHookEx(WH_MSGFILTER, HookProc, nullptr, GetCurrentThreadId()); + + // Combo + SendDlgItemMessage(hwndDlg, IDC_USERNAME, EM_LIMITTEXT, (WPARAM)119, 0); + mir_subclassWindow(GetWindow(GetDlgItem(hwndDlg, IDC_USERNAME), GW_CHILD), EditProc); + + // Buttons + FillCheckbox(hwndDlg, IDC_SHOW_ALL_CONTACTS, LPGENW("Show all contacts"), NULL); + FillButton(hwndDlg, IDC_MESSAGE, LPGENW("Send message"), nullptr, Skin_LoadIcon(SKINICON_EVENT_MESSAGE)); + FillButton(hwndDlg, IDC_FILE, LPGENW("Send file"), NULL, Skin_LoadIcon(SKINICON_EVENT_FILE)); + FillButton(hwndDlg, IDC_URL, LPGENW("Send URL"), NULL, Skin_LoadIcon(SKINICON_EVENT_URL)); + FillButton(hwndDlg, IDC_USERINFO, LPGENW("Open user info"), NULL, Skin_LoadIcon(SKINICON_OTHER_USERDETAILS)); + FillButton(hwndDlg, IDC_HISTORY, LPGENW("Open history"), NULL, Skin_LoadIcon(SKINICON_OTHER_HISTORY)); + FillButton(hwndDlg, IDC_MENU, LPGENW("Open contact menu"), NULL, Skin_LoadIcon(SKINICON_OTHER_DOWNARROW)); + + SendDlgItemMessage(hwndDlg, IDC_USERNAME, CB_SETEXTENDEDUI, TRUE, 0); + + Utils_RestoreWindowPositionNoSize(hwndDlg, NULL, MODULE_NAME, "window"); + + LoadContacts(hwndDlg, FALSE); + + EnableButtons(hwndDlg, NULL); + if (db_get_b(NULL, MODULE_NAME, "EnableLastSentTo", 0)) { + int pos = GetItemPos((MCONTACT)db_get_dw(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: + { + MCONTACT hContact = GetSelectedContact(hwndDlg); + if (hContact == NULL) + break; + + Clist_ContactDoubleClicked(hContact); + + db_set_dw(NULL, MODULE_NAME, "LastSentTo", hContact); + SendMessage(hwndDlg, WM_CLOSE, 0, 0); + } + break; + case IDC_MESSAGE: + { + MCONTACT hContact = GetSelectedContact(hwndDlg); + if (hContact == NULL) { + SetDlgItemText(hwndDlg, IDC_USERNAME, L""); + SetFocus(GetDlgItem(hwndDlg, IDC_USERNAME)); + break; + } + + // Is button enabled? + if (!IsWindowEnabled(GetDlgItem(hwndDlg, IDC_MESSAGE))) + break; + + CallService(MS_MSG_SENDMESSAGEW, hContact, 0); + + db_set_dw(NULL, MODULE_NAME, "LastSentTo", hContact); + SendMessage(hwndDlg, WM_CLOSE, 0, 0); + break; + } + + case HOTKEY_FILE: + case IDC_FILE: + { + MCONTACT hContact = GetSelectedContact(hwndDlg); + if (hContact == NULL) { + SetDlgItemText(hwndDlg, IDC_USERNAME, L""); + SetFocus(GetDlgItem(hwndDlg, IDC_USERNAME)); + break; + } + + // Is button enabled? + if (!IsWindowEnabled(GetDlgItem(hwndDlg, IDC_FILE))) + break; + + CallService(MS_FILE_SENDFILE, hContact, 0); + + db_set_dw(NULL, MODULE_NAME, "LastSentTo", hContact); + SendMessage(hwndDlg, WM_CLOSE, 0, 0); + } + break; + + case HOTKEY_URL: + case IDC_URL: + { + MCONTACT hContact = GetSelectedContact(hwndDlg); + if (hContact == NULL) { + SetDlgItemText(hwndDlg, IDC_USERNAME, L""); + SetFocus(GetDlgItem(hwndDlg, IDC_USERNAME)); + break; + } + + // Is button enabled? + if (!IsWindowEnabled(GetDlgItem(hwndDlg, IDC_URL))) + break; + + CallService(MS_URL_SENDURL, hContact, 0); + + db_set_dw(NULL, MODULE_NAME, "LastSentTo", hContact); + SendMessage(hwndDlg, WM_CLOSE, 0, 0); + } + break; + + case HOTKEY_INFO: + case IDC_USERINFO: + { + MCONTACT hContact = GetSelectedContact(hwndDlg); + if (hContact == NULL) { + SetDlgItemText(hwndDlg, IDC_USERNAME, L""); + SetFocus(GetDlgItem(hwndDlg, IDC_USERNAME)); + break; + } + + // Is button enabled? + if (!IsWindowEnabled(GetDlgItem(hwndDlg, IDC_USERINFO))) + break; + + CallService(MS_USERINFO_SHOWDIALOG, hContact, 0); + + db_set_dw(NULL, MODULE_NAME, "LastSentTo", hContact); + SendMessage(hwndDlg, WM_CLOSE, 0, 0); + } + break; + + case HOTKEY_HISTORY: + case IDC_HISTORY: + { + MCONTACT hContact = GetSelectedContact(hwndDlg); + if (hContact == NULL) { + SetDlgItemText(hwndDlg, IDC_USERNAME, L""); + SetFocus(GetDlgItem(hwndDlg, IDC_USERNAME)); + break; + } + + // Is button enabled? + if (!IsWindowEnabled(GetDlgItem(hwndDlg, IDC_HISTORY))) + break; + + CallService(MS_HISTORY_SHOWCONTACTHISTORY, hContact, 0); + + db_set_dw(NULL, MODULE_NAME, "LastSentTo", hContact); + SendMessage(hwndDlg, WM_CLOSE, 0, 0); + } + break; + + case HOTKEY_MENU: + case IDC_MENU: + { + MCONTACT hContact = GetSelectedContact(hwndDlg); + if (hContact == NULL) { + SetDlgItemText(hwndDlg, IDC_USERNAME, L""); + 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 = Menu_BuildContactMenu(hContact); + int ret = TrackPopupMenu(hMenu, TPM_TOPALIGN | TPM_RIGHTBUTTON | TPM_RETURNCMD, rc.left, rc.bottom, 0, hwndDlg, nullptr); + DestroyMenu(hMenu); + + if (ret) { + SendMessage(hwndDlg, WM_CLOSE, 0, 0); + Clist_MenuProcessCommand(LOWORD(ret), MPCF_CONTACTMENU, hContact); + } + + db_set_dw(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); + wchar_t sztext[120] = L""; + + if (SendMessage(hEdit, EM_GETSEL, 0, 0) != -1) + SendMessage(hEdit, EM_REPLACESEL, 0, (LPARAM)L""); + + GetWindowText(hEdit, sztext, _countof(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; + + case WM_CLOSE: + Utils_SaveWindowPosition(hwndDlg, NULL, MODULE_NAME, "window"); + DestroyWindow(hwndDlg); + break; + + case WM_DESTROY: + UnhookWindowsHookEx(hHook); + hwndMain = nullptr; + FreeContacts(); + InterlockedExchange(&main_dialog_open, 0); + 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 Menu_DrawItem(lParam); + 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, Clist_GetContactIcon(contacts[lpdis->itemData]->hcontact), 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 (auto &it : contacts) { + RECT rcc = { 0, 0, 0x7FFF, 0x7FFF }; + DrawText(lpdis->hDC, it->proto, -1, &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, -1, &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, -1, &rc_tmp, DT_END_ELLIPSIS | DT_NOPREFIX | DT_SINGLELINE); + } + + // Draw text + wchar_t *name; + if (opts.group_append && !opts.group_column) + name = GetListName(contacts[lpdis->itemData]); + else + name = contacts[lpdis->itemData]->szname; + + DrawText(lpdis->hDC, name, -1, &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 Menu_MeasureItem(lParam); + 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, LPARAM) +{ + // Get the icons for the listbox + hIml = Clist_GetImageList(); + + if (!main_dialog_open) { + InterlockedExchange(&main_dialog_open, 1); + + hwndMain = CreateDialog(g_plugin.getInst(), MAKEINTRESOURCE(IDD_MAIN), nullptr, MainDlgProc); + } + + // Show it + SetForegroundWindow(hwndMain); + SetFocus(hwndMain); + ShowWindow(hwndMain, SW_SHOW); + return 0; +} diff --git a/plugins/QuickContacts/src/options.cpp b/plugins/QuickContacts/src/options.cpp index d018d6a20a..3904fb0756 100644 --- a/plugins/QuickContacts/src/options.cpp +++ b/plugins/QuickContacts/src/options.cpp @@ -50,7 +50,7 @@ void LoadOptions() int InitOptionsCallback(WPARAM wParam, LPARAM) { OPTIONSDIALOGPAGE odp = { 0 }; - odp.hInstance = hInst; + odp.hInstance = g_plugin.getInst(); odp.szGroup.w = LPGENW("Contacts"); odp.szTitle.w = LPGENW("Quick Contacts"); odp.pfnDlgProc = OptionsDlgProc; diff --git a/plugins/QuickContacts/src/quickcontacts.cpp b/plugins/QuickContacts/src/quickcontacts.cpp index a7330a36fc..006d1397c2 100644 --- a/plugins/QuickContacts/src/quickcontacts.cpp +++ b/plugins/QuickContacts/src/quickcontacts.cpp @@ -22,85 +22,42 @@ Boston, MA 02111-1307, USA. // Prototypes /////////////////////////////////////////////////////////////////////////// -PLUGININFOEX pluginInfo = { - sizeof(PLUGININFOEX), - __PLUGIN_NAME, - PLUGIN_MAKE_VERSION(__MAJOR_VERSION, __MINOR_VERSION, __RELEASE_NUM, __BUILD_NUM), - __DESCRIPTION, - __AUTHOR, - __COPYRIGHT, - __AUTHORWEB, - UNICODE_AWARE, - // {F93BA59C-4F48-4F2E-8A91-77A2801527A3} - {0xf93ba59c, 0x4f48, 0x4f2e, {0x8a, 0x91, 0x77, 0xa2, 0x80, 0x15, 0x27, 0xa3}} -}; - -HINSTANCE hInst; -HIMAGELIST hIml; int hLangpack = 0; +CMPlugin g_plugin; HANDLE hModulesLoaded = nullptr; HANDLE hEventAdded = nullptr; HANDLE hHotkeyPressed = nullptr; -long main_dialog_open = 0; -HWND hwndMain = nullptr; - -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; - -#define IDC_ICO 12344 - // Functions //////////////////////////////////////////////////////////////////////////// -BOOL WINAPI DllMain(HINSTANCE hinstDLL, DWORD, LPVOID) -{ - hInst = hinstDLL; - return TRUE; -} - +PLUGININFOEX pluginInfo = { + sizeof(PLUGININFOEX), + __PLUGIN_NAME, + PLUGIN_MAKE_VERSION(__MAJOR_VERSION, __MINOR_VERSION, __RELEASE_NUM, __BUILD_NUM), + __DESCRIPTION, + __AUTHOR, + __COPYRIGHT, + __AUTHORWEB, + UNICODE_AWARE, + // {F93BA59C-4F48-4F2E-8A91-77A2801527A3} + {0xf93ba59c, 0x4f48, 0x4f2e, {0x8a, 0x91, 0x77, 0xa2, 0x80, 0x15, 0x27, 0xa3}} +}; extern "C" __declspec(dllexport) PLUGININFOEX* MirandaPluginInfoEx(DWORD) { return &pluginInfo; } -extern "C" __declspec(dllexport) int Load() -{ - mir_getLP(&pluginInfo); +///////////////////////////////////////////////////////////////////////////////////////// - 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(); - - UnhookEvent(hModulesLoaded); - UnhookEvent(hEventAdded); - - return 0; -} - - -// Called when all the modules are loaded -int ModulesLoaded(WPARAM, LPARAM) +static int ModulesLoaded(WPARAM, LPARAM) { InitOptions(); @@ -108,8 +65,6 @@ int ModulesLoaded(WPARAM, LPARAM) Proto_EnumAccounts(&opts.num_protos, nullptr); // Add hotkey to multiple services - hasNewHotkeyModule = TRUE; - HOTKEYDESC hkd = {}; hkd.dwFlags = HKD_UNICODE; hkd.pszName = "Quick Contacts/Open dialog"; @@ -168,9 +123,6 @@ int ModulesLoaded(WPARAM, LPARAM) CallService(MS_SKIN_ADDHOTKEY, 0, (LPARAM)&hk); } - // Get the icons for the listbox - hIml = Clist_GetImageList(); - // Add menu item CMenuItem mi; SET_UID(mi, 0x3a3f768a, 0xcf47, 0x43d5, 0x92, 0x16, 0xe4, 0xeb, 0x93, 0xf6, 0x72, 0xfa); @@ -182,10 +134,9 @@ int ModulesLoaded(WPARAM, LPARAM) return 0; } - // called when a message/file/url was sent // handle of contact is set as window-userdata -int EventAdded(WPARAM wparam, LPARAM hDbEvent) +static int EventAdded(WPARAM wparam, LPARAM hDbEvent) { DBEVENTINFO dbei = {}; db_event_get(hDbEvent, &dbei); @@ -198,878 +149,28 @@ int EventAdded(WPARAM wparam, LPARAM hDbEvent) 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 -{ - wchar_t szname[120]; - wchar_t szgroup[50]; - MCONTACT hcontact; - wchar_t 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! -wchar_t tmp_list_name[120]; - -wchar_t *GetListName(c_struct *cs) -{ - if (opts.group_append && cs->szgroup[0] != '\0') { - mir_snwprintf(tmp_list_name, L"%s (%s)", cs->szname, cs->szgroup); - return tmp_list_name; - } - else { - return cs->szname; - } -} - - -int lstreq(wchar_t *a, wchar_t *b, size_t len = -1) -{ - a = CharLower(wcsdup(a)); - b = CharLower(wcsdup(b)); - int ret; - if (len > 0) - ret = wcsncmp(a, b, len); - else - ret = mir_wstrcmp(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(MCONTACT hContact, char *proto = nullptr) -{ - if (proto == nullptr) - proto = GetContactProto(hContact); - - if (proto == nullptr) - return ID_STATUS_OFFLINE; - - return db_get_w(hContact, proto, "Status", ID_STATUS_OFFLINE); -} - - -void FreeContacts() -{ - for (auto &it : contacts) - delete it; - contacts.destroy(); -} - - -void LoadContacts(HWND hwndDlg, BOOL show_all) -{ - BOOL metacontactsEnabled = db_mc_isEnabled(); - - // Read last-sent-to contact from db and set handle as window-userdata - HANDLE hlastsent = (HANDLE)db_get_dw(NULL, MODULE_NAME, "LastSentTo", -1); - SetWindowLongPtr(hwndMain, GWLP_USERDATA, (LONG_PTR)hlastsent); - - // enumerate all contacts and write them to the array - // item data of listbox-strings is the array position - FreeContacts(); - - for (auto &hContact : Contacts()) { - char *pszProto = GetContactProto(hContact); - if (pszProto == nullptr) - continue; - - // Get meta - MCONTACT hMeta = NULL; - if (metacontactsEnabled) { - if ((!show_all && opts.hide_subcontacts) || opts.group_append) - hMeta = db_mc_getMeta(hContact); - } - else if (!mir_strcmp(META_PROTO, pszProto)) - 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, "ShowOffline%s", pszProto); - - if (!db_get_b(NULL, MODULE_NAME, setting, FALSE)) - continue; - - // Check if proto offline - else if (opts.hide_from_offline_proto && Proto_GetStatus(pszProto) <= ID_STATUS_OFFLINE) - continue; - - } - - // Check if is subcontact - if (opts.hide_subcontacts && hMeta != NULL) { - if (!opts.keep_subcontacts_from_offline) - continue; - - if (GetStatus(hMeta, META_PROTO) > ID_STATUS_OFFLINE) - continue; - - char setting[128]; - mir_snprintf(setting, "ShowOffline%s", META_PROTO); - if (db_get_b(NULL, MODULE_NAME, setting, FALSE)) - continue; - } - } - - // Add to list - - // Get group - c_struct *contact = new c_struct(); - - if (opts.group_append) { - DBVARIANT dbv; - if (db_get_ws(hMeta == NULL ? hContact : hMeta, "CList", "Group", &dbv) == 0) { - if (dbv.ptszVal != nullptr) - mir_wstrncpy(contact->szgroup, dbv.ptszVal, _countof(contact->szgroup)); - - db_free(&dbv); - } - } - - // Make contact name - wchar_t *tmp = (wchar_t *)Clist_GetContactDisplayName(hContact); - mir_wstrncpy(contact->szname, tmp, _countof(contact->szname)); - - PROTOACCOUNT *acc = Proto_GetAccount(pszProto); - if (acc != nullptr) - mir_wstrncpy(contact->proto, acc->tszAccountName, _countof(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, SendDlgItemMessage(hwndDlg, IDC_USERNAME, CB_ADDSTRING, 0, (LPARAM)GetListName(contacts[loop])), loop); -} - - -// Enable buttons for the selected contact -void EnableButtons(HWND hwndDlg, MCONTACT hContact) -{ - if (hContact == NULL) { - EnableWindow(GetDlgItem(hwndDlg, IDC_MESSAGE), 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); - - SendDlgItemMessage(hwndDlg, IDC_ICO, STM_SETICON, 0, 0); - } - else { - // Is a meta? - MCONTACT hSub = db_mc_getMostOnline(hContact); - if (hSub != NULL) - hContact = hSub; - - // Get caps - INT_PTR caps = 0; - - char *pszProto = GetContactProto(hContact); - if (pszProto != nullptr) - caps = CallProtoService(pszProto, PS_GETCAPS, PFLAGNUM_1, 0); - - EnableWindow(GetDlgItem(hwndDlg, IDC_MESSAGE), caps & PF1_IMSEND ? TRUE : FALSE); - 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, Clist_GetContactIcon(hContact), ILD_IMAGE); - SendDlgItemMessage(hwndDlg, IDC_ICO, STM_SETICON, (WPARAM)ico, 0); - } -} - - -// check if the char(s) entered appears in a contacts name -int CheckText(HWND hdlg, wchar_t *sztext, BOOL only_enable = FALSE) -{ - EnableButtons(hwndMain, NULL); - - if (sztext == nullptr || sztext[0] == '\0') - return 0; - - size_t len = mir_wstrlen(sztext); - - if (only_enable) { - for (auto &it : contacts) { - if (lstreq(sztext, it->szname) == 0 || lstreq(sztext, GetListName(it)) == 0) { - EnableButtons(hwndMain, it->hcontact); - return 0; - } - } - } - else { - for (auto &it : contacts) { - if (lstreq(sztext, GetListName(it), len) == 0) { - SetWindowText(hdlg, GetListName(it)); - SendMessage(hdlg, EM_SETSEL, (WPARAM)len, (LPARAM)-1); - EnableButtons(hwndMain, it->hcontact); - return 0; - } - } - } - - EnableButtons(hwndMain, NULL); - return 0; -} - -MCONTACT 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 - wchar_t cname[120] = L""; - - GetDlgItemText(hwndDlg, IDC_USERNAME, cname, _countof(cname)); - - for (auto &it : contacts) - if (!mir_wstrcmpi(cname, GetListName(it))) - return it->hcontact; - - return NULL; -} - -// get array position from handle -int GetItemPos(MCONTACT hcontact) -{ - for (auto &it : contacts) - if (hcontact == it->hcontact) - return contacts.indexOf(&it); - - return -1; -} - - -// 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; - - wchar_t sztext[120] = L""; - DWORD start; - DWORD end; - - int ret = SendMessage(hdlg, EM_GETSEL, (WPARAM)&start, (LPARAM)&end); - - GetWindowText(hdlg, sztext, _countof(sztext)); - - BOOL at_end = (mir_wstrlen(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, 0, (LPARAM)sztext); - GetWindowText(hdlg, sztext, _countof(sztext)); - } - - CheckText(hdlg, sztext, !at_end); - - return 1; - } - case WM_KEYUP: - { - wchar_t sztext[120] = L""; - - 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, FALSE, 0); - break; - } - } - else if (wparam == VK_DELETE) { - GetWindowText(hdlg, sztext, _countof(sztext)); - CheckText(hdlg, sztext, TRUE); - } - - return 0; - } - - case WM_GETDLGCODE: - return DLGC_WANTCHARS | DLGC_WANTARROWS; - } - - return mir_callNextSubclass(hdlg, EditProc, msg, wparam, lparam); -} - -HACCEL hAcct; -HHOOK hHook; - -// This function filters the message queue and translates -// the keyboard accelerators -LRESULT CALLBACK HookProc(int code, WPARAM, LPARAM lparam) +extern "C" __declspec(dllexport) int Load() { - if (code != MSGF_DIALOGBOX) - return 0; - - MSG *msg = (MSG*)lparam; - - if (hasNewHotkeyModule) { - int action = Hotkey_Check(msg, "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; - } + mir_getLP(&pluginInfo); - if (msg->message == WM_KEYDOWN && msg->wParam == VK_ESCAPE) { - switch (SendDlgItemMessage(hwndMain, IDC_USERNAME, CB_GETDROPPEDSTATE, 0, 0)) { - case FALSE: - SendMessage(hwndMain, WM_CLOSE, 0, 0); - break; + CreateServiceFunction(MS_QC_SHOW_DIALOG, ShowDialog); - case TRUE: - SendDlgItemMessage(hwndMain, IDC_USERNAME, CB_SHOWDROPDOWN, FALSE, 0); - break; - } - } + // hooks + hModulesLoaded = HookEvent(ME_SYSTEM_MODULESLOADED, ModulesLoaded); + hEventAdded = HookEvent(ME_DB_EVENT_ADDED, EventAdded); 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, wchar_t *name, wchar_t *key, HICON icon) -{ - wchar_t tmp[256]; - wchar_t *full = tmp; - - if (key == nullptr) - full = TranslateW(name); - else - mir_snwprintf(tmp, L"%s (%s)", TranslateW(name), key); - - SendDlgItemMessage(hwndDlg, dlgItem, BUTTONSETASFLATBTN, 0, 0); - SendDlgItemMessage(hwndDlg, dlgItem, BUTTONADDTOOLTIP, (LPARAM)full, BATF_UNICODE); - SendDlgItemMessage(hwndDlg, dlgItem, BM_SETIMAGE, IMAGE_ICON, (LPARAM)icon); -} - - -static void FillCheckbox(HWND hwndDlg, int dlgItem, wchar_t *name, wchar_t *key) -{ - wchar_t tmp[256]; - wchar_t *full = tmp; - - if (key == nullptr) - full = TranslateW(name); - else - mir_snwprintf(tmp, L"%s (%s)", TranslateW(name), key); - - SetDlgItemText(hwndDlg, dlgItem, 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); - - CreateWindow(L"STATIC", L"", 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, nullptr); - - if (!hasNewHotkeyModule) - hAcct = LoadAccelerators(hInst, MAKEINTRESOURCE(ACCEL_TABLE)); - - hHook = SetWindowsHookEx(WH_MSGFILTER, HookProc, nullptr, GetCurrentThreadId()); - - // Combo - SendDlgItemMessage(hwndDlg, IDC_USERNAME, EM_LIMITTEXT, (WPARAM)119, 0); - mir_subclassWindow(GetWindow(GetDlgItem(hwndDlg, IDC_USERNAME), GW_CHILD), EditProc); - - // Buttons - FillCheckbox(hwndDlg, IDC_SHOW_ALL_CONTACTS, LPGENW("Show all contacts"), hasNewHotkeyModule ? NULL : L"Ctrl+A"); - FillButton(hwndDlg, IDC_MESSAGE, LPGENW("Send message"), nullptr, Skin_LoadIcon(SKINICON_EVENT_MESSAGE)); - FillButton(hwndDlg, IDC_FILE, LPGENW("Send file"), hasNewHotkeyModule ? NULL : L"Ctrl+F", Skin_LoadIcon(SKINICON_EVENT_FILE)); - FillButton(hwndDlg, IDC_URL, LPGENW("Send URL"), hasNewHotkeyModule ? NULL : L"Ctrl+U", Skin_LoadIcon(SKINICON_EVENT_URL)); - FillButton(hwndDlg, IDC_USERINFO, LPGENW("Open user info"), hasNewHotkeyModule ? NULL : L"Ctrl+I", Skin_LoadIcon(SKINICON_OTHER_USERDETAILS)); - FillButton(hwndDlg, IDC_HISTORY, LPGENW("Open history"), hasNewHotkeyModule ? NULL : L"Ctrl+H", Skin_LoadIcon(SKINICON_OTHER_HISTORY)); - FillButton(hwndDlg, IDC_MENU, LPGENW("Open contact menu"), hasNewHotkeyModule ? NULL : L"Ctrl+M", Skin_LoadIcon(SKINICON_OTHER_DOWNARROW)); - - SendDlgItemMessage(hwndDlg, IDC_USERNAME, CB_SETEXTENDEDUI, TRUE, 0); - - Utils_RestoreWindowPositionNoSize(hwndDlg, NULL, MODULE_NAME, "window"); - - LoadContacts(hwndDlg, FALSE); - - EnableButtons(hwndDlg, NULL); - if (db_get_b(NULL, MODULE_NAME, "EnableLastSentTo", 0)) { - int pos = GetItemPos((MCONTACT)db_get_dw(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: - { - MCONTACT hContact = GetSelectedContact(hwndDlg); - if (hContact == NULL) - break; - - Clist_ContactDoubleClicked(hContact); - - db_set_dw(NULL, MODULE_NAME, "LastSentTo", hContact); - SendMessage(hwndDlg, WM_CLOSE, 0, 0); - } - break; - case IDC_MESSAGE: - { - MCONTACT hContact = GetSelectedContact(hwndDlg); - if (hContact == NULL) { - SetDlgItemText(hwndDlg, IDC_USERNAME, L""); - SetFocus(GetDlgItem(hwndDlg, IDC_USERNAME)); - break; - } - - // Is button enabled? - if (!IsWindowEnabled(GetDlgItem(hwndDlg, IDC_MESSAGE))) - break; - - CallService(MS_MSG_SENDMESSAGEW, hContact, 0); - - db_set_dw(NULL, MODULE_NAME, "LastSentTo", hContact); - SendMessage(hwndDlg, WM_CLOSE, 0, 0); - break; - } - - case HOTKEY_FILE: - case IDC_FILE: - { - MCONTACT hContact = GetSelectedContact(hwndDlg); - if (hContact == NULL) { - SetDlgItemText(hwndDlg, IDC_USERNAME, L""); - SetFocus(GetDlgItem(hwndDlg, IDC_USERNAME)); - break; - } - - // Is button enabled? - if (!IsWindowEnabled(GetDlgItem(hwndDlg, IDC_FILE))) - break; - - CallService(MS_FILE_SENDFILE, hContact, 0); - - db_set_dw(NULL, MODULE_NAME, "LastSentTo", hContact); - SendMessage(hwndDlg, WM_CLOSE, 0, 0); - } - break; - - case HOTKEY_URL: - case IDC_URL: - { - MCONTACT hContact = GetSelectedContact(hwndDlg); - if (hContact == NULL) { - SetDlgItemText(hwndDlg, IDC_USERNAME, L""); - SetFocus(GetDlgItem(hwndDlg, IDC_USERNAME)); - break; - } - - // Is button enabled? - if (!IsWindowEnabled(GetDlgItem(hwndDlg, IDC_URL))) - break; - - CallService(MS_URL_SENDURL, hContact, 0); - - db_set_dw(NULL, MODULE_NAME, "LastSentTo", hContact); - SendMessage(hwndDlg, WM_CLOSE, 0, 0); - } - break; - - case HOTKEY_INFO: - case IDC_USERINFO: - { - MCONTACT hContact = GetSelectedContact(hwndDlg); - if (hContact == NULL) { - SetDlgItemText(hwndDlg, IDC_USERNAME, L""); - SetFocus(GetDlgItem(hwndDlg, IDC_USERNAME)); - break; - } - - // Is button enabled? - if (!IsWindowEnabled(GetDlgItem(hwndDlg, IDC_USERINFO))) - break; - - CallService(MS_USERINFO_SHOWDIALOG, hContact, 0); - - db_set_dw(NULL, MODULE_NAME, "LastSentTo", hContact); - SendMessage(hwndDlg, WM_CLOSE, 0, 0); - } - break; - - case HOTKEY_HISTORY: - case IDC_HISTORY: - { - MCONTACT hContact = GetSelectedContact(hwndDlg); - if (hContact == NULL) { - SetDlgItemText(hwndDlg, IDC_USERNAME, L""); - SetFocus(GetDlgItem(hwndDlg, IDC_USERNAME)); - break; - } - - // Is button enabled? - if (!IsWindowEnabled(GetDlgItem(hwndDlg, IDC_HISTORY))) - break; - - CallService(MS_HISTORY_SHOWCONTACTHISTORY, hContact, 0); - - db_set_dw(NULL, MODULE_NAME, "LastSentTo", hContact); - SendMessage(hwndDlg, WM_CLOSE, 0, 0); - } - break; - - case HOTKEY_MENU: - case IDC_MENU: - { - MCONTACT hContact = GetSelectedContact(hwndDlg); - if (hContact == NULL) { - SetDlgItemText(hwndDlg, IDC_USERNAME, L""); - 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 = Menu_BuildContactMenu(hContact); - int ret = TrackPopupMenu(hMenu, TPM_TOPALIGN | TPM_RIGHTBUTTON | TPM_RETURNCMD, rc.left, rc.bottom, 0, hwndDlg, nullptr); - DestroyMenu(hMenu); - - if (ret) { - SendMessage(hwndDlg, WM_CLOSE, 0, 0); - Clist_MenuProcessCommand(LOWORD(ret), MPCF_CONTACTMENU, hContact); - } - - db_set_dw(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); - wchar_t sztext[120] = L""; - - if (SendMessage(hEdit, EM_GETSEL, 0, 0) != -1) - SendMessage(hEdit, EM_REPLACESEL, 0, (LPARAM)L""); - - GetWindowText(hEdit, sztext, _countof(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; - - case WM_CLOSE: - Utils_SaveWindowPosition(hwndDlg, NULL, MODULE_NAME, "window"); - DestroyWindow(hwndDlg); - break; - - case WM_DESTROY: - UnhookWindowsHookEx(hHook); - hwndMain = nullptr; - FreeContacts(); - InterlockedExchange(&main_dialog_open, 0); - 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 Menu_DrawItem(lParam); - 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, Clist_GetContactIcon(contacts[lpdis->itemData]->hcontact), 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 (auto &it : contacts) { - RECT rcc = { 0, 0, 0x7FFF, 0x7FFF }; - DrawText(lpdis->hDC, it->proto, -1, &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, -1, &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, -1, &rc_tmp, DT_END_ELLIPSIS | DT_NOPREFIX | DT_SINGLELINE); - } - - // Draw text - wchar_t *name; - if (opts.group_append && !opts.group_column) - name = GetListName(contacts[lpdis->itemData]); - else - name = contacts[lpdis->itemData]->szname; - - DrawText(lpdis->hDC, name, -1, &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 Menu_MeasureItem(lParam); - 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, LPARAM) +extern "C" __declspec(dllexport) int Unload(void) { - if (!main_dialog_open) { - InterlockedExchange(&main_dialog_open, 1); - - hwndMain = CreateDialog(hInst, MAKEINTRESOURCE(IDD_MAIN), nullptr, MainDlgProc); - } + FreeContacts(); - // Show it - SetForegroundWindow(hwndMain); - SetFocus(hwndMain); - ShowWindow(hwndMain, SW_SHOW); + DeInitOptions(); + UnhookEvent(hModulesLoaded); + UnhookEvent(hEventAdded); return 0; } diff --git a/plugins/QuickContacts/src/stdafx.h b/plugins/QuickContacts/src/stdafx.h index b349233266..842eee329e 100644 --- a/plugins/QuickContacts/src/stdafx.h +++ b/plugins/QuickContacts/src/stdafx.h @@ -25,7 +25,6 @@ Boston, MA 02111-1307, USA. #include #include -#define __NO_CMPLUGIN_NEEDED #include #include #include @@ -52,13 +51,14 @@ Boston, MA 02111-1307, USA. #include "options.h" #include "version.h" -#define MODULE_NAME "QuickContacts" +#define MODULE_NAME "QuickContacts" - -// Global Variables -extern HINSTANCE hInst; - -// Copied from "../modernb/clc.h" /////////////////////////////////////////////////////////////////// +struct CMPlugin : public PLUGIN +{ + CMPlugin() : + PLUGIN(MODULE_NAME) + {} +}; //add a new hotkey so it has a default and can be changed in the options dialog //wParam=0 @@ -78,6 +78,4 @@ typedef struct { #define MS_SKIN_ADDHOTKEY "Skin/HotKeys/AddNew" #define MS_SKIN_PLAYHOTKEY "Skin/HotKeys/Run" - - #endif // __COMMONS_H__ -- cgit v1.2.3