summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
Diffstat (limited to '3rdParty')
-rw-r--r--3rdParty/Snarl/SnarlInterface.cpp959
-rw-r--r--3rdParty/Snarl/SnarlInterface.h412
2 files changed, 567 insertions, 804 deletions
diff --git a/3rdParty/Snarl/SnarlInterface.cpp b/3rdParty/Snarl/SnarlInterface.cpp
index b780140..0ae0b37 100644
--- a/3rdParty/Snarl/SnarlInterface.cpp
+++ b/3rdParty/Snarl/SnarlInterface.cpp
@@ -1,484 +1,412 @@
-// About:
-// Snarl C++ interface implementation
-// To understand what the different functions do and what they return, please
-// have a look at the API on http://www.fullphat.net/dev/api.htm.
-// Also have a look at mSnarl_i.bas found in the CVS/SVN repository for Snarl.
-//
-// The functions in SnarlInterface both have ANSI(UTF8) and UNICODE versions.
-// If the LPCWSTR (unicode) version of the functions are called, the strings
-// are converted to UTF8 by SnarlInterface before sent to Snarl. So using the
-// ANSI/UTF8/LPCSTR versions of the functions are faster!
-//
-//
-// Difference to VB implementation:
-// Please note that string functions return NULL when they fail and not an
-// empty string. So check for NULL...
-// Function names doesn't have the pre "sn".
-//
-//
-// Authors:
-// Written and maintained by Toke Noer Nøttrup
-// Original C++ version by "Whitman"
-//
-// License etc. :
-// Feel free to use this code and class as you see fit.
-// If you improve the code, it would be nice of you to take contact to the
-// authors, so all can get the benifit.
-//
-// There is no guarantee that the code is correct or functional.
-// USE AT YOUR OWN RISK
-//-----------------------------------------------------------------------------
-
-// History
-// 2008/12/31 : Implemented V39 API
-// : Moved SnarlInterface into new Snarl namespace and moved enums etc. out of class
-// : Added WCHAR overloads for all functions
-// 2008/08/27 : Fixed return value of IsMessageVisible and HideMessage (returns false on failure now)
-// : Fixed critical error in the new overloaded UpdateMessage() function
-// 2008/08/27 : x64 compiler fix
-// 2008/08/24 : Renamed all functions to not have prepended "sn".
-// : Memory allocation functions added. (Use FreeString to free strings returned by Snarl)
-// : Added m_nLastMessageId to the class. (Use GetLastMessageId() to get it)
-// : Overloaded a few functions, so one don't have include the message id. (UpdateMessage f.i.)
-
-// 2008/06/20 : Fixed snShowMessageEx so it actually sends the extended version - oops
-// : Fixed compiler warning C4800: forcing value to bool 'true' or 'false' (performance warning)
-
-// 2008/05/19 : uSend and uSendEx would always set return value to M_OK on successfull call
-// 2008/04/14 : Updated to follow (what should be) the final Snarl 2.0 API
-// 2008/03/28 : Few fixes for Snarl 2.0
-// 2007/05/23 : snGetGlobalMsg & snGetSnarlWindow made static
-// 2007/03/25 : 1.6 RC1 fixup
-// 2007/03/04 : Added - snGetAppPath, snGetIconsPath, snGetVersionEx,
-// snSetTimeout, uSendEx
-
+/// <summary>
+/// Snarl C++ interface implementation
+///
+/// Written and maintained by Toke Noer Nøttrup (toke@noer.it)
+///
+/// Please note the following changes compared to the VB6 (official API) dokumentation:
+/// - Function names doesn't have the prefix "sn". Naming of constants and variables are
+/// generally changed to follow Microsoft C# standard. This naming convention is kept for
+/// the C++ version, to keep them alike.
+/// - Grouped variables like SNARL_LAUNCHED, SNARL_QUIT is enums in SnarlEnums namespace.
+/// - Message events like SNARL_NOTIFICATION_CLICKED, is found in SnarlEnums::MessageEvent.
+/// - Please note that string functions return NULL when they fail and not an empty string.
+/// - Some functions in the VB API takes an appToken as first parameter. This token is a
+/// member variable in C++ version, so it is omitted from the functions.
+/// (Always call RegisterApp as first function!)
+/// - Functions manipulating messages (Update, Hide etc.) still takes a message token as
+/// parameter, but you can get the last message token calling GetLastMsgToken();
+/// Example: snarl.Hide(snarl.GetLastMsgToken());
+///
+/// The functions in SnarlInterface both have ANSI(UTF8) and UNICODE versions.
+/// If the LPCWSTR (unicode) version of the functions are called, the strings
+/// are converted to UTF8 by SnarlInterface before sent to Snarl. So using the
+/// ANSI/UTF8/LPCSTR versions of the functions are faster!
+///
+/// Funtions special to C++ V41 API compared to VB version:
+/// GetLastMsgToken()
+/// GetAppPath()
+/// GetIconsPath()
+/// </summary>
+///----------------------------------------------------------------------------
+/// <example>
+/// SnarlInterface snarl;
+/// snarl.RegisterApp(_T("CppTest"), _T("C++ test app"), NULL);
+/// snarl.AddClass(_T("Class1"), _T("Class 1"));
+/// snarl.EZNotify(_T("Class1"), _T("C++ example 1"), _T("Some text"), 10);
+/// snarl.UnregisterApp();
+///
+/// Please see the SimpleTest.cpp and SnarlV41Test.cpp for more example code.
+/// </example>
+///----------------------------------------------------------------------------
+/// <VersionHistory>
+/// 2010-08-13 : First release of V41 Snarl API implementation
+/// </VersionHistory>
+
+#define _CRT_SECURE_NO_WARNINGS
#include "SnarlInterface.h"
-using namespace Snarl;
+namespace Snarl {
+namespace V41 {
//-----------------------------------------------------------------------------
// Constructor/Destructor
//-----------------------------------------------------------------------------
SnarlInterface::SnarlInterface()
-: m_hwndFrom(NULL), m_nLastMessageId(0)
+ : appToken(0), lastMsgToken(0), localError(SnarlEnums::Success)
{
-
}
SnarlInterface::~SnarlInterface()
{
-
}
+// ----------------------------------------------------------------------------
-//-----------------------------------------------------------------------------
-// snShowMessage()
-
-/// Displays a message with Title and Text. Timeout controls how long the
-/// message is displayed for (in seconds) (omitting this value means the message
-/// is displayed indefinately). IconPath specifies the location of a PNG image
-/// which will be displayed alongside the message text.
-/// <returns>Message Id on success or M_RESULT on failure</returns>
-
-LONG32 SnarlInterface::ShowMessage(LPCSTR szTitle, LPCSTR szText, LONG32 timeout, LPCSTR szIconPath, HWND hWndReply, WPARAM uReplyMsg)
+LONG32 SnarlInterface::RegisterApp(LPCSTR signature, LPCSTR title, LPCSTR icon, HWND hWndReply /* = NULL */, LONG32 msgReply /* = 0 */, SnarlEnums::AppFlags flags /* = SnarlEnums::AppDefault */)
{
- SNARLSTRUCT ss;
- ZeroMemory((void*)&ss, sizeof(ss));
-
- ss.Cmd = SNARL_SHOW;
- StringCbCopyA((LPSTR)&ss.Title, SNARL_STRING_LENGTH, szTitle);
- StringCbCopyA((LPSTR)&ss.Text, SNARL_STRING_LENGTH, szText);
- StringCbCopyA((LPSTR)&ss.Icon, SNARL_STRING_LENGTH, szIconPath);
- ss.Timeout = timeout;
+ SnarlMessage msg;
+ msg.Command = SnarlEnums::RegisterApp;
+ msg.Token = 0;
+ PackData(msg.PacketData,
+ "id::%s#?title::%s#?icon::%s#?hwnd::%d#?umsg::%d#?flags::%d",
+ signature, title, icon, hWndReply, msgReply, flags);
- ss.LngData2 = reinterpret_cast<LONG32>(hWndReply);
- ss.Id = static_cast<LONG32>(uReplyMsg);
+ appToken = Send(msg);
+ lastMsgToken = 0;
- m_nLastMessageId = Send(ss);
- return m_nLastMessageId;
+ return appToken;
}
-LONG32 SnarlInterface::ShowMessage(LPCWSTR szTitle, LPCWSTR szText, LONG32 timeout, LPCWSTR szIconPath, HWND hWndReply, WPARAM uReplyMsg)
+LONG32 SnarlInterface::RegisterApp(LPCWSTR signature, LPCWSTR title, LPCWSTR icon, HWND hWndReply /* = NULL */, LONG32 msgReply /* = 0 */, SnarlEnums::AppFlags flags /* = SnarlEnums::AppDefault */)
{
- LPSTR szUTF8Title = WideToUTF8(szTitle);
- LPSTR szUTF8Text = WideToUTF8(szText);
- LPSTR szUFT8IconPath = WideToUTF8(szIconPath);
+ LPCSTR szParam1 = WideToUTF8(signature);
+ LPCSTR szParam2 = WideToUTF8(title);
+ LPCSTR szParam3 = WideToUTF8(icon);
- LONG32 result = ShowMessage(szUTF8Title, szUTF8Text, timeout, szUFT8IconPath, hWndReply, uReplyMsg);
-
- delete [] szUTF8Title;
- delete [] szUTF8Text;
- delete [] szUFT8IconPath;
+ LONG32 result = RegisterApp(szParam1, szParam2, szParam3, hWndReply, msgReply, flags);
+ delete [] szParam1;
+ delete [] szParam2;
+ delete [] szParam3;
+
return result;
}
-
-//-----------------------------------------------------------------------------
-// snShowMessageEx()
-
-/// Displays a notification. This function is identical to snShowMessage()
-/// except that Class specifies an alert previously registered with
-/// snRegisterAlert() and SoundFile can optionally specify a WAV sound to play
-/// when the notification is displayed on screen.
-/// <returns>Message Id on success or M_RESULT on failure</returns>
-
-LONG32 SnarlInterface::ShowMessageEx(LPCSTR szClass, LPCSTR szTitle, LPCSTR szText, LONG32 timeout, LPCSTR szIconPath, HWND hWndReply, WPARAM uReplyMsg, LPCSTR szSoundFile)
+LONG32 SnarlInterface::UnregisterApp()
{
- SNARLSTRUCTEX ssex;
- ZeroMemory((void*)&ssex, sizeof(ssex));
-
- ssex.Cmd = SNARL_EX_SHOW;
- ssex.Timeout = timeout;
- ssex.LngData2 = reinterpret_cast<LONG32>(hWndReply);
- ssex.Id = static_cast<LONG32>(uReplyMsg);
+ SnarlMessage msg;
+ msg.Command = SnarlEnums::UnregisterApp;
+ msg.Token = appToken;
+ PackData(msg.PacketData, NULL);
- StringCbCopyA((LPSTR)&ssex.Class, SNARL_STRING_LENGTH, szClass);
- StringCbCopyA((LPSTR)&ssex.Title, SNARL_STRING_LENGTH, szTitle);
- StringCbCopyA((LPSTR)&ssex.Text, SNARL_STRING_LENGTH, szText);
- StringCbCopyA((LPSTR)&ssex.Icon, SNARL_STRING_LENGTH, szIconPath);
- StringCbCopyA((LPSTR)&ssex.Extra, SNARL_STRING_LENGTH, szSoundFile);
+ appToken = 0;
+ lastMsgToken = 0;
- m_nLastMessageId = Send(ssex);
- return m_nLastMessageId;
+ return Send(msg);
}
-LONG32 SnarlInterface::ShowMessageEx(LPCWSTR szClass, LPCWSTR szTitle, LPCWSTR szText, LONG32 timeout, LPCWSTR szIconPath, HWND hWndReply, WPARAM uReplyMsg, LPCWSTR szSoundFile)
+LONG32 SnarlInterface::UpdateApp(LPCSTR title /* = NULL */, LPCSTR icon /* = NULL */)
{
- LPSTR szUTF8Class = WideToUTF8(szClass);
- LPSTR szUTF8Title = WideToUTF8(szTitle);
- LPSTR szUTF8Text = WideToUTF8(szText);
- LPSTR szUFT8IconPath = WideToUTF8(szIconPath);
- LPSTR szUFT8SoundFile = WideToUTF8(szSoundFile);
-
- LONG32 result = ShowMessageEx(szUTF8Class, szUTF8Title, szUTF8Text, timeout, szUFT8IconPath, hWndReply, uReplyMsg, szUFT8SoundFile);
+ if (title == NULL && icon == NULL)
+ return 0;
+
+ SnarlMessage msg;
+ msg.Command = SnarlEnums::UpdateApp;
+ msg.Token = appToken;
- delete [] szUTF8Class;
- delete [] szUTF8Title;
- delete [] szUTF8Text;
- delete [] szUFT8IconPath;
- delete [] szUFT8SoundFile;
+ // TODO: Uckly code ahead
+ if (title != NULL && title[0] != 0 && icon != NULL && icon[0] != 0)
+ PackData(msg.PacketData, "title::%s#?icon::%s", title, icon);
+ else if (title != NULL && title[0] != 0)
+ PackData(msg.PacketData, "title::%s", title);
+ else if (icon != NULL && icon[0] != 0)
+ PackData(msg.PacketData, "icon::%s", icon);
- return result;
+ return Send(msg);
}
-//-----------------------------------------------------------------------------
-// snHideMessage()
-
-/// Hides the notification specified by Id. Id is the value returned by
-/// snShowMessage() or snShowMessageEx() when the notification was initially
-/// created. This function returns True if the notification was successfully
-/// hidden or False otherwise (for example, the notification may no longer exist).
-
-BOOL SnarlInterface::HideMessage(LONG32 Id)
+LONG32 SnarlInterface::UpdateApp(LPCWSTR title /* = NULL */, LPCWSTR icon /* = NULL */)
{
- SNARLSTRUCT ss;
- ss.Cmd = SNARL_HIDE;
- ss.Id = Id;
+ LPCSTR szParam1 = WideToUTF8(title);
+ LPCSTR szParam2 = WideToUTF8(icon);
+
+ LONG32 result = UpdateApp(szParam1, szParam2);
+
+ delete [] szParam1;
+ delete [] szParam2;
- LONG32 n = Send(ss);
- return (n == -1 || n == 1) ? TRUE : FALSE;
+ return result;
}
-BOOL SnarlInterface::HideMessage()
+LONG32 SnarlInterface::AddClass(LPCSTR className, LPCSTR description, bool enabled /* = true */)
{
- return HideMessage(m_nLastMessageId);
-}
-
-//-----------------------------------------------------------------------------
-// snIsMessageVisible()
-
-/// Returns True if the notification specified by Id is still visible, or
-/// False if not. Id is the value returned by snShowMessage() or
-/// snShowMessageEx() when the notification was initially created.
+ SnarlMessage msg;
+ msg.Command = SnarlEnums::AddClass;
+ msg.Token = appToken;
+ PackData(msg.PacketData, "id::%s#?name::%s#?enabled::%d", className, description, (enabled ? 1 : 0));
-BOOL SnarlInterface::IsMessageVisible(LONG32 Id)
-{
- SNARLSTRUCT ss;
- ss.Cmd = SNARL_IS_VISIBLE;
- ss.Id = Id;
-
- // We are getting -1 when true, checking for 1 just in case. We don't want to return true for the other M_RESULT returns
- LONG32 n = Send(ss);
- return (n == -1 || n == 1) ? TRUE : FALSE;
+ return Send(msg);
}
-BOOL SnarlInterface::IsMessageVisible()
+LONG32 SnarlInterface::AddClass(LPCWSTR className, LPCWSTR description, bool enabled /* = true */)
{
- if (m_nLastMessageId == 0)
- return FALSE;
+ LPCSTR szParam1 = WideToUTF8(className);
+ LPCSTR szParam2 = WideToUTF8(description);
+
+ LONG32 result = AddClass(szParam1, szParam2, enabled);
+
+ delete [] szParam1;
+ delete [] szParam2;
- return IsMessageVisible(m_nLastMessageId);
+ return result;
}
-//-----------------------------------------------------------------------------
-// snUpdateMessage()
-
-/// Changes the title and text in the message specified by Id to the values
-/// specified by Title and Text respectively. Id is the value returned by
-/// snShowMessage() or snShowMessageEx() when the notification was originally
-/// created. To change the timeout parameter of a notification, use snSetTimeout()
-
-M_RESULT SnarlInterface::UpdateMessage(LONG32 id, LPCSTR szTitle, LPCSTR szText, LPCSTR szIconPath)
+LONG32 SnarlInterface::RemoveClass(LPCSTR className, bool forgetSettings /* = false */)
{
- SNARLSTRUCT ss;
- ZeroMemory((void*)&ss, sizeof(ss));
-
- ss.Cmd = SNARL_UPDATE;
- ss.Id = id;
-
- StringCbCopyA((LPSTR)&ss.Title, SNARL_STRING_LENGTH, szTitle);
- StringCbCopyA((LPSTR)&ss.Text, SNARL_STRING_LENGTH, szText);
- StringCbCopyA((LPSTR)&ss.Icon, SNARL_STRING_LENGTH, szIconPath);
+ SnarlMessage msg;
+ msg.Command = SnarlEnums::RemoveClass;
+ msg.Token = appToken;
+ PackData(msg.PacketData, "id::%s#?forget::%d", className, (forgetSettings ? 1 : 0));
- return static_cast<M_RESULT>(Send(ss));
+ return Send(msg);
}
-M_RESULT SnarlInterface::UpdateMessage(LONG32 id, LPCWSTR szTitle, LPCWSTR szText, LPCWSTR szIconPath)
+LONG32 SnarlInterface::RemoveClass(LPCWSTR className, bool forgetSettings /* = false */)
{
- LPSTR szParam1 = WideToUTF8(szTitle);
- LPSTR szParam2 = WideToUTF8(szText);
- LPSTR szParam3 = WideToUTF8(szIconPath);
+ LPCSTR szParam1 = WideToUTF8(className);
- M_RESULT result = UpdateMessage(id, szParam1, szParam2, szParam3);
+ LONG32 result = RemoveClass(szParam1, forgetSettings);
delete [] szParam1;
- delete [] szParam2;
- delete [] szParam3;
-
+
return result;
}
-M_RESULT SnarlInterface::UpdateMessage(LPCSTR szTitle, LPCSTR szText, LPCSTR szIconPath)
+LONG32 SnarlInterface::RemoveAllClasses(bool forgetSettings /* = false */)
{
- return UpdateMessage(m_nLastMessageId, szTitle, szText, szIconPath);
-}
+ SnarlMessage msg;
+ msg.Command = SnarlEnums::RemoveClass;
+ msg.Token = appToken;
+ PackData(msg.PacketData, "all::1#?forget::%d", (forgetSettings ? 1 : 0));
-M_RESULT SnarlInterface::UpdateMessage(LPCWSTR szTitle, LPCWSTR szText, LPCWSTR szIconPath)
-{
- return UpdateMessage(m_nLastMessageId, szTitle, szText, szIconPath);
+ return Send(msg);
}
-//-----------------------------------------------------------------------------
-// snRegisterConfig
-
-/// Registers an application's configuration interface with Snarl.
-/// AppName is the text that's displayed in the Applications list so it should
-/// be people friendly ("My cool app" rather than "my_cool_app").
-
-M_RESULT SnarlInterface::RegisterConfig(HWND hWnd, LPCSTR szAppName, LONG32 replyMsg)
+LONG32 SnarlInterface::EZNotify(LPCSTR className, LPCSTR title, LPCSTR text, LONG32 timeout /* = -1 */, LPCSTR icon /* = NULL */, LONG32 priority /* = 0 */, LPCSTR acknowledge /* = NULL */, LPCSTR value /* = NULL */)
{
- return RegisterConfig2(hWnd, szAppName, replyMsg, "");
-}
+ SnarlMessage msg;
+ msg.Command = SnarlEnums::Notify;
+ msg.Token = appToken;
+ PackData(msg.PacketData,
+ "id::%s#?title::%s#?text::%s#?timeout::%d#?icon::%s#?priority::%d#?ack::%s#?value::%s",
+ className, title, text, timeout, (icon ? icon : ""), priority, (acknowledge ? acknowledge : ""), (value ? value : ""));
-M_RESULT SnarlInterface::RegisterConfig(HWND hWnd, LPCWSTR szAppName, LONG32 replyMsg)
-{
- return RegisterConfig2(hWnd, szAppName, replyMsg, L"");
+ lastMsgToken = Send(msg);
+ return lastMsgToken;
}
-//-----------------------------------------------------------------------------
-// snRegisterConfig2
-
-/// Registers an application's configuration interface with Snarl.
-/// This function is identical to snRegisterConfig() except that Icon can be
-/// used to specify a PNG image which will be displayed against the
-/// application's entry in Snarl's Preferences panel.
-
-M_RESULT SnarlInterface::RegisterConfig2(HWND hWnd, LPCSTR szAppName, LONG32 replyMsg, LPCSTR szIcon)
+LONG32 SnarlInterface::EZNotify(LPCWSTR className, LPCWSTR title, LPCWSTR text, LONG32 timeout /* = -1 */, LPCWSTR icon /* = NULL */, LONG32 priority /* = 0 */, LPCWSTR acknowledge /* = NULL */, LPCWSTR value /* = NULL */)
{
- if (!szAppName || !szIcon)
- return M_BAD_POINTER;
-
- SNARLSTRUCT ss;
+ LPCSTR szParam1 = WideToUTF8(className);
+ LPCSTR szParam2 = WideToUTF8(title);
+ LPCSTR szParam3 = WideToUTF8(text);
+ LPCSTR szParam4 = WideToUTF8(icon);
+ LPCSTR szParam5 = WideToUTF8(acknowledge);
+ LPCSTR szParam6 = WideToUTF8(value);
+
+ LONG32 result = EZNotify(szParam1, szParam2, szParam3, timeout, szParam4, priority, szParam5, szParam6);
+
+ delete [] szParam1; delete [] szParam2; delete [] szParam3;
+ delete [] szParam4; delete [] szParam5; delete [] szParam6;
- m_hwndFrom = hWnd;
+ return result;
+}
- ss.Cmd = SNARL_REGISTER_CONFIG_WINDOW_2;
- ss.LngData2 = reinterpret_cast<LONG32>(hWnd);
- ss.Id = replyMsg;
- StringCbCopyA((LPSTR)&ss.Title, SNARL_STRING_LENGTH, szAppName);
- StringCbCopyA((LPSTR)&ss.Icon, SNARL_STRING_LENGTH, szIcon);
+LONG32 SnarlInterface::Notify(LPCSTR className, LPCSTR packetData)
+{
+ SnarlMessage msg;
+ msg.Command = SnarlEnums::Notify;
+ msg.Token = appToken;
+ PackData(msg.PacketData, "id::%s#?%s", className, packetData);
- return static_cast<M_RESULT>(Send(ss));
+ lastMsgToken = Send(msg);
+ return lastMsgToken;
}
-M_RESULT SnarlInterface::RegisterConfig2(HWND hWnd, LPCWSTR szAppName, LONG32 replyMsg, LPCWSTR szIcon)
+LONG32 SnarlInterface::Notify(LPCWSTR className, LPCWSTR packetData)
{
- LPSTR szParam1 = WideToUTF8(szAppName);
- LPSTR szParam2 = WideToUTF8(szIcon);
-
- M_RESULT result = RegisterConfig2(hWnd, szParam1, replyMsg, szParam2);
+ LPCSTR szParam1 = WideToUTF8(className);
+ LPCSTR szParam2 = WideToUTF8(packetData);
+
+ LONG32 result = Notify(szParam1, szParam2);
- delete [] szParam1;
- delete [] szParam2;
+ delete [] szParam1; delete [] szParam2;
return result;
}
-
-//-----------------------------------------------------------------------------
-// snRevokeConfig
-
-/// Removes the application previously registered using snRegisterConfig() or
-/// snRegisterConfig2(). hWnd should be the same as that used during registration.
-
-M_RESULT SnarlInterface::RevokeConfig(HWND hWnd)
+LONG32 SnarlInterface::EZUpdate(LONG32 msgToken, LPCSTR title /* = NULL */, LPCSTR text /* = NULL */, LONG32 timeout /* = -1 */, LPCSTR icon /* = NULL */)
{
- SNARLSTRUCT ss;
+ SnarlMessage msg;
+ msg.Command = SnarlEnums::UpdateNotification;
+ msg.Token = msgToken;
- m_hwndFrom = NULL;
+ // Create packed data
+ errno_t err = 0;
+ ZeroMemory(msg.PacketData, sizeof(msg.PacketData));
+ char* pData = reinterpret_cast<char*>(msg.PacketData);
- ss.Cmd = SNARL_REVOKE_CONFIG_WINDOW;
- ss.LngData2 = reinterpret_cast<LONG32>(hWnd);
+ if (title != NULL) {
+ err |= strncat_s(pData, SnarlPacketDataSize, (pData[0] != NULL) ? "#?title::" : "title::", _TRUNCATE); //StringCbCat(tmp, SnarlPacketDataSize, "title::%s");
+ err |= strncat_s(pData, SnarlPacketDataSize, title, _TRUNCATE);
+ }
+ if (text != NULL) {
+ err |= strncat_s(pData, SnarlPacketDataSize, (pData[0] != NULL) ? "#?text::" : "text::", _TRUNCATE);
+ err |= strncat_s(pData, SnarlPacketDataSize, text, _TRUNCATE);
+ }
+ if (icon != NULL) {
+ err |= strncat_s(pData, SnarlPacketDataSize, (pData[0] != NULL) ? "#?icon::" : "icon::", _TRUNCATE);
+ err |= strncat_s(pData, SnarlPacketDataSize, icon, _TRUNCATE);
+ }
+ if (timeout != -1) {
+ char tmp[32];
+ _itoa_s(timeout, tmp, 10);
+
+ err |= strncat_s(pData, SnarlPacketDataSize, (pData[0] != NULL) ? "#?timeout::" : "timeout::", _TRUNCATE);
+ err |= strncat_s(pData, SnarlPacketDataSize, tmp, _TRUNCATE);
+ }
+
+ // Check for strcat errors and exit on error
+ if (err != 0) {
+ localError = SnarlEnums::ErrorFailed;
+ return 0;
+ }
- return static_cast<M_RESULT>(Send(ss));
+ return Send(msg);
}
-
-//-----------------------------------------------------------------------------
-// snGetVersion()
-
-/// Checks if Snarl is currently running and, if it is, retrieves the major and
-/// minor release version numbers in Major and Minor respectively.
-/// Returns True if Snarl is running, False otherwise.
-
-BOOL SnarlInterface::GetVersion(WORD* Major, WORD* Minor)
+LONG32 SnarlInterface::EZUpdate(LONG32 msgToken, LPCWSTR title /* = NULL */, LPCWSTR text /* = NULL */, LONG32 timeout /* = -1 */, LPCWSTR icon /* = NULL */)
{
- SNARLSTRUCT ss;
- ss.Cmd = SNARL_GET_VERSION;
- LONG32 versionInfo = Send(ss);
- if (versionInfo > 0 && versionInfo != M_FAILED && versionInfo != M_TIMED_OUT) {
- *Major = HIWORD(versionInfo);
- *Minor = LOWORD(versionInfo);
- return TRUE;
- }
- return FALSE;
-}
+ LPCSTR szParam1 = WideToUTF8(title);
+ LPCSTR szParam2 = WideToUTF8(text);
+ LPCSTR szParam3 = WideToUTF8(icon);
+ LONG32 result = EZUpdate(msgToken, szParam1, szParam2, timeout, szParam3);
+
+ delete [] szParam1; delete [] szParam2; delete [] szParam3;
+
+ return result;
+}
-//-----------------------------------------------------------------------------
-// snGetVersionEx
+LONG32 SnarlInterface::Update(LONG32 msgToken, LPCSTR packetData)
+{
+ SnarlMessage msg;
+ msg.Command = SnarlEnums::UpdateNotification;
+ msg.Token = msgToken;
+ PackData(msg.PacketData, packetData);
-/// Returns the Snarl system version number. This is an integer value which
-/// represents the system build number and can be used to identify the specific
-/// version of Snarl running
+ return Send(msg);
+}
-LONG32 SnarlInterface::GetVersionEx()
+LONG32 SnarlInterface::Update(LONG32 msgToken, LPCWSTR packetData)
{
- SNARLSTRUCT ss;
- ss.Cmd = SNARL_GET_VERSION_EX;
- return Send(ss);
-}
+ LPCSTR szParam1 = WideToUTF8(packetData);
+ LONG32 result = Update(msgToken, szParam1);
+
+ delete [] szParam1;
+
+ return result;
+}
-//-----------------------------------------------------------------------------
-// snSetTimeout()
+LONG32 SnarlInterface::Hide(LONG32 msgToken)
+{
+ SnarlMessage msg;
+ msg.Command = SnarlEnums::HideNotification;
+ msg.Token = msgToken;
+ PackData(msg.PacketData, NULL);
-/// Sets the timeout of existing notification Id to Timeout seconds. Id is the
-/// value returned by snShowMessage() or snShowMessageEx() when the notification
-/// was first created.
+ return Send(msg);
+}
-M_RESULT SnarlInterface::SetTimeout(LONG32 Id, LONG32 Timeout)
+LONG32 SnarlInterface::IsVisible(LONG32 msgToken)
{
- SNARLSTRUCT ss;
- ss.Cmd = SNARL_SET_TIMEOUT;
- ss.Id = Id;
- ss.LngData2 = Timeout;
+ SnarlMessage msg;
+ msg.Command = SnarlEnums::IsNotificationVisible;
+ msg.Token = msgToken;
+ PackData(msg.PacketData, NULL);
- return static_cast<M_RESULT>(Send(ss));
+ return Send(msg);
}
-M_RESULT SnarlInterface::SetTimeout(LONG32 Timeout)
+SnarlEnums::SnarlStatus SnarlInterface::GetLastError()
{
- return SetTimeout(m_nLastMessageId, Timeout);
+ return localError;
}
-//-----------------------------------------------------------------------------
-// snRegisterAlert()
-
-/// Registers an alert of Class for application AppName which must have previously
-/// been registered with either snRegisterConfig() or snRegisterConfig2().
-
-M_RESULT SnarlInterface::RegisterAlert(LPCSTR szAppName, LPCSTR szClass)
+// static
+BOOL SnarlInterface::IsSnarlRunning()
{
- SNARLSTRUCT ss;
- ss.Cmd = SNARL_REGISTER_ALERT;
- StringCbCopyA((LPSTR)&ss.Title, SNARL_STRING_LENGTH, szAppName);
- StringCbCopyA((LPSTR)&ss.Text, SNARL_STRING_LENGTH, szClass);
-
- return static_cast<M_RESULT>(Send(ss));
+ return IsWindow(GetSnarlWindow());
}
-M_RESULT SnarlInterface::RegisterAlert(LPCWSTR szAppName, LPCWSTR szClass)
+LONG32 SnarlInterface::GetVersion()
{
- LPSTR szParam1 = WideToUTF8(szAppName);
- LPSTR szParam2 = WideToUTF8(szClass);
-
- M_RESULT result = RegisterAlert(szParam1, szParam2);
-
- delete [] szParam1;
- delete [] szParam2;
-
- return result;
-}
+ localError = SnarlEnums::Success;
-//-----------------------------------------------------------------------------
-// snGetGlobalMsg()
+ HWND hWnd = GetSnarlWindow();
+ if (!IsWindow(hWnd))
+ {
+ localError = SnarlEnums::ErrorNotRunning;
+ return 0;
+ }
-/// Returns the atom that corresponds to the "SnarlGlobalEvent" registered
-/// Windows message. This message is sent by Snarl when it is first starts and
-/// when it shuts down.
+ HANDLE hProp = GetProp(hWnd, _T("_version"));
+ return reinterpret_cast<int>(hProp);
+}
-LONG32 SnarlInterface::GetGlobalMsg()
+// static
+UINT SnarlInterface::Broadcast()
{
- return RegisterWindowMessage(SNARL_GLOBAL_MSG);
+ return RegisterWindowMessage(SnarlGlobalMsg);
}
+// static
+UINT SnarlInterface::AppMsg()
+{
+ return RegisterWindowMessage(SnarlAppMsg);
+}
-//-----------------------------------------------------------------------------
-// snGetSnarlWindow
-
+// static
HWND SnarlInterface::GetSnarlWindow()
{
- return FindWindow(NULL, _T("Snarl"));
+ return FindWindow(SnarlWindowClass, SnarlWindowTitle);;
}
-
-//-----------------------------------------------------------------------------
-// snGetAppPath()
-
-/// Returns a pointer to the path.
-/// ** Remember to call FreeString
-
LPCTSTR SnarlInterface::GetAppPath()
{
HWND hWnd = GetSnarlWindow();
if (hWnd)
{
- HWND hWndPath = FindWindowEx(hWnd, 0, _T("static"), NULL);
+ HWND hWndPath = FindWindowEx(hWnd, NULL, _T("static"), NULL);
if (hWndPath)
{
TCHAR strTmp[MAX_PATH] = {0};
- int nReturn = GetWindowText(hWndPath, strTmp, MAX_PATH);
+ int nReturn = GetWindowText(hWndPath, strTmp, MAX_PATH-1);
if (nReturn > 0) {
TCHAR* strReturn = AllocateString(nReturn + 1);
- StringCchCopy(strReturn, nReturn + 1, strTmp);
+ _tcsncpy(strReturn, strTmp, nReturn + 1);
+ strReturn[nReturn] = 0;
return strReturn;
}
}
}
+
return NULL;
}
-
-//-----------------------------------------------------------------------------
-// snGetIconsPath()
-
-/// Returns a pointer to the iconpath.
-/// ** Remember to call FreeString when done with the string
-
LPCTSTR SnarlInterface::GetIconsPath()
{
TCHAR* szIconPath = NULL;
@@ -487,13 +415,14 @@ LPCTSTR SnarlInterface::GetIconsPath()
return NULL;
size_t nLen = 0;
- if (SUCCEEDED(StringCbLength(szPath, MAX_PATH, &nLen)))
+ // TODO: _tcsnlen MAX_PATH
+ if (nLen = _tcsnlen(szPath, MAX_PATH))
{
nLen += 10 + 1; // etc\\icons\\ + NULL
szIconPath = AllocateString(nLen);
- StringCbCopy(szIconPath, nLen * sizeof(TCHAR), szPath);
- StringCbCat(szIconPath, nLen * sizeof(TCHAR), _T("etc\\icons\\"));
+ _tcsncpy(szIconPath, szPath, nLen);
+ _tcsncat(szIconPath, _T("etc\\icons\\"), nLen);
}
FreeString(szPath);
@@ -501,312 +430,88 @@ LPCTSTR SnarlInterface::GetIconsPath()
return szIconPath;
}
-
-//-----------------------------------------------------------------------------
-// snSetAsSnarlApp()
-
-/// Identifies an application as a Snarl App. (V39)
-
-void SnarlInterface::SetAsSnarlApp(HWND hWndOwner, SNARL_APP_FLAGS Flags)
+LONG32 SnarlInterface::GetLastMsgToken() const
{
- if (IsWindow(hWndOwner)) {
- SetProp(hWndOwner, _T("snarl_app"), reinterpret_cast<HANDLE>(1));
- SetProp(hWndOwner, _T("snarl_app_flags"), reinterpret_cast<HANDLE>(Flags));
- }
+ return lastMsgToken;
}
//-----------------------------------------------------------------------------
-// snGetAppMsg()
-
-/// Returns the global Snarl Application message (V39)
-
-LONG32 SnarlInterface::GetAppMsg()
-{
- return RegisterWindowMessage(SNARL_APP_MSG);
-}
-
-
-//-----------------------------------------------------------------------------
-// snRegisterApp()
-
-/// Registers an application with Snarl (V39)
-
-M_RESULT SnarlInterface::RegisterApp(LPCSTR Application, LPCSTR SmallIcon, LPCSTR LargeIcon, HWND hWnd, LONG32 ReplyMsg)
-{
- m_hwndFrom = hWnd;
-
- SNARLSTRUCT ss;
- ss.Cmd = SNARL_REGISTER_APP;
-
- StringCbCopyA((LPSTR)&ss.Title, SNARL_STRING_LENGTH, Application);
- StringCbCopyA((LPSTR)&ss.Icon, SNARL_STRING_LENGTH, SmallIcon);
- StringCbCopyA((LPSTR)&ss.Text, SNARL_STRING_LENGTH, LargeIcon);
-
- ss.LngData2 = reinterpret_cast<LONG32>(hWnd);
- ss.Id = ReplyMsg;
- ss.Timeout = GetCurrentProcessId();
-
- return static_cast<M_RESULT>(Send(ss));
-}
-
-M_RESULT SnarlInterface::RegisterApp(LPCWSTR Application, LPCWSTR SmallIcon, LPCWSTR LargeIcon, HWND hWnd, LONG32 ReplyMsg)
-{
- LPSTR szParam1 = WideToUTF8(Application);
- LPSTR szParam2 = WideToUTF8(SmallIcon);
- LPSTR szParam3 = WideToUTF8(LargeIcon);
-
- M_RESULT result = RegisterApp(szParam1, szParam2, szParam3, hWnd, ReplyMsg);
-
- delete [] szParam1;
- delete [] szParam2;
- delete [] szParam3;
-
- return result;
-}
-
-
+// Private functions
//-----------------------------------------------------------------------------
-// snUnregisterApp()
-
-/// Unregisters an application with Snarl (V39)
-M_RESULT SnarlInterface::UnregisterApp()
+LONG32 SnarlInterface::Send(SnarlMessage msg)
{
- SNARLSTRUCT ss;
- ss.Cmd = SNARL_UNREGISTER_APP;
- ss.LngData2 = GetCurrentProcessId();
-
- m_hwndFrom = NULL;
-
- return static_cast<M_RESULT>(Send(ss));
-}
-
+ DWORD_PTR nReturn = 0; // Failure
-//-----------------------------------------------------------------------------
-// snShowNotification()
-
-/// Displays a Snarl notification using registered class (V39)
-/// <returns>Message Id on success or M_RESULT on failure</returns>
-
-LONG32 SnarlInterface::ShowNotification(LPCSTR Class, LPCSTR Title, LPCSTR Text, LONG32 Timeout, LPCSTR Icon, HWND hWndReply, LONG32 uReplyMsg, LPCSTR Sound)
-{
- SNARLSTRUCTEX ssex;
- ssex.Cmd = SNARL_SHOW_NOTIFICATION;
-
- StringCbCopyExA((LPSTR)&ssex.Title, SNARL_STRING_LENGTH, Title, NULL, NULL, STRSAFE_IGNORE_NULLS);
- StringCbCopyExA((LPSTR)&ssex.Text, SNARL_STRING_LENGTH, Text, NULL, NULL, STRSAFE_IGNORE_NULLS);
- StringCbCopyExA((LPSTR)&ssex.Icon, SNARL_STRING_LENGTH, Icon, NULL, NULL, STRSAFE_IGNORE_NULLS);
-
- ssex.Timeout = Timeout;
- ssex.LngData2 = reinterpret_cast<LONG32>(hWndReply);
- ssex.Id = uReplyMsg;
-
- StringCbCopyExA((LPSTR)&ssex.Extra, SNARL_STRING_LENGTH, Sound, NULL, NULL, STRSAFE_IGNORE_NULLS);
- StringCbCopyA((LPSTR)&ssex.Class, SNARL_STRING_LENGTH, Class);
-
- ssex.Reserved1 = GetCurrentProcessId();
-
- m_nLastMessageId = Send(ssex);
- return m_nLastMessageId;
-}
-
-LONG32 SnarlInterface::ShowNotification(LPCWSTR Class, LPCWSTR Title, LPCWSTR Text, LONG32 Timeout, LPCWSTR Icon, HWND hWndReply, LONG32 uReplyMsg, LPCWSTR Sound)
-{
- LPSTR szParam1 = WideToUTF8(Class);
- LPSTR szParam2 = WideToUTF8(Title);
- LPSTR szParam3 = WideToUTF8(Text);
- LPSTR szParam4 = WideToUTF8(Icon);
- LPSTR szParam5 = WideToUTF8(Sound);
-
- LONG32 result = ShowNotification(szParam1, szParam2, szParam3, Timeout, szParam4, hWndReply, uReplyMsg, szParam5);
-
- delete [] szParam1;
- delete [] szParam2;
- delete [] szParam3;
- delete [] szParam4;
- delete [] szParam5;
-
- return result;
-}
-
-
-//-----------------------------------------------------------------------------
-// snChangeAttribute()
-
-/// (V39)
+ HWND hWnd = GetSnarlWindow();
+ if (!IsWindow(hWnd))
+ {
+ localError = SnarlEnums::ErrorNotRunning;
+ return 0;
+ }
-M_RESULT SnarlInterface::ChangeAttribute(LONG32 Id, SNARL_ATTRIBUTES Attr, LPCSTR Value)
-{
- SNARLSTRUCT ss;
- ss.Cmd = SNARL_CHANGE_ATTR;
- ss.Id = Id;
- ss.LngData2 = Attr;
-
- StringCbCopyExA((LPSTR)&ss.Text, SNARL_STRING_LENGTH, Value, NULL, NULL, STRSAFE_IGNORE_NULLS);
-
- return static_cast<M_RESULT>(Send(ss));
-}
+ COPYDATASTRUCT cds;
+ cds.dwData = 0x534E4C02; // "SNL",2;
+ cds.cbData = sizeof(SnarlMessage);
+ cds.lpData = &msg;
-M_RESULT SnarlInterface::ChangeAttribute(LONG32 Id, SNARL_ATTRIBUTES Attr, LPCWSTR Value)
-{
- LPSTR szParam1 = WideToUTF8(Value);
-
- M_RESULT result = ChangeAttribute(Id, Attr, szParam1);
-
- delete [] szParam1;
-
- return result;
-}
+ if (SendMessageTimeout(hWnd, WM_COPYDATA, (WPARAM)GetCurrentProcessId(), (LPARAM)&cds, SMTO_ABORTIFHUNG | SMTO_NOTIMEOUTIFNOTHUNG, 500, &nReturn) == 0)
+ {
+ // return zero on failure
+ if (GetLastError() == ERROR_TIMEOUT)
+ localError = SnarlEnums::ErrorTimedOut;
+ else
+ localError = SnarlEnums::ErrorFailed;
+
+ return 0;
+ }
-M_RESULT SnarlInterface::ChangeAttribute(SNARL_ATTRIBUTES Attr, LPCSTR Value)
-{
- return ChangeAttribute(m_nLastMessageId, Attr, Value);
-}
+ // return result and cache LastError
+ HANDLE hProp = GetProp(hWnd, _T("last_error"));
+ localError = static_cast<SnarlEnums::SnarlStatus>(reinterpret_cast<int>(hProp));
-M_RESULT SnarlInterface::ChangeAttribute(SNARL_ATTRIBUTES Attr, LPCWSTR Value)
-{
- return ChangeAttribute(m_nLastMessageId, Attr, Value);
+ return nReturn;
}
-
//-----------------------------------------------------------------------------
-// snSetClassDefault()
-/// Sets the default value for an alert class (V39)
-
-M_RESULT SnarlInterface::SetClassDefault(LPCSTR Class, SNARL_ATTRIBUTES Attr, LPCSTR Value)
+// Remember to delete [] returned string
+inline
+LPSTR SnarlInterface::WideToUTF8(LPCWSTR szWideStr)
{
- SNARLSTRUCT ss;
- ss.Cmd = SNARL_SET_CLASS_DEFAULT;
- ss.LngData2 = Attr;
- ss.Timeout = GetCurrentProcessId();
-
- StringCbCopyExA((LPSTR)&ss.Text, SNARL_STRING_LENGTH, Class, NULL, NULL, STRSAFE_IGNORE_NULLS);
- StringCbCopyExA((LPSTR)&ss.Icon, SNARL_STRING_LENGTH, Value, NULL, NULL, STRSAFE_IGNORE_NULLS);
-
- return static_cast<M_RESULT>(Send(ss));
-}
+ if (szWideStr == NULL)
+ return NULL;
-M_RESULT SnarlInterface::SetClassDefault(LPCWSTR Class, SNARL_ATTRIBUTES Attr, LPCWSTR Value)
-{
- LPSTR szParam1 = WideToUTF8(Class);
- LPSTR szParam2 = WideToUTF8(Value);
+ int nSize = WideCharToMultiByte(CP_UTF8, 0, szWideStr, -1, NULL, 0, NULL, NULL);
+ LPSTR szUTF8 = new char[nSize];
+ WideCharToMultiByte(CP_UTF8, 0, szWideStr, -1, szUTF8, nSize, NULL, NULL);
- M_RESULT result = SetClassDefault(szParam1, Attr, szParam2);
-
- delete [] szParam1;
- delete [] szParam2;
-
- return result;
-}
-
-
-//-----------------------------------------------------------------------------
-// snGetRevision()
-
-/// Gets the current Snarl revision (build) number (V39)
-/// Returns the build version number, or M_RESULT on failure.
-
-LONG32 SnarlInterface::GetRevision()
-{
- SNARLSTRUCT ss;
- ss.Cmd = SNARL_GET_REVISION;
- ss.LngData2 = 0xFFFE;
-
- return Send(ss);
+ return szUTF8;
}
-
-//-----------------------------------------------------------------------------
-// snAddClass()
-
-/// (V39)
-
-M_RESULT SnarlInterface::AddClass(LPCSTR Class, LPCSTR Description, SNARL_CLASS_FLAGS Flags, LPCSTR DefaultTitle, LPCSTR DefaultIcon, LONG32 DefaultTimeout)
+void SnarlInterface::PackData(BYTE* data, LPCSTR format, ...)
{
- SNARLSTRUCT ss;
- ss.Cmd = SNARL_ADD_CLASS;
- ss.LngData2 = Flags;
- ss.Timeout = GetCurrentProcessId();
-
- StringCbCopyExA((LPSTR)&ss.Text, SNARL_STRING_LENGTH, Class, NULL, NULL, STRSAFE_IGNORE_NULLS);
- StringCbCopyExA((LPSTR)&ss.Title, SNARL_STRING_LENGTH, Description, NULL, NULL, STRSAFE_IGNORE_NULLS);
+ // Always zero array - Used to clear the array in member functions
+ ZeroMemory(data, SnarlPacketDataSize);
- LONG32 result = Send(ss);
+ // Return if format string is empty
+ if (format == NULL || format[0] == 0)
+ return;
- if (static_cast<M_RESULT>(result) == M_OK)
- {
- SetClassDefault(Class, SNARL_ATTRIBUTE_TITLE, DefaultTitle);
- SetClassDefault(Class, SNARL_ATTRIBUTE_ICON, DefaultIcon);
- if (DefaultTimeout > 0) {
- char str[64] = {0};
- StringCbPrintfA((LPSTR)&str, sizeof(str), "%d", DefaultTimeout);
- SetClassDefault(Class, SNARL_ATTRIBUTE_TIMEOUT, str);
- }
-
- return M_OK;
- }
- else
- return M_FAILED;
-}
-
-M_RESULT SnarlInterface::AddClass(LPCWSTR Class, LPCWSTR Description, SNARL_CLASS_FLAGS Flags, LPCWSTR DefaultTitle, LPCWSTR DefaultIcon, LONG32 DefaultTimeout)
-{
- LPCSTR szClass = WideToUTF8(Class);
- LPCSTR szDescription = WideToUTF8(Description);
- LPCSTR szDefaultTitle = WideToUTF8(DefaultTitle);
- LPCSTR szDefaultIcon = WideToUTF8(DefaultIcon);
+ int cchStrTextLen = 0;
+ va_list args;
+ va_start(args, format);
- M_RESULT result = AddClass(szClass, szDescription, Flags, szDefaultTitle, szDefaultIcon, DefaultTimeout);
-
- delete [] szClass;
- delete [] szDescription;
- delete [] szDefaultTitle;
- delete [] szDefaultIcon;
-
- return result;
-}
+ // Get size of buffer
+ cchStrTextLen = _vscprintf(format, args) + 1; // + NULL
+ if (cchStrTextLen <= 1)
+ return;
-//-----------------------------------------------------------------------------
-// Private functions
-//-----------------------------------------------------------------------------
-
-template <class T>
-LONG32 SnarlInterface::Send(T ss)
-{
- DWORD_PTR nReturn = M_FAILED;
+ // Create formated string - _TRUNCATE will ensure zero terminated
+ _vsnprintf_s((char*)data, SnarlPacketDataSize, _TRUNCATE, format, args);
- HWND hWnd = GetSnarlWindow();
- if (IsWindow(hWnd))
- {
- COPYDATASTRUCT cds;
- cds.dwData = 2;
- cds.cbData = sizeof(ss);
- cds.lpData = &ss;
-
- if (SendMessageTimeout(hWnd, WM_COPYDATA, (WPARAM)m_hwndFrom, (LPARAM)&cds, SMTO_ABORTIFHUNG | SMTO_NOTIMEOUTIFNOTHUNG, 1000, &nReturn) == 0)
- {
- if (GetLastError() == ERROR_TIMEOUT)
- nReturn = M_TIMED_OUT;
- }
- }
-
- return static_cast<LONG32>(nReturn);
+ va_end(args);
}
-//-----------------------------------------------------------------------------
-
-// Remember to : delete [] returned string
-
-LPSTR SnarlInterface::WideToUTF8(LPCWSTR szWideStr)
-{
- if (szWideStr == NULL)
- return NULL;
-
- int nSize = WideCharToMultiByte(CP_UTF8, 0, szWideStr, -1, NULL, 0, NULL, NULL);
- LPSTR szUTF8 = new char[nSize];
- WideCharToMultiByte(CP_UTF8, 0, szWideStr, -1, szUTF8, nSize, NULL, NULL);
-
- return szUTF8;
-}
+}} // namespace Snarl::V41
diff --git a/3rdParty/Snarl/SnarlInterface.h b/3rdParty/Snarl/SnarlInterface.h
index 137d597..9440451 100644
--- a/3rdParty/Snarl/SnarlInterface.h
+++ b/3rdParty/Snarl/SnarlInterface.h
@@ -1,218 +1,276 @@
-#ifndef SNARL_INTERFACE
-#define SNARL_INTERFACE
+#ifndef SNARL_INTERFACE_V41
+#define SNARL_INTERFACE_V41
#include <tchar.h>
#include <windows.h>
-#include <strsafe.h>
+#include <cstdio>
+
+#ifndef SMTO_NOTIMEOUTIFNOTHUNG
+ #define SMTO_NOTIMEOUTIFNOTHUNG 8
+#endif
namespace Snarl {
+ namespace V41 {
- static const LPCTSTR SNARL_GLOBAL_MSG = _T("SnarlGlobalEvent");
- static const LPCTSTR SNARL_APP_MSG = _T("SnarlAppMessage");
+ static const LPCTSTR SnarlWindowClass = _T("w>Snarl");
+ static const LPCTSTR SnarlWindowTitle = _T("Snarl");
- static const int SNARL_STRING_LENGTH = 1024;
- static const int SNARL_UNICODE_LENGTH = SNARL_STRING_LENGTH / 2;
+ static const LPCTSTR SnarlGlobalMsg = _T("SnarlGlobalEvent");
+ static const LPCTSTR SnarlAppMsg = _T("SnarlAppMessage");
- static const LONG32 SNARL_LAUNCHED = 1; // Snarl has just started running
- static const LONG32 SNARL_QUIT = 2; // Snarl is about to stop running
- static const LONG32 SNARL_ASK_APPLET_VER = 3; // (R1.5) Reserved for future use
- static const LONG32 SNARL_SHOW_APP_UI = 4; // (R1.6) Application should show its UI
+ static const int SnarlPacketDataSize = 4096;
- static const LONG32 SNARL_NOTIFICATION_CLICKED = 32; // notification was right-clicked by user
- static const LONG32 SNARL_NOTIFICATION_TIMED_OUT = 33;
- static const LONG32 SNARL_NOTIFICATION_ACK = 34; // notification was left-clicked by user
- static const LONG32 SNARL_NOTIFICATION_MENU = 35; // V39 - menu item selected
- static const LONG32 SNARL_NOTIFICATION_MIDDLE_BUTTON = 36; // V39 - notification middle-clicked by user
- static const LONG32 SNARL_NOTIFICATION_CLOSED = 37; // V39 - user clicked the close gadget
+ // Enums put in own namespace, because ANSI C++ doesn't decorate enums with tagname :(
+ namespace SnarlEnums {
- static const LONG32 SNARL_NOTIFICATION_CANCELLED = SNARL_NOTIFICATION_CLICKED; // Added in R1.6
+ /// <summary>
+ /// Global event identifiers.
+ /// Identifiers marked with a '*' are sent by Snarl in two ways:
+ /// 1. As a broadcast message (uMsg = 'SNARL_GLOBAL_MSG')
+ /// 2. To the window registered in snRegisterConfig() or snRegisterConfig2()
+ /// (uMsg = reply message specified at the time of registering)
+ /// In both cases these values appear in wParam.
+ ///
+ /// Identifiers not marked are not broadcast; they are simply sent to the application's registered window.
+ /// </summary>
+ enum GlobalEvent
+ {
+ SnarlLaunched = 1, // Snarl has just started running*
+ SnarlQuit = 2, // Snarl is about to stop running*
+ SnarlAskAppletVer = 3, // (R1.5) Reserved for future use
+ SnarlShowAppUi = 4 // (R1.6) Application should show its UI
+ };
- static const DWORD WM_SNARLTEST = WM_USER + 237; // note hardcoded WM_USER value!
+ /// <summary>
+ /// Message event identifiers.
+ /// These are sent by Snarl to the window specified in RegisterApp() when the
+ /// Snarl Notification raised times out or the user clicks on it.
+ /// </summary>
+ enum MessageEvent
+ {
+ NotificationClicked = 32, // Notification was right-clicked by user
+ NotificationCancelled = 32, // Added in V37 (R1.6) -- same value, just improved the meaning of it
+ NotificationTimedOut = 33, //
+ NotificationAck = 34, // Notification was left-clicked by user
+ NotificationMenu = 35, // Menu item selected (V39)
+ NotificationMiddleButton = 36, // Notification middle-clicked by user (V39)
+ NotificationClosed = 37 // User clicked the close gadget (V39)
+ };
- // --------------------------------------------------------------------
-
- typedef enum M_RESULT {
- M_ABORTED = 0x80000007,
- M_ACCESS_DENIED = 0x80000009,
- M_ALREADY_EXISTS = 0x8000000C,
- M_BAD_HANDLE = 0x80000006,
- M_BAD_POINTER = 0x80000005,
- M_FAILED = 0x80000008,
- M_INVALID_ARGS = 0x80000003,
- M_NO_INTERFACE = 0x80000004,
- M_NOT_FOUND = 0x8000000B,
- M_NOT_IMPLEMENTED = 0x80000001,
- M_OK = 0x00000000,
- M_OUT_OF_MEMORY = 0x80000002,
- M_TIMED_OUT = 0x8000000A
- };
+ /// <summary>
+ /// Error values returned by calls to GetLastError().
+ /// </summary>
+ enum SnarlStatus
+ {
+ Success = 0,
- enum SNARL_COMMANDS {
- SNARL_SHOW = 1,
- SNARL_HIDE,
- SNARL_UPDATE,
- SNARL_IS_VISIBLE,
- SNARL_GET_VERSION,
- SNARL_REGISTER_CONFIG_WINDOW,
- SNARL_REVOKE_CONFIG_WINDOW,
-
- /* R1.6 onwards */
- SNARL_REGISTER_ALERT,
- SNARL_REVOKE_ALERT, // for future use
- SNARL_REGISTER_CONFIG_WINDOW_2,
- SNARL_GET_VERSION_EX,
- SNARL_SET_TIMEOUT,
-
- /* following introduced in Snarl V39 (R2.1) */
- SNARL_SET_CLASS_DEFAULT,
- SNARL_CHANGE_ATTR,
- SNARL_REGISTER_APP,
- SNARL_UNREGISTER_APP,
- SNARL_ADD_CLASS,
-
- /* extended commands (all use SNARLSTRUCTEX) */
- SNARL_EX_SHOW = 0x20,
- SNARL_SHOW_NOTIFICATION // V39
- };
-
- static const SNARL_COMMANDS SNARL_GET_REVISION = SNARL_REVOKE_ALERT;
-
- typedef enum SNARL_APP_FLAGS {
- SNARL_APP_HAS_PREFS = 1,
- SNARL_APP_HAS_ABOUT = 2
- };
-
- static const LONG32 SNARL_APP_PREFS = 1;
- static const LONG32 SNARL_APP_ABOUT = 2;
+ ErrorFailed = 101, // miscellaneous failure
+ ErrorUnknownCommand, // specified command not recognised
+ ErrorTimedOut, // Snarl took too long to respond
-
- /* --------------- V39 additions --------------- */
-
- /* snAddClass() flags */
- enum SNARL_CLASS_FLAGS {
- SNARL_CLASS_ENABLED = 0,
- SNARL_CLASS_DISABLED = 1,
- SNARL_CLASS_NO_DUPLICATES = 2, // means Snarl will suppress duplicate notifications
- SNARL_CLASS_DELAY_DUPLICATES = 4 // means Snarl will suppress duplicate notifications within a pre-set time period
- };
+ ErrorArgMissing = 109, // required argument missing
+ ErrorSystem, // internal system error
- /* Class attributes */
- typedef enum SNARL_ATTRIBUTES {
- SNARL_ATTRIBUTE_TITLE = 1,
- SNARL_ATTRIBUTE_TEXT,
- SNARL_ATTRIBUTE_ICON,
- SNARL_ATTRIBUTE_TIMEOUT,
- SNARL_ATTRIBUTE_SOUND,
- SNARL_ATTRIBUTE_ACK, // file to run on ACK
- SNARL_ATTRIBUTE_MENU
- };
+ ErrorNotRunning = 201, // Snarl handling window not found
+ ErrorNotRegistered, //
+ ErrorAlreadyRegistered, // not used yet; RegisterApp() returns existing token
+ ErrorClassAlreadyExists, // not used yet; AddClass() returns existing token
+ ErrorClassBlocked,
+ ErrorClassNotFound,
+ ErrorNotificationNotFound
+ };
- /* ------------------- end of V39 additions ------------------ */
-
- struct SNARLSTRUCT {
- SNARL_COMMANDS Cmd;
- LONG32 Id;
- LONG32 Timeout;
- LONG32 LngData2;
- char Title[SNARL_STRING_LENGTH];
- char Text[SNARL_STRING_LENGTH];
- char Icon[SNARL_STRING_LENGTH];
- };
+ /// <summary>
+ /// Application flags - features this app supports.
+ /// </summary>
+ enum AppFlags
+ {
+ AppDefault = 0,
+ AppHasPrefs = 1,
+ AppHasAbout = 2,
+ AppIsWindowless = 0x8000
+ };
- struct SNARLSTRUCTEX {
- SNARL_COMMANDS Cmd;
- LONG32 Id;
- LONG32 Timeout;
- LONG32 LngData2;
- char Title[SNARL_STRING_LENGTH];
- char Text[SNARL_STRING_LENGTH];
- char Icon[SNARL_STRING_LENGTH];
-
- char Class[SNARL_STRING_LENGTH];
- char Extra[SNARL_STRING_LENGTH];
- char Extra2[SNARL_STRING_LENGTH];
- LONG32 Reserved1;
- LONG32 Reserved2;
+ enum SnarlCommand
+ {
+ RegisterApp = 1,
+ UnregisterApp,
+ UpdateApp,
+ SetCallback,
+ AddClass,
+ RemoveClass,
+ Notify,
+ UpdateNotification,
+ HideNotification,
+ IsNotificationVisible,
+ LastError // deprecated but retained for backwards compatability
+ };
+ }
+
+ struct SnarlMessage
+ {
+ SnarlEnums::SnarlCommand Command;
+ LONG32 Token;
+ BYTE PacketData[SnarlPacketDataSize];
};
+ static const DWORD WM_SNARLTEST = WM_USER + 237;
// ------------------------------------------------------------------------
- // SnarlInterface class definition
+ /// SnarlInterface class definition
// ------------------------------------------------------------------------
-
class SnarlInterface {
public:
SnarlInterface();
~SnarlInterface();
-
- static HWND GetSnarlWindow();
- static LONG32 GetGlobalMsg();
-
LPTSTR AllocateString(size_t n) { return new TCHAR[n]; }
- void FreeString(LPCTSTR str) { delete [] str; str = NULL; }
+ void FreeString(LPTSTR str) { delete [] str; str = NULL; }
+ void FreeString(LPCTSTR str) { delete [] str; }
+
+ /// <summary>Register application with Snarl.</summary>
+ /// <returns>The application token or 0 on failure.</returns>
+ /// <remarks>The application token is saved in SnarlInterface member variable, so just use return value to check for error.</remarks>
+ LONG32 RegisterApp(LPCSTR signature, LPCSTR title, LPCSTR icon, HWND hWndReply = NULL, LONG32 msgReply = 0, SnarlEnums::AppFlags flags = SnarlEnums::AppDefault);
+ LONG32 RegisterApp(LPCWSTR signature, LPCWSTR title, LPCWSTR icon, HWND hWndReply = NULL, LONG32 msgReply = 0, SnarlEnums::AppFlags flags = SnarlEnums::AppDefault);
+
+ /// <summary>Unregister application with Snarl when application is closing.</summary>
+ /// <returns>0 on failure.</returns>
+ LONG32 UnregisterApp();
+
+ /// <summary>Update information provided when calling RegisterApp.</summary>
+ /// <returns>0 on failure.</returns>
+ LONG32 UpdateApp(LPCSTR title = NULL, LPCSTR icon = NULL);
+ LONG32 UpdateApp(LPCWSTR title = NULL, LPCWSTR icon = NULL);
+
+ /// <summary>Add a notification class to Snarl.</summary>
+ /// <returns>0 on failure.</returns>
+ LONG32 AddClass(LPCSTR className, LPCSTR description, bool enabled = true);
+ LONG32 AddClass(LPCWSTR className, LPCWSTR description, bool enabled = true);
+ /// <summary>Remove a notification class added with AddClass().</summary>
+ /// <returns>0 on failure.</returns>
+ LONG32 RemoveClass(LPCSTR className, bool forgetSettings = false);
+ LONG32 RemoveClass(LPCWSTR className, bool forgetSettings = false);
- LONG32 ShowMessage(LPCSTR szTitle, LPCSTR szText, LONG32 timeout = 0, LPCSTR szIconPath = "", HWND hWndReply = NULL, WPARAM uReplyMsg = 0);
- LONG32 ShowMessage(LPCWSTR szTitle, LPCWSTR szText, LONG32 timeout = 0, LPCWSTR szIconPath = L"", HWND hWndReply = NULL, WPARAM uReplyMsg = 0);
- LONG32 ShowMessageEx(LPCSTR szClass, LPCSTR szTitle, LPCSTR szText, LONG32 timeout = 0, LPCSTR szIconPath = "", HWND hWndReply = NULL, WPARAM uReplyMsg = 0, LPCSTR szSoundFile = "");
- LONG32 ShowMessageEx(LPCWSTR szClass, LPCWSTR szTitle, LPCWSTR szText, LONG32 timeout = 0, LPCWSTR szIconPath = L"", HWND hWndReply = NULL, WPARAM uReplyMsg = 0, LPCWSTR szSoundFile = L"");
-
- LPCTSTR GetAppPath(); // ** Remember to FreeString when finished with the string !
- LPCTSTR GetIconsPath(); // ** Remember to FreeString when finished with the string !
-
- BOOL GetVersion(WORD* Major, WORD* Minor);
- LONG32 GetVersionEx();
- BOOL HideMessage();
- BOOL HideMessage(LONG32 Id);
- BOOL IsMessageVisible();
- BOOL IsMessageVisible(LONG32 Id);
- M_RESULT RegisterAlert(LPCSTR szAppName, LPCSTR szClass);
- M_RESULT RegisterAlert(LPCWSTR szAppName, LPCWSTR szClass);
- M_RESULT RegisterConfig(HWND hWnd, LPCSTR szAppName, LONG32 replyMsg);
- M_RESULT RegisterConfig(HWND hWnd, LPCWSTR szAppName, LONG32 replyMsg);
- M_RESULT RegisterConfig2(HWND hWnd, LPCSTR szAppName, LONG32 replyMsg, LPCSTR szIcon);
- M_RESULT RegisterConfig2(HWND hWnd, LPCWSTR szAppName, LONG32 replyMsg, LPCWSTR szIcon);
- M_RESULT RevokeConfig(HWND hWnd);
- M_RESULT SetTimeout(LONG32 Timeout);
- M_RESULT SetTimeout(LONG32 Id, LONG32 Timeout);
- M_RESULT UpdateMessage(LPCSTR szTitle, LPCSTR szText, LPCSTR szIconPath = "");
- M_RESULT UpdateMessage(LPCWSTR szTitle, LPCWSTR szText, LPCWSTR szIconPath = L"");
- M_RESULT UpdateMessage(LONG32 Id, LPCSTR szTitle, LPCSTR szText, LPCSTR szIconPath = "");
- M_RESULT UpdateMessage(LONG32 Id, LPCWSTR szTitle, LPCWSTR szText, LPCWSTR szIconPath = L"");
+ /// <summary>Remove all notification classes in one call.</summary>
+ /// <returns>0 on failure.</returns>
+ LONG32 RemoveAllClasses(bool forgetSettings = false);
- /* V39 */
- M_RESULT AddClass(LPCSTR Class, LPCSTR Description = NULL, SNARL_CLASS_FLAGS Flags = SNARL_CLASS_ENABLED, LPCSTR DefaultTitle = NULL, LPCSTR DefaultIcon = NULL, LONG32 DefaultTimeout = 0);
- M_RESULT AddClass(LPCWSTR Class, LPCWSTR Description = NULL, SNARL_CLASS_FLAGS Flags = SNARL_CLASS_ENABLED, LPCWSTR DefaultTitle = NULL, LPCWSTR DefaultIcon = NULL, LONG32 DefaultTimeout = 0);
- M_RESULT ChangeAttribute(SNARL_ATTRIBUTES Attr, LPCSTR Value);
- M_RESULT ChangeAttribute(SNARL_ATTRIBUTES Attr, LPCWSTR Value);
- M_RESULT ChangeAttribute(LONG32 Id, SNARL_ATTRIBUTES Attr, LPCSTR Value);
- M_RESULT ChangeAttribute(LONG32 Id, SNARL_ATTRIBUTES Attr, LPCWSTR Value);
- LONG32 GetAppMsg();
- LONG32 GetRevision();
+ /// <summary>Show a Snarl notification.</summary>
+ /// <returns>Returns the notification token or 0 on failure.</returns>
+ /// <remarks>You can use <see cref="GetLastMsgToken()" /> to get the last token.</remarks>
+ LONG32 EZNotify(LPCSTR className, LPCSTR title, LPCSTR text, LONG32 timeout = -1, LPCSTR icon = NULL, LONG32 priority = 0, LPCSTR acknowledge = NULL, LPCSTR value = NULL);
+ LONG32 EZNotify(LPCWSTR className, LPCWSTR title, LPCWSTR text, LONG32 timeout = -1, LPCWSTR icon = NULL, LONG32 priority = 0, LPCWSTR acknowledge = NULL, LPCWSTR value = NULL);
+
+ /// <summary>
+ /// Show a Snarl notification.
+ /// This function requires that you write your own packet data.
+ /// </summary>
+ /// <returns>Returns the notification token or 0 on failure.</returns>
+ /// <remarks>You can use <see cref="GetLastMsgToken()" /> to get the last token.</remarks>
+ LONG32 Notify(LPCSTR className, LPCSTR packetData);
+ LONG32 Notify(LPCWSTR className, LPCWSTR packetData);
+
+ /// <summary>Update the text or other parameters of a visible Snarl notification.</summary>
+ /// <returns>0 on failure.</returns>
+ LONG32 EZUpdate(LONG32 msgToken, LPCSTR title = NULL, LPCSTR text = NULL, LONG32 timeout = -1, LPCSTR icon = NULL);
+ LONG32 EZUpdate(LONG32 msgToken, LPCWSTR title = NULL, LPCWSTR text = NULL, LONG32 timeout = -1, LPCWSTR icon = NULL);
- M_RESULT RegisterApp(LPCSTR Application, LPCSTR SmallIcon, LPCSTR LargeIcon, HWND hWnd = 0, LONG32 ReplyMsg = 0);
- M_RESULT RegisterApp(LPCWSTR Application, LPCWSTR SmallIcon, LPCWSTR LargeIcon, HWND hWnd = 0, LONG32 ReplyMsg = 0);
- void SetAsSnarlApp(HWND hWndOwner, SNARL_APP_FLAGS Flags = (SNARL_APP_FLAGS)(SNARL_APP_HAS_ABOUT | SNARL_APP_HAS_PREFS));
- M_RESULT SetClassDefault(LPCSTR Class, SNARL_ATTRIBUTES Attr, LPCSTR Value);
- M_RESULT SetClassDefault(LPCWSTR Class, SNARL_ATTRIBUTES Attr, LPCWSTR Value);
- LONG32 ShowNotification(LPCSTR Class, LPCSTR Title = NULL, LPCSTR Text = NULL, LONG32 Timeout = 0, LPCSTR Icon = NULL, HWND hWndReply = NULL, LONG32 uReplyMsg = 0, LPCSTR Sound = NULL);
- LONG32 ShowNotification(LPCWSTR Class, LPCWSTR Title = NULL, LPCWSTR Text = NULL, LONG32 Timeout = 0, LPCWSTR Icon = NULL, HWND hWndReply = NULL, LONG32 uReplyMsg = 0, LPCWSTR Sound = NULL);
- M_RESULT UnregisterApp();
+ /// <summary>
+ /// Update the text or other parameters of a visible Snarl notification.
+ /// This function requires that you write your own packet data.
+ /// </summary>
+ /// <returns>0 on failure.</returns>
+ LONG32 Update(LONG32 msgToken, LPCSTR packetData);
+ LONG32 Update(LONG32 msgToken, LPCWSTR packetData);
+
+ /// <summary>Hide a Snarl notification.</summary>
+ /// <returns>0 on failure.</returns>
+ LONG32 Hide(LONG32 msgToken);
+
+ /// <summary>Test if a Snarl notification is visible.</summary>
+ /// <returns>Returns -1 if message is visible. 0 if not visible or if an error occured.</returns>
+ LONG32 IsVisible(LONG32 msgToken);
+
+ /// <summary>Get the last error from Snarl. Call after other functions return 0 to know why it failed.</summary>
+ /// <returns>Returns one of the SnarlEnums::SnarlStatus values.</returns>
+ SnarlEnums::SnarlStatus GetLastError();
+
+ /// <summary>Get Snarl version, if it is running.</summary>
+ /// <returns>Returns a number indicating Snarl version.</returns>
+ LONG32 GetVersion();
+
+ /// <summary>
+ /// Get the path to where Snarl is installed.
+ /// ** Remember to call <see cref="FreeString(LPCTSTR)" /> on the returned string !!!
+ /// </summary>
+ /// <returns>Returns the path to where Snarl is installed.</returns>
+ /// <remarks>This is a V39 API method.</remarks>
+ LPCTSTR GetAppPath();
+
+ /// <summary>
+ /// Get the path to where the default Snarl icons are located.
+ /// <para>** Remember to call <see cref="FreeString(LPCTSTR)" /> on the returned string !!!</para>
+ /// </summary>
+ /// <returns>Returns the path to where the default Snarl icons are located.</returns>
+ /// <remarks>This is a V39 API method.</remarks>
+ LPCTSTR GetIconsPath();
+
+ /// <summary>GetLastMsgToken() returns token of the last message sent to Snarl.</summary>
+ /// <returns>Returns message token of last message.</returns>
+ /// <remarks>This function is not in the official API!</remarks>
+ LONG32 GetLastMsgToken() const;
- LONG32 GetLastMessageId() { return m_nLastMessageId; }
+ /// <summary>Check whether Snarl is running</summary>
+ /// <returns>Returns true if Snarl system was found running.</returns>
+ static BOOL IsSnarlRunning();
+
+ /// <summary>
+ /// Returns the value of Snarl's global registered message.
+ /// Notes:
+ /// Snarl registers SNARL_GLOBAL_MSG during startup which it then uses to communicate
+ /// with all running applications through a Windows broadcast message. This function can
+ /// only fail if for some reason the Windows RegisterWindowMessage() function fails
+ /// - given this, this function *cannnot* be used to test for the presence of Snarl.
+ /// </summary>
+ /// <returns>A 16-bit value (translated to 32-bit) which is the registered Windows message for Snarl.</returns>
+ static UINT Broadcast();
+ /// <summary>Returns the global Snarl Application message (V39)</summary>
+ /// <returns>Returns Snarl application registered message.</returns>
+ static UINT AppMsg();
+
+ /// <summary>Returns a handle to the Snarl Dispatcher window (V37)</summary>
+ /// <returns>Returns handle to Snarl Dispatcher window, or zero if it's not found.</returns>
+ /// <remarks>This is now the preferred way to test if Snarl is actually running.</remarks>
+ static HWND GetSnarlWindow();
+
private:
- template <class T> LONG32 Send(T ss);
+ /// <summary>Send message to Snarl.</summary>
+ /// <returns>Return zero on failure.</returns>
+ LONG32 Send(SnarlMessage msg);
+
+ /// <summary>Convert a unicode string to UTF8</summary>
+ /// <returns>Returns pointer to the new string - Remember to delete [] returned string !</returns>
+ /// <remarks>Remember to delete [] returned string !!!</remarks>
LPSTR WideToUTF8(LPCWSTR szWideStr);
-
- LONG32 m_nLastMessageId;
- HWND m_hwndFrom; // set during snRegisterConfig() or snRegisterConfig2()
- };
+ /// <summary>Pack data into the PackedData member field.</summary>
+ /// <param name="data">Should always be a pointer to the PackedData field</param>
+ /// <param name="format">The format string. Can be NULL or "" to just zero PackedData!</param>
+ /// <param name="...">Variable number of objects to convert</param>
+ void PackData(BYTE* data, LPCSTR format, ...);
+
+ LONG32 appToken;
+ LONG32 lastMsgToken;
+ SnarlEnums::SnarlStatus localError;
+
+ }; // class
-}
+ } // namespace V41
+} // namespace Snarl
-#endif // SNARL_INTERFACE
+#endif // SNARL_INTERFACE_V41