From 35d50950b5c60523f5a4a4959ee5e5a370ceabef Mon Sep 17 00:00:00 2001 From: MikalaiR Date: Tue, 9 Jun 2015 11:38:48 +0000 Subject: MessageState: Initial commit. git-svn-id: http://svn.miranda-ng.org/main/trunk@14072 1316c22d-e87f-b044-9b9b-93d7a3e3ba9c --- plugins/MessageState/MessageState.vcxproj | 28 ++++ plugins/MessageState/MessageState.vcxproj.filters | 4 + plugins/MessageState/res/fail.ico | Bin 0 -> 1150 bytes plugins/MessageState/res/nosent.ico | Bin 0 -> 1150 bytes plugins/MessageState/res/read.ico | Bin 0 -> 1150 bytes plugins/MessageState/res/resource.rc | 73 ++++++++++ plugins/MessageState/res/unread.ico | Bin 0 -> 1150 bytes plugins/MessageState/res/version.rc | 38 +++++ plugins/MessageState/src/global.h | 28 ++++ plugins/MessageState/src/main.cpp | 43 ++++++ plugins/MessageState/src/messagestate.cpp | 160 ++++++++++++++++++++++ plugins/MessageState/src/resource.h | 19 +++ plugins/MessageState/src/stdafx.cxx | 18 +++ plugins/MessageState/src/stdafx.h | 23 ++++ plugins/MessageState/src/version.h | 14 ++ 15 files changed, 448 insertions(+) create mode 100644 plugins/MessageState/MessageState.vcxproj create mode 100644 plugins/MessageState/MessageState.vcxproj.filters create mode 100644 plugins/MessageState/res/fail.ico create mode 100644 plugins/MessageState/res/nosent.ico create mode 100644 plugins/MessageState/res/read.ico create mode 100644 plugins/MessageState/res/resource.rc create mode 100644 plugins/MessageState/res/unread.ico create mode 100644 plugins/MessageState/res/version.rc create mode 100644 plugins/MessageState/src/global.h create mode 100644 plugins/MessageState/src/main.cpp create mode 100644 plugins/MessageState/src/messagestate.cpp create mode 100644 plugins/MessageState/src/resource.h create mode 100644 plugins/MessageState/src/stdafx.cxx create mode 100644 plugins/MessageState/src/stdafx.h create mode 100644 plugins/MessageState/src/version.h (limited to 'plugins') diff --git a/plugins/MessageState/MessageState.vcxproj b/plugins/MessageState/MessageState.vcxproj new file mode 100644 index 0000000000..435e2dd6cc --- /dev/null +++ b/plugins/MessageState/MessageState.vcxproj @@ -0,0 +1,28 @@ + + + + + Debug + Win32 + + + Debug + x64 + + + Release + Win32 + + + Release + x64 + + + + MessageState + {5F09C93B-463A-4BF5-A85E-6E4E916AA8F8} + + + + + \ No newline at end of file diff --git a/plugins/MessageState/MessageState.vcxproj.filters b/plugins/MessageState/MessageState.vcxproj.filters new file mode 100644 index 0000000000..de5ad9f66c --- /dev/null +++ b/plugins/MessageState/MessageState.vcxproj.filters @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/plugins/MessageState/res/fail.ico b/plugins/MessageState/res/fail.ico new file mode 100644 index 0000000000..0056538ccd Binary files /dev/null and b/plugins/MessageState/res/fail.ico differ diff --git a/plugins/MessageState/res/nosent.ico b/plugins/MessageState/res/nosent.ico new file mode 100644 index 0000000000..67587965fd Binary files /dev/null and b/plugins/MessageState/res/nosent.ico differ diff --git a/plugins/MessageState/res/read.ico b/plugins/MessageState/res/read.ico new file mode 100644 index 0000000000..60d0d2f7ad Binary files /dev/null and b/plugins/MessageState/res/read.ico differ diff --git a/plugins/MessageState/res/resource.rc b/plugins/MessageState/res/resource.rc new file mode 100644 index 0000000000..639fe66254 --- /dev/null +++ b/plugins/MessageState/res/resource.rc @@ -0,0 +1,73 @@ +// Microsoft Visual C++ generated resource script. +// +#include "..\src\resource.h" + +#define APSTUDIO_READONLY_SYMBOLS +///////////////////////////////////////////////////////////////////////////// +// +// Generated from the TEXTINCLUDE 2 resource. +// +#include "afxres.h" + +///////////////////////////////////////////////////////////////////////////// +#undef APSTUDIO_READONLY_SYMBOLS + +///////////////////////////////////////////////////////////////////////////// +// Czech (Czech Republic) resources + +#if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_CSY) +LANGUAGE LANG_CZECH, SUBLANG_DEFAULT +#pragma code_page(1250) + +///////////////////////////////////////////////////////////////////////////// +// +// Icon +// + +// Icon with lowest ID value placed first to ensure application icon +// remains consistent on all systems. +IDI_READ ICON "read.ico" +IDI_UNREAD ICON "unread.ico" +IDI_FAIL ICON "fail.ico" +IDI_NOSENT ICON "nosent.ico" + +#ifdef APSTUDIO_INVOKED +///////////////////////////////////////////////////////////////////////////// +// +// TEXTINCLUDE +// + +1 TEXTINCLUDE +BEGIN + "..\\src\\resource.h\0" +END + +2 TEXTINCLUDE +BEGIN + "#include ""afxres.h""\r\n" + "\0" +END + +3 TEXTINCLUDE +BEGIN + "\r\n" + "\0" +END + +#endif // APSTUDIO_INVOKED + +#endif // Czech (Czech Republic) resources +///////////////////////////////////////////////////////////////////////////// + + + +#ifndef APSTUDIO_INVOKED +///////////////////////////////////////////////////////////////////////////// +// +// Generated from the TEXTINCLUDE 3 resource. +// + + +///////////////////////////////////////////////////////////////////////////// +#endif // not APSTUDIO_INVOKED + diff --git a/plugins/MessageState/res/unread.ico b/plugins/MessageState/res/unread.ico new file mode 100644 index 0000000000..b8676315a2 Binary files /dev/null and b/plugins/MessageState/res/unread.ico differ diff --git a/plugins/MessageState/res/version.rc b/plugins/MessageState/res/version.rc new file mode 100644 index 0000000000..5bfbab4754 --- /dev/null +++ b/plugins/MessageState/res/version.rc @@ -0,0 +1,38 @@ +// Microsoft Visual C++ generated resource script. +// +#ifdef APSTUDIO_INVOKED +#error this file is not editable by Microsoft Visual C++ +#endif //APSTUDIO_INVOKED + +#include "afxres.h" +#include "..\src\version.h" + +VS_VERSION_INFO VERSIONINFO + FILEVERSION __FILEVERSION_STRING + PRODUCTVERSION __FILEVERSION_STRING + FILEFLAGSMASK 0x17L +#ifdef _DEBUG + FILEFLAGS 0x1L +#else + FILEFLAGS 0x0L +#endif + FILEOS 0x4L + FILETYPE 0x0L + FILESUBTYPE 0x0L +BEGIN + BLOCK "StringFileInfo" + BEGIN + BLOCK "000004b0" + BEGIN + VALUE "FileDescription", __DESCRIPTION + VALUE "InternalName", __PLUGIN_NAME + VALUE "LegalCopyright", __COPYRIGHT + VALUE "OriginalFilename", __FILENAME + VALUE "ProductName", __PLUGIN_NAME + END + END + BLOCK "VarFileInfo" + BEGIN + VALUE "Translation", 0x0, 1200 + END +END diff --git a/plugins/MessageState/src/global.h b/plugins/MessageState/src/global.h new file mode 100644 index 0000000000..c3fac26cd7 --- /dev/null +++ b/plugins/MessageState/src/global.h @@ -0,0 +1,28 @@ +#ifndef _GLOBAL_H_ +#define _GLOBAL_H_ + +static LIST arMonitoredWindows(3, PtrKeySortT); + +static IconItem Icons[] = +{ + { LPGEN("Unreaded message icon"), "unread_icon", IDI_UNREAD }, + { LPGEN("Readed message icon"), "read_icon", IDI_READ }, + { LPGEN("Failed sending icon"), "fail_icon", IDI_FAIL }, + { LPGEN("Sending message icon"), "nosent_icon", IDI_NOSENT } +}; + +enum SRMM_ICON_TYPE +{ + ICON_HIDDEN, + ICON_READED, + ICON_UNREADED, + ICON_FAILED, + ICON_NOSENT +}; + +#define FLAG_CONTAINS(x,y) ((x & y) == y) +#define DBKEY_MESSAGE_READ_TIME "LastMsgReadTime" + +int OnModulesLoaded(WPARAM, LPARAM); + +#endif //_GLOBAL_H_ \ No newline at end of file diff --git a/plugins/MessageState/src/main.cpp b/plugins/MessageState/src/main.cpp new file mode 100644 index 0000000000..a61065abb0 --- /dev/null +++ b/plugins/MessageState/src/main.cpp @@ -0,0 +1,43 @@ +#include "stdafx.h" + +int hLangpack; +HINSTANCE g_hInst; + +PLUGININFOEX pluginInfo = +{ + sizeof(PLUGININFOEX), + __PLUGIN_NAME, + PLUGIN_MAKE_VERSION(__MAJOR_VERSION, __MINOR_VERSION, __RELEASE_NUM, __BUILD_NUM), + __DESCRIPTION, + __AUTHOR, + __AUTHOREMAIL, + __COPYRIGHT, + __AUTHORWEB, + UNICODE_AWARE, + // {31AAEF41-1411-487E-86E2-C484F4174283} + { 0x31aaef41, 0x1411, 0x487e, { 0x86, 0xe2, 0xc4, 0x84, 0xf4, 0x17, 0x42, 0x83 } } + +}; + +BOOL WINAPI DllMain(HINSTANCE hInstance, DWORD, LPVOID) +{ + g_hInst = hInstance; + return TRUE; +} + +extern "C" __declspec(dllexport) PLUGININFOEX* MirandaPluginInfoEx(DWORD) +{ + return &pluginInfo; +} + +extern "C" int __declspec(dllexport) Load(void) +{ + mir_getLP(&pluginInfo); + HookEvent(ME_SYSTEM_MODULESLOADED, OnModulesLoaded); + return 0; +} + +extern "C" int __declspec(dllexport) Unload(void) +{ + return 0; +} \ No newline at end of file diff --git a/plugins/MessageState/src/messagestate.cpp b/plugins/MessageState/src/messagestate.cpp new file mode 100644 index 0000000000..8f8d450730 --- /dev/null +++ b/plugins/MessageState/src/messagestate.cpp @@ -0,0 +1,160 @@ +#include "stdafx.h" + +LONGLONG GetLastSentMessageTime(MCONTACT hContact) +{ + for (MEVENT hDbEvent = db_event_last(hContact); hDbEvent; hDbEvent = db_event_prev(hContact, hDbEvent)) + { + DBEVENTINFO dbei = { sizeof(dbei) }; + db_event_get(hDbEvent, &dbei); + if (FLAG_CONTAINS(dbei.flags, DBEF_SENT)) + return dbei.timestamp; + } + return -1; +} + +bool CheckProtoSupport(const char *szProto) +{ + if (szProto == NULL) return false; + + DWORD caps = CallProtoService(szProto, PS_GETCAPS, PFLAGNUM_4, 0); + return FLAG_CONTAINS(caps, PF4_READNOTIFY); +} + +void SetSRMMIcon(MCONTACT hContact, SRMM_ICON_TYPE type, time_t time = 0) +{ + if (hContact && arMonitoredWindows.getIndex((HANDLE)hContact) != -1) + { + StatusIconData sid = { sizeof(sid) }; + sid.szModule = MODULENAME; + sid.dwId = 1; + sid.flags = MBF_TCHAR; + + switch (type) + { + case ICON_HIDDEN: + { + sid.flags |= MBF_HIDDEN; + break; + } + case ICON_READED: + { + sid.hIcon = Skin_GetIcon("read_icon"); + TCHAR ttime[64]; + _locale_t locale = _create_locale(LC_ALL, ""); + _tcsftime_l(ttime, SIZEOF(ttime), _T("%X %x"), localtime(&time), locale); + _free_locale(locale); + CMString tooltip(FORMAT, L"%s %s", TranslateT("Last message readed at"), ttime); + sid.tszTooltip = mir_tstrdup(tooltip.GetBuffer()); + break; + } + case ICON_UNREADED: + { + sid.hIcon = Skin_GetIcon("unread_icon"); + sid.tszTooltip = TranslateT("Last message is not readed"); + break; + } + case ICON_FAILED: + { + sid.hIcon = Skin_GetIcon("fail_icon"); + sid.tszTooltip = TranslateT("Last message send failed"); + break; + } + case ICON_NOSENT: + { + sid.hIcon = Skin_GetIcon("nosent_icon"); + sid.tszTooltip = TranslateT("Sending..."); + break; + } + default: + return; + } + + Srmm_ModifyIcon(hContact, &sid); + } +} + +int IconsUpdate(WPARAM hContact, LONGLONG readtime) +{ + if (hContact == NULL) return 1; + + LONGLONG lasttime = GetLastSentMessageTime(hContact); + if (lasttime != -1 && readtime != 0) + { + SetSRMMIcon(hContact, (readtime >= lasttime) ? ICON_READED : ICON_UNREADED, readtime); + } + else + SetSRMMIcon(hContact, ICON_HIDDEN); + return 0; +} + +int OnProtoAck(WPARAM wParam, LPARAM lParam) +{ + ACKDATA *pAck = (ACKDATA *)lParam; + if (pAck && pAck->type == ACKTYPE_MESSAGE && CheckProtoSupport(GetContactProto(pAck->hContact))) + { + if (pAck->result == ACKRESULT_SUCCESS) + { + SetSRMMIcon(pAck->hContact, ICON_UNREADED); + } + else if (pAck->result == ACKRESULT_FAILED) + { + SetSRMMIcon(pAck->hContact, ICON_FAILED); + } + } + return 0; +} + +int OnContactSettingChanged(WPARAM hContact, LPARAM lParam) +{ + DBCONTACTWRITESETTING *cws = (DBCONTACTWRITESETTING*)lParam; + if (CheckProtoSupport(GetContactProto(hContact)) && cws && cws->szSetting && !mir_strcmpi(cws->szSetting, DBKEY_MESSAGE_READ_TIME)) + IconsUpdate(hContact, cws->value.dVal); + return 0; +} + +int OnEventFilterAdd(WPARAM hContact, LPARAM lParam) +{ + DBEVENTINFO *dbei = (DBEVENTINFO *)lParam; + if (FLAG_CONTAINS(dbei->flags, DBEF_SENT) && CheckProtoSupport(dbei->szModule) && db_get_b(hContact, "Tab_SRMsg", "no_ack", 0)) + SetSRMMIcon(hContact, ICON_NOSENT); + return 0; +} + +int OnSrmmWindowEvent(WPARAM, LPARAM lParam) +{ + MessageWindowEventData *event = (MessageWindowEventData *)lParam; + if (event == NULL) + return 0; + + if (event->uType == MSG_WINDOW_EVT_OPEN) { + char *szProto = GetContactProto(event->hContact); + if (CheckProtoSupport(szProto)) + { + arMonitoredWindows.insert((HANDLE)event->hContact); + IconsUpdate(event->hContact, db_get_dw(event->hContact, szProto, DBKEY_MESSAGE_READ_TIME, 0)); + } + } + else if (event->uType == MSG_WINDOW_EVT_CLOSE) + arMonitoredWindows.remove(event->hContact); + + return 0; +} + +int OnModulesLoaded(WPARAM, LPARAM) +{ + HookEvent(ME_MSG_WINDOWEVENT, OnSrmmWindowEvent); + HookEvent(ME_DB_CONTACT_SETTINGCHANGED, OnContactSettingChanged); + HookEvent(ME_PROTO_ACK, OnProtoAck); + HookEvent(ME_DB_EVENT_FILTER_ADD, OnEventFilterAdd); + // IcoLib support + for (size_t i = 0; i < SIZEOF(Icons); i++) + Icon_Register(g_hInst, MODULENAME, &Icons[i], 1); + + StatusIconData sid = { sizeof(sid) }; + sid.szModule = MODULENAME; + sid.flags = MBF_HIDDEN; + sid.dwId = 1; + Srmm_AddIcon(&sid); + + return 0; +} \ No newline at end of file diff --git a/plugins/MessageState/src/resource.h b/plugins/MessageState/src/resource.h new file mode 100644 index 0000000000..a668a8157c --- /dev/null +++ b/plugins/MessageState/src/resource.h @@ -0,0 +1,19 @@ +//{{NO_DEPENDENCIES}} +// Microsoft Visual C++ generated include file. +// Used by ..\res\mobilestate.rc +// +#define IDI_READ 105 +#define IDI_UNREAD 106 +#define IDI_FAIL 107 +#define IDI_NOSENT 108 + +// Next default values for new objects +// +#ifdef APSTUDIO_INVOKED +#ifndef APSTUDIO_READONLY_SYMBOLS +#define _APS_NEXT_RESOURCE_VALUE 109 +#define _APS_NEXT_COMMAND_VALUE 40001 +#define _APS_NEXT_CONTROL_VALUE 1010 +#define _APS_NEXT_SYMED_VALUE 101 +#endif +#endif diff --git a/plugins/MessageState/src/stdafx.cxx b/plugins/MessageState/src/stdafx.cxx new file mode 100644 index 0000000000..6fb37564b7 --- /dev/null +++ b/plugins/MessageState/src/stdafx.cxx @@ -0,0 +1,18 @@ +/* +Copyright (C) 2012-15 Miranda NG project (http://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" \ No newline at end of file diff --git a/plugins/MessageState/src/stdafx.h b/plugins/MessageState/src/stdafx.h new file mode 100644 index 0000000000..f0a5e45916 --- /dev/null +++ b/plugins/MessageState/src/stdafx.h @@ -0,0 +1,23 @@ +#pragma once + +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "resource.h" +#include "Version.h" + +#include "global.h" + +#define MODULENAME "MessageState" + +extern HINSTANCE g_hInst; \ No newline at end of file diff --git a/plugins/MessageState/src/version.h b/plugins/MessageState/src/version.h new file mode 100644 index 0000000000..6a70c46e1c --- /dev/null +++ b/plugins/MessageState/src/version.h @@ -0,0 +1,14 @@ +#define __MAJOR_VERSION 0 +#define __MINOR_VERSION 0 +#define __RELEASE_NUM 1 +#define __BUILD_NUM 0 + +#include + +#define __PLUGIN_NAME "Message state" +#define __FILENAME "MessageState.dll" +#define __DESCRIPTION "" +#define __AUTHOR "MikalaiR" +#define __AUTHOREMAIL "" +#define __AUTHORWEB "http://miranda-ng.org/p/MessageState/" +#define __COPYRIGHT "© 2015 Miranda NG Team" -- cgit v1.2.3