summaryrefslogtreecommitdiff
path: root/plugins/MessageState
diff options
context:
space:
mode:
authorMikalaiR <nikolay.romanovich@narod.ru>2015-06-09 11:38:48 +0000
committerMikalaiR <nikolay.romanovich@narod.ru>2015-06-09 11:38:48 +0000
commit35d50950b5c60523f5a4a4959ee5e5a370ceabef (patch)
tree8fa1791c935acba3d79dc4eb25d67622d61dbe58 /plugins/MessageState
parentbc5b5ca600ad9364aa50de6afe2bf92dc63e1420 (diff)
MessageState: Initial commit.
git-svn-id: http://svn.miranda-ng.org/main/trunk@14072 1316c22d-e87f-b044-9b9b-93d7a3e3ba9c
Diffstat (limited to 'plugins/MessageState')
-rw-r--r--plugins/MessageState/MessageState.vcxproj28
-rw-r--r--plugins/MessageState/MessageState.vcxproj.filters4
-rw-r--r--plugins/MessageState/res/fail.icobin0 -> 1150 bytes
-rw-r--r--plugins/MessageState/res/nosent.icobin0 -> 1150 bytes
-rw-r--r--plugins/MessageState/res/read.icobin0 -> 1150 bytes
-rw-r--r--plugins/MessageState/res/resource.rc73
-rw-r--r--plugins/MessageState/res/unread.icobin0 -> 1150 bytes
-rw-r--r--plugins/MessageState/res/version.rc38
-rw-r--r--plugins/MessageState/src/global.h28
-rw-r--r--plugins/MessageState/src/main.cpp43
-rw-r--r--plugins/MessageState/src/messagestate.cpp160
-rw-r--r--plugins/MessageState/src/resource.h19
-rw-r--r--plugins/MessageState/src/stdafx.cxx18
-rw-r--r--plugins/MessageState/src/stdafx.h23
-rw-r--r--plugins/MessageState/src/version.h14
15 files changed, 448 insertions, 0 deletions
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 @@
+<?xml version="1.0" encoding="utf-8"?>
+<Project DefaultTargets="Build" ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+ <ItemGroup Label="ProjectConfigurations">
+ <ProjectConfiguration Include="Debug|Win32">
+ <Configuration>Debug</Configuration>
+ <Platform>Win32</Platform>
+ </ProjectConfiguration>
+ <ProjectConfiguration Include="Debug|x64">
+ <Configuration>Debug</Configuration>
+ <Platform>x64</Platform>
+ </ProjectConfiguration>
+ <ProjectConfiguration Include="Release|Win32">
+ <Configuration>Release</Configuration>
+ <Platform>Win32</Platform>
+ </ProjectConfiguration>
+ <ProjectConfiguration Include="Release|x64">
+ <Configuration>Release</Configuration>
+ <Platform>x64</Platform>
+ </ProjectConfiguration>
+ </ItemGroup>
+ <PropertyGroup Label="Globals">
+ <ProjectName>MessageState</ProjectName>
+ <ProjectGuid>{5F09C93B-463A-4BF5-A85E-6E4E916AA8F8}</ProjectGuid>
+ </PropertyGroup>
+ <ImportGroup Label="PropertySheets">
+ <Import Project="$(ProjectDir)..\..\build\vc.common\plugin.props" />
+ </ImportGroup>
+</Project> \ 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 @@
+<?xml version="1.0" encoding="utf-8"?>
+<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+ <Import Project="$(ProjectDir)..\..\build\vc.common\common.filters" />
+</Project> \ 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
--- /dev/null
+++ b/plugins/MessageState/res/fail.ico
Binary files differ
diff --git a/plugins/MessageState/res/nosent.ico b/plugins/MessageState/res/nosent.ico
new file mode 100644
index 0000000000..67587965fd
--- /dev/null
+++ b/plugins/MessageState/res/nosent.ico
Binary files differ
diff --git a/plugins/MessageState/res/read.ico b/plugins/MessageState/res/read.ico
new file mode 100644
index 0000000000..60d0d2f7ad
--- /dev/null
+++ b/plugins/MessageState/res/read.ico
Binary files 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
--- /dev/null
+++ b/plugins/MessageState/res/unread.ico
Binary files 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<void> 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 <http://www.gnu.org/licenses/>.
+*/
+
+#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 <windows.h>
+#include <time.h>
+#include <locale.h>
+
+#include <newpluginapi.h>
+#include <m_database.h>
+#include <m_protocols.h>
+#include <m_protosvc.h>
+#include <m_langpack.h>
+#include <m_icolib.h>
+#include <m_extraicons.h>
+#include <m_message.h>
+#include <m_timezones.h>
+#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 <stdver.h>
+
+#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"