From ac13aa1584ca595da727308406c87ec1bd9f5a21 Mon Sep 17 00:00:00 2001 From: George Hazan Date: Tue, 8 Jul 2014 12:14:56 +0000 Subject: FavContacts: - broken group functionality restored; - metacontacts support (patch by bio); - built-in http server wiped out; - optimized memory usage; - version bump git-svn-id: http://svn.miranda-ng.org/main/trunk@9730 1316c22d-e87f-b044-9b9b-93d7a3e3ba9c --- plugins/FavContacts/favcontacts_10.vcxproj | 9 +- plugins/FavContacts/favcontacts_10.vcxproj.filters | 15 +- plugins/FavContacts/favcontacts_12.vcxproj | 9 +- plugins/FavContacts/favcontacts_12.vcxproj.filters | 15 +- plugins/FavContacts/src/Version.h | 2 +- plugins/FavContacts/src/cserver.cpp | 65 -- plugins/FavContacts/src/cserver.h | 42 - plugins/FavContacts/src/csocket.cpp | 19 - plugins/FavContacts/src/csocket.h | 16 - plugins/FavContacts/src/favlist.h | 85 +- plugins/FavContacts/src/headers.h | 31 +- plugins/FavContacts/src/http_api.cpp | 161 --- plugins/FavContacts/src/http_api.h | 7 - plugins/FavContacts/src/main.cpp | 1069 +------------------- plugins/FavContacts/src/menu.cpp | 552 ++++++++++ plugins/FavContacts/src/options.cpp | 280 +++++ plugins/FavContacts/src/services.cpp | 263 +++++ 17 files changed, 1184 insertions(+), 1456 deletions(-) delete mode 100644 plugins/FavContacts/src/cserver.cpp delete mode 100644 plugins/FavContacts/src/cserver.h delete mode 100644 plugins/FavContacts/src/csocket.cpp delete mode 100644 plugins/FavContacts/src/csocket.h delete mode 100644 plugins/FavContacts/src/http_api.cpp delete mode 100644 plugins/FavContacts/src/http_api.h create mode 100644 plugins/FavContacts/src/menu.cpp create mode 100644 plugins/FavContacts/src/options.cpp create mode 100644 plugins/FavContacts/src/services.cpp diff --git a/plugins/FavContacts/favcontacts_10.vcxproj b/plugins/FavContacts/favcontacts_10.vcxproj index 23eeb73d51..a43efec15f 100644 --- a/plugins/FavContacts/favcontacts_10.vcxproj +++ b/plugins/FavContacts/favcontacts_10.vcxproj @@ -179,21 +179,18 @@ - - - + + + Create - - - diff --git a/plugins/FavContacts/favcontacts_10.vcxproj.filters b/plugins/FavContacts/favcontacts_10.vcxproj.filters index 305b7789aa..87c0bb1dc3 100644 --- a/plugins/FavContacts/favcontacts_10.vcxproj.filters +++ b/plugins/FavContacts/favcontacts_10.vcxproj.filters @@ -24,13 +24,13 @@ Source Files - + Source Files - + Source Files - + Source Files @@ -50,15 +50,6 @@ Header Files - - Header Files - - - Header Files - - - Header Files - diff --git a/plugins/FavContacts/favcontacts_12.vcxproj b/plugins/FavContacts/favcontacts_12.vcxproj index 92f1f0d43b..7c12a92107 100644 --- a/plugins/FavContacts/favcontacts_12.vcxproj +++ b/plugins/FavContacts/favcontacts_12.vcxproj @@ -182,21 +182,18 @@ - - - + + + Create - - - diff --git a/plugins/FavContacts/favcontacts_12.vcxproj.filters b/plugins/FavContacts/favcontacts_12.vcxproj.filters index 305b7789aa..e82f9659cd 100644 --- a/plugins/FavContacts/favcontacts_12.vcxproj.filters +++ b/plugins/FavContacts/favcontacts_12.vcxproj.filters @@ -24,13 +24,13 @@ Source Files - + Source Files - + Source Files - + Source Files @@ -50,15 +50,6 @@ Header Files - - Header Files - - - Header Files - - - Header Files - diff --git a/plugins/FavContacts/src/Version.h b/plugins/FavContacts/src/Version.h index 6a8c822637..4b36aad0ac 100644 --- a/plugins/FavContacts/src/Version.h +++ b/plugins/FavContacts/src/Version.h @@ -1,7 +1,7 @@ #define __MAJOR_VERSION 0 #define __MINOR_VERSION 1 #define __RELEASE_NUM 0 -#define __BUILD_NUM 1 +#define __BUILD_NUM 2 #include diff --git a/plugins/FavContacts/src/cserver.cpp b/plugins/FavContacts/src/cserver.cpp deleted file mode 100644 index 881f84cec2..0000000000 --- a/plugins/FavContacts/src/cserver.cpp +++ /dev/null @@ -1,65 +0,0 @@ -#include "headers.h" - -void CServer::Start(int port, IConnectionProcessorFactory *connectionProcessorFactory, bool background) -{ - m_socket = socket(AF_INET, SOCK_STREAM, 0); - if (m_socket == INVALID_SOCKET) return; - - sockaddr_in addr = { 0 }; - addr.sin_family = AF_INET; - addr.sin_addr.s_addr = htonl(INADDR_LOOPBACK); - addr.sin_port = htons((WORD)port); - if (bind(m_socket, (sockaddr *)&addr, sizeof(addr)) == SOCKET_ERROR) { - closesocket(m_socket); - m_socket = INVALID_SOCKET; - return; - } - - listen(m_socket, SOMAXCONN); - - m_connectionProcessorFactory = connectionProcessorFactory; - - if (background) - mir_forkthread(GlobalConnectionAcceptThread, this); - else - ConnectionAcceptThread(); -} - -void CServer::Stop() -{ - shutdown(m_socket, SD_BOTH); - closesocket(m_socket); -} - -DWORD CServer::ConnectionAcceptThread() -{ - while (1) { - SOCKET s = accept(m_socket, NULL, NULL); - if (s == INVALID_SOCKET) break; - - mir_forkthread(GlobalConnectionProcessThread, new GlobalConnectionProcessThreadArgs(this, s)); - } - return 0; -} - -DWORD CServer::ConnectionProcessThread(SOCKET s) -{ - CSocket sock(s); - IConnectionProcessor *processor = m_connectionProcessorFactory->Create(&sock); - processor->ProcessConnection(); - delete processor; - return 0; -} - -void CServer::GlobalConnectionAcceptThread(void *arg) -{ - CServer *server = (CServer *)arg; - server->ConnectionAcceptThread(); -} - -void CServer::GlobalConnectionProcessThread(void *arg) -{ - GlobalConnectionProcessThreadArgs *args = (GlobalConnectionProcessThreadArgs *)arg; - args->m_server->ConnectionProcessThread(args->m_socket); - delete args; -} diff --git a/plugins/FavContacts/src/cserver.h b/plugins/FavContacts/src/cserver.h deleted file mode 100644 index f96c87b2c1..0000000000 --- a/plugins/FavContacts/src/cserver.h +++ /dev/null @@ -1,42 +0,0 @@ -#ifndef cserver_h__ -#define cserver_h__ - -class IConnectionProcessor -{ -public: - virtual ~IConnectionProcessor() {} - virtual void ProcessConnection() = 0; -}; - -class IConnectionProcessorFactory -{ -public: - virtual IConnectionProcessor *Create(CSocket *s) = 0; -}; - -class CServer -{ -private: - SOCKET m_socket; - IConnectionProcessorFactory *m_connectionProcessorFactory; - - DWORD ConnectionAcceptThread(); - DWORD ConnectionProcessThread(SOCKET s); - - static void GlobalConnectionAcceptThread(void *arg); - - struct GlobalConnectionProcessThreadArgs - { - CServer *m_server; - SOCKET m_socket; - - GlobalConnectionProcessThreadArgs(CServer *server, SOCKET s): m_server(server), m_socket(s) {} - }; - static void GlobalConnectionProcessThread(void *arg); - -public: - void Start(int port, IConnectionProcessorFactory *connectionProcessorFactory, bool background); - void Stop(); -}; - -#endif // cserver_h__ diff --git a/plugins/FavContacts/src/csocket.cpp b/plugins/FavContacts/src/csocket.cpp deleted file mode 100644 index b3d53d60f1..0000000000 --- a/plugins/FavContacts/src/csocket.cpp +++ /dev/null @@ -1,19 +0,0 @@ -#include "headers.h" - -int CSocket::Recv(char *buf, int count) -{ - return recv(m_socket, buf, count, 0); -} - -int CSocket::Send(char *buf, int count) -{ - if (count < 0) - count = (int)strlen(buf); - return send(m_socket, buf, count, 0); -} - -void CSocket::Close() -{ - shutdown(m_socket, SD_BOTH); - closesocket(m_socket); -} diff --git a/plugins/FavContacts/src/csocket.h b/plugins/FavContacts/src/csocket.h deleted file mode 100644 index 3fa1c87852..0000000000 --- a/plugins/FavContacts/src/csocket.h +++ /dev/null @@ -1,16 +0,0 @@ -#ifndef csocket_h__ -#define csocket_h__ - -class CSocket -{ -protected: - SOCKET m_socket; - -public: - CSocket(SOCKET socket = INVALID_SOCKET): m_socket(socket) {} - int Recv(char *buf, int count); - int Send(char *buf, int count = -1); - void Close(); -}; - -#endif // csocket_h__ diff --git a/plugins/FavContacts/src/favlist.h b/plugins/FavContacts/src/favlist.h index b420f49c23..4aeeed62e8 100644 --- a/plugins/FavContacts/src/favlist.h +++ b/plugins/FavContacts/src/favlist.h @@ -12,26 +12,19 @@ private: float fRate; public: - TContactInfo(MCONTACT hContact, bool bManual, float fRate = 0) + TContactInfo(MCONTACT _hContact, bool _bManual, float _fRate = 0) : + hContact(_hContact), + bManual(_bManual), + fRate(_fRate) { - DBVARIANT dbv = {0}; + name = mir_tstrdup(pcli->pfnGetContactDisplayName(hContact, 0)); - this->hContact = hContact; - this->bManual = bManual; - this->fRate = fRate; - name = mir_tstrdup((TCHAR *)CallService(MS_CLIST_GETCONTACTDISPLAYNAME, hContact, GCDNF_TCHAR)); - if (g_Options.bUseGroups && !db_get_ts(hContact, "CList", "Group", &dbv)) - { - group = mir_tstrdup(dbv.ptszVal); - db_free(&dbv); - } else - if (g_Options.bUseGroups) - { - group = mir_tstrdup(TranslateT("")); - } else - { - group = mir_tstrdup(TranslateT("Favorite Contacts")); + if (g_Options.bUseGroups) { + if ((group = db_get_tsa(hContact, "CList", "Group")) == NULL) + group = mir_tstrdup(TranslateT("")); } + else group = mir_tstrdup(TranslateT("Favorite Contacts")); + status = db_get_w(hContact, GetContactProto(hContact), "Status", ID_STATUS_OFFLINE); } @@ -64,30 +57,45 @@ public: int res = 0; if (res = lstrcmp(p1->group, p2->group)) return res; - //if (p1->status < p2->status) return -1; - //if (p1->status < p2->status) return +1; if (res = lstrcmp(p1->name, p2->name)) return res; return 0; } }; -class TFavContacts: public LIST +class TFavContacts : public LIST < TContactInfo > { private: int nGroups; + TCHAR *prevGroup; + + void addContact(MIDatabase *db, MCONTACT hContact, bool bManual) + { + DBCachedContact *cc = db->m_cache->GetCachedContact(hContact); + if (cc == NULL) + return; + + if (db_mc_isEnabled()) { + if (cc->IsSub()) // skip subcontacts if MC is enabled + return; + } + else if (cc->IsMeta()) // skip metacontacts if MC is not enabled + return; + + TCHAR *group = addContact(hContact, bManual)->getGroup(); + if (prevGroup && lstrcmp(prevGroup, group)) + ++nGroups; + prevGroup = group; + } public: - TFavContacts(): LIST(5, TContactInfo::cmp) {} + TFavContacts() : LIST(5, TContactInfo::cmp) {} ~TFavContacts() { for (int i = 0; i < this->getCount(); ++i) delete (*this)[i]; } - int groupCount() - { - return nGroups; - } + __forceinline int groupCount() const { return nGroups; } TContactInfo *addContact(MCONTACT hContact, bool bManual) { @@ -98,31 +106,24 @@ public: void build() { - TCHAR *prevGroup = NULL; - + prevGroup = NULL; + MIDatabase *db = GetCurrentDatabase(); + nGroups = 1; for (MCONTACT hContact = db_find_first(); hContact; hContact = db_find_next(hContact)) if (db_get_b(hContact, "FavContacts", "IsFavourite", 0)) - { - TCHAR *group = addContact(hContact, true)->getGroup(); - if (prevGroup && lstrcmp(prevGroup, group)) - ++nGroups; - prevGroup = group; - } + addContact(db, hContact, true); int nRecent = 0; for (int i = 0; nRecent < g_Options.wMaxRecent; ++i) { MCONTACT hContact = g_contactCache->get(i); - if (!hContact) break; - if (!db_get_b(hContact, "FavContacts", "IsFavourite", 0)) - { - TCHAR *group = addContact(hContact, false)->getGroup(); - if (prevGroup && lstrcmp(prevGroup, group)) - ++nGroups; - prevGroup = group; - - ++nRecent; + if (!hContact) + break; + + if (!db_get_b(hContact, "FavContacts", "IsFavourite", 0)) { + addContact(db, hContact, false); + nRecent++; } } } diff --git a/plugins/FavContacts/src/headers.h b/plugins/FavContacts/src/headers.h index f705c9a5d1..bf6bda4158 100644 --- a/plugins/FavContacts/src/headers.h +++ b/plugins/FavContacts/src/headers.h @@ -32,6 +32,7 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. #include #include #include +#include #include #include #include @@ -45,15 +46,18 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. #include #include #include - +#include #include #include "resource.h" #include "version.h" #include "contact_cache.h" -#include "http_api.h" -#include "csocket.h" -#include "cserver.h" + +///////////////////////////////////////////////////////////////////////////////////////// + +#define MS_FAVCONTACTS_SHOWMENU "FavContacts/ShowMenu" +#define MS_FAVCONTACTS_SHOWMENU_CENTERED "FavContacts/ShowMenuCentered" +#define MS_FAVCONTACTS_OPEN_CONTACT "FavContacts/OpenContact" struct Options { @@ -77,4 +81,23 @@ struct Options extern Options g_Options; extern CContactCache *g_contactCache; + #include "favlist.h" + +BOOL MenuDrawItem(LPDRAWITEMSTRUCT lpdis, Options *options = NULL); +BOOL MenuMeasureItem(LPMEASUREITEMSTRUCT lpmis, Options *options = NULL); + +int ProcessOptInitialise(WPARAM, LPARAM); +int ProcessModulesLoaded(WPARAM, LPARAM); + +void LoadOptions(); +int ShowMenu(bool centered); + +void InitMenu(); +void UninitMenu(); + +void InitServices(); +void UninitServices(); + +extern HINSTANCE g_hInst; +extern IconItem iconList[]; diff --git a/plugins/FavContacts/src/http_api.cpp b/plugins/FavContacts/src/http_api.cpp deleted file mode 100644 index 38705d3927..0000000000 --- a/plugins/FavContacts/src/http_api.cpp +++ /dev/null @@ -1,161 +0,0 @@ -#include "headers.h" - -#define MS_FAVCONTACTS_OPEN_CONTACT "FavContacts/OpenContact" - -class CHttpProcessor: public IConnectionProcessor -{ -private: - CSocket *m_socket; - - char *FetchURL(char *s) - { - char *p; - if (p = strstr(s, "\r\n")) *p = 0; - if (p = strrchr(s, ' ')) *p = 0; - if (p = strchr(s, ' ')) while (*p && *p == ' ') p++; - return mir_strdup(p); - } - -public: - CHttpProcessor(CSocket *s): m_socket(s) {} - - void ProcessConnection() - { - char buf[1024]; - int n = m_socket->Recv(buf, sizeof(buf)); - buf[n] = 0; - - char *s = FetchURL(buf); - - if (!strncmp(s, "/fav/list/", 10)) - { - SendList(); - } else - if (!strncmp(s, "/fav/open/", 10)) - { - OpenContact(s); - } - - mir_free(s); - m_socket->Close(); - } - - void OpenContact(char *s) - { - m_socket->Send("HTTP 200 OK\r\n\r\n"); - - int hContact; - sscanf(s, "/fav/open/%d", &hContact); - if (CallService(MS_DB_CONTACT_IS, hContact, 0)) - CallServiceSync(MS_FAVCONTACTS_OPEN_CONTACT, hContact, 0); - } - - void SendList() - { - TFavContacts favList; - favList.build(); - - m_socket->Send( - "HTTP 200 OK\r\n" - "Content-Type: text/javascript\r\n" - "\r\n"); - - Send("try {\r\n"); - Send("SetContactCount("); - Send(favList.getCount()); - Send(");\r\n"); - - for (int i = 0; i < favList.getCount(); ++i) - { - MCONTACT hContact = favList[i]->getHandle(); - TCHAR *name = (TCHAR *)CallService(MS_CLIST_GETCONTACTDISPLAYNAME, hContact, GCDNF_TCHAR); - AVATARCACHEENTRY *avatar = (AVATARCACHEENTRY *)CallService(MS_AV_GETAVATARBITMAP, hContact, 0); - int status = db_get_w(hContact, GetContactProto(hContact), "Status", ID_STATUS_OFFLINE); - - Send("SetContact("); - Send(i); - Send(", "); - Send((int)hContact); - Send(", '"); - SendQuoted(name); - Send("', "); - Send(status); - Send(", '"); - SendQuoted(avatar ? avatar->szFilename : _T("")); - Send("');\r\n"); - } - Send("} catch(e) {}\r\n"); - } - - void Send(char *s) - { - m_socket->Send(s); - } - - - void Send(WCHAR *ws) - { - char *s = mir_utf8encodeW(ws); - m_socket->Send(s); - mir_free(s); - } - - - void Send(int i) - { - char buf[32]; - mir_snprintf(buf, SIZEOF(buf), "%d", i); - Send(buf); - } - - template - void SendQuoted(const XCHAR *s) - { - int length = 0; - const XCHAR *p; - for (p = s; *p; p++) - { - if (*p == '\'' || *p == '\\' || *p == '\"') - length++; - length++; - } - XCHAR *buf = (XCHAR *)mir_alloc(sizeof(XCHAR) * (length + 1)); - XCHAR *q = buf; - for (p = s; *p; p++) - { - if (*p == '\'' || *p == '\\' || *p == '\"') - { - *q = '\\'; - q++; - } - *q = *p; - q++; - } - *q = 0; - Send(buf); - mir_free(buf); - } -}; - -class CHttpProcessorFactory: public IConnectionProcessorFactory -{ -public: - IConnectionProcessor *Create(CSocket *s) - { - return new CHttpProcessor(s); - } -}; - -static CHttpProcessorFactory g_httpProcessorFactory; -static CServer g_httpServer; - -void LoadHttpApi() -{ - g_httpServer.Start(60888, &g_httpProcessorFactory, true); -} - -int UnloadHttpApi(WPARAM, LPARAM) -{ - g_httpServer.Stop(); - return 0; -} diff --git a/plugins/FavContacts/src/http_api.h b/plugins/FavContacts/src/http_api.h deleted file mode 100644 index 936becc0e0..0000000000 --- a/plugins/FavContacts/src/http_api.h +++ /dev/null @@ -1,7 +0,0 @@ -#ifndef http_api_h__ -#define http_api_h__ - -void LoadHttpApi(); -int UnloadHttpApi(WPARAM, LPARAM); - -#endif // http_api_h__ diff --git a/plugins/FavContacts/src/main.cpp b/plugins/FavContacts/src/main.cpp index 2521f730c6..e9847b6821 100644 --- a/plugins/FavContacts/src/main.cpp +++ b/plugins/FavContacts/src/main.cpp @@ -40,43 +40,16 @@ PLUGININFOEX pluginInfo = { {0xce2c0401, 0xf9e0, 0x40d7, {0x8e, 0x95, 0x1a, 0x41, 0x97, 0xd7, 0xab, 0x4}} }; -static IconItem iconList[] = +IconItem iconList[] = { { LPGEN("Favorite Contact"), "favcontacts_favorite", IDI_FAVORITE }, { LPGEN("Regular Contact"), "favcontacts_regular", IDI_REGULAR }, }; -#define MS_FAVCONTACTS_SHOWMENU "FavContacts/ShowMenu" -#define MS_FAVCONTACTS_SHOWMENU_CENTERED "FavContacts/ShowMenuCentered" -#define MS_FAVCONTACTS_OPEN_CONTACT "FavContacts/OpenContact" - -HWND g_hwndMenuHost = NULL; -static LRESULT CALLBACK MenuHostWndProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam); -static INT_PTR CALLBACK OptionsDlgProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam); - -static void sttLoadOptions(); -static void sttSaveOptions(); - -int sttShowMenu(bool centered); - -INT_PTR svcOpenContact(WPARAM wParam, LPARAM lParam); - -INT_PTR svcShowMenu(WPARAM wParam, LPARAM lParam); -INT_PTR svcShowMenuCentered(WPARAM wParam, LPARAM lParam); -int ProcessSrmmEvent(WPARAM wParam, LPARAM lParam); -int ProcessSrmmIconClick(WPARAM wParam, LPARAM lParam); - -float g_widthMultiplier = 0; -UINT g_maxItemWidth = 0; - CContactCache *g_contactCache = NULL; -TCHAR g_filter[1024] = { 0 }; Options g_Options = { 0 }; -static HANDLE hDialogsList = NULL; -static MCONTACT hContactToActivate = NULL; - BOOL WINAPI DllMain(HINSTANCE hinstDLL, DWORD fdwReason, LPVOID lpvReserved) { g_hInst = hinstDLL; @@ -88,177 +61,6 @@ extern "C" __declspec(dllexport) PLUGININFOEX *MirandaPluginInfoEx(DWORD miranda return &pluginInfo; } -static __forceinline COLORREF sttShadeColor(COLORREF clLine1, COLORREF clBack) -{ - return RGB( - (GetRValue(clLine1) * 66UL + GetRValue(clBack) * 34UL) / 100, - (GetGValue(clLine1) * 66UL + GetGValue(clBack) * 34UL) / 100, - (GetBValue(clLine1) * 66UL + GetBValue(clBack) * 34UL) / 100); -} - -static TCHAR* sttGetGroupName(int id) -{ - if (id == 1) { - if (g_Options.bUseGroups) - return TranslateT(""); - return TranslateT("Favorite Contacts"); - } - - return pcli->pfnGetGroupName(id - 1, NULL); -} - -int ProcessTBLoaded(WPARAM wParam, LPARAM lParam) -{ - TTBButton ttb = { sizeof(ttb) }; - ttb.pszTooltipUp = ttb.name = LPGEN("Favorite Contacts"); - ttb.pszService = MS_FAVCONTACTS_SHOWMENU; - ttb.dwFlags = TTBBF_SHOWTOOLTIP | TTBBF_VISIBLE; - ttb.hIconHandleUp = iconList[0].hIcolib; - TopToolbar_AddButton(&ttb); - return 0; -} - -int ProcessReloadFonts(WPARAM wParam, LPARAM lParam) -{ - if (g_Options.hfntName) DeleteObject(g_Options.hfntName); - if (g_Options.hfntSecond) DeleteObject(g_Options.hfntSecond); - - LOGFONT lf = { 0 }; - FontIDT fontid = { sizeof(fontid) }; - lstrcpy(fontid.group, LPGENT("Favorite Contacts")); - lstrcpy(fontid.name, LPGENT("Contact name")); - g_Options.clLine1 = CallService(MS_FONT_GETT, (WPARAM)&fontid, (LPARAM)&lf); - g_Options.hfntName = CreateFontIndirect(&lf); - - lstrcpy(fontid.name, LPGENT("Second line")); - g_Options.clLine2 = CallService(MS_FONT_GETT, (WPARAM)&fontid, (LPARAM)&lf); - g_Options.hfntSecond = CreateFontIndirect(&lf); - - lstrcpy(fontid.name, LPGENT("Selected contact name (color)")); - g_Options.clLine1Sel = CallService(MS_FONT_GETT, (WPARAM)&fontid, (LPARAM)&lf); - - lstrcpy(fontid.name, LPGENT("Selected second line (color)")); - g_Options.clLine2Sel = CallService(MS_FONT_GETT, (WPARAM)&fontid, (LPARAM)&lf); - - ColourIDT colourid = { sizeof(colourid) }; - lstrcpy(colourid.group, LPGENT("Favorite Contacts")); - lstrcpy(colourid.name, LPGENT("Background")); - g_Options.clBack = CallService(MS_COLOUR_GETT, (WPARAM)&colourid, (LPARAM)&lf); - - lstrcpy(colourid.name, LPGENT("Selected background")); - g_Options.clBackSel = CallService(MS_COLOUR_GETT, (WPARAM)&colourid, (LPARAM)&lf); - - return 0; -} - -int ProcessModulesLoaded(WPARAM wParam, LPARAM lParam) -{ - HookEvent(ME_TTB_MODULELOADED, ProcessTBLoaded); - - StatusIconData sid = { sizeof(sid) }; - sid.szModule = "FavContacts"; - sid.szTooltip = LPGEN("Favorite Contacts"); - sid.hIcon = Skin_GetIconByHandle(iconList[0].hIcolib); - sid.hIconDisabled = Skin_GetIconByHandle(iconList[1].hIcolib); - Srmm_AddIcon(&sid); - - HookEvent(ME_MSG_ICONPRESSED, ProcessSrmmIconClick); - HookEvent(ME_MSG_WINDOWEVENT, ProcessSrmmEvent); - - ///////////////////////////////////////////////////////////////////////////////////// - - FontIDT fontid = { sizeof(fontid) }; - lstrcpy(fontid.group, LPGENT("Favorite Contacts")); - lstrcpyA(fontid.dbSettingsGroup, "FavContacts"); - lstrcpy(fontid.backgroundGroup, LPGENT("Favorite Contacts")); - fontid.flags = FIDF_DEFAULTVALID; - fontid.deffontsettings.charset = DEFAULT_CHARSET; - fontid.deffontsettings.size = -11; - lstrcpy(fontid.deffontsettings.szFace, _T("MS Shell Dlg")); - fontid.deffontsettings.style = 0; - - lstrcpy(fontid.backgroundName, LPGENT("Background")); - - lstrcpy(fontid.name, LPGENT("Contact name")); - lstrcpyA(fontid.prefix, "fntName"); - fontid.deffontsettings.colour = GetSysColor(COLOR_MENUTEXT); - fontid.deffontsettings.style = DBFONTF_BOLD; - FontRegisterT(&fontid); - - lstrcpy(fontid.name, LPGENT("Second line")); - lstrcpyA(fontid.prefix, "fntSecond"); - fontid.deffontsettings.colour = sttShadeColor(GetSysColor(COLOR_MENUTEXT), GetSysColor(COLOR_MENU)); - fontid.deffontsettings.style = 0; - FontRegisterT(&fontid); - - lstrcpy(fontid.backgroundName, LPGENT("Selected background")); - - lstrcpy(fontid.name, LPGENT("Selected contact name (color)")); - lstrcpyA(fontid.prefix, "fntNameSel"); - fontid.deffontsettings.colour = GetSysColor(COLOR_HIGHLIGHTTEXT); - fontid.deffontsettings.style = DBFONTF_BOLD; - FontRegisterT(&fontid); - - lstrcpy(fontid.name, LPGENT("Selected second line (color)")); - lstrcpyA(fontid.prefix, "fntSecondSel"); - fontid.deffontsettings.colour = sttShadeColor(GetSysColor(COLOR_HIGHLIGHTTEXT), GetSysColor(COLOR_HIGHLIGHT)); - fontid.deffontsettings.style = 0; - FontRegisterT(&fontid); - - ///////////////////////////////////////////////////////////////////////////////////// - - ColourIDT colourid = { sizeof(colourid) }; - lstrcpy(colourid.group, LPGENT("Favorite Contacts")); - lstrcpyA(colourid.dbSettingsGroup, "FavContacts"); - - lstrcpy(colourid.name, LPGENT("Background")); - lstrcpyA(colourid.setting, "BackColour"); - colourid.defcolour = GetSysColor(COLOR_MENU); - ColourRegisterT(&colourid); - - lstrcpy(colourid.name, LPGENT("Selected background")); - lstrcpyA(colourid.setting, "SelectedColour"); - colourid.defcolour = GetSysColor(COLOR_HIGHLIGHT); - ColourRegisterT(&colourid); - - HookEvent(ME_FONT_RELOAD, ProcessReloadFonts); - HookEvent(ME_COLOUR_RELOAD, ProcessReloadFonts); - ProcessReloadFonts(0, 0); - - ///////////////////////////////////////////////////////////////////////////////////// - - HOTKEYDESC hotkey = { sizeof(hotkey) }; - hotkey.pszName = "FavContacts/ShowMenu"; - hotkey.pszDescription = LPGEN("Show favorite contacts"); - hotkey.pszSection = "Contacts"; - hotkey.pszService = MS_FAVCONTACTS_SHOWMENU_CENTERED; - hotkey.DefHotKey = MAKEWORD('Q', HOTKEYF_EXT); - Hotkey_Register(&hotkey); - - if (ServiceExists(MS_AV_GETAVATARBITMAP)) { - for (MCONTACT hContact = db_find_first(); hContact; hContact = db_find_next(hContact)) - if (db_get_b(hContact, "FavContacts", "IsFavourite", 0)) - CallService(MS_AV_GETAVATARBITMAP, hContact, 0); - } - - return 0; -} - -int ProcessOptInitialise(WPARAM wParam, LPARAM lParam) -{ - OPTIONSDIALOGPAGE odp = { sizeof(odp) }; - odp.position = 100000000; - odp.hInstance = g_hInst; - odp.pszTemplate = MAKEINTRESOURCEA(IDD_OPTIONS); - odp.pszGroup = LPGEN("Contacts"); - odp.pszTitle = LPGEN("Favorites"); - odp.groupPosition = 910000000; - odp.flags = ODPF_BOLDGROUPS; - odp.pfnDlgProc = OptionsDlgProc; - Options_AddPage(wParam, &odp); - return 0; -} - ///////////////////////////////////////////////////////////////////////////////////// extern "C" __declspec(dllexport) int Load(void) @@ -268,883 +70,24 @@ extern "C" __declspec(dllexport) int Load(void) g_contactCache = new CContactCache; - WNDCLASSEX wcl = { sizeof(wcl) }; - wcl.lpfnWndProc = MenuHostWndProc; - wcl.hInstance = g_hInst; - wcl.hCursor = LoadCursor(NULL, IDC_ARROW); - wcl.hbrBackground = (HBRUSH)GetStockObject(LTGRAY_BRUSH); - wcl.lpszClassName = _T("FavContactsMenuHostWnd"); - RegisterClassEx(&wcl); - - g_hwndMenuHost = CreateWindow(_T("FavContactsMenuHostWnd"), NULL, 0, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, HWND_DESKTOP, NULL, g_hInst, NULL); - SetWindowPos(g_hwndMenuHost, 0, 0, 0, 0, 0, SWP_NOZORDER | SWP_NOMOVE | SWP_NOSIZE | SWP_NOACTIVATE | SWP_DEFERERASE | SWP_NOSENDCHANGING | SWP_HIDEWINDOW); - - sttLoadOptions(); - - CreateServiceFunction(MS_FAVCONTACTS_SHOWMENU, svcShowMenu); - CreateServiceFunction(MS_FAVCONTACTS_SHOWMENU_CENTERED, svcShowMenuCentered); - CreateServiceFunction(MS_FAVCONTACTS_OPEN_CONTACT, svcOpenContact); - - HookEvent(ME_OPT_INITIALISE, ProcessOptInitialise); - HookEvent(ME_SYSTEM_MODULESLOADED, ProcessModulesLoaded); - HookEvent(ME_SYSTEM_SHUTDOWN, UnloadHttpApi); + InitMenu(); + InitServices(); + LoadOptions(); ///////////////////////////////////////////////////////////////////////////////////// Icon_Register(g_hInst, LPGEN("Favorites"), iconList, SIZEOF(iconList)); - - LoadHttpApi(); - -#ifdef _DEBUG - CLISTMENUITEM mi = { sizeof(mi) }; - mi.icolibItem = LoadSkinnedIconHandle(SKINICON_OTHER_OPTIONS); - mi.position = 1900000000; - mi.pszName = LPGEN("&Favorite Contacts..."); - mi.pszService = MS_FAVCONTACTS_SHOWMENU; - Menu_AddMainMenuItem(&mi); -#endif - return 0; } extern "C" __declspec(dllexport) int Unload(void) { - WindowList_Destroy(hDialogsList); + UninitServices(); + UninitMenu(); - if (g_hwndMenuHost) DestroyWindow(g_hwndMenuHost); if (g_Options.hfntName) DeleteObject(g_Options.hfntName); if (g_Options.hfntSecond) DeleteObject(g_Options.hfntSecond); delete g_contactCache; return 0; } - -static void sttLoadOptions() -{ - g_Options.bSecondLine = db_get_b(NULL, "FavContacts", "SecondLine", 1); - g_Options.bAvatars = db_get_b(NULL, "FavContacts", "Avatars", 1); - g_Options.bAvatarBorder = db_get_b(NULL, "FavContacts", "AvatarBorder", 0); - g_Options.wAvatarRadius = db_get_w(NULL, "FavContacts", "AvatarRadius", 3); - g_Options.bNoTransparentBorder = db_get_b(NULL, "FavContacts", "NoTransparentBorder", - !db_get_b(NULL, "FavContacts", "AvatarBorderTransparent", 1)); - g_Options.bSysColors = db_get_b(NULL, "FavContacts", "SysColors", 0); - g_Options.bCenterHotkey = db_get_b(NULL, "FavContacts", "CenterHotkey", 1); - g_Options.bUseGroups = db_get_b(NULL, "FavContacts", "UseGroups", 0); - g_Options.bUseColumns = db_get_b(NULL, "FavContacts", "UseColumns", 1); - g_Options.bRightAvatars = db_get_b(NULL, "FavContacts", "RightAvatars", 0); - g_Options.bDimIdle = db_get_b(NULL, "FavContacts", "DimIdle", 1); - - g_Options.wMaxRecent = db_get_b(NULL, "FavContacts", "MaxRecent", 10); -} - -static void sttSaveOptions() -{ - db_set_b(NULL, "FavContacts", "SecondLine", g_Options.bSecondLine); - db_set_b(NULL, "FavContacts", "Avatars", g_Options.bAvatars); - db_set_b(NULL, "FavContacts", "AvatarBorder", g_Options.bAvatarBorder); - db_set_w(NULL, "FavContacts", "AvatarRadius", g_Options.wAvatarRadius); - db_set_b(NULL, "FavContacts", "NoTransparentBorder", g_Options.bNoTransparentBorder); - db_set_b(NULL, "FavContacts", "SysColors", g_Options.bSysColors); - db_set_b(NULL, "FavContacts", "CenterHotkey", g_Options.bCenterHotkey); - db_set_b(NULL, "FavContacts", "UseGroups", g_Options.bUseGroups); - db_set_b(NULL, "FavContacts", "UseColumns", g_Options.bUseColumns); - db_set_b(NULL, "FavContacts", "RightAvatars", g_Options.bRightAvatars); - db_set_b(NULL, "FavContacts", "DimIdle", g_Options.bDimIdle); - db_set_w(NULL, "FavContacts", "MaxRecent", g_Options.wMaxRecent); -} - -static BOOL sttMeasureItem_Group(LPMEASUREITEMSTRUCT lpmis, Options *options) -{ - if (true) { - HDC hdc = GetDC(g_hwndMenuHost); - HFONT hfntSave = (HFONT)SelectObject(hdc, GetStockObject(DEFAULT_GUI_FONT)); - TCHAR *name = sttGetGroupName(lpmis->itemData); - SIZE sz; - if (!options->bSysColors) - SelectObject(hdc, g_Options.hfntName); - GetTextExtentPoint32(hdc, name, lstrlen(name), &sz); - lpmis->itemHeight = sz.cy + 8; - lpmis->itemWidth = sz.cx + 10; - SelectObject(hdc, hfntSave); - ReleaseDC(g_hwndMenuHost, hdc); - } - - return TRUE; -} - -static BOOL sttMeasureItem_Contact(LPMEASUREITEMSTRUCT lpmis, Options *options) -{ - MCONTACT hContact = (MCONTACT)lpmis->itemData; - - lpmis->itemHeight = 4; - lpmis->itemWidth = 8 + 10; - - if (true) { - lpmis->itemWidth += 20; - } - - if (true) { - SIZE sz; - int textWidth = 0; - - HDC hdc = GetDC(g_hwndMenuHost); - HFONT hfntSave = (HFONT)SelectObject(hdc, GetStockObject(DEFAULT_GUI_FONT)); - - if (options->bSecondLine) { - DBVARIANT dbv; - TCHAR *title; - bool bFree = false; - if (db_get_ts(hContact, "CList", "StatusMsg", &dbv) || !*dbv.ptszVal) { - char *proto = GetContactProto(hContact); - int status = db_get_w(hContact, proto, "Status", ID_STATUS_OFFLINE); - title = pcli->pfnGetStatusModeDescription(status, 0); - } - else { - title = dbv.ptszVal; - bFree = true; - } - - if (!options->bSysColors) SelectObject(hdc, g_Options.hfntSecond); - GetTextExtentPoint32(hdc, title, lstrlen(title), &sz); - if (bFree) db_free(&dbv); - textWidth = sz.cx; - lpmis->itemHeight += sz.cy + 3; - } - - TCHAR *name = (TCHAR *)CallService(MS_CLIST_GETCONTACTDISPLAYNAME, hContact, GCDNF_TCHAR); - - if (!options->bSysColors) SelectObject(hdc, g_Options.hfntName); - GetTextExtentPoint32(hdc, name, lstrlen(name), &sz); - textWidth = max(textWidth, sz.cx); - - SelectObject(hdc, hfntSave); - ReleaseDC(g_hwndMenuHost, hdc); - - lpmis->itemWidth += textWidth; - lpmis->itemHeight += sz.cy; - } - - if (options->bAvatars) { - AVATARCACHEENTRY *ace = (AVATARCACHEENTRY *)CallService(MS_AV_GETAVATARBITMAP, hContact, 0); - if (ace && (ace != (AVATARCACHEENTRY *)CALLSERVICE_NOTFOUND)) { - int avatarWidth = lpmis->itemHeight; - if (ace->bmWidth < ace->bmHeight) - avatarWidth = lpmis->itemHeight * ace->bmWidth / ace->bmHeight; - - lpmis->itemWidth += avatarWidth + 5; - } - } - - if (lpmis->itemHeight < 18) lpmis->itemHeight = 18; - - return TRUE; -} - -static BOOL sttMeasureItem(LPMEASUREITEMSTRUCT lpmis, Options *options = NULL) -{ - if (!options) options = &g_Options; - - if (!lpmis->itemData) - return FALSE; - - BOOL res = FALSE; - if (lpmis->itemData == 1) - res = sttMeasureItem_Group(lpmis, options); - else if (CallService(MS_DB_CONTACT_IS, lpmis->itemData, 0)) - res = sttMeasureItem_Contact(lpmis, options); - - if (res && (lpmis->itemWidth > g_maxItemWidth)) lpmis->itemWidth = g_maxItemWidth; - if (res && g_widthMultiplier) lpmis->itemWidth *= g_widthMultiplier; - - return FALSE; -} - -static BOOL sttDrawItem_Group(LPDRAWITEMSTRUCT lpdis, Options *options = NULL) -{ - lpdis->rcItem.top++; - lpdis->rcItem.bottom--; - - HFONT hfntSave = (HFONT)SelectObject(lpdis->hDC, GetStockObject(DEFAULT_GUI_FONT)); - SetBkMode(lpdis->hDC, TRANSPARENT); - if (options->bSysColors) { - FillRect(lpdis->hDC, &lpdis->rcItem, GetSysColorBrush(COLOR_HIGHLIGHT)); - SetTextColor(lpdis->hDC, GetSysColor(COLOR_HIGHLIGHTTEXT)); - } - else { - HBRUSH hbr = CreateSolidBrush(g_Options.clBackSel); - FillRect(lpdis->hDC, &lpdis->rcItem, hbr); - DeleteObject(hbr); - SetTextColor(lpdis->hDC, g_Options.clLine1Sel); - } - - TCHAR *name = sttGetGroupName(lpdis->itemData); - if (!options->bSysColors) - SelectObject(lpdis->hDC, g_Options.hfntName); - DrawText(lpdis->hDC, name, lstrlen(name), &lpdis->rcItem, DT_NOPREFIX | DT_SINGLELINE | DT_VCENTER | DT_CENTER); - - SelectObject(lpdis->hDC, hfntSave); - - return TRUE; -} - -void ImageList_DrawDimmed(HIMAGELIST himl, int i, HDC hdc, int left, int top, UINT fStyle) -{ - int dx, dy; - ImageList_GetIconSize(himl, &dx, &dy); - - HDC dcMem = CreateCompatibleDC(hdc); - HBITMAP hbm = CreateCompatibleBitmap(hdc, dx, dy); - HBITMAP hbmOld = (HBITMAP)SelectObject(dcMem, hbm); - BitBlt(dcMem, 0, 0, dx, dx, hdc, left, top, SRCCOPY); - ImageList_Draw(himl, i, dcMem, 0, 0, fStyle); - BLENDFUNCTION bf = { 0 }; - bf.SourceConstantAlpha = 180; - GdiAlphaBlend(hdc, left, top, dx, dy, dcMem, 0, 0, dx, dy, bf); - SelectObject(dcMem, hbmOld); - DeleteObject(hbm); - DeleteDC(dcMem); -} - -static BOOL sttDrawItem_Contact(LPDRAWITEMSTRUCT lpdis, Options *options = NULL) -{ - MCONTACT hContact = (MCONTACT)lpdis->itemData; - - HDC hdcTemp = CreateCompatibleDC(lpdis->hDC); - HBITMAP hbmTemp = CreateCompatibleBitmap(lpdis->hDC, lpdis->rcItem.right - lpdis->rcItem.left, lpdis->rcItem.bottom - lpdis->rcItem.top); - HBITMAP hbmSave = (HBITMAP)SelectObject(hdcTemp, hbmTemp); - RECT rcSave = lpdis->rcItem; - - OffsetRect(&lpdis->rcItem, -lpdis->rcItem.left, -lpdis->rcItem.top); - - HFONT hfntSave = (HFONT)SelectObject(hdcTemp, GetStockObject(DEFAULT_GUI_FONT)); - SetBkMode(hdcTemp, TRANSPARENT); - COLORREF clBack, clLine1, clLine2; - if (lpdis->itemState & ODS_SELECTED) { - if (options->bSysColors) { - FillRect(hdcTemp, &lpdis->rcItem, GetSysColorBrush(COLOR_HIGHLIGHT)); - clBack = GetSysColor(COLOR_HIGHLIGHT); - clLine1 = GetSysColor(COLOR_HIGHLIGHTTEXT); - } - else { - clBack = g_Options.clBackSel; - clLine1 = g_Options.clLine1Sel; - clLine2 = g_Options.clLine2Sel; - } - } - else { - if (options->bSysColors) { - FillRect(hdcTemp, &lpdis->rcItem, GetSysColorBrush(COLOR_MENU)); - clBack = GetSysColor(COLOR_MENU); - clLine1 = GetSysColor(COLOR_MENUTEXT); - } - else { - clBack = g_Options.clBack; - clLine1 = g_Options.clLine1; - clLine2 = g_Options.clLine2; - } - } - if (options->bSysColors) { - clLine2 = RGB( - (GetRValue(clLine1) * 66UL + GetRValue(clBack) * 34UL) / 100, - (GetGValue(clLine1) * 66UL + GetGValue(clBack) * 34UL) / 100, - (GetBValue(clLine1) * 66UL + GetBValue(clBack) * 34UL) / 100); - } - else { - HBRUSH hbr = CreateSolidBrush(clBack); - FillRect(hdcTemp, &lpdis->rcItem, hbr); - DeleteObject(hbr); - } - - lpdis->rcItem.left += 4; - lpdis->rcItem.right -= 4; - - lpdis->rcItem.top += 2; - lpdis->rcItem.bottom -= 2; - - char *proto = GetContactProto(hContact); - - HIMAGELIST hIml = (HIMAGELIST)CallService(MS_CLIST_GETICONSIMAGELIST, 0, 0); - int iIcon = CallService(MS_CLIST_GETCONTACTICON, hContact, 0); - - if (db_get_dw(hContact, proto, "IdleTS", 0)) { - ImageList_DrawDimmed(hIml, iIcon, hdcTemp, - lpdis->rcItem.left, (lpdis->rcItem.top + lpdis->rcItem.bottom - 16) / 2, - ILD_TRANSPARENT); - } - else { - ImageList_Draw(hIml, iIcon, hdcTemp, - lpdis->rcItem.left, (lpdis->rcItem.top + lpdis->rcItem.bottom - 16) / 2, - ILD_TRANSPARENT); - } - - lpdis->rcItem.left += 20; - - if (options->wMaxRecent && db_get_b(hContact, "FavContacts", "IsFavourite", 0)) { - DrawIconEx(hdcTemp, lpdis->rcItem.right - 18, (lpdis->rcItem.top + lpdis->rcItem.bottom - 16) / 2, - Skin_GetIconByHandle(iconList[0].hIcolib), 16, 16, 0, NULL, DI_NORMAL); - lpdis->rcItem.right -= 20; - } - - if (options->bAvatars) { - AVATARCACHEENTRY *ace = (AVATARCACHEENTRY *)CallService(MS_AV_GETAVATARBITMAP, hContact, 0); - if (ace && (ace != (AVATARCACHEENTRY *)CALLSERVICE_NOTFOUND)) { - int avatarWidth = lpdis->rcItem.bottom - lpdis->rcItem.top; - if (ace->bmWidth < ace->bmHeight) - avatarWidth = (lpdis->rcItem.bottom - lpdis->rcItem.top) * ace->bmWidth / ace->bmHeight; - - AVATARDRAWREQUEST avdr = { 0 }; - avdr.cbSize = sizeof(avdr); - avdr.hContact = hContact; - avdr.hTargetDC = hdcTemp; - avdr.rcDraw = lpdis->rcItem; - if (options->bRightAvatars) - avdr.rcDraw.left = avdr.rcDraw.right - avatarWidth; - else - avdr.rcDraw.right = avdr.rcDraw.left + avatarWidth; - avdr.dwFlags = AVDRQ_FALLBACKPROTO; - if (options->bAvatarBorder) { - avdr.dwFlags |= AVDRQ_DRAWBORDER; - avdr.clrBorder = clLine1; - if (options->bNoTransparentBorder) - avdr.dwFlags |= AVDRQ_HIDEBORDERONTRANSPARENCY; - if (options->wAvatarRadius) { - avdr.dwFlags |= AVDRQ_ROUNDEDCORNER; - avdr.radius = (unsigned char)options->wAvatarRadius; - } - } - avdr.alpha = 255; - CallService(MS_AV_DRAWAVATAR, 0, (LPARAM)&avdr); - - if (options->bRightAvatars) - lpdis->rcItem.right += avatarWidth + 5; - else - lpdis->rcItem.left += avatarWidth + 5; - } - } - - if (true) { - TCHAR *name = (TCHAR *)CallService(MS_CLIST_GETCONTACTDISPLAYNAME, hContact, GCDNF_TCHAR); - - if (!options->bSysColors) SelectObject(hdcTemp, g_Options.hfntName); - SetTextColor(hdcTemp, clLine1); - DrawText(hdcTemp, name, lstrlen(name), &lpdis->rcItem, DT_NOPREFIX | DT_SINGLELINE | DT_TOP | DT_LEFT); - - SIZE sz; GetTextExtentPoint32(hdcTemp, name, lstrlen(name), &sz); - lpdis->rcItem.top += sz.cy + 3; - } - - if (options->bSecondLine) { - DBVARIANT dbv; - TCHAR *title; - bool bFree = false; - if (db_get_ts(hContact, "CList", "StatusMsg", &dbv) || !*dbv.ptszVal) { - int status = db_get_w(hContact, proto, "Status", ID_STATUS_OFFLINE); - title = pcli->pfnGetStatusModeDescription(status, 0); - } - else { - title = dbv.ptszVal; - bFree = true; - } - - if (!options->bSysColors) SelectObject(hdcTemp, g_Options.hfntSecond); - SetTextColor(hdcTemp, clLine2); - DrawText(hdcTemp, title, lstrlen(title), &lpdis->rcItem, DT_NOPREFIX | DT_SINGLELINE | DT_TOP | DT_LEFT); - - if (bFree) db_free(&dbv); - } - - SelectObject(hdcTemp, hfntSave); - - BitBlt(lpdis->hDC, - rcSave.left, rcSave.top, - rcSave.right - rcSave.left, rcSave.bottom - rcSave.top, - hdcTemp, 0, 0, SRCCOPY); - - SelectObject(hdcTemp, hbmSave); - DeleteObject(hbmTemp); - DeleteDC(hdcTemp); - - return TRUE; -} - -static BOOL sttDrawItem(LPDRAWITEMSTRUCT lpdis, Options *options = NULL) -{ - if (!options) options = &g_Options; - - if (!lpdis->itemData) - return FALSE; - - if (lpdis->itemData == 1) - return sttDrawItem_Group(lpdis, options); - - if (CallService(MS_DB_CONTACT_IS, lpdis->itemData, 0)) - return sttDrawItem_Contact(lpdis, options); - - return FALSE; -} - -static LRESULT CALLBACK MenuHostWndProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam) -{ - static MCONTACT hContact = NULL; - - switch (message) { - case WM_MEASUREITEM: - { - LPMEASUREITEMSTRUCT lpmis = (LPMEASUREITEMSTRUCT)lParam; - if (lpmis->CtlType != ODT_MENU) - return FALSE; - - if ((lpmis->itemID >= CLISTMENUIDMIN) && (lpmis->itemID <= CLISTMENUIDMAX)) - return CallService(MS_CLIST_MENUMEASUREITEM, wParam, lParam); - - return sttMeasureItem(lpmis); - } - - case WM_DRAWITEM: - { - LPDRAWITEMSTRUCT lpdis = (LPDRAWITEMSTRUCT)lParam; - if (lpdis->CtlType != ODT_MENU) - return FALSE; - - if ((lpdis->itemID >= CLISTMENUIDMIN) && (lpdis->itemID <= CLISTMENUIDMAX)) - return CallService(MS_CLIST_MENUDRAWITEM, wParam, lParam); - - return sttDrawItem(lpdis); - } - - case WM_MENUCHAR: - while (GetMenuItemCount((HMENU)lParam) > 1) - RemoveMenu((HMENU)lParam, 1, MF_BYPOSITION); - - if (LOWORD(wParam) == VK_BACK) { - if (int l = lstrlen(g_filter)) - g_filter[l - 1] = 0; - } - else if (_istalnum(LOWORD(wParam))) { - if (lstrlen(g_filter) < SIZEOF(g_filter) - 1) { - TCHAR s[] = { LOWORD(wParam), 0 }; - lstrcat(g_filter, s); - } - } - { - int maxRecent = g_Options.wMaxRecent ? g_Options.wMaxRecent : 10; - for (int i = 0, nRecent = 0; nRecent < maxRecent; ++i) { - MCONTACT hContact = g_contactCache->get(i); - if (!hContact) break; - if (!g_contactCache->filter(i, g_filter)) continue; - - AppendMenu((HMENU)lParam, MF_OWNERDRAW, nRecent + 1, (LPCTSTR)hContact); - ++nRecent; - } - } - return MAKELRESULT(1, MNC_SELECT); - - case WM_MENURBUTTONUP: - MENUITEMINFO mii = { sizeof(mii) }; - mii.fMask = MIIM_DATA; - GetMenuItemInfo((HMENU)lParam, wParam, TRUE, &mii); - MCONTACT hContact = (MCONTACT)mii.dwItemData; - if (!CallService(MS_DB_CONTACT_IS, mii.dwItemData, 0)) - return FALSE; - - HMENU hMenu = (HMENU)CallService(MS_CLIST_MENUBUILDCONTACT, hContact, 0); - - POINT pt; - GetCursorPos(&pt); - HWND hwndSave = GetForegroundWindow(); - SetForegroundWindow(g_hwndMenuHost); - int res = TrackPopupMenu(hMenu, TPM_RECURSE | TPM_RIGHTBUTTON | TPM_RETURNCMD, pt.x, pt.y, 0, g_hwndMenuHost, NULL); - SetForegroundWindow(hwndSave); - DestroyMenu(hMenu); - - CallService(MS_CLIST_MENUPROCESSCOMMAND, MAKEWPARAM(res, MPCF_CONTACTMENU), hContact); - return TRUE; - } - - return DefWindowProc(hwnd, message, wParam, lParam); -} - -int sttShowMenu(bool centered) -{ - TFavContacts favList; - HMENU hMenu = CreatePopupMenu(); - SIZE szMenu = { 0 }; - SIZE szColumn = { 0 }; - TCHAR *prevGroup = NULL; - int i, idItem = 100; - MCONTACT hContact; - - favList.build(); - - g_widthMultiplier = 0; - - g_maxItemWidth = GetSystemMetrics(SM_CXSCREEN); - if (g_Options.bUseColumns) g_maxItemWidth /= favList.groupCount(); - - prevGroup = NULL; - for (i = 0; i < favList.getCount(); ++i) { - hContact = favList[i]->getHandle(); - - MEASUREITEMSTRUCT mis = { 0 }; - mis.CtlID = 0; - mis.CtlType = ODT_MENU; - - if (!prevGroup || lstrcmp(prevGroup, favList[i]->getGroup())) { - if (prevGroup && g_Options.bUseColumns) { - szMenu.cx += szColumn.cx; - szMenu.cy = max(szMenu.cy, szColumn.cy); - szColumn.cx = szColumn.cy = 0; - } - - DWORD groupID = (DWORD)Clist_GroupExists(favList[i]->getGroup()) + 1; - - AppendMenu(hMenu, - MF_OWNERDRAW | MF_SEPARATOR | ((prevGroup && g_Options.bUseColumns) ? MF_MENUBREAK : 0), - ++idItem, (LPCTSTR)groupID); - - mis.itemData = groupID; - mis.itemID = idItem; - sttMeasureItem(&mis); - szColumn.cx = max(szColumn.cx, (int)mis.itemWidth); - szColumn.cy += mis.itemHeight; - } - - AppendMenu(hMenu, MF_OWNERDRAW, ++idItem, (LPCTSTR)hContact); - - mis.itemData = (DWORD)hContact; - mis.itemID = idItem; - sttMeasureItem(&mis); - szColumn.cx = max(szColumn.cx, (int)mis.itemWidth); - szColumn.cy += mis.itemHeight; - - prevGroup = favList[i]->getGroup(); - } - szMenu.cx += szColumn.cx; - szMenu.cy = max(szMenu.cy, szColumn.cy); - szColumn.cx = szColumn.cy = 0; - - int maxWidth = GetSystemMetrics(SM_CXSCREEN) * db_get_b(NULL, "FavContacts", "MenuWidth", 66) / 100; - if (szMenu.cx > maxWidth) { - g_widthMultiplier = (float)maxWidth / szMenu.cx; - szMenu.cx *= g_widthMultiplier; - } - - POINT pt; - if (centered) { - if ((pt.x = (GetSystemMetrics(SM_CXSCREEN) - szMenu.cx) / 2) < 0) pt.x = 0; - if ((pt.y = (GetSystemMetrics(SM_CYSCREEN) - szMenu.cy) / 2) < 0) pt.y = 0; - } - else GetCursorPos(&pt); - - HWND hwndSave = GetForegroundWindow(); - SetForegroundWindow(g_hwndMenuHost); - hContact = NULL; - g_filter[0] = 0; - - if (int res = TrackPopupMenu(hMenu, TPM_RETURNCMD, pt.x, pt.y, 0, g_hwndMenuHost, NULL)) { - MENUITEMINFO mii = { 0 }; - mii.cbSize = sizeof(mii); - mii.fMask = MIIM_DATA; - GetMenuItemInfo(hMenu, res, FALSE, &mii); - hContact = (MCONTACT)mii.dwItemData; - } - SetForegroundWindow(hwndSave); - DestroyMenu(hMenu); - - if (hContact) - CallService(MS_CLIST_CONTACTDOUBLECLICKED, hContact, 0); - - return 0; -} - -INT_PTR svcShowMenu(WPARAM wParam, LPARAM lParam) -{ - sttShowMenu(false); - return 0; -} - -INT_PTR svcShowMenuCentered(WPARAM wParam, LPARAM lParam) -{ - sttShowMenu(g_Options.bCenterHotkey ? true : false); - return 0; -} - -INT_PTR svcOpenContact(WPARAM wParam, LPARAM lParam) -{ - hContactToActivate = wParam; - CallService(MS_CLIST_CONTACTDOUBLECLICKED, (WPARAM)hContactToActivate, 0); - return 0; -} - -int ProcessSrmmEvent(WPARAM wParam, LPARAM lParam) -{ - MessageWindowEventData *event = (MessageWindowEventData *)lParam; - - if (event->uType == MSG_WINDOW_EVT_OPEN) { - if (!hDialogsList) - hDialogsList = WindowList_Create(); - WindowList_Add(hDialogsList, event->hwndWindow, event->hContact); - - BYTE fav = db_get_b(event->hContact, "FavContacts", "IsFavourite", 0); - StatusIconData sid = { sizeof(sid) }; - sid.szModule = "FavContacts"; - sid.flags = fav ? 0 : MBF_DISABLED; - Srmm_ModifyIcon(event->hContact, &sid); - - if (event->hContact == hContactToActivate) { - HWND hwndRoot = event->hwndWindow; - while (HWND hwndParent = GetParent(hwndRoot)) - hwndRoot = hwndParent; - - AttachThreadInput(GetWindowThreadProcessId(GetForegroundWindow(), NULL), GetCurrentThreadId(), TRUE); - SetForegroundWindow(hwndRoot); - SetActiveWindow(hwndRoot); - SetFocus(hwndRoot); - AttachThreadInput(GetWindowThreadProcessId(GetForegroundWindow(), NULL), GetCurrentThreadId(), FALSE); - } - - hContactToActivate = NULL; - } - else if (event->uType == MSG_WINDOW_EVT_CLOSING) { - if (hDialogsList) - WindowList_Remove(hDialogsList, event->hwndWindow); - } - - return 0; -} - -int ProcessSrmmIconClick(WPARAM hContact, LPARAM lParam) -{ - StatusIconClickData *sicd = (StatusIconClickData *)lParam; - if (lstrcmpA(sicd->szModule, "FavContacts")) return 0; - - if (!hContact) - return 0; - - if (sicd->flags & MBCF_RIGHTBUTTON) { - BYTE fav = !db_get_b(hContact, "FavContacts", "IsFavourite", 0); - db_set_b(hContact, "FavContacts", "IsFavourite", fav); - if (fav) CallService(MS_AV_GETAVATARBITMAP, hContact, 0); - - StatusIconData sid = { sizeof(sid) }; - sid.szModule = "FavContacts"; - sid.flags = fav ? 0 : MBF_DISABLED; - Srmm_ModifyIcon(hContact, &sid); - } - else sttShowMenu(false); - - return 0; -} - -///////////////////////////////////////////////////////////////////////////////////////// -// Options - -static void sttResetListOptions(HWND hwndList) -{ - SendMessage(hwndList, CLM_SETBKBITMAP, 0, (LPARAM)(HBITMAP)NULL); - SendMessage(hwndList, CLM_SETBKCOLOR, GetSysColor(COLOR_WINDOW), 0); - SendMessage(hwndList, CLM_SETGREYOUTFLAGS, 0, 0); - SendMessage(hwndList, CLM_SETLEFTMARGIN, 4, 0); - SendMessage(hwndList, CLM_SETINDENT, 10, 0); - SendMessage(hwndList, CLM_SETHIDEEMPTYGROUPS, 1, 0); - SendMessage(hwndList, CLM_SETHIDEOFFLINEROOT, 1, 0); - for (int i = 0; i <= FONTID_MAX; ++i) - SendMessage(hwndList, CLM_SETTEXTCOLOR, i, GetSysColor(COLOR_WINDOWTEXT)); -} - -static INT_PTR CALLBACK OptionsDlgProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam) -{ - static bool bInitialized = false; - static MCONTACT hSelectedContact = 0; - - switch (msg) { - case WM_INITDIALOG: - bInitialized = false; - - TranslateDialogDefault(hwnd); - - CheckDlgButton(hwnd, IDC_CHK_GROUPS, g_Options.bUseGroups ? BST_CHECKED : BST_UNCHECKED); - CheckDlgButton(hwnd, IDC_CHK_GROUPCOLUMS, g_Options.bUseColumns ? BST_CHECKED : BST_UNCHECKED); - CheckDlgButton(hwnd, IDC_CHK_SECONDLINE, g_Options.bSecondLine ? BST_CHECKED : BST_UNCHECKED); - CheckDlgButton(hwnd, IDC_CHK_AVATARS, g_Options.bAvatars ? BST_CHECKED : BST_UNCHECKED); - CheckDlgButton(hwnd, IDC_CHK_AVATARBORDER, g_Options.bAvatarBorder ? BST_CHECKED : BST_UNCHECKED); - CheckDlgButton(hwnd, IDC_CHK_NOTRANSPARENTBORDER, g_Options.bNoTransparentBorder ? BST_CHECKED : BST_UNCHECKED); - CheckDlgButton(hwnd, IDC_CHK_SYSCOLORS, g_Options.bSysColors ? BST_CHECKED : BST_UNCHECKED); - CheckDlgButton(hwnd, IDC_CHK_CENTERHOTKEY, g_Options.bCenterHotkey ? BST_CHECKED : BST_UNCHECKED); - CheckDlgButton(hwnd, IDC_CHK_RIGHTAVATARS, g_Options.bRightAvatars ? BST_CHECKED : BST_UNCHECKED); - CheckDlgButton(hwnd, IDC_CHK_DIMIDLE, g_Options.bDimIdle ? BST_CHECKED : BST_UNCHECKED); - SetDlgItemInt(hwnd, IDC_TXT_RADIUS, g_Options.wAvatarRadius, FALSE); - SetDlgItemInt(hwnd, IDC_TXT_MAXRECENT, g_Options.wMaxRecent, FALSE); - - SetWindowLongPtr(GetDlgItem(hwnd, IDC_CLIST), GWL_STYLE, - GetWindowLongPtr(GetDlgItem(hwnd, IDC_CLIST), GWL_STYLE) | CLS_CHECKBOXES | CLS_HIDEEMPTYGROUPS | CLS_USEGROUPS | CLS_GREYALTERNATE | CLS_GROUPCHECKBOXES); - SendMessage(GetDlgItem(hwnd, IDC_CLIST), CLM_SETEXSTYLE, CLS_EX_DISABLEDRAGDROP | CLS_EX_TRACKSELECT, 0); - sttResetListOptions(GetDlgItem(hwnd, IDC_CLIST)); - - hSelectedContact = db_find_first(); - { - for (MCONTACT hContact = db_find_first(); hContact; hContact = db_find_next(hContact)) - SendDlgItemMessage(hwnd, IDC_CLIST, CLM_SETCHECKMARK, - SendDlgItemMessage(hwnd, IDC_CLIST, CLM_FINDCONTACT, hContact, 0), - db_get_b(hContact, "FavContacts", "IsFavourite", 0)); - } - - bInitialized = true; - PostMessage(hwnd, WM_APP, 0, 0); - return TRUE; - - case WM_APP: - { - BOOL bGroups = IsDlgButtonChecked(hwnd, IDC_CHK_GROUPS); - EnableWindow(GetDlgItem(hwnd, IDC_CHK_GROUPCOLUMS), bGroups); - - BOOL bAvatars = IsDlgButtonChecked(hwnd, IDC_CHK_AVATARS); - BOOL bBorders = IsDlgButtonChecked(hwnd, IDC_CHK_AVATARBORDER); - EnableWindow(GetDlgItem(hwnd, IDC_CHK_AVATARBORDER), bAvatars); - EnableWindow(GetDlgItem(hwnd, IDC_CHK_RIGHTAVATARS), bAvatars); - EnableWindow(GetDlgItem(hwnd, IDC_CHK_NOTRANSPARENTBORDER), bAvatars && bBorders); - EnableWindow(GetDlgItem(hwnd, IDC_TXT_RADIUS), bAvatars && bBorders); - } - return TRUE; - - case WM_DRAWITEM: - { - LPDRAWITEMSTRUCT lpdis = (LPDRAWITEMSTRUCT)lParam; - if (lpdis->CtlID == IDC_CANVAS) { - MEASUREITEMSTRUCT mis = { 0 }; - DRAWITEMSTRUCT dis = *lpdis; - - FillRect(lpdis->hDC, &lpdis->rcItem, GetSysColorBrush(COLOR_BTNFACE)); - if (hSelectedContact) { - Options options; - options.bSecondLine = IsDlgButtonChecked(hwnd, IDC_CHK_SECONDLINE); - options.bAvatars = IsDlgButtonChecked(hwnd, IDC_CHK_AVATARS); - options.bAvatarBorder = IsDlgButtonChecked(hwnd, IDC_CHK_AVATARBORDER); - options.bNoTransparentBorder = IsDlgButtonChecked(hwnd, IDC_CHK_NOTRANSPARENTBORDER); - options.bSysColors = IsDlgButtonChecked(hwnd, IDC_CHK_SYSCOLORS); - options.bCenterHotkey = IsDlgButtonChecked(hwnd, IDC_CHK_CENTERHOTKEY); - options.bRightAvatars = IsDlgButtonChecked(hwnd, IDC_CHK_RIGHTAVATARS); - options.bDimIdle = IsDlgButtonChecked(hwnd, IDC_CHK_DIMIDLE); - options.wAvatarRadius = GetDlgItemInt(hwnd, IDC_TXT_RADIUS, NULL, FALSE); - options.wMaxRecent = GetDlgItemInt(hwnd, IDC_TXT_MAXRECENT, NULL, FALSE); - - mis.CtlID = 0; - mis.CtlType = ODT_MENU; - mis.itemData = (DWORD)hSelectedContact; - sttMeasureItem(&mis, &options); - dis.rcItem.bottom = dis.rcItem.top + mis.itemHeight; - - dis.CtlID = 0; - dis.CtlType = ODT_MENU; - dis.itemData = (DWORD)hSelectedContact; - sttDrawItem(&dis, &options); - - RECT rc = lpdis->rcItem; - rc.bottom = rc.top + mis.itemHeight; - FrameRect(lpdis->hDC, &rc, GetSysColorBrush(COLOR_HIGHLIGHT)); - } - return TRUE; - } - } - return FALSE; - - case WM_COMMAND: - switch (LOWORD(wParam)) { - case IDC_CHK_SECONDLINE: - case IDC_CHK_AVATARS: - case IDC_CHK_AVATARBORDER: - case IDC_CHK_NOTRANSPARENTBORDER: - case IDC_CHK_SYSCOLORS: - case IDC_CHK_CENTERHOTKEY: - case IDC_CHK_GROUPS: - case IDC_CHK_GROUPCOLUMS: - case IDC_CHK_RIGHTAVATARS: - SendMessage(GetParent(hwnd), PSM_CHANGED, 0, 0); - RedrawWindow(GetDlgItem(hwnd, IDC_CANVAS), NULL, NULL, RDW_INVALIDATE); - PostMessage(hwnd, WM_APP, 0, 0); - break; - - case IDC_BTN_FONTS: - { - OPENOPTIONSDIALOG ood = { sizeof(ood) }; - ood.pszGroup = "Customize"; - ood.pszPage = "Fonts and colors"; - ood.pszTab = NULL; - Options_Open(&ood); - } - break; - - case IDC_TXT_RADIUS: - if ((HIWORD(wParam) == EN_CHANGE) && bInitialized) { - RedrawWindow(GetDlgItem(hwnd, IDC_CANVAS), NULL, NULL, RDW_INVALIDATE); - SendMessage(GetParent(hwnd), PSM_CHANGED, 0, 0); - } - break; - - case IDC_TXT_MAXRECENT: - if ((HIWORD(wParam) == EN_CHANGE) && bInitialized) - SendMessage(GetParent(hwnd), PSM_CHANGED, 0, 0); - break; - } - break; - - case WM_NOTIFY: - if ((((LPNMHDR)lParam)->idFrom == 0) && (((LPNMHDR)lParam)->code == PSN_APPLY)) { - g_Options.bSecondLine = IsDlgButtonChecked(hwnd, IDC_CHK_SECONDLINE); - g_Options.bAvatars = IsDlgButtonChecked(hwnd, IDC_CHK_AVATARS); - g_Options.bAvatarBorder = IsDlgButtonChecked(hwnd, IDC_CHK_AVATARBORDER); - g_Options.bNoTransparentBorder = IsDlgButtonChecked(hwnd, IDC_CHK_NOTRANSPARENTBORDER); - g_Options.bSysColors = IsDlgButtonChecked(hwnd, IDC_CHK_SYSCOLORS); - g_Options.bCenterHotkey = IsDlgButtonChecked(hwnd, IDC_CHK_CENTERHOTKEY); - g_Options.bUseGroups = IsDlgButtonChecked(hwnd, IDC_CHK_GROUPS); - g_Options.bUseColumns = IsDlgButtonChecked(hwnd, IDC_CHK_GROUPCOLUMS); - g_Options.bRightAvatars = IsDlgButtonChecked(hwnd, IDC_CHK_RIGHTAVATARS); - g_Options.bDimIdle = IsDlgButtonChecked(hwnd, IDC_CHK_DIMIDLE); - g_Options.wAvatarRadius = GetDlgItemInt(hwnd, IDC_TXT_RADIUS, NULL, FALSE); - g_Options.wMaxRecent = GetDlgItemInt(hwnd, IDC_TXT_MAXRECENT, NULL, FALSE); - - sttSaveOptions(); - - for (MCONTACT hContact = db_find_first(); hContact; hContact = db_find_next(hContact)) { - BYTE fav = SendDlgItemMessage(hwnd, IDC_CLIST, CLM_GETCHECKMARK, - SendDlgItemMessage(hwnd, IDC_CLIST, CLM_FINDCONTACT, hContact, 0), 0); - if (fav != db_get_b(hContact, "FavContacts", "IsFavourite", 0)) - db_set_b(hContact, "FavContacts", "IsFavourite", fav); - if (fav) CallService(MS_AV_GETAVATARBITMAP, hContact, 0); - } - } - else if (((LPNMHDR)lParam)->idFrom == IDC_CLIST) { - int iSelection; - - switch (((LPNMHDR)lParam)->code) { - case CLN_OPTIONSCHANGED: - sttResetListOptions(GetDlgItem(hwnd, IDC_CLIST)); - break; - - case CLN_NEWCONTACT: - iSelection = (int)((NMCLISTCONTROL *)lParam)->hItem; - for (MCONTACT hContact = db_find_first(); hContact; hContact = db_find_next(hContact)) { - if (SendDlgItemMessage(hwnd, IDC_CLIST, CLM_FINDCONTACT, hContact, 0) == iSelection) { - SendDlgItemMessage(hwnd, IDC_CLIST, CLM_SETCHECKMARK, iSelection, - db_get_b(hContact, "FavContacts", "IsFavourite", 0)); - break; - } - } - break; - - case CLN_CHECKCHANGED: - iSelection = (int)((NMCLISTCONTROL *)lParam)->hItem; - for (MCONTACT hContact = db_find_first(); hContact; hContact = db_find_next(hContact)) { - if (SendDlgItemMessage(hwnd, IDC_CLIST, CLM_FINDCONTACT, hContact, 0) == iSelection) { - hSelectedContact = hContact; - RedrawWindow(GetDlgItem(hwnd, IDC_CANVAS), NULL, NULL, RDW_INVALIDATE); - } - } - SendMessage(GetParent(hwnd), PSM_CHANGED, 0, 0); - } - } - break; - } - - return FALSE; -} diff --git a/plugins/FavContacts/src/menu.cpp b/plugins/FavContacts/src/menu.cpp new file mode 100644 index 0000000000..3138ff9ba8 --- /dev/null +++ b/plugins/FavContacts/src/menu.cpp @@ -0,0 +1,552 @@ +/* +Favorite Contacts for Miranda IM + +Copyright 2007 Victor Pavlychko + +This program is free software; you can redistribute it and/or +modify it under the terms of the GNU General Public License +as published by the Free Software Foundation; either version 2 +of the License, or (at your option) any later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program; if not, write to the Free Software +Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +*/ + +#include "headers.h" + +UINT g_maxItemWidth = 0; +float g_widthMultiplier = 0; + +TCHAR g_filter[1024] = { 0 }; + +HWND g_hwndMenuHost = NULL; + +static TCHAR* sttGetGroupName(int id) +{ + if (id == 1) { + if (g_Options.bUseGroups) + return TranslateT(""); + return TranslateT("Favorite Contacts"); + } + + return pcli->pfnGetGroupName(id-1, NULL); +} + +static BOOL sttMeasureItem_Group(LPMEASUREITEMSTRUCT lpmis, Options *options) +{ + HDC hdc = GetDC(g_hwndMenuHost); + HFONT hfntSave = (HFONT)SelectObject(hdc, GetStockObject(DEFAULT_GUI_FONT)); + TCHAR *name = sttGetGroupName(-INT_PTR(lpmis->itemData)); + if (!options->bSysColors) + SelectObject(hdc, g_Options.hfntName); + + SIZE sz; + GetTextExtentPoint32(hdc, name, lstrlen(name), &sz); + lpmis->itemHeight = sz.cy + 8; + lpmis->itemWidth = sz.cx + 10; + SelectObject(hdc, hfntSave); + ReleaseDC(g_hwndMenuHost, hdc); + return TRUE; +} + +static BOOL sttMeasureItem_Contact(LPMEASUREITEMSTRUCT lpmis, Options *options) +{ + MCONTACT hContact = (MCONTACT)lpmis->itemData; + + lpmis->itemHeight = 4; + lpmis->itemWidth = 8 + 10; + lpmis->itemWidth += 20; + + SIZE sz; + int textWidth = 0; + + HDC hdc = GetDC(g_hwndMenuHost); + HFONT hfntSave = (HFONT)SelectObject(hdc, GetStockObject(DEFAULT_GUI_FONT)); + + if (options->bSecondLine) { + bool bFree = false; + TCHAR *title = db_get_tsa(hContact, "CList", "StatusMsg"); + if (title == NULL) { + char *proto = GetContactProto(hContact); + int status = db_get_w(hContact, proto, "Status", ID_STATUS_OFFLINE); + title = pcli->pfnGetStatusModeDescription(status, 0); + } + else bFree = true; + + if (!options->bSysColors) + SelectObject(hdc, g_Options.hfntSecond); + GetTextExtentPoint32(hdc, title, lstrlen(title), &sz); + textWidth = sz.cx; + lpmis->itemHeight += sz.cy + 3; + + if (bFree) + mir_free(title); + } + + TCHAR *name = (TCHAR *)CallService(MS_CLIST_GETCONTACTDISPLAYNAME, hContact, GCDNF_TCHAR); + + if (!options->bSysColors) SelectObject(hdc, g_Options.hfntName); + GetTextExtentPoint32(hdc, name, lstrlen(name), &sz); + textWidth = max(textWidth, sz.cx); + + SelectObject(hdc, hfntSave); + ReleaseDC(g_hwndMenuHost, hdc); + + lpmis->itemWidth += textWidth; + lpmis->itemHeight += sz.cy; + + if (options->bAvatars) { + AVATARCACHEENTRY *ace = (AVATARCACHEENTRY *)CallService(MS_AV_GETAVATARBITMAP, hContact, 0); + if (ace && (ace != (AVATARCACHEENTRY *)CALLSERVICE_NOTFOUND)) { + int avatarWidth = lpmis->itemHeight; + if (ace->bmWidth < ace->bmHeight) + avatarWidth = lpmis->itemHeight * ace->bmWidth / ace->bmHeight; + + lpmis->itemWidth += avatarWidth + 5; + } + } + + if (lpmis->itemHeight < 18) lpmis->itemHeight = 18; + + return TRUE; +} + +BOOL MenuMeasureItem(LPMEASUREITEMSTRUCT lpmis, Options *options) +{ + if (!options) + options = &g_Options; + + if (!lpmis->itemData) + return FALSE; + + BOOL res = FALSE; + if (INT_PTR(lpmis->itemData) < 0) + res = sttMeasureItem_Group(lpmis, options); + else if (CallService(MS_DB_CONTACT_IS, lpmis->itemData, 0)) + res = sttMeasureItem_Contact(lpmis, options); + + if (res && (lpmis->itemWidth > g_maxItemWidth)) lpmis->itemWidth = g_maxItemWidth; + if (res && g_widthMultiplier) lpmis->itemWidth *= g_widthMultiplier; + + return FALSE; +} + +static BOOL sttDrawItem_Group(LPDRAWITEMSTRUCT lpdis, Options *options = NULL) +{ + lpdis->rcItem.top++; + lpdis->rcItem.bottom--; + + HFONT hfntSave = (HFONT)SelectObject(lpdis->hDC, GetStockObject(DEFAULT_GUI_FONT)); + SetBkMode(lpdis->hDC, TRANSPARENT); + if (options->bSysColors) { + FillRect(lpdis->hDC, &lpdis->rcItem, GetSysColorBrush(COLOR_HIGHLIGHT)); + SetTextColor(lpdis->hDC, GetSysColor(COLOR_HIGHLIGHTTEXT)); + } + else { + HBRUSH hbr = CreateSolidBrush(g_Options.clBackSel); + FillRect(lpdis->hDC, &lpdis->rcItem, hbr); + DeleteObject(hbr); + SetTextColor(lpdis->hDC, g_Options.clLine1Sel); + } + + TCHAR *name = sttGetGroupName(-INT_PTR(lpdis->itemData)); + if (!options->bSysColors) + SelectObject(lpdis->hDC, g_Options.hfntName); + DrawText(lpdis->hDC, name, lstrlen(name), &lpdis->rcItem, DT_NOPREFIX | DT_SINGLELINE | DT_VCENTER | DT_CENTER); + + SelectObject(lpdis->hDC, hfntSave); + + return TRUE; +} + +void ImageList_DrawDimmed(HIMAGELIST himl, int i, HDC hdc, int left, int top, UINT fStyle) +{ + int dx, dy; + ImageList_GetIconSize(himl, &dx, &dy); + + HDC dcMem = CreateCompatibleDC(hdc); + HBITMAP hbm = CreateCompatibleBitmap(hdc, dx, dy); + HBITMAP hbmOld = (HBITMAP)SelectObject(dcMem, hbm); + BitBlt(dcMem, 0, 0, dx, dx, hdc, left, top, SRCCOPY); + ImageList_Draw(himl, i, dcMem, 0, 0, fStyle); + BLENDFUNCTION bf = { 0 }; + bf.SourceConstantAlpha = 180; + GdiAlphaBlend(hdc, left, top, dx, dy, dcMem, 0, 0, dx, dy, bf); + SelectObject(dcMem, hbmOld); + DeleteObject(hbm); + DeleteDC(dcMem); +} + +static BOOL sttDrawItem_Contact(LPDRAWITEMSTRUCT lpdis, Options *options = NULL) +{ + MCONTACT hContact = (MCONTACT)lpdis->itemData; + + HDC hdcTemp = CreateCompatibleDC(lpdis->hDC); + HBITMAP hbmTemp = CreateCompatibleBitmap(lpdis->hDC, lpdis->rcItem.right - lpdis->rcItem.left, lpdis->rcItem.bottom - lpdis->rcItem.top); + HBITMAP hbmSave = (HBITMAP)SelectObject(hdcTemp, hbmTemp); + RECT rcSave = lpdis->rcItem; + + OffsetRect(&lpdis->rcItem, -lpdis->rcItem.left, -lpdis->rcItem.top); + + HFONT hfntSave = (HFONT)SelectObject(hdcTemp, GetStockObject(DEFAULT_GUI_FONT)); + SetBkMode(hdcTemp, TRANSPARENT); + COLORREF clBack, clLine1, clLine2; + if (lpdis->itemState & ODS_SELECTED) { + if (options->bSysColors) { + FillRect(hdcTemp, &lpdis->rcItem, GetSysColorBrush(COLOR_HIGHLIGHT)); + clBack = GetSysColor(COLOR_HIGHLIGHT); + clLine1 = GetSysColor(COLOR_HIGHLIGHTTEXT); + } + else { + clBack = g_Options.clBackSel; + clLine1 = g_Options.clLine1Sel; + clLine2 = g_Options.clLine2Sel; + } + } + else { + if (options->bSysColors) { + FillRect(hdcTemp, &lpdis->rcItem, GetSysColorBrush(COLOR_MENU)); + clBack = GetSysColor(COLOR_MENU); + clLine1 = GetSysColor(COLOR_MENUTEXT); + } + else { + clBack = g_Options.clBack; + clLine1 = g_Options.clLine1; + clLine2 = g_Options.clLine2; + } + } + if (options->bSysColors) { + clLine2 = RGB( + (GetRValue(clLine1) * 66UL + GetRValue(clBack) * 34UL) / 100, + (GetGValue(clLine1) * 66UL + GetGValue(clBack) * 34UL) / 100, + (GetBValue(clLine1) * 66UL + GetBValue(clBack) * 34UL) / 100); + } + else { + HBRUSH hbr = CreateSolidBrush(clBack); + FillRect(hdcTemp, &lpdis->rcItem, hbr); + DeleteObject(hbr); + } + + lpdis->rcItem.left += 4; + lpdis->rcItem.right -= 4; + + lpdis->rcItem.top += 2; + lpdis->rcItem.bottom -= 2; + + char *proto = GetContactProto(hContact); + + HIMAGELIST hIml = (HIMAGELIST)CallService(MS_CLIST_GETICONSIMAGELIST, 0, 0); + int iIcon = CallService(MS_CLIST_GETCONTACTICON, hContact, 0); + + if (db_get_dw(hContact, proto, "IdleTS", 0)) { + ImageList_DrawDimmed(hIml, iIcon, hdcTemp, + lpdis->rcItem.left, (lpdis->rcItem.top + lpdis->rcItem.bottom - 16) / 2, + ILD_TRANSPARENT); + } + else { + ImageList_Draw(hIml, iIcon, hdcTemp, + lpdis->rcItem.left, (lpdis->rcItem.top + lpdis->rcItem.bottom - 16) / 2, + ILD_TRANSPARENT); + } + + lpdis->rcItem.left += 20; + + if (options->wMaxRecent && db_get_b(hContact, "FavContacts", "IsFavourite", 0)) { + DrawIconEx(hdcTemp, lpdis->rcItem.right - 18, (lpdis->rcItem.top + lpdis->rcItem.bottom - 16) / 2, + Skin_GetIconByHandle(iconList[0].hIcolib), 16, 16, 0, NULL, DI_NORMAL); + lpdis->rcItem.right -= 20; + } + + if (options->bAvatars) { + AVATARCACHEENTRY *ace = (AVATARCACHEENTRY *)CallService(MS_AV_GETAVATARBITMAP, hContact, 0); + if (ace && (ace != (AVATARCACHEENTRY *)CALLSERVICE_NOTFOUND)) { + int avatarWidth = lpdis->rcItem.bottom - lpdis->rcItem.top; + if (ace->bmWidth < ace->bmHeight) + avatarWidth = (lpdis->rcItem.bottom - lpdis->rcItem.top) * ace->bmWidth / ace->bmHeight; + + AVATARDRAWREQUEST avdr = { 0 }; + avdr.cbSize = sizeof(avdr); + avdr.hContact = hContact; + avdr.hTargetDC = hdcTemp; + avdr.rcDraw = lpdis->rcItem; + if (options->bRightAvatars) + avdr.rcDraw.left = avdr.rcDraw.right - avatarWidth; + else + avdr.rcDraw.right = avdr.rcDraw.left + avatarWidth; + avdr.dwFlags = AVDRQ_FALLBACKPROTO; + if (options->bAvatarBorder) { + avdr.dwFlags |= AVDRQ_DRAWBORDER; + avdr.clrBorder = clLine1; + if (options->bNoTransparentBorder) + avdr.dwFlags |= AVDRQ_HIDEBORDERONTRANSPARENCY; + if (options->wAvatarRadius) { + avdr.dwFlags |= AVDRQ_ROUNDEDCORNER; + avdr.radius = (unsigned char)options->wAvatarRadius; + } + } + avdr.alpha = 255; + CallService(MS_AV_DRAWAVATAR, 0, (LPARAM)&avdr); + + if (options->bRightAvatars) + lpdis->rcItem.right += avatarWidth + 5; + else + lpdis->rcItem.left += avatarWidth + 5; + } + } + + if (true) { + TCHAR *name = (TCHAR *)CallService(MS_CLIST_GETCONTACTDISPLAYNAME, hContact, GCDNF_TCHAR); + + if (!options->bSysColors) + SelectObject(hdcTemp, g_Options.hfntName); + SetTextColor(hdcTemp, clLine1); + DrawText(hdcTemp, name, lstrlen(name), &lpdis->rcItem, DT_NOPREFIX | DT_SINGLELINE | DT_TOP | DT_LEFT); + + SIZE sz; + GetTextExtentPoint32(hdcTemp, name, lstrlen(name), &sz); + lpdis->rcItem.top += sz.cy + 3; + } + + if (options->bSecondLine) { + bool bFree = false; + TCHAR *title = db_get_tsa(hContact, "CList", "StatusMsg"); + if (title == NULL) { + int status = db_get_w(hContact, proto, "Status", ID_STATUS_OFFLINE); + title = pcli->pfnGetStatusModeDescription(status, 0); + } + else bFree = true; + + if (!options->bSysColors) SelectObject(hdcTemp, g_Options.hfntSecond); + SetTextColor(hdcTemp, clLine2); + DrawText(hdcTemp, title, lstrlen(title), &lpdis->rcItem, DT_NOPREFIX | DT_SINGLELINE | DT_TOP | DT_LEFT); + + if (bFree) mir_free(title); + } + + SelectObject(hdcTemp, hfntSave); + BitBlt(lpdis->hDC, rcSave.left, rcSave.top, rcSave.right - rcSave.left, rcSave.bottom - rcSave.top, hdcTemp, 0, 0, SRCCOPY); + + SelectObject(hdcTemp, hbmSave); + DeleteObject(hbmTemp); + DeleteDC(hdcTemp); + + return TRUE; +} + +BOOL MenuDrawItem(LPDRAWITEMSTRUCT lpdis, Options *options) +{ + if (!options) + options = &g_Options; + + if (!lpdis->itemData) + return FALSE; + + if (INT_PTR(lpdis->itemData) < 0) + return sttDrawItem_Group(lpdis, options); + + if (CallService(MS_DB_CONTACT_IS, lpdis->itemData, 0)) + return sttDrawItem_Contact(lpdis, options); + + return FALSE; +} + +static LRESULT CALLBACK MenuHostWndProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam) +{ + static MCONTACT hContact = NULL; + + switch (message) { + case WM_MEASUREITEM: + { + LPMEASUREITEMSTRUCT lpmis = (LPMEASUREITEMSTRUCT)lParam; + if (lpmis->CtlType != ODT_MENU) + return FALSE; + + if ((lpmis->itemID >= CLISTMENUIDMIN) && (lpmis->itemID <= CLISTMENUIDMAX)) + return CallService(MS_CLIST_MENUMEASUREITEM, wParam, lParam); + + return MenuMeasureItem(lpmis); + } + + case WM_DRAWITEM: + { + LPDRAWITEMSTRUCT lpdis = (LPDRAWITEMSTRUCT)lParam; + if (lpdis->CtlType != ODT_MENU) + return FALSE; + + if ((lpdis->itemID >= CLISTMENUIDMIN) && (lpdis->itemID <= CLISTMENUIDMAX)) + return CallService(MS_CLIST_MENUDRAWITEM, wParam, lParam); + + return MenuDrawItem(lpdis); + } + + case WM_MENUCHAR: + while (GetMenuItemCount((HMENU)lParam) > 1) + RemoveMenu((HMENU)lParam, 1, MF_BYPOSITION); + + if (LOWORD(wParam) == VK_BACK) { + if (int l = lstrlen(g_filter)) + g_filter[l - 1] = 0; + } + else if (_istalnum(LOWORD(wParam))) { + if (lstrlen(g_filter) < SIZEOF(g_filter) - 1) { + TCHAR s[] = { LOWORD(wParam), 0 }; + lstrcat(g_filter, s); + } + } + { + int maxRecent = g_Options.wMaxRecent ? g_Options.wMaxRecent : 10; + for (int i = 0, nRecent = 0; nRecent < maxRecent; ++i) { + MCONTACT hContact = g_contactCache->get(i); + if (!hContact) break; + if (!g_contactCache->filter(i, g_filter)) continue; + + AppendMenu((HMENU)lParam, MF_OWNERDRAW, nRecent + 1, (LPCTSTR)hContact); + ++nRecent; + } + } + return MAKELRESULT(1, MNC_SELECT); + + case WM_MENURBUTTONUP: + MENUITEMINFO mii = { sizeof(mii) }; + mii.fMask = MIIM_DATA; + GetMenuItemInfo((HMENU)lParam, wParam, TRUE, &mii); + MCONTACT hContact = (MCONTACT)mii.dwItemData; + if (!CallService(MS_DB_CONTACT_IS, mii.dwItemData, 0)) + return FALSE; + + HMENU hMenu = (HMENU)CallService(MS_CLIST_MENUBUILDCONTACT, hContact, 0); + + POINT pt; + GetCursorPos(&pt); + HWND hwndSave = GetForegroundWindow(); + SetForegroundWindow(g_hwndMenuHost); + int res = TrackPopupMenu(hMenu, TPM_RECURSE | TPM_RIGHTBUTTON | TPM_RETURNCMD, pt.x, pt.y, 0, g_hwndMenuHost, NULL); + SetForegroundWindow(hwndSave); + DestroyMenu(hMenu); + + CallService(MS_CLIST_MENUPROCESSCOMMAND, MAKEWPARAM(res, MPCF_CONTACTMENU), hContact); + return TRUE; + } + + return DefWindowProc(hwnd, message, wParam, lParam); +} + +int ShowMenu(bool centered) +{ + HMENU hMenu = CreatePopupMenu(); + SIZE szMenu = { 0 }; + SIZE szColumn = { 0 }; + TCHAR *prevGroup = NULL; + int idItem = 100; + MCONTACT hContact; + + TFavContacts favList; + favList.build(); + + g_widthMultiplier = 0; + + g_maxItemWidth = GetSystemMetrics(SM_CXSCREEN); + if (g_Options.bUseColumns) + g_maxItemWidth /= favList.groupCount(); + + prevGroup = NULL; + for (int i = 0; i < favList.getCount(); ++i) { + hContact = favList[i]->getHandle(); + + MEASUREITEMSTRUCT mis = { 0 }; + mis.CtlID = 0; + mis.CtlType = ODT_MENU; + + if (!prevGroup || lstrcmp(prevGroup, favList[i]->getGroup())) { + if (prevGroup && g_Options.bUseColumns) { + szMenu.cx += szColumn.cx; + szMenu.cy = max(szMenu.cy, szColumn.cy); + szColumn.cx = szColumn.cy = 0; + } + + int groupID = -((int)Clist_GroupExists(favList[i]->getGroup()) + 1); + + AppendMenu(hMenu, + MF_OWNERDRAW | MF_SEPARATOR | ((prevGroup && g_Options.bUseColumns) ? MF_MENUBREAK : 0), + ++idItem, (LPCTSTR)groupID); + + mis.itemData = groupID; + mis.itemID = idItem; + MenuMeasureItem(&mis); + szColumn.cx = max(szColumn.cx, (int)mis.itemWidth); + szColumn.cy += mis.itemHeight; + } + + AppendMenu(hMenu, MF_OWNERDRAW, ++idItem, (LPCTSTR)hContact); + + mis.itemData = (DWORD)hContact; + mis.itemID = idItem; + MenuMeasureItem(&mis); + szColumn.cx = max(szColumn.cx, (int)mis.itemWidth); + szColumn.cy += mis.itemHeight; + + prevGroup = favList[i]->getGroup(); + } + szMenu.cx += szColumn.cx; + szMenu.cy = max(szMenu.cy, szColumn.cy); + szColumn.cx = szColumn.cy = 0; + + int maxWidth = GetSystemMetrics(SM_CXSCREEN) * db_get_b(NULL, "FavContacts", "MenuWidth", 66) / 100; + if (szMenu.cx > maxWidth) { + g_widthMultiplier = (float)maxWidth / szMenu.cx; + szMenu.cx *= g_widthMultiplier; + } + + POINT pt; + if (centered) { + if ((pt.x = (GetSystemMetrics(SM_CXSCREEN) - szMenu.cx) / 2) < 0) pt.x = 0; + if ((pt.y = (GetSystemMetrics(SM_CYSCREEN) - szMenu.cy) / 2) < 0) pt.y = 0; + } + else GetCursorPos(&pt); + + HWND hwndSave = GetForegroundWindow(); + SetForegroundWindow(g_hwndMenuHost); + hContact = NULL; + g_filter[0] = 0; + + if (int res = TrackPopupMenu(hMenu, TPM_RETURNCMD, pt.x, pt.y, 0, g_hwndMenuHost, NULL)) { + MENUITEMINFO mii = { 0 }; + mii.cbSize = sizeof(mii); + mii.fMask = MIIM_DATA; + GetMenuItemInfo(hMenu, res, FALSE, &mii); + hContact = (MCONTACT)mii.dwItemData; + } + SetForegroundWindow(hwndSave); + DestroyMenu(hMenu); + + if (hContact) + CallService(MS_CLIST_CONTACTDOUBLECLICKED, hContact, 0); + + return 0; +} + +void InitMenu() +{ + WNDCLASSEX wcl = { sizeof(wcl) }; + wcl.lpfnWndProc = MenuHostWndProc; + wcl.hInstance = g_hInst; + wcl.hCursor = LoadCursor(NULL, IDC_ARROW); + wcl.hbrBackground = (HBRUSH)GetStockObject(LTGRAY_BRUSH); + wcl.lpszClassName = _T("FavContactsMenuHostWnd"); + RegisterClassEx(&wcl); + + g_hwndMenuHost = CreateWindow(_T("FavContactsMenuHostWnd"), NULL, 0, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, HWND_DESKTOP, NULL, g_hInst, NULL); + SetWindowPos(g_hwndMenuHost, 0, 0, 0, 0, 0, SWP_NOZORDER | SWP_NOMOVE | SWP_NOSIZE | SWP_NOACTIVATE | SWP_DEFERERASE | SWP_NOSENDCHANGING | SWP_HIDEWINDOW); +} + +void UninitMenu() +{ + if (g_hwndMenuHost) + DestroyWindow(g_hwndMenuHost); +} diff --git a/plugins/FavContacts/src/options.cpp b/plugins/FavContacts/src/options.cpp new file mode 100644 index 0000000000..2afb2e1ae8 --- /dev/null +++ b/plugins/FavContacts/src/options.cpp @@ -0,0 +1,280 @@ +/* +Favorite Contacts for Miranda IM + +Copyright 2007 Victor Pavlychko + +This program is free software; you can redistribute it and/or +modify it under the terms of the GNU General Public License +as published by the Free Software Foundation; either version 2 +of the License, or (at your option) any later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program; if not, write to the Free Software +Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +*/ + +#include "headers.h" + +void LoadOptions() +{ + g_Options.bSecondLine = db_get_b(NULL, "FavContacts", "SecondLine", 1); + g_Options.bAvatars = db_get_b(NULL, "FavContacts", "Avatars", 1); + g_Options.bAvatarBorder = db_get_b(NULL, "FavContacts", "AvatarBorder", 0); + g_Options.wAvatarRadius = db_get_w(NULL, "FavContacts", "AvatarRadius", 3); + g_Options.bNoTransparentBorder = db_get_b(NULL, "FavContacts", "NoTransparentBorder", + !db_get_b(NULL, "FavContacts", "AvatarBorderTransparent", 1)); + g_Options.bSysColors = db_get_b(NULL, "FavContacts", "SysColors", 0); + g_Options.bCenterHotkey = db_get_b(NULL, "FavContacts", "CenterHotkey", 1); + g_Options.bUseGroups = db_get_b(NULL, "FavContacts", "UseGroups", 0); + g_Options.bUseColumns = db_get_b(NULL, "FavContacts", "UseColumns", 1); + g_Options.bRightAvatars = db_get_b(NULL, "FavContacts", "RightAvatars", 0); + g_Options.bDimIdle = db_get_b(NULL, "FavContacts", "DimIdle", 1); + + g_Options.wMaxRecent = db_get_b(NULL, "FavContacts", "MaxRecent", 10); +} + +static void sttSaveOptions() +{ + db_set_b(NULL, "FavContacts", "SecondLine", g_Options.bSecondLine); + db_set_b(NULL, "FavContacts", "Avatars", g_Options.bAvatars); + db_set_b(NULL, "FavContacts", "AvatarBorder", g_Options.bAvatarBorder); + db_set_w(NULL, "FavContacts", "AvatarRadius", g_Options.wAvatarRadius); + db_set_b(NULL, "FavContacts", "NoTransparentBorder", g_Options.bNoTransparentBorder); + db_set_b(NULL, "FavContacts", "SysColors", g_Options.bSysColors); + db_set_b(NULL, "FavContacts", "CenterHotkey", g_Options.bCenterHotkey); + db_set_b(NULL, "FavContacts", "UseGroups", g_Options.bUseGroups); + db_set_b(NULL, "FavContacts", "UseColumns", g_Options.bUseColumns); + db_set_b(NULL, "FavContacts", "RightAvatars", g_Options.bRightAvatars); + db_set_b(NULL, "FavContacts", "DimIdle", g_Options.bDimIdle); + db_set_w(NULL, "FavContacts", "MaxRecent", g_Options.wMaxRecent); +} + +static void sttResetListOptions(HWND hwndList) +{ + SendMessage(hwndList, CLM_SETBKBITMAP, 0, (LPARAM)(HBITMAP)NULL); + SendMessage(hwndList, CLM_SETBKCOLOR, GetSysColor(COLOR_WINDOW), 0); + SendMessage(hwndList, CLM_SETGREYOUTFLAGS, 0, 0); + SendMessage(hwndList, CLM_SETLEFTMARGIN, 4, 0); + SendMessage(hwndList, CLM_SETINDENT, 10, 0); + SendMessage(hwndList, CLM_SETHIDEEMPTYGROUPS, 1, 0); + SendMessage(hwndList, CLM_SETHIDEOFFLINEROOT, 1, 0); + for (int i = 0; i <= FONTID_MAX; ++i) + SendMessage(hwndList, CLM_SETTEXTCOLOR, i, GetSysColor(COLOR_WINDOWTEXT)); +} + +static INT_PTR CALLBACK OptionsDlgProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam) +{ + static bool bInitialized = false; + static MCONTACT hSelectedContact = 0; + + switch (msg) { + case WM_INITDIALOG: + bInitialized = false; + + TranslateDialogDefault(hwnd); + + CheckDlgButton(hwnd, IDC_CHK_GROUPS, g_Options.bUseGroups ? BST_CHECKED : BST_UNCHECKED); + CheckDlgButton(hwnd, IDC_CHK_GROUPCOLUMS, g_Options.bUseColumns ? BST_CHECKED : BST_UNCHECKED); + CheckDlgButton(hwnd, IDC_CHK_SECONDLINE, g_Options.bSecondLine ? BST_CHECKED : BST_UNCHECKED); + CheckDlgButton(hwnd, IDC_CHK_AVATARS, g_Options.bAvatars ? BST_CHECKED : BST_UNCHECKED); + CheckDlgButton(hwnd, IDC_CHK_AVATARBORDER, g_Options.bAvatarBorder ? BST_CHECKED : BST_UNCHECKED); + CheckDlgButton(hwnd, IDC_CHK_NOTRANSPARENTBORDER, g_Options.bNoTransparentBorder ? BST_CHECKED : BST_UNCHECKED); + CheckDlgButton(hwnd, IDC_CHK_SYSCOLORS, g_Options.bSysColors ? BST_CHECKED : BST_UNCHECKED); + CheckDlgButton(hwnd, IDC_CHK_CENTERHOTKEY, g_Options.bCenterHotkey ? BST_CHECKED : BST_UNCHECKED); + CheckDlgButton(hwnd, IDC_CHK_RIGHTAVATARS, g_Options.bRightAvatars ? BST_CHECKED : BST_UNCHECKED); + CheckDlgButton(hwnd, IDC_CHK_DIMIDLE, g_Options.bDimIdle ? BST_CHECKED : BST_UNCHECKED); + SetDlgItemInt(hwnd, IDC_TXT_RADIUS, g_Options.wAvatarRadius, FALSE); + SetDlgItemInt(hwnd, IDC_TXT_MAXRECENT, g_Options.wMaxRecent, FALSE); + + SetWindowLongPtr(GetDlgItem(hwnd, IDC_CLIST), GWL_STYLE, + GetWindowLongPtr(GetDlgItem(hwnd, IDC_CLIST), GWL_STYLE) | CLS_CHECKBOXES | CLS_HIDEEMPTYGROUPS | CLS_USEGROUPS | CLS_GREYALTERNATE | CLS_GROUPCHECKBOXES); + SendMessage(GetDlgItem(hwnd, IDC_CLIST), CLM_SETEXSTYLE, CLS_EX_DISABLEDRAGDROP | CLS_EX_TRACKSELECT, 0); + sttResetListOptions(GetDlgItem(hwnd, IDC_CLIST)); + + hSelectedContact = db_find_first(); + { + for (MCONTACT hContact = db_find_first(); hContact; hContact = db_find_next(hContact)) + SendDlgItemMessage(hwnd, IDC_CLIST, CLM_SETCHECKMARK, + SendDlgItemMessage(hwnd, IDC_CLIST, CLM_FINDCONTACT, hContact, 0), + db_get_b(hContact, "FavContacts", "IsFavourite", 0)); + } + + bInitialized = true; + PostMessage(hwnd, WM_APP, 0, 0); + return TRUE; + + case WM_APP: + { + BOOL bGroups = IsDlgButtonChecked(hwnd, IDC_CHK_GROUPS); + EnableWindow(GetDlgItem(hwnd, IDC_CHK_GROUPCOLUMS), bGroups); + + BOOL bAvatars = IsDlgButtonChecked(hwnd, IDC_CHK_AVATARS); + BOOL bBorders = IsDlgButtonChecked(hwnd, IDC_CHK_AVATARBORDER); + EnableWindow(GetDlgItem(hwnd, IDC_CHK_AVATARBORDER), bAvatars); + EnableWindow(GetDlgItem(hwnd, IDC_CHK_RIGHTAVATARS), bAvatars); + EnableWindow(GetDlgItem(hwnd, IDC_CHK_NOTRANSPARENTBORDER), bAvatars && bBorders); + EnableWindow(GetDlgItem(hwnd, IDC_TXT_RADIUS), bAvatars && bBorders); + } + return TRUE; + + case WM_DRAWITEM: + { + LPDRAWITEMSTRUCT lpdis = (LPDRAWITEMSTRUCT)lParam; + if (lpdis->CtlID == IDC_CANVAS) { + MEASUREITEMSTRUCT mis = { 0 }; + DRAWITEMSTRUCT dis = *lpdis; + + FillRect(lpdis->hDC, &lpdis->rcItem, GetSysColorBrush(COLOR_BTNFACE)); + if (hSelectedContact) { + Options options; + options.bSecondLine = IsDlgButtonChecked(hwnd, IDC_CHK_SECONDLINE); + options.bAvatars = IsDlgButtonChecked(hwnd, IDC_CHK_AVATARS); + options.bAvatarBorder = IsDlgButtonChecked(hwnd, IDC_CHK_AVATARBORDER); + options.bNoTransparentBorder = IsDlgButtonChecked(hwnd, IDC_CHK_NOTRANSPARENTBORDER); + options.bSysColors = IsDlgButtonChecked(hwnd, IDC_CHK_SYSCOLORS); + options.bCenterHotkey = IsDlgButtonChecked(hwnd, IDC_CHK_CENTERHOTKEY); + options.bRightAvatars = IsDlgButtonChecked(hwnd, IDC_CHK_RIGHTAVATARS); + options.bDimIdle = IsDlgButtonChecked(hwnd, IDC_CHK_DIMIDLE); + options.wAvatarRadius = GetDlgItemInt(hwnd, IDC_TXT_RADIUS, NULL, FALSE); + options.wMaxRecent = GetDlgItemInt(hwnd, IDC_TXT_MAXRECENT, NULL, FALSE); + + mis.CtlID = 0; + mis.CtlType = ODT_MENU; + mis.itemData = (DWORD)hSelectedContact; + MenuMeasureItem(&mis, &options); + dis.rcItem.bottom = dis.rcItem.top + mis.itemHeight; + + dis.CtlID = 0; + dis.CtlType = ODT_MENU; + dis.itemData = (DWORD)hSelectedContact; + MenuDrawItem(&dis, &options); + + RECT rc = lpdis->rcItem; + rc.bottom = rc.top + mis.itemHeight; + FrameRect(lpdis->hDC, &rc, GetSysColorBrush(COLOR_HIGHLIGHT)); + } + return TRUE; + } + } + return FALSE; + + case WM_COMMAND: + switch (LOWORD(wParam)) { + case IDC_CHK_SECONDLINE: + case IDC_CHK_AVATARS: + case IDC_CHK_AVATARBORDER: + case IDC_CHK_NOTRANSPARENTBORDER: + case IDC_CHK_SYSCOLORS: + case IDC_CHK_CENTERHOTKEY: + case IDC_CHK_GROUPS: + case IDC_CHK_GROUPCOLUMS: + case IDC_CHK_RIGHTAVATARS: + SendMessage(GetParent(hwnd), PSM_CHANGED, 0, 0); + RedrawWindow(GetDlgItem(hwnd, IDC_CANVAS), NULL, NULL, RDW_INVALIDATE); + PostMessage(hwnd, WM_APP, 0, 0); + break; + + case IDC_BTN_FONTS: + { + OPENOPTIONSDIALOG ood = { sizeof(ood) }; + ood.pszGroup = "Customize"; + ood.pszPage = "Fonts and colors"; + ood.pszTab = NULL; + Options_Open(&ood); + } + break; + + case IDC_TXT_RADIUS: + if ((HIWORD(wParam) == EN_CHANGE) && bInitialized) { + RedrawWindow(GetDlgItem(hwnd, IDC_CANVAS), NULL, NULL, RDW_INVALIDATE); + SendMessage(GetParent(hwnd), PSM_CHANGED, 0, 0); + } + break; + + case IDC_TXT_MAXRECENT: + if ((HIWORD(wParam) == EN_CHANGE) && bInitialized) + SendMessage(GetParent(hwnd), PSM_CHANGED, 0, 0); + break; + } + break; + + case WM_NOTIFY: + if ((((LPNMHDR)lParam)->idFrom == 0) && (((LPNMHDR)lParam)->code == PSN_APPLY)) { + g_Options.bSecondLine = IsDlgButtonChecked(hwnd, IDC_CHK_SECONDLINE); + g_Options.bAvatars = IsDlgButtonChecked(hwnd, IDC_CHK_AVATARS); + g_Options.bAvatarBorder = IsDlgButtonChecked(hwnd, IDC_CHK_AVATARBORDER); + g_Options.bNoTransparentBorder = IsDlgButtonChecked(hwnd, IDC_CHK_NOTRANSPARENTBORDER); + g_Options.bSysColors = IsDlgButtonChecked(hwnd, IDC_CHK_SYSCOLORS); + g_Options.bCenterHotkey = IsDlgButtonChecked(hwnd, IDC_CHK_CENTERHOTKEY); + g_Options.bUseGroups = IsDlgButtonChecked(hwnd, IDC_CHK_GROUPS); + g_Options.bUseColumns = IsDlgButtonChecked(hwnd, IDC_CHK_GROUPCOLUMS); + g_Options.bRightAvatars = IsDlgButtonChecked(hwnd, IDC_CHK_RIGHTAVATARS); + g_Options.bDimIdle = IsDlgButtonChecked(hwnd, IDC_CHK_DIMIDLE); + g_Options.wAvatarRadius = GetDlgItemInt(hwnd, IDC_TXT_RADIUS, NULL, FALSE); + g_Options.wMaxRecent = GetDlgItemInt(hwnd, IDC_TXT_MAXRECENT, NULL, FALSE); + + sttSaveOptions(); + + for (MCONTACT hContact = db_find_first(); hContact; hContact = db_find_next(hContact)) { + BYTE fav = SendDlgItemMessage(hwnd, IDC_CLIST, CLM_GETCHECKMARK, + SendDlgItemMessage(hwnd, IDC_CLIST, CLM_FINDCONTACT, hContact, 0), 0); + if (fav != db_get_b(hContact, "FavContacts", "IsFavourite", 0)) + db_set_b(hContact, "FavContacts", "IsFavourite", fav); + if (fav) CallService(MS_AV_GETAVATARBITMAP, hContact, 0); + } + } + else if (((LPNMHDR)lParam)->idFrom == IDC_CLIST) { + int iSelection; + + switch (((LPNMHDR)lParam)->code) { + case CLN_OPTIONSCHANGED: + sttResetListOptions(GetDlgItem(hwnd, IDC_CLIST)); + break; + + case CLN_NEWCONTACT: + iSelection = (int)((NMCLISTCONTROL *)lParam)->hItem; + for (MCONTACT hContact = db_find_first(); hContact; hContact = db_find_next(hContact)) { + if (SendDlgItemMessage(hwnd, IDC_CLIST, CLM_FINDCONTACT, hContact, 0) == iSelection) { + SendDlgItemMessage(hwnd, IDC_CLIST, CLM_SETCHECKMARK, iSelection, + db_get_b(hContact, "FavContacts", "IsFavourite", 0)); + break; + } + } + break; + + case CLN_CHECKCHANGED: + iSelection = (int)((NMCLISTCONTROL *)lParam)->hItem; + for (MCONTACT hContact = db_find_first(); hContact; hContact = db_find_next(hContact)) { + if (SendDlgItemMessage(hwnd, IDC_CLIST, CLM_FINDCONTACT, hContact, 0) == iSelection) { + hSelectedContact = hContact; + RedrawWindow(GetDlgItem(hwnd, IDC_CANVAS), NULL, NULL, RDW_INVALIDATE); + } + } + SendMessage(GetParent(hwnd), PSM_CHANGED, 0, 0); + } + } + break; + } + + return FALSE; +} + +int ProcessOptInitialise(WPARAM wParam, LPARAM lParam) +{ + OPTIONSDIALOGPAGE odp = { sizeof(odp) }; + odp.position = 100000000; + odp.hInstance = g_hInst; + odp.pszTemplate = MAKEINTRESOURCEA(IDD_OPTIONS); + odp.pszGroup = LPGEN("Contacts"); + odp.pszTitle = LPGEN("Favorites"); + odp.groupPosition = 910000000; + odp.flags = ODPF_BOLDGROUPS; + odp.pfnDlgProc = OptionsDlgProc; + Options_AddPage(wParam, &odp); + return 0; +} diff --git a/plugins/FavContacts/src/services.cpp b/plugins/FavContacts/src/services.cpp new file mode 100644 index 0000000000..b853dac162 --- /dev/null +++ b/plugins/FavContacts/src/services.cpp @@ -0,0 +1,263 @@ +/* +Favorite Contacts for Miranda IM + +Copyright 2007 Victor Pavlychko + +This program is free software; you can redistribute it and/or +modify it under the terms of the GNU General Public License +as published by the Free Software Foundation; either version 2 +of the License, or (at your option) any later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program; if not, write to the Free Software +Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +*/ + +#include "headers.h" + +static MCONTACT hContactToActivate; +static HANDLE hDialogsList; + +INT_PTR svcShowMenu(WPARAM wParam, LPARAM lParam) +{ + ShowMenu(false); + return 0; +} + +INT_PTR svcShowMenuCentered(WPARAM wParam, LPARAM lParam) +{ + ShowMenu(g_Options.bCenterHotkey ? true : false); + return 0; +} + +INT_PTR svcOpenContact(WPARAM wParam, LPARAM lParam) +{ + hContactToActivate = wParam; + CallService(MS_CLIST_CONTACTDOUBLECLICKED, (WPARAM)hContactToActivate, 0); + return 0; +} + +int ProcessSrmmEvent(WPARAM wParam, LPARAM lParam) +{ + MessageWindowEventData *event = (MessageWindowEventData *)lParam; + + if (event->uType == MSG_WINDOW_EVT_OPEN) { + if (!hDialogsList) + hDialogsList = WindowList_Create(); + WindowList_Add(hDialogsList, event->hwndWindow, event->hContact); + + BYTE fav = db_get_b(event->hContact, "FavContacts", "IsFavourite", 0); + StatusIconData sid = { sizeof(sid) }; + sid.szModule = "FavContacts"; + sid.flags = fav ? 0 : MBF_DISABLED; + Srmm_ModifyIcon(event->hContact, &sid); + + if (event->hContact == hContactToActivate) { + HWND hwndRoot = event->hwndWindow; + while (HWND hwndParent = GetParent(hwndRoot)) + hwndRoot = hwndParent; + + AttachThreadInput(GetWindowThreadProcessId(GetForegroundWindow(), NULL), GetCurrentThreadId(), TRUE); + SetForegroundWindow(hwndRoot); + SetActiveWindow(hwndRoot); + SetFocus(hwndRoot); + AttachThreadInput(GetWindowThreadProcessId(GetForegroundWindow(), NULL), GetCurrentThreadId(), FALSE); + } + + hContactToActivate = NULL; + } + else if (event->uType == MSG_WINDOW_EVT_CLOSING) { + if (hDialogsList) + WindowList_Remove(hDialogsList, event->hwndWindow); + } + + return 0; +} + +int ProcessSrmmIconClick(WPARAM hContact, LPARAM lParam) +{ + StatusIconClickData *sicd = (StatusIconClickData *)lParam; + if (lstrcmpA(sicd->szModule, "FavContacts")) return 0; + + if (!hContact) + return 0; + + if (sicd->flags & MBCF_RIGHTBUTTON) { + BYTE fav = !db_get_b(hContact, "FavContacts", "IsFavourite", 0); + db_set_b(hContact, "FavContacts", "IsFavourite", fav); + if (fav) CallService(MS_AV_GETAVATARBITMAP, hContact, 0); + + StatusIconData sid = { sizeof(sid) }; + sid.szModule = "FavContacts"; + sid.flags = fav ? 0 : MBF_DISABLED; + Srmm_ModifyIcon(hContact, &sid); + } + else ShowMenu(false); + + return 0; +} + +static __forceinline COLORREF sttShadeColor(COLORREF clLine1, COLORREF clBack) +{ + return RGB( + (GetRValue(clLine1) * 66UL + GetRValue(clBack) * 34UL) / 100, + (GetGValue(clLine1) * 66UL + GetGValue(clBack) * 34UL) / 100, + (GetBValue(clLine1) * 66UL + GetBValue(clBack) * 34UL) / 100); +} + +int ProcessTBLoaded(WPARAM wParam, LPARAM lParam) +{ + TTBButton ttb = { sizeof(ttb) }; + ttb.pszTooltipUp = ttb.name = LPGEN("Favorite Contacts"); + ttb.pszService = MS_FAVCONTACTS_SHOWMENU; + ttb.dwFlags = TTBBF_SHOWTOOLTIP | TTBBF_VISIBLE; + ttb.hIconHandleUp = iconList[0].hIcolib; + TopToolbar_AddButton(&ttb); + return 0; +} + +int ProcessReloadFonts(WPARAM wParam, LPARAM lParam) +{ + if (g_Options.hfntName) DeleteObject(g_Options.hfntName); + if (g_Options.hfntSecond) DeleteObject(g_Options.hfntSecond); + + LOGFONT lf = { 0 }; + FontIDT fontid = { sizeof(fontid) }; + lstrcpy(fontid.group, LPGENT("Favorite Contacts")); + lstrcpy(fontid.name, LPGENT("Contact name")); + g_Options.clLine1 = CallService(MS_FONT_GETT, (WPARAM)&fontid, (LPARAM)&lf); + g_Options.hfntName = CreateFontIndirect(&lf); + + lstrcpy(fontid.name, LPGENT("Second line")); + g_Options.clLine2 = CallService(MS_FONT_GETT, (WPARAM)&fontid, (LPARAM)&lf); + g_Options.hfntSecond = CreateFontIndirect(&lf); + + lstrcpy(fontid.name, LPGENT("Selected contact name (color)")); + g_Options.clLine1Sel = CallService(MS_FONT_GETT, (WPARAM)&fontid, (LPARAM)&lf); + + lstrcpy(fontid.name, LPGENT("Selected second line (color)")); + g_Options.clLine2Sel = CallService(MS_FONT_GETT, (WPARAM)&fontid, (LPARAM)&lf); + + ColourIDT colourid = { sizeof(colourid) }; + lstrcpy(colourid.group, LPGENT("Favorite Contacts")); + lstrcpy(colourid.name, LPGENT("Background")); + g_Options.clBack = CallService(MS_COLOUR_GETT, (WPARAM)&colourid, (LPARAM)&lf); + + lstrcpy(colourid.name, LPGENT("Selected background")); + g_Options.clBackSel = CallService(MS_COLOUR_GETT, (WPARAM)&colourid, (LPARAM)&lf); + + return 0; +} + +int ProcessModulesLoaded(WPARAM wParam, LPARAM lParam) +{ + HookEvent(ME_TTB_MODULELOADED, ProcessTBLoaded); + + StatusIconData sid = { sizeof(sid) }; + sid.szModule = "FavContacts"; + sid.szTooltip = LPGEN("Favorite Contacts"); + sid.hIcon = Skin_GetIconByHandle(iconList[0].hIcolib); + sid.hIconDisabled = Skin_GetIconByHandle(iconList[1].hIcolib); + Srmm_AddIcon(&sid); + + HookEvent(ME_MSG_ICONPRESSED, ProcessSrmmIconClick); + HookEvent(ME_MSG_WINDOWEVENT, ProcessSrmmEvent); + + ///////////////////////////////////////////////////////////////////////////////////// + + FontIDT fontid = { sizeof(fontid) }; + lstrcpy(fontid.group, LPGENT("Favorite Contacts")); + lstrcpyA(fontid.dbSettingsGroup, "FavContacts"); + lstrcpy(fontid.backgroundGroup, LPGENT("Favorite Contacts")); + fontid.flags = FIDF_DEFAULTVALID; + fontid.deffontsettings.charset = DEFAULT_CHARSET; + fontid.deffontsettings.size = -11; + lstrcpy(fontid.deffontsettings.szFace, _T("MS Shell Dlg")); + fontid.deffontsettings.style = 0; + + lstrcpy(fontid.backgroundName, LPGENT("Background")); + + lstrcpy(fontid.name, LPGENT("Contact name")); + lstrcpyA(fontid.prefix, "fntName"); + fontid.deffontsettings.colour = GetSysColor(COLOR_MENUTEXT); + fontid.deffontsettings.style = DBFONTF_BOLD; + FontRegisterT(&fontid); + + lstrcpy(fontid.name, LPGENT("Second line")); + lstrcpyA(fontid.prefix, "fntSecond"); + fontid.deffontsettings.colour = sttShadeColor(GetSysColor(COLOR_MENUTEXT), GetSysColor(COLOR_MENU)); + fontid.deffontsettings.style = 0; + FontRegisterT(&fontid); + + lstrcpy(fontid.backgroundName, LPGENT("Selected background")); + + lstrcpy(fontid.name, LPGENT("Selected contact name (color)")); + lstrcpyA(fontid.prefix, "fntNameSel"); + fontid.deffontsettings.colour = GetSysColor(COLOR_HIGHLIGHTTEXT); + fontid.deffontsettings.style = DBFONTF_BOLD; + FontRegisterT(&fontid); + + lstrcpy(fontid.name, LPGENT("Selected second line (color)")); + lstrcpyA(fontid.prefix, "fntSecondSel"); + fontid.deffontsettings.colour = sttShadeColor(GetSysColor(COLOR_HIGHLIGHTTEXT), GetSysColor(COLOR_HIGHLIGHT)); + fontid.deffontsettings.style = 0; + FontRegisterT(&fontid); + + ///////////////////////////////////////////////////////////////////////////////////// + + ColourIDT colourid = { sizeof(colourid) }; + lstrcpy(colourid.group, LPGENT("Favorite Contacts")); + lstrcpyA(colourid.dbSettingsGroup, "FavContacts"); + + lstrcpy(colourid.name, LPGENT("Background")); + lstrcpyA(colourid.setting, "BackColour"); + colourid.defcolour = GetSysColor(COLOR_MENU); + ColourRegisterT(&colourid); + + lstrcpy(colourid.name, LPGENT("Selected background")); + lstrcpyA(colourid.setting, "SelectedColour"); + colourid.defcolour = GetSysColor(COLOR_HIGHLIGHT); + ColourRegisterT(&colourid); + + HookEvent(ME_FONT_RELOAD, ProcessReloadFonts); + HookEvent(ME_COLOUR_RELOAD, ProcessReloadFonts); + ProcessReloadFonts(0, 0); + + ///////////////////////////////////////////////////////////////////////////////////// + + HOTKEYDESC hotkey = { sizeof(hotkey) }; + hotkey.pszName = "FavContacts/ShowMenu"; + hotkey.pszDescription = LPGEN("Show favorite contacts"); + hotkey.pszSection = "Contacts"; + hotkey.pszService = MS_FAVCONTACTS_SHOWMENU_CENTERED; + hotkey.DefHotKey = MAKEWORD('Q', HOTKEYF_EXT); + Hotkey_Register(&hotkey); + + if (ServiceExists(MS_AV_GETAVATARBITMAP)) { + for (MCONTACT hContact = db_find_first(); hContact; hContact = db_find_next(hContact)) + if (db_get_b(hContact, "FavContacts", "IsFavourite", 0)) + CallService(MS_AV_GETAVATARBITMAP, hContact, 0); + } + + return 0; +} + +void InitServices() +{ + CreateServiceFunction(MS_FAVCONTACTS_SHOWMENU, svcShowMenu); + CreateServiceFunction(MS_FAVCONTACTS_SHOWMENU_CENTERED, svcShowMenuCentered); + CreateServiceFunction(MS_FAVCONTACTS_OPEN_CONTACT, svcOpenContact); + + HookEvent(ME_OPT_INITIALISE, ProcessOptInitialise); + HookEvent(ME_SYSTEM_MODULESLOADED, ProcessModulesLoaded); +} + +void UninitServices() +{ + WindowList_Destroy(hDialogsList); +} -- cgit v1.2.3